Alexa Media Player timers as a trigger

Tags: #<Tag:0x00007f326aa42f60>

I noticed that the Alexa Media Player custom component provides sensors for the next timer, reminder and alarm on each device in version 2.3.0 (https://github.com/custom-components/alexa_media_player/wiki#notifications-alarmstimersreminders-versions--230) - I’ve been having a play with this to try to get a kind of “global timer” to announce on all the Echoes in my house. The documentation above suggests that the state of the next timer sensor can be used to trigger actions when the time passes, but I’m struggling to figure out the best way to do it.

I’ve found that testing if the next timer is in the past indicates whether the timer is currently sounding, but actually triggering on that as a condition is more difficult. I tried creating a binary template sensor for the timer sounding by comparing with sensor.time, but https://www.home-assistant.io/integrations/template/#working-without-entities says that will only check and trigger once per minute, which is a bit too much latency for a kitchen timer.

The best I have managed so far is to have an automation triggering every 10 seconds with a condition to check if the timer is going off:

- alias: "Kitchen Timer Announcement"
  trigger:
    platform: time_pattern
    seconds: "/10"
  condition: 
    condition: template
    value_template: "{{ states('sensor.kitchen_echo_next_timer') != 'None' and as_timestamp(states('sensor.kitchen_echo_next_timer')) < as_timestamp(now()) }}"
  action:
    service: notify.alexa_media
    data_template:
      target: ["media_player.living_room_echo", "media_player.bedroom_echo"]
      data:
        type: "announce"
      message: "The kitchen timer is going off"

This works (every ten seconds while the alarm is sounding!), but is there a better way to do this? What I’d like to be able to do is trigger on the next_timer being updated, and then automatically create some kind of one-shot automation that will run a script at the time in the state of the sensor to make the announcement. Is that possible with HA?

I’m pretty sure you don’t need this. With the assumption that the state will change when the timer starts, ends, or replaced with a new timer on end…

- alias: "Kitchen Timer Announcement"
  trigger:
    platform: state
    entity_id: sensor.kitchen_echo_next_timer
  condition:
    condition: template
    value_template: >
      {% set from = as_timestamp(trigger.from_state.state) %}
      {% set to = as_timestamp(trigger.to_state.state) %}
      {{ (from != to) and ((from and to) or (from and not to)) }}
  action:
    service: notify.alexa_media
    data_template:
      target: ["media_player.living_room_echo", "media_player.bedroom_echo"]
      data:
        type: "announce"
      message: "The kitchen timer is going off"

If my assumption is correct, this should only fire when timers end

Thanks @petro, but unfortunately, it seems that the behaviour of the sensor is that the “next_timer” time is updated when a timer is set, but it is not cleared until the alarm has gone off and been cancelled, so the effect of your version when I tried it was to get the announcement in the living room just after I say “Alexa, stop” in the kitchen. That’s why I have been using the “next_timer < now” test to see when the alarm is going off - but polling that every ten seconds seems a bit rubbish!

I guess the best fix would be for the custom component to implement the sensor differently, but before I look into that I feel like it should be possible to schedule something to happen in the future from an automation - like a service which takes a future timestamp and triggers an event at that time, but I can’t seem to find one (I am pretty new to HA). If I could do that, then I could schedule that event when the timer is set, and at the allotted time check make the announcement if it hasn’t been cancelled in the meantime.

Damn, it was worth a shot.

The longer way to do this is to build a automation and a script. I find it easier than a timer. But you create a script that has a template duration. Whenever the state changes, it should run it.

The turn off script action is to reset the ‘timer’ if it gets triggered again. we do this by turning the script off (canceling the timer) and starting it back up.

script:
  alexa_timer:
    sequence:
    - delay:  "{{ duration }}"
    - service: notify.alexa_media
      data_template:
        target: ["media_player.living_room_echo", "media_player.bedroom_echo"]
        data:
          type: "announce"
        message: "The kitchen timer is going off"
- alias: start timer
  trigger: 
    platform: state
    entity_id: sensor.kitchen_echo_next_timer
  condition:
    condition: template
    value_template: >
      {% set from = as_timestamp(trigger.from_state.state) %}
      {% set to = as_timestamp(trigger.to_state.state) %}
      {{ from != to and not from }}
  action:
  - service: script.turn_off
    entity_id: script.alexa_timer
  - service: script.alexa_timer
    data_template:
      duration: >
        {% set alarm = as_timestamp(trigger.to_state.state) %}
        {{ (alarm-now().timestamp()) | timestamp_custom("%H:%M:%S", false) }}
2 Likes

Thank you! The templated parameter was the missing link I needed! I’ve now got the whole thing working, and split up the script so I can make it loop the announcement while the timer is going off.

For the benefit of people from the future who might want to try this, my final automation looks like this:

- alias: "Kitchen Timer Announcement"
  trigger: 
    platform: state
    entity_id: sensor.kitchen_echo_next_timer
  condition: 
    condition: template
    value_template: "{{ trigger.to_state.state != 'None' and trigger.from_state.state != trigger.to_state.state }}"
  action:
    - service: script.turn_off
      data:
        entity_id: script.alexa_timer_check
    - service: script.alexa_timer_check
      data_template:
        duration: "{{ (as_timestamp(trigger.to_state.state) - now().timestamp() + 5) | timestamp_custom('%H:%M:%S', false) }}"

And these scripts handle the announcements:

alexa_timer_check:
  sequence:
    - delay: "{{ duration }}"
    - service: script.alexa_timer_announce

alexa_timer_announce:
  sequence:
    - condition: template
      value_template: "{{ states('sensor.kitchen_echo_next_timer') != 'None' and as_timestamp(states('sensor.kitchen_echo_next_timer')) < as_timestamp(now()) }}"
    - service: notify.alexa_media
      data_template:
        target: ["media_player.living_room_echo", "media_player.bedroom_echo"]
        data:
          type: "announce"
        message: "The kitchen timer is going off"
    - service: script.alexa_timer_loop

alexa_timer_loop:
  sequence:
    - delay: "00:00:10"
    - service: script.alexa_timer_announce
3 Likes

Thank you for this. This is great! Now I can set a timer in the kitchen, forget I’ve set it, go upstairs, and still get notified!

I’ve noticed that I seem to get entries in the log saying “Script script.alexa_timer_check already running.” when a timer is set. Any idea why? I didn’t think this was possible, since the automation calls turn_off immediately before calling the script? Weirdly this doesn’t actually seem to stop it working though.

it shouldn’t stop working because you turn it off before turning it on again. Do the entries in the log say INFO, ERROR, or WARNING?

They are WARNINGs.

I have noticed that after updating the alexa media player custom component I am also getting some errors because the sensor returns “unknown” now instead of “None”, so I have updated the automation and scripts accordingly.

I set the timer by voice command. Is it possible to read the countown from the Alexa timer and display it in the lovelace?

by the way: I use Sonos with Alexa and have Haaska installed

Thanks

I have sensor.kitchen_echo_next_timer in an entities card in Lovelace and it shows a countdown. It only shows whole minutes remaining, then seconds when there is less than one minute left.

Thanks!
How do you get this sensor? My sonos speacker has just the entity “media_player.kitchen”. There are no sensor (-domains).

Have you installed the Alexa Media Player custom integration from HACS and configured it? https://github.com/custom-components/alexa_media_player/wiki/Configuration
That’s the one I used for all of the stuff earlier in this thread. I don’t know if it works with Sonos speakers - I’ve only used it with Echoes.

1 Like

What is the state change for your automation’s trigger? I keep getting errors that the trigger is undefined. I have copied your script and automation exactly and changed my entity_id to the device I am using.

The scripts have slightly evolved over time since I posted them here. Here’s what I’ve currently got running and it’s probably 95% reliable (sometimes the integration fails to update next_timer when it is set but that seems to have improved with recent updates). No doubt some bits are probably unnecessary but now it works I’m leaving it alone!

The automation:

- alias: Kitchen Timer Announcement
  trigger:
    platform: state
    entity_id: sensor.kitchen_echo_next_timer
  condition:
    condition: template
    value_template: '{{ trigger.to_state.state not in [''None'', ''unknown'', ''unavailable'']
      and trigger.from_state.state != trigger.to_state.state }}'
  action:
  - service: script.turn_off
    data:
      entity_id: script.alexa_timer_check
  - delay:
      seconds: 1
  - service: script.alexa_timer_check
    data_template:
      duration: '{{ (as_timestamp(trigger.to_state.state) - now().timestamp() + 5)
        | timestamp_custom(''%H:%M:%S'', false) }}'

And these are the scripts:

alexa_timer_check:
  sequence:
  - delay: '{{ duration }}'
  - service: script.alexa_timer_announce

alexa_timer_announce:
  sequence:
  - condition: template
    value_template: '{{ states(''sensor.kitchen_echo_next_timer'') not in [''None'',
      ''unknown'', ''unavailable''] and as_timestamp(states(''sensor.kitchen_echo_next_timer''))
      < as_timestamp(now()) }}'
  - service: notify.alexa_media
    data_template:
      target:
      - media_player.living_room_echo
      - media_player.bedroom_echo
      data:
        type: announce
      message: The kitchen timer is going off
  - service: script.turn_off
    data:
      entity_id: script.alexa_timer_loop
  - delay:
      seconds: 1
  - service: script.alexa_timer_loop

alexa_timer_loop:
  sequence:
  - delay: 00:00:9
  - service: script.alexa_timer_announce

hmm, still getting errors. Now with what you just posted, I receive an error about the delay duration of Alexa Timer Check:

alexa_timer_check: Error rendering alexa_timer_check delay template: offset should be format 'HH:MM' or 'HH:MM:SS'`

Then when I try to run the entire automation, I receive this error:

Kitchen Timer Announcement: Error executing script. Unexpected error for call_service at pos 2: Error rendering data template: UndefinedError: 'trigger' is undefined
Kitchen Timer Announcement: Error executing script. Unexpected error for call_service at pos 3: Error rendering data template: UndefinedError: 'trigger' is undefined
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 221, in async_render
    return compiled.render(kwargs).strip()
  File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 1090, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 832, in handle_exception
    reraise(*rewrite_traceback_stack(source=source))
  File "/usr/local/lib/python3.7/site-packages/jinja2/_compat.py", line 28, in reraise
    raise value.with_traceback(tb)
  File "<template>", line 1, in top-level template code
  File "/usr/local/lib/python3.7/site-packages/jinja2/sandbox.py", line 407, in getattr
    value = getattr(obj, attribute)
jinja2.exceptions.UndefinedError: 'trigger' is undefined

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 104, in async_prepare_call_from_config
    template.render_complex(config[CONF_SERVICE_DATA_TEMPLATE], variables)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 70, in render_complex
    return {key: render_complex(item, variables) for key, item in value.items()}
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 70, in <dictcomp>
    return {key: render_complex(item, variables) for key, item in value.items()}
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 72, in render_complex
    return value.async_render(variables)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 223, in async_render
    raise TemplateError(err)
homeassistant.exceptions.TemplateError: UndefinedError: 'trigger' is undefined

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 154, in _async_step
    self, f"_async_{cv.determine_script_action(self._action)}_step"
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 624, in _async_call_service_step
    *self._prep_call_service_step(), blocking=True, context=self._context
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 253, in _prep_call_service_step
    return async_prepare_call_from_config(self._hass, self._action, self._variables)
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 107, in async_prepare_call_from_config
    raise HomeAssistantError(f"Error rendering data template: {ex}") from ex
homeassistant.exceptions.HomeAssistantError: Error rendering data template: UndefinedError: 'trigger' is undefined

Am I doing something incorrectly?

UPDATE: It is working now… I didn’t change anything and it started working… Thanks!

I don’t want hijack this topic.
I like to use the timer function. But i have some problems to integrate my sonos speaker. Everything is not available (nicht Verfügbar). And all my Sonos shows up as two devices (“Yves 2’nd Sonos One” and “Büro” ). I Reinstall the Tool several times and i have no idea what i did wrong. The only Fail i did during the first installation was to choos amazon.com instead of amazone.de

alexa_media_player|433x429

Any idea to help me?
Thanks a lot!

I have one more slit issue with this. All of a sudden, when I set a timer, and that time goes off, the notification seems to loop and the only way I can get it to stop is to restart HA. It was working prior to today just fine where the timer would go off once and then the automation would notify the alexa group I entered, and they it would stop. But like I said, now it just keeps going and the only way to stop it is to reboot HA.

Sorry not to answer the queries above, I’ve not been on here for a while. However, I have just been updating the scripts since they broke after I upgraded to 0.114. The good news is they are much simpler now that they can use the new repeat functionality and mode options for multiple calls, with just one automation and one script instead of three.

Automation:

- alias: Kitchen Timer Announcement
  mode: parallel
  trigger:
    platform: state
    entity_id: sensor.kitchen_echo_next_timer
  condition:
    condition: template
    value_template: '{{ trigger.to_state.state not in [''None'', ''unknown'', ''unavailable'']
      and trigger.from_state.state != trigger.to_state.state }}'
  action:
  - service: script.alexa_timer_announce
    data_template:
      duration: '{{ (as_timestamp(trigger.to_state.state) - now().timestamp() + 5)
        | timestamp_custom(''%H:%M:%S'', false) }}'

And the script:

alexa_timer_announce:
  alias: "Kitchen Timer Announcement Loop"
  mode: restart
  sequence:    
    - delay: '{{ duration }}'
    - repeat:
        while:
          - condition: template
            value_template: '{{ states(''sensor.kitchen_echo_next_timer'') not in [''None'',
              ''unknown'', ''unavailable''] and as_timestamp(states(''sensor.kitchen_echo_next_timer''))
              < as_timestamp(now()) }}'
        sequence:
          - service: notify.alexa_media
            data_template:
              target:
              - media_player.living_room_echo
              - media_player.bedroom_echo
              data:
                type: announce
              message: The kitchen timer is going off
          - delay:
              seconds: 10

I have tested this and it appears to work with single and multiple timers, including when additional timers are set to go off earlier or later than the already running one.

Note: The combination of “mode: parallel” on the automation and “mode: restart” on the script is the critical bit to making the multiple timers work correctly.

1 Like