Repeatable bug in wait_template

I was trying to see it its the fact you use the template in the wait_template or the template per se causing the issue.

a delay would need a timing though so its not simply replacing the same template to check. You could try playing a media file on a media_player and then use my template to see if that finishes correctly.

About intermediary entity: that’s indeed what I do also. the input sets the active media_player, which then is populating the sensor, which state is again used in the template…

I use another option in my intercom scripts, using subscripts, which holds the template as a condition:

main script:

  intercom_message:
    alias: 'Intercom message'
    sequence:
      - condition: template
        value_template: >
          {{ is_state('input_boolean.announce_intercom', 'on') }}
      - service: script.radio_paused_for_message
      - service: script.wakeup_radio_paused_for_message
      - service: media_player.volume_set
        data_template:
          entity_id: >
            {{states('sensor.intercom')}}
          volume_level: >
            {{ states('input_number.intercom_volume')|float }}
#            # {{ states('sensor.intercom_volume')|float  }}
      - service: tts.google_say
        data_template:
          language: >
            {{states('input_select.intercom_language')|lower}}
          entity_id: >
            {{states('sensor.intercom')}}
          message: >
            {{message}}
      - service: script.resume_radio_paused_for_message
      - service: script.resume_wakeup_radio_paused_for_message

and 1 of the subscripts:

  radio_paused_for_message:
    alias: 'Radio paused for message'
    sequence:
      - condition: template
        value_template: >
          {{states('sensor.intercom') == states('sensor.media_player') }}
      - condition: template
        value_template: >
          {{states(states('sensor.media_player')) == 'playing'}}
      - service: input_boolean.turn_on
        entity_id: input_boolean.radio_paused

maybe that’s an option for you?

Ok…
For background I am writing a new (hopefully) more flexible and robust notification system.

This automation is one part of it so may not make too much sense in isolation, but here it is.
The whole thing works but is is currently showing the use of the intermediate sensor in the wait_template

  #============================================
  #=== Notification say published announcement
  #============================================
  - alias: Notification say published announcement
    trigger: 
      - platform: mqtt
        topic: notifications/announcement

    condition:
      #=== Only continue in normal hours or priority announcement
      - condition: or
        conditions:
          - condition: time
            after: '07:00:00'
            before: '23:30:00'

          - condition: state
            entity_id: input_boolean.announcement_priority
            state: 'on'

    action:
      #=== Optional pause before speaking
      - delay: >
          00:00:{{ '{:02}'.format(states('input_number.announcement_pause') | default(0) | int) }}

      #=== Make the announcement
      - service_template: >
          tts.{{ states('input_select.announcement_voice') }}_say
        data_template:
          entity_id: >    
            {{ states('input_text.sonos_group_master') }}
          message: >
            {{ trigger.payload }}

      #=== Wait until announcement starts playing
      - wait_template: >
          {% if states('sensor.sonos_master_state') == 'playing' %}
            True
          {% else %}
            False
          {% endif %}

      #=== Now wait until it has finished playing
      - wait_template: >
          {% if states('sensor.sonos_master_state') == 'paused' %}
            True
          {% else %}
            False
          {% endif %}

      #=== If Last announcement then continue to clean up
      - condition: template
        value_template: >
          {{ is_state('input_boolean.announcement_last', 'on') }}

      #=== Restore Sonos
      - service: sonos.restore
        data_template:
          entity_id: >
            {% for boolean in states.input_boolean if 'announcement_on_' in boolean.entity_id and is_state(boolean.entity_id, 'on') -%}
              media_player.{{ boolean.entity_id.split('.')[1].split('_media_player')[0] }}{%- if not loop.last %}, {% endif %}
            {%- endfor %}

      #=== Remove this announcements identity
      - service: input_text.set_value
        data:
          entity_id: input_text.announcement_id_in_progress
          value: None

      #=== Turn off announcement in progress
      - service: input_boolean.turn_off
        entity_id: input_boolean.announcement_in_progress


Is that what contains the entity_id?

No the entity_id is held in input_text.sonos_group_master

Ok, so when does that get populated in relation to this automation?

Just did a few tests and I’m getting the same results as you.

It works in an automation but not when used as part of a wait_template in a script.

This works when used in an automation’s action:

  action:
  - service: system_log.write
    data_template:
      message: Result is {{ is_state(states('input_text.text1'), 'on') }}
      level: warning

The input_text points to an input_boolean. If that input_boolean is on the syslog message is “Result is True”.

In contrast, this script did not work:

  test_1:
    alias: 'test wait_template'
    sequence:
      - wait_template: "{{ is_state(states('input_text.text1'), 'on') }}"
      - service: light.toggle
        entity_id: light.family

It didn’t care if the input_boolean was on or off and simply waited forever. Attempts to run the script again resulted in the expected error message that the script was already running.

In a previous script.
And yes it is populated. It is never cleared out, just updated.

It’s entirely possible that the wait template creates a listener based on input_text.text1 only and not the entity_id contained in states(‘input_text.text1’). I’d be willing to bet that this is the case based on how triggers and sensor templates work.

Seems reasonable. At least enough to not call it a bug.
I’m still going with deficiency though :wink:

Easily solved using an extra sensor. Not very elegant though.

If my hypothesis is true, it would seem like ‘wait_templates’ could use an enhancement. I.E. Add the entity_id property to them. But yes, the work around would be a template sensor.

EDIT: I bet you could get around this by creating a list of your entities inside the template.

{% set list_that_isnt_used = 'sensor.x', 'sensor.y', 'sensor.z' %}

I’ll buy that. The template is definitely being handed differently within the wait_template compared to within an automation’s action.

For shits and giggles, try this:

      - wait_template: >
          {% set bs = 'media_player.pool_room' %}
          {% set master = states('input_text.sonos_group_master') %}
          {{ is_state(master, 'playing') }}

you could hold that for now please. What ever the reason might be, and @petro is probably right, we should be allowed to expect the same behavior for the same template in the HA system everywhere.

If the template syntax we use successfully in an automation/script as condition or delay doesn’t work when used as a wait_template, this is at least unexpected, undesirable at that, and thus at least a bug in expectation…

as another example this syntax proves to be working just fine:

  - alias: 'Alarm clock off'
    id: 'Alarm clock off'
    initial_state: 'on'
    trigger:
      platform: state
      entity_id:
        - input_boolean.snooze
        - input_boolean.alarmclock_wd_enabled
        - input_boolean.alarmclock_we_enabled
        - input_boolean.sleep_radio
        - input_boolean.wakeup_radio
      to: 'off'
    condition:
      condition: template
      value_template: >
        {{states(states('sensor.sleep_radio')) == 'playing' or
          states(states('sensor.wakeup_radio')) == 'playing'}}
    action:
      - service: media_player.turn_off
        data_template:
          entity_id: >
            {% if states(states('sensor.sleep_radio')) == 'playing' %} {{states('sensor.sleep_radio')}}
            {% else %} {{states('sensor.wakeup_radio')}}
            {% endif %}
      - service: timer.cancel
        data_template:
          entity_id: >
            timer.{% if states(states('sensor.sleep_radio')) == 'playing' %}decrease_volume_delay
            {% else %} {{states('sensor.wakeup_radio')}}increase_volume_delay
            {% endif %}
      - service: automation.turn_off
        entity_id:
          - automation.increase_volume_loop
          - automation.decrease_volume_loop

I will, and I’ll let you know, but I’ve been called away so it won’t be for a few hours… or tomorrow.

Thanks everyone.

I got back for a few minutes.
It doesn’t seem to work I’m afraid.

Is the input_text set equal to the entity_id that was used inside the template?

  - wait_template: >
      {% set bs = 'media_player.pool_room' %}
      {% set master = states('input_text.sonos_group_master') %}
      {{ is_state(master, 'playing') }}

input_text.sonos_group_master was set to the string, ‘media_player.pool_room’

1 Like

Well, it looks like you’ll need to make the template sensor then.

Yeah, I’ve done that.
Thanks anyway.

Yes, I’m back again and it is even worse than I first thought.

It looks to me like not only does the wait_template not work but you can’t have a sensor like this:

      sonos_master_state:
        friendly_name: Sonos Master state
        value_template: >
          {{ states(states('input_text.sonos_group_master')) }}

My input_text contains the full entity id of a media_player:

And I can watch it go to a state of playing while the sensor stays at paused.
I’m surprised it ever got set to anything.

Is it possible for someone to check this out please because if I am right this is starting to look like quiet a serious issue?

Which makes me thing I am overlooking something…

We should be able to control things based on the state of an entity even if we don’t know what entity it is until runtime.