Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Praktische Anwendungen (Showcase)
    4. E-INK Display OpenEPaperLink - Displayanzeige mit Batterie

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    E-INK Display OpenEPaperLink - Displayanzeige mit Batterie

    This topic has been deleted. Only users with topic management privileges can see it.
    • Eisbaeeer
      Eisbaeeer Developer @Eisbaeeer last edited by Eisbaeeer

      Falls noch jemand einen Yellow_AP haben möchte (unterstützt Zigbee & SubGHz), ich habe noch einen einzigen. Danach wird es keine mehr geben. Alle weg.
      9d775c6c-c3d0-4220-bb7d-7f4d34250f77-20240628_224837.jpg
      b8101fb6-4514-44b9-b33b-c170191c04fd-20240628_230823.jpg

      3b61a957-ab61-49eb-a600-95cc89f16a42-20240628_234942.jpg

      Grüße Lars

      1 Reply Last reply Reply Quote 0
      • D
        diwoma last edited by

        Hi Leute,
        Ich hätte mal eine allgemeine Frage:
        Wo bekommt Ihr die AP und vor allem die Tag's her?

        Ich habe anfangs auch damit herumgespielt und es hat mir gefallen.
        Aber nachdem von den 5 Tag die ich hatte nur mehr 2 funktionieren, habe ich das Projekt auf Eis gelegt.

        Aber ich würde gerne damit weiterarbeiten, wenn ich weitere Tag hätte.

        B 1 Reply Last reply Reply Quote 0
        • B
          Beowolf @diwoma last edited by

          @diwoma

          Von 5 funktionieren nur noch 2?

          Was machst du mit den Dinger?

          APs wurden gerade etwas weiter oben angeboten. TAGs, schaue mal bei Youtube nach "open epaper" und dann nach dem Youtuber "Christophel". Einfach mal ansprechen.

          D 1 Reply Last reply Reply Quote 0
          • D
            diwoma @Beowolf last edited by diwoma

            @beowolf sagte in E-INK Display OpenEPaperLink - Displayanzeige mit Batterie:

            Was machst du mit den Dinger?

            Wahrscheinlich zu oft resettet, weil ich damals Probleme mit dem AP hatte.

            APs wurden gerade etwas weiter oben angeboten. TAGs, schaue mal bei Youtube nach "open epaper" und dann nach dem Youtuber "Christophel". Einfach mal ansprechen.

            Christophel habe ich auf Youtube mal was geschrieben, aber darauf keine Antwort bekommen.
            Und die restlichen laufen jetzt so einigermaßen. Deshalb ist das Projekt eingeschlafen.

            Aber wenn ich wieder Tag's bekommen kann, würde ich daran weiterarbeiten.

            B 1 Reply Last reply Reply Quote 0
            • B
              Beowolf last edited by

              Ich hatte Aaron angefragt.

              Er hat mir diese E-Mail Adresse gegeben.

              eink@43u.de

              Einfach antickern.

              Er ist sehr nett und hilfsbereit.

              Grüße

              D 1 Reply Last reply Reply Quote 0
              • B
                bimmi @diwoma last edited by

                @diwoma oder über discord atc1441 anschreiben. Das ist Aaron.

                1 Reply Last reply Reply Quote 1
                • B
                  Beowolf last edited by

                  Gibt es einen einfachen Weg um einen Grafana-Diagramm auf ein Display zu bekommen?

                  Ich bin mir nicht sicher, ob das mit dem Grafana Image Renderer geht. Läuft der auf einem Raspberry pi4?

                  Grüße

                  Eisbaeeer 1 Reply Last reply Reply Quote 0
                  • D
                    diwoma @Beowolf last edited by

                    @beowolf Danke, er hat schon geantwortet.

                    1 Reply Last reply Reply Quote 0
                    • Eisbaeeer
                      Eisbaeeer Developer @Beowolf last edited by Eisbaeeer

                      @beowolf sagte in E-INK Display OpenEPaperLink - Displayanzeige mit Batterie:

                      Gibt es einen einfachen Weg um einen Grafana-Diagramm auf ein Display zu bekommen?

                      Ich bin mir nicht sicher, ob das mit dem Grafana Image Renderer geht. Läuft der auf einem Raspberry pi4?

                      Grüße

                      Ich nutze VIS mit snapshot wie oben beschrieben. Geht wunderbar. Einfach im VIS die Werte auf der View ablegen und es wird auf dem Display dargestellt. Geht auch mit Graphen.
                      669bab7d-43cf-4ed2-b12d-9a81233e293f-20240626_154220.jpg

                      1 Reply Last reply Reply Quote 0
                      • D
                        diwoma last edited by diwoma

                        @eisbaeeer
                        Ich glaube aber, das wird nicht mit Grafana gehen, so wie die Frage war.
                        Da müsssen sicher Vis-spezifische Graphen gebaut werden

                        Eisbaeeer 1 Reply Last reply Reply Quote 0
                        • Eisbaeeer
                          Eisbaeeer Developer @diwoma last edited by Eisbaeeer

                          @diwoma Solange der Grafana eine Webseite macht, geht das genauso. Mit Chrome Headless einen screenshot machen und als Bild auf den Tag laden.

                          chrome --headless --disable-gpu --screenshot https://meine-grafana-seite.html
                          

                          Für rpi und andere gibt es auch das Paket puppeteer.

                          B 1 Reply Last reply Reply Quote 0
                          • B
                            Beowolf @Eisbaeeer last edited by

                            @eisbaeeer

                            Ich mache ja alle anderen Darstellungen mit VIS und dann weiter mit puppeteer.

                            Nur wenn ich eine Darstellung von Grafana in VIS einbinde wir es auf den Displays nicht angezeigt.

                            Allerding sind die Grafana-Sachen auch etwas farbig. Event. liegt es daran.

                            D 1 Reply Last reply Reply Quote 1
                            • D
                              diwoma @Beowolf last edited by

                              @beowolf
                              Ich glaube, Grafana kannst Du nur direkt von grafana holen, so wie es @Eisbaeeer geschrieben hat.
                              Mit einem iFrame in die Vis eingebunden geht es wahrscheinlich nicht.

                              1 Reply Last reply Reply Quote 0
                              • B
                                Beowolf last edited by

                                Es scheint so. Mit einem iFrame geht es nicht.

                                1 Reply Last reply Reply Quote 0
                                • B
                                  Beowolf last edited by Beowolf

                                  Ich habe ab chatgpt wieder ein wenig gequält.

                                  Es geht um die Abfrage der Buttons bei den schwarzen Displays.

                                  Diese meine ich

                                  https://github.com/OpenEPaperLink/OpenEPaperLink/wiki/2.9″-EL029H3WRA

                                  Hier das Skript

                                  // HIER DIE IP ADRESSE VOM OEPL ACCESS POINT EINTRAGEN
                                  const serverIP = '192.168.49.185';  // z.B. 192.168.1.71
                                  
                                  
                                  //Im Skript müssen noch zwei weiter Einträge event. der eigenen Umgebung angepasst werden
                                  // Zeile 17  -  "Datenpunkt zur Steuerung des Skripts"
                                  // Zeile 21  -  "Datenordner der empfangenen TAGs"
                                  // Zeile 176 -  "Diesen Eintrag auch noch entsprechend der eigenen Umgebung anpassen"
                                  
                                  // AB HIER NICHTS MEHR ÄNDERN!
                                  const WebSocket = require('ws');
                                  const http = require('http');
                                  const wsUrl = `ws://${serverIP}/ws`;  // WebSocket-URL
                                  
                                  let ws;
                                  let pingInterval;
                                  let scriptStopping = false;  // Flag, um zu prüfen, ob das Skript gestoppt wird
                                  
                                  const controlState = '0_userdata.0.Tag_Buttons.Button_Skript_Steuerung.Button_Tags_Erdgeschoss';  // Datenpunkt zur Steuerung des Skripts
                                  
                                  function ensureOpenEPaperLinkFolderExists(callback) {
                                      const OpenEPaperLinkFolderPath = '0_userdata.0.Tag_Buttons.Erdgeschoss'; // Datenordner der empfangenen TAGs
                                      getObject(OpenEPaperLinkFolderPath, (err, obj) => {
                                          if (err || !obj) {
                                              setObject(OpenEPaperLinkFolderPath, {
                                                  type: 'channel',
                                                  common: { name: 'Open E-Paper Link' },
                                                  native: {}
                                              }, callback);
                                          } else {
                                              callback();
                                          }
                                      });
                                  }
                                  
                                  function ensureChannelExists(path, alias, callback) {
                                      getObject(path, (err, obj) => {
                                          if (err || !obj) {
                                              setObject(path, {
                                                  type: 'channel',
                                                  common: { name: alias || 'Unbekanntes Gerät' },
                                                  native: {}
                                              }, callback);
                                          } else if (obj.common.name !== alias) {
                                              extendObject(path, { common: { name: alias } }, callback);
                                          } else {
                                              callback();
                                          }
                                      });
                                  }
                                  
                                  function createStateAndSet(statePath, value) {
                                      setObject(statePath, {
                                          type: 'state',
                                          common: {
                                              name: statePath.split('.').pop(),
                                              type: 'string',
                                              role: 'value',
                                              read: true,
                                              write: true
                                          },
                                          native: {}
                                      }, (err) => {
                                          if (!err) {
                                              setState(statePath, String(value), true);
                                          }
                                      });
                                  }
                                  
                                  function updateStateIfChanged(statePath, value) {
                                      getState(statePath, (err, state) => {
                                          if (err || !state) {
                                              createStateAndSet(statePath, String(value));
                                          } else if (state.val !== String(value)) {
                                              setState(statePath, String(value), true);
                                          }
                                      });
                                  }
                                  
                                  function fetchDimensions(hwType, callback) {
                                      const hwTypeHex = hwType.toString(16).padStart(2, '0').toUpperCase();  // Convert hwType to two-digit uppercase hexadecimal
                                      const url = `http://${serverIP}/tagtypes/${hwTypeHex}.json`;
                                      http.get(url, (res) => {
                                          let data = '';
                                          res.on('data', (chunk) => data += chunk);
                                          res.on('end', () => {
                                              if (res.statusCode === 200) {
                                                  try {
                                                      const dimensions = JSON.parse(data);
                                                      callback(null, dimensions);
                                                  } catch (e) {
                                                      callback(`Error parsing JSON from ${url}: ${e}`);
                                                  }
                                              } else {
                                                  callback(`HTTP Error ${res.statusCode} from ${url}`);
                                              }
                                          });
                                      }).on('error', (err) => {
                                          callback(`Error fetching ${url}: ${err.message}`);
                                      });
                                  }
                                  
                                  function handleHWType(basePath, hwType) {
                                      createStateAndSet(`${basePath}.hwType`, String(hwType));  // Save hwType as a state
                                      fetchDimensions(hwType, (err, dimensions) => {
                                          if (!err && dimensions) {
                                              createStateAndSet(`${basePath}.height`, String(dimensions.height));
                                              createStateAndSet(`${basePath}.width`, String(dimensions.width));
                                              createStateAndSet(`${basePath}.name`, String(dimensions.name));
                                              if (dimensions.colors) {
                                                  createStateAndSet(`${basePath}.colors`, String(dimensions.colors));
                                              }
                                              if (dimensions.colortable) {
                                                  createStateAndSet(`${basePath}.colortable`, JSON.stringify(dimensions.colortable));
                                              }
                                          } else {
                                              console.error(`Failed to fetch or set dimensions for hwType ${hwType}: ${err}`);
                                          }
                                      });
                                  }
                                  
                                  function connectWebSocket() {
                                      if (scriptStopping) {
                                          return;  // Wenn das Skript gestoppt wird, keine Verbindung mehr herstellen
                                      }
                                  
                                      ws = new WebSocket(wsUrl);
                                      ws.on('open', function open() {
                                          console.log('Verbunden mit WebSocket');
                                          startHeartbeat();
                                      });
                                  
                                      ws.on('message', function incoming(data) {
                                          console.log('Daten empfangen:', data);
                                          if (data) {
                                              try {
                                                  let parsedData = JSON.parse(data);
                                                  console.log('Verarbeitete Daten:', JSON.stringify(parsedData, null, 2));
                                                  handleData(parsedData);
                                              } catch (err) {
                                                  console.error('Fehler bei der Verarbeitung der Daten:', err);
                                              }
                                          } else {
                                              console.log('Keine Daten oder leere Nachricht empfangen');
                                          }
                                      });
                                  
                                      ws.on('close', function close() {
                                          if (!scriptStopping) {
                                              console.log('WebSocket-Verbindung geschlossen, versuche neu zu verbinden...');
                                              clearInterval(pingInterval);
                                              setTimeout(connectWebSocket, 5000);
                                          }
                                      });
                                  
                                      ws.on('error', function error(err) {
                                          console.error('WebSocket-Fehler:', err);
                                      });
                                  }
                                  
                                  function startHeartbeat() {
                                      pingInterval = setInterval(() => {
                                          if (ws.readyState === WebSocket.OPEN) {
                                              ws.ping(() => console.log('Ping sent'));
                                          }
                                      }, 10000); // Send ping every 10 seconds
                                  
                                      ws.on('pong', () => {
                                          console.log('Pong received');
                                      });
                                  }
                                  
                                  function handleData(parsedData) {
                                      if (parsedData.tags && Array.isArray(parsedData.tags)) {
                                          parsedData.tags.forEach(tag => {
                                              let basePath = `0_userdata.0.Tag_Buttons.Erdgeschoss.${tag.mac.replace(/:/g, '')}`;  //Diesen Eintrag auch noch entsprechend der eigenen Umgebung anpassen
                                              ensureChannelExists(basePath, tag.alias, () => {
                                                  Object.keys(tag).forEach(key => {
                                                      let statePath = `${basePath}.${key}`;
                                                      let value = tag[key];
                                                      updateStateIfChanged(statePath, value);
                                                      if (key === 'hwType') {
                                                          handleHWType(basePath, tag.hwType);
                                                      }
                                                  });
                                              });
                                          });
                                      }
                                  }
                                  
                                  function disconnectWebSocket() {
                                      if (ws) {
                                          ws.close();
                                          ws = null;
                                      }
                                      clearInterval(pingInterval);
                                  }
                                  
                                  // Skript-Start und -Stopp basierend auf einem Datenpunkt steuern
                                  function setupScriptControl() {
                                      setObject(controlState, {
                                          type: 'state',
                                          common: {
                                              name: 'EPaper Script Control',
                                              type: 'boolean',
                                              role: 'switch',
                                              read: true,
                                              write: true,
                                              def: false
                                          },
                                          native: {}
                                      });
                                  
                                      on({id: controlState, change: 'ne'}, (obj) => {
                                          const state = obj.state.val;
                                          if (state) {
                                              // Skript starten
                                              scriptStopping = false;
                                              ensureOpenEPaperLinkFolderExists(connectWebSocket);
                                          } else {
                                              // Skript stoppen
                                              scriptStopping = true;
                                              disconnectWebSocket();
                                              console.log('Skript beendet durch Steuer-Datenpunkt');
                                          }
                                      });
                                  }
                                  
                                  // Initiale Einrichtung
                                  setupScriptControl();
                                  

                                  Jetzt kann das Skript durch Setzen des Datenpunkts 0_userdata.0.ScriptControl.EPaperScript auf true oder false gestartet und gestoppt werden.

                                  Bei mir funktioniert es.

                                  Bitte die Einstellung im Skript beachten !!!

                                  Die Fehlermeldungen bei dem ersten Durchlauf sind wohl normal.

                                  Eisbaeeer B 2 Replies Last reply Reply Quote 1
                                  • Eisbaeeer
                                    Eisbaeeer Developer @Beowolf last edited by

                                    Hat schon jemand das Blockly zum Screenshotten von request befreit?
                                    Nach update auf die neuste Version vom Controller wird request nicht mehr akzeptiert.

                                    BananaJoe B 2 Replies Last reply Reply Quote 0
                                    • BananaJoe
                                      BananaJoe Most Active @Eisbaeeer last edited by BananaJoe

                                      @eisbaeeer ich hatte es versucht ... aber nicht hinbekommen. Zur Zeit triggere ich playwright alle 3 Minuten an, die Bilder landen in einem Ordner meines Webservers (läuft mit auf dem ioBroker Server auf Port 80) und die Tags stehen auf Image URL

                                      Dazu habe ich ein Python-Skript hinterlegt das 3 VIS-Seiten besucht und die Screenshots hinterlegt:

                                      #!/usr/bin/python3
                                      # -*- coding: utf-8 -*-
                                      import subprocess
                                      from playwright.sync_api import sync_playwright, Page, expect
                                      
                                      playwright = sync_playwright().start()
                                      
                                      #browser = playwright.chromium.launch()
                                      #browser = playwright.webkit.launch()
                                      browser = playwright.firefox.launch()
                                      context = browser.new_context(
                                        viewport={"width":800, "height":600},
                                        device_scale_factor=4,
                                      
                                      )
                                      page = context.new_page()
                                      
                                      # Schritt 1: Kühlschrank
                                      page.goto("http://192.168.1.8:60008/vis/index.html?openepaper#Kuehlschrank01")
                                      expect(page.get_by_text("Kuehlschrank01")).to_be_visible()
                                      #page.screenshot(path="/var/www/html/openepaper/Kuehlschrank01_4x.jpg",clip={"x":0,"y":0,"width":296,"height":128},quality=100,type="jpeg")
                                      page.screenshot(path="/var/www/html/openepaper/Kuehlschrank01_4x.png",clip={"x":0,"y":0,"width":296,"height":128},type="png")
                                      myconvert=subprocess.call(['/usr/bin/convert', '/var/www/html/openepaper/Kuehlschrank01_4x.png', '-sample', '296x128', '-quality', '100', '-sampling-factor', '4:4:4', '-brightness-contrast', '0x99', '/var/www/html/openepaper/Kuehlschrank01.jpg' ])
                                      
                                      # Schritt 2: Pylontech
                                      page.goto("http://192.168.1.8:60008/vis/index.html?openepaper#Pylontech")
                                      expect(page.get_by_text("Pylontech")).to_be_visible()
                                      #page.screenshot(path="/var/www/html/openepaper/Pylontech_4x.jpg",clip={"x":0,"y":0,"width":296,"height":128},quality=100,type="jpeg")
                                      page.screenshot(path="/var/www/html/openepaper/Pylontech_4x.png",clip={"x":0,"y":0,"width":296,"height":128},type="png")
                                      myconvert=subprocess.call(['/usr/bin/convert', '/var/www/html/openepaper/Pylontech_4x.png', '-sample', '296x128', '-quality', '100', '-sampling-factor', '4:4:4', '-brightness-contrast', '0x99', '/var/www/html/openepaper/Pylontech.jpg' ])
                                      
                                      # Schritt 3: Briefkasten
                                      page.goto("http://192.168.1.8:60008/vis/index.html?openepaper#Briefkasten")
                                      expect(page.get_by_text("Briefkasten")).to_be_visible()
                                      #page.screenshot(path="/var/www/html/openepaper/Briefkasten_4x.jpg",clip={"x":0,"y":0,"width":296,"height":128},quality=100,type="jpeg")
                                      page.screenshot(path="/var/www/html/openepaper/Briefkasten_4x.png",clip={"x":0,"y":0,"width":296,"height":128},type="png")
                                      myconvert=subprocess.call(['/usr/bin/convert', '/var/www/html/openepaper/Briefkasten_4x.png', '-sample', '296x128', '-quality', '100', '-sampling-factor', '4:4:4', '-brightness-contrast', '0x99', '/var/www/html/openepaper/Briefkasten.jpg' ])
                                      
                                      # Schritt 4: Fenster und Türen
                                      page.goto("http://192.168.1.8:60008/vis/index.html?openepaper#EingangstuerV2")
                                      expect(page.get_by_text("FensterTueren")).to_be_visible()
                                      #page.screenshot(path="/var/www/html/openepaper/FensterTueren_4x.jpg",clip={"x":0,"y":0,"width":400,"height":300},quality=100,type="jpeg")
                                      page.screenshot(path="/var/www/html/openepaper/FensterTueren_4x.png",clip={"x":0,"y":0,"width":400,"height":300},type="png")
                                      myconvert=subprocess.call(['/usr/bin/convert', '/var/www/html/openepaper/FensterTueren_4x.png', '-sample', '400x300', '-quality', '100', '-sampling-factor', '4:4:4', '-brightness-contrast', '0x99', '/var/www/html/openepaper/FensterTueren.jpg' ])
                                      
                                      
                                      browser.close()
                                      
                                      playwright.stop()
                                      
                                      

                                      und das ich per Blockly alle 3 Minuten triggere:
                                      664810da-ac2c-4098-8cfe-bda12090caa6-image.png

                                      In dem Skript gibt es Zeilen für alle 3 Browser, Firefox sah bei mir am besten aus. Playwright installiert alle 3 Engines.
                                      Die Screenshots werden doppelt so groß gefertigt und dann herunterskaliert, dafür muss Imagemagick evenfalls installiert sein (für den Befehl convert)

                                      B 1 Reply Last reply Reply Quote 0
                                      • B
                                        Beowolf @Eisbaeeer last edited by

                                        @eisbaeeer sagte in E-INK Display OpenEPaperLink - Displayanzeige mit Batterie:

                                        Hat schon jemand das Blockly zum Screenshotten von request befreit?
                                        Nach update auf die neuste Version vom Controller wird request nicht mehr akzeptiert.

                                        Was ist daran falsch? Oder meinst du ein anderes Skript?

                                        https://forum.iobroker.net/topic/66380/e-ink-display-openepaperlink-displayanzeige-mit-batterie/586?_=1722257902094

                                        Grüße

                                        Eisbaeeer 1 Reply Last reply Reply Quote 0
                                        • Eisbaeeer
                                          Eisbaeeer Developer @Beowolf last edited by

                                          @beowolf Mit dem neusten js-controller läuft request und somit das Blockly Script nicht mehr.

                                          B Neuschwansteini 2 Replies Last reply Reply Quote 0
                                          • B
                                            Beowolf @Eisbaeeer last edited by Beowolf

                                            @eisbaeeer

                                            Muß jetzt mal unwissend fragen. Mit js-controller meinst du den javaskript Adapter?

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            Support us

                                            ioBroker
                                            Community Adapters
                                            Donate

                                            824
                                            Online

                                            31.7k
                                            Users

                                            79.6k
                                            Topics

                                            1.3m
                                            Posts

                                            42
                                            991
                                            233889
                                            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