ESPHome binding for the Native API [4.0.0;6.0.0)

Just try typing in mdns as the filter in wireshark. I plugged in an ESP32, and within 10 seconds I saw the announcements in wireshark.

You ought to see quite a bit of traffic.

I did, and there was a lot of traffic indeed. But nothing to or from 192.168.1.137… Which makes sense, because filtering on that IP address didn’t yield anything either.

In short:

  • I’ve got 4 ESP32’s running, installed many months ago. They all discovered without problems, and play nicely with openHAB.
  • Earlier this week, I flashed a new ESP32, with the latest ESPHome version, and it refuses to be discovered.
  • If I manually make a thing, the device also doesn’t want to come ONLINE. During these attempts, there is some communication between my openHAB box and the ESP32: ESPHome binding for the Native API [4.0.0;6.0.0) - #457 by ErikDB
  • Pinging the ESP32 works fine, as well as reading its logs via CLI (both on my Windows laptop, as on the Linux openHAB box).

So why isn’t the device reachable in openHAB, is the question…

  1. Delete thing
  2. Stop OH
  3. Set the binding logs to DEBUG
  4. Start OH
  5. Create the thing.
  6. Send logs to me

Also check that you don’t have 2 versions of the binding installed, or any (in theory unrelated) other system issues.

erik@MinipcLG2:/usr/share/openhab/addons$ pal
totaal 4556
drwxr-xr-x 2 openhab openhab    4096 okt 19 15:09  ./
drwxr-xr-x 4 openhab openhab    4096 okt 19 15:09  ../
-rw-r--r-- 1 root    root    3854242 aug 25 10:31  no.seime.openhab.binding.esphome-4.1.0-SNAPSHOT.jar
-rw-r--r-- 1 root    root     604682 sep 23 13:07  org.openhab.binding.shelly-5.0.2-SNAPSHOT.jar
-rw-r--r-- 1 root    root     188578 sep 23 13:32 'org.openhab.binding.unifiprotect-4.0.0-SNAPSHOT-2025-09-23.2 - frame logging.jar'
-rw-r--r-- 1 openhab openhab      70 okt 17 08:16  README

&

Not that I know of…

Done at 16h06.

Done

I suppose that would have been a more logical 2nd step? :stuck_out_tongue: But I was already logging the binding at TRACE level, so okay.

Done

Done at 16h12. I disabled it at 16h14, and re-enabled it after some 10 seconds. Just to add more perspective. :slight_smile:

Will do now.

It seems like it tries to interpret some TCP traffic as X11 packets - which is of course not the case here, and thus they are deemed malformed. Turn off the X11 stuff: “Preferences > Protocols > X11”

That said, the screenshot of raw TCP packets doesn’t tell me much. What is this communication supposed to be? If OH is one of the parties here, I’d think that enabling DEBUG logs for the correct component would reveal more interesting information.

mDNS uses multicast. Multicast don’t have a destination, it’s sent to everybody and those that are interested listen, the rest ignores it. So, your filter will obviously remove these. You could make a filter where the source is OH || ESP32 with no filtering on destination. Sure, you’ll get more irrelevant traffic in there, but it should allow you to retain the mDNS packets.

What is the reason for going with WireShark here? Doesn’t the binding log communication, even on TRACE? Because, this sounds like something that would reveal the reason relatively quickly if you had access to logged communication. Using WireShark is great and all, but depending on the protocol, it can be “hard work” to put everything together.

If the logs are inadequate, I would consider starting up OH in Eclipse with the debugger running, and try to figure out what happens that way.

This isn’t the latest one! It appears you deleted the new one and kept the old one, ref ESPHome binding for the Native API [4.0.0;6.0.0) - #447 by seime

Delete the file and grab the latest from OP (or install from marketplace). The latest one is from medio October, yours appear to be from August.

Based on the logs it appears that you’re suffering due to this ESPHome change: Fix connection time out when device does not support authentication by ccutrer · Pull Request #58 · seime/openhab-esphome · GitHub

:dotted_line_face:

With the latest jar, I ran a manual scan before manually adding the device. It wasn’t discovered, but that’s maybe because I had already created a thing that IP address and device ID in the past? Anyway, now the (manually added)device comes ONLINE and works.

What a stupid mistake… Terrible that I’ve wasted hours of others’ and my time…

I assume this hasn’t been implemented in the meantime?

It was merged 3 days before 2025.10 was released, about 3 weeks ago.

Aha…

I went another way: GitHub - seime/openhab-esphome: ESPHome native API implementation for openHAB binding

