Automation issue: why isn't this wait_template waiting

Automations are triggered by events. Something happening is an event. Something not happening is the absence of an event. How can something be triggered by something not happening???

Not sure I understand why you “fear” a valid, reasonable solution. It is creating the event you’re looking for. I.e., when the timer expires, then the cover hasn’t moved in the specified time period, and that’s the “event” you want.

I don’t use covers, and I’m not that familiar with how they generally work, but yes, I’d agree that this is something the cover entity should do – i.e., indicating it’s moving or not. This isn’t in the state? I.e., open, closed, opening, closing, …???

Regarding you last solution, why would this not work (i.e., without the need for the automations/scripts):

binary_sensor:
  - platform: template
    sensors:
      raamverduistering_stookhok_moving:
        friendly_name: Stookhok moving
        entity_id:
          - sensor.time
          - cover.raamverduistering_stookhok
        value_template: >
          {{(now() - states.cover.raamverduistering_stookhok.last_updated)
             .total_seconds() < 2}}
        device_class: moving

Using Timer as mention, can you use something like this:

timer:
  raamverduistering:
    duration: '00:00:05'
    icon: mdi:timer-sand

automation:
  - alias: Cover stookhok is moving
    trigger:
      platform: state
      entity_id: cover.raamverduistering_stookhok
    action:
      - service: timer.cancel
        entity_id: timer.raamverduistering
      - service: timer.start
        entity_id: timer.raamverduistering

  - alias: Cover stookhok final update
    trigger:
      - platform: event
        event_type: timer.finished
        event_data:
          entity_id: timer.raamverduistering
    action:
      - service: notify.system
        data_template:
          title: Cover is no longer moving
          message: current position is {{trigger.to_state.attributes.current_position|int}} 

It should be similar to the “waiting” logic you have used. Perhaps change the timer to 10sek (or something) if it’s not working?

Edit: I didn’t look at the last automation…

Canceling the timer is unnecessary. If it is started while running it will effectively start over.

Oh. I Didn’t know that.
I posted this code as I not long ago did something similar, and this was the code I used (I of course adapted it to this example).
I also see that my code doesn’t really add anything compared to your code further up the thread. But hey, nobody complains about to many examples :slightly_smiling_face:

1 Like

of course it can’t. No, I was looking for the end of the triggering event. But that will probably be clear…

Well, fear might be a bit heavy. Surprised would be better? that we have to create the even manually, use a timer with a hardcoded length, instead of the integration doing that in core. We cant use a template like in the media_play.play media where we use the length of the media file. Here we have to estimate. Since the automation triggers each second, I figured 2 seconds would be enough for the ‘off’ event to be created. But that was just a bit sharp. restarting for 3 now… :wink:

It would be really nice to have an event_stopped event in HA core. We have many events that are binary, these are clear. This one isn’t, (clear nor digital) but would warrant its own

No, its state is always open or closed, hence my FR to change that, as apparently other cover integrations do. Or at least have an attribute.

I dont know, I ave been struggling with this all day, in many variants. it simply doesnt track the value_template, other than on sensor.time. Which can take up to a minute. Which of course is unacceptable for a frontend representation.

the input_boolean is a nice technique indeed. Just too bad it isn’t using the new Script logic :wink: was really happy to use the script and mode: parallel as I had posted it…

I don’t get what you want the “core” to do.

An “event stopped” event? What is that? What does that even mean? And what do you mean by “events that are binary”? An event is something that ocurrs in an instant, it’s not off & on.

I think you mean you want “something” to monitor for a particular event, and after it sees it, it waits until it doesn’t see it for at least X seconds, and when it doesn’t it does something (fire another event, trigger an automation, etc.) And then it starts monitoring for the event again, …

FWIW, you could probably do something like this (using the new automation capabilities that are hopefully coming soon):

automation:
- trigger:
  - platform: state
    entity_id: cover.raamverduistering_stookhok
  mode: restart
  action:
  - delay: 3
  - service: ...

Every time cover.raamverduistering_stookhok changes state (or an attribute changes) the action will start running, or restart running. So the service step would only be executed if the entity changed at least once, and then didn’t change for at least 3 seconds.

Is that what you’re wanting?

And since the new modes will only be available in scripts first, then you could do this instead:

automation:
- trigger:
  - platform: state
    entity_id: cover.raamverduistering_stookhok
  action:
  - service: script.my_script
script:
  my_script:
    mode: restart
    sequence:
    - delay: 3
    - service: ...

Of course you can use the timer.start service and use a template to specify the duration. It doesn’t have to be hard coded.

for starters, this works now, perfection. So a big thanks is in order! thanks.

automation:
  - alias: Cover stookhok is moving
    trigger:
      platform: state
      entity_id: cover.raamverduistering_stookhok
    action:
#      service: script.trigger
      - service: input_boolean.turn_on
        entity_id: input_boolean.raamverduistering_stookhok_moving
      - service: timer.start
        entity_id: timer.raamverduistering_stookhok_moving

  - alias: Cover stookhok no longer moving
    trigger:
      - platform: event
        event_type: timer.finished
        event_data:
          entity_id: timer.raamverduistering_stookhok_moving
    condition: []
    action:
      - service: input_boolean.turn_off
        entity_id: input_boolean.raamverduistering_stookhok_moving
      - service: notify.system
        data_template:
          title: Cover is no longer moving
          message: >-
            Cover is
            {%- set position = state_attr('cover.raamverduistering_stookhok','current_position')|int %}
            {%- set phrase = 'positioned at: ' %}
            {%- if is_state('cover.raamverduistering_stookhok','closed')%} Closed
            {%- elif position|int == 100 %} Open
            {%- else %} {{phrase}}{{position}}
            {% endif %}

and, this customization reflects that in the frontend:

homeassistant:
  customize:
    cover.raamverduistering_stookhok:
      templates:
        icon: >
          if (entities['binary_sensor.raamverduistering_stookhok_moving'].state == 'on') return 'mdi:animation';
          if (state == 'open' && attributes.current_position == 100) return 'mdi:window-shutter-open';
          if (state == 'closed') return 'mdi:window-shutter';
          else return 'mdi:window-shutter-alert';
        icon_color: >
          if (entities['binary_sensor.raamverduistering_stookhok_moving'].state == 'on') return 'red';
          if (state == 'open' && attributes.current_position == 100) return 'gold';
          if (state == 'closed') return 'darkblue';
          else return 'green';

not sure this is true, at least not in the way I meant it to. I tried to express the desire to template the time it takes to go from moving to not moving. Might be a chicken an egg issue…

yes, an event stopped. the event would be state_changed_to_moving. and state changed from moving to not moving. or playing, or any other event that takes more time than the instant.

But, maybe this is all caused by the integration not correctly stating the opening/closing.

I’d simply like to trigger as we can do with a light. turn_on/off, and between it is glowing. these event are missing here. I can only trigger on the attribute current_position to be changing…

hmm, I guess yes, will have to try and see if that ends up doing the same :wink: How would the binary_sensor need to be templated with this? because that’s the end goal, have a binary change state, and show the frontend the cover is moving or not.

Again, use an input_boolean, and then layer a binary_sensor on top of it if you want.

automation:
- trigger:
  - platform: state
    entity_id: cover.raamverduistering_stookhok
  action:
  - service: script.my_script
script:
  my_script:
    mode: restart
    sequence:
    - service: input_boolean.turn_on
      entity_id: input_boolean.raamverduistering_stookhok
    - delay: 3
    - service: input_boolean.turn_off
      entity_id: input_boolean.raamverduistering_stookhok
1 Like

Smooth! can confirm this works very nicely indeed (and takes advantage of the (future) new scripting options :wink: )

script:
  cover_stookhok:
    alias: Cover stookhok
    mode: restart
    sequence:
      - service: input_boolean.turn_on
        entity_id: input_boolean.raamverduistering_stookhok_moving
      - delay: 2
      - service: input_boolean.turn_off
        entity_id: input_boolean.raamverduistering_stookhok_moving
      - condition: state
        entity_id: input_boolean.notify_developing
        state: 'on'
      - service: notify.system
        data_template:
          title: Cover is no longer moving
          message: >-
            {{as_timestamp(now())|timestamp_custom('%X')}} - Cover is
            {%- set position = state_attr('cover.raamverduistering_stookhok','current_position')|int %}
            {%- set phrase = 'positioned at: ' %}
            {%- if is_state('cover.raamverduistering_stookhok','closed')%} Closed
            {%- elif position|int == 100 %} Open
            {%- else %} {{phrase}}{{position}}
            {% endif %}

automation:
  - alias: Cover stookhok
    trigger:
      platform: state
      entity_id: cover.raamverduistering_stookhok
    action:
      service: script.cover_stookhok

