Timers / read only sliders
Jab2870 opened this issue ยท 9 comments
Is your feature request related to a problem? Please describe.
I currently use the timer-bar-card to display the amount of time an entity has been "on", when that entity turns itself off after a predefined time. This feels similar to the Spotify seeking example given in the readme.
This is what I am hoping to re-create:
Describe the solution you'd like
The "value" of the slider I would like to be templateable, allowing me to get how long an entity has been on, and for the slider to be set to be read only / not draggable.
Describe alternatives you've considered
I am currently using the custom:timer-bar-card card, although am trying to move to tile cards where possible.
Additional context
type: custom:service-call
entries:
- type: slider
range:
- 0
- '{{ states("number.heating_downstairs_timeout") }}'
thumb: line
value: '{{as_timestamp(now()) - as_timestamp(switch.heating_downstairs_relay.last_changed) | float}}'
I am aware that the value
option I've used here isn't anywhere. As far as I can tell, value_attribute
is used everywhere. However, given this isn't an attribute on the entity, I felt maybe it wasn't appropriate to overload that option.
value_attribute
refers to the attribute (or just state
) that should be used for the custom tile features internal value and wouldn't be used like that, but I get what you mean.
I should be able to calculate the current timer value and have the slider update to accurately display that. I don't want to make the slider not do anything when tapped by default, but should also add some logic so that it does nothing if tap_action.action
is none
or not set.
I've got timers working as of the latest alpha with this config:
type: tile
entity: timer.timer_test
features:
- type: custom:service-call
entries:
- type: slider
value_attribute: elapsed
thumb: flat
slider_style:
height: 10px
width: 90%
justify-content: flex-end
right: 0px
background_style:
height: 10px
border-radius: 12px
width: 90%
right: 0px
label_style:
justify-content: flex-start
style:
height: 12px
border-radius: 0px
flex-direction: row
label: |-
{% set minutes = (VALUE / 60) | int %}
{% set seconds = VALUE - 60*minutes %}
{{ minutes }}:{{ 0 if seconds < 10 else "" }}{{ seconds | int }}
step: 1
range:
- 0
- >-
{% set hms = state_attr("timer.timer_test", "duration").split(":")
%}
{{ (hms[0] |int ) * 3600 + (hms[1] | int) * 60 + (hms[2] | int)
}}
- type: custom:service-call
entries:
- type: button
icon: mdi:timer-check
tap_action:
action: call-service
service: timer.start
target:
entity_id: timer.timer_test
- type: button
icon: mdi:timer-pause
tap_action:
action: call-service
service: timer.pause
target:
entity_id: timer.timer_test
- type: button
icon: mdi:timer-cancel
tap_action:
action: call-service
service: timer.cancel
target:
entity_id: timer.timer_test
elapsed
isn't an actual attribute, but I'm using it as a fake one just for timers so other attributes can be accessed by users as needed.
TODO:
- Make slider do nothing and not change position or value if
tap_action.action
isnone
. - Figure out what's causing the render delay.
- Probably due to value not being set until the interval delay happens, I should set the value once before setting the interval.
That is fantastic, thank you for implementing this so quickly!
I have not yet experimented, but will do after work. However, from reading your code, it does appear that I would need to use Home Assistant's timer entities for the elapsed
value_attribute to work. Is that correct?
That certainly works for one of my use cases, but a number of my devices implement the timer onboard, rather than using Home Assistant's timers. My heating for example, consists of a relay and a timeout
The heating controller turns it off after an hour, without relying on home assistant's timers.
That is why I used the template {{as_timestamp(now()) - as_timestamp(switch.heating_downstairs_relay.last_changed) | float}}
in my example.
That template wouldn't have worked anyway, since templates only update when entities change. I wouldn't be able to make value update frequently without a lot of additional specialized logic, and there's a lot of logic around slider values that would be difficult to make user customizable.
Why not create an automation that sets a timer using the heating controller information?
alias: Heating Timer Trigger
description: ""
trigger:
- platform: state
entity_id:
- switch.heating_downstairs_relay
to: "on"
from: "off"
condition: []
action:
- service: timer.start
target:
entity_id: timer.heating_downstairs
data:
duration: >-
{% set seconds = states("number.heating_downstairs_timeout") %}
{% set minutes = (seconds / 60) | int %}
{% set seconds = seconds - 60 * minutes %}
{% set hours = (minutes / 60) | int %}
{% set minutes = minutes - 60 * hours %}
{{ '%02d' % hours }}:{{ '%02d' % minutes }}:{{ '%02d' % seconds }}
mode: single
Fixed the late rendering and made the slider not interactable if tap_action.action
is set to none
. Here's an even better read only timer slider config:
features:
- type: custom:service-call
entries:
- type: button
value_attribute: elapsed
label: >-
{% set minutes = (VALUE / 60) | int %} {% set seconds = (VALUE - 60 *
minutes) | int %} {{ minutes }}:{{ 0 if seconds < 10 else "" }}{{
seconds | int }}
style:
overflow: visible
height: 12px
border-radius: 0px
'--color': none
- type: slider
tap_action:
action: none
value_attribute: elapsed
thumb: flat
style:
flex-basis: 1200%
height: 10px
'--tooltip-label': >-
{% set minutes = (VALUE / 60) | int %} {% set seconds = (VALUE - 60
* minutes) | int %} {{ minutes }}:{{ 0 if seconds < 10 else "" }}{{
seconds | int }}
step: 1
range:
- 0
- >-
{% set hms = state_attr(config.entity, "duration").split(":") %} {{
(hms[0] |int ) * 3600 + (hms[1] | int) * 60 + (hms[2] | int)
}}
- type: button
value_attribute: duration
label: '{% set hms = VALUE.split(":") %} {{ hms[1] | int }}:{{ hms[2] }}'
style:
overflow: visible
height: 12px
border-radius: 0px
'--color': none
- type: custom:service-call
entries:
- type: button
icon: mdi:timer-check
tap_action:
action: call-service
service: timer.start
target:
entity_id: timer.timer_test
- type: button
icon: mdi:timer-pause
tap_action:
action: call-service
service: timer.pause
target:
entity_id: timer.timer_test
- type: button
icon: mdi:timer-cancel
tap_action:
action: call-service
service: timer.cancel
target:
entity_id: timer.timer_test
type: tile
entity: timer.timer_test
As for supporting devices that have internal timers but do not have timer entities - I don't think there's a good way to do so in a standardized way. The implementation wouldn't be standard across all devices, and the devices aren't using the same entity or attribute names or time formats. Like your heater doesn't provide a finishes at datetime or a remaining time sensor.
It should be possible to create timer helpers from the existing heater entities, and those should work with this card now.
@Jab2870 if you're okay with creating timer helpers for internal device timers, then the latest 3.3.2 beta should be the release candidate for this feature.