Haier hOn Air Conditioner not responding after ESPHome update

Hey everyone,

Today it was a bit cold, so I tried turning on the heating mode of my Haier air conditioner.
The last time I remember it working fine was last weekend.

Unfortunately, it’s now not responding at all. The only thing I changed recently was running an “Update All” in the ESPHome dashboard earlier this week.

:wrench: What I’ve tried so far (based on what I found online)

  • Rebuilt and reflashed the S3-Mini
  • Power-cycled the air conditioner
  • Switched from Arduino to esp-idf framework
  • Tried the 2025.10.2 UART component (since 10.3 seems to have UART issues)

:question: Question

Does anyone know what might be causing the
Answer timeout for command 61, phase SENDING_INIT_1
and
Frame parsing error: 9
messages after the update?

Could this be a UART regression, timing change, or something related to the protocol initialization?

:bulb: Any next troubleshooting advice is welcome!

I’m happy to try different builds, frameworks, or debug settings if it helps narrow this down.
Thanks in advance for any ideas or insights! :pray:

:gear: YAML configuration

INFO ESPHome 2025.10.3
INFO Reading configuration /config/esphome/woonkamerairco32.yaml...
INFO Detected log level for Haier protocol: DEBUG
INFO Starting log output from woonkamerairco32.local using esphome API
INFO Successfully resolved woonkamerairco32.local in 0.302s
INFO Successfully connected to woonkamerairco32 @ 172.16.1.204 in 0.003s
INFO Successful handshake with woonkamerairco32 @ 172.16.1.204 in 0.138s
[12:54:43.639][I][app:185]: ESPHome version 2025.10.3 compiled on Oct 26 2025, 11:15:01
[12:54:43.639][C][wifi:679]: WiFi:
[12:54:43.639][C][wifi:458]:   Local MAC: 64:E8:33:84:F3:FC
[12:54:43.639][C][wifi:465]:   IP Address: 172.16.1.204
[12:54:43.641][C][wifi:469]:   SSID: [redacted]
[12:54:43.641][C][wifi:469]:   BSSID: [redacted]
[12:54:43.641][C][wifi:469]:   Hostname: 'woonkamerairco32'
[12:54:43.641][C][wifi:469]:   Signal strength: -56 dB ▂▄▆█
[12:54:43.641][C][wifi:469]:   Channel: 11
[12:54:43.641][C][wifi:469]:   Subnet: 255.255.255.0
[12:54:43.641][C][wifi:469]:   Gateway: 172.16.1.1
[12:54:43.641][C][wifi:469]:   DNS1: 172.16.1.1
[12:54:43.641][C][wifi:469]:   DNS2: 0.0.0.0
[12:54:43.643][C][logger:261]: Logger:
[12:54:43.643][C][logger:261]:   Max Level: DEBUG
[12:54:43.643][C][logger:261]:   Initial Level: DEBUG
[12:54:43.643][C][logger:267]:   Log Baud Rate: 115200
[12:54:43.643][C][logger:267]:   Hardware UART: USB_SERIAL_JTAG
[12:54:43.645][C][logger:274]:   Task Log Buffer Size: 768
[12:54:43.661][C][uart.idf:180]: UART Bus 0:
[12:54:43.665][C][uart.idf:181]:   TX Pin: GPIO21
[12:54:43.665][C][uart.idf:182]:   RX Pin: GPIO20
[12:54:43.665][C][uart.idf:185]:   RX Buffer Size: 256
[12:54:43.665][C][uart.idf:185]:   RX Full Threshold: 8
[12:54:43.665][C][uart.idf:185]:   RX Timeout: 2
[12:54:43.665][C][uart.idf:191]:   Baud Rate: 9600 baud
[12:54:43.665][C][uart.idf:191]:   Data Bits: 8
[12:54:43.665][C][uart.idf:191]:   Parity: NONE
[12:54:43.665][C][uart.idf:191]:   Stop bits: 1
[12:54:43.679][C][haier.climate:255]: Haier Climate 'Climate'
[12:54:43.706][C][haier.climate:256]:   Device communication status: none
[12:54:43.706][C][haier.climate:342]:   Protocol version: hOn
[12:54:43.706][C][haier.climate:342]:   Control method: 1
[12:54:43.706][C][template.select:064]: Template Select 'Airflow vertical'
[12:54:43.706][C][template.select:064]:   Icon: 'mdi:arrow-expand-vertical'
[12:54:43.706][C][template.select:362]:   Update Interval: 5.0s
[12:54:43.706][C][template.select:064]: Template Select 'Airflow horizontal'
[12:54:43.706][C][template.select:064]:   Icon: 'mdi:arrow-expand-horizontal'
[12:54:43.707][C][template.select:362]:   Update Interval: 5.0s
[12:54:43.740][C][captive_portal:116]: Captive Portal:
[12:54:43.743][C][esphome.ota:093]: Over-The-Air updates:
[12:54:43.743][C][esphome.ota:093]:   Address: woonkamerairco32.local:3232
[12:54:43.743][C][esphome.ota:093]:   Version: 2
[12:54:43.743][C][esphome.ota:100]:   Password configured
[12:54:43.759][C][safe_mode:018]: Safe Mode:
[12:54:43.759][C][safe_mode:018]:   Successful after: 60s
[12:54:43.759][C][safe_mode:018]:   Invoke after: 10 attempts
[12:54:43.759][C][safe_mode:018]:   Duration: 300s
[12:54:43.762][C][web_server.ota:241]: Web Server OTA
[12:54:43.779][C][api:222]: Server:
[12:54:43.779][C][api:222]:   Address: woonkamerairco32.local:6053
[12:54:43.779][C][api:222]:   Listen backlog: 4
[12:54:43.779][C][api:222]:   Max connections: 8
[12:54:43.779][C][api:229]:   Noise encryption: YES
[12:54:43.782][C][mdns:179]: mDNS:
[12:54:43.782][C][mdns:179]:   Hostname: woonkamerairco32
[12:54:46.020][D][select:015]: 'Airflow horizontal': Sending state Center (index 2)
[12:54:46.448][D][haier.protocol:019]: Sending frame: type 61, data: 00 07
[12:54:46.451][D][uart_debug:158]: >>> "\xFF\xFF\n"
[12:54:46.479][D][uart_debug:158]: >>> "\x00\x00\x00\x00\x00\x00a\x00\ar"
[12:54:46.509][W][haier.protocol:013]: Frame parsing error: 9
[12:54:46.631][D][uart_debug:158]: <<< "\xFF\xFF.@\x00\x00\x00\x00\x00bE++2.18\x0017062600\xF1\x00\x0017052600\x01U-AC\x00\x00\x00\x00\x00\x04[\x8A\xAB"
[12:54:46.658][W][haier.climate:234]: Answer timeout for command 61, phase SENDING_INIT_1
[12:54:46.673][D][select:015]: 'Airflow vertical': Sending state Center (index 3)
[12:54:51.022][D][select:015]: 'Airflow horizontal': Sending state Center (index 2)
[12:54:51.676][D][select:015]: 'Airflow vertical': Sending state Center (index 3)
[12:54:56.025][D][select:015]: 'Airflow horizontal': Sending state Center (index 2)
[12:54:56.458][D][haier.protocol:019]: Sending frame: type 61, data: 00 07
[12:54:56.461][D][uart_debug:158]: >>> "\xFF\xFF\n"
[12:54:56.486][D][uart_debug:158]: >>> "\x00\x00\x00\x00\x00\x00a\x00\ar"
[12:54:56.518][W][haier.protocol:013]: Frame parsing error: 9
[12:54:56.637][D][uart_debug:158]: <<< "\xFF\xFF.@\x00\x00\x00\x00\x00bE++2.18\x0017062600\xF1\x00\x0017052600\x01U-AC\x00\x00\x00\x00\x00\x04[\x8A\xAB"
[12:54:56.664][W][haier.climate:234]: Answer timeout for command 61, phase SENDING_INIT_1
[12:54:56.676][D][select:015]: 'Airflow vertical': Sending state Center (index 3)