I’ve changed the solved tick to the last post Phil, as I hope it will help many users finding a correct loop with the mode: restart option.

update

only ‘issue’ I experience with this technique is it gets triggered at startup/restart…while using the timer automations did not do that. hmm

so a little more experimenting seems to allow for determining ‘opening’ and ‘closing’, by adding 1 script.cover_stookhok_position, and adding that in the sequence before the existing one:

script:
  cover_stookhok_position:
    alias: Cover stookhok position
    mode: restart
    sequence:
      - condition: template
        value_template: >
          {{toposition != fromposition}}
      - service: input_boolean.turn_on
        data_template:
          entity_id: >
            input_boolean.{{'cover_stookhok_opening' if toposition > fromposition else 'cover_stookhok_closing'}}
# below not needed because booleans are turned off anyway. and always start from 'off'
#      - service: input_boolean.turn_off
#        data_template:
#          entity_id: >
#            input_boolean.{{'cover_stookhok_opening' if toposition < fromposition else 'cover_stookhok_closing'}}

automation:
  - alias: Cover stookhok
    trigger:
      platform: state
      entity_id: cover.raamverduistering_stookhok
    action:
      - service: script.cover_stookhok_position
        data_template:
          toposition: '{{trigger.to_state.attributes.current_position}}'
          fromposition: '{{trigger.from_state.attributes.current_position}}'
      - service: script.cover_stookhok

this in turn allows me to customize the icon even better, and, instead of the ‘motion’ icon, show ‘archive-arrow-down’ and ‘archive-arrow-up’ :wink:
which is a nice and unforeseen use of these ‘Archive’ icons…

homeassistant:
  customize:
    cover.raamverduistering_stookhok:
      templates:
        icon: >
          if (entities['input_boolean.cover_stookhok_opening'].state == 'on') return 'mdi:archive-arrow-up';
          if (entities['input_boolean.cover_stookhok_closing'].state == 'on') return 'mdi:archive-arrow-down';
          if (state == 'open' && attributes.current_position == 100) return 'mdi:window-shutter-open';
          if (state == 'closed') return 'mdi:window-shutter';
          else return 'mdi:window-shutter-alert';
        icon_color: >
          if (entities['binary_sensor.raamverduistering_stookhok_moving'].state == 'on') return 'red';
          if (state == 'open' && attributes.current_position == 100) return 'gold';
          if (state == 'closed') return 'midnightblue';
          else return 'green';
1 Like

I don’t understand that. Both techniques, as I suggested them, used the same trigger, right:

automation:
- trigger:
  - platform: state
    entity_id: cover.raamverduistering_stookhok

How could the behavior of the trigger change depending on what was done in the action section?

Maybe you need the condition I later suggested:

automation:
- trigger:
  - platform: state
    entity_id: cover.raamverduistering_stookhok
  condition:
  - condition: template
    value_template: >
      {{ trigger.to_state.attributes.current_position !=
         trigger.from_state.attributes.current_position }}

I think you could do the same thing more directly with an input_select.

input_select:
  raamverduistering_stookhok:
    options:
    - stationary
    - opening
    - closing
    initial: stationary
automation:
- trigger:
  - platform: state
    entity_id: cover.raamverduistering_stookhok
  condition:
  - condition: template
    value_template: >
      {{ trigger.to_state.attributes.current_position !=
         trigger.from_state.attributes.current_position }}
  action:
  - service: script.raamverduistering_stookhok
    data_template:
      old: "{{ trigger.from_state.attributes.current_position }}"
      new: "{{ trigger.to_state.attributes.current_position }}"
script:
  raamverduistering_stookhok:
    mode: restart
    sequence:
    - service: input_select.select_option
      entity_id: input_select.raamverduistering_stookhok
      data_template:
        option: "{{ 'opening' if new|float > old|float else 'closing' }}"
    - delay: 2
    - service: input_select.select_option
      entity_id: input_select.raamverduistering_stookhok
      data:
        option: stationary

Then you could do your notifying based on state changes of input_select.raamverduistering_stookhok in a separate automation. And, of course, change your icon customizations based on the one input_select instead of two input_boolean's.

2 Likes

better! this removes the issue I have with both booleans having to be toggled at the same time. very nice!

1 Like

