Binary_sensor delay_on/off re-evaluate template value during the waiting period

Hi,

I’m trying to create a binary sensor with a dynamic delay_off value based on sensor status (i.e. put a template in delay_off field), and want to understand the expected behaivor.

Say we have the following config,

template:
  - binary_sensor:
      - name: my_binary_sensor
        delay_off: >
          {% if is_state('sensorA', 'on') %}
            minutes: 10
          {% else %}
            minutes: 20
          {% endif %}
        state: >
          {{ is_state('sensorB', 'on') }}

Consider the following events:

  1. T = 00:00, sensorB switches from on to off, and sensorA is off at this timestamp. So we have delay_off=20 based on the template, and my_binary_sensor is expected to switch to off at 00:20 if no other events.
  2. T = 00:05, sensorA switches from off to on. If we re-evaluate the delay_off template, the value should be 10 instead of 20.

Assume no other changes to sensorA and sensorB then

The question is, when should we expected my_binary_sensor switches from on to off? In theory there are three possibilities,

  • T = 00:20, this is based on the original delay_off in event 1, i.e. event 2 has no effect in this case.
  • T = 00:10. After event 2, delay_off is changed to 10, since sensorB switches to off at 00:00, we have 00:00 + 10min = 00:10.
  • T = 00:15. (Doesn’t make too much sense IMO) After event 2 at 00:05, delay_off is set to 10, so we wait for 10 min to set my_binary_sensor off.

In my test, the current HA behavior is the first case, my_binary_sensor will be changed to off at T=00:20. Is it expected that the template in delay_off is not re-evaluated during the wait period? If so, is there a method to make it have the second behavior (change to off at 00:10), either through template or some automations?

Thanks

You can’t template the YAML itself — only fields marked that it can be templated. In this case, you can’t template delay_on or delay_off. What might work is if you replace that with delays in your automation’s actions. There you can have an if-else or choose block. After the delay you can check for the state again with a condition. For example: trigger to on, delay 10s, check if still on. This is basically equivalent to the for.

You could use a trigger-based binary sensor and set up an automation to have full control over when the template sensor is on or off.

You can set the trigger as an event which can be sent from an automation. Like this post but the only difference is a binary_sensor instead of a sensor .

One thing I’m not clear about is whether you would want the template sensor to turn back on if sensor A turns off after 15 minutes? Or an easier way to think about it: if sensor A is turning on and off rapidly, should the template sensor turn on and off rapidly between 00:10 until 00:20?

Assuming you want the template sensor to not turn back on between 00:10 and 00:20, you could set up your automation to something like this:

alias: Test template trigger
description: ""
trigger:
  - platform: state
    entity_id:
      - binary_sensor.sensorB
    from: "off"
    id: turned_on
    to: "on"
  - platform: state
    entity_id:
      - binary_sensor.sensorB
    from: "on"
    id: turned_off
    to: "off"
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id:
              - turned_on
        sequence:
          - event: set_my_sensor
            event_data:
              state: "on"
      - conditions:
          - condition: trigger
            id:
              - turned_off
        sequence:
          - delay:
              hours: 0
              minutes: 10
              seconds: 0
              milliseconds: 0
          - if:
              - condition: state
                entity_id: binary_sensor.sensorA
                state: "off"
            then:
              - wait_for_trigger:
                  - platform: state
                    entity_id:
                      - binary_sensor.sensorA
                    to: "on"
                    from: "off"
                timeout:
                  hours: 0
                  minutes: 10
                  seconds: 0
                  milliseconds: 0
          - event: set_my_sensor
            event_data:
              state: "off"
mode: restart

You could use a timer helper instead of the delay or the wait for trigger if you don’t like having automations that run for extended time periods and would be ended by a HA restart.

From the doc, template is supported for delay_on and delay_off fields, though the behavior isn’t specified for this case. Will try the automation approach

Thanks for the suggestion, will give it a try and report back

Hmm, right… Normally it’s right next to the field name (look at state at the top, for example). I missed it in the text.

Just figured out how to template the delay_off attribute.
It can be done as follows:

    delay_off: >
      {% if is_state('binary_sensor.toilet_door_sensor_opening_3', 'on') -%}
      0:01:00
      {%- else -%}
      0:00:00
      {%- endif %}
1 Like

I do not know. But be aware that if that would be the case, then it might not trigger at all, because the duration might switch form ‘not long enough yet’ to ‘already too long ago’.