Lovelace: Button card

I keep confusing myself with Javascript inside the YAML to configure a button-card. The following does not work, any hints?

            spin: >-
              [[[
                switch (variables.speed) {
                  case "1":
                  case "2":
                  case "3":
                  case "turbo":
                    return "true";
                  default:
                    return "false";
                }
              ]]]

The variable speed is defined and contains changing states. The frontend behaves as if I were always returning true. I suspect that this is because it returns a string which is then interpreted as true for spin:

Actually, this reduces to the following not working:

spin: '[[[ return false ]]]'

Of course!! Blinded myself thereā€¦
Now same issue but with the border-radius. I have to click it or change song to get i to update
2021-01-12_14h05_56

                      card:
                        type: custom:stack-in-card
                        mode: vertical
                        keep:
                          background: true
                          border-radius: true
#Country mood                                     
                              - type: custom:button-card
                                name: Country<br>mood
                                icon: mdi:spotify
                                color_type: card
                                color: white                                
                                show_icon: true
                                show_name: true
                                show_state: false
                                triggers_update:
                                  ['[[[ return entity.entity_id ]]]']
                                tap_action:
                                  action: call-service
                                  service: media_player.select_source
                                  service_data:
                                    entity_id: '[[[ return entity.entity_id ]]]'
                                    source: 'Country mood'                                      
                                styles:
                                  card:
                                    - width: 5.6em
                                    - height: 5.6em
                                    - margin: 0px 3px 0px 3px
                                    - border-radius: 25px
                                    - color: white
                                  name:
                                    - justify-self: start
                                    - padding-left: 10px
                                    - color: black
                                    - font: SF-text
                                  icon:
                                    - icon-size: 30px
                                    - color: black
                                    - margin-top: -5px 

spin: '[[[ return false ]]]'

Hm, I guess I can answer my own question after some more reading. It looks like the spin: doesnā€™t allow javascript templates. Iā€™ll lodge that as a feature request.

Edit: please check this if you run across the same challenge:
make spin templatable Ā· Issue #355 Ā· custom-cards/button-card (github.com)

you are aware you can do something like this:

    state:
      - operator: template
        value: >
          [[[ return (states['sensor.count_alerts_notifying'].state > 0) ]]]
        spin: true

or

state:
  - operator: template
    value: >
       [[[ return entity.state == 'Aan'; ]]]
    spin: true

?

@Mariusthvdb: yes, thanks. In the specific case the state: is not appropriate to use. To be more precise, I have a button that can take an on/off state plus seven other states for the speed setting of a fan at the same time. Only four of these seven states have a spinning icon.

To make it more complicated, I use button-card templates for on/off states with id:. As I just learnt, these id: templates are meant to be applied only to one state. So I reduced all the combinations of states to just two, on and off. For those I use the id:. All the rest is configured with javascript templates, which works well for the icon: and style: but just not for spin: as I had to find out the hard way.

To template spin you can use css.
spin is a shortcut of animation: rotating 2s linear infinite

so for your use case, what you can do is

styles:
  icon:
    - animation: |
        [[[
          switch (variables.speed) {
            case "1":
            case "2":
            case "3":
            case "turbo":
              return "rotating 2s linear infinite";
            default:
              return null;
          }
        ]]]
1 Like

Please read the documentation about stack-in-card, itā€™s all there: https://github.com/custom-cards/stack-in-card/blob/master/README.md#keep-object

(Hint: border_radius: true)

Thanks for the hint, ā€œ-ā€ instead of ā€œ_ā€!!

FML, sorry.

Thanks again

hi at all!
iā€™m becoming crazy to solve an alignment problemā€¦
I want to achieve this result (similar to standard entity rowā€¦)

dining

icon + name + value (icon__dining room _________ON)

someone could point me in the right direction ???
this is my code:

color_type: icon
entity: light.dining_room
name: LED
show_label: false
show_state: true
show_name: false
show_icon: true
layout: icon_name_state
type: 'custom:button-card'
styles:
  card:
    - height: 50px
  grid:
    - grid-template-columns: min-content min-content
    - width: min-content
    - grid-gap: 0px 409px
  name:
    - color: '#ffffff'
    - font-size: 15px
    - font-weight: 400

