HI Tommy
Da hast du natürlich recht.
Ich habe also den ESP8266 verbunden mit einem LCD 16x4 und gebe dort neben dem Seriellen Monitor die Daten aus.
Einerseits die Daten des Solarmanagers über die online API,
Andererseits die Daten des Askoheat über das heimische Netzwerk.
Ich hoffe ihr könnt es nachvollziehen und nutzen. Oder weiter entwickeln.
Gruss
Robert
Code:
// Boardeinstellung für den ESP8266: NodeMCU 0.9 (ESP12-Module)
// Solarmanager-API ist hier beschrieben. https://external-web.solar-manager.ch/swagger
// Version 2.0 - Zeit stimmt nicht im Winter; Temp.abfrage OK
// Version 2.3 - Erzeugung pro Tag; Zeitabfrage aus WLAN - OK
// Version 2.4 - Erzeugung pro Tag auskommentiert ; Mit Batterieanzeige
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <WiFiClientSecure.h>
#include <ESP8266HTTPClient.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <time.h>
// WiFi credentials
const char* ssid = "Dein W-Lan";
const char* password = "xxxxxxxxxxxxx";
// Solar Manager credentials (Base64 encoded username:password)
const char* authHeader = "Basic xxxxxYOUR_SOLARMANAGER_CODExxxxx";
// Client ID
const char* clientId = "xxxxxxSOLARMANAGER_IDxxxx";
// Initialize the LCD, specifying the I2C address (usually 0x27) and the dimensions (20x4)
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Custom character for degree Celsius
byte degreeCelsius[8] = {
0b11000,
0b11000,
0b00000,
0b00111,
0b01000,
0b01000,
0b01000,
0b00111
};
byte grad[8] = {
0b00111,
0b00101,
0b00111,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000,
};
byte boiler[8] = {
0b11111,
0b10001,
0b10101,
0b10001,
0b10001,
0b10001,
0b11111,
0b11111,
};
void setup() {
Serial.begin(115200);
delay(100);
// Initialize the I2C communication
Wire.begin();
// Initialize the LCD
lcd.begin(20, 4);
lcd.backlight();
// Clear the display
lcd.clear();
// Create the custom degree Celsius character
lcd.createChar(0, degreeCelsius);
lcd.createChar(1, grad);
lcd.createChar(2, boiler);
Serial.println();
Serial.print("Verbinde mit ");
Serial.println(ssid);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Verbinde mit ");
lcd.setCursor(0, 1);
lcd.print(ssid);
lcd.setCursor(0, 3);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
lcd.print(".");
}
Serial.println("");
Serial.println("WiFi verbunden");
Serial.print("IP-Adresse: ");
Serial.println(WiFi.localIP());
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi verbunden");
lcd.setCursor(0, 1);
lcd.print("IP: ");
lcd.print(WiFi.localIP());
// Konfiguriere die Zeitzone für Deutschland (CET/CEST)
configTime(3600, 3600, "pool.ntp.org", "time.nist.gov"); // 3600 Sekunden = 1 Stunde
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
WiFiClientSecure client;
HTTPClient http;
client.setInsecure(); // Use this only if the server uses a self-signed certificate
Serial.print("[HTTP] Verbinde mit Solar Manager...");
if (client.connect("cloud.solar-manager.ch", 443)) {
Serial.println("Verbunden!");
// 1. Daten des Gateways abrufen
String gatewayUrl = String("https://cloud.solar-manager.ch/v1/stream/gateway/") + clientId;
http.begin(client, gatewayUrl);
http.addHeader("accept", "application/json");
http.addHeader("authorization", authHeader);
int gatewayHttpCode = http.GET();
if (gatewayHttpCode > 0) {
String gatewayPayload = http.getString();
Serial.println("[HTTP] Gateway Antwort empfangen");
Serial.println(gatewayPayload);
// Parse the received JSON payload for gateway data
StaticJsonDocument<2048> gatewayDoc;
DeserializationError gatewayError = deserializeJson(gatewayDoc, gatewayPayload);
if (gatewayError) {
Serial.print("Gateway JSON parse error: ");
Serial.println(gatewayError.f_str());
return;
}
// Ausgabe der Daten des Gateways
Serial.println("Gateway Daten:");
serializeJsonPretty(gatewayDoc, Serial);
lcd.clear();
// Ausgabe des aktuellen Stromverbrauchs
if (gatewayDoc.containsKey("currentPowerConsumption")) {
float currentPowerConsumption = gatewayDoc["currentPowerConsumption"];
int roundedCurrentPowerConsumption = round(currentPowerConsumption);
Serial.print("Aktueller Stromverbrauch: ");
Serial.println(roundedCurrentPowerConsumption);
lcd.setCursor(0, 1);
lcd.print("Verbrauch: ");
lcd.print(roundedCurrentPowerConsumption);
lcd.print(" W");
}
// Ausgabe der aktuellen Solarleistung
if (gatewayDoc.containsKey("currentPvGeneration")) {
float currentPvGeneration = gatewayDoc["currentPvGeneration"];
int roundedCurrentPvGeneration = round(currentPvGeneration);
Serial.print("Aktuelle Solarleistung: ");
Serial.println(roundedCurrentPvGeneration);
lcd.setCursor(0, 0);
lcd.print("PV-Anlage: ");
lcd.print(roundedCurrentPvGeneration);
lcd.print(" W");
}
// Ausgabe des aktuellen Netzbezugs oder Einspeisung
if (gatewayDoc.containsKey("currentGridPower")) {
float currentGridPower = gatewayDoc["currentGridPower"];
int roundedCurrentGridPower = round(currentGridPower);
if (roundedCurrentGridPower < 0) {
Serial.print("Aktuelle Einspeisung: ");
Serial.println(-roundedCurrentGridPower);
lcd.setCursor(0, 2);
lcd.print("Einspeis.: ");
lcd.print(-roundedCurrentGridPower);
lcd.print(" W");
} else {
Serial.print("Aktueller Netzbezug: ");
Serial.println(roundedCurrentGridPower);
lcd.setCursor(0, 2);
lcd.print("Netzbezug: ");
lcd.print(roundedCurrentGridPower);
lcd.print(" W");
}
}
// Ausgabe der aktuellen Batterieanzeige
if (gatewayDoc.containsKey("soc")) {
float soc = gatewayDoc["soc"];
int roundedsoc = round(soc);
Serial.print("Batterie: ");
Serial.println(roundedsoc);
lcd.setCursor(0, 3);
lcd.print("Batterie : ");
lcd.print(roundedsoc);
lcd.print(" %");
}
/*
// Zeit vom Netzwerk abrufen
time_t now = time(nullptr);
struct tm* timeInfo = localtime(&now);
char fromTime[25];
char correctedTimestamp[25];
strftime(fromTime, sizeof(fromTime), "%Y-%m-%dT00:00:00.000Z", timeInfo);
strftime(correctedTimestamp, sizeof(correctedTimestamp), "%Y-%m-%dT%H:%M:%S.000Z", timeInfo);
// 2. Produktion abfragen für den spezifischen Zeitraum
String productionUrl = "https://cloud.solar-manager.ch/v1/statistics/gateways/" + String(clientId) + "?accuracy=low&from=" + fromTime + "&to=" + correctedTimestamp;
http.begin(client, productionUrl);
http.addHeader("accept", "application/json");
http.addHeader("authorization", authHeader);
int productionHttpCode = http.GET();
if (productionHttpCode > 0) {
String productionPayload = http.getString();
Serial.println("[HTTP] Production Antwort empfangen");
Serial.println(productionPayload);
Serial.print("fromTime: ");
Serial.println(fromTime);
Serial.print("correctedTimestamp: ");
Serial.println(correctedTimestamp);
// Parse production JSON payload
StaticJsonDocument<2048> productionDoc;
DeserializationError productionError = deserializeJson(productionDoc, productionPayload);
if (productionError) {
Serial.print("Production JSON parse error: ");
Serial.println(productionError.f_str());
return;
}
// Output production data
if (productionDoc.containsKey("production")) {
float production = productionDoc["production"];
int roundedProduction = round(production);
Serial.print("Produktion: ");
Serial.println(roundedProduction);
lcd.setCursor(0, 3);
lcd.print("S.Energie: ");
lcd.print(roundedProduction);
lcd.print(" Wh");
} else {
Serial.print("[HTTP] Fehler beim Abrufen der Produktion: ");
Serial.println(productionHttpCode);
}
http.end(); // Close production HTTP request
} else {
Serial.println("[HTTP] Timestamp nicht gefunden in der Gateway-Antwort");
}
*/
} else {
Serial.print("[HTTP] Fehler beim Abrufen der Gateway-Antwort: ");
Serial.println(gatewayHttpCode);
}
http.end(); // Close gateway HTTP request
if (WiFi.status() == WL_CONNECTED) {
WiFiClient client;
HTTPClient http;
//Abfrage des Askoheat (Boilerheizung) über das Heimnetzwerk
Serial.print("[HTTP] Verbinde mit EMA...");
if (http.begin(client, "http://192.168.1.249/getema.json")) {
int httpCode1 = http.GET();
if (httpCode1 > 0) {
String payload = http.getString();
Serial.println("[HTTP] EMA Response received");
Serial.println(payload);
// Parse the received JSON payload for EMA data
StaticJsonDocument<1024> emaDoc;
DeserializationError error = deserializeJson(emaDoc, payload);
if (error) {
Serial.print("EMA JSON parse error: ");
Serial.println(error.c_str());
return;
}
// Display EMA temperatures
if (emaDoc.containsKey("MODBUS_EMA_TEMPERATURE_FLOAT_SENSOR1") && emaDoc.containsKey("MODBUS_EMA_TEMPERATURE_FLOAT_SENSOR0")) {
float sensor1Temp = emaDoc["MODBUS_EMA_TEMPERATURE_FLOAT_SENSOR1"].as<String>().toFloat();
float sensor0Temp = emaDoc["MODBUS_EMA_TEMPERATURE_FLOAT_SENSOR0"].as<String>().toFloat();
int roundedSensor1Temp = round(sensor1Temp);
int roundedSensor0Temp = round(sensor0Temp);
Serial.print("Sensor 1 Temperature: ");
Serial.println(roundedSensor1Temp);
Serial.print("Sensor 0 Temperature: ");
Serial.println(roundedSensor0Temp);
lcd.setCursor(18, 0);
lcd.write(byte(1));
lcd.setCursor(19, 0);
lcd.print("C");
lcd.setCursor(18, 1);
lcd.print(roundedSensor1Temp);
lcd.setCursor(18, 2);
lcd.print(roundedSensor0Temp);
}
} else {
Serial.print("[HTTP] Fehler beim Abrufen der EMA-Antwort: ");
Serial.println(httpCode1);
}
http.end(); // Close EMA HTTP request
} else {
Serial.println("[HTTP] Verbindung zu EMA fehlgeschlagen");
}
}
} else {
Serial.println("[HTTP] Verbindung zum Solar Manager fehlgeschlagen");
}
delay(10000);
}
}