Closed SLaks closed 3 months ago
To use this with Google Home timers, install the following cards from HACS:
extend_paper_buttons_row
object)
Then paste the following card YAML (no custom sensors needed):type: custom:auto-entities
filter:
template: >
{%- set results = namespace(timers = []) -%}
{%- set state_map = {
"set": "active",
"ringing": "active",
} -%} {%- set icon_map = {
"set": "mdi:timer",
"ringing": "mdi:timer-alert",
"paused": "mdi:timer-pause",
} -%} {%- for entity_id in integration_entities('google_home') if entity_id
is contains '_timers' -%}
{%- set multiple = not loop.first or not loop.last -%}
{%- set suffix = '' if not multiple
else ' – ' + state_attr(entity_id, 'friendly_name')
| replace(' timers', '') -%}
{%- for t in state_attr(entity_id, 'timers') -%}
{%- set label = t.label if t.label else t.duration | regex_replace('^0:0*', '') + ' timer' -%}
{%- set results.timers = results.timers + [{
'icon': icon_map[t.status],
'duration': {'fixed': t.duration},
'end_time': {'fixed': t.local_time_iso},
'name': label + suffix,
'state': {'fixed': state_map[t.status] | default(t.status)},
"extend_paper_buttons_row": {
"position": "right",
"buttons": [
{
"icon": "mdi:close",
"tooltip": "Dismiss",
"tap_action": {
"action": "call-service",
"service": "google_home.delete_timer",
"service_data": {
"timer_id": t.timer_id,
"entity_id": entity_id,
"skip_refresh": False,
}
}
}
]
}
}] -%}
{%- endfor -%}
{%- endfor -%} {{ results.timers }}
card:
type: custom:timer-bar-card
show_empty: false
This will generate one row per timer on every Google Home device in HA; if you have multiple Google Homes, each timer will also be labeled with its device.
Thanks so much! That's quite the hefty PR. I'll take a read though it this weekend.
Yes; there is no way to make this shorter.
FYI, for the future, I recommend building this kind of code in 2 separate parts: A model class that takes the config and exposes resolved properties (eg, name, total and remaining time), and the card layout code that consumes the model only. This keeps the config system separate from the rendering, and would mean that a change like this one wouldn't touch the rendering code at all.
Yeah that's great advice. If I had to redo this card that would be a great way to structure it. This card originated just as me uploading the timer part of my opensprinkler card to a separate repository. I never expected it to grow this much.
The PR overall looks great. Thanks so much for writing this!
Finally this works! But not sure why it won't display the name of the device with the active timer for me, weird.
My code above only adds the device name if there are multiple Google Home devices.
To always add the device name, remove '' if loop.first and loop.last else
Also check whether it's getting truncated.
I did CTRL-F and found 2 of those lines in the code, not sure exactly what I need to change sorry.
{%- set multiple = not loop.first or not loop.last -%}
{%- set suffix = '' if loop.first and loop.last
else ' – ' + state_attr(entity_id, 'friendly_name')
| replace(' timers', '') -%}
The second one (which contains else
).
The first line is currently unused; I just edited the instructions to fix that.
Ok so I just tried doing this updated code and the card just disappears with it unfortunately doesn't work....
type: custom:auto-entities
filter:
template: >
{%- set results = namespace(timers = []) -%}
{%- set state_map = {
"set": "active",
"ringing": "active",
} -%} {%- set icon_map = {
"set": "mdi:timer",
"ringing": "mdi:timer-alert",
"paused": "mdi:timer-pause",
} -%} {%- for entity_id in integration_entities('google_home') if entity_id
is contains '_timers' -%}
{%- set multiple = not loop.first or not loop.last -%}
# {%- set suffix = '' if not multiple
# else ' – ' + state_attr(entity_id, 'friendly_name')
# | replace(' timers', '') -%}
{%- for t in state_attr(entity_id, 'timers') -%}
{%- set label = t.label if t.label else t.duration | regex_replace('^0:0*', '') + ' timer' -%}
{%- set results.timers = results.timers + [{
'icon': icon_map[t.status],
'duration': {'fixed': t.duration},
'end_time': {'fixed': t.local_time_iso},
'name': label + suffix,
'state': {'fixed': state_map[t.status] | default(t.status)},
"extend_paper_buttons_row": {
"position": "right",
"buttons": [
{
"icon": "mdi:close",
"tooltip": "Dismiss",
"tap_action": {
"action": "call-service",
"service": "google_home.delete_timer",
"service_data": {
"timer_id": t.timer_id,
"entity_id": entity_id,
"skip_refresh": False,
}
}
}
]
}
}] -%}
{%- endfor -%}
{%- endfor -%} {{ results.timers }}
card:
type: custom:timer-bar-card
show_empty: false
I don't mean comment out those lines; I mean delete literally '' if loop.first and loop.last else
(to make it unconditional) and nothing else.
Ok so this is the new code? thanks.
{%- set suffix = ' – ' + state_attr(entity_id, 'friendly_name')
| replace(' timers', '') -%}
Exactly
This refactors a bunch of the card code to make
state
objects optional.It also makes accessors consistent.