ePaper XIAO 7.5″ mit Home Assistant verbinden – ganz schnell mit Screenshot-Trick!

Du willst dein Home Assistant Dashboard auf einem stromsparenden E-Ink Display anzeigen? In diesem Beitrag zeige ich dir zwei Möglichkeiten, wie du das 7.5 Zoll große ePaper Display von Seeed Studio mit ESPHome nutzen kannst – inklusive Deep-Sleep-Unterstützung und Screenshot-Trick per Puppet Add-on.

▶️ Das passende YouTube-Video mit allen Details findest du hier:

https://youtu.be/j_XxQwnzzRU

📦 Gerät kaufen

Du bekommst das „Seeed XIAO ESP32S3 mit 7.5“ E-Ink Panel“ hier:

Zum Produkt (mit 5% Rabattcode „X0FKM5CS“)

Du unterstützt damit meinen Kanal – ohne Mehrkosten für dich, aber mit einer kleinen Provision für mich. Danke!

📀 Windows-Treiber installieren

Wenn der COM-Port beim ersten Anschluss nicht automatisch erkannt wird, benötigst du diesen Treiber:

NodeMCU USB-Treiber (GitHub)

🧵 3D-Druck-Modelle für die Wandmontage

Es gibt bereits mehrere passende Modelle für eine Wandhalterung auf Makerworld:

Standard-Wandhalterung

Magnet-Wandhalterung

⚖️ Möglichkeit #1: Individuelles Dashboard zeichnen (aufwändig)

Mit ESPHome kannst du das Display direkt per Code gestalten – pixelgenau und individuell. Das ist mächtig, aber komplex.

Hier ein vollständiges Beispiel inkl.:

  • Deep-Sleep-Support
  • Kalenderdaten
  • Wetteranzeige
  • Pool- und Gartentemperatur
  • PV-Überschuss

Folgenden Code bitte unter ota: einfügen.

Sollte oberhalb dieses Eintrages noch ein Zeilen mit wifi: oder captive_portal: stehen, diese vorher löschen!

globals:
  - id: wifi_status
    type: int
    restore_value: no
    initial_value: "0"
  - id: first_update_done
    type: bool
    restore_value: no
    initial_value: "false"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  on_connect:
    then:
      - lambda: |-
          id(wifi_status) = 1;
  on_disconnect:
    then:
      - lambda: |-
          id(wifi_status) = 0;


captive_portal:

# Here is deep sleep part
deep_sleep:
  id: deep_sleep_1
  run_duration: 1min  # Device wake up and run 60s (enough to pull data and update)
  sleep_duration: 60min  # deep sleep for 1h

script:
  - id: update_display
    then:
      - component.update: my_display

interval:
  # Condition: wifi connected && data retrieved && first time
  - interval: 10s  # Check every second
    then:
      - if:
          condition:
            and:
              - wifi.connected:
              - lambda: "return !id(ha_calendar_event_1).state.empty();"
              - lambda: "return !id(first_update_done);"
          then:
            - lambda: |-
                ESP_LOGD("Display", "Updating Display...");
            - script.execute: update_display  # Refresh immediately
            - lambda: "id(first_update_done) = true;"
  - interval: 59s  # run this command before 1s of run_duration end
    then:
      - logger.log: "Entering deep sleep now..."


image:
  - file: image/wifi.jpg
    type: BINARY
    id: esphome_logo
    resize: 400x240
    invert_alpha: true

# Connect to Home Assistant to get time
time:
  - platform: homeassistant
    id: homeassistant_time

text_sensor:
  - platform: homeassistant
    id: ha_calendar_event_1
    entity_id: calendar.familienkalender_google
    attribute: "message"
  - platform: homeassistant
    id: ha_calendar_start_time_1
    entity_id: calendar.familienkalender_google
    attribute: "start_time"
  - platform: homeassistant
    id: ha_calendar_end_time_1
    entity_id: calendar.familienkalender_google
    attribute: "end_time"

  - platform: homeassistant
    entity_id: weather.openweathermap
    id: myWeather
  - platform: homeassistant
    entity_id: sensor.pool_temperatur
    id: temp
  - platform: homeassistant
    entity_id: sensor.garten_temperatur
    id: humi
  - platform: homeassistant
    entity_id: binary_sensor.wc_fenster
    id: press
  - platform: homeassistant
    entity_id: sensor.pv_uberschuss_15min
    id: wind

font:
  - file: "fonts/Montserrat-Black.ttf"
    id: web_font
    size: 20
  - file: "fonts/Montserrat-Black.ttf"
    id: data_font
    size: 30
  - file: "fonts/Montserrat-Black.ttf"
    id: sensor_font
    size: 22

  - file: "gfonts://Inter@700" #
    id: font1
    size: 24

  - file: 'fonts/materialdesignicons-webfont.ttf' # Directory to save ttf file
    id: font_mdi_large
    size: 200
    glyphs: &mdi-weather-glyphs # https://pictogrammers.com/library/mdi/
      - "\U000F050F" # Thermometer
      - "\U000F058E" # Humidity
      - "\U000F059D" # Wind speed
      - "\U000F0D60" # Atmospheric pressure
      - "\U000F0590" # Cloudy weather
      - "\U000F0596" # Rainy weather
      - "\U000F0598" # Snowy weather
      - "\U000F0599" # Sunny weather
      - "\U000F11DC" # Windows
      - "\U000F0D9C" # Solarpanel
  - file: 'fonts/materialdesignicons-webfont.ttf'
    id: font_weather # Copy the above icon and change the size to 40
    size: 200
    glyphs: *mdi-weather-glyphs
  - file: 'fonts/materialdesignicons-webfont.ttf'
    id: img_font_sensor # Copy the above icon and change the size to 40
    size: 70
    glyphs: *mdi-weather-glyphs

spi:
  clk_pin: GPIO8
  mosi_pin: GPIO10

