Resume timers after reboot

FWIW, I posted a means of automatically saving and restoring active/paused timers (employs two automations):

It uses last_changed and remaining (available for both active and paused timers) to determine how much longer the timer should run after Home Assistant is restarted again.

Normally, it won’t restart a timer whose duration expired while Home Assistant was offline. However, to satisfy requests to modify this behavior, near the end of the thread I offered a modification that allows even expired timers to be restarted for just one second so that they’re allowed to generate a ‘finished’ event (and trigger any associated automation listening for that event).

Personally, I don’t use many timers, and the host machine is protected by a UPS, but I do use this system to ensure active timers are restored.

This is a horribly old topic so apologies for the necromancing, but it occurs to me that @gremblin 's PR needed to not worry so much about how to handle expired timers during the HA outage, but to simply advise of that scenario and let the user deal with it however they choose to. So effectively, add another Event for the Timer integration like timer.expired that would fire during restoration of the active timers, if the original finishes_at attribute is before now() instead of restoring the timer.

I’ve never looked deep into events, but I assume there is attributes there so the event data can include the original finishes_at attribute, in case the user then wants to do something with the original end date/time (eg text in a notification).

Whether this is a viable way to handle the situation or not, two years on this PR is the closest we have ever got to natively handling timers across a restart. As someone smart once said - if it was easy, we would have done it already :slight_smile:

If you use input_datetimes, you can handle all this logic yourself and avoid timers all together. And it’s fairly easy to do if you make a ‘timer script’.

script:
  start_timer:
    sequence:
    - service: input_datetime.set_datetime
      target:
        entity_id: "{{ datetime }}"
      data:
        datetime: "{{ (now() + timedelta(seconds=duration)).strftime("%Y-%m-%d %H:%M:%S") }}"

Then your automations just use the datetimes. And when you want to start the timers. Just use the following service:

- service: script.start_timer
  data:
    datetime: input_datetime.xyz
    duration: 120

And if you want to display the ‘timer’ in the frontend make a template sensor for the datetime:

template:
- sensor:
  - name: My Timer
    device_class: timestamp
    state: "{{ (states('input_datetime.xyz') | as_datetime or now())| as_local }}"

Now you can do whatever you want with your automations because you have the end time. When you restart it will persist from the input_datetime. Then just make automations to check the datetimes on startup and action off that if they are ‘expired’.

2 Likes

Putting my use-cases aside, what’s your thoughts on the suggestion of firing a timer.expired event rather than handling the expired timers with some sort of grace period? I fleshed out the idea a bit more in one of the Month of WTH posts with an example of automation yaml here.

I appreciate the response and these are some good suggestions, but for me you’ve simply underscored that the built-in timer construct is not good enough to be useful. It’s not like you’ve used a timer object and then used a hack to extend the functionality, you’ve actually moved away from timers altogether and used an alternate object type. :man_shrugging:

In my case, I use the timer state (active, idle) not an event of start or finished, so your workarounds do not simply slip in as a replacement for my existing timers. I could rework the logic I guess, but I’d prefer to put that effort into one of the hacks that store the finishes_at time into a datetime object and uses that to “restore” the timer on HA start - that way if we do ever get timers that persist my automations are still valid as-is.

Personally, I’ve never found them useful because delay on a script achieves the exact same functionality if you template delay. The script is off when it’s not running the delay, and on when it is. You can cancel and restart the script using script.turn_off and script.turn_on. To me, timers were added to appease people who did not understand how to set that up in a script. So I’m the grandpa that still uses ‘timers’ the old way.

It could be useful but I’m not sure when it would fire. That would need to be fleshed out. Event’s in general are usually good ideas. The main problem is the logic applied at startup. By default, the only entities that store states after restarts are input_* devices if they are configured to behave that way.

I’ve been trying to get some love from the devs on this topic for a while now but no one seems to think it’s an issue.

I even posted a suggestion here on how it might be done.

sure there are complex work arounds but I still think a timer functionality is a pretty basic requirement for any real automation system.

every industrial PLC/CNC system I have ever worked with (siemens/modicon/twincat/allen bradley) provides that function, even 30 years ago.

petro must be REALLY old… :wink:

Yeah I saw that thread and your comments, and that (saving finish time at state change) is the approach I would take if I was to use datetime helpers to work around the current issue.

I agree that petro is not thinking about things in the same way that I am - a wait in an automation is not intuitive when the time wait is several tens of minutes or even hours. Plus that also suffers from the same issue - an in-flight automation with a 2-hour wait in it does not resume after an HA restart - leaving me with exactly the same problem still and zero options for working around it.

The longest delay I use is 5 minutes. Anything else’s is a scheduled time with templates. Survives restarts and displays nicely in the frontend. :man_shrugging: