Mushroom : how to display remaining time of a timer?

Hello,

I want to display the remaining time of a timer, but…

I tried this :

type: custom:mushroom-chips-card
chips:
  - type: back
  - type: entity
    entity: timer.countdown_streaming_camera_garagedeur
    tap_action:
      action: call-service
      service: script.sensor_garagedeur_start_countdown_streaming
      data: {}
      target: {}
    use_entity_picture: false
  - type: template
    entity: timer.countdown_streaming_camera_garagedeur
    content: >-
      {{ state_attr('timer.countdown_streaming_camera_garagedeur', 'remaining')
      }}
    tap_action:
      action: call-service
      service: script.sensor_garagedeur_start_countdown_streaming
      data: {}
      target: {}

The first gives me the state (“active/idle”), the second the duration of the timer.

This gives me what I want, but is not mushroom :slight_smile:

type: entities
entities:
  - entity: timer.countdown_streaming_camera_garagedeur
    name: Streaming garage door

You’d have to look at the end time when its active and calculate it.

So I have to made a sensor ?

What should I use as start time (now, I made use of the time when script which start the timer was last triggered) ?

- trigger:
    - platform: time_pattern
      seconds: "/1"    
  sensor:
    - name: timer_countdown_streaming_camera_garagedeur_remaining
      state: >
        {%- if (states['timer.countdown_streaming_camera_garagedeur'].attributes.duration == "none") or (states['timer.countdown_streaming_camera_garagedeur'].state == "idle") -%}
        {{ 0 | int }}
        {%- else -%}
        {% set duration_seconds = ((states['timer.countdown_streaming_camera_garagedeur'].attributes.duration).split(':')[0] |int * 60 * 60) + ((states['timer.countdown_streaming_camera_garagedeur'].attributes.duration).split(':')[1] |int * 60 ) + ((states['timer.countdown_streaming_camera_garagedeur'].attributes.duration).split(':')[2] |int) %}
        {% set last_triggered =
              state_attr('script.sensor_garagedeur_start_countdown_streaming','last_triggered') or
              now() %} 
        {{ (duration_seconds - ( now() - last_triggered).total_seconds()) | timestamp_custom('%H:%M:%S', 0) }}
        {%- endif -%}

{% set timer = 'timer.kitchen_auto_off_timer' %}
{% if state_attr(timer,'finishes_at') %}
  {{(as_timestamp(state_attr(timer,'finishes_at'))-as_timestamp(now()))|int}}
{% else %}
  0
{% endif%}

Seconds left on the timer for example…

EDIT: Handle None

That’s a lot easier :slight_smile:

Thank you very much, you made my day !

This would also work and is shorter. shrugs (Fixed)

{% set f = state_attr('timer.auto_arm_time', 'finishes_at') %}
{{ iif(f != None,(as_timestamp(f,0)-as_timestamp(now()))|int,0) }}
2 Likes

Very nice ! :ok_hand:

I believe this short version requires the addition of a default value for the as_timestamp function on the state_attr(timer,'finishes_at') to avoid an error when the timer is idle and therefor has no finishes_at
The long version works fine without.

{% set timer = 'timer.kitchen_auto_off_timer' %}
{{ iif(state_attr(timer,'finishes_at'),(as_timestamp(state_attr(timer,'finishes_at'),0)-as_timestamp(now()))|int,0) }}

Yes that’s correct. :white_check_mark:

I believe this fixes it though.

{% set f = state_attr('timer.auto_arm_time', 'finishes_at') %}
{{ iif(f != None,(as_timestamp(f,0)-as_timestamp(now()))|int,0) }}

or

{% set timer = 'timer.auto_arm_time' %}
{% set f = state_attr(timer, 'finishes_at') %}
{{ iif(f != None,(as_timestamp(f,0)-as_timestamp(now()))|int,0) }}

or which I think is most readable.

{% set t = 'timer.auto_arm_time' %}
{% set f = state_attr(t, 'finishes_at') %}
{% set s = (as_timestamp(f,0)-as_timestamp(now()))|int %}
{{ iif(f != None,s,0) }}

This will handle if the timer is PAUSED as well rather than just showing zero if it was paused.

{% set t = 'timer.kitchen_auto_off_timer' %}
{% set fin = state_attr(t, 'finishes_at') %}
{% set rem = state_attr(t, 'remaining') %}
{% set fsec = as_timestamp(fin,0)-as_timestamp(now()) %}
{% set rsec = as_timedelta("0 " ~ rem).seconds %}
{{ iif(fin == None,iif(rem == None,0,rsec),fsec)|int(0) }}

That’s long ago…

