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

Found it. In your code you have

name_add_mac_suffix: true

, so when you read the logs, under the entry for mDNS it gives it the name you named it plus the mac suffix which may be different from ESPHome sees

Changing it to false shows the name that matches the device name and name, and it sees the ESP8266 again without ping.

1 Like

Thanks again @paveldn for your work on this!

I have a KZW-W002, so SmartAir2 with a Haier 1U50MEEFRA (Haier Tundra Plus single-split airconditioning set - 5,0 kW).

Using a ESP32-WROOM-32U. Iā€™m a C# developer, but not an ESPHome/hardware expert.

Try 3+ over the lats 2 years, sadly doesnā€™t work out this time either. It doesnā€™t initialize, it might be because of UART issues / misconfiguration. Hmm, at least the pin numbers look correct. And I think I have connected the TX/RX the right way, USB Green to RX on ESP, USB White on TX on ESP.


In the beginning I got stuck with the uart_id part, but when using ā€œuart1ā€ it works. send_wifi is not needed for SmartAir2, but it doesnā€™t hurt.

Also couldnā€™t get it to work with the includes, despite commenting components: [haier], so I had to include the separate yaml partsā€¦ Itā€™s strange, because I see that it works for @rx78nt1alex

Most of the config file (removed irrelevant parts):

substitutions:
  device_name: Haier AC
  device_id: esphome4
  uart_id: "uart1"
  send_wifi: "true"
  
external_components:
  - source: 
      type: git
      url: https://github.com/paveldn/haier-esphome

esphome:
  name: esphome4
  platform: ESP32
  board: esp32dev

logger:
  level: VERBOSE
  # Important, do not log over UART
  baud_rate: 0
  logs:
    json: NONE

uart:
  baud_rate: 9600
  tx_pin: 1
  rx_pin: 3
  id: ${uart_id}

wifi:
  use_address: esphome4.local

  networks:
  - ssid: !secret wifi_primary_ssid
    password: !secret wifi_primary_pass
  - ssid: !secret wifi_secondary_ssid
    password: !secret wifi_secondary_pass

api:
  services:
    - service: turn_on
      then:
      - climate.haier.power_on: ${device_id}
    - service: turn_off
      then:
      - climate.haier.power_off: ${device_id}
  # services:
  #  - <<: !include configs/api/service.turn_on.yaml
  #  - <<: !include configs/api/service.turn_off.yaml

ota:

switch:
  - platform: restart
    name: "Esphome4 restart"
  - platform: template
    id: ${device_id}_display_switch
    name: ${device_name} display
    icon: mdi:led-on
    entity_category: config
    restore_state: yes
    lambda: |-
      return id(${device_id}).get_display_state();
    turn_on_action:
      climate.haier.display_on: ${device_id}
    turn_off_action:
      climate.haier.display_off: ${device_id}
  - platform: template
    id: ${device_id}_health_mode
    name: ${device_name} health mode
    icon: mdi:leaf
    restore_state: yes
    lambda: |-
      return id(${device_id}).get_health_mode();
    turn_on_action:
      climate.haier.health_on: ${device_id}
    turn_off_action:
      climate.haier.health_off: ${device_id}

climate:
  - platform: haier
    id: ${device_id}
    protocol: smartAir2
    name: ${device_name} 
    uart_id: ${uart_id}
    visual:                     # Optional, you can use it to limit min and max temperatures in UI (not working for remote!)
      min_temperature: 16 Ā°C
      max_temperature: 30 Ā°C
      temperature_step: 1 Ā°C
    supported_modes:            # Optional, can be used to disable some modes if you don't need them
    - 'OFF'                     # always available
    - AUTO                      # always available
    - COOL
    - HEAT
    - DRY
    - FAN_ONLY
    supported_swing_modes:      # Optional, can be used to disable some swing modes if your AC does not support it
    - 'OFF'                     # always available
    - VERTICAL                  # always available
    - HORIZONTAL
    - BOTH

# switch:
#   - <<: !include configs/switch/display.yaml
#   - <<: !include configs/switch/health_mode.yaml
#   - <<: !include configs/switch/restart.yaml

Part of the logs:

