Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Praktische Anwendungen (Showcase)
    4. Vorstellung: e-Ink display für Hausstatus

    NEWS

    • 15. 05. Wartungsarbeiten am ioBroker Forum

    • Monatsrückblick - April 2025

    • Minor js-controller 7.0.7 Update in latest repo

    Vorstellung: e-Ink display für Hausstatus

    This topic has been deleted. Only users with topic management privileges can see it.
    • L
      lxs last edited by

      Hallo,

      Ich würde euch gerne mein kleines Projekt vorstellen. Ich habe mir ein Display gebaut, welches ich an der Haustüre innen verbauen will, so dass ich auf einen Blick sehe ob z.B. noch Fenster offen sind. Ausserdem habe ich gleich noch eine Anwesenheitserkennung mit aufgebaut.

      Eingesetzt habe ich:

      • Olimex ESP32-POE-ISO Board: Bluetooth Low Energy Scanner und Ansteuerung für das Display
      • Waveshare 400x300, 4.2inch E-Ink raw display (Artikelnr. 13186)
      • Waveshare 4.2inch e-Paper Raw Panel Case (Artikelnr. 16116
      • Waveshare Universal e-Paper Raw Panel Driver HAT (Artikelnr 13512)
      • Gigaset G-Tag Bluetooth Low Energy beacons

      Das Setup ist folgendes:

      Das ESP32 Board habe ich mit ESPHome programmiert. Die Verbindung zum iobroker geht über mqtt. Das ESP32 Board wird über POE mit Strom und LAN versorgt. Am Ende wird das in eine Unterputz-Installationsdose versenkt und das Display auf einer Blindabdeckung auf dem Schalterrahmen befestigt.

      Hier der relevante Code:

      Die yaml-Datei für ESPhome:

      esphome:
        name: bt_eingang
        platform: ESP32
        board: esp32-poe-iso
      
      ethernet:
        type: LAN8720
        mdc_pin: GPIO23
        mdio_pin: GPIO18
        clk_mode: GPIO17_OUT
        phy_addr: 0
        power_pin: GPIO12
        
      font:
        - file: "ubuntu.ttf"
          id: my_font
          size: 20
      spi:
        clk_pin: 14
        mosi_pin: 4
        
      
      esp32_ble_tracker:
      
      binary_sensor:
        - platform: ble_presence
          mac_address: 58:9E:XX:XX:XX:XX
          name: "Tracker white"
          id: track_w
        - platform: ble_presence
          mac_address: 58:9E:XX:XX:XX:XX
          name: "Tracker black"
          id: track_b
      
      text_sensor:
        - platform: mqtt_subscribe
          name: "Aussentemperatur"
          id: temp_out
          topic: bt_eingang/display/temp_out
        - platform: mqtt_subscribe
          name: "Headline"
          id: fc_symbol
          topic: bt_eingang/display/headline
        - platform: mqtt_subscribe
          name: "Line 2OG Licht"
          id: line_2OG_licht
          topic: bt_eingang/display/line_2OG_licht
        - platform: mqtt_subscribe
          name: "Line 2OG Fenster"
          id: line_2OG_fenster
          topic: bt_eingang/display/line_2OG_fenster
        - platform: mqtt_subscribe
          name: "Line 1OG Licht"
          id: line_1OG_licht
          topic: bt_eingang/display/line_1OG_licht
        - platform: mqtt_subscribe
          name: "Line 1OG Fenster"
          id: line_1OG_fenster
          topic: bt_eingang/display/line_1OG_fenster
        - platform: mqtt_subscribe
          name: "Line EG Fenster"
          id: line_EG_fenster
          topic: bt_eingang/display/line_EG_fenster
        - platform: mqtt_subscribe
          name: "Line EG Licht"
          id: line_EG_licht
          topic: bt_eingang/display/line_EG_licht    
        - platform: mqtt_subscribe
          name: "Anwesenheit"
          id: presence_string
          topic: bt_eingang/display/presence_string
      
      #Bilder aus dem DasWetter-Adapter invertiert und als jpg ohne Transparenz gespeichert
      
      image:
        - file: "icons/tiempo-weather/galeria5/PNG/mine/1.jpg"
          id: image_1
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/2.jpg"
          id: image_2
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/3.jpg"
          id: image_3
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/4.jpg"
          id: image_4
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/5.jpg"
          id: image_5
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/6.jpg"
          id: image_6
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/7.jpg"
          id: image_7
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/8.jpg"
          id: image_8
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/9.jpg"
          id: image_9
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/10.jpg"
          id: image_10
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/11.jpg"
          id: image_11
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/12.jpg"
          id: image_12
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/13.jpg"
          id: image_13
          resize: 60x60
        - file: "icons/tiempo-weather/galeria5/PNG/mine/14.jpg"
          id: image_14
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/15.jpg"
          id: image_15
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/16.jpg"
          id: image_16
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/17.jpg"
          id: image_17
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/18.jpg"
          id: image_18
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/19.jpg"
          id: image_19
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/20.jpg"
          id: image_20
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/21.jpg"
          id: image_21
          resize: 40x40
        - file: "icons/tiempo-weather/galeria5/PNG/mine/22.jpg"
          id: image_22
          resize: 40x40
       
      
      display:
        - platform: waveshare_epaper
          cs_pin: 16
          dc_pin: 15
          busy_pin: 13
          reset_pin: 2
          model: 4.20in
          update_interval: 3600s  #Displayrefresh flickert bei dem Display leider
          id: my_display
          lambda: |-
            it.printf(10,20, id(my_font), "Temperatur: %s", id(temp_out).state.c_str());
            it.print(250,10, id(my_font), "Vorhersage:");
            if (id(fc_symbol).state == "1") { it.image(360, 0, id(image_1)); };
            if (id(fc_symbol).state == "2") { it.image(360, 0, id(image_2)); };
            if (id(fc_symbol).state == "3") { it.image(360, 0, id(image_3)); };
            if (id(fc_symbol).state == "4") { it.image(360, 0, id(image_4)); };
            if (id(fc_symbol).state == "5") { it.image(360, 0, id(image_5)); };
            if (id(fc_symbol).state == "6") { it.image(360, 0, id(image_6)); };
            if (id(fc_symbol).state == "7") { it.image(360, 0, id(image_7)); };
            if (id(fc_symbol).state == "8") { it.image(360, 0, id(image_8)); };
            if (id(fc_symbol).state == "9") { it.image(360, 0, id(image_9)); };
            if (id(fc_symbol).state == "10") { it.image(360, 0, id(image_10)); };
            if (id(fc_symbol).state == "11") { it.image(360, 0, id(image_11)); };
            if (id(fc_symbol).state == "12") { it.image(360, 0, id(image_12)); };
            if (id(fc_symbol).state == "13") { it.image(360, 0, id(image_13)); };
            if (id(fc_symbol).state == "14") { it.image(360, 0, id(image_14)); };
            if (id(fc_symbol).state == "15") { it.image(360, 0, id(image_15)); };
            if (id(fc_symbol).state == "16") { it.image(360, 0, id(image_16)); };
            if (id(fc_symbol).state == "17") { it.image(360, 0, id(image_17)); };
            if (id(fc_symbol).state == "18") { it.image(360, 0, id(image_18)); };
            if (id(fc_symbol).state == "19") { it.image(360, 0, id(image_19)); };
            if (id(fc_symbol).state == "20") { it.image(360, 0, id(image_20)); };
            if (id(fc_symbol).state == "21") { it.image(360, 0, id(image_21)); };
            if (id(fc_symbol).state == "22") { it.image(360, 0, id(image_22)); };
           //geht sicher auch schöner in einer Zeile Code...
            it.line(0, 47, 400, 47);
            //Table
            it.line(100, 110, 300, 110); 
            it.line(100, 150, 300, 150);
            it.line(100, 190, 300, 190); 
            it.line(100, 230, 300, 230);
            it.line(200, 110, 200, 230);
            it.line(100, 110, 100, 230);
            it.line(300, 110, 300, 230);
            //Lastline
            it.line(0, 255, 400, 255);
            it.print(130,80,id(my_font), "Licht");
            it.print(220,80,id(my_font), "Fenster");
            it.print(50,120,id(my_font), "2 OG");
            it.print(50,160,id(my_font), "1 OG");
            it.print(70,200,id(my_font), "EG");
            it.printf(110,130, id(my_font), "%s", id(line_2OG_licht).state.c_str());
            it.printf(210,130, id(my_font), "%s", id(line_2OG_fenster).state.c_str());
            it.printf(110,170, id(my_font), "%s", id(line_1OG_licht).state.c_str());
            it.printf(210,170, id(my_font), "%s", id(line_1OG_fenster).state.c_str());
            it.printf(110,210, id(my_font), "%s", id(line_EG_licht).state.c_str());
            it.printf(210,210, id(my_font), "%s", id(line_EG_fenster).state.c_str());
            it.printf(10,275,id(my_font), "Anwesenheit: %s", id(presence_string).state.c_str());
      
      
      # Enable logging
      logger:
      mqtt:
        broker: #IP vom iobroker
        username: #wie in iobroker mqtt adapter
        password: #wie in iobroker mqtt adapter
        client_id: bt_Eingang
      #  log_topic: bt_eingang/log/
        on_message: # Manueller refresh des Displays bei Änderung
          topic: bt_eingang/display/refresh
          payload: "ON"
          then:
            - component.update: my_display
            
      ota:
      

      Das spannende (aber dann doch triviale - man kann hier recht frei entscheiden) war hier die HW Verkabelung. Diese ist im yaml dokumentiert. die GPIO Pins stehen im Plan auf der Olimex-Seite.

      Auf dem iobroker habe ich ein Javascript um per mqtt die entsprechenden Werte zu liefern:

      var fenster1OG=['hm-rpc.3.0000XXXXXXXXXX.1.STATE'/*Fensterkontakt Schlafzimmer:1 STATE*/, 
      'hm-rpc.0.KEQ00XXXXX.1.STATE'/*Fenster Balko Arbeitszimmer:1 STATE*/,
      'hm-rpc.0.KEQ00XXXXX.1.STATE'/*Fenster KiZi:1 STATE*/,
      'hm-rpc.0.KEQ00XXXXX.1.STATE'/*Fenster Bad 1OG STATE*/,
      'hm-rpc.0.MEQ02XXXXX.1.STATE'/*Fenster Fenster AZ STATE*/];
      
      var fenster2OG=['hm-rpc.0.JEQ0XXXXXX.1.STATE'/*Fenster Dach Nord:1 STATE*/,
      'hm-rpc.0.KEQ00XXXXX.1.STATE'/*Fenster Küche STATE*/,
      'hm-rpc.0.KEQ00XXXXX.1.STATE'/*Fenster Gaube STATE*/,
      'hm-rpc.0.KEQ00XXXXX.1.STATE'/*Fenster Fenster West:1 STATE*/,
      'hm-rpc.0.KEQ01XXXXX.1.STATE'/*Fenster Badewanne:1 STATE*/,
      'hm-rpc.0.KEQ00XXXXX.1.STATE'/*Fenster Bad 2OG:1 STATE*/];
      
      var presence=['javascript.1.presence_black'/*presence black*/,'javascript.1.presence_white'/*javascript 1 presence white*/]; //u.a. aus den Werten des BLE Scanners ermittler, aber noch aus einem zweiten Scanner und mit einer Hysterese
      
      on({id:'hm-rega.0.XXX'/*Licht 1OG*/, change: "ne"}, function(obj) { //Variable fürs Licht wird bei mir in der CCU gepflegt.
         var output;
         var input=obj.state.val;
         if (input) {
             output="An";
         } else {
             output="Aus";
         };
         setState('mqtt.0.bt_eingang.display.line_1OG_licht'/*bt eingang/display/line 1OG licht*/,output);
         redraw_display();
      });
      
      on({id:'hm-rega.0.1XXX'/*Licht2OG*/, change: "ne"}, function(obj) {
         var output;
         var input=obj.state.val;
         if (input) {
             output="An";
         } else {
             output="Aus";
         };
         setState('mqtt.0.bt_eingang.display.line_2OG_licht'/*bt eingang/display/line 1OG licht*/,output);
         redraw_display();
      });
      
      on({id:presence, change: "ne"}, function(obj) {
         var output="";
         if (getState("javascript.1.presence_black").val){
             output = output +"Schwarz "; //Hier kann man die Namen der Besitzer eintragen
         };
         if (getState("javascript.1.presence_white").val) {
             output = output + "Weiss ";
         };
         setState('mqtt.0.bt_eingang.display.presence_string'/*bt eingang/display/presence string*/,output);
         redraw_display();
      }); 
      
      on({id:fenster1OG, change: "ne"}, function(obj) {
         var output;
         var input=obj.state.val;
         var open_1OG=0;
         var gekippt_1OG=0;
         var closed_1OG=0;
         for (var i = 0; i < fenster1OG.length; i++) {
             var ws = getState(fenster1OG[i]).val;
             if (fenster1OG[i]=="hm-rpc.3.0000DXXXXXXX.1.STATE") {  //Fensterkontakt mit nur zwei Zuständen
                 if (ws==0) {
                     closed_1OG++;
                 } else if (ws==1) {
                     open_1OG++;
                 };
             } else {   //Normalerweise habe ich Griffsensoren mit 3 Zuständen
                 if (ws==0) {
                     closed_1OG++;
                 } else if (ws==1) {
                     gekippt_1OG++;
                 } else if (ws==2) {
                     open_1OG++;
                 }
             };
         };
         output = windowstring(open_1OG,gekippt_1OG,closed_1OG);
         setState('mqtt.0.bt_eingang.display.line_1OG_fenster'/*bt eingang/display/line 1OG fenster*/,output);
         redraw_display();
      });
      
      on({id:fenster2OG, change: "ne"}, function(obj) {
         var output;
         var input=obj.state.val;
         var open_2OG=0;
         var gekippt_2OG=0;
         var closed_2OG=0;
         for (var i = 0; i < fenster2OG.length; i++) {
             var ws = getState(fenster2OG[i]).val;
          
             if (fenster2OG[i]=="hm-rpc.3.000XXXXXX1.STATE") { 
                 if (ws==0) {
                     closed_2OG++;
                 } else if (ws==1) {
                     open_2OG++;
                 };
             } else {
                 if (ws==0) {
                     closed_2OG++;
                 } else if (ws==1) {
                     gekippt_2OG++;
                 } else if (ws==2) {
                     open_2OG++;
                 }
             };
         };
         output = windowstring(open_2OG,gekippt_2OG,closed_2OG);
         setState('mqtt.0.bt_eingang.display.line_2OG_fenster'/*bt eingang/display/line 1OG fenster*/,output);
         redraw_display();
      });
      
      on({id:'netatmo.0.XXXX.XXX.Temperature.Temperature'/*Temperature*/, change: "ne"}, function(obj) {
         setState('mqtt.0.bt_eingang.display.temp_out'/*bt eingang/display/temp out*/,obj.state.val);
      }); //Aussentemperatur. Änderung macht kein Display-Refresh, da das e-ink ca. 2-3 Sekunden beim aktualisieren flackert. Wird bei der nächsten Änderung oder nach 3600s wie im esphome-Skript aktualisiert. 
      
      on({id:"daswetter.0.NextHours.Location_1.Day_1.in1hours.symbol_value", change:"ne"}, function(obj){
         setState('mqtt.0.bt_eingang.display.headline'/*bt eingang/display/headline*/,obj.state.val);
         redraw_display();
      }); //Forecast für die nächste Stunde. 
      
      
      function redraw_display() {
         setState('mqtt.0.bt_eingang.display.refresh'/*bt eingang/display/refresh*/,"ON");
         setStateDelayed('mqtt.0.bt_eingang.display.refresh', "OFF",  1000);    
      }; //mit "ON" wird das Display aktualisiert. 
      
      
      function windowstring (w_open, w_kipp, w_close){
         var output;
         if (w_open==0 && w_kipp==0) {
             output ="Zu";
         } else {
             output = "O:"+ w_open +" K:"+ w_kipp;
         };
         return output;
      }
      //Das Erdgeschoß ist noch im Umbau, deswegen noch nicht im Skript enthalten
      
      

      Das ganze sieht dann so aus:

      IMG_20200524_161732.jpg
      IMG_20200524_161726.jpg

      Aktuell habe ich nur noch das Problem, dass ich kein OTA Update auf dem ESP32 machen kann, da das abbricht. Per USB lässt er sich aber problemlos flashen.

      In Summe hat die Hardware ca. 70 EUR gekostet (30 EUR für das ESP Board und 37 EUR für das Display mit Versand)

      Viel Spass beim nachmachen, es war einfacher als befürchtet:-)

      Alexander

      L FredF 2 Replies Last reply Reply Quote 3
      • L
        lxs @lxs last edited by

        Hi,

        Da ich gerade eine Frage zu dem Projekt bekommen habe, hier ein kleines Update wie das ganze im eingebauten Zustand aussieht :

        IMG_20210125_142326.jpg IMG_20210125_142335.jpg

        Unter der Blindabdeckung ist eine EDV Dose in der das ESP32 Modul mit PoE angeschlossen ist. Die obere Dose ist bis auf das kleine Board für die Displaysteuerung leer und hat auch eine Blindabdeckung an der mit einem Klebeband das Display befestigt ist. In der mittleren Dose ist ein haus-bus.de Multitaster (tolle Schalter!) .

        Die EDV Dose war recht knapp, da das Cat6 Kabel mit Ethernet-Stecker etwas unflexibel ist, aber es hat gepasst.

        Mikewolf 1 Reply Last reply Reply Quote 2
        • FredF
          FredF Most Active Forum Testing @lxs last edited by

          @lxs sagte in Vorstellung: e-Ink display für Hausstatus:

          Die Verbindung zum iobroker geht über mqtt.

          Vielleicht magst du mal testen:
          Es gibt mittlerweile einen ESPhome Adapter zwar noch alpha...
          Nutzt die API, also kein MQTT nötig. Habe ihn installiert und er läuft.
          https://github.com/iobroker-community-adapters/ioBroker.esphome

          1 Reply Last reply Reply Quote 0
          • Mikewolf
            Mikewolf @lxs last edited by Mikewolf

            @lxs
            hallo , gibts ne step by step anleitung ???
            schaffe es leider nicht auch nicht mit hilfe von google....
            kommt immer error mapping bei spi definition

            apping values are not allowed here
              in "/config/esphome/esphome-web-8c4680.yaml", line 146, column 11:
                    cs_pin: 16
            

            Mit freundlichen Grüßen
            mikewolf

            B 1 Reply Last reply Reply Quote 0
            • B
              bernd33-1 @Mikewolf last edited by

              @mikewolf Hi, ich hab einen ESP8266 verwendet. Dabei hab ich festgestellt, dass die EPaper Displays etwas sensibel mit den verwendeten Pins sind. Ich hab es so verbunden:

              Display -> ESP8266

              Busy -> D2
              Reset -> D1
              DC -> D4
              CS -> D8
              CLK -> D5
              Din -> D7
              GND -> GND (Masse)
              Vcc -> 3.3V am ESP8266

              VORSICHT1: In der YAML-Datei wird statt z.B. "D4" die GPIO-Nummer angegeben. D4 ist z.B. GPIO2

              VORSICHT2: Man muss die Font-Datei, die in der YAML angegeben ist auf den IOBroker hoch laden. Bei mir ist es die arial.ttf und hat die ID: font1. Wohin hochladen? Hier hin: /opt/iobroker/iobroker-data/esphome.0

              Hier meine YAML:

              esphome:
                name: 42display
                platform: ESP8266
                board: esp01_1m
              
              # Enable logging
              logger:
              
              # Enable Home Assistant API
              api:
              
              ota:
                password: "ist-geheim"
              
              wifi:
                ssid: "Ich-hoere-euch-beim-Sex"
                password: "auch-geheim"
              
                # Enable fallback hotspot (captive portal) in case wifi connection fails
                ap:
                  ssid: "42Display Fallback Hotspot"
                  password: "jajaja"
              
              captive_portal:
              
              spi:
                clk_pin: GPIO14
                mosi_pin: GPIO13
                
              font:
                - file: "arial.ttf"
                  id: font1
                  size: 12
                  
              mqtt:
                broker: Die-IP-deine-MQTT/IOBroker
                #username: #wie in iobroker mqtt adapter
                #password: #wie in iobroker mqtt adapter
                client_id: 42Display
              #  log_topic: bt_eingang/log/
                on_message: # Manueller refresh des Displays bei Änderung
                  topic: 42Display/display/refresh
                  payload: "ON"
                  then:
                    - component.update: my_display
                    
              text_sensor:
                - platform: mqtt_subscribe
                  name: "Bio-Muell"
                  id: bio_muell
                  topic: 42Display/display/bio
                - platform: mqtt_subscribe
                  name: "papier"
                  id: papier
                  topic: 42Display/display/papier
                
              display:
                - platform: waveshare_epaper
                  cs_pin: GPIO15
                  dc_pin: GPIO2
                  busy_pin: GPIO4
                  reset_pin: GPIO5
                  model: 4.20in
                  update_interval: 300s  #Displayrefresh flickert bei dem Display leider
                  id: my_display
                  lambda: |-
                    it.print(0, 0, id(font1), "Hello World!");  
                    it.printf(10,20, id(font1), "Bio-Muell: %s", id(bio_muell).state.c_str());
                    it.printf(10,35, id(font1), "Papier: %s", id(papier).state.c_str());
              
              
              
              1 Reply Last reply Reply Quote 0
              • First post
                Last post

              Support us

              ioBroker
              Community Adapters
              Donate

              722
              Online

              31.6k
              Users

              79.5k
              Topics

              1.3m
              Posts

              4
              5
              5966
              Loading More Posts
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes
              Reply
              • Reply as topic
              Log in to reply
              Community
              Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
              The ioBroker Community 2014-2023
              logo