Warum openHASP wenn es auch mit ESPHome und LVGL geht 😎

Hallo :slight_smile:

Mein Experiment fing vor einem Jahr an, als meine Frau auf mich zukam und meinte “Ich will wieder eine Uhr im Bad und sehen wie die Zeit meiner ZahnbĂŒrste ist” Der Grund dieser Anforderung war das wir frĂŒher die OralB Pro hatten und da gab es solch ein Teil dazu
image

Die neuen iO haben sowas nicht. Der erste Versuch war das hier, wo ich mich ewig und 3 Tage mit der ESP-IDF IDE gequÀlt hab und das Template von SeeedStudio umgebaut hab.

Nun
10 Monate spĂ€ter hat ESPHome alles was es braucht um ohne Umwege ĂŒber MQTT/OpenHASP, Espressif-IDE oder Ă€hnliches, sich schöne Touchscreens zu bauen. Einige Display-Treiber sind dazu gekommen unter anderem fĂŒr den Sensecap Indicator, neue Touchscreen Treiber und letztendlich: native LVGL UnterstĂŒtzung :star_struck:

Jetzt musste ein 2. Sensecap her, ich wollte das produktive Teil ja nicht ruinieren :wink:

In einem ersten Wurf, um gefĂŒhlt Jahre schneller entwickelt, mit mehr Comfort, kam das dabei raus (da kommt noch die Lichtsteuerung etc gleich mit rein)

image
image

Wir haben die gewĂŒnschte Uhr, jetzt auch mit den AkkustĂ€nden der beiden OralB, wenn jemand anfĂ€ngt zu putzen, schaltet das Display um und nach 5min wieder zurĂŒck auf die Uhr.
Nebenbei ist das Design an unseren anderen Dashboards angelehnt. Nur das Blurring gibts noch nicht.

Ich kipp einfach mal den Code, soweit wie ich jetzt bin mal hier rein und darunter kommen viele Links :slight_smile:

esphome:
  name: dev-sensecapindicator
  friendly_name: DEV-SensecapIndicator
  platformio_options:
    build_unflags: -Werror=all

esp32:
  board: esp32-s3-devkitc-1
  variant: esp32s3
  flash_size: 8MB
  framework:
    type: esp-idf
    version: 5.2.2
    platform_version: 6.7.0
    sdkconfig_options:
      CONFIG_ESPTOOLPY_FLASHSIZE_8MB: y
      CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: y
      CONFIG_ESP32S3_DATA_CACHE_64KB: y
      CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y
      CONFIG_SPIRAM_RODATA: y

psram:
  mode: octal
  speed: 80MHz
    
# Enable logging
logger:
  level: DEBUG

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

ota:
  - platform: esphome
    password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

wifi:
  networks:
  - ssid: !secret wifi_ssid_UGV2
    password: !secret wifi_password_UGV2
    hidden: True
    
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "DEV-SensecapIndicator"
    password: !secret wifi_password_fallback

captive_portal:

time:
  - platform: sntp
    id: sntp_time
    timezone: Europe/Zurich
    servers:
     - 192.168.166.1 #mein Router, falls das Internet mal Pause macht
    on_time_sync:
      - script.execute: time_update
    on_time:
      - minutes: '*'
        seconds: 0
        then:
          - script.execute: time_update

script:
  - id: time_update
    then:
      - lvgl.label.update:
          id: lvgl_clock_minute
          text:
            format: "%02d"
            args: [ 'id(sntp_time).now().minute' ]

      - lvgl.label.update:
          id: lvgl_clock_hour
          text:
            format: "%02d"
            args: [ 'id(sntp_time).now().hour' ]
      - lvgl.label.update:
          id: lvgl_clock_longdate
          text:
            format: "%s, %02d.%02d.%04d"
            args: 
              - '(new const char *[7]{"Sunntig", "MÀÀntig", "Ziischtig", "Mittwuch", "Dunschtig", "Friitig", "Samschtig"})[id(sntp_time).now().day_of_week-1]'
              - 'id(sntp_time).now().day_of_month'
              - 'id(sntp_time).now().month'
              - 'id(sntp_time).now().year'
          
  - id: back_to_timepage
    mode: restart
    then:
      - delay: 5 min
      - lvgl.page.show: page_time
      
