// virtuellerSmartmeter für openDTU OnBattery auf Basis von ESP8266 von BalkonBKW(R) (einphasig) // hier wird ein schelly 3em pro simuliert #include #include #include #include #include #include #include int shellyNummer; const int Debug = 1 ; // ein mögliches Szenario int einspeiser = 0; // variable für Einspeiseleistung (shelly PlugS gen.2 am AC-Ausgang von Mikrowechselrichter) int verbraucher1 = 0; // variable für Leistungsbezug Steckdose1 (shelly PlusS gen.2 - Steckdose) int verbraucher2 = 0; // variable für Leistungsbezug Steckdose2 (shelly PlusS gen.2 - Steckdose) int verbraucher3 = 0; // variable für Leistungsbezug Steckdose3 (shelly PlusS gen.2 - Steckdose) int verbraucher4 = 0; // variable für Leistungsbezug Steckdose4 (shelly PlusS gen.2 - Steckdose) int verbraucher5 = 0; // variable für Leistungsbezug (shelly 1pm mini - z.B. Leuchtendose) unsigned long previousMillis = 0; const long interval = 350; // Abfrageinterval der einzelnen shellys (ms) - anpassbnar float pwrNetz = 0; // WICHTIG: OpenDTU-onBattery erwartet oft einen Float-Wert im JSON ESP8266WebServer server(80); /* http Händler für openDTU On-battery */ void handleStatus() { // Shelly Pro 3EM Gen2 API Format String json = "{\"em:0\":{\"total_act_power\":" + String(pwrNetz, 1) + "}}"; server.send(200, "application/json", json); } /*Router, z.B. Fritzbox7490, den shellys feste ip-adressen im WLAM vergeben*/ const char* ssid = "hier eigene ssid eintragen"; const char* password = "hier fritzbox pw eintragen"; String Shelly_IP1 = "192.168.188.10"; // shelly PlusS gen.2 String Shelly_IP2 = "192.168.188.11"; // shelly PlusS gen.2 String Shelly_IP3 = "192.168.188.12"; // shelly PlusS gen.2 String Shelly_IP4 = "192.168.188.13"; // shelly PlusS gen.2 String Shelly_IP5 = "192.168.188.14"; // shelly PlusS gen.2 String Shelly_IP6 = "192.168.188.15"; // shelly 1pm mini ESP8266WiFiMulti WiFiMulti; const int led = LED_BUILTIN; void setup() { pinMode(led, OUTPUT); digitalWrite(led, LOW); Serial.begin(115200); Serial.println(); Serial.printf("[SETUP] WAIT ...\n"); Serial.flush(); Serial.println(); WiFi.mode(WIFI_STA); WiFiMulti.addAP(ssid, password); digitalWrite(led, HIGH); int shellyNummer = 1; // Wichtig: Der Pfad muss exakt stimmen server.on("/rpc/Shelly.GetStatus", handleStatus); server.begin(); Serial.println("HTTP Server gestartet"); /*Damit die Simulation funktioniert, musst du in der Web-Oberfläche der OpenDTU folgende Einstellungen unter Stromzähler vornehmen: • Typ: HTTP JSON • URL: http://192.168.188.19/rpc/Shelly.GetStatus // Die URL von D1mini ist hier http://192.168.188.XX/ • JSON-Pfad: em:0/total_act_power */ } int http_get(String getstr,int pwr) { DynamicJsonDocument doc(2048); WiFiClient client; HTTPClient http; if (getstr=="Shelly") { if (shellyNummer == 1) { getstr = "http://" + Shelly_IP1 + "/rpc/Shelly.GetStatus" ; } // Shelly PlugS Abfrage (Einspeisen) else if (shellyNummer == 2) { getstr = "http://" + Shelly_IP2 + "/rpc/Shelly.GetStatus" ; } // Shelly PlugS Abfrage (Verbrauch) else if (shellyNummer == 2) { getstr = "http://" + Shelly_IP3 + "/rpc/Shelly.GetStatus" ; } // Shelly PlugS Abfrage (Verbrauch) else if (shellyNummer == 2) { getstr = "http://" + Shelly_IP4 + "/rpc/Shelly.GetStatus" ; } // Shelly PlugS Abfrage (Verbrauch) else if (shellyNummer == 2) { getstr = "http://" + Shelly_IP5 + "/rpc/Shelly.GetStatus" ; } // Shelly PlugS Abfrage (Verbrauch) else if (shellyNummer == 6) { getstr = "http://" + Shelly_IP6 + "/rpc/Shelly.GetStatus" ; } // Shelly 1pmmini Abfrage (Verbrauch) } if (Debug > 0) {Serial.println(getstr);} ; if (http.begin(client, getstr)) { int httpCode = http.GET(); if (httpCode > 0) { if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { String payload = http.getString(); //Serial.println(payload); DeserializationError error = deserializeJson(doc, payload); if (Debug >1) {serializeJsonPretty(doc, Serial); } ; // nur Debug if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f_str()); } if (shellyNummer == 1) { einspeiser = doc["switch:0"]["apower"] ; // Shelly PlugS --> Einspeisen Serial.print("Einspeisung(Watt): "); Serial.println(einspeiser); } if (shellyNummer == 2) { verbraucher1 = doc["switch:0"]["apower"] ; // Shelly PlugS --> Einspeisen Serial.print("Einspeisung(Watt): "); Serial.println(einspeiser); } if (shellyNummer == 3) { verbraucher2 = doc["switch:0"]["apower"] ; // Shelly PlugS --> Einspeisen Serial.print("Einspeisung(Watt): "); Serial.println(einspeiser); } if (shellyNummer == 4) { verbraucher3 = doc["switch:0"]["apower"] ; // Shelly PlugS --> Einspeisen Serial.print("Einspeisung(Watt): "); Serial.println(einspeiser); } if (shellyNummer == 5) { verbraucher4 = doc["switch:0"]["apower"] ; // Shelly PlugS --> Einspeisen Serial.print("Einspeisung(Watt): "); Serial.println(einspeiser); } else if (shellyNummer == 6) { verbraucher5 = doc["pm1:0"]["apower"] ; // Shelly 1PMmini --> Leuchte Serial.print("Wohnzimmer(Watt): "); Serial.println(verbraucher5); } } } else { Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); if (shellyNummer == 1) {einspeiser = 0; Serial.print("Einspeisen(Watt): "); Serial.println(einspeiser);} else if (shellyNummer == 2) {verbraucher1 = 0; Serial.print("Verbraucher1(Watt): "); Serial.println(verbraucher1);} else if (shellyNummer == 3) {verbraucher1 = 0; Serial.print("Verbraucher2(Watt): "); Serial.println(verbraucher2);} else if (shellyNummer == 4) {verbraucher1 = 0; Serial.print("Verbraucher3(Watt): "); Serial.println(verbraucher3);} else if (shellyNummer == 5) {verbraucher1 = 0; Serial.print("Verbraucher5(Watt): "); Serial.println(verbraucher5);} else if (shellyNummer == 6) {verbraucher5 = 0; Serial.print("Leuchte(Watt): "); Serial.println(verbraucher5);} } http.end(); } else { Serial.printf("[HTTP} Unable to connect\n"); } return pwr; } void loop() { int pwrConsum; int pwrReture; int pwrDiff; // Serial.println(pwrDiff); int grundlast = 0; // shelly's eigener Verbrauch und Grundlast unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) // Shellys AbfrageInterval { previousMillis = currentMillis; // wait for WiFi connection if ((WiFiMulti.run() == WL_CONNECTED)) { //digitalWrite(led, LOW); http_get("Shelly",0); //digitalWrite(led, HIGH); shellyNummer ++; /* hier wird die Abfrage auf zwei shelly's begrenz */ if (shellyNummer > 2) // den Zyklus fortsetzen sobald alle 2 shellys abgefragt wurden (shellyNummer nach Bedarf anpassen) { pwrConsum = verbraucher1 + grundlast; // Gesamtverbrauch wird ermittelt (beim Erweitern: + verbraucher + verbraucher3 usw.) pwrReture = einspeiser; pwrDiff = pwrConsum - pwrReture; // Gesamtverbrauch - Einspeisung Serial.print("VerbrauchMinusEinspeisung: "); Serial.println(pwrDiff); pwrNetz = pwrDiff; // umwandlung von int zu float server.handleClient(); // http Händler für openDTU On-battery shellyNummer = 1; // nächste shellys Abfrage vorbereiten } } } }