display:
  - platform: waveshare_epaper
    id: my_display
    cs_pin: GPIO3
    dc_pin: GPIO5
    busy_pin: 
      number: GPIO4
      inverted: true
    reset_pin: GPIO2
    model: 7.50inv2
    update_interval: 50s
    lambda: |-
      if(id(wifi_status) == 0){
        it.image(180, 0, id(esphome_logo));
        it.print(230, 300, id(data_font), "WI-FI CONNECTING");
      }else{
        // Draw weather images here
        std::string weather_string = id(myWeather).state.c_str();
        if(weather_string == "rainy" || weather_string == "lightning" || weather_string == "pouring"){
          // Draw rainy weather image
          it.printf(120, 85, id(font_weather), TextAlign::CENTER, "\U000F0596");
        }else if(weather_string == "snowy"){
          // Draw snowy weather image
          it.printf(120, 85, id(font_weather), TextAlign::CENTER, "\U000F0598");
        }else if(weather_string == "sunny" || weather_string == "windy"){
          // Draw sunny weather image
          it.printf(120, 85, id(font_weather), TextAlign::CENTER, "\U000F0599");
        }else{
          // Draw cloudy weather image
          it.printf(120, 85, id(font_weather), TextAlign::CENTER, "\U000F0590");
        }

        auto time_now = id(homeassistant_time).now();
        // Month conversion
        const char* months[] = {
          "Januar", "Februar", "März", "April", "Mai", "Juni",
          "Juli", "August", "September", "Oktober", "November", "Dezember"
        };
        const char* month_str = months[time_now.month - 1];  // Month index starts from 0
        // Get the day
        int day = time_now.day_of_month;
        // Draw the date
        it.printf(250, 110, id(data_font), "%s %d", month_str, day);
        // Get the day of the week
        const char* days[] = {"Samstag", "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag"};
        const char* day_of_week = days[time_now.day_of_week];
        it.printf(250, 70, id(data_font), "%s", day_of_week);

        int x = 20, y = 180, w = 180, h = 120, r = 10, thickness = 4;
        // Draw four borders
        it.filled_rectangle(x + r, y, w - 2 * r, thickness); // Top border
        it.filled_rectangle(x + r, y + h - thickness, w - 2 * r, thickness); // Bottom border
        it.filled_rectangle(x, y + r, thickness, h - 2 * r); // Left border
        it.filled_rectangle(x + w - thickness, y + r, thickness, h - 2 * r); // Right border
        // Draw four rounded corners
        it.filled_circle(x + r, y + r, r); // Top-left corner
        it.filled_circle(x + w - r, y + r, r); // Top-right corner
        it.filled_circle(x + r, y + h - r, r); // Bottom-left corner
        it.filled_circle(x + w - r, y + h - r, r); // Bottom-right corner
        // Fill the inside with black to form a border
        it.filled_rectangle(x + thickness, y + thickness, w - 2 * thickness, h - 2 * thickness, COLOR_OFF);
        // Temperature
        it.printf(x+10, y+10, id(sensor_font), "Temp. Pool");
        it.printf(x+45, y+75, id(img_font_sensor), TextAlign::CENTER, "\U000F050F");
        // Get temperature data
        it.printf(x+75,y+65, id(data_font), "%s°C", id(temp).state.c_str());

        x = 220;
        y = 180;
        // Draw four borders
        it.filled_rectangle(x + r, y, w - 2 * r, thickness); // Top border
        it.filled_rectangle(x + r, y + h - thickness, w - 2 * r, thickness); // Bottom border
        it.filled_rectangle(x, y + r, thickness, h - 2 * r); // Left border
        it.filled_rectangle(x + w - thickness, y + r, thickness, h - 2 * r); // Right border
        // Draw four rounded corners
        it.filled_circle(x + r, y + r, r); // Top-left corner
        it.filled_circle(x + w - r, y + r, r); // Top-right corner
        it.filled_circle(x + r, y + h - r, r); // Bottom-left corner
        it.filled_circle(x + w - r, y + h - r, r); // Bottom-right corner
        // Fill the inside with black to form a border
        it.filled_rectangle(x + thickness, y + thickness, w - 2 * thickness, h - 2 * thickness, COLOR_OFF);
        // Humidity
        it.printf(x+10, y+10, id(sensor_font), "Temp. Garten");
        it.printf(x+45, y+75, id(img_font_sensor), TextAlign::CENTER, "\U000F050F");
        // Get humidity data
        it.printf(x+75,y+65, id(data_font), "%s°C", id(humi).state.c_str());

        x = 20;
        y = 320;
        // Draw four borders
        it.filled_rectangle(x + r, y, w - 2 * r, thickness); // Top border
        it.filled_rectangle(x + r, y + h - thickness, w - 2 * r, thickness); // Bottom border
        it.filled_rectangle(x, y + r, thickness, h - 2 * r); // Left border
        it.filled_rectangle(x + w - thickness, y + r, thickness, h - 2 * r); // Right border
        // Draw four rounded corners
        it.filled_circle(x + r, y + r, r); // Top-left corner
        it.filled_circle(x + w - r, y + r, r); // Top-right corner
        it.filled_circle(x + r, y + h - r, r); // Bottom-left corner
        it.filled_circle(x + w - r, y + h - r, r); // Bottom-right corner
        // Fill the inside with black to form a border
        it.filled_rectangle(x + thickness, y + thickness, w - 2 * thickness, h - 2 * thickness, COLOR_OFF);
        // Air Pressure
        it.printf(x+10, y+10, id(sensor_font), "Fenster offen");
        it.printf(x+45, y+75, id(img_font_sensor), TextAlign::CENTER, "\U000F11DC");
        // Get atmospheric pressure data
        it.printf(x+85,y+50, id(data_font), "%s", id(press).state.c_str());
        //it.printf(x+85,y+78, id(sensor_font), "inHg");

        x = 220;
        y = 320;
        // Draw four borders
        it.filled_rectangle(x + r, y, w - 2 * r, thickness); // Top border
        it.filled_rectangle(x + r, y + h - thickness, w - 2 * r, thickness); // Bottom border
        it.filled_rectangle(x, y + r, thickness, h - 2 * r); // Left border
        it.filled_rectangle(x + w - thickness, y + r, thickness, h - 2 * r); // Right border
        // Draw four rounded corners
        it.filled_circle(x + r, y + r, r); // Top-left corner
        it.filled_circle(x + w - r, y + r, r); // Top-right corner
        it.filled_circle(x + r, y + h - r, r); // Bottom-left corner
        it.filled_circle(x + w - r, y + h - r, r); // Bottom-right corner
        // Fill the inside with black to form a border
        it.filled_rectangle(x + thickness, y + thickness, w - 2 * thickness, h - 2 * thickness, COLOR_OFF);
        // Wind Speed
        it.printf(x+10, y+10, id(sensor_font), "PV Ueberschuss");
        it.printf(x+45, y+75, id(img_font_sensor), TextAlign::CENTER, "\U000F0D9C");
        // Get wind speed data
        it.printf(x+85,y+50, id(data_font), "%s", id(wind).state.c_str());

        // Draw a vertical line
        it.filled_rectangle(430, 30, 5, 430);
        // Right section
        it.printf(540, 40, id(data_font), "Kalender");

        // Define event structure
        struct Event {
            std::string message;
            std::string start_time;
            std::string end_time;
            time_t start_timestamp;
        };

        // Parse time string to time_t (UNIX timestamp)
        auto parse_time = [](const std::string &time_str) -> time_t {
            struct tm timeinfo = {};
            if (strptime(time_str.c_str(), "%Y-%m-%d %H:%M:%S", &timeinfo) == nullptr) {
                return 0;  // Invalid time
            }
            return mktime(&timeinfo);
        };

        // Create event list
        std::vector<Event> events = {
            {id(ha_calendar_event_1).state, id(ha_calendar_start_time_1).state, id(ha_calendar_end_time_1).state, parse_time(id(ha_calendar_start_time_1).state)}
        };
        ESP_LOGD("myCalendar", "Start Time: %s -> %ld", id(ha_calendar_start_time_1).state.c_str(), parse_time(id(ha_calendar_start_time_1).state));

        // Filter invalid events (start_timestamp == 0)
        events.erase(std::remove_if(events.begin(), events.end(), [](const Event &e) { return e.start_timestamp == 0; }), events.end());

        // Sort by `start_timestamp` (earliest to latest)
        std::sort(events.begin(), events.end(), [](const Event &a, const Event &b) {
            return a.start_timestamp < b.start_timestamp;
        });

        // Define a function to format time
        auto format_time = [](std::string time_str) -> std::string {
            struct tm timeinfo;
            if (strptime(time_str.c_str(), "%Y-%m-%d %H:%M:%S", &timeinfo) == nullptr) {
                return "Invalid";
            }
            char buffer[10];
            strftime(buffer, sizeof(buffer), "%I:%M%p", &timeinfo); // Convert to 12-hour format
            return std::string(buffer);
        };
        // Parse date
        auto format_date = [](const std::string &time_str) -> std::string {
            struct tm timeinfo = {};
            if (strptime(time_str.c_str(), "%Y-%m-%d %H:%M:%S", &timeinfo) == nullptr) {
                return "Invalid";
            }
            char buffer[6];  // Need to store "MM-DD\0"
            strftime(buffer, sizeof(buffer), "%m-%d", &timeinfo);
            return std::string(buffer);
        };

        // Draw events
        int even_x_start_offset = 460;
        int even_y_start_offset = 80;
        for (const auto &event : events) {
          if(even_y_start_offset >= 420){
            break;
          }

          // Format time
          std::string formatted_date = format_date(event.start_time);
          std::string formatted_start_time = format_time(event.start_time);
          std::string formatted_end_time = format_time(event.end_time);

          // Combine time range string
          std::string time_range = formatted_start_time + " - " + formatted_end_time;
          time_range = formatted_date + "  " + time_range;
          if(formatted_start_time == "Invalid" || formatted_end_time == "Invalid"){
            time_range.clear();
          }
          // Display time range, e.g., "10:00AM - 11:00AM"
          it.printf(even_x_start_offset, even_y_start_offset, id(sensor_font), "%s", time_range.c_str());
          even_y_start_offset += 30;
          // Display event name
          it.printf(even_x_start_offset, even_y_start_offset, id(sensor_font), "%s", event.message.c_str());
          even_y_start_offset += 40;
        }
      }