text_sensor:
  - platform: wifi_info
    ssid:
      name: SSID
    bssid:
      name: BSSID

  - platform: homeassistant
    name: "papi_Mode"
    entity_id: sensor.oralb_papi_mode
    id: papi_mode
    internal: true
    on_value:
      - lvgl.label.update:
          id: lvgl_papi_mode
          text:
            format: "%s"
            args: [ 'id(papi_mode).state.c_str()' ]

  - platform: homeassistant
    name: "mami_Mode"
    entity_id: sensor.oralb_mami_mode
    id: mami_mode
    internal: true
    on_value:
      - lvgl.label.update:
          id: lvgl_mami_mode
          text:
            format: "%s"
            args: [ 'id(mami_mode).state.c_str()' ]

  - platform: homeassistant
    name: "papi_Pressure"
    entity_id: sensor.oralb_papi_pressure
    id: papi_pressure
    internal: true
    on_value:
      - lvgl.label.update:
          id: lvgl_papi_pressure
          text:
            format: "%s"
            args: [ 'id(papi_pressure).state.c_str()' ]

  - platform: homeassistant
    name: "mami_Pressure"
    entity_id: sensor.oralb_mami_pressure
    id: mami_pressure
    internal: true
    on_value:
      - lvgl.label.update:
          id: lvgl_mami_pressure
          text:
            format: "%s"
            args: [ 'id(mami_pressure).state.c_str()' ]

  - platform: homeassistant
    name: "papi_State"
    entity_id: sensor.oralb_papi_toothbrush_state
    id: papi_state
    internal: true

  - platform: homeassistant
    name: "mami_State"
    entity_id: sensor.oralb_mami_toothbrush_state
    id: mami_state
    internal: true

  - platform: homeassistant
    name: "papi_Sector"
    entity_id: sensor.oralb_papi_sector
    id: papi_sector
    internal: true
    on_value:
      - lvgl.label.update:
          id: lvgl_papi_sector
          text:
            format: "%s"
            args: [ 'id(papi_sector).state.c_str()' ]

  - platform: homeassistant
    name: "mami_Sector"
    entity_id: sensor.oralb_mami_sector
    id: mami_sector
    internal: true
    on_value:
      - lvgl.label.update:
          id: lvgl_mami_sector
          text:
            format: "%s"
            args: [ 'id(mami_sector).state.c_str()' ]

