diff --git a/src/config/settings.h b/src/config/settings.h index 2b653fb9..e54dce4d 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -313,14 +313,15 @@ typedef struct { unsigned long lastRefresh; uint16_t wait; + bool battSwitchInit; bool battSwitch; // PID controller float eSum; float eOld; - float Kp; - float Ki; - float Kd; + uint8_t Kp; + uint8_t Ki; + uint8_t Kd; float y; } zeroExportGroup_t; @@ -704,7 +705,7 @@ class settings { mCfg.plugin.zeroExport.groups[group].minimum = true; mCfg.plugin.zeroExport.groups[group].powerTolerance = 10; mCfg.plugin.zeroExport.groups[group].powerMax = 600; - mCfg.plugin.zeroExport.groups[group].Kp = -1; + mCfg.plugin.zeroExport.groups[group].Kp = 50; mCfg.plugin.zeroExport.groups[group].Ki = 0; mCfg.plugin.zeroExport.groups[group].Kd = 0; // @@ -716,6 +717,7 @@ class settings { // mCfg.plugin.zeroExport.groups[group].pm_P2 = 0; // mCfg.plugin.zeroExport.groups[group].pm_P3 = 0; + mCfg.plugin.zeroExport.groups[group].battSwitchInit = false; mCfg.plugin.zeroExport.groups[group].battSwitch = false; mCfg.plugin.zeroExport.groups[group].power = 0; } @@ -1102,11 +1104,11 @@ class settings { if (obj.containsKey(F("powerMax"))) getVal(obj, F("powerMax"), &mCfg.plugin.zeroExport.groups[group].powerMax); if (obj.containsKey(F("Kp"))) - getVal(obj, F("Kp"), &mCfg.plugin.zeroExport.groups[group].Kp); + getVal(obj, F("Kp"), &mCfg.plugin.zeroExport.groups[group].Kp); if (obj.containsKey(F("Ki"))) - getVal(obj, F("Ki"), &mCfg.plugin.zeroExport.groups[group].Ki); + getVal(obj, F("Ki"), &mCfg.plugin.zeroExport.groups[group].Ki); if (obj.containsKey(F("Kd"))) - getVal(obj, F("Kd"), &mCfg.plugin.zeroExport.groups[group].Kd); + getVal(obj, F("Kd"), &mCfg.plugin.zeroExport.groups[group].Kd); } } diff --git a/src/defines.h b/src/defines.h index 308ff3f2..c68bc63a 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 1030019 +#define VERSION_PATCH 1030020 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/platformio.ini b/src/platformio.ini index 4b124944..9d25a742 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -23,9 +23,10 @@ extra_scripts = pre:../scripts/convertHtml.py pre:../scripts/applyPatches.py pre:../scripts/reduceGxEPD2.py + ;;post:../scripts/add_littlefs_binary.py lib_deps = - https://github.com/esphome/ESPAsyncWebServer @ ^3.2.0 + https://github.com/esphome/ESPAsyncWebServer @ ^3.2.2 https://github.com/nRF24/RF24.git#v1.4.8 paulstoffregen/Time @ ^1.6.1 https://github.com/bertmelis/espMqttClient#v1.7.0 @@ -40,6 +41,8 @@ build_flags = build_unflags = -std=gnu++11 + + [env:esp8266-minimal] platform = espressif8266 board = esp12e @@ -146,11 +149,13 @@ build_flags = ${env.build_flags} monitor_filters = esp8266_exception_decoder + + [env:esp32-wroom32-minimal] platform = espressif32@6.6.0 board = lolin_d32 build_flags = ${env.build_flags} - -DUSE_HSPI_FOR_EPD + ;;-DSPI_HAL monitor_filters = esp32_exception_decoder @@ -158,10 +163,10 @@ monitor_filters = platform = espressif32@6.6.0 board = lolin_d32 build_flags = ${env:esp32-wroom32-minimal.build_flags} + -DUSE_HSPI_FOR_EPD -DENABLE_MQTT -DPLUGIN_DISPLAY -DENABLE_HISTORY - -DPLUGIN_ZEROEXPORT monitor_filters = esp32_exception_decoder @@ -199,7 +204,7 @@ build_flags = ${env:esp32-wroom32.build_flags} -DDEF_ETH_MISO_PIN=12 -DDEF_ETH_MOSI_PIN=13 -DDEF_ETH_IRQ_PIN=4 - -DDEF_ETH_RST_PIN=2 + -DDEF_ETH_RST_PIN=255 -DDEF_NRF_CS_PIN=5 -DDEF_NRF_CE_PIN=17 -DDEF_NRF_IRQ_PIN=16 @@ -217,15 +222,17 @@ build_flags = ${env:esp32-wroom32-ethernet.build_flags} monitor_filters = esp32_exception_decoder + + [env:esp32-s2-mini] platform = espressif32@6.6.0 board = lolin_s2_mini build_flags = ${env.build_flags} -DUSE_HSPI_FOR_EPD + ;;-DSPI_HAL -DENABLE_MQTT -DPLUGIN_DISPLAY -DENABLE_HISTORY - -DPLUGIN_ZEROEXPORT -DDEF_NRF_CS_PIN=12 -DDEF_NRF_CE_PIN=3 -DDEF_NRF_IRQ_PIN=5 @@ -248,15 +255,17 @@ build_flags = ${env:esp32-s2-mini.build_flags} monitor_filters = esp32_exception_decoder + + [env:esp32-c3-mini] platform = espressif32@6.6.0 board = lolin_c3_mini build_flags = ${env.build_flags} -DUSE_HSPI_FOR_EPD + ;;-DSPI_HAL -DENABLE_MQTT -DPLUGIN_DISPLAY -DENABLE_HISTORY - -DPLUGIN_ZEROEXPORT -DDEF_NRF_CS_PIN=5 -DDEF_NRF_CE_PIN=0 -DDEF_NRF_IRQ_PIN=1 @@ -279,6 +288,8 @@ build_flags = ${env:esp32-c3-mini.build_flags} monitor_filters = esp32_exception_decoder + + [env:opendtufusion-minimal] platform = espressif32@6.6.0 board = esp32-s3-devkitc-1 @@ -349,7 +360,6 @@ build_flags = ${env:opendtufusion-minimal.build_flags} -DENABLE_MQTT -DPLUGIN_DISPLAY -DENABLE_HISTORY - -DPLUGIN_ZEROEXPORT -DDEF_ETH_CS_PIN=42 -DDEF_ETH_SCK_PIN=39 -DDEF_ETH_MISO_PIN=41 @@ -368,3 +378,19 @@ build_flags = ${env:opendtufusion-ethernet.build_flags} -DLANG_DE monitor_filters = esp32_exception_decoder, colorize + +[env:opendtufusion-ethernet-zero_export] +platform = espressif32@6.6.0 +board = esp32-s3-devkitc-1 +upload_protocol = esp-builtin +build_flags = ${env:opendtufusion-ethernet.build_flags} + -DPLUGIN_ZEROEXPORT +monitor_filters = + esp32_exception_decoder, colorize + +[env:opendtufusion-ethernet-zero_export-de] +platform = espressif32@6.6.0 +board = esp32-s3-devkitc-1 +upload_protocol = esp-builtin +build_flags = ${env:opendtufusion-ethernet-zero_export.build_flags} + -DLANG_DE diff --git a/src/plugins/zeroExport/powermeter.h b/src/plugins/zeroExport/powermeter.h index 4cf6f5d9..d590aae1 100644 --- a/src/plugins/zeroExport/powermeter.h +++ b/src/plugins/zeroExport/powermeter.h @@ -294,7 +294,7 @@ class powermeter { /** setHeader * */ - void setHeader(HTTPClient *h, String auth = "", u8_t realm = NULL) { + void setHeader(HTTPClient *h, String auth = "", u8_t realm = 0) { h->setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); /// h->setUserAgent("Ahoy-Agent"); /// // TODO: Ahoy-0.8.850024-zero diff --git a/src/plugins/zeroExport/zeroExport.h b/src/plugins/zeroExport/zeroExport.h index 572c07e9..160da4a2 100644 --- a/src/plugins/zeroExport/zeroExport.h +++ b/src/plugins/zeroExport/zeroExport.h @@ -24,7 +24,7 @@ class ZeroExport { /** ZeroExport * constructor */ - ZeroExport() {} + ZeroExport() { } /** ~ZeroExport * destructor @@ -91,6 +91,31 @@ class ZeroExport { zeroExportGroup_t *CfgGroup = &mCfg->groups[group]; zeroExportGroupInverter_t *CfgGroupInv = &CfgGroup->inverters[inv]; Inverter<> *iv = mSys->getInverterByPos(Queue.id); + if(NULL == iv) return; + + if(!CfgGroup->battSwitch && !CfgGroup->battSwitchInit) + { + if(!iv->alarmCnt) return; + bool stb_flag = false; + + for(int16_t i = 0; i < iv->alarmCnt; i++) { + if(iv->lastAlarm[i].code == 124) { + stb_flag = true; + _log.addProperty("alarm1", stb_flag); + _log.addProperty("start", iv->lastAlarm[i].start ); + _log.addProperty("end", iv->lastAlarm[i].end ); + + if (iv->lastAlarm[i].end > iv->lastAlarm[i].start) { + stb_flag = false; + _log.addProperty("alarm2", stb_flag); + } + sendLog(); + clearLog(); + } + } + if(!stb_flag) CfgGroup->battSwitch = true; + CfgGroup->battSwitchInit = true; + } _log.addProperty("g", group); _log.addProperty("i", inv); @@ -115,7 +140,7 @@ class ZeroExport { return; } - + // Wird nur zum debuggen benötigt? uint16_t groupPower = 0; uint16_t groupLimit = 0; for (uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) { @@ -125,6 +150,8 @@ class ZeroExport { _log.addProperty("gP", groupPower); _log.addProperty("gL", groupLimit); + // Wird nur zum debuggen benötigt? + // Batteryprotection _log.addProperty("bEn", (uint8_t)CfgGroup->battCfg); @@ -145,10 +172,10 @@ class ZeroExport { CfgGroup->battSwitch = true; _log.addProperty("bA", "turn on"); } - if ((CfgGroup->battValue > CfgGroup->battLimitOff) && (CfgGroupInv->power > 0)) { - CfgGroup->battSwitch = true; - _log.addProperty("bA", "turn on"); - } + //if ((CfgGroup->battValue > CfgGroup->battLimitOff) && (CfgGroupInv->power > 0)) { + // CfgGroup->battSwitch = true; + // _log.addProperty("bA", "turn on"); + //} } else { if (CfgGroup->battValue < CfgGroup->battLimitOff) { CfgGroup->battSwitch = false; @@ -195,9 +222,9 @@ class ZeroExport { } // Regler - float Kp = CfgGroup->Kp; - float Ki = CfgGroup->Ki; - float Kd = CfgGroup->Kd; + float Kp = CfgGroup->Kp * -0.01; + float Ki = CfgGroup->Ki * -0.001; + float Kd = CfgGroup->Kd * -0.001; unsigned long Ta = Tsp - CfgGroup->lastRefresh; CfgGroup->lastRefresh = Tsp; int16_t yP = Kp * e; diff --git a/src/utils/DynamicJsonHandler.h b/src/utils/DynamicJsonHandler.h index 4c7a7476..74a39e7d 100644 --- a/src/utils/DynamicJsonHandler.h +++ b/src/utils/DynamicJsonHandler.h @@ -1,6 +1,13 @@ //----------------------------------------------------------------------------- -// 2022 Ahoy, https://github.com/lumpapu/ahoy +// 2024 Ahoy, https://github.com/lumpapu/ahoy // Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// +// The DynamicJsonHandler class is a helper class designed to facilitate the handling of JSON documents on embedded systems such as the ESP32. +// It uses the ArduinoJson library to dynamically manage JSON data and provides functionality for adding properties, +// serializing the document, and managing storage. +// +// Written from tictrick & DanielR92 +// //----------------------------------------------------------------------------- #ifndef __DYNAMICJSONHANDLER_H__ @@ -9,6 +16,7 @@ #include #include #include +#include "config/settings.h" // needed for MAX_ALLOWED_BUF_SIZE class DynamicJsonHandler { public: @@ -24,8 +32,8 @@ public: private: DynamicJsonDocument doc; - static const size_t min_size = 256; - static const size_t max_size = 5000; // Max RAM : 2 = da es für resizeDocument eng werden könnte? + const size_t min_size = 256; + const size_t max_size = MAX_ALLOWED_BUF_SIZE / 2; // Max RAM : 2 = da es für resizeDocument eng werden könnte? void resizeDocument(size_t requiredSize); size_t min(size_t a, size_t b); diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 3dd96d94..37749779 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -866,12 +866,12 @@ class RestApi { // Advanced objGroup[F("setPoint")] = (int16_t)mConfig->plugin.zeroExport.groups[group].setPoint; objGroup[F("minimum")] = (bool)mConfig->plugin.zeroExport.groups[group].minimum; - objGroup[F("power")] = (int32_t)mConfig->plugin.zeroExport.groups[group].power; + objGroup[F("power")] = (float)mConfig->plugin.zeroExport.groups[group].power; objGroup[F("powerTolerance")] = (uint8_t)mConfig->plugin.zeroExport.groups[group].powerTolerance; objGroup[F("powerMax")] = (uint16_t)mConfig->plugin.zeroExport.groups[group].powerMax; - objGroup[F("Kp")] = ah::round3((float)mConfig->plugin.zeroExport.groups[group].Kp); - objGroup[F("Ki")] = ah::round3((float)mConfig->plugin.zeroExport.groups[group].Ki); - objGroup[F("Kd")] = ah::round3((float)mConfig->plugin.zeroExport.groups[group].Kd); + objGroup[F("Kp")] = (uint8_t)mConfig->plugin.zeroExport.groups[group].Kp; + objGroup[F("Ki")] = (uint8_t)mConfig->plugin.zeroExport.groups[group].Ki; + objGroup[F("Kd")] = (uint8_t)mConfig->plugin.zeroExport.groups[group].Kd; } } #endif @@ -1146,8 +1146,8 @@ class RestApi { // Plugin ZeroExport #if defined(PLUGIN_ZEROEXPORT) else if(F("ze_batt_onff") == jsonIn[F("cmd")]) { - uint8_t group = jsonIn[F("id")]; - mConfig->plugin.zeroExport.groups[group].battSwitch = (bool)jsonIn[F("battSwitch")]; + uint8_t group = (uint8_t)jsonIn[F("id")]; + mConfig->plugin.zeroExport.groups[group].battSwitch = (bool)jsonIn[F("val")]; } else if(F("ze_save_group") == jsonIn[F("cmd")]) { // General diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 4d6ba40f..2d625d4f 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -1290,29 +1290,21 @@ /*IF_PLUGIN_ZEROEXPORT*/ function apiCbBattOnOff(obj) { -// var e = document.getElementById("battSwitch"); -// e.value = "88"; -// selDelAllOpt(e); -// if(obj["success"]) -// e.appendChild(opt("-1", "{#NETWORK_SCANNING}")) -// else -// e.appendChild(opt("-1", "{#ERROR} " + obj["error"])); + var e = document.getElementById("battSwitch"); + if(obj["success"]) { + // dann über ajax denn gesetzten wert zurück aus dem system holen + modalClose(); + getAjax("/api/setup", parse); + } + else + e.innerHTML = "{#ERROR}" + obj["error"]; + } function battOnOff() { - // TODO: zuerst wert setzen - // dann über ajax denn gesetzten wert zurück aus dem system holen - // damit man sieht das es erfolgreich gesetzt worden ist. const sw = document.getElementById("battSwitch"); - if (sw.value == 0) { - sw.value = 1; - sw.innerHTML = "{#BTN_ON}"; - } else { - sw.value = 0; - sw.innerHTML = "{#BTN_OFF}"; - } - - var obj = {cmd: "ze_batt_onff", token: "*"} + if(sw == null) return; + var obj = {cmd: "ze_batt_onff", token: "*", id: parseInt(sw.dataset.group), val: (sw.dataset.status === "true") ? false : true} getAjax("/api/setup", apiCbBattOnOff, "POST", JSON.stringify(obj)); } @@ -1442,7 +1434,7 @@ divRow("{#ZE_GROUP_TAB_BATTERY_TOPIC}", ml("input", {name: "battTopic", class: "text", type: "text", value: obj.battTopic}, null),), divRow("{#ZE_GROUP_TAB_BATTERY_LIMITON}", ml("input", {name: "battLimitOn", class: "text", type: "number", min: "0", max: "100", step: "0.1", value: obj.battLimitOn}, null),), divRow("{#ZE_GROUP_TAB_BATTERY_LIMITOFF}", ml("input", {name: "battLimitOff", class: "text", type: "number", min: "0", max: "100", step: "0.1", value: obj.battLimitOff}, null),), - divRow("{#ZE_GROUP_TAB_BATTERY_ONOFF}", ml("input", {name: "battSwitch", id: "battSwitch", class: "btn", type: "button", value: obj.battSwitch}, null)), + divRow("{#ZE_GROUP_TAB_BATTERY_ONOFF}", ml("input", {name: "battSwitch", id: "battSwitch", "data-group": String(obj.id), "data-status": String(obj.battSwitch), class: "btn", type: "button", value: (obj.battSwitch ? "{#BTN_ON}" : "{#BTN_OFF}")}, null)), // TODO: Uebersetzen mit lang.json und auf die entsprechende Dokuseite verlinken divRow("Hinweis: ", ml("a", {href: "https://docs.ahoydtu.de/de/latest/zeroExport.html"}, "Bitte beachten Sie die Ausfüllhinweise in der Dokumentation."),), // TODO: Hinweis Github/Discord - Entfernen wenn erledigt @@ -1454,9 +1446,9 @@ divRow("{#ZE_GROUP_TAB_ADVANCED_MINIMUM}", cb_minimum), divRow("{#ZE_GROUP_TAB_ADVANCED_POWERTOLERANCE}", ml("input", {name: "powerTolerance", class: "text", type: "number", min: "0", max: "255", value: obj.powerTolerance}, null)), divRow("{#ZE_GROUP_TAB_ADVANCED_POWERMAX}", ml("input", {name: "powerMax", class: "text", type: "number", min: "0", max: "65535", value: obj.powerMax}, null)), - divRow("{#ZE_GROUP_TAB_ADVANCED_KP}", ml("input", {name: "Kp", class: "text", type: "number", min: "-1", max: "0", step: "0.001", value: obj.Kp}, null)), - divRow("{#ZE_GROUP_TAB_ADVANCED_KI}", ml("input", {name: "Ki", class: "text", type: "number", min: "-0.01", max: "0", step: "0.001", value: obj.Ki}, null)), - divRow("{#ZE_GROUP_TAB_ADVANCED_KD}", ml("input", {name: "Kd", class: "text", type: "number", min: "-0.01", max: "0", step: "0.001", value: obj.Kd}, null)), + divRow("{#ZE_GROUP_TAB_ADVANCED_KP}", ml("input", {name: "Kp", class: "text", type: "number", min: "0", max: "100", step: "1", value: obj.Kp}, null)), + divRow("{#ZE_GROUP_TAB_ADVANCED_KI}", ml("input", {name: "Ki", class: "text", type: "number", min: "0", max: "100", step: "1", value: obj.Ki}, null)), + divRow("{#ZE_GROUP_TAB_ADVANCED_KD}", ml("input", {name: "Kd", class: "text", type: "number", min: "0", max: "100", step: "1", value: obj.Kd}, null)), // TODO: Uebersetzen mit lang.json und auf die entsprechende Dokuseite verlinken divRow("Hinweis: ", ml("a", {href: "https://docs.ahoydtu.de/de/latest/zeroExport.html"}, "Bitte beachten Sie die Ausfüllhinweise in der Dokumentation."),), // TODO: Hinweis Github/Discord - Entfernen wenn erledigt @@ -1734,7 +1726,7 @@ o.power = 0; o.powerTolerance = 10; o.powerMax = 600; - o.Kp = -1; + o.Kp = 50; o.Ki = 0; o.Kd = 0; // Global