Zigbee MQTT binding doesnt give feedback of switch Item On-Off commands

Hi OpenHab community.

Running OpenHAB 4.3.2 on Pi 5 with a Sonoff Zigbee dongle.
And now starting to migrate to Zigbee2MQTT with a second Sonoff Zigbee dongle.

Mainly because there are MUCH more information and device setup in Z2M than in the OH Zigbee binding.

I have noticed a behaviour of the MQTT binding (or of Zigbee2mqtt, I don’t know which) that is worse that the native Zigbee binding.

With the OH Zigbee binding,
When a PowerOutlet switch Item is set to On (or Off, but lets take On for simplicity), the Item status gets feedback from the device.
Visually, the PowerOutlet Item icon in OH shows a GREEN led if the device has actually changed to On.
But if the On command doesnt succeed (AFAIGuess probably due to Zigbee network problems), the Item’s status remains Off, the led RED, and quite soon, the thing will go Offline.

With the OH MQTT binding,
When a PowerOutlet switch Item is set to On the OH Item icon immediately changes GREEN On, even if I have previously unplugged the PowerOutlet device.
And the Thing will not go Offline untill the Zigbee device availability parameter timeout pops (10 mn AFAIK).

Zigbee2mqtt actually detects that the command didn’t succeed.
z2m: Publish ‘set’ ‘state’ to ‘POxx’ failed: ‘Error: ZCL command 0xhh/1 genOnOff.on({}, {“timeout”:10000,“disableResponse”:false,“disableRecovery”:false,“disableDefaultResponse”:false,“direction”:0,“reservedBits”:0,“writeUndiv”:false}) failed (Timeout - 43942 - 1 - 157 - 6 - 11 after 10000ms)’
But either this doesn’t come to the OH MQTT binding, or the OH MQTT binding ignores it.

Edit: I can stop Zigbee2mqtt service, OH still behaves the same.
On => Status ON/Green.
Off => Status Of/Red.
This means (IMHO) that OH doesn’t wait for a feedback after the command.

To resume:
With OH Zigbee binding, there is a reliable and visible feedback of the commands result.
This is quite important to check that distant devices work correctly. Particularily the thing going Offline that can be used to Alarms.
With MQTT binding, the command works, or not, but there is no feedback.

Sorry being a bit long for this description.

My question of course is: is there a way to have Zigbee2mqtt (or the OH MQTT binding, whatever) provide synchronous feedback for the commands.

Thank you for your help and regards.

you’ve got two places to modify the behavior of a switch:

  • in openhab disable auto-update under metadata
  • in zigbee2mqtt disable optimistic under settings

In many cases optimistic is the wanted behavior to avoid delays in the UI so that’s the default but you can change that to your needs.

Thank you Locke.

Well I already tried many things in OH, inculding the auto-update Meta, active, unactive, removed.
But whatever I do, when using the toggle switch icon, the switch status is immediately updated to On or Off (Red or Green). Even if the PO is unplugged. Even if Z2m is stopped (Z2m not Mosquitto, shutting down Mosquitto sets the MQTT bridge and Things Offline).

So I think this is the behaviour of the MQTT binding. Any chance for a fix ?

I then decided to create a rule when the switch item is updated that waits 5 s and then checks the elapsed time of last-seen Item to update the switch Item to UNDEF if more than 5 secs…
But I had strange results because of the second issue below.

I think Z2m to blame for this one.
When using the toggle button is the “Exposed” section of the PowerOutlet in Z2m, Z2m publishes state messages (On, Linkquality, voltage, …) 3 or 4 times.
This reflects in OH log, saying >Item ‘PO_05_On_Off_Switch’ received command ON < several times as well.
Same behaviour with the toggle button in OH.
Similar issues seem to have been reported, but … no fix.
I will try to open a new issue by myself if I have time.

But all in all
Z2m and the MQTT binding are complex to configure, at least for begginners, with little OH specific documentation (What to code for a Thing availibility topic ? Availability Payload ? What to code as command topic for a switch ? Transforms ? JSONPATH, JS, How to ???), and this results in lot of time spent googling and scanning the forums.

(Aside: This is a general problem with OH, at least for me. There is a nice online official documentation, but when I have a problem with settings in the GUI, and I go the OH web site, I can see lots of information about what must be coded in FILES that I don’t use. Information I don’t understand, I don’t see how to use. No GUI samples or hard copies. And I’m back struggling with Google and forums.
I know OH is Open source and freely supported and I’m very thankfull to the developpers, but please provide a GUI documentation. A GUI parameter → a GUI documentation and examples).

Migration will require to recreate or adapt allmost all (Item naming scheme changes). A huge work.
Reliability is not as I expected, at least for switches (when I activate a PowerOutlet, I want to make sure it actually went On or Off or that I am alerted if not).
There are unfixed and unanswered issues in Z2m.
I posted the same message as here on the Z2m forum, but none answered.
Well I guess there are too much drowbacks with Z2m and I will stick with the standard Zigbee binding and cancel migration. May have another try later.

In theory migrating to Z2m seemed a good idea.
I’d like to live in theory because life is so easy there.

first of all: z2m is not the perfect choice for beginners. If you don’t need the additional features of z2m then my recommendation would be to stay with the binding.

Then: What you want to a achieve definetly works without problems. The only thing you have to change is to set Auto-update to false. The default settings of z2m and mqtt are just fine. Of course I don’t know if you have changed something else (so maybe recreate your mqtt-thing…).

Thank you again Locke.

If the things and channels are auto discovered in Home Assistant mode, if the physical Switch item doesn’t obey to OH commands, its status remains unchanged.
That’s almost ok. Except that
1 - The Thing doesn’t go Offline.
2 - The definitions are awfully verbose and all this is greek to me, I don’t want this.

HA mode disabled to back to manual definition.

if Auto-update is enabled or defaulted:
I can control the physical switch with the OH toggle switch On, Off, all is Ok (except all I explained above).

If Auto-update is set to false as you advise, let’s say while the OH Poweroutlet switch is On/Green.
I can controll the physical Poweroutlet to go Off, but the OH status stays On/Green (OH doesn’t know the Poweroutlet has gone Off).
Trying to switch back to On doesn’t work: OH doesnt issue commands to set to On an Item that is already… On !

When the OH toggle switch is set to Off, I can see Z2m several messages.
Mosquitto
1741908010: Received PUBLISH from a64bcbc1-2e7b-4386-8f3a-f2c1261fa491 (d0, q2, r0, m1, ‘zigbee2mqtt/PO_99/set/state’, … (2 bytes))
1741908010: Sending PUBLISH to mqttjs_fecbf3ac (d0, q0, r0, m0, ‘zigbee2mqtt/PO_99/set/state’, … (2 bytes))

1741908010: Received PUBLISH from mqttjs_fecbf3ac (d0, q0, r0, m0, ‘zigbee2mqtt/PO_99/state’, … (2 bytes))
1741908010: Sending PUBLISH to a64bcbc1-2e7b-4386-8f3a-f2c1261fa491 (d0, q0, r0, m0, ‘zigbee2mqtt/PO_99/state’, … (2 bytes))

Z2m several messages.
>z2m:mqtt: MQTT publish: topic ‘zigbee2mqtt/PO_99/state’, payload ‘OFF’<

The OH log messages show
2025-03-14 00:30:15.241 [INFO ] [openhab.event.ItemCommandEvent ] - Item ‘PO99sw’ received command OFF
2025-03-14 00:30:15.294 [INFO ] [openhab.event.ItemCommandEvent ] - Item ‘PO99sw’ received command OFF

But not that it has worked:
There is NO MESSAGE >Item ‘PO99sw’ changed from ON to OFF< .

The MQTT comand Topic
zigbee2mqtt/PO_99/set/state

The MQTT state Topic is
zigbee2mqtt/PO_99/state

Just in case, I coded the ‘Custom On (Off) Value’ ro ON and OFF resp. But no luck.

It looks like

  • I have made a definition mistake, but I used Copy/Paste and all looks ok…
  • Or that the MQTT binding ignores the State Topic sent by Z2M and the Item has no state feedback.

Maybe you have a clue. Otherwise, I give up and take hollidays.

Thanks and regards.

I don’t use this binding, so could be off base, but the command topic looks off compared to binding I do use. One thing that is not clear, have you used MQTT explorer to copy and paste the topics for the generic Mqtt thing?

Another thought, does the Z2m app have a way to control the switch without involving OH? If yes, does that work and what MQTT messages/topics do you see with Explorer when doing that?

The issue not about the Thing or Item not working.
They DO work.
But the PowerOutlet switch item only works with auto-update Meta defaulted or set to true.
In other words, it works blind, without feedback that the action really succeeded.

If Zigbee is similar to Zwave, when a command is sent, it is followed in 1-2 seconds with a “command poll”. That should return the new state of the device.
command poll 2025-03-14 143554

If that doesn’t exist, you could try a rule to “Refresh” the channel at 1.5 seconds when the item is changed. That should also update

Thank you Bob.

But it is Zigbee, not Zwave.

Maybe someone could review this thread and give an advice to solve the issue that seems due to Z2m or the MQTT binding.

Have you configured the availibility topic for the thing?

Have you enabled ‘availibility’ in the z2m settings?

Would be helpful if you can post the Thing configuration.

Yes, the code (from the code tab if configured by UI) is most important to enable people to help you. And please use code fences (for logs too) so that’s it’s readable.

After reading again I’m pretty sure that the command is working but the state is not received by openhab. The auto-update only does a blind guess in order to avoid having to wait for the state change of the device. That gives you the impression that it’s working.

Did you enable attribute or attribute_and_json in z2m under settings - advanced - mqtt output-type?

And: This thread is a great source of examples: Zigbee2mqtt revisited: No more ugly transformations

Same here. I have several zigbee switches connected to openHAB via zigbee2mqtt, but have never seen a command topic like this.

Usually it is something like:

zigbee2mqtt/PO_99/set for the command topic and

zigbee2mqtt/PO_99/state for the state topic.

UID: mqtt:topic:fdaf9d8381:f4df0452e6
label: "Aa PO99 "
thingTypeUID: mqtt:topic
configuration:
  payloadNotAvailable: offline
  payloadAvailable: online
  transformationPattern:
    - JSONPATH:$.state
  availabilityTopic: zigbee2mqtt/PO_99/availability
bridgeUID: mqtt:broker:fdaf9d8381
channels:
  - id: PO99SW
    channelTypeUID: mqtt:switch
    label: PO99SW
    configuration:
      postCommand: true
      qos: 2
      commandTopic: zigbee2mqtt/PO_99/set/state
      stateTopic: zigbee2mqtt/PO_99/state
      transformationPattern:
        - JSONPATH:$.state
      off: OFF
      on: ON
  - id: PO99LINK
    channelTypeUID: mqtt:number
    label: PO99Link
    configuration:
      stateTopic: zigbee2mqtt/PO_99/linkquality

You could make life a lot easier if you would listen to this advice:

No transformation patterns needed anymore …

I agree the command topic looks strange.
AFAIC, I would have expected
zigbee2mqtt/PO_99/state/set instead of zigbee2mqtt/PO_99/set/state …

But I had great difficulties finding documentation and samples either in either in Z2m or OH.
I anyone can help …

I ended up searching forums and finding:
…/set/state
And it DOES work.

Just found this is finally confirmed in Z2m:
‘Without JSON
In case you don’t want to use JSON, publishing to
zigbee2mqtt/ [FRIENDLY_NAME]/set/state with payload ON is the same as publishing to
zigbee2mqtt/ [FRIENDLY_NAME]/set payload (“state”: “ON”}’

So, sorry, dead end. No syntax error.

Once again, my concern is not that the Switch toggle button does not work, but that it requires auto-update unset or true:
The OH Item goes ON or OFF independent of what physically happens.

And I don’t understand

  • why creating Things with the native Zigbee bindings creates switch Items with default unset auto-update behaving as being set to FALSE resulting in a reliable behaviour.
  • while the Items created for channels of the MQTT binding Things are created with auto-update behaving as being set to …TRUE.

I mean maybe they are set to true because the MQTT binding is not able to work correctly otherwise, and this would be what I notice.

Very funny !

I meant documentation that clearly explains what to code in OH.

This was not meant funny.

You were asking for documentation for your device.
You can find documentation on that page.

If both topics, command and state, are set properly, you will get feedback from your device when you hit the physical switch. Regardless if you use MQTT binding with Z2M or the native Zigbee binding.

… And I don’t understand

why creating Things with the native Zigbee bindings creates switch Items with default unset auto-update behaving as being set to FALSE resulting in a reliable behaviour.
while the Items created for channels of the MQTT binding Things are created with auto-update behaving as being set to …TRUE.
I mean maybe they are set to true because the MQTT binding is not able to work correctly otherwise, and this would be what I notice.

All I can help is providing a working power plug config (including representing the correct state in openHAB when the physical switch is pressed on the power plug), connected to z2m and the mqtt binding:

Device: Innr SP 220 control via MQTT | Zigbee2MQTT

openHAB config:

UID: mqtt:topic:mosquitto:innr-sp220-01
label: MQTT Zigbee Innr SP220-01
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:mosquitto
channels:
  - id: innr-sp220-01-sw
    channelTypeUID: mqtt:switch
    label: innr-sp220-01-sw
    description: ""
    configuration:
      commandTopic: zigbee2mqtt/innr-sp220-01/set
      stateTopic: zigbee2mqtt/innr-sp220-01/state
  - id: innr-sp220-01-linkquality
    channelTypeUID: mqtt:number
    label: innr-sp220-01-linkquality
    description: ""
    configuration:
      stateTopic: zigbee2mqtt/innr-sp220-01/linkquality
  - id: innr-sp220-01-last_seen
    channelTypeUID: mqtt:datetime
    label: innr-sp220-01-last_seen
    description: ""
    configuration:
      stateTopic: zigbee2mqtt/innr-sp220-01/last_seen

command topic (mqtt sniffer):

state topic (mqtt sniffer):