:receipt: Logs

esphome:
  name: woonkamerairco32
  friendly_name: WoonkamerAirco32

esp32:
  board: esp32-c3-devkitm-1
  framework:
    type: arduino

# Enable logging
logger:

ota:
  - platform: esphome
    password: "xxxxxxxxxxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Woonkamerairco32"
    password: "xxxxxxxxxxxxxx"

#10.3 has issues with UART, for now use 2025.10.2
external_components:
  - source: github://esphome/[email protected]
    components: [uart]
    refresh: 1h

captive_portal:

uart:
  id: haier_uart
  tx_pin:
    number: GPIO21
  rx_pin:
    number: GPIO20
  baud_rate: 9600
  debug:
    direction: BOTH
    dummy_receiver: true
    after:
      delimiter: "\n"
    sequence:
      - lambda: |-
          UARTDebug::log_string(direction, bytes);

api:
  encryption:
    key: "xxxxxxxxxxxxxx"
  services:
    - service: turn_on
      then:
      - climate.haier.power_on: haier_ac
    - service: turn_off
      then:
      - climate.haier.power_off: haier_ac

climate:
  - platform: haier
    id: haier_ac
    protocol: hon
    name: Climate
    uart_id: haier_uart
    wifi_signal: true
    visual:
      min_temperature: 16 °C
      max_temperature: 30 °C
      temperature_step: 
        target_temperature: 1
        current_temperature: 0.5
    supported_modes:
      - 'OFF'
      - HEAT_COOL
      - COOL
      - HEAT
      - DRY
      - FAN_ONLY
    supported_swing_modes:
      - 'OFF'
      - VERTICAL
      - HORIZONTAL
      - BOTH
    supported_presets:
      - BOOST
      - SLEEP
    on_alarm_start:
      then:
        - homeassistant.service:
            service: logbook.log
            data:
              domain: climate
              name: Climate
            data_template:
              message: "Alarm activated ({{ alarm_code }}): {{alarm_message}}" 
            variables:
              alarm_message: !lambda "return message;"
              alarm_code: !lambda "return code;"
        - homeassistant.service:
            service: notify.persistent_notification
            data:
              title: "Haier hOn Climate: alarm activated"
            data_template:
              message: "Code: {{ alarm_code }}, message: \"{{ alarm_message }}\""
            variables:
              alarm_message: !lambda "return message;"
              alarm_code: !lambda "return code;"
    on_alarm_end:
      then:
        - homeassistant.service:
            service: logbook.log
            data:
              domain: climate
              name: Climate
            data_template:
              message: "Alarm deactivated ({{ alarm_code }}): {{alarm_message}}" 
            variables:
              alarm_message: !lambda "return message;"
              alarm_code: !lambda "return code;"