sensor:
  - platform: wifi_signal
    id: wifi_signal_db
    name: "WiFi Signal"
    update_interval: 60s
  
  - platform: copy
    id: wifi_signal_percent
    source_id: wifi_signal_db
    internal: true
    name: "WiFi Signal Percent"
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    on_value:
      - lvgl.label.update:
          id: lvgl_wifi_signal_percent
          text:
            format: "%.0f%%"
            args: [ 'id(wifi_signal_percent).get_state()' ]
      - lvgl.label.update:
          id: lvgl_wifi_signal_percent_icon
          text: !lambda |-
            static char buf[10];
            std::string icon;
            if (x == 100.0) {
                icon = "\U000F0928";
            } else if (x > 75) {
                icon = "\U000F0925";
            } else if (x > 50) {
                icon = "\U000F0922";
            } else if (x > 25) {
                icon = "\U000F091F";
            } else {
                icon = "\U000F092F";
            }
            snprintf(buf, sizeof(buf), "%s", icon.c_str());
            return buf;

  - platform: homeassistant
    name: "papi_Battery"
    entity_id: sensor.oralb_papi_battery
    id: papi_battery
    internal: true
    on_value:
      - lvgl.label.update:
          id: lvgl_papi_battery
          text:
            format: "%.0f %%"
            args: [ 'id(papi_battery).get_state()' ]
      - lvgl.label.update:
          id: lvgl_papi_battery_front
          text:
            format: "%.0f%%"
            args: [ 'id(papi_battery).get_state()' ]
      - lvgl.label.update:
          id: lvgl_papi_battery_icon
          text: !lambda |-
            static char buf[10];
            std::string icon;
            if (x == 100.0) {
                icon = "\U000F0948"; // mdi-battery (full)
            } else if (x > 90) {
                icon = "\U000F0946"; // mdi-battery-90
            } else if (x > 80) {
                icon = "\U000F0945"; // mdi-battery-80
            } else if (x > 70) {
                icon = "\U000F0944"; // mdi-battery-70
            } else if (x > 60) {
                icon = "\U000F0943"; // mdi-battery-60
            } else if (x > 50) {
                icon = "\U000F0942"; // mdi-battery-50
            } else if (x > 40) {
                icon = "\U000F0941"; // mdi-battery-40
            } else if (x > 30) {
                icon = "\U000F0940"; // mdi-battery-30
            } else if (x > 20) {
                icon = "\U000F093F"; // mdi-battery-20
            } else if (x > 10) {
                icon = "\U000F093E"; // mdi-battery-10
            } else if (x > 0) {
                icon = "\U000F10CD"; // mdi-battery-outline
            } else {
                icon = "\U000F10CD"; // mdi-battery-unknown
            }
            snprintf(buf, sizeof(buf), "%s", icon.c_str());
            return buf;
      - lvgl.label.update:
          id: lvgl_papi_battery_front_icon
          text: !lambda |-
            static char buf[10];
            std::string icon;
            if (x == 100.0) {
                icon = "\U000F0948"; // mdi-battery (full)
            } else if (x > 90) {
                icon = "\U000F0946"; // mdi-battery-90
            } else if (x > 80) {
                icon = "\U000F0945"; // mdi-battery-80
            } else if (x > 70) {
                icon = "\U000F0944"; // mdi-battery-70
            } else if (x > 60) {
                icon = "\U000F0943"; // mdi-battery-60
            } else if (x > 50) {
                icon = "\U000F0942"; // mdi-battery-50
            } else if (x > 40) {
                icon = "\U000F0941"; // mdi-battery-40
            } else if (x > 30) {
                icon = "\U000F0940"; // mdi-battery-30
            } else if (x > 20) {
                icon = "\U000F093F"; // mdi-battery-20
            } else if (x > 10) {
                icon = "\U000F093E"; // mdi-battery-10
            } else if (x > 0) {
                icon = "\U000F10CD"; // mdi-battery-outline
            } else {
                icon = "\U000F10CD"; // mdi-battery-unknown
            }
            snprintf(buf, sizeof(buf), "%s", icon.c_str());
            return buf;

  - platform: homeassistant
    name: "mami_Battery"
    entity_id: sensor.oralb_mami_battery
    id: mami_battery
    internal: true
    on_value:
      - lvgl.label.update:
          id: lvgl_mami_battery
          text:
            format: "%.0f %%"
            args: [ 'id(mami_battery).get_state()' ]
      - lvgl.label.update:
          id: lvgl_mami_battery_front
          text:
            format: "%.0f%%"
            args: [ 'id(mami_battery).get_state()' ]
      - lvgl.label.update:
          id: lvgl_mami_battery_icon
          text: !lambda |-
            static char buf[10];
            std::string icon;
            if (x == 100.0) {
                icon = "\U000F0948"; // mdi-battery (full)
            } else if (x > 90) {
                icon = "\U000F0946"; // mdi-battery-90
            } else if (x > 80) {
                icon = "\U000F0945"; // mdi-battery-80
            } else if (x > 70) {
                icon = "\U000F0944"; // mdi-battery-70
            } else if (x > 60) {
                icon = "\U000F0943"; // mdi-battery-60
            } else if (x > 50) {
                icon = "\U000F0942"; // mdi-battery-50
            } else if (x > 40) {
                icon = "\U000F0941"; // mdi-battery-40
            } else if (x > 30) {
                icon = "\U000F0940"; // mdi-battery-30
            } else if (x > 20) {
                icon = "\U000F093F"; // mdi-battery-20
            } else if (x > 10) {
                icon = "\U000F093E"; // mdi-battery-10
            } else if (x > 0) {
                icon = "\U000F10CD"; // mdi-battery-outline
            } else {
                icon = "\U000F10CD"; // mdi-battery-unknown
            }
            snprintf(buf, sizeof(buf), "%s", icon.c_str());
            return buf;
      - lvgl.label.update:
          id: lvgl_mami_battery_front_icon
          text: !lambda |-
            static char buf[10];
            std::string icon;
            if (x == 100.0) {
                icon = "\U000F0948"; // mdi-battery (full)
            } else if (x > 90) {
                icon = "\U000F0946"; // mdi-battery-90
            } else if (x > 80) {
                icon = "\U000F0945"; // mdi-battery-80
            } else if (x > 70) {
                icon = "\U000F0944"; // mdi-battery-70
            } else if (x > 60) {
                icon = "\U000F0943"; // mdi-battery-60
            } else if (x > 50) {
                icon = "\U000F0942"; // mdi-battery-50
            } else if (x > 40) {
                icon = "\U000F0941"; // mdi-battery-40
            } else if (x > 30) {
                icon = "\U000F0940"; // mdi-battery-30
            } else if (x > 20) {
                icon = "\U000F093F"; // mdi-battery-20
            } else if (x > 10) {
                icon = "\U000F093E"; // mdi-battery-10
            } else if (x > 0) {
                icon = "\U000F10CD"; // mdi-battery-outline
            } else {
                icon = "\U000F10CD"; // mdi-battery-unknown
            }
            snprintf(buf, sizeof(buf), "%s", icon.c_str());
            return buf;

  - platform: homeassistant
    name: "papi_Timer"
    entity_id: sensor.oralb_papi_timer
    id: papi_timer
    internal: true
    on_value:
      - lvgl.label.update:
          id: lvgl_papi_timer
          text:
            format: "%.0f"
            args: [ 'id(papi_timer).get_state()' ]
      - lvgl.bar.update:
          id: lvgl_papi_bar
          value: !lambda |-
            return id(papi_timer).get_state();
      - if:
          condition:
            lambda: |-
              return x == 1;
          then:
            - lvgl.page.show:
                id: page_oralb
            - script.execute: back_to_timepage

  - platform: homeassistant
    name: "mami_Timer"
    entity_id: sensor.oralb_mami_timer
    id: mami_timer
    internal: true
    on_value:
      - lvgl.label.update:
          id: lvgl_mami_timer
          text:
            format: "%.0f"
            args: [ 'id(mami_timer).get_state()' ]
      - lvgl.bar.update:
          id: lvgl_mami_bar
          value: !lambda |-
            return id(mami_timer).get_state();
      - if:
          condition:
            lambda: |-
              return x == 1;
          then:
            - lvgl.page.show:
                id: page_oralb
            - script.execute: back_to_timepage

binary_sensor:
  - platform: gpio
    internal: true
    id: sensecap_greenbutton
    name: "Green Button"
    pin:
      number: GPIO38
      inverted: yes
      mode:
        input: true
        pullup: true
    on_press:
      then:
        - light.toggle: sensecap_display_backlight
        
        
output:
  - platform: ledc
    pin: 
      number: GPIO45
      ignore_strapping_warning: true
    id: ledc_gpio45
    frequency: 100Hz
    
light:
  - platform: monochromatic
    output: ledc_gpio45
    name: Display Backlight
    id: sensecap_display_backlight
    internal: true
    restore_mode: ALWAYS_ON

i2c:
  - id: bus_a
    sda: GPIO39
    scl: GPIO40
    scan: false

spi:
  - id: lcd_spi
    clk_pin: GPIO41
    mosi_pin: GPIO48

pca9554:
  - id: pca9554a_device
    address: 0x20
    pin_count: 16

touchscreen:
  platform: ft5x06
  id: sensecap_touchscreen
  transform:
    mirror_x: true
    mirror_y: true

display:
  - platform: st7701s
    id: sensecap_display
    auto_clear_enabled: false
    data_rate: 4MHz
    update_interval: never
    spi_mode: MODE3
    color_order: RGB
    dimensions:
      width: 480
      height: 480
    invert_colors: true
    transform:
      mirror_x: true
      mirror_y: true
    cs_pin:
      pca9554: pca9554a_device
      number: 4
    reset_pin:
      pca9554: pca9554a_device
      number: 5
    de_pin: GPIO18
    hsync_pin: GPIO16
    vsync_pin: GPIO17
    pclk_pin: GPIO21
    init_sequence:
      - 1 # select canned init sequence number 1
      - delay 5ms
      - [ 0xE0, 0x1F ]  # Set sunlight readable enhancement
    data_pins:
      red:
        - GPIO4         #r1
        - GPIO3         #r2
        - GPIO2         #r3
        - GPIO1         #r4
        - GPIO0         #r5
      green:
        - GPIO10        #g0
        - GPIO9         #g1
        - GPIO8         #g2
        - GPIO7         #g3
        - GPIO6         #g4
        - GPIO5         #g5
      blue:
        - GPIO15        #b1
        - GPIO14        #b2
        - GPIO13        #b3
        - GPIO12        #b4
        - GPIO11        #b5

