Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Beowolf

    NEWS

    • Monatsrückblick – September 2025

    • Neues Video "KI im Smart Home" - ioBroker plus n8n

    • Neues Video über Aliase, virtuelle Geräte und Kategorien

    B
    • Profile
    • Following 1
    • Followers 0
    • Topics 145
    • Posts 1464
    • Best 82
    • Groups 3

    Beowolf

    @Beowolf

    94
    Reputation
    195
    Profile views
    1464
    Posts
    0
    Followers
    1
    Following
    Joined Last Online

    Beowolf Follow
    Pro Starter Most Active

    Best posts made by Beowolf

    • Wohnungsputzstress an Weihnachten

      An alle die sich einen übertriebenen Wohnungsputz-Weihnachtsstress machen.

      Es kommt das Christkind - nicht das Gesundheitsamt.

      Trotzdem eine frohe Weihnachtszeit und einen guten Rutsch in das neue Jahr.

      🤗 🤗 🤗

      posted in Plauderecke
      B
      Beowolf
    • RE: Wemos d1 mini - http Aufruf geht nur einmal.

      @opensourcenomad

      Echt jetzt? Könnt Ihr den Kleinkrieg an einer anderen Stelle machen?

      Danke

      posted in Microcontroller
      B
      Beowolf
    • RE: E-INK Display OpenEPaperLink - Displayanzeige mit Batterie

      @mcm57

      Displays:
      www.tindie.com/products/electronics-by-nic/5-pcs-29-epaper-tags-for-openepaperlink

      AP:
      www.tindie.com/products/electronics-by-nic/openepaperlink-mini-ap-v3-zigbee-wifi-gateway/

      posted in Praktische Anwendungen (Showcase)
      B
      Beowolf
    • RE: Wasserzähler - Version 2 - all-in-device

      @doggie sagte in Wasserzähler - Version 2 - all-in-device:

      Mir scheint das ganze AI on the edge Projekt ist nicht annähernd ausgereift. Sehr, sehr schade. Und enttäuschend.
      Was sagen andere dazu?
      Gibt es eigentlich Systeme die fehlerfrei laufen?
      Als Entwickler des Systems würde mich so ein Fehler nicht schlafen lassen.

      Ein klein wenig Demut wäre nicht schlecht. Hier macht jemand ein Projekt in seiner Freizeit. Alles kostenlos. Letztendlich ist es "Bastelei". Was nicht bedeutet das es sehr, sehr gute Projekte sind.

      Wenn ein 100% zuverlässiges System gesucht wird, sollte man sich event. im Fachhandel umschauen. Ob dort die entsprechenden System und Programme auch kostenlos angeboten werden, kann ich so nicht sagen. Ich glaube aber eher nicht.

      Grüße
      Manfred

      posted in Hardware
      B
      Beowolf
    • RE: Test Adapter iQontrol 2.0.x Vis (Entwicklungs-Thread)

      Vielen Dank. 👍 👍 👍

      Ich liebe dieses Forum und die Leute darin. 😊 😊

      posted in Tester
      B
      Beowolf
    • RE: E-INK Display OpenEPaperLink - Displayanzeige mit Batterie

      @bananajoe sagte in EPS E-INK Display Ansteuerung -> Statusdisplay für 2€:

      @beowolf hast du die selbst geflasht? In der Bucht sind die gerade zu kaufen und ich starre gerade schon eine ganze weile auf das Pinout wo ich denn ran müsste ... (ich bin Tasmota-verwöhnt, da wird immer ein Bild hinterlegt welche Pins man nehmen muss)

      Eines vorab. Das ist nicht auf meinem Mist gewachsen. Ich habe das auch nur mit der Hilfe von Aaron Christophel hin bekommen.

      Vielen, vielen Dank dafür.

      Hier z.B. ein Video von ihm.

      https://www.youtube.com/watch?v=8oQdo9bJ7Rk

      Es geht um diesen TAG

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

      Für den Anschluss und Positionierung der POGO-Pins geht dieses z.B.

      https://github.com/jjwbruijn/OpenEPaperLink/blob/master/Hardware/M3 Newton Jigs by Jelmer/M3-2.9.stl

      Ich habe dieses

      https://github.com/jjwbruijn/OpenEPaperLink/tree/master/Tag_Flasher

      herunter geladen.

      Nun in das Verzeichnis ESP32_Flasher wechseln und dann mit der Hilfe von Visual Studio Code den Flasher auf einen ESP32 S2 aufgespielen.

      Den ESP dann so wie hier mit dem TAG verbinden.

      Anschluss schwarze TAGs.jpg

      Nun ein Verzeichnis höher gehen. Also in den Tag_Flasher Ordner gehen.

      Dann diese Datei herunterladen und in das Verzeichnis ablegen.

      https://github.com/jjwbruijn/OpenEPaperLink/blob/master/binaries/Tag/SOL_M3_Uni_full_26.bin

      Ich habe es mit diesem Befehl gemacht.

      python3 OEPL-Flasher.py -p COM11 -e -n write SOL_M3_Uni_full_26.bin --flash --pt

      COM11 natürlich anpassen.

      Für das Flashen muß auf dem Rechner Python installiert sein.

      Hier die passende Version laden.

      https://www.python.org/

      Bei dem Versuch kamen bei mir ein paar Meldungen das diese oder jenes nicht da ist.

      Ich musste z.b. dieses nachinstallieren: "pip install pyserial". Sollten da noch Meldungen kommen. einfach kurz bei google suchen.

      Danach sollte der Tag mit OPenEPaper geflasht sein.

      Ich hoffe ich habe nichts vergessen.

      posted in Praktische Anwendungen (Showcase)
      B
      Beowolf
    • RE: E-INK Display OpenEPaperLink - Displayanzeige mit Batterie

      @bananajoe sagte in EPS E-INK Display Ansteuerung -> Statusdisplay für 2€:

      @beowolf sagte in EPS E-INK Display Ansteuerung -> Statusdisplay für 2€:

      Ich bin ein wenig Ratlos und weiß nicht wo ich anfangen soll.

      Hier mal grob in Schritten zusammengefasst:

      Schritt 1: Eigene VIS für die ePaper Tags
      .........

      Für die schwarzen TAGs muß die Auflösung geändert werden. Sonst gibt es nur Schrott in der Anzeige.

      M3.Newton.2.9-2.jpg

      Also auf 384 x 168 Pixel

      Grüße

      posted in Praktische Anwendungen (Showcase)
      B
      Beowolf
    • RE: E-INK Display OpenEPaperLink - Displayanzeige mit Batterie

      Noch ein kleiner Tipp. Ich habe in meinen Blocklys noch eine "Pausezeit" für die Displays eingefügt.

      So werden sie in der Zeit von 23 Uhr bis 8 Uhr nicht mehr aktualisiert. Ist eh keiner wach um auf die TAGs zu schauen.

      So kann Energie gespart werden und die Batterien halten etwas länger.

      posted in Praktische Anwendungen (Showcase)
      B
      Beowolf
    • RE: E-INK Display OpenEPaperLink - Displayanzeige mit Batterie

      @basti97

      Frag doch einfach den "atc" wie oben in meinem Beitrag nach einem yellow AP. Das Ding läuft. Der hat ein Display.

      posted in Praktische Anwendungen (Showcase)
      B
      Beowolf
    • RE: E-INK Display OpenEPaperLink - Displayanzeige mit Batterie

      @m-a-x sagte in E-INK Display OpenEPaperLink - Displayanzeige mit Batterie:

      Edit: an der von dir verlinkten Lösung gefällt mir nicht: zusätzlicher Router (Strom Verbrauch und mehr Hardware), die displays sehen sehr oft / immer billig aus (kein Gehäuse oder nur ein seitlich offenes).

      Nichts für ungut, aber ob ein ESP32 jetzt "den" Stromverbrauch hat? Nun gut.

      Displays billig? Schau dir diese an

      displ1.jpg
      Anzeige steht gerade auf dem Kopf.
      displ2.jpg
      IMG_20240529_091954.jpg

      Weder billig noch offen.

      Was möchtest du denn noch mehr?

      posted in Praktische Anwendungen (Showcase)
      B
      Beowolf

    Latest posts made by Beowolf

    • Einfache Solarleistungsanzeige

      Ich habe mal eine einfache Anzeige der derzeitigen Solarleistung gebastelt. Meine Frau hatte immer gefragt, ob jetzt ein guter Zeitpunkt sei um dieses oder jenes laufen zu lassen. Also Waschmaschine, Kochen usw..

      Die Werte holt sich das Skript von OpenDTU und einem Hichi Lesekopf.

      Programmübersicht
      Dieses Programm läuft auf einem ESP8266-Mikrocontroller (z. B. NodeMCU oder Wemos D1 mini) und dient als Energie-Monitoring- und Anzeige-System.
      Es verbindet sich mit einem WLAN, liest Energiedaten von zwei Quellen (OpenDTU und HiChi/Tasmota-Stromzähler), zeigt die Werte auf einem TFT-Display an und stellt zusätzlich ein Web-Dashboard mit Live-Daten zur Verfügung.
      Über eine Weboberfläche können Einstellungen zur Display-Hintergrundbeleuchtung (An/Aus/Dimmen) vorgenommen und im EEPROM dauerhaft gespeichert werden.
      Zusätzlich unterstützt das Programm Over-the-Air Updates (OTA) und mDNS, damit das Gerät leicht im Netzwerk auffindbar ist.


      Hauptfunktionen des Programms

      1. WLAN-Verbindung
        • Das Gerät verbindet sich mit den im Code hinterlegten WLAN-Zugangsdaten (ssid, password).
        • Nach erfolgreicher Verbindung ist es über die lokale IP-Adresse erreichbar.
        • Die IP wird beim Start für kurze Zeit auf dem TFT-Display angezeigt.

      1. Zeitverwaltung
        • Die lokale Zeit wird über NTP-Server synchronisiert (pool.ntp.org, time.nist.gov).
        • Die Funktion isDST() berücksichtigt Sommerzeit (DST) und stellt sicher, dass die Uhrzeit korrekt angezeigt und für Beleuchtungssteuerung verwendet wird.

      1. Hintergrundbeleuchtung des Displays
        • Die TFT-Hintergrundbeleuchtung wird je nach Uhrzeit automatisch gesteuert:
        o Voll an: tagsüber
        o Gedimmt: ab einer festgelegten Uhrzeit am Abend
        o Aus: nachts
        • Diese Zeiten sind in Variablen gespeichert (stunde_an, stunde_dimmen, stunde_aus) und können über die Weboberfläche geändert werden.
        • Werte werden im EEPROM gespeichert, damit sie auch nach einem Neustart erhalten bleiben.

      1. Anzeige auf dem TFT-Display
        • Das Display zeigt nach dem Start zunächst die IP-Adresse für 5 Sekunden.
        • Danach wird ein Hauptbildschirm angezeigt:
        o Solarleistung (Watt) von der OpenDTU
        o Netzleistung (Watt) vom Zähler
        o Einspeisung (kWh)
        o Bezug (kWh)
        • Unten wird ein farbiges Feld angezeigt:
        o Rot mit "Netzbezug", wenn Strom aus dem Netz gezogen wird.
        o Grün mit "Einspeisung", wenn Strom ins Netz eingespeist wird.

      1. Abruf von Energiedaten
        • OpenDTU-API (opendtu_url): liefert die aktuelle Solarleistung.
        • HiChi/Tasmota-Zähler (hichi_url): liefert Netzleistung, Einspeisung und Bezug.
        • Die Abfrage erfolgt regelmäßig alle 5 Sekunden (updateInterval).
        • Daten werden per HTTP GET abgerufen und mit ArduinoJson geparst.

      1. Webserver-Funktionen
        Das Programm startet einen lokalen Webserver (Port 80), erreichbar über die IP-Adresse oder per mDNS („esp.local“).
        • / (Root):
        Dashboard-Seite im Browser mit Anzeige von Solar, Netz, Einspeisung, Bezug und der aktuellen Uhrzeit.
        Die Daten werden per AJAX (fetch /data) alle 5 Sekunden aktualisiert.
        • /data:
        Liefert die aktuellen Messwerte als JSON (für die Live-Aktualisierung im Browser).
        • /set:
        Ermöglicht das Ändern der Zeiten für An, Dimmen, Aus und des Dimmwertes.
        Werte werden geprüft, gespeichert und ins EEPROM geschrieben.

      1. OTA-Updates
        • Mit ArduinoOTA kann das Programm im Netzwerk neu geflasht werden, ohne den ESP8266 über USB anschließen zu müssen.
        • Das Gerät ist durch Hostname und Passwort abgesichert.

      Ablauf im loop()
      Die Endlosschleife (loop()) kümmert sich um:

      1. Abwicklung von OTA-Updates (ArduinoOTA.handle()).
      2. Beantwortung von Webserver-Anfragen (server.handleClient()).
      3. Anzeige der IP-Adresse beim Start für 5 Sekunden.
      4. Regelmäßige Abfrage der Energiedaten (alle 5 Sekunden).
      5. Aktualisierung der TFT-Anzeige mit den neuen Werten.
      6. Steuerung der Hintergrundbeleuchtung in Abhängigkeit von Uhrzeit und gespeicherten Einstellungen.

      Zusammenfassung
      Das Programm realisiert ein komplettes Energie-Monitoring-System mit:
      • Automatischer Abfrage von Solar- und Netzleistungen.
      • Anzeige der Werte auf einem TFT-Farbdisplay.
      • Steuerung der Display-Beleuchtung nach Uhrzeit.
      • Bereitstellung einer Weboberfläche mit Live-Daten und Einstellmöglichkeiten.
      • Speicherung von Benutzer-Einstellungen im EEPROM.
      • OTA-Update-Funktion für einfache Wartung.

      Skript:

      /*
        Ausführlich kommentierte Version des bereitgestellten ESP8266-Skripts.
        Dieses Skript verbindet sich mit einem WLAN, holt LIVE-Daten von zwei HTTP-APIs,
        zeigt Werte auf einem TFT-Display an, bietet ein kleines Web-Dashboard zum Lesen
        und Einstellen von Hintergrundlicht-Zeiten und unterstützt OTA-Updates.
      */
      
      #include <ESP8266WiFi.h>        // WiFi-Funktionalität für den ESP8266
      #include <ESP8266HTTPClient.h>  // HTTP-Client, um GET/POST-Requests zu machen
      #include <ESP8266WebServer.h>   // Einfacher HTTP-Server auf dem Gerät
      #include <ESP8266mDNS.h>        // mDNS (Multicast DNS) zur Namensauflösung im LAN
      #include <TFT_eSPI.h>           // Treiber für das TFT-Display (ILI9341/ILI9488 etc.)
      #include <ArduinoOTA.h>         // Over-the-Air Firmware-Updates (OTA)
      #include <ArduinoJson.h>        // JSON-Parsing für Antworten der APIs
      #include <time.h>               // Zeitfunktionen (time_t, struct tm, localtime...)
      #include <EEPROM.h>             // EEPROM zum dauerhaften Speichern kleiner Einstellungen
      
      #define EEPROM_SIZE 64         // Größe des verwendeten EEPROM-Bereichs
      
      // ---------- Netzwerk- und Service-Konfiguration (statisch im Sketch) ----------
      const char* ssid = "xxxxx";                  // WLAN-SSID
      const char* password = "xxxxxxxxxxxxxxx"; // WLAN-Passwort
      
      // URLs und Zugangsdaten für die entfernten Dienste
      const char* opendtu_url = "http://192.168.xxx.xxx/api/livedata/status"; // API 1
      const char* opendtu_user = "xxxxxxxxxx";                                      // Basic-Auth Benutzer
      const char* opendtu_password = "xxxxxxxxxxxxx";                         // Basic-Auth Passwort
      
      const char* hichi_url = "http://192.168.xxx.xxx/cm?cmnd=status%208";     // API 2 (z.B. Tasmota-Gerät)
      
      // OTA (Over-The-Air) Einstellungen
      String otaHostname = "ESP-Solar-1"; // Hostname für OTA
      String otaPassword = "xxxxx";      // Passwort für OTA (einfacher Schutz)
      
      // Objekte für Netzwerk, HTTP, Display und Webserver
      WiFiClient client;                     // Client für HTTP-Verbindungen
      HTTPClient http;                       // HTTP-Client-Wrapper
      TFT_eSPI tft = TFT_eSPI();             // TFT-Display-Objekt (Bibliothek TFT_eSPI)
      ESP8266WebServer server(80);           // HTTP-Server lauscht auf Port 80
      
      // ---------- Anzuzeigende Werte (globale Variablen) ----------
      float solarPower = 0;  // Aktuelle Solarleistung (W)
      float gridPower = 0;   // Aktuelle Netzleistung (positiv: Bezug, negativ: Einspeisung) (W)
      float einspeisung = 0; // kWh Ausgehende Energie (Einspeisung)
      float bezug = 0;       // kWh Eingehende Energie (Bezug)
      
      // Timing / Update-Intervall
      unsigned long lastUpdate = 0;                  // letzer Zeitstempel der Aktualisierung (millis)
      const unsigned long updateInterval = 5000;    // Aktualisierungsintervall in ms (5s)
      
      // Hintergrundbeleuchtung / PWM
      const int backlightPin = 3;                    // Pin für Hintergrundbeleuchtung (hier RX/PWM)
      int brightness = 1023;                         // Voller PWM-Wert (für analoge Ausgabe auf ESP8266)
      int brightnessDim = 200;                       // Gedimmter PWM-Wert (kann per Webinterface gesetzt werden)
      
      // Zeitpunkte für Hintergrundbeleuchtung (jeweils hh/mm)
      int stunde_an = 7;    // Zeitpunkt: Hintergrundlicht an (Stunde)
      int minute_an = 0;    // Zeitpunkt: Hintergrundlicht an (Minute)
      int stunde_dimmen = 21; // Ab wann dimmen
      int minute_dimmen = 0;
      int stunde_aus = 23;  // Ab wann ganz aus
      int minute_aus = 0;
      
      // UI/IP Anzeige Steuerung
      bool showIP = true;                           // Flag: zeigt beim Start die IP-Adresse an
      unsigned long ipDisplayStart = 0;             // millis() Zeitpunkt des Starts der IP-Anzeige
      const unsigned long ipDisplayDuration = 5000; // Zeitdauer der IP-Anzeige in ms (5s)
      
      // ------------------ Hilfsfunktionen für Zeitvergleiche ------------------
      
      // Vergleicht zwei Zeiten (h1:m1) >= (h2:m2)
      // Rückgabe: true, wenn (h1:m1) gleich oder nach (h2:m2) liegt.
      bool isTimeAfter(int h1, int m1, int h2, int m2) {
        if (h1 > h2) return true;
        if (h1 == h2 && m1 >= m2) return true;
        return false;
      }
      
      // Vergleicht zwei Zeiten (h1:m1) < (h2:m2)
      // Rückgabe: true, wenn (h1:m1) strikt vor (h2:m2) liegt.
      bool isTimeBefore(int h1, int m1, int h2, int m2) {
        if (h1 < h2) return true;
        if (h1 == h2 && m1 < m2) return true;
        return false;
      }
      
      // DST (Daylight Saving Time) Bestimmung für Mitteleuropa (MEZ/CEST)
      // Die Funktion prüft, ob die gegebene lokale Zeit in der Sommerzeit (DST) liegt.
      // Implementierung orientiert sich an: DST ist von letztem Sonntag im März (02:00) bis
      // letztem Sonntag im Oktober (03:00) gültig. Hier wird aus tm-Struktur (lokale Zeit)
      // entschieden. (Die Berechnung verwendet tm_mon, tm_mday, tm_wday, tm_hour.)
      bool isDST(struct tm* timeinfo) {
        int month = timeinfo->tm_mon + 1; // tm_mon: 0-11, darum +1
        int day = timeinfo->tm_mday;
        int wday = timeinfo->tm_wday;     // 0=Sonntag..6=Samstag
        int hour = timeinfo->tm_hour;
      
        // Monate außerhalb April-Oktober sind sicher keine DST-Monate
        if (month < 3 || month > 10) return false; // Jan, Feb, Nov, Dez -> kein DST
      
        // Apr-Sep sind immer DST
        if (month > 3 && month < 10) return true;  // Apr bis Sep -> DST
      
        // März: DST beginnt am letzten Sonntag im März um 2:00 Uhr
        if (month == 3) {
          // Berechnung des letzten Sonntags im Monat
          int lastSunday = 31 - ((wday + (31 - day)) % 7);
          if ((day > lastSunday) || (day == lastSunday && hour >= 2)) return true;
          else return false;
        }
      
        // Oktober: DST endet am letzten Sonntag im Oktober um 3:00 Uhr
        if (month == 10) {
          int lastSunday = 31 - ((wday + (31 - day)) % 7);
          if ((day < lastSunday) || (day == lastSunday && hour < 3)) return true;
          else return false;
        }
      
        return false; // Fallback
      }
      
      // ------------------ Anzeige-Funktionen (TFT) ------------------
      
      // Zeichnet einen einfachen Rahmen / Layout-Linien auf dem Display
      void drawFrame() {
        tft.drawRect(0, 0, tft.width(), tft.height(), TFT_WHITE);
        tft.drawLine(0, 28, tft.width(), 28, TFT_WHITE);   // obere Trennlinie
        tft.drawLine(0, 160, tft.width(), 160, TFT_WHITE); // mittlere Trennlinie
      }
      
      // Setzt die Hintergrundbeleuchtung je nach eingestellten Zeiten
      // - während der "aus"-Periode wird auf 0 gesetzt (aus)
      // - während der "dimmen"-Periode wird brightnessDim gesetzt
      // - sonst volle Helligkeit (brightness)
      void updateBacklight() {
        time_t now = time(nullptr);
        struct tm* timeinfo = localtime(&now);
        int curr_h = timeinfo->tm_hour;
        int curr_m = timeinfo->tm_min;
      
        // Aus: wenn aktuelle Zeit >= stunde_aus oder < stunde_an
        if (isTimeAfter(curr_h, curr_m, stunde_aus, minute_aus) || isTimeBefore(curr_h, curr_m, stunde_an, minute_an)) {
          analogWrite(backlightPin, 0); // ganz aus
        }
        // Dimmen: wenn aktuelle Zeit >= stunde_dimmen
        else if (isTimeAfter(curr_h, curr_m, stunde_dimmen, minute_dimmen)) {
          analogWrite(backlightPin, brightnessDim); // gedimmt
        }
        // Voll an: sonst
        else {
          analogWrite(backlightPin, brightness); // volle Helligkeit
        }
      }
      
      // Zeigt bei Start die IP-Adresse mittig auf dem Bildschirm an
      void showIPOnDisplay() {
        tft.fillScreen(TFT_BLACK);
        tft.setTextColor(TFT_YELLOW);
        tft.setTextDatum(MC_DATUM); // zentriert
        tft.setTextSize(3);
        tft.drawString("IP-Adresse:", tft.width() / 2, tft.height() / 3);
        tft.drawString(WiFi.localIP().toString(), tft.width() / 2, tft.height() / 2);
      }
      
      // Initiale (leere) Hauptanzeige (wird später bei Updates gefüllt)
      void showMainDisplay() {
        tft.fillScreen(TFT_BLACK);
        drawFrame();
        tft.setTextSize(2);
        tft.setTextColor(TFT_YELLOW);
        tft.setTextDatum(MC_DATUM);
        tft.drawString("Energieanzeige", tft.width() / 2, 14);
        // Die numerischen Werte werden regelmäßig in loop() gezeichnet/aktualisiert
      }
      
      // ------------------ Webserver-Handler ------------------
      
      // Handler für die Root-Seite: baut ein HTML-Dashboard als String zusammen
      // - Verwendet ein Raw-String-Literal (R"rawliteral(... )rawliteral") für das HTML-Template
      // - Fügt dynamische Werte (Hostname, Zeit, Messwerte, Formulareingaben) ein
      void handleRoot() {
        time_t now = time(nullptr);
        struct tm* timeinfo = localtime(&now);
        char timeStr[30];
        strftime(timeStr, sizeof(timeStr), "%d.%m.%Y %H:%M:%S", timeinfo);
      
        // Der HTML-Block ist ein Raw-String-Literal, damit Anführungszeichen im HTML nicht
        // escaped werden müssen. Danach werden dynamische Teile (Hostname, Werte, Formulare)
        // als String-Konkatenationen angehängt.
        String html = R"rawliteral(
      <!DOCTYPE html>
      <html lang="de">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>ESP Energie Dashboard</title>
        <style>
          /* Einfache CSS-Stile für ein dunkel gehaltenes Dashboard */
          body { background-color: #0b1120; color: #e2e8f0; font-family: "Segoe UI", sans-serif; margin: 0; padding: 20px; box-sizing: border-box; }
          h1 { text-align: center; color: #facc15; font-size: 2em; margin-bottom: 5px; }
          .subtitle { text-align: center; font-size: 0.9em; color: #94a3b8; margin-bottom: 20px; }
          .card { background-color: #1e293b; padding: 20px; margin: 20px auto; border-radius: 16px; max-width: 500px; width: 100%; box-shadow: 0 0 10px rgba(255, 255, 255, 0.05); }
          .label { color: #94a3b8; font-size: 0.9em; margin-top: 10px; }
          .value { font-size: 1.3em; margin-bottom: 12px; color: #f1f5f9; }
          form { display: flex; flex-direction: column; }
          form input[type='text'], form input[type='number'] { width: 100%; padding: 8px; margin: 6px 0; border-radius: 4px; border: none; background-color: #334155; color: white; box-sizing: border-box; }
          form input[type='submit'] { background-color: #4ade80; padding: 10px; margin-top: 12px; cursor: pointer; font-weight: bold; border: none; border-radius: 6px; transition: background 0.2s; }
          form input[type='submit']:hover { background-color: #22c55e; }
          @media (max-width: 600px) { h1 { font-size: 1.5em; } .card { margin: 10px; padding: 15px; } .value { font-size: 1.1em; } .label { font-size: 0.8em; } }
        </style>
        <script>
          // JavaScript-Funktion, die /data periodisch abfragt und Felder im HTML aktualisiert
          function updateData() {
            fetch('/data')
              .then(response => response.json())
              .then(data => {
                document.getElementById('zeit').textContent = data.zeit;
                document.getElementById('solar').textContent = data.solar + " W";
                document.getElementById('netz').textContent = data.netz + " W";
                document.getElementById('einspeisung').textContent = data.einspeisung + " kWh";
                document.getElementById('bezug').textContent = data.bezug + " kWh";
              })
              .catch(err => console.error("Fehler beim Datenabruf:", err));
          }
          setInterval(updateData, 5000); // alle 5 Sekunden aktualisieren
          window.onload = updateData;
        </script>
      </head>
      <body>
        <h1>ESP Energie Dashboard</h1>
        <div class="subtitle">Gerätename: )rawliteral";
      
        // Hier wird der Gerätename (OTA-Hostname) eingefügt
        html += otaHostname;
        html += R"rawliteral(</div>
        <div class="card">
          <div class="label">Zeit:</div>
          <div class="value" id="zeit">)rawliteral";
      
        // Aktuelle Zeit (Server-seitig) als initialer Wert
        html += String(timeStr);
        html += R"rawliteral(</div>
          <div class="label">Solar:</div>
          <div class="value" id="solar">)rawliteral";
      
        // Aktuelle Solarleistung als initialer Wert
        html += String(solarPower);
        html += R"rawliteral( W</div>
          <div class="label">Netz:</div>
          <div class="value" id="netz">)rawliteral";
      
        // Aktuelle Netzleistung
        html += String(gridPower);
        html += R"rawliteral( W</div>
          <div class="label">Einspeisung:</div>
          <div class="value" id="einspeisung">)rawliteral";
      
        // Aktuelle Einspeisung (kWh)
        html += String(einspeisung);
        html += R"rawliteral( kWh</div>
          <div class="label">Bezug:</div>
          <div class="value" id="bezug">)rawliteral";
      
        // Aktueller Bezug (kWh)
        html += String(bezug);
        html += R"rawliteral( kWh</div>
        </div>
      
        <div class="card">
          <form method='POST' action='/set'>
            <div class="label">Hintergrundlicht an (hh:mm):</div>
        )rawliteral";
      
        // Formularfelder: Werte werden aus den gespeicherten Variablen eingefügt
        html += "<input name='an_h' value=\"" + String(stunde_an) + "\" type='number' min='0' max='23'> : ";
        html += "<input name='an_m' value=\"" + String(minute_an) + "\" type='number' min='0' max='59'><br>";
        html += "<div class='label'>Dimmen ab (hh:mm):</div>";
        html += "<input name='dimmen_h' value=\"" + String(stunde_dimmen) + "\" type='number' min='0' max='23'> : ";
        html += "<input name='dimmen_m' value=\"" + String(minute_dimmen) + "\" type='number' min='0' max='59'><br>";
        html += "<div class='label'>Aus ab (hh:mm):</div>";
        html += "<input name='aus_h' value=\"" + String(stunde_aus) + "\" type='number' min='0' max='23'> : ";
        html += "<input name='aus_m' value=\"" + String(minute_aus) + "\" type='number' min='0' max='59'><br>";
        html += "<div class='label'>Dimmwert (0–1023):</div>";
        html += "<input name='dimValue' value=\"" + String(brightnessDim) + "\" type='number' min='0' max='1023'><br>";
        html += "<input type='submit' value='Speichern'>";
        html += "</form></div></body></html>";
      
        // Antwort an den Browser
        server.send(200, "text/html", html);
      }
      
      // Handler für das Formular /set (POST)
      // Liest die Formularfelder, validiert sie grob und schreibt sie ins EEPROM
      void handleSet() {
        if (server.method() == HTTP_POST) {
          // Formulardaten einlesen
          int an_h = server.arg("an_h").toInt();
          int an_m = server.arg("an_m").toInt();
          int dimmen_h = server.arg("dimmen_h").toInt();
          int dimmen_m = server.arg("dimmen_m").toInt();
          int aus_h = server.arg("aus_h").toInt();
          int aus_m = server.arg("aus_m").toInt();
          int dimValue = server.arg("dimValue").toInt();
      
          // Einfache Validierungschecks (nur Bereichsprüfung)
          if (an_h >= 0 && an_h < 24) stunde_an = an_h;
          if (an_m >= 0 && an_m < 60) minute_an = an_m;
          if (dimmen_h >= 0 && dimmen_h < 24) stunde_dimmen = dimmen_h;
          if (dimmen_m >= 0 && dimmen_m < 60) minute_dimmen = dimmen_m;
          if (aus_h >= 0 && aus_h < 24) stunde_aus = aus_h;
          if (aus_m >= 0 && aus_m < 60) minute_aus = aus_m;
          if (dimValue >= 0 && dimValue <= 1023) brightnessDim = dimValue;
      
          // Persistente Speicherung: einzelne Bytes ins EEPROM schreiben
          EEPROM.write(0, stunde_an);
          EEPROM.write(1, minute_an);
          EEPROM.write(2, stunde_dimmen);
          EEPROM.write(3, minute_dimmen);
          EEPROM.write(4, stunde_aus);
          EEPROM.write(5, minute_aus);
          EEPROM.write(6, brightnessDim & 0xFF);          // LSB des 16-bit Werts
          EEPROM.write(7, (brightnessDim >> 8) & 0xFF);   // MSB
          EEPROM.commit(); // Wichtig: Änderungen wirklich speichern
      
          // Bestätigungsseite zurück an den Browser
          String html = "<html><body style='font-family:sans-serif; background:#0b1120; color:#e2e8f0; padding:20px;'>";
          html += "<h2>✅ Einstellungen gespeichert</h2>";
          html += "<p><a href=\"/\">Zurück zum Dashboard</a></p>";
          html += "</body></html>";
          server.send(200, "text/html", html);
        } else {
          // Nur POST ist erlaubt
          server.send(405, "text/plain", "Method Not Allowed");
        }
      }
      
      // ------------------ Setup-Funktion ------------------
      void setup() {
        Serial.begin(115200); // Serielle Ausgabe für Debug
      
        // PWM / Backlight Pin vorbereiten
        pinMode(backlightPin, OUTPUT);
        analogWriteFreq(500); // PWM-Frequenz setzen (ESP8266 spezifisch)
      
        // Mit WLAN verbinden
        WiFi.begin(ssid, password);
        while (WiFi.status() != WL_CONNECTED) delay(500); // Blockiert bis Verbindung steht
      
        // Zeitkonfiguration: Zeitzone und NTP-Server
        // configTzTime nutzt die POSIX-Zeitzonenbeschreibung. Hier CET/CEST wird gesetzt.
        configTzTime("CET-1CEST,M3.5.0,M10.5.0/3", "pool.ntp.org", "time.nist.gov");
      
        // OTA initialisieren
        ArduinoOTA.setHostname(otaHostname.c_str());
        ArduinoOTA.setPassword(otaPassword.c_str());
        ArduinoOTA.begin();
      
        // TFT initialisieren
        tft.init();
        tft.invertDisplay(1); // Manche Displays benötigen invertiert beim ersten Einschalten
        tft.setRotation(3);   // Ausrichtung des Displays
      
        // IP-Anzeige beim Start initialisieren
        showIP = true;
        ipDisplayStart = millis();
      
        // mDNS: Gerät im lokalen Netzwerk unter "esp.local" verfügbar machen (falls mdns funktioniert)
        if (MDNS.begin("esp")) MDNS.addService("http", "tcp", 80);
      
        // Webserver Routen registrieren
        server.on("/", handleRoot);
        server.on("/set", HTTP_POST, handleSet);
        server.on("/data", handleData);
        server.begin();
      
        // Background initial: Hintergrundbeleuchtung auf vollen Wert setzen
        pinMode(backlightPin, OUTPUT);
        analogWrite(backlightPin, brightness);
      
        // EEPROM initialisieren und gespeicherte Einstellungen laden
        EEPROM.begin(EEPROM_SIZE);
        stunde_an = EEPROM.read(0);
        minute_an = EEPROM.read(1);
        stunde_dimmen = EEPROM.read(2);
        minute_dimmen = EEPROM.read(3);
        stunde_aus = EEPROM.read(4);
        minute_aus = EEPROM.read(5);
        brightnessDim = EEPROM.read(6) + (EEPROM.read(7) << 8); // 16-bit Wert aus zwei Bytes zusammensetzen
      
        // Gültigkeit der geladenen Werte prüfen, ggf. Standardwerte setzen
        bool invalid = false;
        if (stunde_an > 23) { stunde_an = 7; invalid = true; }
        if (minute_an > 59) { minute_an = 0; invalid = true; }
        if (stunde_dimmen > 23) { stunde_dimmen = 21; invalid = true; }
        if (minute_dimmen > 59) { minute_dimmen = 0; invalid = true; }
        if (stunde_aus > 23) { stunde_aus = 23; invalid = true; }
        if (minute_aus > 59) { minute_aus = 0; invalid = true; }
        if (brightnessDim > 1023) { brightnessDim = 200; invalid = true; }
      
        // Wenn ungültige Werte gefunden wurden, die korrigierten Standardwerte zurückschreiben
        if (invalid) {
          EEPROM.write(0, stunde_an);
          EEPROM.write(1, minute_an);
          EEPROM.write(2, stunde_dimmen);
          EEPROM.write(3, minute_dimmen);
          EEPROM.write(4, stunde_aus);
          EEPROM.write(5, minute_aus);
          EEPROM.write(6, brightnessDim & 0xFF);
          EEPROM.write(7, (brightnessDim >> 8) & 0xFF);
          EEPROM.commit();
        }
      }
      
      // ------------------ /data Handler: liefert JSON mit den aktuellen Werten ------------------
      void handleData() {
        time_t now = time(nullptr);
        struct tm* timeinfo = localtime(&now);
        char timeStr[30];
        strftime(timeStr, sizeof(timeStr), "%d.%m.%Y %H:%M:%S", timeinfo);
      
        // Einfacher JSON-String (manuell zusammengesetzt) mit den aktuellen Werten
        String json = "{";
        json += "\"zeit\":\"" + String(timeStr) + "\",";
        json += "\"solar\":" + String(solarPower) + ",";
        json += "\"netz\":" + String(gridPower) + ",";
        json += "\"einspeisung\":" + String(einspeisung) + ",";
        json += "\"bezug\":" + String(bezug);
        json += "}";
      
        server.send(200, "application/json", json);
      }
      
      // ------------------ Hauptschleife ------------------
      void loop() {
        ArduinoOTA.handle();   // OTA-Ereignisse verarbeiten (falls ein Update hereinkommt)
        server.handleClient(); // HTTP-Server-Anfragen verarbeiten
      
        // Beim Start die IP ein paar Sekunden zeigen
        if (showIP) {
          showIPOnDisplay();
          delay(5000); // 5 Sekunden warten während die IP angezeigt wird (blockierend)
          if (millis() - ipDisplayStart > ipDisplayDuration) {
            showIP = false;
            showMainDisplay();
          }
        } else {
          // Hintergrundbeleuchtung anpassen (je nach aktuellem Zeitpunkt)
          updateBacklight();
      
          unsigned long now = millis();
          if (now - lastUpdate > updateInterval) {
            lastUpdate = now;
      
            // Nur wenn WLAN verbunden ist, Daten abfragen
            if (WiFi.status() == WL_CONNECTED) {
              // --- 1) Anfrage an opendtu_url ---
              http.begin(client, opendtu_url);
              http.setAuthorization(opendtu_user, opendtu_password); // Basic Auth
              int httpCode = http.GET();
              if (httpCode == 200) {
                // JSON-Antwort parsen
                StaticJsonDocument<2048> doc;
                DeserializationError err = deserializeJson(doc, http.getString());
                if (!err)
                  solarPower = doc["total"]["Power"]["v"] | 0.0; // Pfad gemäß API (falls vorhanden)
              }
              http.end(); // Verbindung schließen
      
              // --- 2) Anfrage an hichi_url (z.B. Tasmota Status) ---
              http.begin(client, hichi_url);
              httpCode = http.GET();
              if (httpCode == 200) {
                StaticJsonDocument<1024> doc;
                DeserializationError err = deserializeJson(doc, http.getString());
                if (!err) {
                  // Werte (Pfad entsprechend der Tasmota-Status-Antwort)
                  gridPower = doc["StatusSNS"]["Zaehler"]["Power"] | 0.0;
                  einspeisung = doc["StatusSNS"]["Zaehler"]["E_out"] | 0.0;
                  bezug = doc["StatusSNS"]["Zaehler"]["E_in"] | 0.0;
                }
              }
              http.end();
      
              // ------------------ TFT-Display aktualisieren ------------------
              tft.fillRect(0, 30, tft.width(), 130, TFT_BLACK); // Bereich löschen
      
              // Solarleistung: große Schrift
              tft.setTextSize(3);
              tft.setTextColor(TFT_GREEN);
              tft.setTextDatum(MC_DATUM);
              char solarText[30];
              snprintf(solarText, sizeof(solarText), "Solar: %.0f W", solarPower);
              tft.drawString(solarText, tft.width() / 2, 50);
      
              // Einspeisung / Ausgang (kWh)
              tft.setTextSize(2);
              tft.setTextColor(TFT_LIGHTGREY);
              char einspeisungText[30];
              snprintf(einspeisungText, sizeof(einspeisungText), "Ausgang: %.2f kWh", einspeisung);
              tft.drawString(einspeisungText, tft.width() / 2, 80);
      
              // Netzleistung: Farbe abhängig vom Vorzeichen
              tft.setTextSize(3);
              uint16_t netzfarbe = (gridPower >= 0) ? TFT_RED : TFT_GREEN; // positiv=rot (Bezug), negativ=grün (Einspeisung)
              tft.setTextColor(netzfarbe);
              char gridText[30];
              snprintf(gridText, sizeof(gridText), "Netz: %.0f W", gridPower);
              tft.drawString(gridText, tft.width() / 2, 110);
      
              // Bezug (kWh)
              tft.setTextSize(2);
              tft.setTextColor(TFT_LIGHTGREY);
              char bezugText[30];
              snprintf(bezugText, sizeof(bezugText), "Eingang: %.2f kWh", bezug);
              tft.drawString(bezugText, tft.width() / 2, 140);
      
              // Unterer Balken: färbt die Fläche nach Netzstatus und schreibt Text
              uint16_t bottomColor = gridPower >= 0 ? TFT_RED : TFT_GREEN;
              tft.fillRect(0, 161, tft.width(), tft.height() - 161, bottomColor);
              tft.setTextSize(3);
              tft.setTextColor(TFT_BLACK);
              const char* statusText = gridPower >= 0 ? "Netzbezug" : "Einspeisung";
              int centerY = 161 + (tft.height() - 161) / 2;
              tft.drawString(statusText, tft.width() / 2, centerY);
            }
          }
        }
      }
      

      Technische Dokumentation – ESP8266 Energieanzeige

      1. Einleitung
        Das Projekt implementiert ein Energie-Monitoring-System auf einem ESP8266-Mikrocontroller.
        Es verbindet sich mit dem WLAN, ruft Energiedaten von einer OpenDTU und einem Tasmota-basierten Stromzähler ab, zeigt die Werte auf einem TFT-Display an und stellt zusätzlich ein Web-Dashboard zur Verfügung.
        Die Benutzer können Einstellungen für die Display-Hintergrundbeleuchtung über eine Weboberfläche vornehmen und im EEPROM speichern.
        Zusätzlich unterstützt das System Over-the-Air Updates (OTA) und ist per mDNS im Netzwerk auffindbar.

      1. Systemübersicht
        Hardware
        • ESP8266 (z. B. NodeMCU / Wemos D1 mini)
        • TFT-Display (angesteuert über TFT_eSPI-Library)
        • Stromzähler (HiChi/Tasmota) – liefert Netzwerte per HTTP
        • OpenDTU – liefert Solarleistungswerte per HTTP
        • Hintergrundbeleuchtung des TFT über PWM (Pin D3/RX)
        Software
        • Arduino Core for ESP8266
        • Wichtige Bibliotheken:
        o ESP8266WiFi (WLAN-Verbindung)
        o ESP8266WebServer (Webserver)
        o ArduinoJson (Parsing von API-Daten)
        o ArduinoOTA (Over-the-Air Updates)
        o TFT_eSPI (Displaysteuerung)
        o EEPROM (Speichern von Benutzer-Einstellungen)
        o time.h (NTP-Synchronisation, Sommerzeit)

      1. Programmablauf
        Setup (setup())
      2. WLAN-Verbindung mit gespeicherten SSID/Passwort.
      3. Zeitkonfiguration via NTP mit Sommerzeitregelung.
      4. OTA-Konfiguration (Hostname, Passwort, Start).
      5. Display-Initialisierung (Rotation, invertieren, Startanzeige).
      6. mDNS starten (esp.local).
      7. Webserver einrichten:
        o / → Dashboard
        o /data → JSON-Daten
        o /set → Einstellungsformular
      8. EEPROM laden und Werte prüfen/korrigieren.

      Loop (loop())
      • OTA-Requests bearbeiten (ArduinoOTA.handle()).
      • Webserver-Anfragen bedienen (server.handleClient()).
      • Display-Anzeige:
      o Start: IP-Adresse 5 Sekunden lang.
      o Danach: Hauptanzeige mit Solar, Netz, Einspeisung, Bezug.
      • Hintergrundbeleuchtung nach Uhrzeit an/aus/dimmen.
      • Alle 5 Sekunden:
      o Daten von OpenDTU (Solarleistung) und HiChi-Zähler (Netz, Einspeisung, Bezug) abrufen.
      o Display mit neuen Werten aktualisieren.


      1. Webinterface
        Dashboard (/)
        • Anzeige von:
        o Solarleistung (Watt)
        o Netzleistung (Watt)
        o Einspeisung (kWh)
        o Bezug (kWh)
        o Aktuelle Uhrzeit
        • Automatische Aktualisierung alle 5 Sekunden per AJAX.
        Einstellungen (/set)
        • Einstellen von:
        o An-Zeit (hh:mm)
        o Dimm-Zeit (hh:mm)
        o Aus-Zeit (hh:mm)
        o Dimmwert (PWM, 0–1023)
        • Werte werden im EEPROM gespeichert und beim Neustart geladen.
        Daten-Endpunkt (/data)
        • JSON-Ausgabe mit aktuellen Messwerten, z. B.:
        {
        "zeit": "10.09.2025 12:34:56",
        "solar": 450.0,
        "netz": -120.0,
        "einspeisung": 5.32,
        "bezug": 2.45
        }

      2. EEPROM-Nutzung
        Die Benutzer-Einstellungen werden im EEPROM gespeichert:
        • Adresse 0 → Stunde An
        • Adresse 1 → Minute An
        • Adresse 2 → Stunde Dimmen
        • Adresse 3 → Minute Dimmen
        • Adresse 4 → Stunde Aus
        • Adresse 5 → Minute Aus
        • Adresse 6 → Dimmwert LSB
        • Adresse 7 → Dimmwert MSB
        Damit bleiben die Werte auch nach einem Neustart erhalten.


      1. Besondere Funktionen
        • Sommerzeitberechnung: Automatische Umstellung gemäß Mitteleuropäischer Zeit (MEZ/MEZ+1).
        • Farbanzeige im Display:
        o Rot: Netzbezug
        o Grün: Einspeisung
        • OTA-Update: Programm kann per WLAN aktualisiert werden, ohne USB.
        • mDNS: Zugriff über http://esp.local/.

      1. Einsatzszenario
        Dieses System eignet sich besonders für Heimanwendungen, bei denen ein Balkonkraftwerk (Solar-Inverter) und ein Haushaltszähler überwacht werden sollen.
        Es bietet:
        • Schnelle Übersicht am Display (lokal, ohne PC/Smartphone).
        • Browser-Dashboard für Remote-Zugriff im Netzwerk.
        • Benutzerfreundliche Steuerung der Anzeige (automatische Dimmung).

      1. Grenzen und Anforderungen
        • Läuft ausschließlich auf ESP8266-Boards.
        • Erfordert ein funktionierendes WLAN.
        • Abhängigkeit von OpenDTU- und Tasmota-Geräten für Messdaten.
        • EEPROM hat begrenzte Schreibzyklen → sollte nicht zu oft überschrieben werden.

      Als Gehäuse habe ich dieses genommen:

      https://www.thingiverse.com/thing:4570437

      Display (2,4" TFT LCD Display Modul ILI9341 240x320) ist solch eines:

      https://www.roboter-bausatz.de/p/2-4-tft-lcd-display-modul-ili9341-240x320
      Es scheint, das es zwei verschiedene Arten von diesem Display gibt. Im Skript ist dafür eine Einstellung vorgesehen um die Farben zu invertieren.

      und natürlich ein Wemos D1 mini.

      Für das Display gibt es auch eine direkt Adapterplatine um den Wemos D1 mini ohne Kabelgefummel anzuschliessen.

      sm_red_top.png

      KiCAD-master.zip

      Hier mal ein Bild:

      innen.jpg
      anzeige.jpg
      einspeisung.jpg

      Bei mir hat es sich gezeigt, das der "WAF" sehr hoch ist. 😊

      posted in Praktische Anwendungen (Showcase)
      B
      Beowolf
    • RE: Test Adapter shuttercontrol v2.0.x

      @simatec

      Danke für die Info. Funktioniert alles.

      posted in Tester
      B
      Beowolf
    • RE: Test Adapter shuttercontrol v2.0.x

      @simatec sagte in Test Adapter shuttercontrol v2.0.x:

      val === 'up' ? 100 : val === 'shade' ? 50 : 0

      Ich verstehe nicht wo das eingegeben werden muß?

      posted in Tester
      B
      Beowolf
    • RE: Test Adapter shuttercontrol v2.0.x

      @simatec
      Hattest du schon Zeit um es etwas genauer zu beschreiben?

      posted in Tester
      B
      Beowolf
    • RE: Test Adapter shuttercontrol v2.0.x

      shade kennt er noch.

      "Dem Alias kannst du so erstellen, dass up = 100 und down = 0 ist."

      Kannst du mir zeigen wo das gemacht wird?

      posted in Tester
      B
      Beowolf
    • RE: Test Adapter shuttercontrol v2.0.x

      Hab da mal ne Frage.

      Ich habe TDEF-Motoren von Jarolift. Die verstehen UP, DOWN und STOP per mqtt.

      Kann ich die in den Adapter auch anbinden und steuern?

      posted in Tester
      B
      Beowolf
    • RE: E-Ink OpenEpaperLink - JSON-Steuerung per Javascript

      Könntest du die kleinen Grafiken hier anzeigen?

      Also window_open48.jpg usw.

      Grüße

      posted in Praktische Anwendungen (Showcase)
      B
      Beowolf
    • RE: [Vorlage] Xiaomi Airpurifier 3H u.a. inkl. Token auslesen.

      @dirkhe

      Ist das richtig, das das skript hier hin kommt?

      /opt/iobroker/node_modules/iobroker.mihome-vacuum/lib/

      Wenn ja, der Inhalt der Datei die dort schon liegt ist identisch mit der auf github.

      posted in JavaScript
      B
      Beowolf
    • RE: Test Adapter mihome-cloud

      Habe das Skript mal gerade getestet. Scheitert bei mir mit der gleichen Fehlermeldung. Man kann sich nicht anmelden.

      posted in Tester
      B
      Beowolf
    • RE: Test Adapter mihome-cloud

      @haselchen

      Ich glaube, das hier etwas durcheinander läuft.

      Welches Skript meinst du? Event. noch einmal hier einstellen.

      posted in Tester
      B
      Beowolf
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo