Files
esp8266_lcd_energymeter/src/main.cpp
2024-12-26 22:19:38 +01:00

351 lines
9.6 KiB
C++

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <LiquidCrystal_I2C.h>
//#include <settings.h>
#include <settings-my-ignore.h>
#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;
}
}