From 0d798086caa76ebb8fd5a3b2b66c28ec3c137bc4 Mon Sep 17 00:00:00 2001 From: Thorsten Date: Thu, 26 Dec 2024 21:33:42 +0100 Subject: [PATCH] Button switches Modes now (Power, 1.8.0, 1.8.1, 1.8.2, 2.8.0) --- src/main.cpp | 259 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 151 insertions(+), 108 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5f839b2..42350a3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,28 +3,37 @@ #include #include - #define BUTTON_PIN D3 // GPIO-Pin verbunden mit Taster (D3 entspricht GPIO0) const uint32_t connectTimeoutMs = 10000; // WLAN Timeout // Globale Variablen unsigned long lastUpdateTime = 0; // Zeitstempel der letzten Aktion -unsigned long refreshRate = 5000; // Anfangsverzögerung in Millisekunden -unsigned long messageDisplayTime = 0; // Zeitstempel für die 5-Sekunden-Anzeige -bool isMessageDisplayed = false; // Zustand, ob die Aktualisierungsrate angezeigt wird - -int currentDelayIndex = 0; // Aktueller Index im Delay-Array -const unsigned long delayOptions[] = {5000, 10000, 15000, 20000, 30000, 45000, 60000, 1000, 2000}; -const int delayOptionsSize = sizeof(delayOptions) / sizeof(delayOptions[0]); +unsigned long refreshRate = 2500; // Aktualisierungsrate in Millisekunden +bool isModeChanged = false; // Zustand, ob eine Nachricht angezeigt wird int lastButtonState = HIGH; // Letzter Zustand des Buttons int currentButtonState; +// Array für die Werte +String ip_netzbezug_values[5]; +String ip_erzeugung_values[5]; + +String ip_netzbezug_values_old[5]; +String ip_erzeugung_values_old[5]; + +// Modus-Definitionen +int currentMode = 0; +const char* modeNames[] = {"Leistung", "1.8.0", "1.8.1", "1.8.2", "2.8.0"}; + + + String netzbezug; String netzbezug_alt; String erzeugung; String erzeugung_alt; +String e_in_180; +String e_in_180_old; // LCD initialisieren (16x2 Display) LiquidCrystal_I2C lcd(0x27, 16, 2); @@ -45,128 +54,106 @@ byte customChar_wlan[] = { B00000 }; -// Funktion zum Anzeigen von Text auf einem 1602 LCD Display -// -// _lcd_display_text(TEXT, ROW, RETURNTOSTART, ALIGNMENT) -// -// row = 0 Zeile 0 wir beschrieben [default] -// = 1 Zeile 1 wir beschrieben [default] -// text = Der anzuzeigende Text (default löscht die komplette Zeile) -// alignment = left Text Ausrichtung links (Bei <= 16 Zeichen) [default] -// = center Text Ausrichtung zentriert (Bei <= 16 Zeichen) -// = right Text Ausrichtung links (Bei <= 16 Zeichen) -// returnToStart = false Zu langer Text der durchgescrollt wird stoppt am Ende [default] -// true Zu langer Text der durchgescrollt wird springt zum 1. Buchstaben zurück void _lcd_display_text(int row = 0, const char* text = " ", const char* alignment = "left", bool returnToStart = false) { - - // Textlänge ermitteln int textLength = strlen(text); - // Sicherstellen, dass die Zeile gültig ist (0 oder 1) if (row < 0 || row > 1) { return; } lcd.setCursor(0, row); - // Wenn der Text <= 16 Zeichen ist, ausrichten if (textLength <= 16) { int padding = 0; if (strcmp(alignment, "center") == 0) { - padding = (16 - textLength) / 2; // Zentriert + padding = (16 - textLength) / 2; } else if (strcmp(alignment, "right") == 0) { - padding = 16 - textLength; // Rechtsbündig + padding = 16 - textLength; } - //lcd.clear(); lcd.setCursor(0, row); - // Leerzeichen vor dem Text für Ausrichtung for (int i = 0; i < padding; i++) { lcd.print(" "); } - // Text ausgeben lcd.print(text); - } else { - // Wenn der Text > 16 Zeichen ist, zuerst die ersten 16 Zeichen anzeigen lcd.setCursor(0, row); lcd.print(text); - delay(2000); // Kurze Pause, damit der Anfang lesbar ist + delay(2000); - // Danach scrollen for (int i = 1; i <= textLength - 16; i++) { lcd.setCursor(0, row); - lcd.print(text + i); // Ab Offset i den Text anzeigen - delay(300); // Verzögerung für Scroll-Geschwindigkeit + lcd.print(text + i); + delay(300); } - // Verhalten nach dem Scrollen festlegen if (returnToStart) { lcd.setCursor(0, row); - lcd.print(text); // Anfang des Textes wieder anzeigen + lcd.print(text); } else { lcd.setCursor(0, row); - lcd.print(text + (textLength - 16)); // Text hinten stehen lassen + lcd.print(text + (textLength - 16)); } } } -// Funktion zum Extrahieren eines Wertes aus der GET-Anfrage von Tasmota-Geräten -String _extract_value_tasmota_json(const String& url, const String& key) { - WiFiClient client; // WiFiClient-Objekt erstellen +void extractTasmotaValues(const String& url, String values[5]) { + WiFiClient client; HTTPClient http; - if (http.begin(client, url)) { // Begin mit WiFiClient und URL + if (http.begin(client, url)) { int httpResponseCode = http.GET(); if (httpResponseCode == 200) { String response = http.getString(); http.end(); - int startIndex = response.indexOf("\"" + key + "\":"); - if (startIndex == -1) { - return "?"; // Key nicht gefunden + // Array mit den Schlüsseln der gewünschten Werte + const String keys[5] = {"Power", "E_in_180", "E_in_181", "E_in_182", "E_out_280"}; + + // Werte initialisieren + for (int i = 0; i < 5; i++) { + values[i] = ""; // Standardwert, falls Key nicht gefunden wird + int keyIndex = response.indexOf("\"" + keys[i] + "\":"); + if (keyIndex != -1) { + int valueStart = keyIndex + keys[i].length() + 3; // Position nach dem ":" + int valueEnd = response.indexOf(",", valueStart); // Ende der Zahl oder des Wertes + if (valueEnd == -1) { + valueEnd = response.indexOf("}", valueStart); // Falls am Ende der JSON-Objekte + } + if (valueEnd != -1) { + values[i] = response.substring(valueStart, valueEnd); + values[i].trim(); // Entfernt überflüssige Leerzeichen + } + } } - startIndex += key.length() + 3; - int endIndex = response.indexOf(",", startIndex); - if (endIndex == -1) { - endIndex = response.indexOf("}", startIndex); - } - if (endIndex == -1) { - return "?"; - } - String value = response.substring(startIndex, endIndex); - value.trim(); - return String((int)value.toFloat()); // Nachkommastellen abschneiden } else { - //Serial.println("Fehler bei der Anfrage: " + String(httpResponseCode)); + Serial.println("HTTP Fehler: " + String(httpResponseCode)); } http.end(); } else { Serial.println("Verbindung zur URL fehlgeschlagen: " + url); } - - return "?"; } -// WLAN-Verbindung herstellen + + void connectToWiFi() { Serial.println("WLAN Verbindungsaufbau zu: " + String(ssidList[current_ap])); Serial.println("Passwort: " + String(passwordList[current_ap])); _lcd_display_text(0, "Bitte warten", "center"); _lcd_display_text(1, "WLAN verbinden ", "left"); - + lcd.createChar(0, customChar_wlan); lcd.setCursor(15, 1); lcd.write(byte(0)); WiFi.begin(ssidList[current_ap], passwordList[current_ap]); - //Blinkendes WLAN Symbol wärend das WLAN versucht zu verbinden int attempt = 0; while (WiFi.status() != WL_CONNECTED && attempt < 10) { delay(500); @@ -179,19 +166,14 @@ void connectToWiFi() { attempt++; } - //Verbindung fehlgeschlagen (current_ap erhöhen) if (WiFi.status() != WL_CONNECTED) { WiFi.disconnect(); delay(500); Serial.println("\nVerbindung fehlgeschlagen."); current_ap = (current_ap + 1) % numNetworks; reconnecting = false; - //Verbunden } else { - Serial.print("\nWLAN verbunden: "); - Serial.print(WiFi.SSID()); - Serial.print(" "); - Serial.println(WiFi.RSSI()); + Serial.println("\nWLAN verbunden: " + WiFi.SSID()); _lcd_display_text(0, "WLAN verbunden", "center"); _lcd_display_text(1); @@ -207,51 +189,65 @@ void connectToWiFi() { void update_power_values() { - Serial.print("SmartMeterReader auslesen: "); - netzbezug = _extract_value_tasmota_json("http://" + ip_netzbezug + "/cm?cmnd=Status%208", "Power"); - Serial.print(netzbezug + "W\n"); + lcd.setCursor(10, 0); + lcd.print(" "); + lcd.setCursor(16 - (ip_netzbezug_values[0].length() + 1), 0); + lcd.print(ip_netzbezug_values[0]); + lcd.print("W"); + lcd.setCursor(10, 1); + lcd.print(" "); + lcd.setCursor(16 - (ip_erzeugung_values[0].length() + 1), 1); + lcd.print(ip_erzeugung_values[0]); + lcd.print("W"); - Serial.print("Zwischenstecker auslesen : "); - erzeugung = _extract_value_tasmota_json("http://" + ip_erzeugung + "/cm?cmnd=Status%208", "Power"); - Serial.print(erzeugung + "W\n"); + ip_netzbezug_values_old[0] = ip_netzbezug_values[0]; + ip_erzeugung_values_old[0] = ip_erzeugung_values[0]; +} - if (netzbezug != netzbezug_alt) { - lcd.setCursor(10, 0); - lcd.print(" "); - lcd.setCursor(16 - (netzbezug.length() + 1), 0); - lcd.print(netzbezug); - } +void update_180_values() { + _lcd_display_text(1, (ip_netzbezug_values[1] + "kWh").c_str(), "center"); + ip_netzbezug_values_old[1] = ip_netzbezug_values[1]; +} +void update_181_values() { + _lcd_display_text(1, (ip_netzbezug_values[2] + "kWh").c_str(), "center"); + ip_netzbezug_values_old[2] = ip_netzbezug_values[2]; +} - if (erzeugung != erzeugung_alt) { - lcd.setCursor(10, 1); - lcd.print(" "); - lcd.setCursor(16 - (erzeugung.length() + 1), 1); - lcd.print(erzeugung); - } - - netzbezug_alt = netzbezug; - erzeugung_alt = erzeugung; +void update_182_values() { + _lcd_display_text(1, (ip_netzbezug_values[3] + "kWh").c_str(), "center"); + ip_netzbezug_values_old[3] = ip_netzbezug_values[3]; +} +void update_280_values() { + _lcd_display_text(1, (ip_netzbezug_values[4] + "kWh").c_str(), "center"); + ip_netzbezug_values_old[4] = ip_netzbezug_values[4]; } void handleButtonPress() { + currentButtonState = digitalRead(BUTTON_PIN); if (currentButtonState == LOW && lastButtonState == HIGH) { - currentDelayIndex = (currentDelayIndex + 1) % delayOptionsSize; - refreshRate = delayOptions[currentDelayIndex]; - Serial.print("Neue Aktualisierungsrate: "); + lcd.clear(); + + currentMode = (currentMode + 1) % 5; + + Serial.print("Neuer Modus: "); + Serial.println(modeNames[currentMode]); + + if (currentMode == 0) { + refreshRate = 2500; + } else { + refreshRate = 15000; + } + + Serial.print("Aktualisierungsrate: "); Serial.println(refreshRate); - _lcd_display_text(0, " Aktual. Rate "); - _lcd_display_text(1); - _lcd_display_text(1, (String(refreshRate / 1000) + " Sekunden").c_str(), "center"); - - isMessageDisplayed = true; - messageDisplayTime = millis(); + isModeChanged = true; delay(200); } @@ -274,30 +270,77 @@ void setup() { lcd.setCursor(0, 0); _lcd_display_text(0, "Bereit", "center"); + + + + } void loop() { + handleButtonPress(); + //Serial.print("."); + if (WiFi.status() != WL_CONNECTED && !reconnecting) { reconnecting = true; connectToWiFi(); } - if (isMessageDisplayed && millis() - messageDisplayTime >= 2500) { - isMessageDisplayed = false; - _lcd_display_text(0, "Netzbezug: ?W"); - _lcd_display_text(1, "Erzeugung: ?W"); - update_power_values(); - } if (WiFi.status() == WL_CONNECTED && !reconnecting) { - - if (!isMessageDisplayed && millis() - lastUpdateTime >= refreshRate) { + if (millis() - lastUpdateTime >= refreshRate) { lastUpdateTime = millis(); - update_power_values(); - } + extractTasmotaValues("http://" + ip_netzbezug + "/cm?cmnd=Status%208", ip_netzbezug_values); + + switch (currentMode) { + case 0: + extractTasmotaValues("http://" + ip_erzeugung + "/cm?cmnd=Status%208", ip_erzeugung_values); + } + } } + + + switch (currentMode) { + case 0: + if (ip_netzbezug_values[0] != ip_netzbezug_values_old[0] || isModeChanged == true) { + isModeChanged = false; + _lcd_display_text(0, "Netzbezug:", "left"); + _lcd_display_text(1, "Erzeugung:", "left"); + update_power_values(); + + } + break; + case 1: + if (ip_netzbezug_values[1] != ip_netzbezug_values_old[1] || isModeChanged == true) { + isModeChanged = false; + _lcd_display_text(0, "1.8.0:", "center"); + update_180_values(); + } + break; + case 2: + if (ip_netzbezug_values[2] != ip_netzbezug_values_old[2] || isModeChanged == true) { + isModeChanged = false; + _lcd_display_text(0, "1.8.1:", "center"); + update_181_values(); + } + break; + case 3: + if (ip_netzbezug_values[3] != ip_netzbezug_values_old[3] || isModeChanged == true) { + isModeChanged = false; + _lcd_display_text(0, "1.8.2:", "center"); + update_182_values(); + } + break; + case 4: + if (ip_netzbezug_values[4] != ip_netzbezug_values_old[4] || isModeChanged == true) { + isModeChanged = false; + _lcd_display_text(0, "2.8.0:", "center"); + update_280_values(); + } + break; + } + }