How does Automation Wait for trigger works?

I want the following to happened in my Automation. When the automation has been triggered (time), I want the automation action only to run when a binary sensor is “off”. If its “on” the the action should wait to the binary sensor is “off”.

action:
  - wait_for_trigger:
      platform: state
      entity_id: binary_sensor.window5_open
      to: 'off'
  - choose:

With this code the automation stops at the wait_for_trigger when the binary_sensor is “off”.
If I understand correctly the action should run without waiting since the binary sensor is “off”. If the binary_sensor would be “on” the action should wait until its “off”?

That is because it does not change to off. Triggers only happen when state changes. If you do not want to wait when it is already off, place it under an if.

1 Like

Aha, got it.
wait_template: "{{ is_state('binary_sensor.window5_open', 'off') ' }}"

This action evaluates the template, and if true, the script will continue. If not, then it will wait until it is true.

  - if:
      - condition: not
        conditions:
          - condition: state
            entity_id: binary_sensor.window5_open
            state: 'off'
    then:
      - wait_for_trigger:
          - platform: state
            entity_id: binary_sensor.window5_open
            to: 'off'

4 Likes

I personally do not use wait_for or delay unless I know it will be s short wait. Otherwise I use a separate automation with a normal trigger. The reason being wait is aborted if HA restarts or automations are reloaded.

4 Likes

Exactly. Personally, i’d add a trigger to the automation

trigger:
  - platform: state
    entity_id: binary_sensor.upstairs_motion
    from: 'off'
    to: 'on'
    id: nowoff
  - platform: state
    entity_id: binary_sensor.other
    from: 'off'
    to: 'on'
    id: regular
action:
  - if:
      - condition: trigger
        id: regular
    then:
      - asfsfsaasfasfsadfa
  - if:
      - condition: trigger
        id: nowoff
    then:
      - sdfasfasfasfasdfas

Or you can put these in separate automations. The caveat with the same automation is you’d need to set the automation mode to either queued or parallel depending on the logic.

1 Like

You beat me to the punch with a combination. However, your example does not check for both conditions to be true, so it won’t do as asked. I had this example ready for how I would normally do this:

alias: Close curtain in evening if/when window closed
description: ''
mode: single
trigger:
  - platform: time
    at: '20:00:00'
  - platform: state
    entity_id: binary_sensor.openclose_bedroom
    to: 'off'
condition:
  - condition: time
    after: '19:59:59'
  - condition: state
    entity_id: binary_sensor.openclose_bedroom
    state: 'off'
action:
  - service: cover.close_cover
    data: {}
    target:
      entity_id: cover.cover_bedroom

Can I tag onto this, this seems to be the closest post to what I’m trying to accomplish.

So I have a motion control for my bathroom light. I have a separate motion sensor for the main room, and another motion sensor in the shower. Normally, the bathroom sensor senses motion, I wait for the trigger for motion to stop and the bathroom light turns off. What I want it to do is to also wait for the motion in the shower to stop as well. But, the kicker is that I want it to be a perpetual wait, not just a one time check. In other words, if the shower is detecting motion when the bathroom stops detecting motion, it will wait UNTIL the shower stops detecting motion and then still turn off the bathroom light. Rather than what seems to be happening which is when the bathroom stops detecting motion, it checks if the shower is detecting motion, and if it is, it makes the decision to not turn off the bathroom light and that’s it.

Here’s the yaml:

alias: Upstairs Bathroom Sink Light Motion (Night)
description: ""
trigger:
  - type: motion
    platform: device
    device_id: 40d7e7188614674e7956b25eda87bcc1
    entity_id: binary_sensor.upstairs_bathroom_motion_sensor_motion
    domain: binary_sensor
condition:
  - condition: state
    entity_id: input_text.mode_helper
    state: Night
action:
  - service: light.turn_on
    data:
      kelvin: 3500
      brightness_pct: 10
    target:
      entity_id: light.upstairs_bathroom_ceiling_light
  - wait_for_trigger:
      - type: no_motion
        platform: device
        device_id: 40d7e7188614674e7956b25eda87bcc1
        entity_id: binary_sensor.upstairs_bathroom_motion_sensor_motion
        domain: binary_sensor
        for:
          hours: 0
          minutes: 2
          seconds: 0
    timeout: "60:00"
    continue_on_timeout: true
  - condition: state
    entity_id: binary_sensor.upstairs_shower_sensor_motion
    state: "off"
  - type: turn_off
    device_id: 24e895b9d6b59c6dfbbe1e46f0760791
    entity_id: switch.upstairs_bathroom_sink_light
    domain: switch
  - type: turn_off
    device_id: 563d0221e4f92116c62721f80c6b4303
    entity_id: light.upstairs_bathroom_ceiling_light
    domain: light
mode: single

I would not use a wait for trigger in this case for two reasons:

  1. It does not survive a restart or automations reload, so I never used it, maybe some day for very short waits.
  2. It is much easier to implement with an extra automation, triggered by both motion sensors, and with two conditions that both motion sensors must be off. I’d probably also put in a for: x seconds clause in both the triggers and the conditions, just to make sure light does not flicker when moving from one to the other.

Edwin, is there a way to schedule (new) automations, that will survive a reload (or power cut, or whatever)? As you point out, automations that wait do not survive restarts.

Something akin to anacron, that ensures that eventually something that turned On reliably gets turned Off.

The use case is long delays after variable triggers, like water/heating/lights that you don’t want left on by accident.

Any best practices for such long delays that have variable starts?

(Note that even fixed time triggers can be missed if HA was reloading at that moment.)

You can use timer helpers that fire an event and that will survive a reboot (there’s an option in the timer helper) and fire an event when the timer is done. But most of the time a timer isn’t needed, as there often is an event to trigger on. In the above example a wait_for_trigger can be replaced by a separate automation and a normal trigger. That trigger can also be a time. Also, triggers have a delay that makes timers unneeded in most cases. It all depends on what you need in a specific situation.

You could also use a time helper. But it may be that you also need a startup event to check if something needs turning off. The event could have passed when Home Assistant was down. But I rarely need that kind of certainty.

This is an extract of my automation:

action:

[...]

        # Per sicurezza, forzo su "off" il pressostato
        - service: switch.turn_off
          data:
            entity_id: switch.lastricosolare_pressostatorabboccovasche
        - service: switch.turn_on
          data:
            entity_id:
              - switch.lastricosolare_generaleacqua
              - switch.lastricosolare_rabboccovasche
        - wait_for_trigger:
            - platform: state
              entity_id: switch.lastricosolare_pressostatorabboccovasche
              from: "off"
              to: "on"
              for: "00:00:30"
          timeout: "00:15:00"

let’s see it together:

        - service: switch.turn_off
          data:
            entity_id: switch.lastricosolare_pressostatorabboccovasche

I force off the switch of our interest…

        - service: switch.turn_on
          data:
            entity_id:
              - switch.lastricosolare_generaleacqua
              - switch.lastricosolare_rabboccovasche

Open the water…

        - wait_for_trigger:
            - platform: state
              entity_id: switch.lastricosolare_pressostatorabboccovasche
              from: "off"
              to: "on"
              for: "00:00:30"
          timeout: "00:15:00"

Now I have to wait for the tanks to fill (and then the switch to go from “off” to “on” for 30 seconds) or at most 15 minutes
But this doesn’t happen since the extract of the automation tracks shows:

      "action/6/then/2": [
        {
          "path": "action/6/then/2",
          "timestamp": "2023-06-24T04:58:57.002319+00:00",
          "result": {
            "params": {
              "domain": "switch",
              "service": "turn_on",
              "service_data": {
                "entity_id": [
                  "switch.lastricosolare_generaleacqua",
                  "switch.lastricosolare_rabboccovasche"
                ]
              },
              "target": {}
            },
            "running_script": false,
            "limit": 10
          }
        }
      ],
      "action/6/then/3": [
        {
          "path": "action/6/then/3",
          "timestamp": "2023-06-24T04:58:57.112794+00:00",
          "result": {
            "wait": {
              "remaining": 833.8613884790102,
              "trigger": {
                "id": "0",
                "idx": "0",
                "alias": null,
                "platform": "state",
                "entity_id": "switch.lastricosolare_pressostatorabboccovasche",
                "from_state": {
                  "entity_id": "switch.lastricosolare_pressostatorabboccovasche",
                  "state": "off",
                  "attributes": {
                    "raw_state": false,
                    "friendly_name": "LastricoSolare_PressostatoRabboccoVasche"
                  },
                  "last_changed": "2023-06-24T04:59:31.461254+00:00",
                  "last_updated": "2023-06-24T04:59:31.461254+00:00",
                  "context": {
                    "id": "01H3NWB285RQVV0EYBMB3CGNEM",
                    "parent_id": null,
                    "user_id": null
                  }
                },
                "to_state": {
                  "entity_id": "switch.lastricosolare_pressostatorabboccovasche",
                  "state": "on",
                  "attributes": {
                    "raw_state": true,
                    "friendly_name": "LastricoSolare_PressostatoRabboccoVasche"
                  },
                  "last_changed": "2023-06-24T04:59:33.250633+00:00",
                  "last_updated": "2023-06-24T04:59:33.250633+00:00",
                  "context": {
                    "id": "01H3NWB402T9Z4H74ZQ0M654K8",
                    "parent_id": null,
                    "user_id": null
                  }
                },
                "for": {
                  "__type": "<class 'datetime.timedelta'>",
                  "total_seconds": 30
                },
                "attribute": null,
                "description": "state of switch.lastricosolare_pressostatorabboccovasche"
              }
            }
          }
        }
      ],
      "action/6/then/4": [
        {
          "path": "action/6/then/4",
          "timestamp": "2023-06-24T05:00:03.255831+00:00",
          "changed_variables": {
            "wait": {
              "remaining": 833.8613884790102,
              "trigger": {
                "id": "0",
                "idx": "0",
                "alias": null,
                "platform": "state",
                "entity_id": "switch.lastricosolare_pressostatorabboccovasche",
                "from_state": {
                  "entity_id": "switch.lastricosolare_pressostatorabboccovasche",
                  "state": "off",
                  "attributes": {
                    "raw_state": false,
                    "friendly_name": "LastricoSolare_PressostatoRabboccoVasche"
                  },
                  "last_changed": "2023-06-24T04:59:31.461254+00:00",
                  "last_updated": "2023-06-24T04:59:31.461254+00:00",
                  "context": {
                    "id": "01H3NWB285RQVV0EYBMB3CGNEM",
                    "parent_id": null,
                    "user_id": null
                  }
                },
                "to_state": {
                  "entity_id": "switch.lastricosolare_pressostatorabboccovasche",
                  "state": "on",
                  "attributes": {
                    "raw_state": true,
                    "friendly_name": "LastricoSolare_PressostatoRabboccoVasche"
                  },
                  "last_changed": "2023-06-24T04:59:33.250633+00:00",
                  "last_updated": "2023-06-24T04:59:33.250633+00:00",
                  "context": {
                    "id": "01H3NWB402T9Z4H74ZQ0M654K8",
                    "parent_id": null,
                    "user_id": null
                  }
                },
                "for": {
                  "__type": "<class 'datetime.timedelta'>",
                  "total_seconds": 30
                },
                "attribute": null,
                "description": "state of switch.lastricosolare_pressostatorabboccovasche"
              }
            }
          },

Always exits as timeouted after a few seconds (not 15 minutes).
Where am I wrong?

I’ve tried your automation with two input booleans (start_automation and lastricosolare_pressostatorabboccovasche) and it works perfectly.

alias: Automation test
description: ""
trigger:
  - platform: state
    entity_id:
      - input_boolean.start_automation
    from: "off"
    to: "on"
condition: []
action:
  - wait_for_trigger:
      - platform: state
        entity_id:
          - input_boolean.lastricosolare_pressostatorabboccovasche
        from: "off"
        to: "on"
        for: "00:00:30"
    timeout: "00:15:00"
  - service: input_boolean.turn_off
    data: {}
    target:
      entity_id: input_boolean.start_automation
mode: single

Thanks for your attention.

can I have a - wait_for_trigger: or - wait_for_trigger: ?

Hello,

i have the same question as [Faecon].
Would be very usefull for automations that are waiting on active answer or decision.
Maybe this could be a option to at this for wait for trigger?

Regards

They told me that a 2 wait for triggers al always or

For multiple triggers of which only one is enough you need to place multiple items under the wait_for_trigger entry. Multiple wait_for_triggers are of course consecutive waits. I don’t think you can put wait_for_trigger within an or condition (or you are not meant to) - results are likely unpredictable.