From fb55ccdfe0d4784c0cf407136600d331a3859af9 Mon Sep 17 00:00:00 2001 From: Carsten Schmiemann Date: Mon, 7 Nov 2022 03:54:48 +0100 Subject: [PATCH] Migrate to WifiManager and modular config --- src/main.cpp | 294 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 248 insertions(+), 46 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 82fbcf6..6be9d1f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,8 +24,14 @@ */ #include #include -//#include -ESP32 -#include +#ifdef ESP32 + #include + #include +#endif +#ifdef ESP8266 + #include + #include +#endif #include #include #include @@ -40,15 +46,49 @@ #include #define VERSION "0.1a" -static const unsigned long DISPLAY_REFRESH_INTERVAL = 500; // ms -static const unsigned long DISPLAY_SCREEN_INTERVAL = 10000; // ms -//MQTT -const char* mqtt_server = "10.1.0.9"; -WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40); +//Defaults +char mqtt_server[15] = "10.3.4.5"; +char gx_vrm_id[20] = "123456789a"; +char disp_refresh_interval[6] = "500"; +char disp_screen_interval[6] = "10000"; +char address_pv_charger[6] = "0"; +char address_grid_meter[6] = "0"; +char address_inverter[6] = "0"; +char address_battery[6] = "0"; +char address_outside_temperature[6] = "0"; +long unsigned int DISPLAY_REFRESH_INTERVAL; +long unsigned int DISPLAY_SCREEN_INTERVAL; + +//MQTT connect strings +char mqtt_pv_voltage[80]; +char mqtt_pv_power[80]; +char mqtt_pv_yield[80]; +char mqtt_pv_bat_current[80]; +char mqtt_grid_power[80]; +char mqtt_inv_power[80]; +char mqtt_inv_current[80]; +char mqtt_bat_soc[80]; +char mqtt_bat_voltage[80]; +char mqtt_bat_current[80]; +char mqtt_bat_power[80]; +char mqtt_bat_max_cell_volt[80]; +char mqtt_bat_min_cell_volt[80]; +char mqtt_temp_outside[80]; +char mqtt_grid_power_l1[80]; +char mqtt_grid_power_l2[80]; +char mqtt_grid_power_l3[80]; + +//WiFiManager flag for saving data +bool shouldSaveConfig = false; + +//WiFiManager callback notifying us of the need to save config +void saveConfigCallback () { + Serial.println("Should save config"); + shouldSaveConfig = true; +} //Library setup -WiFiManager wifiManager; WiFiClient espClient; PubSubClient client(espClient); @@ -75,108 +115,108 @@ void callback(char* topic, byte* message, unsigned int length) { logPrintlnD(messageTemp); //PV Charger - solar voltage - if (String(topic) == "N/48e7da87c8df/solarcharger/279/Pv/V") { + if (String(topic) == mqtt_pv_voltage) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); pv_v = json["value"]; } //PV Charger - solar power - if (String(topic) == "N/48e7da87c8df/solarcharger/279/Yield/Power") { + if (String(topic) == mqtt_pv_power) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); pv_w = json["value"]; } //PV Charger - solar yield - if (String(topic) == "N/48e7da87c8df/solarcharger/279/History/Daily/0/Yield") { + if (String(topic) == mqtt_pv_yield) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); pv_kwh = json["value"]; } //PV Charger - bat charge current - if (String(topic) == "N/48e7da87c8df/solarcharger/279/Dc/0/Current") { + if (String(topic) == mqtt_pv_bat_current) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); pv_i = json["value"]; } //Grid meter - power - if (String(topic) == "N/48e7da87c8df/grid/40/Ac/Power") { + if (String(topic) == mqtt_grid_power) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); grid_p = json["value"]; } //Inverter - power - if (String(topic) == "N/48e7da87c8df/vebus/276/Ac/ActiveIn/L1/P") { + if (String(topic) == mqtt_inv_power) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); inv_p = json["value"]; } //Inverter - current - if (String(topic) == "N/48e7da87c8df/vebus/276/Dc/0/Current") { + if (String(topic) == mqtt_inv_current) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); inv_i = json["value"]; } //Battery - SOC - if (String(topic) == "N/48e7da87c8df/battery/512/Soc") { + if (String(topic) == mqtt_bat_soc) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); batt_soc = json["value"]; } //Battery - voltage - if (String(topic) == "N/48e7da87c8df/battery/512/Dc/0/Voltage") { + if (String(topic) == mqtt_bat_voltage) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); batt_v = json["value"]; } //Battery - current - if (String(topic) == "N/48e7da87c8df/battery/512/Dc/0/Current") { + if (String(topic) == mqtt_bat_current) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); batt_i = json["value"]; } //Battery - power - if (String(topic) == "N/48e7da87c8df/battery/512/Dc/0/Power") { + if (String(topic) == mqtt_bat_power) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); batt_p = json["value"]; } //Battery - max cell volts - if (String(topic) == "N/48e7da87c8df/battery/512/System/MaxCellVoltage") { + if (String(topic) == mqtt_bat_max_cell_volt) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); batt_c_max = json["value"]; } //Battery - min cell volts - if (String(topic) == "N/48e7da87c8df/battery/512/System/MinCellVoltage") { + if (String(topic) == mqtt_bat_min_cell_volt) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); batt_c_min = json["value"]; } //Temperature - outside - if (String(topic) == "N/48e7da87c8df/temperature/18/Temperature") { + if (String(topic) == mqtt_temp_outside) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); temp_outside = json["value"]; } //System - AC Load Phase 1 - if (String(topic) == "N/48e7da87c8df/system/0/Ac/ConsumptionOnInput/L1/Power") { + if (String(topic) == mqtt_grid_power_l1) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); load_ph1 = json["value"]; } //System - AC Load Phase 2 - if (String(topic) == "N/48e7da87c8df/system/0/Ac/ConsumptionOnInput/L2/Power") { + if (String(topic) == mqtt_grid_power_l2) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); load_ph2 = json["value"]; } //System - AC Load Phase 3 - if (String(topic) == "N/48e7da87c8df/system/0/Ac/ConsumptionOnInput/L3/Power") { + if (String(topic) == mqtt_grid_power_l3) { DynamicJsonDocument json(512); deserializeJson(json, messageTemp); load_ph3 = json["value"]; @@ -194,23 +234,24 @@ void reconnect() { if (client.connect("PV_solar_monitor")) { logPrintlnI("connected"); // Subscribe - client.subscribe("N/48e7da87c8df/solarcharger/279/Pv/V"); - client.subscribe("N/48e7da87c8df/solarcharger/279/Yield/Power"); - client.subscribe("N/48e7da87c8df/solarcharger/279/History/Daily/0/Yield"); - client.subscribe("N/48e7da87c8df/solarcharger/279/Dc/0/Current"); - client.subscribe("N/48e7da87c8df/grid/40/Ac/Power"); - client.subscribe("N/48e7da87c8df/vebus/276/Ac/ActiveIn/L1/P"); - client.subscribe("N/48e7da87c8df/vebus/276/Dc/0/Current"); - client.subscribe("N/48e7da87c8df/battery/512/Soc"); - client.subscribe("N/48e7da87c8df/battery/512/Dc/0/Voltage"); - client.subscribe("N/48e7da87c8df/battery/512/Dc/0/Current"); - client.subscribe("N/48e7da87c8df/battery/512/Dc/0/Power"); - client.subscribe("N/48e7da87c8df/battery/512/System/MaxCellVoltage"); - client.subscribe("N/48e7da87c8df/battery/512/System/MinCellVoltage"); - client.subscribe("N/48e7da87c8df/temperature/18/Temperature"); - client.subscribe("N/48e7da87c8df/system/0/Ac/ConsumptionOnInput/L1/Power"); - client.subscribe("N/48e7da87c8df/system/0/Ac/ConsumptionOnInput/L2/Power"); - client.subscribe("N/48e7da87c8df/system/0/Ac/ConsumptionOnInput/L3/Power"); + client.subscribe(mqtt_pv_voltage); + client.subscribe(mqtt_pv_power); + client.subscribe(mqtt_pv_yield); + client.subscribe(mqtt_pv_bat_current); + client.subscribe(mqtt_grid_power); + client.subscribe(mqtt_inv_power); + client.subscribe(mqtt_inv_current); + client.subscribe(mqtt_bat_soc); + client.subscribe(mqtt_bat_voltage); + client.subscribe(mqtt_bat_current); + client.subscribe(mqtt_bat_power); + client.subscribe(mqtt_bat_max_cell_volt); + client.subscribe(mqtt_bat_min_cell_volt); + client.subscribe(mqtt_temp_outside); + client.subscribe(mqtt_grid_power_l1); + client.subscribe(mqtt_grid_power_l2); + client.subscribe(mqtt_grid_power_l3); + logPrintlnI("subscribed to topics"); } else { logPrintlnE("failed, rc="); logPrintlnE((char*)client.state()); @@ -227,20 +268,181 @@ void setup() { display_begin(); Serial.println("Display init..."); display_init((char*)VERSION); + + //read configuration from FS json + Serial.println("mounting FS..."); + + if (SPIFFS.begin()) { + Serial.println("mounted file system"); + if (SPIFFS.exists("/config.json")) { + //file exists, reading and loading + Serial.println("reading config file"); + File configFile = SPIFFS.open("/config.json", "r"); + if (configFile) { + Serial.println("opened config file"); + size_t size = configFile.size(); + // Allocate a buffer to store contents of the file. + std::unique_ptr buf(new char[size]); + + configFile.readBytes(buf.get(), size); + + #if defined(ARDUINOJSON_VERSION_MAJOR) && ARDUINOJSON_VERSION_MAJOR >= 6 + DynamicJsonDocument json(1024); + auto deserializeError = deserializeJson(json, buf.get()); + serializeJson(json, Serial); + if ( ! deserializeError ) { + #else + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.parseObject(buf.get()); + json.printTo(Serial); + if (json.success()) { + #endif + Serial.println("\nparsed json"); + strcpy(mqtt_server, json["mqtt_server"]); + strcpy(gx_vrm_id, json["gx_vrm_id"]); + strcpy(disp_refresh_interval, json["disp_refresh_interval"]); + strcpy(disp_screen_interval, json["disp_screen_interval"]); + strcpy(address_pv_charger, json["address_pv_charger"]); + strcpy(address_grid_meter, json["address_grid_meter"]); + strcpy(address_inverter, json["address_inverter"]); + strcpy(address_battery, json["address_battery"]); + strcpy(address_outside_temperature, json["address_outside_temperature"]); + } else { + Serial.println("failed to load json config"); + } + configFile.close(); + } + } + } else { + Serial.println("failed to mount FS"); + } + delay(2000); logPrintlnI("Booting solar monitor app..." VERSION); display_wifi((char*)"AP: PV_Mon for Config"); - wifiManager.addParameter(&custom_mqtt_server); - wifiManager.setTimeout(60); - wifiManager.autoConnect("PV_Mon"); + //Wifi Manager parameters + WiFiManagerParameter custom_mqtt_server("mqtt_server", "IP adress of GX Device (MQTT No SSL)", mqtt_server, 15); + WiFiManagerParameter custom_gx_vrm_id("gx_vrm_id", "VRM ID of GX device", gx_vrm_id, 20); + WiFiManagerParameter custom_disp_refresh_interval("disp_refresh_interval", "Refresh cycle of display in ms", disp_refresh_interval, 6); + WiFiManagerParameter custom_disp_screen_interval("disp_screen_interval", "Rotation time of screens in ms", disp_screen_interval, 6); + WiFiManagerParameter custom_address_pv_charger("address_pv_charger", "Address of pv charger", address_pv_charger, 6); + WiFiManagerParameter custom_address_grid_meter("address_grid_meter", "Address of grid meter", address_grid_meter, 6); + WiFiManagerParameter custom_address_inverter("address_inverter", "Address of vebus inverter", address_inverter, 6); + WiFiManagerParameter custom_address_battery("address_battery", "Address of can battery", address_battery, 6); + WiFiManagerParameter custom_address_outside_temperature("address_outside_temperature", "Address of outside temperature", address_outside_temperature, 6); + WiFiManager wm; + + wm.setSaveConfigCallback(saveConfigCallback); + wm.addParameter(&custom_mqtt_server); + wm.addParameter(&custom_gx_vrm_id); + wm.addParameter(&custom_disp_refresh_interval); + wm.addParameter(&custom_disp_screen_interval); + wm.addParameter(&custom_address_pv_charger); + wm.addParameter(&custom_address_grid_meter); + wm.addParameter(&custom_address_inverter); + wm.addParameter(&custom_address_battery); + wm.addParameter(&custom_address_outside_temperature); + wm.setTimeout(60); + + wm.autoConnect("PV_Mon"); logPrintlnI("Connecting wifi..."); IPAddress ip = WiFi.localIP(); + strcpy(mqtt_server, custom_mqtt_server.getValue()); + strcpy(gx_vrm_id, custom_gx_vrm_id.getValue()); + strcpy(disp_refresh_interval, custom_disp_refresh_interval.getValue()); + strcpy(disp_screen_interval, custom_disp_screen_interval.getValue()); + strcpy(address_pv_charger, custom_address_pv_charger.getValue()); + strcpy(address_grid_meter, custom_address_grid_meter.getValue()); + strcpy(address_inverter, custom_address_inverter.getValue()); + strcpy(address_battery, custom_address_battery.getValue()); + strcpy(address_outside_temperature, custom_address_outside_temperature.getValue()); + + DISPLAY_REFRESH_INTERVAL = strtol(disp_refresh_interval, NULL, 10); + DISPLAY_SCREEN_INTERVAL = strtol(disp_screen_interval, NULL, 10); + client.setServer(mqtt_server, 1883); client.setCallback(callback); char* ip_address = new char[40](); sprintf(ip_address, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); display_wifi(ip_address); - delay(2000); + //save the custom parameters to FS + if (shouldSaveConfig) { + Serial.println("saving config"); + #if defined(ARDUINOJSON_VERSION_MAJOR) && ARDUINOJSON_VERSION_MAJOR >= 6 + DynamicJsonDocument json(1024); + #else + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + #endif + json["mqtt_server"] = mqtt_server; + json["gx_vrm_id"] = gx_vrm_id; + json["disp_refresh_interval"] = disp_refresh_interval; + json["disp_screen_interval"] = disp_screen_interval; + json["address_pv_charger"] = address_pv_charger; + json["address_grid_meter"] = address_grid_meter; + json["address_inverter"] = address_inverter; + json["address_battery"] = address_battery; + json["address_outside_temperature"] = address_outside_temperature; + + File configFile = SPIFFS.open("/config.json", "w"); + if (!configFile) { + Serial.println("failed to open config file for writing"); + } + + #if defined(ARDUINOJSON_VERSION_MAJOR) && ARDUINOJSON_VERSION_MAJOR >= 6 + serializeJson(json, Serial); + serializeJson(json, configFile); + #else + json.printTo(Serial); + json.printTo(configFile); + #endif + configFile.close(); + //end save + } + //Generate mqtt topics from id and address + Serial.println(); + Serial.println("-------------- MQTT topic list --------------"); + sprintf(mqtt_pv_voltage, "N/%s/solarcharger/%s/Pv/V", gx_vrm_id, address_pv_charger); + Serial.println(mqtt_pv_voltage); + sprintf(mqtt_pv_power, "N/%s/solarcharger/%s/Yield/Power", gx_vrm_id, address_pv_charger); + Serial.println(mqtt_pv_power); + sprintf(mqtt_pv_yield, "N/%s/solarcharger/%s/History/Daily/0/Yield", gx_vrm_id, address_pv_charger); + Serial.println(mqtt_pv_yield); + sprintf(mqtt_pv_bat_current, "N/%s/solarcharger/%s/Dc/0/Current", gx_vrm_id, address_pv_charger); + Serial.println(mqtt_pv_bat_current); + sprintf(mqtt_grid_power, "N/%s/grid/%s/Ac/Power", gx_vrm_id, address_grid_meter); + Serial.println(mqtt_grid_power); + sprintf(mqtt_inv_power, "N/%s/vebus/%s/Ac/ActiveIn/L1/P", gx_vrm_id, address_inverter); + Serial.println(mqtt_inv_power); + sprintf(mqtt_inv_current, "N/%s/vebus/%s/Dc/0/Current", gx_vrm_id, address_inverter); + Serial.println(mqtt_inv_current); + sprintf(mqtt_bat_soc, "N/%s/battery/%s/Soc", gx_vrm_id, address_battery); + Serial.println(mqtt_bat_soc); + sprintf(mqtt_bat_voltage, "N/%s/battery/%s/Dc/0/Voltage", gx_vrm_id, address_battery); + Serial.println(mqtt_bat_voltage); + sprintf(mqtt_bat_current, "N/%s/battery/%s/Dc/0/Current", gx_vrm_id, address_battery); + Serial.println(mqtt_bat_current); + sprintf(mqtt_bat_power, "N/%s/battery/%s/Dc/0/Power", gx_vrm_id, address_battery); + Serial.println(mqtt_bat_power); + sprintf(mqtt_bat_max_cell_volt, "N/%s/battery/%s/System/MaxCellVoltage", gx_vrm_id, address_battery); + Serial.println(mqtt_bat_max_cell_volt); + sprintf(mqtt_bat_min_cell_volt, "N/%s/battery/%s/System/MinCellVoltage", gx_vrm_id, address_battery); + Serial.println(mqtt_bat_min_cell_volt); + sprintf(mqtt_temp_outside, "N/%s/temperature/%s/Temperature", gx_vrm_id, address_outside_temperature); + Serial.println(mqtt_temp_outside); + sprintf(mqtt_grid_power_l1, "N/%s/system/0/Ac/ConsumptionOnInput/L1/Power", gx_vrm_id); + Serial.println(mqtt_grid_power_l1); + sprintf(mqtt_grid_power_l2, "N/%s/system/0/Ac/ConsumptionOnInput/L2/Power", gx_vrm_id); + Serial.println(mqtt_grid_power_l2); + sprintf(mqtt_grid_power_l3, "N/%s/system/0/Ac/ConsumptionOnInput/L3/Power", gx_vrm_id); + Serial.println(mqtt_grid_power_l3); + Serial.println(); + Serial.println("-------------- Settings --------------"); + Serial.print("mqtt server: "); Serial.println(mqtt_server); + Serial.print("gx_vrm_id: "); Serial.println(gx_vrm_id); + Serial.print("disp_refresh_interval: "); Serial.println(DISPLAY_REFRESH_INTERVAL); + Serial.print("mqtt disp_screen_interval: "); Serial.println(DISPLAY_SCREEN_INTERVAL); + } void loop() {