thanks a lot

ok, you have to find out which config suits your situation best. As always, there are more ways than 1 to reach the same goal:

button_updater:
  template: button_body
  styles:
    icon:
      - color: >
          [[[ if (entity.state == 'on') return 'green'; return 'grey'; ]]]
      - animation: >
          [[[ if (entity.state == 'on') return 'rotating 2s ease infinite'; ]]]
    state:
      - color: >
          [[[ if (entity.state == 'on') return 'green'; return 'grey'; ]]]
      - animation: >
          [[[ if (entity.state == 'on') return 'blink 2s ease infinite'; ]]]

#button_updater:
#  template: button_body
#  state:
#    - value: 'on'
#      styles:
#        icon:
#          - color: green
#          - animation: rotating 2s ease infinite
#        state:
#          - color: green
#          - animation: blink 2s ease infinite
#    - operator: default
#      styles:
#        icon:
#          - color: grey
#        state:
#          - color: grey

button-card is so versatile, you never stop discovering its possibilities.
button-card templates are amazing, and the global variables a huge help in minimizing code. traditional yaml anchors too:

  tap_action:
    <<: &action
      action: more-info
      entity: >
        [[[ return 'group.' + variables.id; ]]]
    haptic: light
  hold_action:
    <<: *action
    haptic: success

or, when tap and hold could be identical:

  tap_action: &action
    action: more-info
    entity: >
      [[[ return 'group.' + variables.id; ]]]
    haptic: light
  hold_action: *action

have fun!

1 Like

Thanks, @Mariusthvdb, @RomRider and all the other here for all the great help and support. The custom:button-card really is amazing. I combined it with @thomasloven custom:state-switch and custom:card-mod to leverage @betaboonā€™s fresh attempt at integrating the Philips air purifiers. Adding on top some self-made icons (what an act to get that right). Here is what my card looks like:

High air quality, auto fan speed, display light on and humidification activated Somewhat lower air quality, night mode, display light off and humidification deactivated

The glowing ring follows the Philips design of indicating air freshness according to IAI values. It changes it color with air quality. The icons on top signal when filter changes are needed or the water of the humidifier is low. Note that some of those are deactivated when the humidification is switched off. They change from green to orange to red (when they also start blinking). The readings in the middle give me some stats of the device. Nothing is clickable in the upper part.

The four buttons are a bit Homekit style and control the device. They can have a combination of states: they all go dark when off, but some also cycle through the modes of, e.g. fan speed. The cycling changes the icons. Here is where I struggled quite a bit with state logic in combination with templating.

Overall, I made quite some use of the button-card templates and variables, which came in very handy.

Here is how I did it:

In the configuration.yaml I integrate the air purifier using the fork of @betaboon as mentioned above (it works better with encrypted coap devices):

# Philips Air Purifier
fan:
  - platform: philips_airpurifier
    host: !secret philips_ac2889_host
    model: ac2889
    name: air_ac2889

  - platform: philips_airpurifier
    host: !secret philips_ac2729_host
    model: ac2729
    name: air_ac2729

As I have two devices, I tried to develop the card in a flexible way that can deal with both devices gracefully, even though the AC2889 doesnā€™t have the humidification function. That requires a bit of testing and switching. Also, the entity variable comes in quite handy to keep it abstract, as youā€™ll see below. Iā€™ll show the code for the AC2729 device which corresponds to the screenshots above. The main card essentially is a vertical-stack with button-cards inside:

