Home Assistant Deck component (HA Deck)

HA Deck is a config-driven Home Assistant dashboard built on top of ESPHome using LVGL.

Demo video
GitHub Repository

Currently, I am developing HA Deck v2. The new version includes styling support, new widgets, and other useful features. However, I cannot guarantee fast development due to a lack of enthusiasm.

PS
I’ve created this topic so all HA Deck related questions can be asked here instead of using the Subscribe and unsubscribe from HA events dynamically. Also, I may post some updates here.

4 Likes

Hi @strange_v,

the dashboard works great.
I just tried to add icons using icon: mdi:icon-name, but it doesn’t work for me.
Can you pls explain how you integrated the icons in the code? Your icons appear as “?” in my code, but resolve well on the screen.

Thanks a lot!

You must copy a glyph, just click on an icon

Also, make sure you are using the icon from this subset: Home Assistant - Docs - Pictogrammers

1 Like

That was too easy. I couldn’t find the copy-paste function. :see_no_evil:

Do you have any experience how many icons can be used before the ESP32 gets overloaded?

The main limitation is the flash size. Currently, fonts use 3.13 MB, an additional 7.91 MB for the background image (in the case of hd_device_sc01_plus).

Ideally, icon fonts should be generated in runtime with only used icons. It’ll be possible when ESPHome integrates native LVGL support.

Hi @strange_v ,

Thanks again for sharing your amazing work! Without changing your script, but with a little tweaking I have created an amazing dashboard including PV and Spotify control. :slight_smile:

PV: Dashboard:

Spotify Dashboard:
Slider is used for song progress and volume change. Value cards without text and funktion are used for icons below sliders:

Spotify Playlist Menu:

1 Like

@brix29, it looks nice! It should look even better in a new version as, for example, sliders natively support text or icons, and different styles can be applied. Unfortunately, I haven’t touched this project for more than a month.

1 Like

Hi @strange_v,

The slider’s fill bar seems to render correctly at your fixed height (276px) only. It would be a great feature, if scaling the height of the slider dynamically using “dimensions” would be possible. Just in case you plan work on the code again. :smiley: :crossed_fingers:

Hello @brix29

I´m was able to compile and run strange_v yaml example in to my WT32-SC01 Plus but I´m having difficult to understand how to modify yaml to create my custom dashboard.

would you mind share your yaml code?

thank you.

This is the Spotify screen. I hope it helps:


    - name: ${SCREEN_SPOTIFY_PLAYER}
      widgets:
        # BACK BUTTON
        - type: button
          position: 8, 162
          dimensions: 48x150
          icon: 󰅁
          enabled: return true;
          on_click:
            - lambda: id(deck).switch_screen("$SCREEN_MAIN");
      
        # A1-A2: TITLE
        - type: value-card
          id: current_title_element
          position: 8, 18
          dimensions: 325x60
          enabled: return true;
          value: |-
            return id(current_title).state;

        # A1-A2: ARTIST
        - type: value-card
          id: current_artist_element
          position: 8, 78
          dimensions: 325x75 
          enabled: return true;
          value: |-
            return id(current_artist).state;

        # C1: Button für Play/Pause Spotify
        - type: button
          position: 73, 188
          dimensions: 80x80
          icon: 󰐊
          toggle: true
          enabled: return true;
          checked: |-
            return id(esp32_spotify_play).state;
          on_click:
            then:
              - homeassistant.service:
                  service: media_player.media_play_pause
                  data:
                    entity_id: media_player.spotify_lt12b

        # C2: Button for Next Song
        - type: button
          position: 163, 188  # Nach rechts und oben angepasst für 80x80 Dimension
          dimensions: 80x80
          icon: 󰒭
          enabled: return true;
          on_click:
            then:
              - homeassistant.service:
                  service: media_player.media_next_track
                  data:
                    entity_id: media_player.spotify_lt12b

        # C3: Button for Spotify Playlist Screen
        - type: button
          position: 253, 188
          dimensions: 80x80
          icon: 󰹯
          enabled: return true;
          on_click:
            - lambda: id(deck).switch_screen("$SCREEN_SPOTIFY_PLAYLISTS");

      # SLIDER SPOTIFY PROGRESS, no "text: "
        - type: slider
          position: 352, 18
          dimensions: 50x250
          min: 0
          max: 100
          enabled: return true;
          value: |-
            return id(spotify_progress).state;
          on_change:
            then:
              - lambda: |-
                  ESP_LOGD("Custom", "Slider-Wert Progress direkt in lambda: %.2f", x);
      # C3: Icon only: Play. Text and value are empty.
        - type: value-card
          position: 352, 262
          dimensions: 50x50
          icon: 󰐊
          enabled: return true;
      # SLIDER SPOTIFY VOLUME, no "text:"
        - type: slider
          position: 417, 18
          dimensions: 50x250
          min: 0
          max: 100
          enabled: return true;
          value: return id(spotify_volume).state;
          on_change:
            then:
              - lambda: |-
                  ESP_LOGD("Custom", "Slider-Wert Volume direkt in lambda: %.2f", x);
              - homeassistant.service:
                  service: input_number.set_value
                  data:
                    entity_id: input_number.esp32_spotify_volume_input
                    value: !lambda 'return x;'
      # C4: Icon only: Speaker. Text and value are empty.
        - type: value-card
          position: 417, 262
          dimensions: 50x50
          icon: 󰕾
          enabled: return true;