font:
  - file:
      type: gfonts
      family: Roboto
      weight: 400
    id: roboto14
    size: 14
    bpp: 4
    glyphs: '!"%()+=,-_.:°/?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ abcdefghijklmnopqrstuvwxyzĂ€Ă¶ĂŒ'
  - file:
      type: gfonts
      family: Roboto
      weight: 400
    id: roboto16
    size: 16
    bpp: 4
    glyphs: '!"%()+=,-_.:°/?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ abcdefghijklmnopqrstuvwxyzĂ€Ă¶ĂŒ'

  - file:
      type: gfonts
      family: Roboto
      weight: 400
    id: roboto18
    size: 18
    bpp: 4
    glyphs: '!"%()+=,-_.:°/?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ abcdefghijklmnopqrstuvwxyzĂ€Ă¶ĂŒ'

  - file:
      type: gfonts
      family: Roboto
      weight: 400
    id: roboto22
    size: 22
    bpp: 4
    glyphs: '!"%()+=,-_.:°/?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ abcdefghijklmnopqrstuvwxyzĂ€Ă¶ĂŒ'

  - file:
      type: gfonts
      family: Roboto
      weight: 400
    id: roboto48
    size: 48
    bpp: 4
    glyphs: '0123456789'

  - file:
      type: gfonts
      family: Roboto
      weight: 700
    id: robotobold140
    size: 140
    bpp: 4
    glyphs: '0123456789'

  - file:
      type: gfonts
      family: Roboto
      weight: 700
    id: robotobold96
    size: 96
    bpp: 4
    glyphs: ':'

  - file: "https://github.com/Templarian/MaterialDesign-Webfont/raw/master/fonts/materialdesignicons-webfont.ttf"
    id: icons32
    size: 32
    bpp: 4
    glyphs: [
      "\U000F1AE1",  # mdi:timer-play-outline
      "\U000F01FB",  # mdi:engine-outline
      "\U000F0199",  # mdi:counter
      "\U000F029A",  # mdi:gauge
      "\U000F092F",  # mdi:wifi-strength-outline
      "\U000F091F",  # mdi:wifi-strength-1
      "\U000F0922",  # mdi:wifi-strength-2
      "\U000F0925",  # mdi:wifi-strength-3
      "\U000F0928",  # mdi:wifi-strength-4
      "\U000F02FD",  # mdi:information-outline
      "\U000F093E",  # mdi:battery-10-bluetooth
      "\U000F093F",  # mdi:battery-20-bluetooth
      "\U000F0940",  # mdi:battery-30-bluetooth
      "\U000F0941",  # mdi:battery-40-bluetooth
      "\U000F0942",  # mdi:battery-50-bluetooth
      "\U000F0943",  # mdi:battery-60-bluetooth
      "\U000F0944",  # mdi:battery-70-bluetooth
      "\U000F0945",  # mdi:battery-80-bluetooth
      "\U000F0946",  # mdi:battery-90-bluetooth
      "\U000F0948",  # mdi:battery-bluetooth
      "\U000F10CD",  # mdi:battery-alert-variant-outline
    ]

  - file: "https://github.com/Templarian/MaterialDesign-Webfont/raw/master/fonts/materialdesignicons-webfont.ttf"
    id: icons24
    size: 24
    bpp: 4
    glyphs: [
      "\U000F092F",  # mdi:wifi-strength-outline
      "\U000F091F",  # mdi:wifi-strength-1
      "\U000F0922",  # mdi:wifi-strength-2
      "\U000F0925",  # mdi:wifi-strength-3
      "\U000F0928",  # mdi:wifi-strength-4
      "\U000F093E",  # mdi:battery-10-bluetooth
      "\U000F093F",  # mdi:battery-20-bluetooth
      "\U000F0940",  # mdi:battery-30-bluetooth
      "\U000F0941",  # mdi:battery-40-bluetooth
      "\U000F0942",  # mdi:battery-50-bluetooth
      "\U000F0943",  # mdi:battery-60-bluetooth
      "\U000F0944",  # mdi:battery-70-bluetooth
      "\U000F0945",  # mdi:battery-80-bluetooth
      "\U000F0946",  # mdi:battery-90-bluetooth
      "\U000F0948",  # mdi:battery-bluetooth
      "\U000F10CD",  # mdi:battery-alert-variant-outline
    ]