type: vertical-stack
layout: horizontal
cards:
  - type: 'custom:button-card'
    icon: 'custom:circle'
    entity: fan.air_ac2729
    show_name: false
    template: ac_state
    size: 100%
    state:
      - operator: template
        value: '[[[ return variables.has_iai <= 3 ]]]'
        color: blue
      - operator: template
        value: '[[[ return variables.has_iai <= 6 ]]]'
        color: '#6666ff'
      - operator: template
        value: '[[[ return variables.has_iai <= 9 ]]]'
        color: '#ff00ff'
      - operator: template
        value: '[[[ return variables.has_iai > 9 ]]]'
        color: red
    styles:
      icon:
        - filter: drop-shadow(0 0 0.7rem)
      card:
        - pointer-events: none
      grid:
        - position: relative
      custom_fields:
        primary_reading:
          - position: absolute
          - top: 50%
          - left: 50%
          - transform: 'translate(-50%, -60%)'
          - pointer-events: none
        secondary_reading:
          - position: absolute
          - top: 57%
          - left: 50%
          - transform: 'translate(-50%, 0%)'
          - pointer-events: none
        notifications:
          - position: absolute
          - top: 25%
          - left: 50%
          - transform: 'translate(-50%, 0%)'
          - pointer-events: none
    custom_fields:
      notifications:
        card:
          type: horizontal-stack
          cards:
            - type: 'custom:button-card'
              template: ac_notifications
              icon: 'mdi:air-filter'
              color: darkgreen
              state:
                - operator: template
                  value: '[[[ return variables.has_days_pre <=1 ]]]'
                  styles:
                    icon:
                      - color: darkred
                      - animation: blink 3s ease infinite
                - operator: template
                  value: '[[[ return variables.has_days_pre <=3 ]]]'
                  styles:
                    icon:
                      - color: darkorange
            - type: 'custom:button-card'
              template: ac_notifications
              icon: 'philips:filter_replacement'
              color: darkgreen
              state:
                - operator: template
                  value: '[[[ return variables.has_days_hepa <=1 ]]]'
                  styles:
                    icon:
                      - color: darkred
                      - animation: blink 3s ease infinite
                - operator: template
                  value: '[[[ return variables.has_days_hepa <=3 ]]]'
                  styles:
                    icon:
                      - color: darkorange
            - type: 'custom:button-card'
              template: ac_notifications
              icon: 'mdi:image-filter-none'
              color: darkgreen
              state:
                - operator: template
                  value: '[[[ return variables.has_days_carbon <=1 ]]]'
                  styles:
                    icon:
                      - color: darkred
                      - animation: blink 3s ease infinite
                - operator: template
                  value: '[[[ return variables.has_days_carbon <=3 ]]]'
                  styles:
                    icon:
                      - color: darkorange
            - type: 'custom:state-switch'
              entity: template
              template: '[[[ return variables.has_water >= 0 && !variables.is_pur ]]]'
              states:
                'true':
                  type: 'custom:button-card'
                  template: ac_notifications
                  icon: 'philips:water_refill'
                  color: darkgreen
                  state:
                    - operator: template
                      value: '[[[ return variables.has_water <=10 ]]]'
                      styles:
                        icon:
                          - color: darkred
                          - animation: blink 3s ease infinite
                    - operator: template
                      value: '[[[ return variables.has_water <=30 ]]]'
                      styles:
                        icon:
                          - color: darkorange
            - type: 'custom:state-switch'
              entity: template
              template: '[[[ return variables.has_days_wick >= 0 && !variables.is_pur ]]]'
              states:
                'true':
                  type: 'custom:button-card'
                  template: ac_notifications
                  icon: 'philips:prefilter_wick_cleaning'
                  color: darkgreen
                  state:
                    - operator: template
                      value: '[[[ return variables.has_days_wick <=1 ]]]'
                      styles:
                        icon:
                          - color: darkred
                          - animation: blink 3s ease infinite
                    - operator: template
                      value: '[[[ return variables.has_days_wick <=3 ]]]'
                      styles:
                        icon:
                          - color: darkorange
      secondary_reading:
        card:
          type: vertical-stack
          cards:
            - type: 'custom:button-card'
              template: ac_readings
              icon: |
                [[[
                  if (variables.is_pm25)
                    return 'philips:iai' 
                  else
                    return 'philips:pm25'
                ]]]              
              variables:
                var_reading_text: |
                  [[[
                    if (variables.is_pm25)
                      return variables.has_iai
                    else
                      return variables.has_pm25
                  ]]] 
            - type: 'custom:state-switch'
              entity: template
              template: '[[[ return variables.has_temp >= 0 ]]]'
              states:
                'true':
                  type: 'custom:button-card'
                  template:
                    - ac_readings
                    - ac_state
                  icon: 'hass:thermometer'
                  variables:
                    var_reading_text: '[[[ return variables.has_temp + " Ā°C" ]]]'
            - type: 'custom:state-switch'
              entity: template
              template: '[[[ return variables.has_humidity >= 0 ]]]'
              states:
                'true':
                  type: 'custom:button-card'
                  template: ac_readings
                  icon: 'philips:humidity_button'
                  variables:
                    var_reading_text: '[[[ return variables.has_humidity + " %" ]]]'
      primary_reading:
        card:
          type: 'custom:button-card'
          icon: |
            [[[
              if (variables.is_pm25)
                return 'philips:pm25' 
              else
                return 'philips:iai'
            ]]] 
          size: 50%
          label: |
            [[[
              if (variables.is_pm25)
                return variables.has_pm25
              else
                return variables.has_iai
            ]]] 
          layout: icon_label
          show_label: true
          styles:
            label:
              - font-size: 400%
          style: |
            ha-card {
              box-shadow: none;
              background: none;
            }
  - type: horizontal-stack
    cards:
      - type: 'custom:button-card'
        template: buttons
        icon: 'philips:power_button'
        entity: fan.air_ac2729
        name: Power
        tap_action:
          action: call-service
          service: script.toggle_ac_power
          service_data:
            entity_id: entity
      - type: 'custom:button-card'
        template:
          - buttons
          - ac_state
        entity: fan.air_ac2729
        name: LĆ¼fter
        tap_action:
          action: call-service
          service: script.toggle_ac_fan_speed
          service_data:
            entity_id: entity
        state:
          - operator: template
            value: '[[[ return variables.is_off ]]]'
            styles:
              card:
                - pointer-events: none
          - operator: template
            value: '[[[ return variables.is_on ]]]'
            id: activated_state
            icon: |-
              [[[
                switch (variables.has_speed) {
                  case "1":
                    return "philips:fan_speed_button"
                  case "2":
                    return "philips:fan_speed_button"
                  case "3":
                    return "philips:fan_speed_button"
                  case "auto":
                    return "philips:auto_mode"
                  case "allergen":
                    return "philips:allergen_mode"
                  case "night":
                    return "philips:sleep_mode"
                  case "turbo":
                    return "philips:fan_speed_button"
                }
              ]]]
        styles:
          icon:
            - animation: |-
                [[[
                  var speed = 'linear 0s infinite normal none running rotating';
                  switch (variables.has_speed) {
                    case '1':
                      return '12s ' + speed;
                    case '2':
                      return '6s ' + speed;
                    case '3':
                      return '2s ' + speed;
                    case 'turbo':
                      return '0.5s ' + speed;
                    default:
                      return 'none'; 
                  }
                ]]]
          grid:
            - position: relative
          custom_fields:
            fan_speed:
              - position: absolute
              - top: 47%
              - left: 42%
              - transform: 'translate(-50%, -60%)'
              - pointer-events: none
        custom_fields:
          fan_speed:
            card:
              type: 'custom:button-card'
              template: activated_state
              color_type: icon
              show_icon: false
              show_label: true
              label: |-
                [[[
                  switch (variables.has_speed) {
                    case '1':
                      return '1';
                    case '2':
                      return '2';
                    case '3':
                      return '3';
                    case 'turbo':
                      return 't';
                  }
                ]]]
              state:
                - operator: template
                  value: '[[[ return variables.is_on ]]]'
                  id: activated_state
              styles:
                label:
                  - padding: 2px 6px 0px 6px
                  - font-weight: bold
                  - color: |
                      [[[
                        if (variables.is_off)
                          return 'var(--paper-item-icon-color)';
                        else
                          return 'var(--mmp-accent-color, var(--accent-color))';
                      ]]]
              style: |
                ha-card {
                  box-shadow: none;
                }
      - type: 'custom:button-card'
        template:
          - buttons
          - ac_state
        icon: 'philips:light_dimming_button'
        entity: fan.air_ac2729
        name: Anzeige
        tap_action:
          action: call-service
          service: script.toggle_ac_light
          service_data:
            entity_id: entity
        state:
          - operator: template
            value: '[[[ return variables.is_off ]]]'
            styles:
              card:
                - pointer-events: none
          - operator: template
            value: '[[[ return variables.is_backlight ]]]'
            id: activated_state
      - type: 'custom:button-card'
        template:
          - buttons
          - ac_state
        entity: fan.air_ac2729
        name: Modus
        tap_action:
          action: call-service
          service: script.toggle_ac_two_in_one_mode
          service_data:
            entity_id: entity
        state:
          - operator: template
            value: '[[[ return variables.is_on && variables.has_humidity > 0 ]]]'
            icon: >-
              [[[ return variables.is_pur ? "philips:purification_only_mode" :
              "philips:two_in_one_mode" ]]]
            id: activated_state
          - operator: template
            value: '[[[ return variables.is_off || variables.has_humidity < 0 ]]]'
            icon: >-
              [[[ return variables.is_pur ? "philips:purification_only_mode" :
              "philips:two_in_one_mode" ]]]
            styles:
              card:
                - pointer-events: none

