Is there a way to not repeat conditions in each template? something like a void that I can call

In my YAML code on ESPHOME I created a structure that basically turns on 3 status LEDs in my bedroom meaning that: 1) GREEN LED all doors and windows are closed; 2) YELLOW LED: at least one door/window on the first floor is open; 3) RED LED: at least one door/window on the ground floor is open.

To do this I created the following code in each binary sensor:


- platform: gpio
    pin:
      number: GPIO17
      inverted: false
      mode:
        input: true
        pullup: True
    name: "MAIN DOOR"
    device_class: door
    id: main_door

    on_press:
      then:
        - light.turn_on: red_led
        - light.turn_off: green_led

    on_release:
      then:
        - if:
            condition:
              and:
                #   I evaluate if everything is closed
                - binary_sensor.is_off: main_door
                - binary_sensor.is_off: garage
                - binary_sensor.is_off: window1
                - binary_sensor.is_off: window2
                - binary_sensor.is_off: door1
                - binary_sensor.is_off: window3
                - binary_sensor.is_off: window4
                - binary_sensor.is_off: window5
                - binary_sensor.is_off: door2
                - binary_sensor.is_off: window6
                - binary_sensor.is_off: window7
                - binary_sensor.is_off: window8
            then:
              - light.turn_on: green_led
              - light.turn_off: red_led
        - if:
            condition:
              and:
                # I evaluate if it concerns only the ground floor
                - binary_sensor.is_off: main_door
                - binary_sensor.is_off: garage
                - binary_sensor.is_off: window1
                - binary_sensor.is_off: window2
                - binary_sensor.is_off: door1
                - binary_sensor.is_off: window3
            then:  
                - light.turn_off: red_led

Since i have to repeat the conditions for all the sensors, is there a way to group them (I mean the conditions) and call them with something like “void”?

For me, I would probably approach it a bit differently.

I would create three template binary sensors green_alert, yellow_alert, red_alert.

They derive their states from the relevant child binary sensors using “or” logic .

Then you add on_press & on_release actions to these aggregate binary sensors.

1 Like

If I’m not asking too much, could you give a quick example. Tks in advance


binary_sensor:

  - platform: template
    name: "Green Alert"
    id: green_alert
    device_class: power

  - platform: template
    name: "Red Alert"
    id: red_alert
    device_class: power

  - platform: template
    name: "Yellow Alert"
    id: yellow_alert
    device_class: power

# how do i implement binary GPIO sensors?

  - platform: gpio
    pin:
      number: GPIO17
      inverted: false
      mode:
        input: true
        pullup: True
    name: "MAIN DOOR"
    device_class: door
    id: main_door

Update: Ok, now I understand the solution you meant. Basically the correlated sensors (at each floor) at each on_press and on_release updated the respective alert (which is the binary sensor template) and then, the template with another on_press / on_release turns the LEDs on or off. However, even if the solution is perhaps better than mine, it doesn’t solve the problem of duplicating lines of code to verify the status of single entities. So I think the best solution is to integrate the answer of “petro” with that of “Mahko_Mahko”. Thank you both.

You can use yaml anchors

- platform: gpio
    pin:
      number: GPIO17
      inverted: false
      mode:
        input: true
        pullup: True
    name: "MAIN DOOR"
    device_class: door
    id: main_door

    on_press:
      then:
        - light.turn_on: red_led
        - light.turn_off: green_led

    on_release:
      then:
        - if:
            condition:
              and: &and_everything
                #   I evaluate if everything is closed
                - binary_sensor.is_off: main_door
                - binary_sensor.is_off: garage
                - binary_sensor.is_off: window1
                - binary_sensor.is_off: window2
                - binary_sensor.is_off: door1
                - binary_sensor.is_off: window3
                - binary_sensor.is_off: window4
                - binary_sensor.is_off: window5
                - binary_sensor.is_off: door2
                - binary_sensor.is_off: window6
                - binary_sensor.is_off: window7
                - binary_sensor.is_off: window8
            then:
              - light.turn_on: green_led
              - light.turn_off: red_led
        - if:
            condition:
              and: &and_ground_floor
                # I evaluate if it concerns only the ground floor
                - binary_sensor.is_off: main_door
                - binary_sensor.is_off: garage
                - binary_sensor.is_off: window1
                - binary_sensor.is_off: window2
                - binary_sensor.is_off: door1
                - binary_sensor.is_off: window3
            then:  
                - light.turn_off: red_led

Then if you want to use them later, call *and_everything or *and_ground_floor

Keep in mind, anchors are limited (I suggest reading up on them). You cannot merge lists, you can merge dicts.

2 Likes

I was thinking something along these lines. Untested.

# id(main_door).state
# id(garage).state
# id(window1).state
# id(window2).state
# id(door1).state
# id(window3).state
# id(window4).state
# id(window5).state
# id(door2).state
# id(window6).state
# id(window7).state
# id(window8).state


binary_sensor:
  - platform: gpio
      pin:
        number: GPIO17
        inverted: false
        mode:
          input: true
          pullup: True
      name: "MAIN DOOR"
      device_class: door
      id: main_door
      
#...................

  - platform: template
    name: "Green Alert" #All Sensors are off
    id: green_alert_all_are_off
    device_class: power
    filters:
      - invert: #Inverts below logic. Use this inversion where you need.
    #Check if any are on. || is the "or" syntax. && is "and"
    lambda: |-
      return
        id(main_door).state ||
        id(garage).state ||
        id(window1).state ||
        id(window2).state ||
        id(door1).state ||
        id(window3).state ||
        id(window4).state ||
        id(window5).state ||
        id(door2).state ||
        id(window6).state ||
        id(window7).state ||
        id(window8).state ||
      ;
    #Adjust actions as required
    on_press: 
      then:
        - light.turn_on: red_led
        - light.turn_off: green_led   
    on_release:
      then:
        - light.turn_on: red_led
        - light.turn_off: green_led   
    

  - platform: template
    name: "Red Alert" #>=1 on on the Ground Floor
    id: red_alert
    device_class: power
    #Check if any are on
    lambda: |-
      return
        id(main_door).state ||
        id(garage).state ||
        id(window1).state ||
        id(window2).state ||
        id(door1).state ||
        id(window3).state ||
      ;
    #Adjust actions as required
    on_press: 
      then:
        - light.turn_on: red_led
        - light.turn_off: green_led   
    on_release:
      then:
        - light.turn_on: red_led
        - light.turn_off: green_led

Could you elaborate a little on this please?

1 Like

Thanks for the further reply. I find it very elegant and will test it right away. Regarding the code duplication issue, since I didn’t understand your approach and, erroneously, I thought that I would have to repeat the status check for each binary sensor (which you clarified with your example). So sorry again, but that was due to my misinterpretation.

1 Like

No worries. I was pretty brief with my initial descriptions and was just on my mobile.

1 Like