Nested 'if' conditions in ESPhome action?

Hi guys. I’ve spent an hour or so searching for an example or clue on how one creates an ESPhome ‘if’ condition statement that contains a second ‘if’ condition inside it, and found nothing obvious.

Has anyone done it and got an example ?
I’ve tried hacking at my code but get validation errors of one type or another.
In my action code a want to check a binary sensor (switch) on the ESP32 is true/on, and check a LED on another gpio for state false/off before moving a servo. Can paste code, but there must be a nested ‘if condition’ around someplace ?

Sorted it myself with when I found the right info.
I need to stop thinking in C++ nesting terms and switch to HA YAML coding (I find this flipping between coding styles very hard to do (C, C++, JSON, YAML, etc)).
I remember when it was just assembler (and machine code) !

For anyone else, this was what I couldn’t find earlier, just did not fluke the right google string till late last night. The states to be checked are stacked (not nested) under the and: modifier.

ESPhome and/or/not conditions

    on_press:
      then:
        if:
          condition:
            and:
              - binary_sensor.is_on: esp32_local_switch
              - light.is_off: ha_remote_blocking
          then:
            - output.turn_on: yellow_led
#            - output.turn_on: esp32_blue_led
            - output.set_level:
                id: gpio_21_servo
                level: 100.0% # 100% = 2mS as set by 'max_power'
            - delay: 700ms    
            - output.set_level:
                id: gpio_21_servo
                level: 0.0%  # 0% = 1mS as set by 'min_power'
          else:
            - output.turn_on: yellow_led
7 Likes

Thanks for the share as I had given up on that in the past not having found the right way :wink:

Google can be very cruel when you don’t know enough to ask the right question (search)…

FORTH - the power and speed of assembly in a structured language. sigh

And what if we would like:

  • if value is in range a-b: then: switch.toggle: relay1
  • if value is in range d-e: then: switch.toggle: relay2
  • if value is in range g-h: then: switch.toggle: relay3
    ?

@nickrout of course I were there. But there is no 3 ranges example. And simple using it 3 times

    on_value_range:
      above: 5
      below: 10
      then:
        - switch.turn_on: relay_1
    on_value_range:
      above: 25
      below: 30
      then:
        - switch.turn_on: relay_2
    on_value_range:
      above: 45
      below: 50
      then:
        - switch.turn_on: relay_3

do not works.

“Do not works” is not much of an error report.

I understand, sorry but ESPhome is not saying too much, just:
duplicate key: "on_value_range"
And is indicating the line with second on_value_range

Does this work ?

 on_value_range:
   - above: 5
     below: 10
     then:
       - switch.turn_on: relay_1
   - above: 25
     below: 30
     then:
       - switch.turn_on: relay_2
   - above: 45
     below: 50
     then:
       - switch.turn_on: relay_3

based on the docs:

sensor:
  - platform: dht
    humidity:
      name: "Living Room Humidity"
      on_value_range:
        - above: 65.0
          then:
            - switch.turn_on: dehumidifier1
        - below: 50.0
          then:
            - switch.turn_off: dehumidifier1
    temperature:
      name: "Living Room Temperature"

Nope. Doesn’t work. The error is
duplicate key: "above"

EDIT:
for others: dashes! sorry. with dashes before above it works.

OK, worth a try. Maybe try a lambda ?

This should be a feature request, it would be very useful. For now, a lambda should work nicely.

1 Like

This is exactly the problem I’ve been trying to solve for the last few hours, but I have 8 ‘if’ conditions.

I have no clue where to start with the Lambda solution. Could someone point me in the right direction please?

I have a wind vane that outputs between 0V and 2.0V for 360’ of wind direction.

I just want to generate text for each 1/8 of the compass. N, NE, W etc.

I have a longwinded clunky solution using 8 switches but am not happy with the room it takes up.

This sounds like a ‘case’ statement in Arduino coding. A port of that concept would be good.
A lot of us have trouble with the lambda syntax…
https://www.arduino.cc/en/Reference.SwitchCase

I use something similar, maybe something like this ?

make sure you set the voltage sensor to the id below

text_sensor:
  - platform: template
    name: "Wind Direction"
    lambda: !lambda |-
      if (id(voltage).state)>=0.000 and (id(voltage).state)<0.250 {
        return N;
      if (id(voltage).state)>=0.250 and (id(voltage).state)<0.500 {
        return NE;
      if (id(voltage).state)>=0.500 and (id(voltage).state)<0.750 {
        return E;
      if (id(voltage).state)>=0.750 and (id(voltage).state)<1.000 {
        return SE;
      if (id(voltage).state)>=1.000 and (id(voltage).state)<1.250 {
        return S;
      if (id(voltage).state)>=1.250 and (id(voltage).state)<1.500 {
        return SW;
      if (id(voltage).state)>=1.500 and (id(voltage).state)<1.750 {
        return W;
      if (id(voltage).state)>=1.750 and (id(voltage).state)<=2.000 {
        return NW;
      } else {
        return NaN;
      }
    update_interval: 60s
1 Like

Excellent! Thank you. I’ll give that a try tonight.

EDIT: Couldn’t wait so gave it a try. I’m getting this compilation error:

src/main.cpp: In lambda function:
src/main.cpp:322:33: error: expected primary-expression before '>=' token
       if (wind_direction->state)>=0.000 and (wind_direction->state)<0.250 {
                                 ^
src/main.cpp:322:75: error: expected ';' before '{' token
       if (wind_direction->state)>=0.000 and (wind_direction->state)<0.250 {
                                                                           ^
src/main.cpp:349:1: error: expected '}' at end of input
 }
 ^
src/main.cpp:349:1: warning: no return statement in function returning non-void [-Wreturn-type]
src/main.cpp: In function 'void setup()':
src/main.cpp:349:1: error: expected ')' at end of input

What am I missing after the (wind_direction->state)?

Closer, closer;) And how it should be to have switch.turn_on as a result of condition?

BTW I made suggested feature reqest.

Whoops

text_sensor:
  - platform: template
    name: "Wind Direction"
    lambda: !lambda |-
      if (id(wind_direction).state)>=0.000 and (id(wind_direction).state)<0.250 {
        return {"N"};
      }
      if (id(wind_direction).state)>=0.250 and (id(wind_direction).state)<0.500 {
        return {"NE"};
      }
      if (id(wind_direction).state)>=0.500 and (id(wind_direction).state)<0.750 {
        return {"E"};
      }
      if (id(wind_direction).state)>=0.750 and (id(wind_direction).state)<1.000 {
        return {"SE"};
      }
      if (id(wind_direction).state)>=1.000 and (id(wind_direction).state)<1.250 {
        return {"S"};
      }
      if (id(wind_direction).state)>=1.250 and (id(wind_direction).state)<1.500 {
        return {"SW"};
      }
      if (id(wind_direction).state)>=1.500 and (id(wind_direction).state)<1.750 {
        return {"W"};
      }
      if (id(wind_direction).state)>=1.750 and (id(wind_direction).state)<=2.000 {
        return {"NW"};
      } else {
        return {"NaN"};
      }
    update_interval: 60s