Trying to set a notifcation when there is a minute left on timer

Created a simple sleep timer automation for my tv and I used the event.started to send a notification to the tv that it has been started. Now Im trying to send a notification when the timer hits 1 min, 30 secs, and 10 seconds. I see the attribute “remaining” exists but it’s static, always stays at the initial time…so that makes no sense to me.

The only thing that I can think of, in which I don’t have much experience with and hoping someone can help me is use the "finishes_at attribute and subtract it from the time now(). Am I on the right track with this?

Its weird to me there isn’t a real time attribute for the timer component.

Yes. Your automation can use a Template Trigger.

Something to consider:

When the timer is running, the finshes_at attribute exists. However, when paused or finished, the attribute no longer exists. The template must be able to gracefully handle the case where the attribute isn’t available.

Try this: EDIT Does not work as desired; see explanation several posts below.

alias: 'example 1'
trigger:
  - platform: template
    value_template: >
      {% set f = state_attr('timer.your_timer', 'finishes_at') %}
      {{ f != none and (as_timestamp(f) - now().timestamp()) | int in [10, 30, 60] }}
action:
  - service: notify.persistent_notification
    data:
      title: Attention
      message: >
        There are {{ (as_timestamp(state_attr('timer.your_timer', 'finishes_at')) - now().timestamp()) | int }} seconds remaining.
1 Like

Awesome! I didn’t realize you can add all 3 times into one, that’s pretty cool. Il try this tomorrow and report back.

Im getting an error atm with it. Saying the format tag is undefined.

Logger: homeassistant.helpers.template
Source: helpers/template.py:1346
First occurred: 12:10:23 PM (4 occurrences)
Last logged: 12:10:35 PM

Template variable error: 'f' is undefined when rendering '{{ f != none and (as_timestamp(f) - now().timestamp()) | int in [10, 30, 60] }}'

you didn’t copy his template fully.

Yes I did, but now just realized the code had too many closing brackets after 'finishes_at

('timer.tv_timer.15', 'finishes_at'))

Not spitting anymore errors so going to test it out in a bit.

I just realized that the example will not work for the desired time intervals (all are under a minute).

A listener will be assigned to the one identifiable entity in this template, namely the timer:

      {% set f = state_attr('timer.your_timer', 'finishes_at') %}
      {{ f != none and (as_timestamp(f) - now().timestamp()) | int in [10, 30, 60] }}

That means the template is evaluated only when the timer’s state changes which, of course, won’t occur while its counting down because its state simply remains active.

At best, the template’s inclusion of now() means the template will be evaluated once a minute (on the minute). However, that’s a 1-minute time resolution which is too coarse for the desired purpose.

You would have to include something in the template that causes it to be evaluated every second. The problem is, if you do that, the template will continue to be evaluated every second even when the timer is not active.

I can’t think of an elegant way to meet your requirements. One could use a cascading series of timers (each with a duration set to your desired intervals) with automations to make them work in sequence and fire off notifications … but that seems like a terrible kludge.

Hopefully some else can come up with something more clever.

2 Likes

Ah okay… Well I appreciate the effort you put into it so far. Why would this be such a chore anyways? Not sure why there can’t be ab attribute that counts in real-time.

I tried something different.

This automation triggers when the timer starts then loops every second (only while the timer is active). In each loop, it calculates the remaining time and checks if it matches 10, 30, or 60 seconds. If it does it sends a notification.

alias: 'Timer Notifications'
id: timer_notifications
trigger:
- platform: event
  event_type: timer.started
  event_data:
    entity_id: timer.test
action:
- variables:
    f: "{{ as_timestamp(state_attr('timer.test', 'finishes_at')) }}"
- repeat:
    while:
    - condition: template
      value_template: "{{ is_state('timer.test', 'active') }}"
    sequence:
    - variables:
        t: "{{ (f - now().timestamp()) | int }}"
    - choose:
      - conditions: "{{ t in [10, 30, 60] }}"
        sequence:
        - service: notify.persistent_notification
          data:
            title: Attention
            message: "There are {{ t }} seconds remaining."
    - delay: '00:00:01'

Based on a few tests, it seems to work as desired:

What’s important here is that this repeated looping every second only occurs while the timer is active. It stops when the timer is idle or paused. In other words, it’s reasonably efficient and uses no resources while the timer is not active.

3 Likes

Man…Thanks so much for your time and work. I’m working on trying this out right now and hoping one day I can be much proficient with templates. Taking python this semester in school and it’s been helping me understand the syntax better in HA.

If the automation I posted resolves your original problem, please consider marking my post (above) with the Solution tag.

It will automatically place a check-mark next to the topic’s title which signals to others that your problem has been resolved. It will also place a link below your first post that leads to the Solution post.

All of this helps other users find answers to similar questions.

Hey, sorry iv been so busy with school with my last week and exams I got around to trying it but it still does not show the notification on the TV. I edited your code to fit my entities and it seems all correct, so not sure whats going. My notification is using the android tv notification app. The initial message when it starts works.

- alias: 'Timer Notifications'
  trigger:
  - platform: event
    event_type: timer.started
    event_data:
      entity_id: timer.tv_timer_15
  action:
  - variables:
      f: "{{ as_timestamp(state_attr('timer.tv_timer_15', 'finishes_at')) }}"
  - repeat:
      while:
      - condition: template
        value_template: "{{ is_state('timer.tv_timer_15', 'active') }}"
      sequence:
      - variables:
          t: "{{ (f - now().timestamp()) | int }}"
  - choose:
      - conditions: "{{ t in [10, 30, 60] }}"
        sequence:
        - service: notify.mikes_bedroom_tv
          data:
            title: Attention
            message: "There are {{ t }} seconds remaining."
  - delay: '00:00:01'

Have you tested the example I posted and confirmed it works on your system?

  • If it fails then we can correct it.
  • If it works then the concept is sound and there’s something else that causes your adapted version to fail.

No I had not as I figured changing to my proper timer and a different notification service wouldn’t matter. So I will make a test timer and see

Okay so I did test it and it works with persistent notifications so not sure what the difference would be with the android notification would be

OK, so the concept is sound and proven to work.

The issue is that the chosen notification method, AndroidTV notification integration, fails to work.

I’m unfamiliar with the AndroidTV notification integration. Have you confirmed it works correctly by testing it in Developer Tools > Services? Try something simple like:

service: notify.mikes_bedroom_tv
data:
  title: Attention
  message: Hello world!

Oh yes, I have been using that integration for a few years now. So not sure whats up.

1 Like

This is great, just what I’ve been looking for. How would I do the same, but for minutes not seconds?

Simplest way is to multiply the seconds by 60. For example, this represents 1, 2, and 5 minutes.

      - conditions: "{{ t in [60, 120, 600] }}"
1 Like

Yes, I have done that but a notification that says “x in 300 seconds” is a bit less user friendly “than x in 5 minutes”.