Conditional data in a switch

Hi,
I want to create a switch for my siren with a conditional payload.
The switch works fine with no conditional payload but not with my conditional payload code.
Can anyone tell me what is wrong in my code?

sirene_garage_on_off:
  friendly_name: "Sirene Garage: Marche/Arret"
  turn_on:
    - service: mqtt.publish
      data:
        qos: "0"
        retain: false
        topic: zigbee2mqtt/Sirene Garage/set
        payload: >-
          {% if is_state('input_boolean.sirenes_blocage','off') %}
                "{\"warning\": {\"duration\": 300, \"mode\": \"emergency\", \"strobe\": false}}"
          {% else %}
                "{\"warning\": {\"duration\": 1, \"mode\": \"off\", \"level\": \"low\", \"strobe\": true, \"strobe_duty_cycle\": 5}}"
          {% endif %}
    - service: input_boolean.turn_on
      target:
        entity_id: input_boolean.sirene_garage_state
      data: {}
  turn_off:
    - service: mqtt.publish
      data:
        qos: "0"
        retain: false
        topic: zigbee2mqtt/Sirene Garage/set
        payload: "{\"warning\": {\"duration\": 5, \"mode\": \"stop\", \"strobe\": false}}"
    - service: input_boolean.turn_off
      target:
        entity_id: input_boolean.sirene_garage_state
      data: {}

Thanks for your help.

I have the ‘feeling’ that it is the JSON formatting of your payload.

I would pull it all into a template and do the logic with jinja. Example here:
HA_Blueprints/Automations/AutoFanControl_MQTT.yaml at ac4f56f22450de4793fc5dc2e2d6d7e38e5d586d · SirGoodenough/HA_Blueprints · GitHub.

OR look into the to_json template functions to format that.

Here’s how I handle complex payloads for mqtt.publish.

I define the payload as a variable and, where necessary, use templates to determine the value of each property. Then I use to_json to convert the variable’s contents into valid JSON for publishing to the topic. I find this method of defining a complex payload is easier to compose and read compared to writing it directly in JSON.

sirene_garage_on_off:
  friendly_name: "Sirene Garage: Marche/Arret"
  turn_on:
    - variables:
        is_off: "{{ is_state('input_boolean.sirenes_blocage','off') }}"
        msg:
          warning:
            duration: "{{ iif(is_off, 300, 1) }}"
            mode: "{{ iif(is_off, 'emergency', 'off') }}"
            level: "{{ iif(is_off, '????', 'low') }}"
            strobe: "{{ iif(is_off, false, true) }}"
            strobe_duty_cycle: "{{ iif(is_off, ????, 5) }}"
    - service: mqtt.publish
      data:
        qos: "0"
        retain: false
        topic: zigbee2mqtt/Sirene Garage/set
        payload: "{{ msg | to_json }}"
    - service: input_boolean.turn_on
      target:
        entity_id: input_boolean.sirene_garage_state
      data: {}
  turn_off:
    - variables:
        msg:
          warning:
            duration: 5
            mode: stop
            strobe: false
    - service: mqtt.publish
      data:
        qos: "0"
        retain: false
        topic: zigbee2mqtt/Sirene Garage/set
        payload: "{{ msg | to_json }}"
    - service: input_boolean.turn_off
      target:
        entity_id: input_boolean.sirene_garage_state

The challenge of using this method for your application is what should the values of level and strobe_duty_cycle be when the input_boolean is off?

You have more knowledge about controlling the siren than I do. In the example above, I set them to ???? which you should replace with correct values.

For example, perhaps strobe_duty_cycle should be 0 and level should be off or maybe its actual value doesn’t matter because strobe is false.


EDIT 1

Correction. Replaced double-quotes with single-quotes inside the template.

EDIT 2

Correction. Variable containing payload lacked a top-level dictionary key.

1 Like

Thanks for your reply.
I get this error when I check the configuration.yaml file:

Error loading /config/configuration.yaml: while parsing a block mapping
in “/config/configuration.yaml”, line 511, column 18
expected , but found ‘’
in “/config/configuration.yaml”, line 512, column 41

Line 511 ==> warning:
Line 512 ==>   duration: "{{ iif(is_off, 300, 1) }}"

Sorry, that’s due to a mistake I made. In two of the templates, I used double-quotes inside and outside the template. I have corrected the example by replacing the inner double-quotes with single-quotes.

          mode: "{{ iif(is_off, 'emergency', 'off') }}"
          level: "{{ iif(is_off, '????', 'low') }}"

Ensure you replace ???? with appropriate values in two places, otherwise there will be another error message.

level: "{{ iif(is_off, '????', 'low') }}"

strobe_duty_cycle: "{{ iif(is_off, ????, 5) }}"

Hi,
With single-quotes I no longer have an error checking the configuration.yalm file but the siren doesn’t works.
I think something is missing in the payload statement. I don’t understand how the label "{"warning": is insert in the payload statement when using warning variable.
Is it possible to send the explode of “{{ warning | to_json }}” statement into a file to check its contents?
This code works fine with the first payload definition (not using variable):

      sirene_garage_on_off:
        friendly_name: "Sirène Garage: Marche/Arrêt"
        turn_on:
          - variables:
              is_off: "{{ is_state('input_boolean.sirenes_blocage','off') }}"
              warning:
                 duration: "{{ iif(is_off, 300, 300) }}"
                 mode: "{{ iif(is_off, 'emergency', 'stop') }}"
                 level: "{{ iif(is_off, 'high', 'low') }}"
                 strobe: "{{ iif(is_off, false, true) }}"
                 strobe_duty_cycle: "{{ iif(is_off, 5, 5) }}"
          - service: mqtt.publish
            data:
              qos: "0"
              retain: false
              topic: zigbee2mqtt/Sirène Garage/set
              payload: "{\"warning\": {\"duration\": 300, \"mode\": \"stop\", \"level\": \"low\", \"strobe\": true, \"strobe_duty_cycle\": 5}}"
          - service: input_boolean.turn_on
            target:
              entity_id: input_boolean.sirene_garage_state
            data: {}
        turn_off:
          - variables:
              warning:
                duration: 1
                mode: stop
                strobe: false
          - service: mqtt.publish
            data:
              qos: "0"
              retain: false
              topic: zigbee2mqtt/Sirène Garage/set
              payload: "{\"warning\": {\"duration\": 1, \"mode\": \"stop\", \"strobe\": false}}"
          - service: input_boolean.turn_off
            target:
              entity_id: input_boolean.sirene_garage_state

This code works fine too with the second payload definition (not using variable):

      sirene_garage_on_off:
        friendly_name: "Sirène Garage: Marche/Arrêt"
        turn_on:
          - variables:
              is_off: "{{ is_state('input_boolean.sirenes_blocage','off') }}"
              warning:
                 duration: "{{ iif(is_off, 300, 300) }}"
                 mode: "{{ iif(is_off, 'emergency', 'stop') }}"
                 level: "{{ iif(is_off, 'high', 'low') }}"
                 strobe: "{{ iif(is_off, false, true) }}"
                 strobe_duty_cycle: "{{ iif(is_off, 5, 5) }}"
          - service: mqtt.publish
            data:
              qos: "0"
              retain: false
              topic: zigbee2mqtt/Sirène Garage/set
              payload: "{\"warning\": {\"duration\": 300, \"mode\": \"emergency\", \"level\": \"high\", \"strobe\": false, \"strobe_duty_cycle\": 5}}"
          - service: input_boolean.turn_on
            target:
              entity_id: input_boolean.sirene_garage_state
            data: {}
        turn_off:
          - variables:
              warning:
                duration: 1
                mode: stop
                strobe: false
          - service: mqtt.publish
            data:
              qos: "0"
              retain: false
              topic: zigbee2mqtt/Sirène Garage/set
              payload: "{\"warning\": {\"duration\": 1, \"mode\": \"stop\", \"strobe\": false}}"
          - service: input_boolean.turn_off
            target:
              entity_id: input_boolean.sirene_garage_state