Youā€™ll notice that it uses templates and variables. These are put into the lovelace raw configuration:

button_card_templates:
  activated_state:
    state:
      - id: activated_state
        styles:
          card:
            - background-color: var(--primary-text-color)
            - color: var(--card-background-color)
          name:
            - color: 'var(--mmp-accent-color, var(--accent-color))'
            - font-weight: bold
          label:
            - color: 'var(--mmp-accent-color, var(--accent-color))'
          state:
            - color: 'var(--mmp-accent-color, var(--accent-color))'
          icon:
            - color: 'var(--mmp-accent-color, var(--accent-color))'
  raw_buttons:
    template: activated_state
    aspect_ratio: 1/1
    color: var(--paper-item-icon-color)
    tap_action:
      action: toggle
      haptic: medium
    state:
      - value: 'on'
        id: activated_state
    styles:
      card:
        - '--mdc-ripple-color': black
        - '--mdc-press-opacity': 0.5
        - font-size: var(--paper-font-body1_-_font-size)
        - padding-bottom: 10px
  buttons:
    template: raw_buttons
    show_name: true
    show_label: true
    show_state: false
    color_type: icon
    styles:
      grid:
        - grid-template-areas: '"i" "l" "n"'
        - grid-template-columns: 1fr
        - grid-template-rows: 4fr 1fr 1fr
      img_cell:
        - align-self: start
        - text-align: start
        - justify-content: start
        - padding-left: 16px
      name:
        - justify-self: start
        - padding-left: 10px
        - font-weight: bold
      label:
        - justify-self: start
        - padding-left: 10px
  state_buttons:
    template: buttons
    show_name: false
    show_state: true
    styles:
      grid:
        - grid-template-areas: '"i" "l" "s"'
      state:
        - justify-self: start
        - padding-left: 10px
        - font-weight: bold
  ac_state:
    variables:
      is_on: '[[[ return entity && entity.state && entity.state == "on" ]]]'
      is_off: '[[[ return entity && entity.state && entity.state == "off" ]]]'
      is_pur: |-
        [[[ return entity && entity.attributes && entity.attributes.function &&
            entity.attributes.function == "Purification"
        ]]]
      is_backlight: |-
        [[[ return entity && entity.attributes && entity.attributes.function &&
            entity.attributes.display_backlight > 0
        ]]]
      is_pm25: >-
        [[[ return entity && entity.attributes &&
        entity.attributes.preferred_index &&
            entity.attributes.preferred_index == "PM2.5"
        ]]]
      has_speed: |-
        [[[ return (entity && entity.attributes && entity.attributes.speed) ?
            entity.attributes.speed : null
        ]]]
      has_iai: |-
        [[[
          return (entity && entity.attributes ) ?
          entity.attributes.indoor_allergen_index : -1
        ]]]
      has_pm25: |-
        [[[
          return (entity && entity.attributes ) ?
          entity.attributes.pm25 : -1
        ]]]
      has_temp: |-
        [[[
          return (entity && entity.attributes ) ?
          entity.attributes.temperature : -1
        ]]]
      has_humidity: |-
        [[[
          return (entity && entity.attributes ) ?
          entity.attributes.humidity : -1
        ]]]
      has_days_pre: |-
        [[[
          return (entity && entity.attributes ) ?
          (entity.attributes.filter_pre_remaining).match(/\d+/i) : -1
        ]]]
      has_days_hepa: |-
        [[[
          return (entity && entity.attributes ) ?
          (entity.attributes.filter_hepa_remaining).match(/\d+/i) : -1
        ]]]
      has_days_carbon: |-
        [[[
          return (entity && entity.attributes ) ?
          (entity.attributes.filter_active_carbon_remaining).match(/\d+/i) : -1
        ]]]
      has_days_wick: |-
        [[[
          return (entity && entity.attributes ) ?
          (entity.attributes.filter_wick_remaining).match(/\d+/i) : -1
        ]]]
      has_water: |-
        [[[
          return (entity && entity.attributes ) ?
          entity.attributes.water_level : -1
        ]]]
  ac_readings:
    variables:
      var_name: var_reading_text
    label: |
      [[[ return variables.var_reading_text ]]]
    layout: icon_label
    show_label: true
    size: 100%
    styles:
      label:
        - font-size: 100%
      card:
        - width: 100px
        - height: 30px
        - box-shadow: none
        - background: none
  ac_notifications:
    layout: vertical
    show_label: false
    show_name: false
    color: red
    size: 100%
    styles:
      card:
        - width: 50px
        - height: 30px
        - box-shadow: none
        - background: none
  label_card:
    styles:
      card:
        - background: none
        - box-shadow: none
        - pointer-events: none
      name:
        - font-size: 'var(--ha-card-header-font-size, 24px)'
        - justify-self: start
        - padding-left: 10px