Synopsis: ESPHome build 2025.10.3 breaks the rollershutter item

Background: I’m on openHAB 5.0.2 and running esphome. Today, I noticed my esphome devices could be updated so I decided to update one of them. Afterwards, the shutter on the upgraded device did not tilt when ever I pressed UP, STOP, or DOWN. I’ve attached the openHAB logs from the upgraded version and from another blind running an older build. The blind on the upgraded unit does work when I visit the device page and press UP, DOWN, or STOP. Any suggestions on what I can do?

Openhab Configuration
###############  openhab  #####################################################
###############################################################################
## Ip = X.X.X.X
## Release = Debian GNU/Linux 12 (bookworm)
## Kernel = Linux 6.8.12-16-pve
## Platform = lxc
## Uptime = 5 day(s). 19:30:06
## CPU Usage = 1.45% avg over 2 cpu(s) (4 core(s) x 1 socket(s))
## CPU Load = 1m: 0.10, 5m: 0.05, 15m: 0.05
## Memory = Free: 0.56GB (28%), Used: 1.43GB (72%), Total: 2.00GB
## Swap = Free: 1.88GB (94%), Used: 0.11GB (6%), Total: 2.00GB
## Root = Free: 2.10GB (28%), Used: 5.25GB (72%), Total: 7.77GB
## Updates = 0 apt updates available.
## Sessions = 2 session(s)
## Processes = 33 running processes of 4194304 maximum processes
###############################################################################
Esphome Yaml East Blind Configuration (Failing)
esphome:
  name: "blinds-kit-east"
  friendly_name: Blinds-kitchen-east

esp8266:
  board: nodemcuv2

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "key"

ota:
  - platform: esphome
    password: "password"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Blinds-Kitchen-East"
    password: "password"

captive_portal:

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO14
      mode: INPUT_PULLUP
      inverted: True
    name: Rocker Left
    on_press: 
      then:
        - lambda: |-
            id(my_pos) = 20;
        - script.execute: move_servo
        - cover.template.publish:
            id: pub_pos
            state: OPEN
        
  - platform: gpio
    pin:
      number: GPIO12
      mode: INPUT_PULLUP
      inverted: True
    name: Rocker Right
    on_press: 
      then:
        - lambda: |-
            id(my_pos) = -90;
        - script.execute: move_servo
        - cover.template.publish:
            id: pub_pos
            state: CLOSED
number:
  - platform: template
    name: Servo Control
    min_value: -100
    initial_value: 0
    max_value: 100
    step: 1
    optimistic: true
    #set_action:
    on_value:
      then:
        - servo.write:
            id: servo_master1
            level: !lambda 'return x / 100.0;'

globals:
  - id: my_pos
    type: float

script:
  - id: move_servo
    then:
      - servo.write:
          id: servo_master1
          level: !lambda "return id(my_pos) / 100.0;"

cover:
  - platform: template
    name: "East Blind"
    id: pub_pos
    has_position: false
    optimistic: True
    assumed_state: True

    open_action:
      - lambda: |-
          id(my_pos) = 20;
      - script.execute: move_servo

    close_action:     
      - lambda: |-
          id(my_pos) = -90;
      - script.execute: move_servo

    stop_action:
      - servo.detach: servo_master1

output:
  - platform: esp8266_pwm
    id: 'tilt'
    pin: GPIO5
    frequency: 50 Hz      
    
servo:
  - id: servo_master1
    transition_length: 5000ms
    auto_detach_time: 1000ms
    output: 'tilt'
    