This code doesn’t work with conditional payload definition (using variable):

      sirene_garage_on_off:
        friendly_name: "Sirène Garage: Marche/Arrêt"
        turn_on:
          - variables:
              is_off: "{{ is_state('input_boolean.sirenes_blocage','off') }}"
              warning:
                 duration: "{{ iif(is_off, 300, 300) }}"
                 mode: "{{ iif(is_off, 'emergency', 'stop') }}"
                 level: "{{ iif(is_off, 'high', 'low') }}"
                 strobe: "{{ iif(is_off, false, true) }}"
                 strobe_duty_cycle: "{{ iif(is_off, 5, 5) }}"
          - service: mqtt.publish
            data:
              qos: "0"
              retain: false
              topic: zigbee2mqtt/Sirène Garage/set
              payload: "{{ warning | to_json }}"
          - service: input_boolean.turn_on
            target:
              entity_id: input_boolean.sirene_garage_state
            data: {}
        turn_off:
          - variables:
              warning:
                duration: 1
                mode: stop
                strobe: false
          - service: mqtt.publish
            data:
              qos: "0"
              retain: false
              topic: zigbee2mqtt/Sirène Garage/set
              payload: "{\"warning\": {\"duration\": 1, \"mode\": \"stop\", \"strobe\": false}}"
          - service: input_boolean.turn_off
            target:
              entity_id: input_boolean.sirene_garage_state

You can use an online YAML to JSON converter to demonstrate what the converted YAML looks like:

However, you cannot use the online converter to test YAML that also contains Jinja2 templates.

I suggest you use an MQTT client to observe the value published to:
zigbee2mqtt/Sirène Garage/set

Home Assistant has an MQTT client in:
Settings → Devices & Services → Integrations → MQTT → Configure → Listen to a topic

image

Enter the topic and click Start Listening. Then publish a payload to the topic (using the code posted above) and observe what is displayed by the MQTT client. You will see if the payload is in proper JSON format or not.

A far better MQTT client is MQTT Explorer. I recommend you take the time to install and learn how to use it. It’s an indispensable tool for debugging MQTT issues.

Hi,
On your advice I use an MQTT client to observe the value published to see what was happening.
Thanks to you I increased my modest skills with HA and MQTT.

I added:

  payload_param:
    warning:

Here the configuration that works:

      sirene_garage_on_off:
        friendly_name: "Sirène Garage: Marche/Arrêt"
        turn_on:
          - variables:
              is_off: "{{ is_state('input_boolean.sirenes_blocage','off') }}"
              payload_param:
                warning:
                   duration: "{{ iif(is_off, 300, 300) }}"
                   mode: "{{ iif(is_off, 'emergency', 'stop') }}"
                   level: "{{ iif(is_off, 'high', 'low') }}"
                   strobe: "{{ iif(is_off, true, true) }}"
                   strobe_duty_cycle: "{{ iif(is_off, 5, 5) }}"
          - service: mqtt.publish
            data:
              qos: "0"
              retain: false
              topic: zigbee2mqtt/Sirène Garage/set
              payload: "{{ payload_param | to_json }}"
          - service: input_boolean.turn_on
            target:
              entity_id: input_boolean.sirene_garage_state
            data: {}
        turn_off:
          - variables:
              payload_param:
                warning:
                  duration: 1
                  mode: stop
                  strobe: false
          - service: mqtt.publish
            data:
              qos: "0"
              retain: false
              topic: zigbee2mqtt/Sirène Garage/set
              payload: "{\"warning\": {\"duration\": 1, \"mode\": \"stop\", \"strobe\": false}}"
          - service: input_boolean.turn_off
            target:
              entity_id: input_boolean.sirene_garage_state
1 Like

I reviewed my own automation (sending IR commands via MQTT) and discovered that the variable’s name should be separate from the payload to be published. In other words, the entire payload dictionary to be published must be contained within the variable. For your application warning cannot be the variable’s name but must be the name of a dictionary key contained by the variable.

So not this:

              warning:
                 duration: "{{ iif(is_off, 300, 300) }}"
                 mode: "{{ iif(is_off, 'emergency', 'stop') }}"
                 level: "{{ iif(is_off, 'high', 'low') }}"
                 strobe: "{{ iif(is_off, true, true) }}"
                 strobe_duty_cycle: "{{ iif(is_off, 5, 5) }}"

but like this:

              msg:
                warning:
                   duration: "{{ iif(is_off, 300, 300) }}"
                   mode: "{{ iif(is_off, 'emergency', 'stop') }}"
                   level: "{{ iif(is_off, 'high', 'low') }}"
                   strobe: "{{ iif(is_off, true, true) }}"
                   strobe_duty_cycle: "{{ iif(is_off, 5, 5) }}"

Then the template becomes:

payload: "{{ msg | to_json }}"

Fortunately, you already discovered this on your own. Glad to hear it’s working now.

I have corrected my example posted above.