Squirrel Logo

Home Assistant Timers made easy

Johan Vromans
Articles » HA Timers


Home Assistant Timers made easy

Note: I’m a software developer and I consider Home Assistant YAML config files as a piece of software. If you are not familiar with basic software development, source editing and version control then this article is not for you. Also note that I work on a Linux workstation. Everything I do can alse be done on Windows and Mac if you read the appropriate documentation.

Everything described here is available in my Github repository.

Timers

A Home Assistant Timer is a special entity that has a duration that can be set and then counts down to zero. A timer can be started, stopped, paused and cancelled. Each of these operations cause an event to be fired that can be used in automations.

The state of a timer is persistent and can be configured to survive a Home Assistant restart or system boot.

What do we need for a timer?

This more or less follows from the description: we need a timer entity, and scripts to perform the operations. Depending on the purpose of the timer we need automations that responds to the timer events.

A switch-off timer

An often used timer is a switch-off timer. It is connected to a device and switches the device off when the countdown timer finishes. So we need a timer:

timer:
  keuken_afzuigkap:
    duration: "00:15:00"
    restore: true

The initial duration is 15 minutes. The restore attribute controls whether the timer state persists across reboots.

A script to start the timer:

script:
  start_keuken_afzuigkap_timer:
    alias: Start Keuken Afzuigkap Timer
    description: >-
      Starts the keuken_afzuigkap timer for 00:15:00.
    sequence:
      - service: timer.start
        data:
          duration: "00:15:00"
        target:
          entity_id: timer.keuken_afzuigkap
    mode: queued

As you can see, the timer duration can also be specified when the timer is started.

Finally an action to perform when the timer finishes:

automation:
  - id: Automation__Switch_Off_Keuken_Afzuigkap
    alias: Switch Off Keuken Afzuigkap
    description: Switch Off Keuken Afzuigkap
    trigger:
      - platform: event
        event_type: timer.finished
        event_data:
          entity_id: timer.keuken_afzuigkap
    action:
      - service: switch.turn_off
        entity_id: switch.keuken_afzuigkap

This is sufficient for the timer to work. It can be started, possibly by pusing a button, and when the timer finishes the device is switched off.

This is all pretty much straightforward. You only need the name of the timer and the associated switch and everything follows automatically. So this is an excellent case to use a templating system as described in my article Managing Home Assistant YAML config files.

This is all what will be needed to create the above timer (Github):

[% INCLUDE switchoff_timer name = "Keuken Afzuigkap" %]

Of course, the magic is in the switchoff_timer template:

[%# Switch-Off timer			-*- tt -*-

Arguments:

name	   A name for the timer, e.g. "Keuken Afzuigkap".
type	   The type of the associated device, e.g. "switch" or "light".
	   Defaults to "switch".
duration   Duration of the count down timer. Defaults to 15 minutes.
timer	   A name for the timer, defaults to an id derived from the name.
switch	   The switch to turn off, if not the same as the timer.

-%][%- # Switch-Off timer
   DEFAULT type      = "switch";
   DEFAULT duration  = "00:15:00";
   DEFAULT increment = "00:15:00";
   DEFAULT timer     = name.lower.replace(" ","_");
   DEFAULT switch    = timer;
   -%]
timer:

  [%timer %]:
    duration: "[%duration %]"
    restore: true

script:

  start_[%timer %]_timer:

    alias: Start [%name %] Timer
    description: >-
      Starts the [%timer %] timer for [%duration %].
    sequence:
      - service: timer.start
        data:
          duration: "[%duration %]"
        target:
          entity_id: timer.[%timer %]
    mode: queued

automation:

  - id: Automation__Switch_Off_[%name.replace(" ","_") %]
    alias: Switch Off [%name %]
    description: Switch Off [%name %]
    trigger:
      - platform: event
        event_type: timer.finished
        event_data:
          entity_id: timer.[%timer %]
    action:
      - service: [%type %].turn_off
        entity_id: [%type %].[%switch %]

Once we have this template it is easy to construct timers for all kinds of purposes. Moreover, when we enhance the template with functionality, all timers will benefit.

For example (Github):

[%# Switch-Off timer			-*- tt -*-

Arguments:

name	   A name for the timer, e.g. "Keuken Afzuigkap".
type	   The type of the associated device, e.g. "switch" or "light".
	   Defaults to "switch".
duration   Duration of the count down timer. Defaults to 15 minutes.
increment  Increment the timer when it is already running.
timer	   A name for the timer, defaults to an id derived from the name.
switch	   The switch to turn off, if not the same as the timer.

-%][%-
   DEFAULT type      = "switch";
   DEFAULT duration  = "00:15:00";
   DEFAULT increment = "00:15:00";
   DEFAULT timer     = name.lower.replace(" ","_");
   DEFAULT switch    = timer;
   -%]
timer:

  [%timer %]:
    duration: "[%duration %]"
    restore: true

script:

  start_[%timer %]_timer:

    alias: Start [%name %] Timer
    description: >-
      Starts the [%timer %] timer for [%duration %].
      If it is already running, increment with [%increment %].
    sequence:
      - service: timer.start
        data:
          duration: >-
            {% set f = state_attr('timer.[%timer %]','finishes_at') %}
            {{ "[%duration %]" if f == None else
               ( (as_datetime(f) - now() + as_timedelta("[%increment %]")).total_seconds() )|int }}
        target:
          entity_id: timer.[%timer %]
    mode: queued

automation:

  - id: Automation__Stop_[%name.replace(" ","_") %]_timer
    alias: "Stop [%name %] timer."
    description: "Stop [%name %] timer."
    mode: queued

    trigger:
      - platform: state
        entity_id: switch.[%switch %]
        to: 'off'

    action:
      - service: timer.cancel
        entity_id: timer.[%timer %]

  - id: Automation__Switch_Off_[%name.replace(" ","_") %]
    alias: Switch Off [%name %]
    description: Switch Off [%name %]
    trigger:
      - platform: event
        event_type: timer.finished
        event_data:
          entity_id: timer.[%timer %]
    action:
      - service: [%type %].turn_off
        entity_id: [%type %].[%switch %]

Now each of the timers will be cancelled if the associated switch is switched off. And when the start script is executed when the timer is running, the countdown value is increased.

This can be used e.g. in an entities card on the dashboard (Github):

  - entity: switch.keuken_afzuigkap
    name: Afzuigkap
    icon: mdi:fan
    hold_action:
      action: call-service
      service: script.start_keuken_afzuigkap_timer

  - [% INCLUDE switchoff_timer_row name = "Timer",
       timer = "keuken_afzuigkap", icon = "fan" %]

The switchoff_timer_row template provides a conditional row that displays the timer if it is running. It’s hold_action will cancel the timer.

timer.png

Repository files

Everything described here is available in my Github repository.



© Copyright 2003-2023 Johan Vromans. All Rights Reserved.
articles/hass_timers/index.html last modified 21:25:00 31-Jan-2023