To make it work, I need a few scripts:

Toggeling power takes care of restoring the display light setting (the device insists on switching the light back on when it is powered on regardless of previous state):

alias: Toggle AC power
sequence:
  - choose:
      - conditions:
          - condition: template
            value_template: '{{ is_state(entity_id, "off") }}'
        sequence:
          - service: fan.turn_on
            data:
              entity_id: '{{ entity_id }}'
          - choose:
              - conditions:
                  - condition: template
                    value_template: '{{ light == False }}'
                sequence:
                  - delay: '1'
                  - service: philips_airpurifier.set_light_brightness
                    data:
                      entity_id: '{{ entity_id }}'
                      brightness: 0
                  - delay: '1'
                  - service: philips_airpurifier.set_display_backlight_off
                    data:
                      entity_id: '{{ entity_id }}'
    default:
      - service: fan.turn_off
        data:
          entity_id: '{{ entity_id }}'
mode: single
icon: 'philips:power_button'
fields:
  entity_id:
    description: Entity of fan
    example: fan.air_ac2729
description: Toggle the power of Philips AC
variables:
  light: '{{ state_attr(entity_id, "display_backlight") }}'

Toggeling the light is required as two settings have to be set:

alias: Toggle AC light
sequence:
  - choose:
      - conditions:
          - condition: template
            value_template: '{{ is_state(entity_id, "on") }}'
        sequence:
          - choose:
              - conditions:
                  - condition: template
                    value_template: '{{ is_state_attr(entity_id, ''display_backlight'', true) }}'
                sequence:
                  - service: philips_airpurifier.set_display_backlight_off
                    data:
                      entity_id: '{{ entity_id }}'
                  - service: philips_airpurifier.set_light_brightness
                    data:
                      entity_id: '{{ entity_id }}'
                      brightness: 0
            default:
              - service: philips_airpurifier.set_display_backlight_on
                data:
                  entity_id: '{{ entity_id }}'
              - service: philips_airpurifier.set_light_brightness
                data:
                  entity_id: '{{ entity_id }}'
                  brightness: 100
mode: single
icon: 'philips:light_dimming_button'
fields:
  entity_id:
    description: Entity of fan
    example: fan.air_ac2729
description: Toggle the backlight of philips AC

Toggeling the purification mode is rather simple, it can only take two states:

alias: Toggle AC 2in1 mode
sequence:
  - choose:
      - conditions:
          - condition: template
            value_template: '{{ states[entity_id].attributes.function == ''Purification''}}'
        sequence:
          - service: philips_airpurifier.set_function
            data:
              entity_id: '{{ entity_id }}'
              function: purification_humidification
    default:
      - service: philips_airpurifier.set_function
        data:
          entity_id: '{{ entity_id }}'
          function: purification
mode: single
icon: 'philips:two_in_one_mode_button'
fields:
  entity_id:
    description: Entity of fan
    example: fan.air_ac2729
description: Toggle the backlight of philips AC

What took me a while is to figure out how to cycle through an attribute state list with multiple states when repeatedly clicking a button - while skipping the first state as this switches the device off:

(updated from the original script for the new fan model in HA introducing preset_mode. Note, for this to work you also need at least version 0.4.0 of the custom integration: GitHub - betaboon/philips-airpurifier-coap: šŸ’Ø Philips AirPurifier custom component for Home Assistant. With support for new Devices with CoAP protocol. Tested on AC2729/10 (bought early 2020) )

