#include #include #include //#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 = 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); int numNetworks = sizeof(ssidList) / sizeof(ssidList[0]); int current_ap = 0; // Start mit der ersten SSID bool reconnecting = false; // Flag für den Reconnect-Status // WLAN Symbol byte customChar_wlan[] = { B00000, B01110, B10001, B00100, B01010, B00000, B00100, B00000 }; void _lcd_display_text(int row = 0, const char* text = " ", const char* alignment = "left", bool returnToStart = false) { int textLength = strlen(text); if (row < 0 || row > 1) { return; } lcd.setCursor(0, row); if (textLength <= 16) { int padding = 0; if (strcmp(alignment, "center") == 0) { padding = (16 - textLength) / 2; } else if (strcmp(alignment, "right") == 0) { padding = 16 - textLength; } lcd.setCursor(0, row); for (int i = 0; i < padding; i++) { lcd.print(" "); } lcd.print(text); } else { lcd.setCursor(0, row); lcd.print(text); delay(2000); for (int i = 1; i <= textLength - 16; i++) { lcd.setCursor(0, row); lcd.print(text + i); delay(300); } if (returnToStart) { lcd.setCursor(0, row); lcd.print(text); } else { lcd.setCursor(0, row); lcd.print(text + (textLength - 16)); } } } void extractTasmotaValues(const String& url, String values[5]) { WiFiClient client; HTTPClient http; for (int i = 0; i < 5; i++) { values[i] = "?"; // Standardwert, falls Tasmota Gerät nicht antwortet } if (http.begin(client, url)) { int httpResponseCode = http.GET(); if (httpResponseCode == 200) { String response = http.getString(); http.end(); // Array mit den Schlüsseln der gewünschten Werte const String keys[5] = {json_prefix_Power, json_prefix_1_8_0, json_prefix_1_8_1, json_prefix_1_8_2, json_prefix_2_8_0}; // 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 } } } } else { Serial.println("HTTP Fehler: " + String(httpResponseCode)); } http.end(); } else { Serial.println("Verbindung zur URL fehlgeschlagen: " + url); } } 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]); int attempt = 0; while (WiFi.status() != WL_CONNECTED && attempt < 10) { delay(500); Serial.print("."); lcd.setCursor(15, 1); lcd.print(" "); delay(500); lcd.setCursor(15, 1); lcd.write(byte(0)); attempt++; } if (WiFi.status() != WL_CONNECTED) { WiFi.disconnect(); delay(500); Serial.println("\nVerbindung fehlgeschlagen."); current_ap = (current_ap + 1) % numNetworks; reconnecting = false; } else { Serial.println("\nWLAN verbunden: " + WiFi.SSID()); _lcd_display_text(0, "WLAN verbunden", "center"); _lcd_display_text(1); _lcd_display_text(1, WiFi.SSID().c_str()); reconnecting = false; delay(2500); _lcd_display_text(0, "Netzbezug: ?W"); _lcd_display_text(1, "Erzeugung: ?W"); } } void update_power_values() { 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"); ip_netzbezug_values_old[0] = ip_netzbezug_values[0]; ip_erzeugung_values_old[0] = ip_erzeugung_values[0]; } 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]; } 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) { 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); isModeChanged = true; delay(200); } lastButtonState = currentButtonState; } void setup() { pinMode(BUTTON_PIN, INPUT_PULLUP); Serial.begin(115200); delay(1000); lcd.init(); lcd.backlight(); lcd.createChar(0, customChar_wlan); WiFi.setHostname(hostname); WiFi.mode(WIFI_STA); lcd.setCursor(0, 0); _lcd_display_text(0, "Bereit", "center"); } void loop() { handleButtonPress(); if (WiFi.status() != WL_CONNECTED && !reconnecting) { reconnecting = true; connectToWiFi(); } if (WiFi.status() == WL_CONNECTED && !reconnecting) { if (millis() - lastUpdateTime >= refreshRate) { lastUpdateTime = millis(); extractTasmotaValues("http://" + ip_netzbezug + "/cm?cmnd=Status%208", ip_netzbezug_values); if (currentMode == 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 (HT+NT):", "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 (HT):", "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 (NT):", "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 (Einsp.):", "center"); update_280_values(); } break; } }