Reverse-engineered documentation for the Midea D1D2 communication bus used in VRF HVAC systems.
This repo contains my understanding of midea's D1/D2 protocol by sniffing the bus. There are several messages on this bus, and ultimately one or two of them were simpler for me to use.
My goal was to be able to control the indoor units (IDUs) and read their status locally and eventually control the units via Home Assistant. This repo contains my code that uses this protocol to control the IDUs.
This page on Home Assistant Community forum may have some more info.
My Midea VRF (Variable Refrigerant Flow) air conditioner (model: MDV-V200WN1) consists of one outdoor unit (IDU) and several indoor units (IDUs). The IDUs have different communication buses:
- On my system, they use
PQEbus to talk to the ODU. I didn't touch it. Apparently, it's a RS485 bus as well. - The other bus that I was interested in was
D1D2. All IDUs are connected to each other through this D1D2. - There's a 3rd bus there as well -
X1X2.X1X2is a bus that connectsWiFi wall controllerto oneIDU.X1X2is carrying both data and power. On this system I measured it 18VDC and it has some sort of data modulation on it. More on that here. My understanding is if a customer asks for aWiFi wall controller, which usesX1X2bus, the installer will also runD1D2wiring. Otherwise, the system will only have one bus,PQEin our case, which is beyond the scope of this repo.
- There's also a 4th bus on the IDUs named
M1M2. Based on the user manual it's for communicating with ODU as well (similar toPQE) but with different generation. It's not used on my system.
I used a simple ESP32 and TTL-to-RS485 module (both from AliExpress) to connect to D1D2 bus. After reading the baud rate through osciloscope, I wrote an ESPHome code to sniff the traffic. Eventually, I started sending commands through the app (which talks to the wifi-wall-controller through the internet) I found the necessary bits and pieces.
Note that for sniffing we could disconnect the DI and force the DE and RE pins to GND to make sure we are not writing to the bus and always listening.
The D1D2 bus uses RS485:
- 4800 baud
- 8 data bits
- No parity
- 1 stop bit
Communication is half-duplex (one master, multiple slaves).
Measured voltage is approximately 0v and 5v differential.
| Byte | Description |
|---|---|
| 0 | Header (start) - Always 0xAA |
| 1 | Command |
| 2 and 3 | Destination address (little endian) |
| 4 and 5 | Source address (little endian) |
| 6 | Payload length (len) |
| 7 to 7+len-1 | Payload (len bytes) |
| 2 bytes | CRC-16/MODBUS (little endian) |
| last 2 bytes | Footer (end) - Always 0x55 0xFE |
raw message: AA 2A 01 00 04 00 01 01 50 73 55 FE
AA -> start
2A -> command
00 01 -> destination address (0x0001 or simply 1)
00 04 -> source (usually master) address (0x0004 or simply 4)
01 -> payload length
01 -> payload (length is 1 in this example)
50 73 -> CRC-16/MODBUS (0x7350, reversed)
55 FE -> Footer (end)
The CRC is a standard CRC-16/MODBUS - little endian. CRC calculation does not include the starting byte (0xAA). It includes byte1 until the last payload byte. Here's a python code to show how it is being calculated.
Work in progress. Commands will be added in near future.
As mentioned a subset of the confirmed commands is implemented in the controller repo and is used for real-time control of indoor units..
- Decode remaining bus commands, particularly those related to room temperature reporting.
This project is an independent reverse-engineering effort and is not affiliated with or endorsed by Midea. I did it on my free time and tested it on one system. Many things could be wrong! Use it with your own risk!