I suppose you could even extend the options to include closed, opened & partially_opened, and at the end of the script, use new|float to decide if the cover was fully closed, fully opened, or somewhere in between.

as a matter of fact, I was already tinkering with that …:wink: My notification does something alike already.

for reference up to the post before the above, I can confirm all issues gone! no incidental double turned on booleans, which are now replaced by the input_select. Ive simply added the notification to the one automation as final step:

  raamverduistering_stookhok:
    mode: restart
    sequence:
    - service: input_select.select_option
      entity_id: input_select.raamverduistering_stookhok
      data_template:
        option: >
          {{'opening' if new|float > old|float else 'closing'}}
    - delay: 2 # might require 3, to be seen in practice
    - service: input_select.select_option
      entity_id: input_select.raamverduistering_stookhok
      data:
        option: stationary
    - condition: state
      entity_id: input_boolean.notify_developing
      state: 'on'
    - service: notify.system
      data_template:
        title: Cover is no longer moving
        message: >-
          {{as_timestamp(now())|timestamp_custom('%X')}} - Cover is
          {%- set position = state_attr('cover.raamverduistering_stookhok','current_position')|int %}
          {%- set phrase = 'positioned at: ' %}
          {%- if is_state('cover.raamverduistering_stookhok','closed')%} Closed
          {%- elif position|int == 100 %} Open
          {%- else %} {{phrase}}{{position}}
          {% endif %}

very nice indeed, so thanks again. And again. Aa.

Do you remember when we found a now() template that DID update in use ?
I think it was something stupid like : -

{{ as_timestamp(now()) | int % 2 == 0 }}

Basically this flip-flops every 2 seconds
I haven’t tried it but maybe if you incorporated something like : -

{% set notused = as_timestamp(now()) | int % 2 == 0 %}

In the template it would ‘maybe’ get looked at every 2 seconds ??? and then update the rest of the template too ???

Not sure if I’d rely on it though as this is completely undocumented

When a template is rendered has more to do with where that template is used than by the template itself. E.g., if it’s used in a condition of an automation, then it is rendered when a trigger fires. But if it’s used in a template trigger, or a template sensor, that’s a different story. It’s that use case that determines when to render the template. E.g., as currently implemented, there would be no way to get that template to render based on time changing if it was used in a template trigger. But if it was used in a template sensor, then one can use the sensor’s entity_id option to force when the template is evaluated.

True

I just didn’t consider that, Sorry !

well here is the final (…) version then, with the extended options in the end phase:

script:
  raamverduistering_stookhok:
    mode: restart
    sequence:
      - service: input_select.select_option
        entity_id: input_select.raamverduistering_stookhok
        data_template:
          option: >
            {{'Opening' if new|float > old|float else 'Closing'}}
      - delay: 2
      - service: input_select.select_option
        entity_id: input_select.raamverduistering_stookhok
        data_template:
          option: >
            {% if new|float == 100 %} Open
            {% elif new|float == 0 %} Closed
            {% else %} Stationary
            {% endif %}
      - condition: state
        entity_id: input_boolean.notify_developing
        state: 'on'
      - service: notify.system
        data_template:
          title: Cover is no longer moving
          message: >-
            {% set state = states('input_select.raamverduistering_stookhok') %}
            {{as_timestamp(now())|timestamp_custom('%X')}} - Cover is
            {%- if is_state('cover.raamverduistering_stookhok','closed')%} Closed
            {%- elif new|int == 100 %} Open
            {%- else %} {{state|lower}} at {{new|int}} %
            {% endif %}

input_boolean hasn’t got an initial anymore, because the new options also include an expansion on stationary, which can be open and closed completely.

input_select:
  raamverduistering_stookhok:
    options:
      - Stationary
      - Opening
      - Closing
      - Open
      - Closed
#    initial: Stationary

because the input_select can be manipulated in the frontend, and here it is only used to store the state the automation sets it to, Ive also created a safer sensor, to show in the frontend:

sensor:
  - platform: template
    sensors:
      cover_stookhok_position:
        friendly_name: Stookhok position
        value_template: >
          {% set position = state_attr('cover.raamverduistering_stookhok','current_position')%}
          {% set state = states('input_select.raamverduistering_stookhok')%}
          {% if state == 'Stationary' %} {{state}} at {{position|int}} %
          {% else %} {{state}}
          {% endif %}

Question, considering the above: there is no backend option to set for an input_select, to not allow manual manipulating somehow?

1 Like