Display remaining seconds of timer in frontend

That looks like a much cleaner solution then the kludge I did.

I created an input number that would record the as_timestamp(now()) when the timer was started, and then another sensor that would calculate the active timer_duration - (input_number - as_timestamp(now())) to work out how long was left on the timer. It works perfectly but is impractical to do for all timers, I only do it where I need to know how long is left on a timer, to add or minus time from an existing running timer or I want something I can visually see on the GUI.

1 Like

this works for me.
how do i allow the card to be shown even if the timer is idle?

Don’t use a Conditional Card?

didn’t occur to me. haha thanks

Hey @callifo

Could you share the yaml of your solution? It is a little crude but basically what I am looking for. I only use it for one timer and it would allow me to query the remaining duration in other places

Configuration.yaml, sensors stored as both remaining seconds, and HH:MM:SS

sensor:
  - platform: mqtt
    state_topic: "home/timers/timer.aircon_run_timer/start"
    name: "Timer Start Aircon Run"
  - platform: mqtt
    state_topic: "home/timers/timer.aircon_run_timer/duration"
    name: "Timer Duration Aircon Run"
  - platform: template
    sensors:
      timer_remaining_sec_aircon_run:
        friendly_name: "Timer - Remaining Seconds - Aircon Run"
        value_template: >-
          {%- if (states['timer.aircon_run_timer'].attributes.duration == "none") or (states['timer.aircon_run_timer'].state == "idle") -%}
          {{ 0 | int }}
          {%- else -%}
          {{ ((((states['timer.aircon_run_timer'].attributes.duration).split(':')[0] |int * 60 * 60) + ((states['timer.aircon_run_timer'].attributes.duration).split(':')[1] |int * 60 ) + ((states['timer.aircon_run_timer'].attributes.duration).split(':')[2] |int)) - (as_timestamp(now()) | float - states['sensor.timer_start_aircon_run'].state | float) ) | int }}
          {%- endif -%}
        entity_id: 
          - timer.aircon_run_timer
      timer_remaining_hms_aircon_run:
        friendly_name: "Timer - Remaining HMS - Aircon Run"
        value_template: >-
          {%- if states['sensor.timer_remaining_sec_aircon_run'].state == 0 -%}
          00:00:00
          {%- else -%}
          {{ states['sensor.timer_remaining_sec_aircon_run'].state | int | timestamp_custom('%H:%M:%S', 0) }}
          {%- endif -%}
        entity_id: 
          - sensor.timer_remaining_sec_aircon_run

Automation to record initial start time (via MQTT, not input_number, my mistake), and then periodically update the sensor, as HA doesn’t seem to update it automatically, only runs when a timer is active.

Last automation restores active timer value on HA restart

- id: timer_start_all_timers
  alias: 'Store - Start - All timers'
  hide_entity: True
  initial_state: 'on'
  trigger:
    - platform: state
      entity_id: 
        - timer.aircon_run_timer
      to: 'active'
  action:
    - service: mqtt.publish
      alias: MQTT store timer timestamp
      data_template:
        payload_template: "{{ as_timestamp(now()) | int }}"
        topic: "home/timers/{{trigger.entity_id}}/start"
        retain: true
    - service: mqtt.publish
      alias: MQTT store timer duration
      data_template:
        payload_template: "{{ ((trigger.to_state.attributes.duration).split(':')[0] |int * 60 * 60) + ((trigger.to_state.attributes.duration).split(':')[1] |int * 60 ) + ((trigger.to_state.attributes.duration).split(':')[2] |int) }}"
        topic: "home/timers/{{trigger.entity_id}}/duration"
        retain: true
- id: timer_remaining_update
  alias: 'Timer - Remaining - Update all'
  hide_entity: True
  initial_state: 'on'
  trigger:
    - platform: state
      entity_id:
        - timer.aircon_run_timer
      to: 'active'
    - platform: time_pattern
      seconds: "/5"
  condition:
    - condition: or
      conditions:
        - condition: state
          entity_id: timer.aircon_run_timer
          state: 'active'
  action:
    - service: homeassistant.update_entity
      entity_id:
        - sensor.timer_remaining_sec_aircon_run
- id: timer_restart_all_timers
  alias: 'Store - Restart at Boot - All timers'
  hide_entity: True
  initial_state: 'on'
  trigger:
    - platform: homeassistant
      event: start
  action:
    - service_template: >
        {% if (states.sensor.timer_start_aircon_run.state | int + states.sensor.timer_duration_aircon_run.state | int) > (as_timestamp(now()) | int) %}
          timer.start
        {% else %}
          script.do_nothing
        {% endif %}
      data_template:
        entity_id: timer.aircon_run_timer
        duration: "{{ ((states.sensor.timer_start_aircon_run.state | int + states.sensor.timer_duration_aircon_run.state | int) - as_timestamp(now()) | int) | timestamp_custom('%H:%M:%S', 0) }}"

Once you’ve got the initial automations in there, you can just add more timers to them (they use trigger entity_id so are generic).

6 Likes

Wow, that is some automation. Thank you for sharing!

late post, but can you share your config of sensor.timer_start_aircon_run? I see it referenced in the post but didn’t find the config for it.

That is the sensor that is created by the MQTT sensor (at the top of the first section),

sensor:
  - platform: mqtt
    state_topic: "home/timers/timer.aircon_run_timer/start"
    name: "Timer Start Aircon Run"

It’s possible to use it with input_number.
I have one irrigation system with input time and start button.
I want display count down of this input_time number.

Somebody can help me, give me some orientation?
Thanks a lot for script callifo :wink:

Same here… I Would like to have access to the timer’s remaining time. At least the minutes that are remaining. But it seems that there is no “clean” way to do it.

Agreed. I really hope there will be a ‘clean’ and simple way to do this soon.
@pnbruckner - do you have any ideas about this? Getting the current value (remaining time) of a timer?
For my desired use, I want to create a nice custom big timer view that I’ll cast.

Please don’t randomly tag people to bring them into foreign threads.

The best way to get a ‘countdown’ is to create a timestamp sensor when the timer end will occur. The UI will naturally count down to that timestamp but it will be in a long winded format. There may be other ways to handle this now that the main event loop is sub-second based as well. But these are uncharted waters in that regards.

This sensor should get the job done.

sensor:
  - platform: template
    sensors:
      timer_end:
        friendly_name: "Timer End"
        device_class: timestamp
        entity_id: timer.xxxxxxxxxxxxxxxx # <--- Your timer (and first line of template)
        value_template: >-
          {%- set duration = state_attr('timer.xxxxxxxxxxxxxxxx ', 'duration') %}
          {%- if duration in ['none', 'idle'] %}
            unavailable
          {%- else %}
            {% set h, m, s = duration.split(':') %}
            {% set n = now().timestamp() | list | map('int') %}
            {{ (n + h * 60 * 60 + m * 60 + s) | timestamp_custom('%Y-%m-%dT%H:%M:%S-00:00', False) }}
          {%- endif -%}

This will create a sensor that looks weird in the template section, but when you place it into an entity or entities card, it will update live.

2 Likes

Is there something missing in the timer_end Template Sensor because, based on a test, it doesn’t update live.

Before it can be tested, the template needs this minor adjustment because h, m, and s are strings:

(n + h|int * 60 * 60 + m|int * 60 + s|int)

When the associated timer begins its countdown, the Template Sensor displays the timestamp. However, during the countdown, it doesn’t change because its entity_id (the associated timer) maintains a constant state of active and none of its attributes change.

You can sort of see that from this screenshot where timer.my_timer is active (therefore in a countdown) but sensor.my_timer maintains the same value (5 minutes and 15 seconds) throughout the countdown.
Screenshot from 2020-07-24 09-28-56

Yep fixed the template

This shouldn’t matter. Adding device_class: timestamp with a timestamp causes the UI to treat the datetime as a relative time. So it should count up or down without state changes when placed into UI elements that utilize the timestamp deviceclass.

EDIT: This is how ‘last_updated’, ‘last_changed’, and ‘last_triggered’ works in the UI by the way.

EDIT2: The states page will just have the timestamp like you see in your pic.

EDIT3: The only question is, (haven’t tested) Does relative time work for future timestamps? My memory says yes.

I have no luck getting it to work.

Screenshot from 2020-07-24 10-07-09

That’s a screenshot of this:

views:
  - title: Timer Test
    badges:
      - entity: timer.my_timer
      - entity: sensor.my_timer_end
    cards:
      - type: entities
        title: ''
        entities:
          - entity: timer.my_timer
          - entity: sensor.my_timer_end
  • timer.my_timer displayed as a badge or in an entities card, displays its countdown.
  • sensor.my_timer_end displays the full duration in a badge and Invalid date in an entities card but never shows a countdown.

Regardless of whether timer.my_timer is idle or active, the state of sensor.my_timer_end remains fixed at my_timer's duration (5 minutes in this example).

Screenshot from 2020-07-24 10-14-02

Screenshot from 2020-07-24 10-16-16

Hmm, I just noticed this:

image

Mistake in my template? It should just be the timestamp but it also has the duration?

Aaargh! That’s my mistake! I was experimenting with the template and that leading time is a leftover (from the Template Editor) that I copied into the sensor’s configuration.

It works now and looks like this:

Screenshot from 2020-07-24 10-32-19

:man_facepalming:

Nice, I would be interested to see what happens with the template under 1 minute. Also what happens if you pause

Hmm. Paused with 1:41 remaining.

Screenshot from 2020-07-24 10-35-50

Even though the timer remains paused, the sensor continues to report the time difference and proceeds to say:
In 4 minutes
In 3 minutes
In 2 minutes
In 1 minute
In 59 seconds
etc

Screenshot from 2020-07-24 10-39-47

It then proceeds to “wrap around” and tell you how long ago the timer allegedly finished (even though it is actually still paused).

Screenshot from 2020-07-24 10-40-34

Upon starting the paused timer, the sensor resets itself to the original duration.
Screenshot from 2020-07-24 10-43-00