Debouncing binary sensory

You could also try doing what you have but instead of using the state attr of the automation last being triggered try using the binary sensor itself as the condition and use last_changed and make it something like 2 or 3 seconds … still might be too fast of a bounce though and you may have to go to input Boolean route suggested above

EDIT: sorry should have read more closely it seems you said it wasn’t;t working as you had it because it was always false… this is what I have…

value_template: "{{(as_timestamp(now()) - (as_timestamp(states.group.key_group.last_changed))>60)}}"

so your’s would be:

value_template: "{{(as_timestamp(now()) - (as_timestamp(states.binary_sensor.back_door_motion.last_changed))>5)}}"
4 Likes

i’m still waiting for an explanation of why the condition as written won’t work…

1 Like

Thank you so much for taking the time with such a well written and comprehensive answer. I appreciate it.

1 Like

I’ll give that a try too.

Thank you for your time.

At the point the condition is tested the automation has just been triggered so the condition is false.

It will work if the notification firing was used in the template, instead of the automation trigger, but I’m not sure it can beacuse notify.mobile_app is not unique to this activity.

I don’t think that’s correct at all.

I don’t think the “last_triggered” gets set until the action part actually runs.

Have you actually tested that?

Yes, I tested it today without success. Still working on a solution though.

You can leverage the fact that an automation can turn itself off and on. As it turns out, turning off an automation while it is running doesn’t halt the execution of the script running within the automation. When the automation is turned off it can’t be triggered again.

- alias: test
  trigger:
    - platform: state
      entity_id: binary_sensor.foobar
      from: 'off'
      to: 'on'
  action:
    - service: homeassistant.turn_off
      entity_id: automation.test 
    ### add your actions here
    - delay: 00:01
    - service: homeassistant.turn_on
      entity_id: automation.test

well, that’s strange.

I just built a test automation:

- alias: test
  initial_state: 'on'
  trigger:
    platform: state
    entity_id: input_boolean.bool_15
    to: 'on'
  condition:
    - condition: template
      value_template: '{{ (as_timestamp(now()) - as_timestamp(state_attr("automation.test", "last_triggered")) | int > 10)}}'
  action:
    - delay: '00:00:05'
    - service: homeassistant.turn_off
      entity_id: input_boolean.bool_15

And when I turn bool_15 on in 5 seconds the boolean gets turned back off (the automation works). If I wait more than 10 seconds from the first time I switch it on then it goes off again in 5 seconds (the automation works).

If I switch it on again withing 10 seconds after the automation turns it off then it stays on forever until I turn it off (the automation works therefore keeping the switch on by not running the action).

I think I’ve proven to my satisfaction that what I’m saying is correct.

2 Likes

Thank you, finity, you are quite correct. It does indeed work. I re coded it this morning and voilà!

For those who may also need this, here’s my yaml:

- alias: Announce Mail has been delivered
  hide_entity: false
  initial_state: 'on'
  trigger:
    - platform: state
      entity_id: binary_sensor.letterbox
      from: 'off'
      to: 'on'
  condition:
    - condition: template
      value_template: '{{ (as_timestamp(now()) - as_timestamp(state_attr("automation.announce_mail_has_been_delivered", "last_triggered") | default(0)) | int > 5)}}'
  action:
    - service: tts.google_say
      data:
       entity_id: media_player.kitchen_speaker
       message: "Mail has been delivered"
1 Like

You forcing me to prove you were wrong :wink: actually helped me learn something.

I now know that the “last_triggered” gets updated as soon as the actions begin to be executed and not when they are complete.

So the sequence of operation is:

check if the trigger is true
check for condition true
if true then update “last_triggered”
perform actions

You can see the effects of that sequence by swapping the times between the delay and the template in my automation. If you set the delay for 10 seconds and set the template compare value to 5 seconds then the condition will always be true and the automation will run every time since no matter how fast you are you can’t make 10 seconds to be less than 5 seconds. :slightly_smiling_face:

I realized that because I actually did have those values swapped and could never get the automation to not run.

And…

I think it gets even stranger than that because the sequence isn’t exactly as i have it above. There was a thread a while back in which I’m fairly sure it was proven that the conditions actually get evaluated before the trigger gets evaluated.

so it seems that the real sequence is:

check if the conditions are true
check if the trigger is true
set “last_triggered”
perform actions.

I’m not seeing that behavior (tested with 0.89 and 0.91).

I recall posting the results of an experiment using for and a condition with a time-based threshold. Unfortunately, I no longer recall the thread. However, it’s very easy to repeat the experiment.

The following automation turns off light.mantle after 3 minutes but only if the current time is before 11:30:00.

- alias: 'test timed-light off'
  trigger:
    entity_id: light.mantle
    platform: state
    from: 'off'
    to: 'on'
    for: '00:03:00'
  condition:
    condition: time
    before: '11:30:00'
  action:
    - service: light.turn_off
      data:
        entity_id: light.mantle

Here’s what I did:

  • I turned the light on at 11:26 and the automation set the light off, 3 minutes later, at 11:29.
  • Then I immediately turned the light on again. Now the 3-minute period crosses the threshold.
  • At 11:32, the light was not turned off and stayed on.

The automation checked condition after the 3-minute period expired, discovered the current time (11:32) exceeds the threshold time (11:30) and did not execute the action.

Try it and let me know if you get the same result or if the light gets turned off even if the period crosses the threshold.

This is getting more and more interesting by the minute.

I never expected my original post would stimulate such discussion.

Yeah, I didn’t test that specific case myself so maybe something has changed in the later version of HA to “fix” it.

Isn’t the internet great?!! :grinning:

neat solution. however a simpler approach is outlined here

The linked post is three times longer so, just based on its length, I’ll ask you to summarize how it is a “simpler approach”.

Plus, a year has passed since this topic was written, and now in 0.113 it’s possible to use a completely different technique to ensure a script is only executed once (“debounced”).

although the post is long-ish on purpose, to help people understand without asking further questions, it does explain what is achieved visually.

and this isn’t about debouncing a script. its about debouncing a sensor (like a ping sensor) which emits ‘singular blips’ of binary state which needs to be transformed into longer spans of binary state. let me know if there’s something to achieve that in 0.113

Did you notice that the technique used in the linked post is the same one discussed in this topic?

The suggestion I had offered (using a timer) was an alternative approach and I even admitted in my post that it is best to use the other one that had been presented.

yes my bad. i noticed the approaches are more or less the same. i understand that the timer approach can have race conditions and the linked approach avoids that complexity.

anyway - thanks for telling me about the great new automation features in 0.113. i looked at them in detail and it seems like we have an even simpler approach now.

all one needs to do now is to:

  1. create an automation with the “restart” mode,
  2. which gets triggered by the binary sensor and,
  3. turns on another sensor (for keeping the active state),
  4. waits for a delay seconds
  5. turns off the state sensor

with the help of the “restart” mode, the state sensor stays activated upto delay-seconds from the last trigger time of the binary sensor (hence, debounced).

in fact there’s a lot more that can be done now using the new choose sequence feature (debounce multiple binary sensors together based on some if-else-if-else condition, what have you).

thanks @123