alias: Toggle AC fan speed
sequence:
  - service: fan.set_preset_mode
    data_template:
      entity_id: '{{ entity_id }}'
      preset_mode: >
        {%- set current = state_attr(entity_id, 'preset_mode') %}
        {%- set modes = state_attr(entity_id, 'preset_modes') %}
        {%- set index = modes.index(current) %}
        {%- set next = 0 if current == modes[-1] else index + 1 %}
        {{ modes[next] }}
mode: single
icon: 'philips:fan_speed_button'
fields:
  entity_id:
    description: Entity of fan
    example: fan.air_ac2729
description: Set the speed mode of philips AC

Maybe this can serve someone as help and inspiration. Iā€™m sure some things could have been done more elegantly. I save you the code for the custom icons, as this is a separate can of worms. However, I documented my approach here.

8 Likes

Great stuff :blush: you should share your config as a source of inspiration/good complex example for other users :wink:

1 Like

Hey there everyone, Iā€™m looking to achieve multiple sensors along side a logo as seen in the upper photo in this post https://imgur.com/a/wHmiSNv I canā€™t quite figure out where to go from here, Iā€™ve got plain name text working or a switch working on the card but I canā€™t figure out multiple sensors. The bottom image is what I have so far. Hereā€™s my current yaml:

type: 'custom:button-card'
layout: icon_name_state
entity: sensor.current_version
show_entity_picture: true
entity_picture: 'https://pbs.twimg.com/profile_images/720135322223312896/WS3etv24_400x400.jpg'
styles:
  card:
    - border-radius: 0%
    - height: 115px

Happy to share. Not sure if I did it the most efficient way as this was my first attempt at button-card, learning yaml, javascript, jinja2 and HA all at the same time. Iā€™ll add it to the original post.

@RomRider On a different note: maybe something like a HACS-style store for button-card examples would be a helpful thing. Something like a structured repository of reusable cards. Iā€™m pretty sure there is amazing stuff out there.

1 Like

@Krispkiwi Iā€™ve done something like that in my rather lengthy example above. The magic comes through custom_fields. You could make each sensor a custom field. I found this description a great inspiration.

I had some thoughts about this, the simple approach is just a git repo with a bunch of templates and how to use them + screenshots. That can be easily setup.
I doubt that button-card templates will ever land as a first class citizen in HACS, but Iā€™ll let @ludeeus chime in here :blush: On my side, I wouldnā€™t have time to maintain an HACS-like tool just for button-card

I guess on a higher level this would have to be a repository of configured but not active cards in HA. Sounds like a rather fundamental thing. As Iā€™m new to this, I donā€™t even know that best-practice is when you take-out a card (with all the configuration thatā€™s spread all over the place) but would like to store it for later use.

That sounds horrible :see_no_evil:, maybe just use this https://sharethelove.io/ :man_shrugging:

In the examples I canā€™t see any switches or sensors under the custom fields bit so Iā€™m not entirely sure how to write the yaml