ESP Haier: Haier Air Conditioner + ESP Home + Wemos D1 mini

Hi everybody,

Is there anybody with ESP8266 that can help me with testing? I think I made code working on this board but can’t test it. I tried with my D1 mini - code is running but of course no real communication with AC. Keep in mind that I can’t guarantee you that your ESP device will not be bricked so it would be good if you are able to restore bricked device with esptools etc.
So if I did not scare you and you are willing to help, please, use this file (no need to pull my git repo esphome will do it for you):

substitutions:
  device_name: Haier AC

esphome:
  name: haier
  name_add_mac_suffix: true

esp8266:
  board: esp01_1m

external_components:
  - source: github://paveldn/ESP32-S0WD-Haier@dev
    components: [haier]

uart:
  baud_rate: 9600
  tx_pin: 1
  rx_pin: 3
  id: ac_port  
    
logger:
  level: DEBUG
  baud_rate: 0

web_server:

wifi:
  ap:

captive_portal:
    
api:

ota:

climate:
  - platform: haier
    name: ${device_name} 
    uart_id: ac_port
    wifi_signal: true
    outdoor_temperature:
      name: ${device_name} outdoor temperature

It should work OK if you used ivoh95 implementation. Or replace board type with your type.
Let me know if it worked for you.
Thank you in advance.

ok i will try tomorrow

only here the solution from https://github.com/Oksion/esphaier worked for me, ivoh95’s solution did not work initially, why is that?

I didn’t check everything of course but I don’t see CRC calculation in Oksion implementation. Haier protocol have two versions. Version 1 uses 1 byte check sum which is just a sum of all bytes mod FF, version 2 have same checksum plus 2 bytes CRC16 at the end. Are you sure your AC is using Haier 2 protocol?
My implementation using version 2, probably it will not work for you. I can try to adopt it to work with both versions but I will need a help from you. Can you share logs that you got from solution that works for you? 5 min is enough but I need logs from the beginning of communication so I will see how communication starts.

Yes, of course, then I won’t try your solution for now, because it might not really suit me, but first I’ll show you the log for 5 minutes

1 Like

Do you have a telegram messenger? It will probably speed up your work

Great work, your project seems much better written, with room to grow, tested it on my unit and it seems to work great. I like the fact that you got the wifi light to work as well haha.

The only thing stopping me from migrating to your version is the lack of the cleaning modes, health mode, screen off, and other features. (that screen is way too bright at night) Do you have any ideas of a good way to implement those? Did i miss someway to enable them? Thanks for your contributions to this!

Thanks! I am planning to add additional features and cleaning, but first, need to do some refactoring. So yes I have some ideas. Also, I want to support both ESP32 and ESP8266, and for both frameworks (idf and Arduino).

Sounds like the ideal way for this project to grow. Especially since we can reflash the factory dongle. Let me know if I can help in any way, I’m more than willing to test and help. I’ve got esp32 and esp8266 chips on hand.

Thanks. Actually, it will be helpful if you can provide me with 5 min of logs from your AC. It looks like my AC doesn’t support many features of this Haier protocol like human presence, power usage, humidity, etc. Probably if yours does supports any of them I could figure it out from logs.

For sure, sadly I do not think mine has those features either, I’ve added the model number in the file name. The outdoor temp is questionable to me, i think we either got the math wrong or that some other sensor, since it shows 42c when its only about 22c outside and rainy. Maybe its got a negative offset to allow negative outside temps?

Logs from your firmware running on an esp01, I power cycled the whole ac after switching firmware. It has off and cool mode, let me know if you want any other modes logged.

Thanks!

Yes your logs looks same way as mine. Probably there is no ACs yet that support all set of these features.

That was also my idea. Will try to match this values with my weather station.
Thanks for the logs!

That is how temperatures looks like for my o outdoor weather station and AC sensor:


There is definitely an offset, will the to figure it out.
P.S. It looks like there is 25C offset give or take. Weather station is in the garden and external AC is on garage roof under sun. So highest temperatures for AC is higher. Today is rainy so sun will not make big difference, will check my theory with 25C offset.