web_server:      ```
Esphome Yaml West Blind Configuration
esphome:
  name: blinds-kit-west
  friendly_name: blinds-kit-west

esp8266:
  board: esp01_1m

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "key"

ota:
  - platform: esphome
    password: "password"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Blinds-Kit-West Fallback Hotspot"
    password: "password"

captive_portal:

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO14
      mode: INPUT_PULLUP
      inverted: True
    name: Rocker Left
    on_press: 
      then:
        - lambda: |-
            id(my_pos) = -57;
        - script.execute: move_servo
        - cover.template.publish:
            id: pub_pos
            state: OPEN
        
  - platform: gpio
    pin:
      number: GPIO12
      mode: INPUT_PULLUP
      inverted: True
    name: Rocker Right
    on_press: 
      then:
        - lambda: |-
            id(my_pos) = 90;
        - script.execute: move_servo
        - cover.template.publish:
            id: pub_pos
            state: CLOSED
number:
  - platform: template
    name: Servo Control
    min_value: -100
    initial_value: 0
    max_value: 100
    step: 1
    optimistic: true
    #set_action:
    on_value:
      then:
        - servo.write:
            id: servo_master1
            level: !lambda 'return x / 100.0;'

globals:
  - id: my_pos
    type: float

script:
  - id: move_servo
    then:
      - servo.write:
          id: servo_master1
          level: !lambda "return id(my_pos) / 100.0;"

cover:
  - platform: template
    name: "West Blind"
    id: pub_pos
    has_position: false
    optimistic: True
    assumed_state: True

    open_action:
      - lambda: |-
          id(my_pos) = -57;
      - script.execute: move_servo

    close_action:     
      - lambda: |-
          id(my_pos) = 90;
      - script.execute: move_servo

    stop_action:
      - servo.detach: servo_master1

output:
  - platform: esp8266_pwm
    id: 'tilt'
    pin: GPIO5
    frequency: 50 Hz      
    
servo:
  - id: servo_master1
    transition_length: 5000ms
    auto_detach_time: 500ms
    output: 'tilt'
    
web_server:          
RollerShutter Logs on 25.10.03 (Fails)

openHAB log

info_circle 18:17:01.253 INFO openhab.event.ItemCommandEvent Item ‘blindskiteast_East’ received command UP
info_circle 18:17:01.831 INFO openhab.event.ItemStateUpdatedEvent Item ‘blindskiteast_East’ updated to 0
info_circle 18:17:04.965 INFO openhab.event.ItemCommandEvent Item ‘blindskiteast_East’ received command DOWN
info_circle 18:17:05.495 INFO openhab.event.ItemStateUpdatedEvent Item ‘blindskiteast_East’ updated to 0
info_circle 18:17:24.728 INFO openhab.event.ItemCommandEvent Item ‘blindskiteast_East’ received command UP
info_circle 18:17:25.255 INFO openhab.event.ItemStateUpdatedEvent Item ‘blindskiteast_East’ updated to 0

ESPhome log

Time Level Tag Message
18:32:44 [D] [cover:077] ‘East Blind’ - Setting
18:32:44 [D] [cover:167] ‘East Blind’ - Publishing:
18:32:44 [D] [cover:175] State: CLOSED
18:32:44 [D] [cover:183] Current Operation: IDLE
18:32:48 [D] [cover:077] ‘East Blind’ - Setting
18:32:48 [D] [cover:167] ‘East Blind’ - Publishing:
18:32:48 [D] [cover:175] State: CLOSED
18:32:48 [D] [cover:183] Current Operation: IDLE
18:32:51 [D] [cover:077] ‘East Blind’ - Setting
18:32:51 [D] [cover:081] Command: STOP
18:32:51 [D] [cover:167] ‘East Blind’ - Publishing:
18:32:51 [D] [cover:175] State: CLOSED
18:32:51 [D] [cover:183] Current Operation: IDLE
18:32:51 [D] [cover:167] ‘East Blind’ - Publishing:
18:32:51 [D] [cover:175] State: CLOSED
RollerShutter logs on 25.07.05 (Works)

openHAB log

info_circle 18:21:56.732 INFO openhab.event.ItemCommandEvent Item ‘blindskitwest_West’ received command UP
info_circle 18:21:57.248 INFO openhab.event.ItemStateUpdatedEvent Item ‘blindskitwest_West’ updated to 0
info_circle 18:21:57.248 INFO openhab.event.ItemStateChangedEvent Item ‘blindskitwest_West’ changed from 100 to 0
info_circle 18:22:00.931 INFO openhab.event.ItemCommandEvent Item ‘blindskitwest_West’ received command STOP
info_circle 18:22:01.462 INFO openhab.event.ItemStateUpdatedEvent Item ‘blindskitwest_West’ updated to 0
info_circle 18:22:03.491 INFO openhab.event.ItemCommandEvent Item ‘blindskitwest_West’ received command DOWN
info_circle 18:22:04.034 INFO openhab.event.ItemStateUpdatedEvent Item ‘blindskitwest_West’ updated to 100
info_circle 18:22:04.035 INFO openhab.event.ItemStateChangedEvent Item ‘blindskitwest_West’ changed from 0 to 100

Esphome Log

Time Level Tag Message
18:32:11 [D] [cover:076] ‘West Blind’ - Setting
18:32:12 [D] [cover:086] Command: OPEN
18:32:12 [D] [servo:084] New target: -0.570000
18:32:12 [D] [cover:170] ‘West Blind’ - Publishing:
18:32:12 [D] [cover:176] State: OPEN
18:32:12 [D] [cover:186] Current Operation: IDLE
18:32:15 [D] [servo:069] Reached target
18:32:16 [D] [servo:047] Detached on auto_detach_time
18:32:19 [D] [cover:076] ‘West Blind’ - Setting
18:32:19 [D] [cover:086] Command: CLOSE
18:32:19 [D] [servo:084] New target: 0.900000
18:32:19 [D] [cover:170] ‘West Blind’ - Publishing:
18:32:19 [D] [cover:178] State: CLOSED
18:32:19 [D] [cover:186] Current Operation: IDLE
18:32:22 [D] [servo:069] Reached target
18:32:23 [D] [servo:047] Detached on auto_detach_time
18:32:25 [D] [cover:076] ‘West Blind’ - Setting
18:32:25 [D] [cover:080] Command: STOP
18:32:25 [D] [cover:170] ‘West Blind’ - Publishing:
18:32:25 [D] [cover:178] State: CLOSED
18:32:25 [D] [cover:186] Current Operation: IDLE
18:32:25 [D] [cover:170] ‘West Blind’ - Publishing:
18:32:25 [D] [cover:178] State: CLOSED
  1. Could you provide the output of `openhab-cli` command `bundle:list |grep ESPHome’ ?
  2. Please set the ESPHome binding logs to DEBUG
  3. Please that the ESPHome version of the “old” ESP
  4. Please provide OH channel→item mapping for both West and East devices

Findings so far:

  1. In the new ESP, the commands sent by OH are UP, STOP and DOWN. Based on the OH logs it appears 3 cmds are sent and 3 state updates are received, but only 1 cmd logged in the esp `

    [cover:081] Command: STOP

    `

  2. In the “old” ESP the commands sent by OH are UP, DOWN, UP, commands received by the ESP are OPEN, CLOSE and STOP.

  3. The binding appears to be sending commands and receiveing updates from both ESPs

  4. You appear to be posting the esphome yaml for the “West” blind device (which appears to be working), but not the “East” blind device that isn’t.

BRG

I edited my original post and added the east blind yaml configuration. They should be identical. Not sure how I can provide the channel to item mapping. There’s no channel->item mapping in the things code and the item code only shows the type of rollershutter

From what I can deduce you have linked your `blindskiteast_East` to the `legacy_state` channel. It is deprecated, and may be the reason it no longer works in the latest esphome release. See aioesphomeapi/aioesphomeapi/api.proto at 7012c9382898fe79beef1d251e124d2575c920cf · esphome/aioesphomeapi · GitHub

(Check in your .items file or in MainUi Item settings to see which channel you’re linked against. If it is the only one, modify your esphome yaml to provide ie the tilt information. Then you’ll get a `tilt`channel on OH)

If he’s using the legacy channel, that would definitely be the case. I have some Ruby code that connects to the ESPHome API, and with the 2025.10 release I had to stop using the legacy up/down commands.

I’m confused because I’m using the template cover and it doesn’t seem that it is deprecated. Somehow, the ESPHome is reading it as a legacy channel.

The cover component itself isn’t deprecated. A piece of the protocol changed. Though… does your cover not support position, only open/close? Does the thing in openHAB even have a Rollershutter channel? I could see that being a problem. If @seime hasn’t looked by tomorrow, I’ll check to make sure the Rollershutter channel gets created even if position isn’t supported.

EDIT: that’s correct, your cover doesn’t have a position.

EDIT 2: and yup, if the cover doesn’t support position, it doesn’t create the Rollershutter channel, only the legacy_state channel. So yes, a bug in the binding.

@ccutrer, thanks Cody for confirming. If I were to add position, does a different rollerchannel gets created? Could you share that sample code so I understand what’s happening?

I’m currently checking the following fields in the API message; has_position and has_tilt. If either is true, the corresponding one is created. If none are true, none are created. The only channels that does not depend on these are the legacy_state and current_operation.

Looking at hte docs I see that there is a yaml option has_position, but not has_tilt. So I’ve changed the binding to always show the tilt channel disregarding whether has_tilt is true or false set.

Please test the updated jar.

BRG

I don’t think that will help. Either the roller shutter channel needs to always be added (where it will never display anything besides 0% or 100%, and presumably the device will ignore commands for anything between 1-99%), or the legacy_state channel needs to send position 0/1 instead of the legacy_command options. My vote would be the former (since sending UP/DOWN/STOP commands seems most natural to me), and completely removing the legacy_state channel (new ESPHome no longer ever sets the legacy_state field in the protobuf). This is also how the Home Assistant (MQTT) binding works - Cover components always get a Rollershutter channel.