Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow state: {fixed: 'active'} instead of using an entity #140

Merged
merged 2 commits into from
Apr 10, 2024

Conversation

SLaks
Copy link
Contributor

@SLaks SLaks commented Apr 1, 2024

This refactors a bunch of the card code to make state objects optional.

It also makes accessors consistent.

@SLaks
Copy link
Contributor Author

SLaks commented Apr 1, 2024

image

To use this with Google Home timers, install the following cards from HACS:

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.

@SLaks SLaks marked this pull request as draft April 1, 2024 15:36
@SLaks SLaks marked this pull request as ready for review April 1, 2024 15:37
This refactors a bunch of the card code to make `state` objects optional.

It also makes accessors consistent.
@rianadon
Copy link
Owner

rianadon commented Apr 3, 2024

Thanks so much! That's quite the hefty PR. I'll take a read though it this weekend.

@SLaks
Copy link
Contributor Author

SLaks commented Apr 3, 2024

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.

@rianadon
Copy link
Owner

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!

@rianadon rianadon merged commit dbfa170 into rianadon:main Apr 10, 2024
1 of 2 checks passed
@dnestico
Copy link

dnestico commented May 19, 2024

Finally this works! But not sure why it won't display the name of the device with the active timer for me, weird.
Screenshot 2024-05-18 at 9 15 54 PM

@SLaks
Copy link
Contributor Author

SLaks commented May 19, 2024

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.

@dnestico
Copy link

dnestico commented May 19, 2024

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', '') -%}
Screenshot 2024-05-19 at 7 58 26 PM

@SLaks
Copy link
Contributor Author

SLaks commented May 20, 2024

The second one (which contains else).

The first line is currently unused; I just edited the instructions to fix that.

@dnestico
Copy link

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

@SLaks
Copy link
Contributor Author

SLaks commented May 21, 2024

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.

@dnestico
Copy link

dnestico commented May 21, 2024

Ok so this is the new code? thanks.

      {%- set suffix =  ' – ' + state_attr(entity_id, 'friendly_name')
                      | replace(' timers', '') -%}

@SLaks
Copy link
Contributor Author

SLaks commented May 21, 2024

Exactly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants