Problem with template sensor with "stacked" if statements?

hello,

i made an template sensor for my flood sensors, to convert 4xbinary swim sensors to one sensor with “speaking” states like “level0, level1, level2, level3, level4” and “Sensor Error!” what works quite well.

now i want to replace the last state “Sensor Error!” with a more detailed string. the idea was to have an state like this “Sensor error: 0111”, where i can see the actual state of the 4 sensors in a kind of binary number. i made an convert of 4 binary states into a “0” or “1” and then to concatenating them to one “message”…
that needs a second “stacked” if statement but i can´t get it run? :sob:

what did i do wrong? or isn´t it possible to stack if statements?

## FLOODLEVEL template Sensor Sickerschacht START
      floodlevel_soakaway:
        #unit_of_measurement: mm
        value_template: >-
          {% if is_state("binary_sensor.aqara_ws_95_water_leak", "off") and is_state("binary_sensor.aqara_ws_96_water_leak", "off") and is_state("binary_sensor.aqara_ws_97_water_leak", "off") and is_state("binary_sensor.aqara_ws_98_water_leak", "off")  %}
            Level0
          {% elif is_state("binary_sensor.aqara_ws_95_water_leak", "on") and is_state("binary_sensor.aqara_ws_96_water_leak", "off") and is_state("binary_sensor.aqara_ws_97_water_leak", "off") and is_state("binary_sensor.aqara_ws_98_water_leak", "off")  %}
            Level1
          {% elif is_state("binary_sensor.aqara_ws_95_water_leak", "on") and is_state("binary_sensor.aqara_ws_96_water_leak", "on") and is_state("binary_sensor.aqara_ws_97_water_leak", "off") and is_state("binary_sensor.aqara_ws_98_water_leak", "off")  %}
            Level2
          {% elif is_state("binary_sensor.aqara_ws_95_water_leak", "on") and is_state("binary_sensor.aqara_ws_96_water_leak", "on") and is_state("binary_sensor.aqara_ws_97_water_leak", "on") and is_state("binary_sensor.aqara_ws_98_water_leak", "off")  %}
            Level3
          {% elif is_state("binary_sensor.aqara_ws_95_water_leak", "on") and is_state("binary_sensor.aqara_ws_96_water_leak", "on") and is_state("binary_sensor.aqara_ws_97_water_leak", "on") and is_state("binary_sensor.aqara_ws_98_water_leak", "on")  %}
            Level4
          {% else %}
            {% if is_state("binary_sensor.aqara_ws_95_water_leak", "on")%}
              {%  set message95 = '1' | int %}  
            {% elif is_state("binary_sensor.aqara_ws_95_water_leak", "off")% }
              {%  set message95 = '0' | int%}  
            {% endif %}
            {% if is_state("binary_sensor.aqara_ws_96_water_leak", "on")%}
              {%  set message96 = '1' | int %}  
            {% elif is_state("binary_sensor.aqara_ws_96_water_leak", "off")% }
              {%  set message96 = '0' | int%}  
            {% endif %}
            {% if is_state("binary_sensor.aqara_ws_97_water_leak", "on")%}
              {%  set message97 = '1' | int %}  
            {% elif is_state("binary_sensor.aqara_ws_97_water_leak", "off")% }
              {%  set message97 = '0' | int%}  
            {% endif %}
            {% if is_state("binary_sensor.aqara_ws_98_water_leak", "on")%}
              {%  set message98 = '1' | int %}  
            {% elif is_state("binary_sensor.aqara_ws_98_water_leak", "off")% }
              {%  set message98 = '0' | int%}  
            {% endif %}

            {{ "Sensor error: " ~ message95 ~ message96 ~ message97 ~ message98}}

          {% endif %}
## FLOODLEVEL template Sensor Sickerschacht END
Configuration warnings
Invalid config for 'template' from integration 'sensor' at sensor.yaml, line 496: invalid template (TemplateSyntaxError: unexpected '}') for dictionary value 'sensors->floodlevel_soakaway->value_template', got '{% if is_state("binary_sensor.aqara_ws_95_water_leak", "off") and is_state("binary_sensor.aqara_ws_96_water_leak", "off") and is_state("binary_sensor.aqara_ws_97_water_leak", "off") and is_state("binary_sensor.aqara_ws_98_water_leak", "off")  %}\n  Level0\n{% elif is_state("binary_sensor.aqara_ws_95_water_leak", "on") and is_state("binary_sensor.aqara_ws_96_water_leak", "off") and is_state("binary_sensor.aqara_ws_97_water_leak", "off") and is_state("binary_sensor.aqara_ws_98_water_leak", "of...