Yes, it will be interesting to see if other folks have values that seem plausible for outdoor temperatures. Right now im trying (value/2.0)-20 and it gives me a plausible value for outdoor temperature. Which seems to line up with my model being “rated” for -20c operation in the advertising

Looking through your packet decoding .h, i see a use_half_degree:1 definition, does that mean that bit allows for set points in 0.5c increments? Did you find any bits to disable the beeper when a command is received?

Also wanted to ask, where did you find information on the protocol? I see you managed to get a lot further in decoding the unknown bits/bytes.

1 Like

I still think (value/2.0)-25 is better fit in my case. And also i I would develop AC that should work from -20 I would add some margins (5 C is reasonable). But I think this is details.

Have no idea, still need to try this. I suppose so.

I think it is probably echo_status but again I didn’t try it yet.

That is actually a funny story. I was trying to reverse code the original firmware. I failed because all tools for disassembling that I found didn’t decode code properly. That is actually amazing that such a popular platform as Xtensa doesn’t have normal support in disassemblers. But at least I extracted resources. And there I found strings that describe fields in packet. So after this, I analyzed logs of the original firmware and found that it prints names of the fields for received packets in the same order as bytes in packet. It worked for fields that we know already. But I don’t know the size of the fields or how this field converted. For some of them, I figured it out during experiments. For some, it is obvious because the number of fields is the same as the number of bits available. But for some fields it is still not clear how they are encoded. For example, I know that bytes from 26 to 41 have the following fields totalCleaningTime, indoorPM2p5Value, outdoorPM2p5Value, ch2oValue, vocValue, co2Value, totalElectricityUsed and they go in exactly this order but I don’t have any idea how they encoded and what is the size for each of them. They are always 0 for my AC.

1 Like

Ahhhh I see! It never crossed my mind to dump the original firmware, I just blindly overwrote it thinking I’d never use it. Any chance you still have that firmware bin file?

This gave me the idea to do some more research, i found a service manual for a model that uses the same indoor PCB as my unit but claims to have the missing sensors. Pins S1 and S2 on CN15 have weak internal pullups to 5V, these should be the pins for the light sensor and human sensor. They dont have the same value pullups, so one is probably a resistive light sensor, the other is a high low signal. Not sure if they need anything to be implemented in firmware on the main pcb to be functional. Havent had a chance to test yet, but we might be able to add generic versions of these sensors to enable these on our units.

Also, i tested echo_status, the bit does indeed silence the beeper, but only for that command, then it automatically returns to 0. so we must send each command with that bit high if we want it to be quiet. This shouldnt be too bad to implement as an option.

Lastly, I noticed there is the option to receive the indoor temperature from the remote vs the builtin temp sensor, based on how the protocol works we might be able to inject that temperature from the esp! allowing us to use other temp sensors from within HA. Byte 13 looks like a prime candidate for where that value should go. But havent been able to test yet.

Please let me know how else i can help, looking forward to potentially all the new features this might bring.

2 Likes

I tested the half_degree bit, same deal as the echo bit, you must send it each command. But it didnt seem to affect the setpoint, i expected everything to need to be doubled. But everything seemed to function as before. Maybe something else needs to be set, for this function to work. Also played around with byte 13 and 16 with no obvious effect.

Im not sure how to implement extra switches in your code, but I think once you have some time to add one, I can try to help out and add all the others as well by following your example

I do have it but there is a unique certificate inside each of bin files so I don’t think mine will work on your board. At least when I accidentally flashed the wrong image to one of my ESP boards (I have 4 of them) it was not able to communicate to the Haier platform. Mast by related to mac address or serial number etc.

Thanks for the service manual nice document to check. But I don’t think it will help us with the protocol. Sadly but there should be much more under the hood. I am afraid the only way to figure out all functionality is to reverse code the original firmware. I have a couple of thoughts but I need some equipment first. I ordered things already but it will take some time to receive.

NIce, that is what I can easily add to functionality. Will try it.

