Wait for trigger not working in scripts/automations

Quote the closed string. “closed”

If i do, HA changes is back to unquoted after save.

I looked in my code for an example. Here’s what I’ve used that does work.

          - wait_template: "{{ is_state(entity_id,'on') }}"
            timeout:
              seconds: "{{ timeout_seconds * repeat.index }}"
            continue_on_timeout: true

Test your cover state template in developer tools / templates.

i did! works just fine…returns True/False… all the time. only wait_for_trigger is not working. Maybe i should add that i use wait_for_trigger in a lot of automations with other integrations than zwave. they all work just as documented and expected.

but let me try your approach because i used platform template in wait_for_trigger

ok. this is strange.
wait_template is working:

alias: testcover
sequence:
  - service: cover.close_cover
    metadata: {}
    data: {}
    target:
      entity_id: cover.ez_raff01
  - wait_template: "{{ is_state('cover.ez_raff01','closed') }}"
    continue_on_timeout: false
    timeout: "20"
  - service: notify.signal_tom
    metadata: {}
    data:
      message: action after trigger
mode: single

So, this means wait_for_trigger is not working but wait_template is working.

The questions is why is wait_for_trigger not working?

Two possibilities.

First, wait for trigger requires that the trigger happens. So if it is already closed before that the script gets to the trigger it will not trigger. Because zwave service calls do seem to wait for the command to complete in on the zwave network. It would not be surprising for the state to already be updated in HA.

You could test this by adding a call to

                - service: system_log.write
                    data:
                      level: info
                      message: "turn_on {{states('cover.my_cover')}} {{now().strftime('%H:%M:%S.%f')[:-3]}}"
                      logger: service

And see what’s in the log. You may need to make it a warning to show up.

The template, on the other hand, evaluates when it executes, and then will wait if it’s not true for the timeout.

Second, a weird issue with “closed” not be quoted. Likely not the issue though.

Nevertheless, it’s hard to think of a good reason for using device ids.

Rather than using wait for trigger, have you considered two or more separate automations? Easier to write and easier to maintain.

The issue is probably that it’s already closed.
I find it really strange but HA needs it to switch to closed while it’s waiting, it can already be closed.

The workaround is to use a if else.

If closed 
   Do something, preferably a script
else
  wait for trigger
    Do something, preferably a script
end if

Then why are you using wait for trigger if is already closed?

That is the purpose of wait for trigger, wait something to happen.

this is the correct solution. and it’s not strange. quite explainable.

as @PeteRage said, if the state of the cover is closed already by the time it enters this wait, then the trigger won’t happen in the non-template case because that other method is saying “wait for this change to happen”.

@Hellis81 i would recommend against the “if” check around the wait. this may be mostly hypothetical, but the if check closes the window of vulnerability, but theoretically if the cover achieves close between the if check and the else clause execution (remember there’s no promise that these are atomic) then it can still fail. odds of that happening are very small, but why chance it… negative code beauty points :slight_smile: and the template method doesn’t have that vulnerability.

No shit! Aren’t you clever.
Well what if the entity is a device tracker that glitches every now and then and you want to wait for a phone to disconnect from the cars Bluetooth when they are in the home zone.
The device tracker says you are at work even though you are home, the Bluetooth disconnects then the device tracker updates.

Oh? That failed?? Gosh…

In Node red the wait for trigger looks at the current state also which is in my opinion the way it should work.
The wait for trigger in HA makes it complicated for no good reason.

Alright. Thank you so much for your help and the enlightening discussion guys.

It is exactly as @PeteRage pointed out. Right after the service call cover.close_cover the state of the cover changes to closed even though the cover is not really closed yet. If the cover is already very nearly closed before this goes mostly unnoticed. If the cover is mostly open though you can clearly see that right after the service call it changes to closed and just a few seconds later back to open until it is really closed.
I think this is called opportunistic in HA?!

This is the point the for: directive from wait_for_trigger comes in handy. Is there any way to make some sort of for in wait_template/jinja2?

BR
Tom

I think the word you’re looking for is optimistic

2 Likes

Right! Not editing, to expose my stupidity. :sweat_smile:

1 Like

Just blame it on autocorrect :wink:

In a more pedantic implementation there would be a closing state before a closed state for this exact purpose.

but before you throw in the towel, one thing you might try is to go to full open then to full close( maximize the amount of time closing) then look in the Dev tools states to see if there are any intermediary states you can key off of while it is traveling…

That state should be coming from zwave only. Now I would not be surprised if the device sends a closed right after the command. Then sends a closing. I’ve seen similar behavior with a fan switch which in the early days of zwavejs was causing issues, but they sorted it out. Turn on debug logging for zwavejsui, run the test and we should be able to see the sequence.

If you want to force a value read, use zwave_js.refresh_value. This call does not block until the refresh, so a delay of 200ms after may be neccesary. But this may give you a more accurate view of the value before going into the wait template.

I’m assuming the whole point of the automation is to get notified when the cover fails to close as instructed?

thank you. yes i already figured that. it never gets any other state than open or closed. even attributes like current_position are changed immediately after a service call and then adjusted as the cover travels.

1 Like

Thanks i will give that a shot. In the meantime i found a way (some ppl recommended this here in the forum) that works as expected by using a wait_for_trigger like this:

alias: testcover
sequence:
  - service: cover.close_cover
    metadata: {}
    data: {}
    target:
      entity_id: cover.ez_raff01
  - wait_for_trigger:
      - platform: device
        device_id: d75cba3cd07d400f5e12996a40a3e728
        domain: zwave_js
        type: zwave_js.value_updated.value
        property: currentValue
        command_class: 38
        to: "0"
    continue_on_timeout: false
    timeout:
      hours: 0
      minutes: 2
      seconds: 0
      milliseconds: 0
  - service: notify.signal_tom
    metadata: {}
    data:
      message: action after trigger
mode: single

This works exactly as it should in any situation. But (big BUT) it uses the device platform which for various reasons is not what i want/should do (as pointed out further above). i am unsure how to translate (if even possible) this to the state or any other platform. But i am not giving up yet.

Yeah maybe i should have said from the beginning what i am aiming for. So, this script is actually just for testing (hence the alias). What i am trying to achieve is to move a Cover to a certain position (e.g. close it) and then tilt it by using cover.set_cover_tilt_position.

BR
Tom

Maybe more like this…as the docs state:

alias: testcover
sequence:
  - service: cover.close_cover
    metadata: {}
    data: {}
    target:
      entity_id: cover.ez_raff01
  - wait_for_trigger:
      - platform: zwave_js.value_updated
        entity_id: cover.ez_raff01
        property: currentValue
        command_class: 38
        to: "0"
    continue_on_timeout: false
    timeout:
      hours: 0
      minutes: 2
      seconds: 0
      milliseconds: 0
  - service: notify.signal_tom
    metadata: {}
    data:
      message: action after trigger
  - service: cover.set_cover_tilt_position
    metadata: {}
    data:
      tilt_position: 49
    target:
      entity_id: cover.ez_raff01
mode: single

This does exactly what i am after without using a device_id

3 Likes