Resume timers after reboot

This might need to be a feature request, but thought that I would check here first in case I overlooked something.

Is there a way to to resume a timer or all the timers after rebooting/restarting Home Assistant? I have some timers that will be set for a number of hours. If I am developing other Automations or Configurations in YAML and I need to restart home assistant to apply the changes, I want my timers to continue where they left off. It’s ok if the timer is delayed during the time the HA took to restart, but I guess it would be ideal if that was taken into account as well.

Right now what happens when a timer is set, the countdown begins. If HA is restarted during the timer execution, the timer is reset and since the duration is set by a template and there is no default value there is no timer duration set.

I can see that I could manually implement this by having an automation that records the current time remaining in the timers, pauses the timer, and at HA start, it sets the duration to the saved time and starts the timer… but this could cause issues if their is an associated automation based on the timer starting and it seems like there should be a more elegant solution. Another option might be to create a custom-component that saves the timestamp of when the timer should be finished and restores the state of the timer at boot by restoring the remaining (to_finish_timestamp - now().timestamp) and the state (active, idle, paused, etc.)

Anyone know of a better or simpler solution?

Solutions:

@123 Came up with a solution that works with the built in Home Assistant timer. See the solution here: Resume timers after reboot

@gremblin Came up with a solution by editing the Home Assistant timer component. This needs to be installed in custom_components and overrides the built in Home Assistant timer. See the solution here: Resume timers after reboot

Unfortunately no.

I was just recently in the same situation as you with needing to make sure a timer got restarted after a HA restart. I ended up using an automation(s) to accomplish it.

The solution was provided by @klogg in this post:

If you have a bunch of timers to keep track of it’s going to get messy…

A built in way of maintaining timer state after start would be really convenient.

1 Like

Thank you for the quick reply and for sharing your solution. I was afraid that this might be my answer. Sounds like it might get messy.

It’s not all that messy. For example, this automation publishes a timer’s state and attributes, as a JSON string, to an MQTT topic.

- alias: 'Timer Monitor'
  trigger:
    platform: state
    entity_id:
      - timer.my_timer
      - timer.another_timer
  action:
    service: mqtt.publish
    data_template:
      topic: timer/{{trigger.to_state.object_id}}
      payload: '{"state":"{{trigger.to_state.state}}", "duration":"{{trigger.to_state.attributes.duration}}, "remaining":"{{trigger.to_state.attributes.remaining}}"}'
      retain: true

So if timer.my_timer is in operation, its information will be published to the topic:

timer/my_timer

and its payload will be a JSON string, something like this:

{"state":"active", "duration":"0:00:10, "remaining":"0:00:10"}

or this:

{"state":"paused", "duration":"0:00:10, "remaining":"0:00:06.043552"}

or this:

{"state":"idle", "duration":"0:00:10, "remaining":"0:00:00"}

So if Home Assistant is restarted while the timer is working, the topic’s payload will report the sensor’s last-known state, namely active. This information can be used at startup (by another automation) to determine if the timer was interrupted and should be started again.

HOWEVER, that’s merely sufficient to know if the timer should be restarted from the beginning of its duration, not from where it was interrupted.

The reason is because remaining is not refreshed with each clock tick. It refreshes when the timer is paused and when it is finished. Because there’s no indication of how much time is actually remaining while it is counting down, there’s no value available to restart the timer from the point it was interrupted.

Yes, and that limitation is solved by the automations provided at the link I posted.

That’s the messy part if you have more than a couple of timers that you need to keep track of.

I’ve seen it and it’s a very case-specific way of solving the problem. In effect, you’re no longer using a timer directly but indirectly through associated input_datetime entities (they must be used to set the timer’s duration). Each timer needs its own input_datetime entities and anywhere you use the timer you have to employ a template to calculate its duration.

… and if I’ve misunderstood its theory of operation, please correct me!

Don’t get me wrong, it’s a clever way of tackling the issue but requires a fair amount of overhead for each instance of a timer and a different way of using a timer.

What I was attempting to present was a transparent, general-purpose solution where you aren’t obligated to handle timers differently (with input_datetime entities and a special template). I can get as far as determining if a timer should be restarted (from the beginning of its duration) but not from where it was interrupted. If there was some way to get the actual remaining time, then the solution would be complete.

If anyone has any insight into how to acquire this value, it would be very helpful.

You’d also have to consider some application timers may require a start and a finish giving you x duration
Other applications may need a total duration timer split to y initialise upto shutdown and z from restart to completion - even if the gap between is 10 minutes or 10 years ???

In its basic form, a timer has a state, duration, and remaining time to expiration. Ideally, these states and attributes should survive a restart (like, say, a binary_sensor). However, they don’t; if Home Assistant is restarted during a timer’s active countdown state, the timer will be restored to its idle state.

There may be corner-cases where a timer should not survive a restart (generally speaking, I’ve yet to encounter one but I recognize it may exist). Perhaps the conditions that led to the timer’s activation no longer exist after Home Assistant is restarted (so it shouldn’t be automatically restarted at startup). To handle this requirement, a flag is needed to indicate if the timer should/shouldn’t be restored. Now we are off into Feature Request territory.

So I have to post it again?!

OK…

:wink::laughing:

but joking aside…

There isn’t any other way. You have to do it in the other harder, messier way.

It may not be the best way but as far as I know, until HA changes the way timers work on restarts, it’s the only way it can be done.

And to be fair, I’m not sure that I would call your automation any more transparent than doing it the other way. It may be way shorter because you can list all of your existing timers in the one automation but you still have to have other automation(s) to start the timer again. And ultimately it doesn’t solve the final step in any desired complete solution.

I assume you’re pulling my leg now because we both know klogg’s approach doesn’t use the timer’s remaining attribute … and that is what I was requesting in my previous post.

You appear to know more about his solution than I do, so I would appreciate it if you can confirm my understanding of it is correct.

It creates an eco-system around a timer entity using:

  • An input_text input_number to store the timer’s duration.
  • An input_datetime to store the timer’s start time.

The following template, part of the automation that runs at startup, appears to be based on the premise that if Home Assistant’s startup occurs between the timer’s start and end time then it means the timer must have been interrupted. Therefore the timer’s remaining time is:

(timer’s start time stored in the input_datetime + timer’s duration stored in the input_text) - current time

The result of this calculation represents the timer’s remaining time to run and is used to set the timer’s duration.

      - service: timer.start
        data_template:
          entity_id: timer.guest_mode_schedule_1_duration
          duration: >
            {% set time_now = as_timestamp(now()) %}
            {% set start_time = states('input_datetime.guest_mode_schedule_1_start_time') %}
            {% set start_time = as_timestamp(now()) | timestamp_custom('%Y-%m-%d') + ' ' + start_time %}
            {% set duration = states('input_number.guest_mode_schedule_1_duration') | int * 60 %}
            {% set end_time = as_timestamp(start_time) + duration %}
            {% set seconds_left = end_time - time_now %}
            {% set hours_left = seconds_left // 3600  %}
            {% set minutes_left = (seconds_left - (hours_left * 3600)) // 60 %}
            {{ '%02i' | format(hours_left) }}:{{ '%02i' | format(minutes_left) }}:01

If I’ve got that right then it is, as I said, a clever solution but intended for a very specific use-case. In effect, this is a scheduler composed of three parts:

  1. timer
  2. input_text input_number
  3. input_datetime

By design it assumes:

  • the timer’s previous state was active and excludes the possibility it was paused during its countdown (or idle due to cancellation)
  • the timer will be started exclusively at the time specified by its input_datetime

It’s a good solution but designed for a specific way of operating a timer. I’m still trying to devise a general-purpose solution … but it doesn’t look promising.


EDIT
Correction. Replaced input_text with input_number

of course! :slightly_smiling_face:

You are generally correct.

It stores the duration in Klogg’s case by use of an input_number (not an input_text) but that’s not really any more than a minor misunderstanding. And that is only necessary if you want the user to select the duration on the frontend.

In my case I have a fixed duration timer so I just use a number directly in my logic and no input_number is necessary.

yes. But it also uses another means of testing whether the timer should be running or not as well. In Kloggs case I think he used a “guest mode on”. In my case I am using a “CPAP Timer Master” input_boolean being on to run the timer restart automation. So, yes, there is an assumption that the timer was active at restart but it’s not totally a S.W.A.G. :wink: It is based on a tangible thing to say it should have been running.

And also in my case I only store the datetime that the timer is actually started. So the only time the datetime gets set is when the timer is actually started so not really an assumption there either.

And generally most people don’t use a lot of timers. I’ve been using HA for over 2 years and I’ve only got 4 timers total in my system (and I may not actually still be using one of those). And even of those timers most of the time they wouldn’t be super-critical to force a restart. I’ve never needed this until now.

So taking all of that into account this way of ensuring a timer restart for the remaining duration won’t typically become too cumbersome.

I agree but good luck in finding some way of doing more cleanly. If anyone can do it I think you can.

OK thanks (and I corrected by original post regarding the input_text).

So it has a slightly bigger eco-system than I described; I overlooked the ‘activity flag’ implemented with an input_boolean.

Thanks for the vote of confidence but even if I had access to the timer’s actual remaining time, I don’t think my so-called ‘general purpose’ solution would be as universally useful as I first thought. Here’s what I mean:

Let’s say you start a 15-minute timer. The timer begins its countdown and then, perhaps 5 minutes into its operation, there’s a power failure (and the host is not protected by a UPS). An hour later, power is restored and Home Assistant restarts. Does that 15-minute timer still need to run for another 10 minutes? Perhaps whatever needed to happen at the original 15-minute mark no longer applies after a delay of an hour. Effectively, the timer has gone stale. Maybe forcing it to continue now will produce an undesirable result.

As a consequence of this observation, one should be able to have a timer opt out of being monitored and restored. In the interest of a achieving a ‘transparent, general purpose’ solution, you don’t want to have to create an input_boolean, to serve as an ‘opt in/out’ flag, for each timer. So far, the only quasi-transparent solution to this is to manually create a group containing the timers that should be monitored and restored (something like group.restored_timers).

Anyway, the primary hurdle remains the ability to get the actual remaining time and that’s currently unavailable from the timer itself.

Oh, I like the idea of saving the state information in an MQTT topic. I was thinking that I would have to save it in an input_text entity or use a python script to create a new entity or something. An MQTT topic allows it to be more dynamic so if I add timers, I don’t have to create matching input_text entities every time.

You can dynamically pull all your timers that are defined with this template:

{%- for d in states | groupby('entity_id') %}
  {%- if 'timer.' in d[0] %}
    {{ d[0] }}
  {%- endif %}
{%- endfor %}

My thought is that at shutdown, I could calculate and save the timestamp of when the timer should finish (if it is active). Then at boot check to see if there is a topic for that timer, and set the new duration to finish_timestamp - now() as long as that time has not already passed.

Of course if your automation trigger is a HA shutdown event, this won’t save your information if there is a sudden power outage, but that’s ok for me. There will be other issues for me to deal with if that happens. My HA is on a UPS anyway.

You can replace the for-loop with this:

{{ states.timer | map(attribute='entity_id') | join(',') }}

I like your idea of using the homeassistant_stop event to trigger the ‘save all timers’ automation. At least it handles the case of an orderly shutdown which is half the battle.

I’m of the opinion that it shouldn’t save all timers by default. I feel it should be an opt-in approach. The easiest way is to create a group containing the timers that should be saved/restored. Then the expand function can be used to process the group’s members.

{{ expand('group.restored_times') | list }}

How do you propose to do the following?

Base the calculation on the timer’s last_updated parameter?

Cool :+1: Thanks.

Also cool :+1: I have used loops in the past to do this.

That might work… Another option is to calculate the finish time when the timer is first executed, and then clear it when the timer finishes. If it do it that way, then I don’t need to worry about making sure that it is captured on the HA stopped event. I would just restore it on the HA start event.

Correct me if I’m wrong but this sounds like something that must be done when the timer.start event occurs. That implies it needs an automation to handle that event for each timer (and so goes the transparent nature of the solution).

Based on some simple tests, I noticed that when a timer’s state changes, its last_changed and last_updated parameters are updated. Using this information, I’ve created a template that can determine when the timer should finish (if the timer is active, then add duration to last_changed).

If you can capture the timer status on shutdown, you could also capture it with a specific command on a time pattern.
Depending on the criticality and the duration you could set it accordingly.
Pointless capturing 5 minute timers every five mins but 4 hour timers maybe.
This is all speculation though

Edit: This would be to capture in the event of power failure etc.

To recap, here’s the general idea (so far) for storing an active timer’s finish time:

  • On event homeassistant_stop
  • Get all active timers (possibly only those listed in group.restored_timers)
  • For each timer, calculate its finish_time by adding its duration to its last_changed
  • Publish the resulting timestamp to an MQTT topic

I still need to ruminate on how to consume this stored information:

  • An MQTT Sensor can subscribe to the topic and store the payload in an attribute (this circumvents the 255 character limitation of storing it in the sensor’s state).
  • On homeassistant_start, it processes the MQTT Sensor’s attribute.
  • If a timer’s finish_time is greater than the current_time then the timer should be started with a new duration of finish_time minus the current_time.
  • There may be a timing problem where the MQTT Sensor isn’t populated when homeassistant_start occurs. A small delay may be required.

Based on these ideas, I think this solution is useful for long-duration timers. Anything under a minute (or even several minutes) isn’t likely to benefit from it.


EDIT

Here’s my proposed structure for the topic’s payload:

{"saved":<date_and_time>, "timers":["this_timer":<timestamp>, "that_timer:<timestamp>, "another_timer":<timestamp>]}

saved is used for the sensor’s state (represents the time when Home Assistant was stopped) and the timers list is stored as an attribute.

… Or time pattern initiated store command??? Or are you saying power loss is unable to be provisioned for?
MQTT - where do people stand who don’t currently use the MQTT platform ?

Eh. So true. I obviously over looked that issue.

Ok. Sounds like we have a winner.

I’d probably just pull the topic directly and not define a sensor… but maybe it would be simpler with the sensor

Yes, this solution assumes proper shutdown.

They would have to come up with a different way of storing the data. This is not an HA wide solution. An HA wide solution would be to build this functionality into the timer platform, and not work within the confines of the current platform. It might not be too bad to get this to work with a custom-component. I don’t know how hard it is to get a pull request approved… I’ve never done it. I was just looking for a quick fix.