WallPanel w moim wykonaniu

Ja zrobiłem sobie trochę maksymalistyczny dashboard, który na jednej stronie pokazuje wszystkie stany głównych encji. Wygląda trochę jak zestawy kontrolek na samochodowym kokpicie… Dodatkowo “kontrolki” zmieniają kolor lub sposób animacji w zależności od wartości encji…

Całość obsługuję z panelu LCD lodówki Samsung:

Wszystko, co widzicie na panelu (poza badge’ami i kartą zegara), zrobiłem wyłącznie przy użyciu custom: button-card

EDIT:
Ponieważ dostałem mnóstwo próśb na PW o udostępnienie kodu ‘samochodowych kontrolek’, ochoczo dzielę się efektem swojej pracy. Poniższy kod obejmuje tylko kartę [Gabinet], ale karty pozostałych pomieszczeń są zrobione - co do zasady - w identyczny sposób:

type: custom:button-card
name: Gabinet
icon: mdi:desktop-classic
style: |
  ha-card:hover {
  transform: scale(1.05);
  }
tap_action:
  action: navigate
  navigation_path: gabinet
extra_styles: |
  @keyframes obrot {100%{transform:rotatez(360deg)}}
styles:
  grid:
    - grid-template-areas: >-
        "i temp" "i wilg" "n n" "klim klim" "okna okna" "swiatlo swiatlo" "ruch
        ruch"
    - grid-template-columns: 1fr 1fr
    - grid-template-rows: 1fr min-content min-contentfr1
  card:
    - font-size: 13px
    - width: 120px
    - height: 120px
    - margin: 3px
    - border-radius: 10%
    - background-color: var(--primary-background-color)
    - box-shadow: 0px 0px 10px cyan, 0px 0px 10px blue
  name:
    - align-self: start
    - justify-self: start
    - justify-items: left
    - padding-bottom: 50%
    - padding-left: 5%
  img_cell:
    - justify-content: start
    - align-items: start
    - padding-left: 0px
    - padding-bottom: 10%
    - margin: 7px
  icon:
    - color: var(--paper-item-icon-active-color)
    - align-self: middle
    - height: 70%
    - top: 10%
    - left: 20%
    - justify-items: middle
    - padding-left: 5%
  custom_fields:
    temp:
      - color: orange
      - position: absolute
      - top: 10%
      - left: 48%
      - align-self: start
      - justify-self: left
      - font-size: 10px
      - padding-bottom: 2px
    wilg:
      - color: dodgerblue
      - position: absolute
      - top: 30%
      - left: 48%
      - align-self: start
      - justify-self: left
      - font-size: 10px
      - padding-bottom: 2px
    klim:
      - background-color: var(--primary-background-color)
      - position: absolute
      - top: 50%
      - left: 2%
      - padding-bottom: 0px
      - border-radius: 50%
      - height: 20px
      - width: 20px
      - color: |
          [[[
            if (states["climate.haier_ac1"].state == 'heat') return 'crimson'
            if (states["climate.haier_ac1"].state == 'cool') return 'dodgerblue'
            if (states["climate.haier_ac1"].state == 'dry') return 'orange'
            if (states["climate.haier_ac1"].state == 'fan') return 'aqua'
            if (states["climate.haier_ac1"].state == 'auto') return 'darkorchid'
            else return 'dimgray'
          ]]]
      - animation: |
          [[[
            if ((states["climate.haier_ac1"].state == 'heat') || (states["climate.haier_ac1"].state == 'cool') || (states["climate.haier_ac1"].state == 'dry') || (states["climate.haier_ac1"].state == 'fan') || (states["climate.haier_ac1"].state == 'auto')) return 'blink 2s infinite'
            else return 'null'
          ]]]
    grzej:
      - background-color: var(--primary-background-color) ]]]
      - position: absolute
      - top: 50%
      - left: 22%
      - padding-bottom: 0px
      - border-radius: 50%
      - height: 20px
      - width: 20px
      - color: |
          [[[
            if (states["climate.grzejnik_gabinet"].state == 'heat') return 'magenta'
            else return 'dimgray'
          ]]]
    okna:
      - background-color: var(--primary-background-color)
      - position: absolute
      - top: 50%
      - left: 42%
      - padding-bottom: 0px
      - border-radius: 50%
      - height: 20px
      - width: 20px
      - color: |
          [[[
            if (states["group.okna_gabinet"].state == 'on') return 'turquoise'
            else return 'dimgray'
          ]]]
      - animation: |
          [[[
            if (states["group.okna_gabinet"].state == 'on') return 'blink 0.5s infinite'
            else return 'null'
          ]]]
    swiatlo:
      - background-color: var(--primary-background-color)
      - position: absolute
      - top: 50%
      - left: 62%
      - padding-bottom: 0px
      - border-radius: 50%
      - height: 20px
      - width: 20px
      - color: |
          [[[
            if (states["group.oswietlenie_gabinet"].state == 'on') return 'gold'
            else return 'dimgray'
          ]]]
      - animation: |
          [[[
            if (states["group.oswietlenie_gabinet"].state == 'on') return 'blink 2s infinite'
            else return 'null'
          ]]]
    ruch:
      - background-color: var(--primary-background-color)
      - position: absolute
      - top: 50%
      - left: 82%
      - padding-bottom: 0px
      - border-radius: 50%
      - height: 20px
      - width: 20px
      - color: |
          [[[
            if (states["binary_sensor.czujnik_gabinet_occupancy"].state == 'on') return 'lime'
            else return 'dimgray'
          ]]]
      - animation: |
          [[[
            if (states["binary_sensor.czujnik_gabinet_occupancy"].state == 'on') return 'blink 2s infinite'
            else return 'null'
          ]]]
    philips:
      - background-color: var(--primary-background-color)
      - position: absolute
      - top: 65%
      - left: 2%
      - padding-bottom: 0px
      - border-radius: 50%
      - height: 17px
      - width: 20px
      - color: |
          [[[
            if ((states["media_player.philips_tam8905"] != 'undefined') && (states["media_player.philips_tam8905"] != 'unavailable'))
              {if (states["media_player.philips_tam8905"].state == 'playing') return 'lime'
              else return 'dimgray'}
            else return 'dimgray'
          ]]]
      - animation: |
          [[[
            if ((states["media_player.philips_tam8905"] != 'undefined') && (states["media_player.philips_tam8905"] != 'unavailable'))
              if (states["media_player.philips_tam8905"].state == 'playing') return 'rotating 2.5s linear infinite'
          ]]]
    dysk_nas:
      - background-color: var(--primary-background-color) ]]]
      - position: absolute
      - top: 65%
      - left: 22%
      - padding-bottom: 0px
      - border-radius: 50%
      - height: 20px
      - width: 20px
      - color: |
          [[[
            if (states["switch.dysk_sieciowy_nas"].state == 'on') return 'lime'
            else return 'dimgray'
          ]]]
      - animation: |
          [[[
            if (states["switch.dysk_sieciowy_nas"].state == 'on') return 'blink 2s infinite'
            else return 'null'
          ]]]
    lampa_bankiera:
      - background-color: var(--primary-background-color)
      - position: absolute
      - top: 65%
      - left: 42%
      - padding-bottom: 0px
      - border-radius: 50%
      - height: 20px
      - width: 20px
      - color: |
          [[[
            if (states["light.lampa_bankiera"].state == 'on') return 'gold'
            else return 'dimgray'
          ]]]
      - animation: |
          [[[
            if (states["light.lampa_bankiera"].state == 'on') return 'blink 2s infinite'
            else return 'null'
          ]]]
    biurko:
      - background-color: var(--primary-background-color)
      - position: absolute
      - top: 65%
      - left: 62%
      - padding-bottom: 0px
      - border-radius: 50%
      - height: 20px
      - width: 20px
      - color: |
          [[[
            if (states["switch.office_desk"].state == 'on') return 'gold'
            else return 'dimgray'
          ]]]
      - animation: |
          [[[
            if (states["switch.office_desk"].state == 'on') return 'blink 2s infinite'
            else return 'null'
          ]]]
    online:
      - background-color: var(--primary-background-color)
      - position: absolute
      - top: 65%
      - left: 82%
      - padding-bottom: 0px
      - border-radius: 50%
      - height: 20px
      - width: 20px
      - color: |
          [[[
            if (states["switch.lan_hub_ii_pietro"].state == 'on') return 'lime'
            else return 'crimson'
          ]]]
      - animation: |
          [[[
            if (states["switch.lan_hub_ii_pietro"].state == 'off') return 'blink 0.5s infinite'
              else return 'null'
          ]]]
    filtr_powietrza:
      - background-color: var(--primary-background-color)
      - position: absolute
      - top: 80%
      - left: 2%
      - padding-bottom: 0px
      - border-radius: 50%
      - height: 20px
      - width: 20px
      - color: |
          [[[
            if (states["fan.filtr_gabinet"].state == 'sleep') return 'lime'
            if (states["fan.filtr_gabinet"].state == 'auto') return 'magenta'
            if (states["fan.filtr_gabinet"].state == 'favorite') return 'dodgerblue'
            if (states["fan.filtr_gabinet"].state == 'off') return 'dimgray'
          ]]]
      - animation: |
          [[[
            if (states["fan.filtr_gabinet"].state != 'off') return 'blink 2s ease infinite'
            else return 'null'
          ]]]
    nawilzacz:
      - background-color: var(--primary-background-color)
      - position: absolute
      - top: 80%
      - left: 22%
      - padding-bottom: 0px
      - border-radius: 50%
      - height: 20px
      - width: 20px
      - color: |
          [[[
            if (states["humidifier.nawilzacz_gabinet"].state == 'on') return 'dodgerblue'
            else return 'dimgray'
          ]]]
      - animation: |
          [[[
            if (states["humidifier.nawilzacz_gabinet"].state != 'off') return 'blink 2s ease infinite'
            else return 'null'
          ]]]
custom_fields:
  temp: |
    [[[
      return `<ha-icon
        icon="mdi:thermometer"
        style="width: 22px; height: 18px;">
        </ha-icon>${states['sensor.termometr_gabinet_temperature'].state } °C`
    ]]]
  wilg: |
    [[[
      return `<ha-icon
        icon="mdi:water-percent"
        style="width: 22px; height: 18px;">
        </ha-icon>${states['sensor.termometr_gabinet_humidity'].state } %`
    ]]]
  klim: |
    [[[
      return `<ha-icon
        icon="mdi:air-conditioner"
        style="width: 20px; height: 14px;">
        </ha-icon>`
    ]]]
  grzej: |
    [[[
      return `<ha-icon
        icon="mdi:radiator"
        style="width: 20px; height: 14px;">
        </ha-icon>`
    ]]]
  okna: |
    [[[
      return `<ha-icon
        icon="mdi:window-closed-variant"
        style="width: 20px; height: 14px;">
        </ha-icon>`
    ]]]
  swiatlo: |
    [[[
      return `<ha-icon
        icon="mdi:ceiling-light-multiple"
        style="width: 20px; height: 14px;">
        </ha-icon>`
    ]]]  
  ruch: |
    [[[
      return `<ha-icon
        icon="mdi:run"
        style="width: 20px; height: 14px;">
        </ha-icon>`
    ]]]
  philips: |
    [[[
      if (states["media_player.philips_tam8905"].state != 'undefined')
      {return `<ha-icon
        icon="mdi:spotify"
        style="width: 20px; height: 15px;">
        </ha-icon>`}
    ]]]
  dysk_nas: |
    [[[
      return `<ha-icon
        icon="mdi:nas"
        style="width: 20px; height: 14px;">
        </ha-icon>`
    ]]]
  lampa_bankiera: |
    [[[
      return `<ha-icon
        icon="mdi:desk-lamp"
        style="width: 20px; height: 14px;">
        </ha-icon>`
    ]]]
  biurko: |
    [[[
      return `<ha-icon
        icon="mdi:desktop-classic"
        style="width: 20px; height: 14px;">
        </ha-icon>`
    ]]]  
  online: |
    [[[
      return `<ha-icon
        icon="mdi:router-wireless"
        style="width: 20px; height: 14px;">
        </ha-icon>`
    ]]]
  filtr_powietrza: |
    [[[
      return `<ha-icon
        icon="mdi:air-purifier"
        style="width: 20px; height: 14px;">
        </ha-icon>`
    ]]]
  nawilzacz: |
    [[[
      return `<ha-icon
        icon="mdi:air-humidifier"
        style="width: 20px; height: 14px;">
        </ha-icon>`
    ]]]
5 polubień