Inconsistent payloads (json/plain)

I’ve noticed some inconsistencies in state behavior from zigbee2mqtt:
When switched on i can see two different messages depending on device manufacturer:

zigbee2mqtt/Lamp/set ON
zigbee2mqtt/Lamp/set {“state”:“ON”}

The first one is an Ikea switch, not using JSON payload format
Second one is a Philips Hue Light bulb using JSON payload format

Maybe i’ve made some mistake somewhere, or is this by design different for different device manufacturers?

Or just different by device class (one is a switch the other a light bulb)

You haven’t done anything wrong.

This is why there are so many different herdsman converters for different devices. Each manufacturer implements it in their own way.

Thanks for your feedback!. I had hoped that zigbee2mqtt would straighten out these manufacturer differences internally somehow…

I have another platform subscribing to the zigbee2mqtt topic, so it seems that i have to be prepared to receive different payload formats depending on manufacturer.

You shouldn’t need to worry about it. If you have the homeassistant option enabled in your z2m settings it will publish the required discovery topics home assistant can use and the devices will automatically appear under the mqtt integration. No need to configure any mqtt config yourself.

I understand that and all is fine within Home Assistant !

The concern is actually not Home Assistant related but my own legacy “ESPEasy” platform that i’m running next to Home Assistant.
Maybe i’m going to migrate those units to ESPHOME some day.

Maybe i have to raise a topic on a specific zigbee2mqtt forum because it is not a Home Assistent issue, although zigbee2mqtt is running on top of HAOS.

What does ESPEasy have to do with zigbee2mqtt?

My ESPEasy devices are connected to the same MQTT broker as zigbee2mqtt and Home Assistent so they receive events like switching a zigbee light.Using rules i can trigger custom actions on the ESPEasy device after receiving such event.

And here i noticed that the event payload format seems to depend on the manufacturer and is different between Ikea and Hue.

Just spend some more time to study what is going on here and i think i can answer my own observation now.

The received messages actually come from Home Assistant to control zigbee2mqtt, but i have figured out why these seem inconsistent.

zigbee2mqtt instructs Home Assistant on how to manage a specific device using the MQTT homeassistant/…/config topics:

For Ikea switch

  command_topic  : zigbee2mqtt/Living/Lamp1/set
  payload_off    : OFF
  payload_on     : ON

For Hue light bulb

  command_topic         : zigbee2mqtt/Living/Lamp2/set
  schema                : json

So this explains why Home Assistant seems to send inconsistent messages: it is by design as configured by zigbee2mqtt.

I’m not sure if it’s inconsistent: a switch typically has a binary state, ON or OFF, so to limit the amount of data required to change state, a simple “ON”/“OFF” string would be sufficient.

Lights often have other properties that can be set besides state, like brightness, color, transition time, etc. In such a case, using JSON makes more sense.

Although the documentation suggests that /set should only be used with JSON; if you want to change the state directly, the topic should be /set/state :thinking:

When i look at the documentation, it seems that there is some incorrect behaviour in my own zigbee2mqtt setup.

Zigbee2mqtt actually instructs Home Assistant to use
zigbee2mqtt/HA/Zolder/Bureaulamp/set
topic with a plain payload OFF/ON
And according to the documentation the topic should then be zigbee2mqtt/HA/Zolder/Bureaulamp/set/state

Full config for switch and light:

homeassistant/switch/0x881a14fffe2fabeb/switch/config

availability   : {@{topic=zigbee2mqtt/bridge/state; value_template={{ value_json.state }}}}
command_topic  : zigbee2mqtt/HA/Zolder/Bureaulamp/set
device         : @{hw_version=1; identifiers=System.Object[]; manufacturer=IKEA; model=TRETAKT smart plug; model_id=E22x4; 
                 name=HA/Zolder/Bureaulamp; sw_version=2.4.25; via_device=zigbee2mqtt_bridge_0x00124b0028f55f51}
name           : 
object_id      : ha/zolder/bureaulamp
origin         : @{name=Zigbee2MQTT; sw=2.4.0; url=https://www.zigbee2mqtt.io}
payload_off    : OFF
payload_on     : ON
state_topic    : zigbee2mqtt/HA/Zolder/Bureaulamp
unique_id      : 0x881a14fffe2fabeb_switch_zigbee2mqtt
value_template : {{ value_json.state }}

homeassistant/light/0x00178801033bb4d1/light/config

availability          : {@{topic=zigbee2mqtt/bridge/state; value_template={{ value_json.state }}}}
brightness            : True
brightness_scale      : 254
command_topic         : zigbee2mqtt/HA/Schuur/Lamp/set
device                : @{hw_version=1; identifiers=System.Object[]; manufacturer=Philips; model=Hue White A60 Single bulb E27/B22; 
                        model_id=8718696449691; name=HA/Schuur/Lamp; sw_version=1.116.3; via_device=zigbee2mqtt_bridge_0x00124b0028f55f51}
effect                : True
effect_list           : {blink, breathe, okay, channel_change...}
name                  : 
object_id             : ha/schuur/lamp
origin                : @{name=Zigbee2MQTT; sw=2.4.0; url=https://www.zigbee2mqtt.io}
schema                : json
state_topic           : zigbee2mqtt/HA/Schuur/Lamp
supported_color_modes : {brightness}
unique_id             : 0x00178801033bb4d1_light_zigbee2mqtt

Contrary to documentation, zigbee2mqtt seems to accept non-json payloads on “/set” anyway, at least in my setup.
Maybe this is due to some backwards compatibility?

I see the same in my setup, for switches the command_topic is /set and not /set/state as you’d expect from what the documentation states.

That was my first guess too.