I don’t think remote talks to ESP directly I think it just sends data to AC directly. In the best case, AC reports it to esp. At worst - keep it to itself. But I am just guessing here.

Thanks. I will defiantly ask to help with testing and after I will add a way to update known parameters you can help with adding support to new features.

Yes, I don’t think it would be that easy. And probably not all ACs support this. Or maybe there is just reserved for the future use

That is all in the python code. Yes I probably write short instruction how to do it. But first I need to implement wayt to update parameters properly
.

1 Like

@ivoh95
Added echo option as beeper to configuration. Now you can set beeper: false in yaml file
Updated it on the dev branch.

P.S. And you were right about 20 C to offset it looks better. Also included in sources.

2 Likes

I have tested @paveldn code with 8266 on haier AC with two different protocols

on smartAir2:

[01:45:11][C][uart.arduino_esp8266:102]: UART Bus:
[01:45:11][C][uart.arduino_esp8266:103]:   TX Pin: GPIO1
[01:45:11][C][uart.arduino_esp8266:104]:   RX Pin: GPIO3
[01:45:11][C][uart.arduino_esp8266:106]:   RX Buffer Size: 256
[01:45:11][C][uart.arduino_esp8266:108]:   Baud Rate: 9600 baud
[01:45:11][C][uart.arduino_esp8266:109]:   Data Bits: 8
[01:45:11][C][uart.arduino_esp8266:110]:   Parity: NONE
[01:45:11][C][uart.arduino_esp8266:111]:   Stop bits: 1
[01:45:11][C][uart.arduino_esp8266:113]:   Using hardware serial interface.
[01:45:11][W][uart.arduino_esp8266:127]:   You're using the same serial port for logging and the UART component. Please disable logging over the serial port by setting logger->baud_rate to 0.
[01:45:11][C][captive_portal:088]: Captive Portal:
[01:45:11][C][web_server:125]: Web Server:
[01:45:12][C][web_server:126]:   Address: :80
[01:45:12][C][mdns:084]: mDNS:
[01:45:12][C][mdns:085]:   Hostname: 
[01:45:12][C][ota:085]: Over-The-Air Updates:
[01:45:12][C][ota:086]:   Address: :8266
[01:45:12][C][api:138]: API Server:
[01:45:12][C][api:139]:   Address: :6053
[01:45:12][C][api:143]:   Using noise encryption: NO
[01:45:14][D][Haier:506]: Message sent: FF FF 0A 00 00 00 00 00 00 61 00 07 72
[01:45:15][W][Haier:338]: Incoming packet timeout, packet size 11, expected size 13
[01:45:19][D][Haier:506]: Message sent: FF FF 0A 00 00 00 00 00 00 61 00 07 72
[01:45:20][W][Haier:338]: Incoming packet timeout, packet size 11, expected size 13
[01:45:24][D][Haier:506]: Message sent: FF FF 0A 00 00 00 00 00 00 61 00 07 72
[01:45:25][W][Haier:338]: Incoming packet timeout, packet size 11, expected size 13
[01:45:29][D][Haier:506]: Message sent: FF FF 0A 00 00 00 00 00 00 61 00 07 72
[01:45:30][W][Haier:338]: Incoming packet timeout, packet size 11, expected size 13
[01:45:34][D][Haier:506]: Message sent: FF FF 0A 00 00 00 00 00 00 61 00 07 72
[01:45:35][W][Haier:338]: Incoming packet timeout, packet size 11, expected size 13

8266 on hON model, seems good

[01:53:45][C][logger:275]: Logger:
[01:53:45][C][logger:276]:   Level: DEBUG
[01:53:45][C][logger:277]:   Log Baud Rate: 115200
[01:53:45][C][logger:278]:   Hardware UART: UART0
[01:53:45][C][uart.arduino_esp8266:102]: UART Bus:
[01:53:45][C][uart.arduino_esp8266:103]:   TX Pin: GPIO1
[01:53:45][C][uart.arduino_esp8266:104]:   RX Pin: GPIO3
[01:53:45][C][uart.arduino_esp8266:106]:   RX Buffer Size: 256
[01:53:45][C][uart.arduino_esp8266:108]:   Baud Rate: 9600 baud
[01:53:46][C][uart.arduino_esp8266:109]:   Data Bits: 8
[01:53:46][C][uart.arduino_esp8266:110]:   Parity: NONE
[01:53:46][C][uart.arduino_esp8266:111]:   Stop bits: 1
[01:53:46][C][uart.arduino_esp8266:113]:   Using hardware serial interface.
[01:53:46][W][uart.arduino_esp8266:127]:   You're using the same serial port for logging and the UART component. Please disable logging over the serial port by setting logger->baud_rate to 0.
[01:53:46][C][captive_portal:088]: Captive Portal:
[01:53:46][C][web_server:125]: Web Server:
[01:53:46][C][web_server:126]:   Address: :80
[01:53:46][C][mdns:084]: mDNS:
[01:53:46][C][mdns:085]:   Hostname: 
[01:53:46][C][ota:085]: Over-The-Air Updates:
[01:53:46][C][ota:086]:   Address: :8266
[01:53:46][C][api:138]: API Server:
[01:53:46][C][api:139]:   Address: :6053
[01:53:46][C][api:143]:   Using noise encryption: NO
[01:53:48][D][Haier:506]: Message sent: FF FF 0A 40 00 00 00 00 00 01 4D 01 99 B3 B4
[01:53:48][D][Haier:668]: HVAC Mode = 0x4
[01:53:48][D][Haier:669]: Fan speed Status = 0x5
[01:53:48][D][Haier:670]: Horizontal Swing Status = 0x0
[01:53:48][D][Haier:671]: Vertical Swing Status = 0x2
[01:53:48][D][Haier:672]: Set Point Status = 0x6
[01:53:49][D][climate:385]: '${device_name}' - Sending state:
[01:53:49][D][climate:388]:   Mode: OFF
[01:53:49][D][climate:393]:   Fan Mode: AUTO
[01:53:49][D][climate:399]:   Preset: NONE
[01:53:49][D][climate:405]:   Swing Mode: OFF
[01:53:49][D][climate:408]:   Current Temperature: 25.00°C
[01:53:49][D][climate:414]:   Target Temperature: 22.00°C
[01:53:49][D][Haier:485]: Received Poll command answer message during phase 8, size: 45, content: FF FF 2A 40 00 00 00 00 00 02 6D 01 06 02 45 00 02 02 00 00 00 0C 32 00 5C 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C6 BB DC
[01:53:51][D][Haier:506]: Message sent: FF FF 08 40 00 00 00 00 00 FC 44 23 40
[01:53:51][D][Haier:485]: Received Signal request answer message during phase 10, size: 17, content: FF FF 0E 40 00 00 00 00 00 FD 00 00 00 00 00 00 4B C1 DD
[01:53:51][D][Haier:285]: WiFi signal is: -41dBm => 67%
[01:53:51][D][Haier:506]: Message sent: FF FF 0C 40 00 00 00 00 00 F7 00 00 00 43 86 F5 F1
[01:53:51][D][Haier:485]: Received Signal level answer message during phase 12, size: 11, content: FF FF 08 40 00 00 00 00 00 05 4D 61 80
[01:53:53][D][Haier:506]: Message sent: FF FF 0A 40 00 00 00 00 00 01 4D 01 99 B3 B4
[01:53:53][D][Haier:668]: HVAC Mode = 0x4
[01:53:53][D][Haier:669]: Fan speed Status = 0x5
[01:53:53][D][Haier:670]: Horizontal Swing Status = 0x0
[01:53:53][D][Haier:671]: Vertical Swing Status = 0x2
[01:53:53][D][Haier:672]: Set Point Status = 0x6
[01:53:54][D][climate:385]: '${device_name}' - Sending state:
[01:53:54][D][climate:388]:   Mode: OFF
[01:53:54][D][climate:393]:   Fan Mode: AUTO
[01:53:54][D][climate:399]:   Preset: NONE
[01:53:54][D][climate:405]:   Swing Mode: OFF
[01:53:54][D][climate:408]:   Current Temperature: 25.00°C
[01:53:54][D][climate:414]:   Target Temperature: 22.00°C
[01:53:54][D][Haier:485]: Received Poll command answer message during phase 8, size: 45, content: FF FF 2A 40 00 00 00 00 00 02 6D 01 06 02 45 00 02 02 00 00 00 0C 32 00 5C 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C6 BB DC
[01:53:55][D][api:102]: Accepted 192.168.51.3
[01:53:55][D][api.connection:861]: Home Assistant 2022.7.6 (192.168.51.3): Connected successfully
[01:53:58][D][Haier:506]: Message sent: FF FF 0A 40 00 00 00 00 00 01 4D 01 99 B3 B4
[01:53:58][D][Haier:668]: HVAC Mode = 0x4
[01:53:58][D][Haier:669]: Fan speed Status = 0x5
[01:53:58][D][Haier:670]: Horizontal Swing Status = 0x0
[01:53:58][D][Haier:671]: Vertical Swing Status = 0x2
[01:53:58][D][Haier:672]: Set Point Status = 0x6
[01:53:59][D][climate:385]: '${device_name}' - Sending state:
[01:53:59][D][climate:388]:   Mode: OFF
[01:53:59][D][climate:393]:   Fan Mode: AUTO
[01:53:59][D][climate:399]:   Preset: NONE
[01:53:59][D][climate:405]:   Swing Mode: OFF
[01:53:59][D][climate:408]:   Current Temperature: 25.00°C
[01:53:59][D][climate:414]:   Target Temperature: 22.00°C
[01:53:59][D][Haier:485]: Received Poll command answer message during phase 8, size: 45, content: FF FF 2A 40 00 00 00 00 00 02 6D 01 06 02 45 00 02 02 00 00 00 0C 32 00 5C 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C6 BB DC
[01:54:01][D][Haier:506]: Message sent: FF FF 08 40 00 00 00 00 00 FC 44 23 40
[01:54:01][D][Haier:485]: Received Signal request answer message during phase 10, size: 17, content: FF FF 0E 40 00 00 00 00 00 FD 00 00 00 00 00 00 4B C1 DD
[01:54:01][D][Haier:285]: WiFi signal is: -40dBm => 68%
[01:54:01][D][Haier:506]: Message sent: FF FF 0C 40 00 00 00 00 00 F7 00 00 00 44 87 37 B0
[01:54:01][D][Haier:485]: Received Signal level answer message during phase 12, size: 11, content: FF FF 08 40 00 00 00 00 00 05 4D 61 80
[01:54:03][D][Haier:506]: Message sent: FF FF 0A 40 00 00 00 00 00 01 4D 01 99 B3 B4
[01:54:03][D][Haier:668]: HVAC Mode = 0x4
[01:54:03][D][Haier:669]: Fan speed Status = 0x5
[01:54:03][D][Haier:670]: Horizontal Swing Status = 0x0
[01:54:04][D][Haier:671]: Vertical Swing Status = 0x2
[01:54:04][D][Haier:672]: Set Point Status = 0x6
[01:54:04][D][climate:385]: '${device_name}' - Sending state:
[01:54:04][D][climate:388]:   Mode: OFF
[01:54:04][D][climate:393]:   Fan Mode: AUTO
[01:54:04][D][climate:399]:   Preset: NONE
[01:54:04][D][climate:405]:   Swing Mode: OFF
[01:54:04][D][climate:408]:   Current Temperature: 25.00°C
[01:54:04][D][climate:414]:   Target Temperature: 22.00°C

(yes, i forgot to add substitution section :smiley: )

In HA all looks ok on the first sight and control test, apart from outdoor temperature, seems about 10C off, but after a quick glance at previous posts, guess that was discussed here before.


Maybe just the long time no use thing.

Hi @evlo,

Thanks for testing. Actually, I also have a version for smartAir2 AC. But it is not finished yet. I will publish it on Github soon.