Mqtt light with json payload and state

hi,

I am having trouble using a mqtt light component:

this is my setup:

    light:
      - platform: mqtt
        name: Licht Büro
        command_topic: "hm/set/HM-LC-Sw1PBU-FM LEQ1234567:1/STATE"
        state_topic: "hm/status/HM-LC-Sw1PBU-FM LEQ1234567:1/STATE"
        payload_on: '{"val": true}'
        payload_off: '{"val": false}'
        state_value_template: '{{value_json.val}}'

this will send a message like:

hm/set/HM-LC-Sw1PBU-FM LEQ1234567:1/STATE {"val": true}

or

hm/set/HM-LC-Sw1PBU-FM LEQ1234567:1/STATE {"val": false}

(even though, the later cannot be send because if this issue)

which correctly switches on the light but the switch immediately toggles back to the off state, even though the lights are kept on

whenever the real switch is toggled, either by hand, through some remote or through home assistant, mqtt shows the state change like this:

hm/status/HM-LC-Sw1PBU-FM LEQ1234567:1/STATE {"val":true,"ts":1533586178971,"lc":1533585670207,"hm":{"ADDRESS":"LEQ1234567:1"}}

or

hm/status/HM-LC-Sw1PBU-FM LEQ1234567:1/STATE {"val":false,"ts":1533586178971,"lc":1533585670207,"hm":{"ADDRESS":"LEQ1234567:1"}}

when off

to verify the state read out I created a temporary binary sensor which displays the current state correctly:

binary_sensor:
  - platform: mqtt
    name: "Licht Status Büro"
    state_topic: "hm/status/HM-LC-Sw1PBU-FM LEQ1234567:1/STATE"
    device_class: light
    value_template: '{{ value_json.val }}'
    payload_on: true
    payload_off: false

the binary sensor shows the state correctly but I am unable to apply this value to the light component


any ideas?

Have you tried this? Not sure if it’ll work but worth a try
value_template: ‘{{ value_json.val }}’
payload_on: ‘true’
payload_off: ‘false’

Sorry replying from phone and seems the markup button doesn’t work.

I’m not an expert, but perhaps try something like the following (not sure about the quotation marks):

 state_value_template: >
   {% if value_json.val == 'true' %}
     {"val": true}
   {% else %}
     {"val": false}
   {% endif %}”

@lolouk44
tried that, this publishes a mqtt message in the wrong format

hm/set/HM-LC-Sw1PBU-FM LEQ1234567:1/STATE true

but it expects a json as payload, additionally it changes the way the light is triggered, which works already… I just can’t get the state for that device to work

@wmaker
tried this already, I guess the true should be without quotes as it returned as a boolean

anyway, with and without quotes in the expression, the state does not update accordingly

Up until the latest release (0.75), one of the limitations of the HA implementation was that the the command payload had to match the state payload, which made decoding your situation complex.

However, HA v 0.75 introduced the state_on and state_off parameters to separate these.

I haven’t used it myself yet, but from the documentation I think you should be able to do

    light:
      - platform: mqtt
        name: Licht Büro
        command_topic: "hm/set/HM-LC-Sw1PBU-FM LEQ1234567:1/STATE"
        state_topic: "hm/status/HM-LC-Sw1PBU-FM LEQ1234567:1/STATE"
        payload_on: '{"val": true}'
        payload_off: '{"val": false}'
        state_on: true
        state_off: false
        state_value_template: '{{value_json.val}}'

Note that there should not be quotes around the true and false parameters as the json values in the response are binary values, not text values.

@gpbenton

I checked the above mentioned changes in 0.75 and updated:

Allow MQTT Switch to have an optional state configuration (@PrimusNZ - #15430) (switch.mqtt docs)

which means it does not work for mqtt light components

I modified my code to work as a mqtt switch without any changes… the state is still stuck and does not get updated

Ah well. It is a shame the developers can’t develop for all mqtt components at once.

In that case, I think the only approach is that mentioned by @wmaker above, but with the alteration that the comparison must match a binary rather than a string

state_value_template: >
   {% if value_json.val == true %}
     {"val": true}
   {% else %}
     {"val": false}
   {% endif %}”

The important thing is that the result must match the payload_on: value exactly.

Edit: I got a chance to play around and try this, but I couldn’t get the above syntax to work (my yaml isn’t that good). However, this line seems to work fine

    state_value_template: '{% if value_json.val == true  %}{"val": true}{% else %}{"val": false}{% endif %}'