Preface
So, I live in a fairly damp London home. We try and run a dehumidifier reguarlly but we have diffrent rates of electric. So natrually, I wanted to mess around with it and see if I could hook it up to home assistant…
I was orignally planning just to connect up to a button on the controller board but it used some dumb touch sensors which are just a pain to deal with. I also wanted the humidity reading for my home assistant dashboard. So I decided to find another way!
There are two controller boards, one is the buttons and display out and the other is what actuarly turns it on and off along with giving the read out from the humidity sensor.
Getting the information out from UART
I have a SH-U9C5 serial adapter which I used connected up to the cable. I had to re-pin the cable, which looked a little like this:
I had to get the cables connected the right way round but its only two ways so all was good after the second try. I used
picocom
to connect: sudo picocom /dev/ttyUSB0 --imap spchex,tabhex,crhex,lfhex,nrmhex,8bithex --baud 9600
. This output the data as HEX in a nice readable way. This is what I would see when toggling the power button:
[bb][51][80][31][00][01][00][00][00][b2] # POWER ON
[bb][51][00][31][00][01][00][00][00][32] # POWER OFF
To test that this worked, I flipped the RX and TX so I could transmit the power off and on commands. Like magic, it worked! It was still connected up to my laptop but I could controll the device! This was the first major step to getting this to work!
So, I grabbed a ESP-32 I had lying around. Flashed it with ESP-HOME and added this as the config:
uart:
tx_pin: GPIO00
rx_pin: GPIO01
baud_rate: 9600
parity: NONE
switch:
- platform: template
name: "Dehumidifier"
turn_on_action:
- uart.write: [0xBB, 0x51, 0x80, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00, 0xB2]
turn_off_action:
- uart.write: [0xBB, 0x51, 0x00, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32]
As soon as I tried… it… did nothing… I had the fucking RX and TX the wrong way. Now when I flip it, it works! HELL YEAH!
I mean I can only turn it off and on at the moment. Not really the most impressive thing. Next I wanted to get the humidity reading off the device.
Reading the humidity sensor
So, how this device works is it sends back data to the controller board with the humidity on. It sends it in HEX format. I wasn’t really sure what I was looking at. I tried putting the value (with out the start and end bites) into a hex to int converter but it still made no sence. I had a seperate humidity sensor so I was sure the value I was getting was wrong, it was also to like 20 decimal places.
For context, this is what I was seeing:
[bb][51][00][31][36][01][00][40][00][00][15][00][40][00][fd]
[bb][51][00][31][36][01][00][40][00][00][14][00][40][00][fc]
[bb][51][00][31][36][01][00][40][00][00][15][00][40][00][fd]
[bb][51][00][31][36][01][00][40][00][00][14][00][40][00][fc]
As it turns out, I don’t need the whole string, I just need the 4th bit. In the above example it is just showing 36. Converted that and other values I was seeing into a int and it was about the same as my humidity sensor! This was a huge result! All I had to do now was add this as a sensor to ESP-HOME. How hard could that be?
Humitity sensor in ESP-HOME
So, getting the data into ESP-HOME was something I had no clue how to do. I found THIS, spesifically Simon Bok’s comment. I basicly just copied the humidity sensor part leaving me with this:
uart:
tx_pin: GPIO00
rx_pin: GPIO01
baud_rate: 9600
parity: NONE
debug:
direction: BOTH
dummy_receiver: true
sequence:
- lambda: |-
UARTDebug::log_hex(direction, bytes, ',');
if (direction == UART_DIRECTION_RX) {
if (bytes[0] == 0xBB) {
float humidity = bytes[4];
id(humidity_sensor).publish_state(humidity);
}
}
switch:
- platform: template
id: dehumidifier_switch
name: "Dehumidifier Switch"
turn_on_action:
- uart.write: [0xBB, 0x51, 0x80, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00, 0xB2]
turn_off_action:
- uart.write: [0xBB, 0x51, 0x00, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32]
sensor:
- platform: template
name: "Humidity reading"
id: humidity_sensor
unit_of_measurement: "%"
device_class: "humidity"
state_class: "measurement"
- platform: template
Now I have a entity called humidity_sensor
. This just work. I mean don’t get me wrong, it took me a while to figure out what I needed to copy and tried lots of other things first. The main thing was creating a if statment to only look at RX and ensuring the first bytes were the 0xBB
ones. I found this has been most reliable.
As it turns out it also had a tempriture sensor which I added with this:
uart:
...
debug:
...
- lambda: |-
...
if (direction == UART_DIRECTION_RX) {
if (bytes[0] == 0xBB){
float temperature = bytes[10];
id(temperature_sensor).publish_state(temperature);
}
}
...
sensor:
...
- platform: template
name: "Temperature reading"
id: temperature_sensor
unit_of_measurement: "°C"
device_class: "temperature"
state_class: "measurement"
accuracy_decimals: 1
Once again, taken from that comment.
The last little bits.
One thing that was really annoying was the HA switches would automaticly go back to off after a few seconds of turning the device on. Now it didn’t turn it off, just the switch state changed. I realised what I needed to do was pull in the power state. In the UART string I was reciving, it would also be telling me the power state.
BB,51,80,31,40,01,00,03,00,00,14,00,40,00,49 # POWERED ON
BB,51,00,31,40,01,00,03,00,00,14,00,40,00,49 # POWERED OFF
The second byte changed from 80
to 00
. This is what stated weather the device was on or off. All I need to do was add another if statment to the lambda, like this:
if (bytes[0] == 0xBB && bytes[2] == 0x80) {
id(dehumidifier_switch).publish_state(true);
}
if (bytes[0] == 0xBB && bytes[2] == 0x00) {
id(dehumidifier_switch).publish_state(false);
}
This updates the switch state depending on the state reported back to the esp. Nice!
Now, I did figure out some other bits but eh, I don’t really want to talk about them. I will leave what I know so far about the hex here:
BB,51,80,31,3F,01,00,83,00,00,14,00,40,00,C8
S ? pw SP H ? ? ? ? TP T ? ? ? F
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
S - start bit?
pw - power status
H - humidity
SP - Speed? 0x12 0x32 and default maybe 0x31
T - Tempriture
F - Tank fill level? Really might not be, the value seems to not change much when the tank isn't in and changes a lot when I wiggle a magnet but further investigation is required.
TP - Tank presence (changes from 04 to 00 when not present (or the other way around))
If you want my full config, you can find it here
esphome:
name: esp32-dehumidifier
friendly_name: bedroom-dehumidifier
on_boot:
- priority: 800
then:
- uart.write: [0xBB, 0x51, 0x00, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32]
uart:
tx_pin: GPIO00
rx_pin: GPIO01
baud_rate: 9600
parity: NONE
debug:
direction: BOTH
dummy_receiver: true
sequence:
- lambda: |-
UARTDebug::log_hex(direction, bytes, ',');
if (direction == UART_DIRECTION_RX) {
if (bytes[0] == 0xBB) {
float humidity = bytes[4];
id(humidity_sensor).publish_state(humidity);
}
if (bytes[0] == 0xBB){
float temperature = bytes[10];
id(temperature_sensor).publish_state(temperature);
}
if (bytes[0] == 0xBB && bytes[2] == 0x80) {
id(dehumidifier_switch).publish_state(true);
}
if (bytes[0] == 0xBB && bytes[2] == 0x00) {
id(dehumidifier_switch).publish_state(false);
}
if (bytes[0] == 0xBB) {
float tank = bytes[14];
id(tank_sensor).publish_state(tank);
}
if (bytes[0] == 0xBB && bytes[9] == 0x00) {
ESP_LOGD("tank_installed", "installed");
}
if (bytes[0] == 0xBB && bytes[9] == 0x04) {
ESP_LOGD("tank_installed", "uninstalled");
}
//if (bytes[0] == 0xBB && bytes[3] == 0x32) {
// ESP_LOGD("speed_state", "default");
//}
//if (bytes[0] == 0xBB && bytes[3] == 0x12) {
// ESP_LOGD("speed_state", "12");
//}
//if (bytes[0] == 0xBB && bytes[3] == 0x31) {
// ESP_LOGD("speed_state", "31");
//}
}
switch:
- platform: template
id: dehumidifier_switch
name: "Dehumidifier Switch"
turn_on_action:
- uart.write: [0xBB, 0x51, 0x80, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00, 0xB2]
turn_off_action:
- uart.write: [0xBB, 0x51, 0x00, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32]
- platform: template
name: "Dehumidifier Speed"
id: dehumidifier_speed_switch
turn_on_action:
- uart.write: [0xBB, 0x51, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2]
turn_off_action:
- uart.write: [0xBB, 0x51, 0x80, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92]
sensor:
- platform: template
name: "Humidity reading"
id: humidity_sensor
unit_of_measurement: "%"
device_class: "humidity"
state_class: "measurement"
- platform: template
name: "Temperature reading"
id: temperature_sensor
unit_of_measurement: "°C"
device_class: "temperature"
state_class: "measurement"
accuracy_decimals: 1
- platform: template
name: "tank reading"
id: tank_sensor
unit_of_measurement: ""
state_class: "measurement"
Conclusion
This was a really fun project, I learnt a lot about UART and got that itch for modding/hacking again. This wasn’t the most complicated thing to get working, so it was perfect for a first project.
A artical I want to mention is this: This blog was someone’s attempt at doing this. They used the button method on the touch sensors. It didn’t work for me but was a cool write up
Comments
You can respond to this post on Mastodon: 🔗 or click to copy the URL to your clipboard so you can paste it into your client.