Events repeatedly fired during automation delay works wired?

Let’s say we setup a simple automation, triggered by an motion sensor event and control a light.

“if motion event happenedd” -> “turn on the light” -> “delay 2 mins” -> “turn off the light”

Then I tested this by firing the trigger event in web UI deverloper tools manually.

Fire the event only one time, everything works perfect as expected.

But if fire the event twice before the 2mins delay is over. The light goes off on the second event fired

At first I suspect the problem may comes with the light turn_on service. So I invoke the turn_on service manually twice, the light didn’t turned off like the automation did.

So where did I do wrong?

here is the automation yaml:

- id: '1552436834458'
  alias: Study Light
  trigger:
  - event_data:
      entity_id: binary_sensor.motion_sensor_155d000157c7e3
    event_type: xiaomi_aqara.motion
    platform: event
  condition: []
  action:
  - data:
      entity_id: light.study
    service: light.turn_on
  - delay: 00:02:00
  - data:
      entity_id: light.study
    service: light.turn_off

I just saw a document with link above. Which seems can solve the problem.

But I still don’t understand why my solution works wired like that.

If an automation is waiting in a delay and the automation is triggered again it skips the delay and continues execution of the actions.

Rather than using a delay try using the “triggered for:” options. e.g.

  trigger:
    platform: state
    entity_id: binary_sensor.pir_entry
    to: 'off'
    for:
      minutes: 3
1 Like

the drawback of using for: x minutes in a separate turn off automation is that this automation will run 100% of the time. Meaning anytime you turn the study light on, it will turn off after 2 minutes. Personally, that’s a deal breaker for me.

The other method is a timer method, which requires a timer, an on automation, and an off automation. This method is good, but personally don’t like creating 9 million automations and entities in my home assistant instance. It just creates more overhead work in the long run with editing.

So, what you can do is segregate your script and turn it off before starting your delay.

automation

- id: '1552436834458'
  alias: Study Light
  trigger:
  - event_data:
      entity_id: binary_sensor.motion_sensor_155d000157c7e3
    event_type: xiaomi_aqara.motion
    platform: event
  condition: []
  action:
  - service: script.turn_off
    entity_id: script.study_light
  - service: light.turn_on
    data:
      entity_id: light.study
  - service: script.study_light

script

script:
  study_light:
    sequence:
    - delay: 00:02:00
    - data:
        entity_id: light.study
      service: light.turn_off

So what this does is avoid the issue of the delay getting skipped. The first service in the automation turns off the script. This means the script isn’t running anymore, so if it executes again, the full 2 minute delay will be executed.

It essentially creates a 2 minute timer that will only fire when this event is seen. It will never fire when the light is turned off. It also has the least amount of home assistant entities with out any drawbacks, if you are a minimalist.

EDIT: This of course assumes that you will continue to trigger off the event and your 2nd automation was triggering off the light turning on.

2 Likes

Thanks for the solution. It works great.

If an automation is waiting in a delay and the automation is triggered again it skips the delay and continues execution of the actions.

But I’m curious for what reason HA design such mechanism?

Great design! I really appreciate not only making something work. But also working gracefully.

I’m quite new to HA. From your code, I guess a HA script should be a single thread/process like stuff, right?

Also, it seems making dozens of sensors and other devices working gracefully needs much more code than I expected before. Does HA have methods to reused code&configs?

Yep. Only one instance of a script or automation can be run at a time.

no, not really. Unless you move to appdaemon which is a python automation utility. appdaemon has the ability to reuse code whenever you want.

Also, I want to clarify, the solution I provided will work with your event trigger. Using @tom_l’s method with a state change on the binary_sensor itself (not using an event) is identical to the solution I provided. I made an assumption that was not true, I assumed your 2nd automation was going to trigger off the light, not the binary_sensor. So you really only need to use my solution if you still plan on using the event for the triggers.

I see. But even if we want a Singleton instance. Restart it all over or even throw exceptions are more resonable then continue the process and skip the delay.

So, the design of this mechanism must have its purpose right? Otherwise it’s just so wired to my opinion.

Great, I’ll go and give appdaemon a shot. Thanks for your answer and information. It helps me a lot.

It’s still a neat way to get around the problem which I will keep in mind for future use.

The devs must have thought differently.

try it:

- id: '1567093370829'
  alias: 自动开玄关灯
  trigger:
  - event_data:
      entity_id: binary_sensor.motion_sensor_158d000237a917
    event_type: xiaomi_aqara.motion
    platform: event
  condition:
  - condition: state
    entity_id: switch.wall_switch_left_158d0002425dcb
    state: 'off'
  action:
  - data:
      entity_id: switch.wall_switch_left_158d0002425dcb
    service: switch.turn_on
  - timeout: 0:30:00
    wait_template: '{{is_state("binary_sensor.motion_sensor_158d000237a917","off")}}'
  - data:
      entity_id: switch.wall_switch_left_158d0002425dcb
    service: switch.turn_off