Hi Folks,
Introduction
based on the question from @Christopher_Hemmings, I’d like to introduce you to the world of reverse engineering a device communication protocol. As many products we buy, there is mearly an APP or a vendor-specific way to access the device, rendering it next to useless to our smart homes.
In this topic, I’ll show you how I reverse engineered our Poolstar / PoolEx Heat Pump controller. Goal was to replace the LCD-controller with an WIFI MQTT bridge.
What I’ve reverse engineered so far, some examples
- Siemens Albatros2 BSB-Bus (BTW, I’m happy to see it lead to bsb_lan)
- LG Therma V R32 Monobloc Heat Pump
What you need
- Time and interest
- PC with SigRok installed
- Multimeter (Volts, Continuity / Resistance)
- Advisable: Osciloscope (Some el-cheapo DS150 might do)
- Logic analyser (I can recommend this or its cheap clones)
- Some wires
- Manuals (in this case this one)
- Screwdriver etc.
- USB to RS485 transceiver
Step 1: Know your ground / Research
The first step is to read all consumer information materials carefully. Notice where which information is present. For example, the controller in this case is able to display the water temperatures entering and leaving the unit and the fan RPM. So there must be some communication telling the controller what to display. Also take note how many PCBs are present and how they are interconnected.
As you finished getting to know the unit inside out, we’ll start to go layer-by-layer upwards to our target.
Step 2: Starting with the physical layer
There’s something called the ISO OSI Model which is a good starting point for a structured analysis. We’ll therefor start with the physical layer / layer1.
You take a close look at the connection between the controller and the heat pump. You’ll notice there are four wires between the devices - red, black, yellow and green.
First guess would be: Red positive supply, black is ground and the others are for communication. You may verify or falsify the guessing with the Multimeter. As the wires are thin and easily accessible, common sense says: there has to be no mains voltage on it. So set the multimeter to voltage measurement in DC and something smaller than 50 V and start probing. You see between red and black 12V and fluctating voltages between black (GND) and yellow and black (GND) and green. These go from 0 to approx. 3,5V.
Next step to short cut is to disconnect and open up the controller and take a close look.
Notice the labels on the connector? 12V, G, B and A. Mh, so our voltage measurement is correct. Black is ground and A,B - what’s that. Take a look at the labels on the ICs. in the upper left corner is an max13085E IC which is an RS485 transceiver. RS485 has to has something of about 120Ohms between A and B. Measure this and you’ll see, R58 is the searched resistor. You may also probe the pins on the IC and the wires just to verify.
So in conslusio, we know we get 12V and ground along with an RS485 communication on the wire. Good start!
Step 3: Starting to sniff
Now that we know what we have sitting before us, we can grab our logic analyser and take some traces. Hook up GND, A and B and start a capturing session with sigrok. Once you got some stream, add an UART decoder and save the file. The baud rate is guessable or tried until no errors appear. I got one published here for you to play with. Beside the data, take a look at the timings between messages. Those are also important.
Set up a way to produce a long term log of the communication data as it is important to get a grip on which data changeds when. Let the unit sit a few hours and use it as a normal user while logging all.
Step 4: Making sense out of the data
As soon as you got some data, you may copy and paste it into an excel table and first step is to filter out same lines. Put each byte into a seperate column and add some color:
Take a look at changing data. Mark never chaning data. Most communication protocols add a CRC check to the end of each message, as is this time. You may guess if its a CRC by seeing it frequently and heavily change.
Now, go thru all operational modes and let them run a few minutes - cooling, heating, automatic, silent mode, boost mode. Mark the bytes that change. Those have to contain information on the operational mode.
Temperatures are identified by converting the hex values (2 bytes per temperature) to decimal and matching up with the controller value. For example, 01 A7 is 423 decimal (use windows calculator) while the controller shows 1,2°C. You need to collect enough data and start calculating. Result in this case is to convert to decimal and substract 300 then divide by 10. So we even get more resolution: 01 A7 turns out to be 1,23°C.
Step 5: Resolving diffucult data
That has been easy. However - how do you resolv data you just can’t get a grip on. Simple: Emulate the heatpump and send the controller known values and check this for changes.
In this case, I got some problem with f.e. the fan RPM readout.
I’ve used a python script which sends the controller hooked up the the USB/RS485 dongle and a 12V power supply values which may be changed one by one using the cursor keys:
Step 6: Create a MQTT bridge
Now we know what those bytes mean, grab an ESP8266 and start up your prepared arduino environment. You may use my sktech as a starting point.
Basic workflow is:
- Connect to WiFi and MQTT broker
- Read bytes until a valid message appears (CRC, length)
- Parse it
- Send it to broker
- If mqtt command received, send to heat pump
Result
TBD / Notes
- The communication between heat pump and controller is kind of challange/response, e.g.: HP sends state until controller responds with “go on” reply. If no reply is received, the HP repeats to send its state. Controller behaves the same.
- Baudrate is measureable: see SparkFun
- Work in progress, I’m happy for feedback