button:
  - platform: haier
    haier_id: haier_ac
    self_cleaning:
      name: Start self cleaning
    steri_cleaning:
      name: Start 56°C steri-cleaning

text_sensor:
  - platform: haier
    haier_id: haier_ac
    cleaning_status:
      name: Cleaning status
    protocol_version:
      name: Protocol version

switch:
  - platform: haier
    beeper:
      name: beeper
    health_mode:
      name: Health mode
    display:
      name: Display
    quiet_mode:
      name: Quiet mode

select:
  - platform: template
    id: haier_ac_vertical_direction
    name: Airflow vertical
    entity_category: config
    icon: mdi:arrow-expand-vertical
    update_interval: 5s
    options:
      - Health Up
      - Max Up
      - Up
      - Center
      - Down
      - Max Down
      - Health Down
      - Auto
    lambda: >-
      switch (id(haier_ac).get_vertical_airflow().value_or(esphome::haier::hon_protocol::VerticalSwingMode::CENTER))
      {
          case esphome::haier::hon_protocol::VerticalSwingMode::HEALTH_UP:
              return std::string("Health Up");
          case esphome::haier::hon_protocol::VerticalSwingMode::MAX_UP:
              return std::string("Max Up");
          case esphome::haier::hon_protocol::VerticalSwingMode::UP:
              return std::string("Up");
          default:
          case esphome::haier::hon_protocol::VerticalSwingMode::CENTER:
              return std::string("Center");
          case esphome::haier::hon_protocol::VerticalSwingMode::DOWN:
              return std::string("Down");
          case esphome::haier::hon_protocol::VerticalSwingMode::MAX_DOWN:
              return std::string("Max Down");
          case esphome::haier::hon_protocol::VerticalSwingMode::HEALTH_DOWN:
              return std::string("Health Down");
          case esphome::haier::hon_protocol::VerticalSwingMode::AUTO:
          case esphome::haier::hon_protocol::VerticalSwingMode::AUTO_SPECIAL:
              return std::string("Auto");
      }
    set_action:
      - climate.haier.set_vertical_airflow:
          id: haier_ac
          vertical_airflow: !lambda >-
            if (x == "Health Up")
                return esphome::haier::hon_protocol::VerticalSwingMode::HEALTH_UP;
            else if (x == "Max Up")
                return esphome::haier::hon_protocol::VerticalSwingMode::MAX_UP;
            else if (x == "Up")
                return esphome::haier::hon_protocol::VerticalSwingMode::UP;
            else if (x == "Down")
                return esphome::haier::hon_protocol::VerticalSwingMode::DOWN;
            else if (x == "Max Down")
                return esphome::haier::hon_protocol::VerticalSwingMode::MAX_DOWN;
            else if (x == "Health Down")
                return esphome::haier::hon_protocol::VerticalSwingMode::HEALTH_DOWN;
            else if (x == "Auto")
                return esphome::haier::hon_protocol::VerticalSwingMode::AUTO;
            else
                return esphome::haier::hon_protocol::VerticalSwingMode::CENTER;
  - platform: template
    id: haier_ac_horizontal_direction
    name: Airflow horizontal
    entity_category: config
    icon: mdi:arrow-expand-horizontal
    update_interval: 5s
    options:
      - Max Left
      - Left
      - Center
      - Right
      - Max Right
      - Auto
    lambda: >-
      switch (id(haier_ac).get_horizontal_airflow().value_or(esphome::haier::hon_protocol::HorizontalSwingMode::CENTER))
      {
          case esphome::haier::hon_protocol::HorizontalSwingMode::MAX_LEFT:
              return std::string("Max Left");
          case esphome::haier::hon_protocol::HorizontalSwingMode::LEFT:
              return std::string("Left");
          default:
          case esphome::haier::hon_protocol::HorizontalSwingMode::CENTER:
              return std::string("Center");
          case esphome::haier::hon_protocol::HorizontalSwingMode::RIGHT:
              return std::string("Right");
          case esphome::haier::hon_protocol::HorizontalSwingMode::MAX_RIGHT:
              return std::string("Max Right");
          case esphome::haier::hon_protocol::HorizontalSwingMode::AUTO:
              return std::string("Auto");
      }
    set_action:
      - climate.haier.set_horizontal_airflow:
          id: haier_ac
          horizontal_airflow: !lambda >-
            if (x == "Max Left")
                return esphome::haier::hon_protocol::HorizontalSwingMode::MAX_LEFT;
            else if (x == "Left")
                return esphome::haier::hon_protocol::HorizontalSwingMode::LEFT;
            else if (x == "Right")
                return esphome::haier::hon_protocol::HorizontalSwingMode::RIGHT;
            else if (x == "Max Right")
                return esphome::haier::hon_protocol::HorizontalSwingMode::MAX_RIGHT;
            else if (x == "Auto")
                return esphome::haier::hon_protocol::HorizontalSwingMode::AUTO;
            else
                return esphome::haier::hon_protocol::HorizontalSwingMode::CENTER;

