Timers and wait_template. What is going on here? Bug or user error?

Am I going mad!?
I have spent ages trying to find out what was wrong with my scripts…
I still don’t know why but I might have found a solution.

Please! Put me out of my misery by explaining or confirming there is a bug.


Why does this NOT work:

      - wait_template: >
          {{ is_state('timer.irrigation_test_' ~ zone ~ '_timer', 'idle') }}

But this DOES:

      - wait_template: >
          {% set entity = 'timer.irrigation_test_' ~ zone ~ '_timer' %}
          {{ is_state(entity, 'idle') }}

And in case I haven’t overlooked anything stupid and you’d like to prove it for yourself, here is an entire package that should replicate it.

notify:
  - platform: file
    name: irrigation_test
    filename: my-log-irrigation_test.log

timer:
  irrigation_test_zone1_timer:

input_number:
  irrigation_test_cycle1_zone1_duration:
    min: 0
    max: 60

input_boolean:
  irrigation_test_cycle1_zone1_skip:

script:
  irrigation_test:
    sequence:
      - service: script.irrigation_test_irrigate_a_zone
        data_template:
          cycle: >
            cycle1
          zone: >
            zone1

  irrigation_test_irrigate_a_zone:
    sequence:
      - service: script.irrigation_test_start_zone_timer
        data_template:
          cycle: "{{ cycle }}"
          zone: "{{ zone }}"

      - service: notify.irrigation_test
        data_template:
          message: END script.irrigation_test_start_zone_timer

  irrigation_test_start_zone_timer:
    sequence:
      - service: timer.start
        data_template:
          entity_id: >
            timer.irrigation_test_{{ zone }}_timer
          duration: >
            {% set minutes = states('input_number.irrigation_test_' ~ cycle ~ '_' ~ zone ~ '_duration') | float %}
            {{ minutes | int }}

      - wait_template: >
          #=== This doesn't work
          # {{ is_state('timer.irrigation_test_' ~ zone ~ '_timer', 'idle') }}

          #=== This does work
          {% set entity = 'timer.irrigation_test_' ~ zone ~ '_timer' %}
          {{ is_state(entity, 'idle') }}

      - service: notify.irrigation_test
        data_template:
          message: After Wait


LOG Output when it DOES work

Home Assistant notifications (Log started: 2020-02-22T09:15:04.370936+00:00)
--------------------------------------------------------------------------------
END script.irrigation_test_start_zone_timer
After Wait

LOG Output when it DOESN’T work

Home Assistant notifications (Log started: 2020-02-22T09:19:29.825874+00:00)
--------------------------------------------------------------------------------
END script.irrigation_test_start_zone_timer

And the script stays on with last_action: wait_template

When you say “it doesn’t work” you mean the script irrigation_test_irrigate_a_zone is still running?
You need to read how wait_template works - it’ll wait forever unless you specify a timeout.
Looks like your second condition does not return True.

Afaik the classic approach is to start a timer and have another automation that triggers on finished event from this timer.
Your code shows that you start a timer and wait for it to become idle. It’s ok but…

Perhaps it’s something to do with the way HA detects entities to watch in templates - read this.

Yes.

Yes I’ve done that.

Bu that is exactly the point, it does.

Except that I can’t do that as I am passing data between scripts so that I don’t have to duplicate everything eight times (24 if you count the fact that I have three cycles). And also my way allows for a variable number of cycles / zones with the minimum of code changes.

I’m not sure what the ‘but’ is :wink:

however, considering this

your wait_template is still waiting meaning its value is not True. Or am I wrong?

Well it would seem you are right but if I do the same test in the template editor it evaluates to True and what is more the timer in the States page is idle.

I bet the issue is in your design as both template options are valid and evaluate to the same values in Template editor.
Perhaps you need to re-design your script or something…

Hmmm… maybe, but I think not. Quite simply, one of these works and not the other. No amount of re-designing my script will explain why that is the case!

    sequence:
      - service: timer.start
        data_template:
          entity_id: >
            timer.irrigation_test_{{ zone }}_timer
          duration: >
            {% set minutes = states('input_number.irrigation_test_' ~ cycle ~ '_' ~ zone ~ '_duration') | float %}
            {{ minutes | int }}

      - wait_template: >
          #=== This doesn't work
          # {{ is_state('timer.irrigation_test_' ~ zone ~ '_timer', 'idle') }}

          #=== This does work
          {% set entity = 'timer.irrigation_test_' ~ zone ~ '_timer' %}
          {{ is_state(entity, 'idle') }}

If you use packages you can copy and paste it all into one file and test it for yourself.

Well. Here’s the proof :wink:

:slight_smile:

Yes, I haven’t read it all yet (no time now) but I still don’t understand why one form works and not the other.

As I said in the other post, thank you.

to be honest I’m surprised either wait template works because HA can’t gather an entity_id from your template. All templates are the same, they need something to ‘trigger’ the template updating. Without the parser being able to find your entity_id, nothing will cause it to trigger. Same issue you’ve heard over and over again with template sensors.

I haven’t completely verified, but by reviewing the code, it does appear that in this scenario (i.e., a wait_template as opposed to a template sensor), if it can’t find any entity IDs, it will re-evaluate whenever any state change in the system occurs.

2 Likes

Unless I misunderstand you, you are misunderstanding me :upside_down_face:

Both scenarios are a wait_template. Neither are a sensor.

#=== This doesn't work
- wait_template: >
    {{ is_state('timer.irrigation_test_' ~ zone ~ '_timer', 'idle') }}

#=== This does work
- wait_template: >
    {% set entity = 'timer.irrigation_test_' ~ zone ~ '_timer' %}
    {{ is_state(entity, 'idle') }}

My reply was in reference to the statement that petro made. I really have no idea why you seem to get a different behavior between the two versions of the wait_template. Unless it is some sort of race condition, where the first version of the template runs faster than the second version.

Wow, that’s good to know