pls help! thanx in advance!
br
Frank

i tried this way, but i got the same errors…

## FLOODLEVEL template Sensor Sickerschacht START
      floodlevel_soakaway:
        #unit_of_measurement: mm
        value_template: >-
          {% if is_state("binary_sensor.aqara_ws_95_water_leak", "on")%}
            {%  set message95 = '1' | int %}  
          {% elif is_state("binary_sensor.aqara_ws_95_water_leak", "off")% }
            {%  set message95 = '0' | int%}  
          {% endif %}
          {% if is_state("binary_sensor.aqara_ws_96_water_leak", "on")%}
            {%  set message96 = '1' | int %}  
          {% elif is_state("binary_sensor.aqara_ws_96_water_leak", "off")% }
            {%  set message96 = '0' | int%}  
          {% endif %}
          {% if is_state("binary_sensor.aqara_ws_97_water_leak", "on")%}
            {%  set message97 = '1' | int %}  
          {% elif is_state("binary_sensor.aqara_ws_97_water_leak", "off")% }
            {%  set message97 = '0' | int%}  
          {% endif %}
          {% if is_state("binary_sensor.aqara_ws_98_water_leak", "on")%}
            {%  set message98 = '1' | int %}  
          {% elif is_state("binary_sensor.aqara_ws_98_water_leak", "off")% }
            {%  set message98 = '0' | int%}  
          {% endif %}

          {% if is_state("binary_sensor.aqara_ws_95_water_leak", "off") and is_state("binary_sensor.aqara_ws_96_water_leak", "off") and is_state("binary_sensor.aqara_ws_97_water_leak", "off") and is_state("binary_sensor.aqara_ws_98_water_leak", "off")  %}
            Level0
          {% elif is_state("binary_sensor.aqara_ws_95_water_leak", "on") and is_state("binary_sensor.aqara_ws_96_water_leak", "off") and is_state("binary_sensor.aqara_ws_97_water_leak", "off") and is_state("binary_sensor.aqara_ws_98_water_leak", "off")  %}
            Level1
          {% elif is_state("binary_sensor.aqara_ws_95_water_leak", "on") and is_state("binary_sensor.aqara_ws_96_water_leak", "on") and is_state("binary_sensor.aqara_ws_97_water_leak", "off") and is_state("binary_sensor.aqara_ws_98_water_leak", "off")  %}
            Level2
          {% elif is_state("binary_sensor.aqara_ws_95_water_leak", "on") and is_state("binary_sensor.aqara_ws_96_water_leak", "on") and is_state("binary_sensor.aqara_ws_97_water_leak", "on") and is_state("binary_sensor.aqara_ws_98_water_leak", "off")  %}
            Level3
          {% elif is_state("binary_sensor.aqara_ws_95_water_leak", "on") and is_state("binary_sensor.aqara_ws_96_water_leak", "on") and is_state("binary_sensor.aqara_ws_97_water_leak", "on") and is_state("binary_sensor.aqara_ws_98_water_leak", "on")  %}
            Level4
          {% else %}
            {{ "Sensor error: " ~ message95 ~ message96 ~ message97 ~ message98}}
          {% endif %}
## FLOODLEVEL template Sensor Sickerschacht END

Booleans can be converted to their integer equivalents 0/1 by using the int filter, you don’t need all the if/thens. Here’s one way to approach it using variables and a couple little number tricks instead of writing out all those is_state functions:

{%  set message95 = states('binary_sensor.aqara_ws_95_water_leak') | bool('e') | int('e')%} 
{%  set message96 = states('binary_sensor.aqara_ws_96_water_leak') | bool('e') | int('e')%} 
{%  set message97 = states('binary_sensor.aqara_ws_97_water_leak') | bool('e') | int('e')%} 
{%  set message98 = states('binary_sensor.aqara_ws_98_water_leak') | bool('e') | int('e') %}

{% if [message95,message96,message97,message98] is search('e') %}
  {{ "Sensor error: " ~ message95 ~ message96 ~ message97 ~ message98 }}
{% elif [message95,message96,message97,message98]|sum == 0 %}
  Level0
{% elif message95 and [message96,message97,message98]|sum == 0 %}
  Level1
{% elif [message95,message96]|sum == 2 and [message97,message98]|sum == 0 %}
  Level2
{% elif [message95,message96,message97]|sum == 3  and message98 == 0%}
  Level3
{% elif [message95,message96,message97,message98]|sum == 4  %}
  Level4
{% endif %}

Another, more compact option is to use list comparison:

{% set x = ['binary_sensor.aqara_ws_95_water_leak', 'binary_sensor.aqara_ws_96_water_leak',
'binary_sensor.aqara_ws_97_water_leak', 'binary_sensor.aqara_ws_98_water_leak']
| map('states') | map('bool', 'e') | map('int', 'e') | list %}
{% if x == [1,0,0,0] %} Level1
{% elif x == [1,1,0,0] %} Level2
{% elif x == [1,1,1,0] %} Level3
{% elif x == [1,1,1,1] %} Level4
{% else %} Sensor Error: {{ x | join }}
{% endif %}
1 Like

hi @Didgeridrew ,
wow, really nice and short solution! thanx!! i was never good in math so i´m impressed by this “simple” solution… thanx! :grin:

but your short solution leaves me with some questions…

  • what does the shorthand comma separated “if statement” (if [message95,message96,message97,message98]) exactly means? multible conditions with AND OR? can´t find any explanation…`? so in this example: if at least ONE contains an “e”, or ALL of them?
  • why is this douple pipes needed (first bool() then int())? just to prevent an unavailable bool value and set an default (“e”) before converting too integer, or what?? wouldn´t come only “| int(‘e’)” to the same result?
  • so i came up to my next question: bool(‘e’) will set an default (“e”) when bool state has either true nor false, imho this could only happen when boolstate is “not available”, correct? beeing honest this combination i had not in mind (but it’s also good to have :grin:).
    “my” idea behing “sensor error”, was the situation, when the “lowest” swimsensor is not detecting (beeing available, but having state ‘false’), but at least one of the “upper” swimsensors does have ‘true’ (so all where available), what must be an error, because it can´t (should´nd) be…(wrong order of sensor detection, because flood rises from buttom up, … could only be, when swim sensor is blocked mechanically, or cable is broken…?)

so i added the “else” clause to your solution to (hopefully) cover this up… :thinking:
i have to wait until tomorrow before i can test…

{%  set message95 = states('binary_sensor.aqara_ws_95_water_leak') | bool('e') | int('e')%} 
{%  set message96 = states('binary_sensor.aqara_ws_96_water_leak') | bool('e') | int('e')%} 
{%  set message97 = states('binary_sensor.aqara_ws_97_water_leak') | bool('e') | int('e')%} 
{%  set message98 = states('binary_sensor.aqara_ws_98_water_leak') | bool('e') | int('e') %}

{% if [message95,message96,message97,message98] is search('e') %}
  {{ "Sensor error: " ~ message95 ~ message96 ~ message97 ~ message98 }}
{% elif [message95,message96,message97,message98]|sum == 0 %}
  Level0
{% elif message95 == 1 and [message96,message97,message98]|sum == 0  %}
  Level1
{% elif [message95,message96]|sum == 2 and [message97,message98]|sum == 0 %}
  Level2
{% elif [message95,message96,message97]|sum == 3  and message98 == 0 %}
  Level3
{% elif [message95,message96,message97,message98]|sum == 4  %}
  Level4
{% else %}
  {{ "Sensor error: " ~ message95 ~ message96 ~ message97 ~ message98 }}
{% endif %}

Square brackets are the delimiters for a list, so the statement is searching for “e” amongst the lists items. If any one of the sensors is unknown or unavailable then the search will be true.

No, because all states in HA are strings. The binary sensors return the strings “on” or “off”, not an actual boolean value.

Yes, it is important to guard against unknown or unavailable entity states. Your additional else to guard against false negatives of the “earlier” sensor should work fine.

1 Like