Hinweis: Diese Variante lohnt sich, wenn du ein sehr spezielles Layout willst. Für alle anderen empfehle ich…

Möglichkeit #2 mit Puppet

🤖 Möglichkeit #2: Puppet Add-on + Screenshot = Dashboard ohne Aufwand!

Mit dem Puppet Add-on kannst du einfach dein Home Assistant Dashboard als Screenshot anzeigen lassen. Du brauchst:

Folgend der Code für mein Dashboard

  - type: sections
    max_columns: 4
    title: Flur
    path: flur
    sections:
      - type: grid
        cards:
          - type: tile
            entity: sensor.pv_uberschuss_15min
            features_position: bottom
            vertical: true
            name: PV Überschuss
            icon: mdi:solar-panel-large
            show_entity_picture: false
          - type: tile
            entity: sensor.pool_temperatur
            features_position: bottom
            vertical: true
            icon: mdi:pool-thermometer
          - type: entity-filter
            entities:
              - entity: binary_sensor.wc_fenster
              # - ... eure zu überwachenden Entitäten für "Fenster / Tür auf"
            state_filter:
              - 'on'
            card:
              type: entities
          - type: entity-filter
            entities:
              - switch.wz_mehrfachsteckdose_aquariumlicht
              - light.bad_stripe
              # - ... eure zu überwachenden Entitäten für "Licht an"

            state_filter:
              - 'on'
            card:
              type: entities
      - type: grid
        cards:
          - clock_size: small
            show_seconds: false
            type: clock
            title: Letzte Aktualisierung
            grid_options:
              columns: 12
              rows: 1
          - initial_view: dayGridDay
            type: calendar
            entities:
              - calendar.familienkalender_google # eure Kalenderentität

ESP Code zum Testen ohne Deep-Sleep

esphome:
  name: edisplayflur
  friendly_name: eDisplayFlur

esp32:
  board: esp32-c3-devkitm-1
  framework:
    type: esp-idf

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "HUk+qHsrRe/WROKX4Snb/3wVBPMF1sxy2R2uMSp+gwU="

ota:
  - platform: esphome
    password: "b07af141786f53d8db43bdc67b9010fc"


wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

captive_portal:

# Hier ist der auskommentierte Deep-Sleep Part
#deep_sleep:
#  id: deep_sleep_1
#  run_duration: 1min  # Device wake up and run 60s (enough to pull data and update)
#  sleep_duration: 60min  # deep sleep for 1h#

http_request:
  verify_ssl: false
  timeout: 30s
  watchdog_timeout: 15s

online_image:
  - id: dashboard_image
    format: BMP
    type: BINARY
    buffer_size: 25000
    url: http://192.168.1.83:10000/lovelace/flur?viewport=800x480&eink=2&format=bmp&invert
    update_interval: 120sec
    on_download_finished:
      - delay: 0ms
      - component.update: main_display

spi:
  clk_pin: GPIO8
  mosi_pin: GPIO10

display:
  - platform: waveshare_epaper
    id: main_display
    cs_pin: GPIO3
    dc_pin: GPIO5
    busy_pin: 
      number: GPIO4
      inverted: true
    reset_pin: GPIO2
    model: 7.50inv2
    update_interval: never
    lambda: |-
      it.image(0, 0, id(dashboard_image));

Der fertige Code für ESP Home mit Deep Sleep

esphome:
  name: edisplayflur
  friendly_name: eDisplayFlur

esp32:
  board: esp32-c3-devkitm-1
  framework:
    type: esp-idf

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "HUk+qHsrRe/WROKX4Snb/3wVBPMF1sxy2R2uMSp+gwU="

ota:
  - platform: esphome
    password: "b07af141786f53d8db43bdc67b9010fc"


wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

captive_portal:

# Hier ist der aktivierte Deep-Sleep Part
deep_sleep:
  id: deep_sleep_1
  run_duration: 1min  # Device wake up and run 60s (enough to pull data and update)
  sleep_duration: 60min  # deep sleep for 1h

http_request:
  verify_ssl: false
  timeout: 30s
  watchdog_timeout: 15s

online_image:
  - id: dashboard_image
    format: BMP
    type: BINARY
    buffer_size: 25000
    url: http://192.168.1.83:10000/lovelace/flur?viewport=800x480&eink=2&format=bmp&invert
    update_interval: 120sec
    on_download_finished:
      - delay: 0ms
      - component.update: main_display

spi:
  clk_pin: GPIO8
  mosi_pin: GPIO10

display:
  - platform: waveshare_epaper
    id: main_display
    cs_pin: GPIO3
    dc_pin: GPIO5
    busy_pin: 
      number: GPIO4
      inverted: true
    reset_pin: GPIO2
    model: 7.50inv2
    update_interval: never
    lambda: |-
      it.image(0, 0, id(dashboard_image));

Hinweis: Beim Arbeiten mit Deep Sleep musst du für neue Uploads wie hier beschrieben vorgehen:
Seeed FAQ zu Deep Sleep

✅ Fazit

Das XIAO 7.5″ ePaper Display ist eine super Möglichkeit, dein Home Assistant Dashboard elegant und stromsparend anzuzeigen. Du hast zwei Optionen:

  • Individuelle Anzeige per Code: Flexibel, aber aufwändig
  • Screenshot mit Puppet: Schnell, einfach, wartungsarm

Ich nutze die zweite Methode für die meisten Anwendungsfälle – vor allem mit Deep Sleep für lange Batterielaufzeit.


Kommentare

15 Antworten zu „ePaper XIAO 7.5″ mit Home Assistant verbinden – ganz schnell mit Screenshot-Trick!“

  1. Avatar von LazyBee

    Danke für den ausführlichen Bericht.
    Ich versuche die erste variante zum laufen zu bekommen und scheitere an dieser Stelle:
    image:
    – file: image/wifi.jpg
    type: BINARY
    id: esphome_logo
    resize: 400×240
    invert_alpha: true

    Wo bekomme ich das image her und wo lege ich das ab?

  2. Ich habe mir ebenfalls das ePaper Display angeschafft und es mit der Methode 2 versucht.
    In deinem Video sagst du, du hast es mit PNG nicht hinbekommen, das hat allerdings nichts mit dem Addon Puppet zu tun.

    Wir starten aber erst mal vorne.

    Das XIAO 7.5″ ePaper Panel von Seed Studio läuft mit einem ESP32-C3.
    (in deiner Anleitung schreibst du „Du bekommst das „Seeed XIAO ESP32S3 mit 7.5“ E-Ink Panel“ hier:“ Es ist allerdings kein ESP32S3)

    Wir kriegen also einen ESP32-C3, dieser hat allerdings nur 400 kB SRAM.
    Das ist schon ziemlich grenzwertig für ein 7,5″ ePaper Display.

    Ich habe es anfangs auch mit BMP versucht und die buffer size auf 25000 gesetzt.
    Es spielt übrigens keine Rolle wie hoch man die buffer size setzt, dieser wird dynamisch angepasst, wenn er nicht ausreicht.

    [15:49:04] Downloading image (Size: 48062)
    [15:49:08] Image fully downloaded, read 48062 bytes, width/height = 800/480

    Das Problem ist nur, der geringe SRAM reicht nicht immer um Bilder mit der Größe zu verarbeiten.

    [E][online_image:092]: allocation of 48000 bytes failed. Biggest block in heap: 43008 Bytes
    In dem Fall hatte der ESP32-C3 im Heat nur 43 008 Bytes am Stück frei, reicht also nicht. und die Allokation scheitert.

    Ergebnis ist, manchmal wird ein Bild übertragen, manchmal nicht.
    Je nachdem, wie der ESP gerade so ausgelastet ist.

    Also habe ich es mit PNG versucht.
    Puppet liefert das Bild mit 496 Bytes also super klein.
    Der PNG-Decoder muss das Bild aber im Ram größer machen.
    Bei 800×480 braucht er trotzdem ~48 kB Puffer, egal wie stark komprimiert die Datei ist.
    Auch da, passiert letztlich das gleiche.
    Abbruch weil zu wenig Ram.
    [16:14:00][D][online_image:089]: Allocating new buffer of 48000 bytes
    [16:14:00][E][online_image:092]: allocation of 48000 bytes failed. Biggest block in heap: 34816 Bytes
    [16:14:00][E][online_image.png:086]: Error decoding image: N\xc6V²\x89\xae\x8aPII“\xcc*\x84&\xcaJ\xc8R\xc4\xce6\x89\xba\x84
    [16:14:00]\xef\xf0?\xebc\x8c
    [16:14:00][E][online_image:250]: Error when decoding image.

    Die einzige Lösung hierbei ist mit der Auflösung runter zu gehen.
    Damit wird das Ergebnis aber nicht wirklich schön

    Vielleicht hat noch wer eine andere Idee?

    Mit dem ESP32-C3 ist die Methode 2 jedenfalls nicht wirklich umsetzbar.

    1. hatte das gleiche Problem. Mein Thema war, dass ich ein Dashboard von HomeAssistant auf dem Display abbilden wollte und das ging so nicht, wie beschrieben aus eben diesen RAM-Limit-Problem und dann gabs softwareseitig noch ein Thema im ESPHome.
      Das Display verkraftet auch jpg. Mit den Einstellungen klappt es dann:
      online_image:
      – id: dashboard_image
      format: jpeg
      type: BINARY
      buffer_size: 32000

      Als Screenshotter für das Display nehme ich übrigens das HA-Addon hier, hat etwas gedauert, bis ich was für mich funktionierendes gefunden hab: „Dashboard Image Renderer“, hier das Repository ist das: https://github.com/iclanton/hass-dashboard-renderer

      1. Hi. Kannst du vielleicht mal deinen ganzen ESP Code hier rein stellen?! Ich habe es mit dem dashboard-renderer versucht und der legt auch tatsächlich das Bild ab, so dass ich manuell über den Port 5000 drauf zugreifen kann. Aber ich kriege das Epaper Display per ESP Code nicht dazu, dieses abzurufen. Es wirft noch nicht mal eine richtige Fehlermeldung aus, sondern sagt nur er bricht den Kontakt zur API ab. Eventuell würde mir dein Code weiterhelfen, bei dir scheint es ja zu funktionieren?! Danke..:))

  3. Avatar von Christoph

    Ich versuche gerade das Display zu programmieren, aber ich bekomme beim Kompilieren des Quellcodes die folgende Fehlermeldung:

    Reading CMake configuration…
    — git rev-parse returned ‚fatal: not a git repository (or any parent up to mount point /)
    Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).‘
    — Building ESP-IDF components for target esp32c3
    Processing 3 dependencies:
    [1/3] espressif/mdns (1.8.2)
    [2/3] zorxx/multipart-parser (1.0.1)
    [3/3] idf (5.4.2)
    — Configuring incomplete, errors occurred!

    fatal: not a git repository (or any parent up to mount point /)
    Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).
    CMake Error at /data/cache/platformio/packages/framework-espidf/tools/cmake/component.cmake:155 (message):
    Directory ‚/data/build/xiao-epaper/managed_components/espressif__mdns‘ does
    not contain a component.
    Call Stack (most recent call first):
    /data/cache/platformio/packages/framework-espidf/tools/cmake/build.cmake:318 (__component_add)
    .pioenvs/xiao-epaper/managed_components_list.temp.cmake:1 (idf_build_component)
    /data/cache/platformio/packages/framework-espidf/tools/cmake/build.cmake:623 (include)
    /data/cache/platformio/packages/framework-espidf/tools/cmake/project.cmake:718 (idf_build_process)
    CMakeLists.txt:3 (project)

    Was kann der Fehler sein, ich habe das aktuelle Add-on?
    Gruß Christoph

    1. Avatar von Christoph

      Wie auch immer, nachdem ich das Projekt gelöscht und wieder neu aufgesetzt habe, funktioniert es ansatzweise.
      Die Verbindung des Displays mit HA ist recht unzuverlässig, es wird immer wieder von der API getrennt und kann dann kein Update machen, na das werde ich noch weiter klären!

      1. Hallo. Wäre cool, wenn du mir mal deinen ESP Code teilen könntest. Ich habe auch das Problem, dass er von der API trennt, aber bei mir hat es noch nie geklappt, das Bild vom Dashboard zu holen. Komme da nicht weiter. 🙁

        1. Avatar von Christoph

          Also, wie gesagt: die Verbindung ist nicht zuverlässig!
          Aber nichts desto trotz, hier der Code:

          esphome:
          name: xiao-epaper
          friendly_name: XIAO ePaper

          esp32:
          board: esp32-c3-devkitm-1
          framework:
          type: esp-idf

          # Enable logging
          logger:

          # Enable Home Assistant API
          api:
          encryption:
          key: „gLIbC2Pe+1/MosHIla3KuL3Sce+eedXvRsn8cV292j0=“

          ota:
          – platform: esphome

          wifi:
          ssid: !secret wifi_ssid
          password: !secret wifi_password

          # Enable fallback hotspot (captive portal) in case wifi connection fails
          ap:
          ssid: „Xiao-Epaper Fallback Hotspot“
          password: !secret wifi_heimat_password

          captive_portal:

          web_server:
          version: 2

          http_request:
          verify_ssl: false
          timeout: 30s
          watchdog_timeout: 15s

          online_image:
          – id: dashboard_image
          format: BMP
          type: BINARY
          buffer_size: 25000
          url: http://192.168.0.78:10000/lovelace/kalender?viewport=800×480&eink=2&format=bmp&invert&next=30
          update_interval: 120sec
          on_download_finished:
          – delay: 0ms
          – component.update: main_display

          spi:
          clk_pin: GPIO8
          mosi_pin: GPIO10

          display:
          – platform: waveshare_epaper
          id: main_display
          cs_pin: GPIO3
          dc_pin: GPIO5
          busy_pin:
          number: GPIO4
          inverted: true
          reset_pin: GPIO2
          model: 7.50inv2
          update_interval: never
          lambda: |-
          it.image(0, 0, id(dashboard_image));

          Bekommst Du denn eine Verbindung zu HA hin? Im Code habe ich den webServer aktiviert, da kann man dann recht einfach dem Display über die Schulter schauen.
          Und als Erweiterung zum Code auf dieser Seite habe ich den Paramter next=30 an die URL für den Screenshot angehängt

      2. Hi Christoph, dass die Verbindung getrennt wird, ist doch ganz normal und gewollt.
        Wir arbeiten doch mit einem Deep Sleep, der nach 1Minute den ESP in den Schalfmodus versetzt und dann die WLAN Verbindung kappt.
        Wenn du ohne USB Kabel länger mit dem Gerät kommunizieren möchtest, musst du hier den Wert erhöhen
        # Here is deep sleep part
        deep_sleep:
        id: deep_sleep_1
        run_duration: 1min # Device wake up and run 60s (enough to pull data and update) <==================================== sleep_duration: 180min # deep sleep for 3h

        1. Avatar von Christoph

          Wenn ich es recht verstehe, habe ich den Deep Sleep nicht eingeschaltet.
          Ich meine ja auch nur, das die Verbindung nicht stabil ist. Gerade habe ich festgestellt, das ich nun eine recht gute Anzeige hinbekommen habe, aber dann beim nächsten Update braucht Puppet zu lange für die Seite, und es kommen seltsame Fehlermeldungen auf dem Display. Ich habe auf der Seite einen CalDav eingefügt, der scheint dazu zu führen, das das gesamte Timing durcheinander gerät. Wenn ich die Dashboardseite im Browser öffne, ist die Anzeige so, wie es erwarte. Aber auf dem ePaper wird mir angezeigt, das es einen Konfigurationsfehlergibt, beim nächsten Mal ist die Seite leer usw. Wohlgemerkt ist der Screenshot gemeint, das Log sagt immer, das alles richtig läuft!

    2. Hi Christoph, ist ein bekanntes Problem von ESP Home. Einmal Addon neustarten sollte das Problem beheben.

      1. Avatar von Christoph

        Na dann werde ich das mal tun und ausprobieren!
        Danke jedenfalls für den Tip

      2. Avatar von Christoph

        Na der Neustart hat nicht geholfen, das Problem mit dem Disconnect tritt jetzt dauerhaft auf, immer nachdem die Seite mit dem Screenshot angefordert wird.
        Danach wird zwar die Verbindung neu aufgebaut, aber deshalb wir die Seite dauerhaft nicht geladen. Das Display ist so nicht zu verwenden und wandert erstmal in den Schrank.

        Noch ein Hinweis:
        Beim Kompilieren werden die Strapping-pins 2 und 8 mit Warnungen belegt, diese kann man mit der folgenden Erweiterung des Quellcodes entfernen:

        spi:
        clk_pin:
        number: GPIO8
        ignore_strapping_warning: True
        mosi_pin: GPIO10

        und im display:

        reset_pin:
        number: GPIO2
        ignore_strapping_warning: True

  4. Kann es sein, dass nach dem letzten Puppet Update dieses nicht mehr BMP ausgibt?

Schreibe einen Kommentar zu Benny Antwort abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert