Templating help - Show remaining time in HH:MM of timer

Full disclosure: I know nothing about that particular custom card.

My guess is that the Entities card calculates the remaining time exclusively in the frontend. I would imagine that any card can be designed to replicate that behavior; it only requires the finishes_at value and the current time (with one-second resolution). Again, just a guess because I don’t currently have the time to inspect the card’s code.

It uses templates, but with javascript. It just outputs the result of the template. He’s most likely grabbing the state from the state machine. I.e. he’d have to build the HTML that displays the information properly but he most likely doesn’t have access to it in the templating machine built into the card.

Ah! Understood. It’s a generalist and not really within its mission to give any particular entity special handling (like “show timer’s remaining time”).

right, you probably can do it though if you had access to the frontend toolkit within the template itself. Not sure if that’s a thing for that card or not.

Unfortunately it doesn’t show me the remaining time in the entity card, only “active”.

The example I posted is for the Entities card, not the Entity card.

The Entities card displays an active timer’s remaining time. An Entity card doesn’t.

Hi togehter,

my dishwasher had only this entity:

sensor.401030425339002116_bsh_common_option_remainingprogramtime

no attributes. it shows this as Time: 2023-03-05T11:54:32+00:00

How can i this as contdown? for example: Dishwasher ist ready in 03:12:00 (hh:mm:ss)

Can someone help me, pls?

Thanks

I just found it myself. I solved as follows:

sensor:

  • platform: template
    sensors:
    dishwasher finish:
    value_template: >
    {% set ct = states(‘sensor.401030425339002116_bsh_common_option_remainingprogramtime’) | as_datetime %}
    {{ ‘00:00’ if now() > ct else (ct - now()).total_seconds() | timestamp_custom(’%H:%M’, false) }}

2023-04-03T22:00:00Z

IMPORTANT!! replace ’ to " !