image:
  - file: 'lvgl/sensecap_wp1.png'
    id: wallpaper
    resize: 480x480
    type: RGB565
    use_transparency: true

lvgl:
  displays:
    - sensecap_display
  touchscreens:
    - sensecap_touchscreen
  disp_bg_image: wallpaper
  style_definitions:
    - id: panelwithouttimer
      width: 190
      height: 65
      border_color: 0xFFFFFF
      border_width: 2
      border_opa: 30%
      bg_color: 0x16417d
      bg_opa: 30%
      radius: 4
      scrollbar_mode: "off"
      pad_all: 0

    - id: label_icon
      x: 10
      y: 16
      width: 32
      height: 32
      text_color: 0xFFFFFF
      text_font: icons32
      text_align: LEFT

    - id: label_name
      x: 55
      y: 9
      text_color: 0xC4C4C4
      text_font: roboto16
      text_align: LEFT

    - id: label_value
      x: 55
      y: 30
      text_color: 0xFFFFFF
      text_font: roboto18
      text_align: LEFT

  pages:
    - id: page_time
      bg_color: 0x16417d
      bg_opa: TRANSP
      widgets:
        - obj:
            x: -142
            y: 10
            align: TOP_MID
            width: 135
            height: 41
            border_color: 0xFFFFFF
            border_width: 2
            border_opa: 30%
            bg_color: 0x16417d
            bg_opa: 30%
            radius: 20
            scrollbar_mode: "off"
            pad_all: 0
            widgets:
              - label:
                  x: 15
                  y: 6
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: icons24
                  text_align: LEFT
                  id: lvgl_mami_battery_front_icon
                  text: "\U000F10CD"
              - label:
                  x: 45
                  y: 11
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: roboto14
                  text_align: LEFT
                  text: "Mami"
              - label:
                  x: 85
                  y: 11
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: roboto14
                  text_align: LEFT
                  id: lvgl_mami_battery_front
                  text: "--%"
        - obj:
            x: 2
            y: 10
            align: TOP_MID
            width: 125
            height: 41
            border_color: 0xFFFFFF
            border_width: 2
            border_opa: 30%
            bg_color: 0x16417d
            bg_opa: 30%
            radius: 20
            scrollbar_mode: "off"
            pad_all: 0
            widgets:
              - label:
                  x: 15
                  y: 6
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: icons24
                  text_align: LEFT
                  id: lvgl_papi_battery_front_icon
                  text: "\U000F10CD"
              - label:
                  x: 45
                  y: 11
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: roboto14
                  text_align: LEFT
                  text: "Papi"
              - label:
                  x: 80
                  y: 11
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: roboto14
                  text_align: LEFT
                  id: lvgl_papi_battery_front
                  text: "--%"
        - obj:
            x: 145
            y: 10
            align: TOP_MID
            width: 130
            height: 41
            border_color: 0xFFFFFF
            border_width: 2
            border_opa: 30%
            bg_color: 0x16417d
            bg_opa: 30%
            radius: 20
            scrollbar_mode: "off"
            pad_all: 0
            widgets:
              - label:
                  x: 15
                  y: 6
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: icons24
                  text_align: LEFT
                  id: lvgl_wifi_signal_percent_icon
                  text: "\U000F092F"
              - label:
                  x: 45
                  y: 11
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: roboto14
                  text_align: LEFT
                  text: "WiFi"
              - label:
                  x: 80
                  y: 11
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: roboto14
                  text_align: LEFT
                  id: lvgl_wifi_signal_percent
                  text: "--%"
        - label:
            id: lvgl_clock_longdate
            x: 40
            y: 110
            width: SIZE_CONTENT
            height: SIZE_CONTENT
            text_color: 0xFFFFFF
            text_font: roboto22
            text_align: LEFT
            text: " "
        - obj:
            x: -110
            y: 0
            align: CENTER
            width: 190
            height: 170
            border_color: 0xFFFFFF
            border_width: 2
            border_opa: 30%
            bg_color: 0x16417d
            bg_opa: 30%
            radius: 4
            scrollbar_mode: "off"
            pad_all: 0
            widgets:
              - label:
                  id: lvgl_clock_hour
                  x: 0
                  y: 0
                  align: CENTER
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: robotobold140
                  text_align: CENTER
                  text: "00"
        - obj:
            x: 110
            y: 0
            align: CENTER
            width: 190
            height: 170
            border_color: 0xFFFFFF
            border_width: 2
            border_opa: 30%
            bg_color: 0x16417d
            bg_opa: 30%
            radius: 4
            scrollbar_mode: "off"
            pad_all: 0
            widgets:
              - label:
                  id: lvgl_clock_minute
                  x: 0
                  y: 0
                  align: CENTER
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: robotobold140
                  text_align: CENTER
                  text: "00"
        - label:
            x: 0
            y: 0
            align: CENTER
            width: SIZE_CONTENT
            height: SIZE_CONTENT
            text_color: 0xFFFFFF
            text_font: robotobold96
            text_align: CENTER
            text: ":"

    - id: page_oralb
      bg_color: 0xFFFFFF
      bg_opa: TRANSP
      widgets:
        - obj:
            x: 40
            y: 20
            width: 190
            height: 40
            border_color: 0xFFFFFF
            border_width: 2
            border_opa: 30%
            bg_color: 0x16417d
            bg_opa: 30%
            radius: 4
            scrollbar_mode: "off"
            pad_all: 0
            widgets:
              - label:
                  x: 5
                  y: 7
                  width: 180
                  height: 30
                  text_color: 0xFFFFFF
                  text_font: roboto18
                  text_align: CENTER
                  text: "Papi"
        - obj:
            x: 250
            y: 20
            width: 190
            height: 40
            border_color: 0xFFFFFF
            border_width: 2
            border_opa: 30%
            bg_color: 0x16417d
            bg_opa: 30%
            radius: 4
            scrollbar_mode: "off"
            pad_all: 0
            widgets:
              - label:
                  x: 5
                  y: 7
                  width: 180
                  height: 30
                  text_color: 0xFFFFFF
                  text_font: roboto18
                  text_align: CENTER
                  text: "Mami"
        - obj:
            x: 40
            y: 70
            width: 190
            height: 90
            border_color: 0xFFFFFF
            border_width: 2
            border_opa: 30%
            bg_color: 0x16417d
            bg_opa: 30%
            radius: 4
            scrollbar_mode: "off"
            pad_all: 0
            widgets:
              - label:
                  x: 7
                  y: 20
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: icons32
                  text_align: LEFT
                  text: "\U000F1AE1"
              - label:
                  id: lvgl_papi_timer
                  x: 40
                  y: 7
                  width: 90
                  text_color: 0xFFFFFF
                  text_font: roboto48
                  text_align: RIGHT
                  text: "--"
              - label:
                  x: 140
                  y: 30
                  text_color: 0xFFFFFF
                  text_font: roboto22
                  text: "sek"
              - bar:
                  x: 15
                  y: 65
                  height: 10
                  width: 160
                  id: lvgl_papi_bar
                  min_value: 0
                  max_value: 180
                  bg_color: 0x363636
                  bg_opa: 40%
                  indicator:
                    bg_color: 0xFF0000
                    bg_opa: 80%
                    bg_grad_color: 0x00FF00
                    bg_grad_dir: HOR

        - obj:
            x: 250
            y: 70
            width: 190
            height: 90
            border_color: 0xFFFFFF
            border_width: 2
            border_opa: 30%
            bg_color: 0x16417d
            bg_opa: 30%
            radius: 4
            scrollbar_mode: "off"
            pad_all: 0
            widgets:
              - label:
                  x: 7
                  y: 20
                  width: SIZE_CONTENT
                  height: SIZE_CONTENT
                  text_color: 0xFFFFFF
                  text_font: icons32
                  text_align: LEFT
                  text: "\U000F1AE1"
              - label:
                  id: lvgl_mami_timer
                  x: 40
                  y: 7
                  width: 90
                  text_color: 0xFFFFFF
                  text_font: roboto48
                  text_align: RIGHT
                  text: "--"
              - label:
                  x: 140
                  y: 30
                  text_color: 0xFFFFFF
                  text_font: roboto22
                  text: "sek"
              - bar:
                  x: 15
                  y: 65
                  height: 10
                  width: 160
                  id: lvgl_mami_bar
                  min_value: 0
                  max_value: 180
                  bg_color: 0x363636
                  bg_opa: 40%
                  indicator:
                    bg_color: 0xFF0000
                    bg_opa: 80%
                    bg_grad_color: 0x00FF00
                    bg_grad_dir: HOR

        - obj:
            x: 40
            y: 170
            styles: panelwithouttimer
            widgets:
              - label:
                  styles: label_icon
                  text: "\U000F01FB"
              - label:
                  styles: label_name
                  text: "Reinigung"
              - label:
                  id: lvgl_papi_mode
                  styles: label_value
                  text: "--"

        - obj:
            x: 250
            y: 170
            styles: panelwithouttimer
            widgets:
              - label:
                  styles: label_icon
                  text: "\U000F01FB"
              - label:
                  styles: label_name
                  text: "Reinigung"
              - label:
                  id: lvgl_mami_mode
                  styles: label_value
                  text: "--"

        - obj:
            x: 40
            y: 245
            styles: panelwithouttimer
            widgets:
              - label:
                  styles: label_icon
                  text: "\U000F0199"
              - label:
                  styles: label_name
                  text: "Sektor"
              - label:
                  id: lvgl_papi_sector
                  styles: label_value
                  text: "--"

        - obj:
            x: 250
            y: 245
            styles: panelwithouttimer
            widgets:
              - label:
                  styles: label_icon
                  text: "\U000F0199"
              - label:
                  styles: label_name
                  text: "Sektor"
              - label:
                  id: lvgl_mami_sector
                  styles: label_value
                  text: "--"

        - obj:
            x: 40
            y: 320
            styles: panelwithouttimer
            widgets:
              - label:
                  styles: label_icon
                  text: "\U000F029A"
              - label:
                  styles: label_name
                  text: "BĂŒrstendruck"
              - label:
                  id: lvgl_papi_pressure
                  styles: label_value
                  text: "--"

        - obj:
            x: 250
            y: 320
            styles: panelwithouttimer
            widgets:
              - label:
                  styles: label_icon
                  text: "\U000F029A"
              - label:
                  styles: label_name
                  text: "BĂŒrstendruck"
              - label:
                  id: lvgl_mami_pressure
                  styles: label_value
                  text: "--"

        - obj:
            x: 40
            y: 395
            styles: panelwithouttimer
            widgets:
              - label:
                  id: lvgl_papi_battery_icon
                  styles: label_icon
                  text: "\U000F0948"
              - label:
                  styles: label_name
                  text: "Batteriestand"
              - label:
                  id: lvgl_papi_battery
                  styles: label_value
                  text: "--"

        - obj:
            x: 250
            y: 395
            styles: panelwithouttimer
            widgets:
              - label:
                  id: lvgl_mami_battery_icon
                  styles: label_icon
                  text: "\U000F0948"
              - label:
                  styles: label_name
                  text: "Batteriestand"
              - label:
                  id: lvgl_mami_battery
                  styles: label_value
                  text: "--"

ESPHome LVGL Graphics
ESPHome LVGL Tipps
ESPHome LVGL Widgets
GitHub LVGL Esphome Samples (glĂŒcklicherweise fĂŒr den Sensecap)
HA Forum LVGL auf einem Guition 4" Display

FĂŒr Designer gibts noch das Squareline Studio https://squareline.io/, bei Registration gibts eine Einzel-Lizenz. Damit hab ich das Design fĂŒr Espressif gemacht, es ist nur bedingt fĂŒr ESPHome geeignet da es keinen Yaml-Code ausspuckt, aber um die ganzen Koordinaten schon zu haben und die Möglichkeiten auszuschöpfen ist es allemal gut.

Nun
viel Spass beim Designen


2 „GefĂ€llt mir“

Also bei meiner iO10 war noch so eine Uhr mit allen Daten mit dabei :crazy_face::partying_face:

VIELEN DANK - da steckt SO viel drin fĂŒr einen passionierten Abkupferer wie mich. Aktuell arbeite ich daran, ein paar WT32-SC01-PLUS Panels mit ESPhome zu versorgen - Dein Beispiel hat mir sehr, sehr geholfen.

Wenn es weiter fortgeschritten ist, stelle ich die Config mal ein.