[13:00:00][D][sensor:127]: 'Esphome1 Uptime Sensor': Sending state 97.54100 s with 0 decimals of accuracy
[13:00:02][V][haier.climate:083]: Phase transition: SENDING_FIRST_STATUS_REQUEST => WAITING_FIRST_STATUS_ANSWER
[13:00:02][D][haier.protocol:019]: Sending frame: type 01, data: 4D 01
[13:00:02][V][haier.protocol:022]: Sending data: FF FF 0A 00 00 00 00 00 00 01 4D 01 59
[13:00:03][W][haier.climate:170]: Answer timeout for command 01, phase WAITING_FIRST_STATUS_ANSWER
[13:00:03][V][haier.climate:083]: Phase transition: WAITING_FIRST_STATUS_ANSWER => SENDING_INIT_1
[13:00:03][V][haier.climate:083]: Phase transition: SENDING_INIT_1 => SENDING_FIRST_STATUS_REQUEST
[13:00:12][V][haier.climate:083]: Phase transition: SENDING_FIRST_STATUS_REQUEST => WAITING_FIRST_STATUS_ANSWER
[13:00:12][D][haier.protocol:019]: Sending frame: type 01, data: 4D 01
[13:00:12][V][haier.protocol:022]: Sending data: FF FF 0A 00 00 00 00 00 00 01 4D 01 59
[13:00:13][W][haier.climate:170]: Answer timeout for command 01, phase WAITING_FIRST_STATUS_ANSWER
[13:00:13][V][haier.climate:083]: Phase transition: WAITING_FIRST_STATUS_ANSWER => SENDING_INIT_1
[13:00:13][V][haier.climate:083]: Phase transition: SENDING_INIT_1 => SENDING_FIRST_STATUS_REQUEST
```![20230528_130110|281x500](upload://vREVB7t5jXa5mJjBhWR8KUcX3Tn.jpeg)

Did you see something obviously wrong? Any things I can test / next steps?

Thanks again!

Are you using a USB/serial convertor cable? That looks like it might be one.

You want to connect the esp pins directly to USB data + and - pins on a USB cable, the USB port on the AC is not a USB port, they are just using the USB style connector.

1 Like

Ahhā€¦ Yes. Iā€™m currently indeed using a USB UART cable, which might already is too ā€˜smartā€™.

OK, thanks! Iā€™ll try a real dumb USB cable.

Yes, @ivoh95 is right. The connection is not USB it is just a USB connector for the UART port. You should use a direct connection without any conversion

with esp32-s3 and esp32-c3 based devkits you can use USB input (even usb-c) to directly pass UART - you just set uart as gpio 20 and 21 on S3 (on c3 it is 18 and 19) so no need for soldering. I have tested this and it really works.

maybe it can be easier for you, just an idea, you can ignore this if it is confusing

Thanks. Iā€™ve tried a real USB cable, on pin 1/3, and 16/17, it doesnā€™t ā€˜initilizeā€™. I really donā€™t understand.

maybe try switching rx and tx wires between the pins? 3 to 1 and 1 to 3. White should indeed be TX, but does not worth to try.

what do you mean it odes not initialize? no ā€œpower onā€ LED? usb red wire should go to 5v pin and black to GND, but I guess that was already working for you from the photos and log.

this should at least show in the log if there is ANY traffic from the AC

uart:
  debug:
    direction: BOTH
    dummy_receiver: false
    after:
      delimiter: "\n"
    sequence:
      - lambda: UARTDebug::log_hex(direction, bytes, ':')

The esp32-c3 with usb-c way is probably still most bulletproof as you can use usb 2.0 type-c cable you get in the store

1 Like

Thanks @evlo Iā€™ve tried the aurt debug logging and created a PR for @paveldn that you should not use an USB cable, added a picture for that, and added uart debug logging in the readme.

Together with my brother we logged both the response that the original KZW-002 stick sends, and the ESP haier and they are different.

Iā€™ve uploaded both ā€˜catā€™ logs of ttyUSB0 in linux. The repeat over and over again of course, and they probably start in the middle.

ESP:
image

KZW-002:
image

So probably not compatible and therefor not responding. Hopefully it means more to any of you to see if we can make it compatible.

Again, just a guess, but I see in this thread year and 7 days ago our conversation :slight_smile: when I tried albetaCOM Haierv2 and that for some reason worked on my smartAir2 AC while other smartAir2 versions did not, so that might be worth a try.

I did change to the board with hON firmware so I cannot test that anymore.
But I remember that @paveldnā€™s version for smartAir2 also worked for me ā€¦ confusing.

I guess by that i meant this esp-haier/Haierv2.h at d5e9bd6dabcdd9c8f442dfb24d35b6bb29159292 Ā· albetaCOM/esp-haier Ā· GitHub component.

1 Like

Original (full sequence, repeats over and over):

FF FF 0A 00 00 00 00 00 01 01 4D 01 5A
FF FF 0A 00 00 00 00 00 01 01 4D 01 5A
FF FF 0A 00 00 00 00 00 01 01 4D 01 5A
FF FF 0A 00 00 00 00 00 01 01 4D 01 5A
FF FF 0A 00 00 00 00 00 01 01 4D 01 5A
FF FF 0A 00 00 00 00 00 01 01 4D 01 5A
FF FF 0A 00 00 00 00 00 01 01 4D 01 5A
FF FF 0A 00 00 00 00 00 01 01 4D 01 5A
FF FF 0A 00 00 00 00 00 01 01 4D 01 5A
FF FF 0A 00 00 00 00 00 00 61 00 07 72
FF FF 0A 00 00 00 00 00 00 61 00 07 72
FF FF 0A 00 00 00 00 00 00 61 00 07 72
FF FF 08 00 00 00 00 00 00 70 78
FF FF 08 00 00 00 00 00 00 70 78
FF FF 08 00 00 00 00 00 00 70 78

ESP:

FF FF 0A 00 00 00 00 00 00 01 4D 01 59
FF FF 0A 00 00 00 00 00 00 01 4D 01 59
FF FF 0A 00 00 00 00 00 00 01 4D 01 59

FF FF 0A 00 00 00 00 00 01 01 4D 01 5A matches the initialization of albetaCOM/esp-haier

It looks like the ā€œ59ā€ and ā€œ5Aā€ difference is because of the checksum, so then there is only a single byte difference and the 59 will automatically change to a ā€œ5Aā€.

Iā€™ve tried finding the place where it sends the initialization, but could find where I should change it from ā€œ00ā€ to ā€œ01ā€. Looked at/near SENDING_INIT_1 and SENDING_FIRST_STATUS_REQUEST.

It looks like it is a byte before this part, as I see the 4D 01 there. Maybe itā€™s part of the HaierMessage class.

static const haier_protocol::HaierMessage STATUS_REQUEST((uint8_t) smartair2_protocol::FrameType::CONTROL, 0x4D01)

Hi @KoalaBear ,
I know about this sequence and have a plan on implementing it but it will not happen soon. And it wouldnā€™t be that easy. I implemented a protocol in a kind of state machine so to change it you will need to properly add states to the main cycle.
I would recommend you first try hOn protocol implementation, at least the first command (61 00 07) is the same for both protocols. If you can provide me logs for this I can check and see if I can help you here.

1 Like

BTW do you know what is the first 01 in theSmartAir2? As other than that it seem pretty much same as hON - at least the initial commands.
Is it maybe id multiple unit system?

@KoalaBear Haier Climate ā€” ESPHome this also has 01014d so maybe it make sense to try this first to try get at least some basic control ā€¦

1 Like

Thanks @paveldn and @evlo

OK, I think that KZW-002 is SmartAir as also noted in readme of paveldn/haier-esphome

No, have a single unit: 1U50MEEFRA (Haier Tundra Plus single-split airconditioning set - 5,0 kW)

Iā€™ll try both soon, hopefully before the weekend.

Good morning everybody,
I need help from people with smartAir2.
So what I am trying to do: is to change the way how smartAir2 starts communicating with AC to be more aligned with the algorithm that the original module is using.
How can you can help me:

  1. Make sure you are using smartAir2 AC :wink:
  2. Get the latest code from the experimental branch: GitHub - paveldn/haier-esphome at experimental
  3. Make sure that your config uses at least Debug logging level
  4. Add to your config the following code:
button:
  - platform: template
    name: Reset protocol
    icon: mdi:restart
    on_press:
      then:
        - lambda: |
            id(${device_id}).reset_protocol();
  1. Compile the code and update your module
  2. With this code you will get a new button with the name ā€œReset protocolā€
  3. Capture logs from your device to file, including when you push the ā€œReset protocolā€ button and at least 10 seconds after this.
  4. If you got some sensitive information in the file (like MAC or IP addresses etc.) replace them with *
  5. Post logs here.
    Probably different ACs have different startup sequences so more logs - better.
    Thank you in advance.

Thanks @paveldn
Iā€™ve ran it, although Iā€™m not a 100% sure that I have a unit with SmartAir2, as it isnā€™t working until now with SmartAir2. But I do use the KZW-002.

Looks like it repeats the tests, I understand. Good news! At least I got a response for the first time, so now I know that the TX/RX must be correct.

Here is the log:

I also tried to use the official (?) Haier Climate ā€” ESPHome

OK, it compiles and flashes, kept ports and everything else the same, but it sadly wonā€™t respond to anything.

Glad your communication is working. According to what I see in the logs your device is hOn, not SmartAir2. Commands for hOn have two extra bytes at the end with CRC (except command 0x61 which is universal for both protocols). So your AC is not answering to commands because it is waiting for extra 2 bytes. Just try hOn it should work.

1 Like

I used the reset protocol button, but Iā€™m not sure how to save the log to file from ESPHome. So I just opened the debug window in ESPHome dashboard and pressed the button.
Outcome has been shared here: Haier-smartAir2.txt ~ pixeldrain

Let me know if you need anything else!

Thanks @paveldn! Finally, why do I have hOn, because Iā€™m using a KZW-002. So now we know that KZW-002 does not (always) equals SmartAir2, as also pointed out on the readme :sweat_smile: (Maybe also change that in the readme to save many hours for others :joy:)

The only thing I would like is 2 extra ā€˜optionsā€™. Something like the ā€œExtra Powerā€ mode, and the swing position down, because itā€™s on the attic, so it points down to the stairs.

If that is something we can add, let me know and Iā€™ll provide logging for the actions.

**edit
I do see that there is a Boost Preset, is that the ā€˜powerā€™ mode?
image