sensor:
  - platform: haier
    haier_id: haier_ac
    compressor_current:
      name: Compressor Current
    compressor_frequency:
      name: Compressor Frequency
    expansion_valve_open_degree:
      name: Expansion Valve Open Degree
    indoor_coil_temperature:
      name: Indoor Coil Temperature
    outdoor_coil_temperature:
      name: Outdoor Coil Temperature
    outdoor_defrost_temperature:
      name: Outdoor Defrost Temperature
    outdoor_in_air_temperature:
      name: Outdoor In Air Temperature
    outdoor_out_air_temperature:
      name: Outdoor Out Air Temperature
    outdoor_temperature:
      name: Outdoor temperature
    power:
      name: Power

binary_sensor:
  - platform: haier
    haier_id: haier_ac
    compressor_status:
      name: Compressor Status
    defrost_status:
      name: Defrost Status
    four_way_valve_status:
      name: Four-way Valve Status
    indoor_electric_heating_status:
      name: Indoor Electric Heating Status
    indoor_fan_status:
      name: Indoor Fan Status
    outdoor_fan_status:
      name: Outdoor Fan Status

In case someone encounters the same issue, I solved it for now by changing the framework type to esp-idf and using the UART and Haire components from the 2025.09.3 release. I’m not sure if all three changes are necessary, but this combination worked for me.

esp32:
  board: esp32-c3-devkitm-1
  framework:
    type: esp-idf

#10.3 has issues with UART, for now use 2025.9.3
external_components:
  - source: github://esphome/[email protected]
    components: [uart, haier]
    refresh: 1h

Just for curiosity, what kind of uart issue there is? Related to the board? You mention S3-mini but code is for C3.