2 Likes

Hello

I there a way to make something like that with gauge ?

Capture d’écran 2024-02-29 à 13.51.03

I added some value-cards with different lambdas in visible, so that they are not shown at the same time. This works great if I stay on the same screen. If I go to another screen and back again, all of the cards are rendered at the same time which looks very strange :slight_smile:

Do you have an idea what could cause such behavior?

The relevant part of my config looks like this:

ha_deck:
...
  screens:
    - name: scr_main
      widgets:
        - type: button
          position: 8, 216
          text: Status
          icon: 󰚡
          enabled: return true;
          visible: return id(status).state == "home";
        - type: value-card
          position: 8, 216
          text: Status
          icon: 󰀝
          enabled: return true;
          visible: return id(status).state == "not_home";
          value: |-
            char buff[6];
            sprintf(buff, "%2.0f km", id(distance).state);
            return std::string(buff);
        - type: value-card
          position: 8, 216
          text: Status
          icon: 󰌢
          enabled: return true;
          visible: return id(status).state == "work";
          value: |-
            return std::string("work");

@multinet33, it is, for sure, possible to implement, but I doubt it’ll be added soon (at least by me, with the current progress on the new version…).

@j_d, AFAIR, all components are visible by default. After the rendering, visibility lambda applies and hides the component if needed. So, maybe it is worth checking if visibility lambda is set, and, in that case, do not show the component (by default). I’ll try, as I have a similar case in my setup.

Hi @strange_v, hi community,

I’m trying to create a value widget with a bigger number. Do you have your font in other sizes available? Eg 36 or 42?
Which converter did you use? Somehow I haven’t been successful creating my own.

Has anybody else created further widgets?
I can share a different background, if somebody is interested.

Thanks!

1 Like

@brix29 Sorry for the late response. I’m using lv_font_conv. Also, you can use a web converter: Online font converter - TTF or WOFF fonts to C array | LVGL

Late response. 29 Mins. :laughing: Thanks a lot. I will give it a try!

Hmm. For some reason, I thought 15 days passed).

Is it possible to add auto scrolling of text, if the text gets too long?

I tried to achieve it with LV_LABEL_LONG_SCROLL_CIRCULAR in the value card and lv_obj_set_style_anim_speed, but due to my lack of coding knowledge, I was not successful. (How to customize the circular scrolling of a label? - How-to - LVGL Forum)

I think the functionality needs to be loaded somewhere in the deep code. :face_with_monocle:

My binary sensors “jump” to a wrong state after some minutes, even though the state has not been changed at all. I’m facing this issue for several binary sensors.

If I update the sensor in the dev console, the state is correct again immediately, but it looses the value after a while and changes the “checked” state.

binary_sensor:
  - platform: homeassistant
    entity_id: binary_sensor.live_pv_strom_verfuegbar_binary
    id: live_pv_strom_verfuegbar_binary
        - type: button
          position: 8, 216
          icon: 󰩲
          text: "PV"
          enabled: return true;
          checked: |-
            return id(live_pv_strom_verfuegbar_binary).state;
          on_click:
            lambda: |- 
                id(deck).switch_screen("$SCREEN_PV");

Any idea?
A workaround could be to update the sensor every minute with an automation, but I would prefer a smarter solution. :smiley:
Thanks a lot!

Binary sensors (homeassistant platform) are part of the ESPHome core and if they behave incorrectly it is worth reporting a bug. I haven’t seen such an issue in my setup.