I made this :

        {% set timer = 'timer.countdown_streaming_camera_garagedeur' %}
        {% if (states[timer].attributes.duration == "none") or (states[timer].state == "idle") %}
          {{0| timestamp_custom('%H:%M:%S', 0)}}
        {% else %}
          {{((as_timestamp(state_attr(timer,'finishes_at'))-as_timestamp(now()))|int)| timestamp_custom('%H:%M:%S', 0)}}
        {% endif%}

I think that fails with a paused timer

This won’t.

{% set t = 'timer.kitchen_auto_off_timer' %}
{% set state = states(t) %}
{% set finish = state_attr(t, 'finishes_at') %}
{% set remain = state_attr(t, 'remaining') %}
{% set seconds = (as_timestamp(finish,0)-as_timestamp(now()))|int %}
{% set left = iif(finish == None,iif(remain == None,0,as_timedelta('0 ' ~remain).seconds),seconds) %}
{{ left| timestamp_custom('%H:%M:%S', 0) }}

EDIT: Corrected mistake.

Correct…I didn’t have the problem cause my timer never pauses :upside_down_face:

For the sport I tried your code, but I get an error when the timer is paused :

I changed the last line and now it’s always working :wink: :

    - name: timer_countdown_streaming_camera_garagedeur_remaining
      state: >
        {% set t = 'timer.countdown_streaming_camera_garagedeur' %}
        {% set state = states(t) %}
        {% set finish = state_attr(t, 'finishes_at') %}
        {% set remain = state_attr(t, 'remaining') %}
        {% set seconds = (as_timestamp(finish,0)-as_timestamp(now()))|int %}
        {% set left = iif(finish == None,iif(remain != None,remain,0),seconds) %}
        {% if finish == None and remain != None %}
          {{ left }}
        {% else %}
          {{ left| timestamp_custom('%H:%M:%S', 0) }}
        {% endif %}

2 Likes

I pasted the wrong thing. This is what I meant to paste. Had multiple browsers open.

{% set t = 'timer.kitchen_auto_off_timer' %}
{% set state = states(t) %}
{% set finish = state_attr(t, 'finishes_at') %}
{% set remain = state_attr(t, 'remaining') %}
{% set seconds = (as_timestamp(finish,0)-as_timestamp(now()))|int %}
{% set left = iif(finish == None,iif(remain == None,0,as_timedelta('0 ' ~remain).seconds),seconds) %}
{{ left| timestamp_custom('%H:%M:%S', 0) }}  

Regardless, what’s with all the “:upside_down_face:” “:wink:”. Comes across so nasty. Really makes people not want to share. :kissing_heart:

But thanks for the correction as the entire point of my post was to correct my code for the next reader.

I joke a lot in life, which “written” is sometimes misinterpreted. So sorry if it came across that way, I really didn’t mean to hurt you or make fun of you in any way.

Meanwhile I tested it and it works fine ! Thanks !

4 Likes

The template is working but refreshes only every 30 sec. on the frontend. Any soltion to show the seconds in realtime?

Steffen

Add a trigger :

- trigger:
    - platform: time_pattern
      seconds: "/1"
  sensor:
    - name: timer_countdown_streaming_camera_garagedeur_remaining
      state: >
        {% set t = 'timer.countdown_streaming_camera_garagedeur' %}
        {% set state = states(t) %}
        {% set finish = state_attr(t, 'finishes_at') %}
        {% set remain = state_attr(t, 'remaining') %}
        {% set seconds = (as_timestamp(finish,0)-as_timestamp(now()))|int %}
        {% set left = iif(finish == None,iif(remain == None,0,as_timedelta('0 ' ~remain).seconds),seconds) %}
        {{ left| timestamp_custom('%H:%M:%S', 0) }}  

1 Like

Why it is so complicated, the normal entity card shows the remaining time by default. Can the remaining time not be provided as secondary info?

4 Likes

Curious about this… I noticed the attributes reported on my timer are completely wrong. Is there a setting somewhere in HA that I missed?

For example, my coffee timer is currently active, with almost 2 hours remaining:

…but if I look at the attributes, the “remaining time” is the same as the “duration,” and the “finishes_at” time is this afternoon (in about 7 hours):
Screen Shot 2023-02-06 at 8.56.47 AM

Thoughts? Ideas?

I’d love to add this to my code; where would I include it? Does this go in my config somewhere? The formatting doesn’t look like any of my other sensor templates:

  - platform: template
    sensors:
      sensor_name:
        value_template: >-

Create a new file templates.yaml and put this in the file:

image

In your configuration.yaml file add this :

template: !include templates.yaml