{% set ct = states(“sensor.401030…”)
{{"'00:00" if now() > ct else (ct - now()).total_seconds() | timestamp_custom("%H:%M", false) }}

1 Like

Would you share your code please? I am trying to achieve exactly the same… THANKS!
Showing remaining timer time of a fan/light in a custom button card that turns it on - Configuration / Frontend - Home Assistant Community (home-assistant.io)

I’m fascinated that no one seems to mind that the countdown timer doesn’t show a remaining countdown time in state, nor even atribute, but only if it’s active or not. It’s so illogical, that I would like to meet the guy who did it. :slight_smile: Imagine you get task to create timer and you do not think the remaining time is most relevant. I´m sorry.

3 Likes

You don’t want that value changing in an attribute, you’ll have a database change every second if you do. That’s why it’s done in the frontend. If you want a countdown, make a template sensor that has the value of the ending time as a state. Wherever you put it in the UI will show it’s countdown, live.

1 Like

Understand what you are saying and the decision about timer was made that it has limited purpose. I would expect from timer as a click option to show remaining time because the database can handle this as nothing when you use it for minutes, once in a while and it should be up to the user to choose from, to help him and save his time. Now to the logic workaround with templates.

You wrote: If you want a countdown, make a template sensor that has the value of the ending time as a state. Wherever you put it in the UI will show it’s countdown, live.

template: 
  - sensor:
      - name: "countdown"
        state: >
            {% set fin = state_attr('timer.countdown', 'finishes_at') %}
            {{ '00' if fin == None else  as_datetime(fin).astimezone().time() }}

Above it is, the ending time. Anywhere in card I put it I see ending time what is logical, not remaining time as you wrote. Only timer itself in only one type card of entities showing remaining time. So foreground countdown not much from it.

Working solution as you wrote above with writing to database:

template: 
  - sensor:
      - name: "countdown2"
        state: >
            {% set fin = state_attr('timer.countdown', 'finishes_at') %}
            {{ '00' if fin == None else  (as_datetime(fin) - now()).total_seconds() | timestamp_custom('%M:%S', false) }}

Now I can send via mqtt the remaining time via sensor.countdown2 to electronic clock display.
But yes, I can save the writting to database using calculation directly in mqtt payload:

payload: "{{ (as_datetime(state_attr('timer.countdown', 'finishes_at')) - now()).total_seconds() | timestamp_custom('%M:%S', false) }}"

Plus automatisation to set duration from input to timer.
Plus automatisation to update remaining / send via mqtt.

also if anybody will find it usefull:
I can take duration from input_datatime like this:
{% set dur = strptime(states('input_datetime.minutka'), "%H:%M:%S") %}
I can create final time like this:
{% set fin = (now() + timedelta(hours = dur.hour, minutes = dur.minute)) %}
but in template sensor it would be updated as time goes, not once with manual trigger:

template: 
  - sensor:
      - name: "finaltime"
        state: >
	    {% set dur = strptime(states('input_datetime.minutka'), "%H:%M:%S") %}
            {{ now() + timedelta(hours = dur.hour, minutes = dur.minute) }}
  - sensor:
      - name: "countdown"
        state: >
            {% set fin = states('sensor.finaltime') %}
            {{ (as_datetime(fin) - now()).total_seconds() | timestamp_custom('%M:%S', false) }}

So I learned a lot again, which I will forget until next time. Again, I thought I’d use the timer helper and it would save me hours of searching, learning to write, but as every HA user knows, if you want something, carve it out.

Thank you petro for helping.

Show remaining time of a timer in minutes and seconds as a badge in the frontend

FWIW, I show the remaining time by embedding a custom:button-card inside another custom:button-card like this:

              - type: 'custom:button-card'
                entity: switch.office_bath_light
                name: 'Bath Light'
                variables:
                  timer_var: "timer.office_bath_light"
                template: 
                  - base_card
                  - timer_template

button_card_templates:
  base_card:
    state_color: true
    show_label: true
    tap_action:
      action: toggle
    styles:
      card:
        - border-radius: 6px
        - height: 70px
        - margin: 3px
        - padding: 8px
      grid:
        - grid-template-areas: '"i timer" "n n"'
        - grid-template-rows: 40px 1fr
        - grid-template-columns: 40px 1fr
      img_cell:
        - align-self: start
        - text-align: start
        - justify-self: start
        - place-self: start
        - margin-right: 20px
      icon:
        - align-self: start
        - justify-self: start
        - height: 30px
        - width: 30px
      name:
        - justify-self: center
        - font-size: 13px
        - margin: 0
      label:
        - align-self: end
        - justify-self: end
        - font-size: 12px
      custom_fields:
        timer:
          - justify-self: end
          - align-self: start
          - font-size: 13px

  timer_template:
    variables:
      timer_var: "placeholder"
    triggers_update: all
    custom_fields:
      timer:
        card:
          type: custom:button-card
          entity: '[[[ return variables.timer_var ]]]'
          show_name: false
          show_icon: false
          show_state: true
          styles:
            card:
              - font-size: 12px
              - box-shadow: none
              - background-color: "transparent"
              - border: none
            state:
              - color: 'red'
              - opacity: >
                  [[[
                    return states[variables.timer_var].state === 'idle' ? '0' : '1';
                  ]]]

Hi @vonagio @123 @petro
I`ve made this sensor to show the remaining time based of the choosen program. If the dishwasher is powered on the sensor will display the time remaining of the program if the dishwasher is powered off the sensor will display " : -:-- "
Here is the sensor:

- platform: template
    sensors:
      remaining_time:
        friendly_name: "Remaining Time"
        value_template: >
            {% if states('sensor.402110526515021364_bsh_common_option_remainingprogramtime') == 'unavailable' %}  -:--
            {% elif (as_timestamp(states('sensor.402110526515021364_bsh_common_option_remainingprogramtime'))) >0  %}
            {% set sec = as_timestamp(states('sensor.402110526515021364_bsh_common_option_remainingprogramtime'))-as_timestamp(now()) %}
            {%set hr = (sec / 3600) | int %}
            {%set min = sec / 60 - hr * 60%} 
            {% if hr > 0 and is_state('switch.402110526515021364_bsh_common_setting_powerstate', 'on' ) %}
              {{"%d:%02d" % (hr, min + 1)}}  
            {% elif sec | round(1, default=0) <0  %}  
              -:--
            {%elif is_state('switch.402110526515021364_bsh_common_setting_powerstate', 'on' )%}
              {{"%d:%02d" % (hr, min + 1)}}
            {%else%}
              -:--
            {% endif %}
            {% endif %}

Hope this will work also for you

Also see this

Thanks, but that still won’t update once a second. Not only that, but the code can be optimized as well.

template:
- trigger:
  - platform: time_pattern
    seconds: "/1"
  sensor:
  - name: Remaining Time
    state: >
      {% set entity_id = 'sensor.402110526515021364_bsh_common_option_remainingprogramtime' %}
      {% if entity_id | has_value and is_state('switch.402110526515021364_bsh_common_setting_powerstate', 'on') %}
        {% set td = states(entity_id) | as_datetime | as_local - now() %}
        {{ "%d:%02d" % (td.seconds // 3600, td.seconds // 60 % 60) }}
      {% else %}
        -:--
      {% endif %}

If you don’t care about the second updates…

template:
- sensor:
  - name: Remaining Time
    state: >
      {% set entity_id = 'sensor.402110526515021364_bsh_common_option_remainingprogramtime' %}
      {% if entity_id | has_value and is_state('switch.402110526515021364_bsh_common_setting_powerstate', 'on') %}
        {% set td = states(entity_id) | as_datetime | as_local - now() %}
        {{ "%d:%02d" % (td.seconds // 3600, td.seconds // 60 % 60) }}
      {% else %}
        -:--
      {% endif %}

Hi Richard
I like the idea, but I can’t figure out where to define the timer_template and button_card_templates in order to use them.
Can you please elaborate on that.
BR Poul Anker

Button card templates are documented here

1 Like

:+1: really appreciate your answer.

Thank You for posting your code. It helped me to implement my countdown sensor.

There is a typo in this line. Should be

{{ "%d:%02d" % (td.seconds // 3600, td.seconds // 60 % 60) }}
1 Like