diff --git a/src/config/settings.h b/src/config/settings.h index bdcd25e0..2b653fb9 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -206,7 +206,7 @@ typedef struct { #define ZEROEXPORT_MAX_QUEUE_ENTRIES 64 #define ZEROEXPORT_MAX_GROUPS 8 #define ZEROEXPORT_GROUP_MAX_LEN_NAME 25 -#define ZEROEXPORT_GROUP_MAX_LEN_PM_URL 100 +#define ZEROEXPORT_GROUP_MAX_LEN_PM_SRC 100 #define ZEROEXPORT_GROUP_MAX_LEN_PM_JSONPATH 100 #define ZEROEXPORT_GROUP_MAX_LEN_PM_USER 25 #define ZEROEXPORT_GROUP_MAX_LEN_PM_PASS 25 @@ -288,7 +288,7 @@ typedef struct { uint8_t pm_refresh; unsigned long pm_peviousTsp; uint8_t pm_type; - char pm_url[ZEROEXPORT_GROUP_MAX_LEN_PM_URL]; + char pm_src[ZEROEXPORT_GROUP_MAX_LEN_PM_SRC]; char pm_jsonPath[ZEROEXPORT_GROUP_MAX_LEN_PM_JSONPATH]; char pm_user[ZEROEXPORT_GROUP_MAX_LEN_PM_USER]; char pm_pass[ZEROEXPORT_GROUP_MAX_LEN_PM_PASS]; @@ -674,7 +674,7 @@ class settings { mCfg.plugin.zeroExport.groups[group].pm_refresh = 5; mCfg.plugin.zeroExport.groups[group].pm_peviousTsp = 0; mCfg.plugin.zeroExport.groups[group].pm_type = zeroExportPowermeterType_t::None; - snprintf(mCfg.plugin.zeroExport.groups[group].pm_url, ZEROEXPORT_GROUP_MAX_LEN_PM_URL, "%s", DEF_ZEXPORT); + snprintf(mCfg.plugin.zeroExport.groups[group].pm_src, ZEROEXPORT_GROUP_MAX_LEN_PM_SRC, "%s", DEF_ZEXPORT); snprintf(mCfg.plugin.zeroExport.groups[group].pm_jsonPath, ZEROEXPORT_GROUP_MAX_LEN_PM_JSONPATH, "%s", DEF_ZEXPORT); snprintf(mCfg.plugin.zeroExport.groups[group].pm_user, ZEROEXPORT_GROUP_MAX_LEN_PM_USER, "%s", DEF_ZEXPORT); snprintf(mCfg.plugin.zeroExport.groups[group].pm_pass, ZEROEXPORT_GROUP_MAX_LEN_PM_PASS, "%s", DEF_ZEXPORT); @@ -1033,7 +1033,7 @@ class settings { // Powermeter obj[F("pm_refresh")] = mCfg.plugin.zeroExport.groups[group].pm_refresh; obj[F("pm_type")] = mCfg.plugin.zeroExport.groups[group].pm_type; - obj[F("pm_url")] = mCfg.plugin.zeroExport.groups[group].pm_url; + obj[F("pm_src")] = mCfg.plugin.zeroExport.groups[group].pm_src; obj[F("pm_jsonPath")] = mCfg.plugin.zeroExport.groups[group].pm_jsonPath; obj[F("pm_user")] = mCfg.plugin.zeroExport.groups[group].pm_user; obj[F("pm_pass")] = mCfg.plugin.zeroExport.groups[group].pm_pass; @@ -1067,8 +1067,8 @@ class settings { getVal(obj, F("pm_refresh"), &mCfg.plugin.zeroExport.groups[group].pm_refresh); if (obj.containsKey(F("pm_type"))) getVal(obj, F("pm_type"), &mCfg.plugin.zeroExport.groups[group].pm_type); - if (obj.containsKey(F("pm_url"))) - getChar(obj, F("pm_url"), mCfg.plugin.zeroExport.groups[group].pm_url, ZEROEXPORT_GROUP_MAX_LEN_PM_URL); + if (obj.containsKey(F("pm_src"))) + getChar(obj, F("pm_src"), mCfg.plugin.zeroExport.groups[group].pm_src, ZEROEXPORT_GROUP_MAX_LEN_PM_SRC ); if (obj.containsKey(F("pm_jsonPath"))) getChar(obj, F("pm_jsonPath"), mCfg.plugin.zeroExport.groups[group].pm_jsonPath, ZEROEXPORT_GROUP_MAX_LEN_PM_JSONPATH); if (obj.containsKey(F("pm_user"))) diff --git a/src/defines.h b/src/defines.h index e3415824..253b50b3 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 1030013 +#define VERSION_PATCH 1030016 //------------------------------------- typedef struct { uint8_t ch; diff --git a/src/platformio.ini b/src/platformio.ini index 8d36207c..763ac041 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -40,7 +40,6 @@ build_flags = build_unflags = -std=gnu++11 - [env:esp8266-minimal] platform = espressif8266 board = esp12e @@ -148,7 +147,7 @@ monitor_filters = esp8266_exception_decoder [env:esp32-wroom32-minimal] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_d32 build_flags = ${env.build_flags} -DUSE_HSPI_FOR_EPD @@ -156,7 +155,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_d32 build_flags = ${env:esp32-wroom32-minimal.build_flags} -DENABLE_MQTT @@ -167,7 +166,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-de] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_d32 build_flags = ${env:esp32-wroom32.build_flags} -DLANG_DE @@ -175,7 +174,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-prometheus] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_d32 build_flags = ${env:esp32-wroom32.build_flags} -DENABLE_PROMETHEUS_EP @@ -183,7 +182,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-wroom32-prometheus-de] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_d32 build_flags = ${env:esp32-wroom32-prometheus.build_flags} -DLANG_DE @@ -219,7 +218,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-s2-mini] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_s2_mini build_flags = ${env.build_flags} -DUSE_HSPI_FOR_EPD @@ -242,7 +241,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-s2-mini-de] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_s2_mini build_flags = ${env:esp32-s2-mini.build_flags} -DLANG_DE @@ -250,7 +249,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-c3-mini] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_c3_mini build_flags = ${env.build_flags} -DUSE_HSPI_FOR_EPD @@ -273,7 +272,7 @@ monitor_filters = esp32_exception_decoder [env:esp32-c3-mini-de] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = lolin_c3_mini build_flags = ${env:esp32-c3-mini.build_flags} -DLANG_DE @@ -281,7 +280,7 @@ monitor_filters = esp32_exception_decoder [env:opendtufusion-minimal] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env.build_flags} @@ -306,19 +305,18 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion-minimal.build_flags} -DENABLE_MQTT -DPLUGIN_DISPLAY -DENABLE_HISTORY - -DPLUGIN_ZEROEXPORT monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-de] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion.build_flags} @@ -326,8 +324,24 @@ build_flags = ${env:opendtufusion.build_flags} monitor_filters = esp32_exception_decoder, colorize +[env:opendtufusion-zero_export] +platform = espressif32@6.6.0 +board = esp32-s3-devkitc-1 +upload_protocol = esp-builtin +build_flags = ${env:opendtufusion.build_flags} + -DPLUGIN_ZEROEXPORT +monitor_filters = + esp32_exception_decoder, colorize + +[env:opendtufusion-zero_export-de] +platform = espressif32@6.6.0 +board = esp32-s3-devkitc-1 +upload_protocol = esp-builtin +build_flags = ${env:opendtufusion-zero_export.build_flags} + -DLANG_DE + [env:opendtufusion-ethernet] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion-minimal.build_flags} @@ -347,7 +361,7 @@ monitor_filters = esp32_exception_decoder, colorize [env:opendtufusion-ethernet-de] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 board = esp32-s3-devkitc-1 upload_protocol = esp-builtin build_flags = ${env:opendtufusion-ethernet.build_flags} diff --git a/src/plugins/zeroExport/powermeter.h b/src/plugins/zeroExport/powermeter.h index f6053d8c..eb0e6253 100644 --- a/src/plugins/zeroExport/powermeter.h +++ b/src/plugins/zeroExport/powermeter.h @@ -14,7 +14,6 @@ #include "config/settings.h" #if defined(ZEROEXPORT_POWERMETER_TIBBER) -#include #include #include @@ -47,7 +46,8 @@ class powermeter { * @param *log * @returns void */ - bool setup(zeroExport_t *cfg, PubMqttType *mqtt, JsonObject *log) { + bool setup(IApp *app, zeroExport_t *cfg, PubMqttType *mqtt, JsonObject *log) { + mApp = app; mCfg = cfg; mMqtt = mqtt; mLog = log; @@ -65,15 +65,22 @@ class powermeter { if (millis() - mPreviousTsp <= 1000) return; // skip when it is to fast mPreviousTsp = millis(); + if (mCfg->debug) DBGPRINTLN(F("pm Takt:")); + bool result = false; float power = 0.0; for (u_short group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) { if ((!mCfg->groups[group].enabled) || (mCfg->groups[group].sleep)) continue; - if ((millis() - mCfg->groups[group].pm_peviousTsp) <= ((uint16_t)mCfg->groups[group].pm_refresh * 1000)) continue; + if ((millis() - mCfg->groups[group].pm_peviousTsp) < ((uint16_t)mCfg->groups[group].pm_refresh * 1000)) continue; mCfg->groups[group].pm_peviousTsp = millis(); + if (mCfg->debug) DBGPRINTLN(F("pm Do:")); + + result = false; + power = 0.0; + switch (mCfg->groups[group].pm_type) { #if defined(ZEROEXPORT_POWERMETER_SHELLY) case zeroExportPowermeterType_t::Shelly: @@ -91,9 +98,14 @@ class powermeter { break; #endif #if defined(ZEROEXPORT_POWERMETER_TIBBER) + /* Anscheinend nutzt bei mir Tibber auch diese Freq. + 862.75 MHz - keine Verbindung + 863.00 MHz - geht (standard) jedoch hat Tibber dann Probleme... => 4 & 5 Balken + 863.25 MHz - geht (ohne Tibber Probleme) => 3 & 4 Balken + */ case zeroExportPowermeterType_t::Tibber: + if (mCfg->groups[group].pm_refresh < 3) mCfg->groups[group].pm_refresh = 3; result = getPowermeterWattsTibber(*mLog, group, &power); - mPreviousTsp += 2000; // Zusätzliche Pause break; #endif #if defined(ZEROEXPORT_POWERMETER_SHRDZM) @@ -103,22 +115,14 @@ class powermeter { #endif } + // if (mMqtt->isConnected()) mMqtt->publish(String("zero/state/groups/" + String(group) + "/result").c_str(), String(ret).c_str(), false); + if (result) { bufferWrite(power, group); // MQTT - Powermeter - if (mCfg->debug) { - if (mMqtt->isConnected()) { - // P - mqttObj["Sum"] = ah::round1(power); - // mqttObj["L1"] = ah::round1(power.P1); - // mqttObj["L2"] = ah::round1(power.P2); - // mqttObj["L3"] = ah::round1(power.P3); - mMqtt->publish(String("zero/state/groups/" + String(group) + "/powermeter/P").c_str(), mqttDoc.as().c_str(), false); - mqttDoc.clear(); - - // W (TODO) - } + if (mMqtt->isConnected()) { + mMqtt->publish(String("zero/state/groups/" + String(group) + "/powermeter/P").c_str(), String(ah::round1(power)).c_str(), false); } } } @@ -149,13 +153,33 @@ class powermeter { float min = 0.0; for (int i = 0; i < 5; i++) { - if (i == 0) min = mPowermeterBuffer[group][i]; - if ( min > mPowermeterBuffer[group][i]) min = mPowermeterBuffer[group][i]; + if (i == 0) + min = mPowermeterBuffer[group][i]; + if (min > mPowermeterBuffer[group][i]) + min = mPowermeterBuffer[group][i]; } return min; } + /** getDataMAX + * Holt die Daten vom Powermeter + * @param group + * @returns value + */ + float getDataMAX(uint8_t group) { + float max = 0.0; + + for (int i = 0; i < 5; i++) { + if (i == 0) + max = mPowermeterBuffer[group][i]; + if (max < mPowermeterBuffer[group][i]) + max = mPowermeterBuffer[group][i]; + } + + return max; + } + /** onMqttConnect * */ @@ -163,12 +187,12 @@ class powermeter { #if defined(ZEROEXPORT_POWERMETER_MQTT) for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) { - if (!strcmp(mCfg->groups[group].pm_jsonPath, "")) continue; + if (!strcmp(mCfg->groups[group].pm_src, "")) continue; if (!mCfg->groups[group].enabled) continue; if (mCfg->groups[group].pm_type == zeroExportPowermeterType_t::Mqtt) { - mMqtt->subscribeExtern(String(mCfg->groups[group].pm_jsonPath).c_str(), QOS_2); + mMqtt->subscribeExtern(String(mCfg->groups[group].pm_src).c_str(), QOS_2); } } @@ -176,7 +200,7 @@ class powermeter { } /** onMqttMessage - * + * This function is needed for all mqtt connections between ahoy and other devices. */ void onMqttMessage(JsonObject obj) { String topic = String(obj["topic"]); @@ -188,27 +212,35 @@ class powermeter { if (!mCfg->groups[group].pm_type == zeroExportPowermeterType_t::Mqtt) continue; - if (!strcmp(mCfg->groups[group].pm_jsonPath, "")) continue; + if (!strcmp(mCfg->groups[group].pm_src, "")) continue; - if (strcmp(mCfg->groups[group].pm_jsonPath, String(topic).c_str())) continue; + if (strcmp(mCfg->groups[group].pm_src, String(topic).c_str())) continue; float power = 0.0; - power = (uint16_t)obj["val"]; + +// //TODO: datajson 100 enough? +// // this if-statement need to check if value contains a json object. +// // is it so, then deserialize it and get the values (Shelly GEN2) +// DynamicJsonDocument datajson(100); +// if (!deserializeJson(datajson, obj["val"])) +// { +// switch (mCfg->groups[group].pm_target) { +// case 0: power = datajson["a_act_power"]; break; +// case 1: power = datajson["b_act_power"]; break; +// case 2: power = datajson["c_act_power"]; break; +// case 3: power = datajson["total_act_power"]; break; +// } +// } else { +// //TODO: check if parse is possible here? Is that right? + power = (uint16_t)obj["val"]; +// } bufferWrite(power, group); // MQTT - Powermeter if (mCfg->debug) { if (mMqtt->isConnected()) { - // P - mqttObj["Sum"] = ah::round1(power); - /// mqttObj["L1"] = ah::round1(power.P1); - /// mqttObj["L2"] = ah::round1(power.P2); - /// mqttObj["L3"] = ah::round1(power.P3); - mMqtt->publish(String("zero/state/groups/" + String(group) + "/powermeter/P").c_str(), mqttDoc.as().c_str(), false); - mqttDoc.clear(); - - // W (TODO) + mMqtt->publish(String("zero/state/groups/" + String(group) + "/powermeter/P").c_str(), String(ah::round1(power)).c_str(), false); } } @@ -246,8 +278,9 @@ class powermeter { zeroExport_t *mCfg; PubMqttType *mMqtt = nullptr; JsonObject *mLog; + IApp *mApp = nullptr; - unsigned long mPreviousTsp = 0; + unsigned long mPreviousTsp = millis(); float mPowermeterBuffer[ZEROEXPORT_MAX_GROUPS][5] = {0}; short mPowermeterBufferPos[ZEROEXPORT_MAX_GROUPS] = {0}; @@ -260,8 +293,9 @@ class powermeter { */ void setHeader(HTTPClient *h) { h->setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); - h->setUserAgent("Ahoy-Agent"); - // TODO: Ahoy-0.8.850024-zero +/// h->setUserAgent("Ahoy-Agent"); +/// // TODO: Ahoy-0.8.850024-zero + h->setUserAgent(mApp->getVersion()); h->setConnectTimeout(500); h->setTimeout(1000); h->addHeader("Content-Type", "application/json"); @@ -280,7 +314,7 @@ class powermeter { setHeader(&http); - String url = String("http://") + String(mCfg->groups[group].pm_url) + String("/") + String(mCfg->groups[group].pm_jsonPath); + String url = String("http://") + String(mCfg->groups[group].pm_src) + String("/") + String(mCfg->groups[group].pm_jsonPath); logObj["HTTP_URL"] = url; http.begin(url); @@ -373,8 +407,8 @@ class powermeter { http.addHeader("Content-Type", "application/json"); http.addHeader("Accept", "application/json"); - // String url = String("http://") + String(mCfg->groups[group].pm_url) + String("/") + String(mCfg->groups[group].pm_jsonPath); - String url = String(mCfg->groups[group].pm_url); + // String url = String("http://") + String(mCfg->groups[group].pm_src) + String("/") + String(mCfg->groups[group].pm_jsonPath); + String url = String(mCfg->groups[group].pm_src); logObj["HTTP_URL"] = url; http.begin(url); @@ -482,23 +516,12 @@ class powermeter { {{0x01, 0x00, 0x02, 0x08, 0x00, 0xff}, &smlOBISWh, &_powerMeterExport}}; bool getPowermeterWattsTibber(JsonObject logObj, uint8_t group, float *power) { - mPreviousTsp = mPreviousTsp + 2000; // Zusätzliche Pause - bool result = false; logObj["mod"] = "getPowermeterWattsTibber"; - String auth; - if (strlen(mCfg->groups[group].pm_user) > 0 && strlen(mCfg->groups[group].pm_pass) > 0) { - auth = base64::encode(String(mCfg->groups[group].pm_user) + String(":") + String(mCfg->groups[group].pm_pass)); - snprintf(mCfg->groups[group].pm_user, ZEROEXPORT_GROUP_MAX_LEN_PM_USER, "%s", DEF_ZEXPORT); - snprintf(mCfg->groups[group].pm_pass, ZEROEXPORT_GROUP_MAX_LEN_PM_PASS, "%s", auth.c_str()); - //@TODO:mApp->saveSettings(false); - } else { - auth = mCfg->groups[group].pm_pass; - } - - String url = String("http://") + mCfg->groups[group].pm_url + String("/") + String(mCfg->groups[group].pm_jsonPath); + String auth = mCfg->groups[group].pm_pass; + String url = String("http://") + mCfg->groups[group].pm_src + String("/") + String(mCfg->groups[group].pm_jsonPath); setHeader(&http); http.begin(url); @@ -551,7 +574,7 @@ class powermeter { setHeader(&http); String url = - String("http://") + String(mCfg->groups[group].pm_url) + + String("http://") + String(mCfg->groups[group].pm_src) + String("/") + String(mCfg->groups[group].pm_jsonPath + String("?user=") + String(mCfg->groups[group].pm_user) + String("&password=") + String(mCfg->groups[group].pm_pass)); http.begin(url); diff --git a/src/plugins/zeroExport/zeroExport.h b/src/plugins/zeroExport/zeroExport.h index d0c215ff..58541623 100644 --- a/src/plugins/zeroExport/zeroExport.h +++ b/src/plugins/zeroExport/zeroExport.h @@ -47,7 +47,7 @@ class ZeroExport { mApi = api; mMqtt = mqtt; - mIsInitialized = mPowermeter.setup(mCfg, mqtt, &mLog); + mIsInitialized = mPowermeter.setup(mApp, mCfg, mqtt, &mLog); } /** loop @@ -106,18 +106,14 @@ class ZeroExport { return; } - // Calc Data->groupPower - uint16_t groupPower = 0; - for (uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) { - groupPower += mCfg->groups[group].inverters[inv].power; - } - mLog["gP"] = groupPower; - // Calc Data->groupLimit + uint16_t groupPower = 0; uint16_t groupLimit = 0; for (uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) { - groupLimit += mCfg->groups[group].inverters[inv].limit; + groupPower += mCfg->groups[group].inverters[inv].power; // Calc Data->groupPower + groupLimit += mCfg->groups[group].inverters[inv].limit; // Calc Data->groupLimit } + mLog["gP"] = groupPower; mLog["gL"] = groupLimit; // Batteryprotection @@ -485,6 +481,17 @@ class ZeroExport { mLog["i"] = inv; mCfg->groups[group].inverters[inv].waitAck = 0; mLog["wA"] = mCfg->groups[group].inverters[inv].waitAck; + + mCfg->groups[group].inverters[inv].limit = mCfg->groups[group].inverters[inv].powerMin; + iv->powerLimit[0] = static_cast(mCfg->groups[group].inverters[inv].limit * 10.0); + iv->powerLimit[1] = AbsolutNonPersistent; + if (iv->setDevControlRequest(ActivePowerContr)) { + mApp->triggerTickSend(iv->id); + mCfg->groups[group].inverters[inv].waitAck = 60; + mCfg->groups[group].inverters[inv].action = zeroExportAction_t::doNone; + mCfg->groups[group].inverters[inv].actionTimer = 0; + mCfg->groups[group].inverters[inv].actionTimestamp = millis(); + } sendLog(); clearLog(); } @@ -637,53 +644,41 @@ class ZeroExport { if (obj["path"] == "ctrl" && obj["cmd"] == "zero") { int8_t topicGroup = getGroupFromTopic(topic.c_str()); - if (topicGroup != -1) - mLog["g"] = topicGroup; int8_t topicInverter = getInverterFromTopic(topic.c_str()); - if (topicInverter == -1) - mLog["i"] = topicInverter; + + if (topicGroup != -1) mLog["g"] = topicGroup; + if (topicInverter == -1) mLog["i"] = topicInverter; + + mLog["k"] = topic; // "topic":"ctrl/zero/enabled" - if (topic.indexOf("ctrl/zero/enabled") != -1) { - mCfg->enabled = (bool)obj["val"]; - mLog["k"] = "ctrl/zero/enabled"; - mLog["v"] = mCfg->enabled; - } + if (topic.indexOf("ctrl/zero/enabled") != -1) mCfg->enabled = mLog["v"] = (bool)obj["val"]; // "topic":"ctrl/zero/sleep" - if (topic.indexOf("ctrl/zero/sleep") != -1) { - mCfg->sleep = (bool)obj["val"]; - mLog["k"] = "ctrl/zero/sleep"; - mLog["v"] = mCfg->sleep; - } + else if (topic.indexOf("ctrl/zero/sleep") != -1) mCfg->sleep = mLog["v"] = (bool)obj["val"]; + + else if ((topicGroup >= 0) && (topicGroup < ZEROEXPORT_MAX_GROUPS)) + { + String stopicGroup = String(topicGroup); - if ((topicGroup >= 0) && (topicGroup < ZEROEXPORT_MAX_GROUPS)) { // "topic":"ctrl/zero/groups/+/enabled" - if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/enabled") != -1) { - mCfg->groups[topicGroup].enabled = (bool)obj["val"]; - mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/enabled"; - mLog["v"] = mCfg->groups[topicGroup].enabled; - } + if (topic.endsWith("/enabled")) mCfg->groups[topicGroup].enabled = mLog["v"] = (bool)obj["val"]; // "topic":"ctrl/zero/groups/+/sleep" - if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/sleep") != -1) { - mCfg->groups[topicGroup].sleep = (bool)obj["val"]; - mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/sleep"; - mLog["v"] = mCfg->groups[topicGroup].sleep; - } + else if (topic.endsWith("/sleep")) mCfg->groups[topicGroup].sleep = mLog["v"] = (bool)obj["val"]; // Auf Eis gelegt, dafür 2 Gruppen mehr // 0.8.103008.2 // // "topic":"ctrl/zero/groups/+/pm_ip" // if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/pm_ip") != -1) { - // snprintf(mCfg->groups[topicGroup].pm_url, ZEROEXPORT_GROUP_MAX_LEN_PM_URL, "%s", obj[F("val")].as()); + // snprintf(mCfg->groups[topicGroup].pm_src, ZEROEXPORT_GROUP_MAX_LEN_PM_SRC, "%s", obj[F("val")].as()); /// TODO: - // snprintf(mCfg->groups[topicGroup].pm_url, ZEROEXPORT_GROUP_MAX_LEN_PM_URL, "%s", obj[F("val")].as()); - // strncpy(mCfg->groups[topicGroup].pm_url, obj[F("val")], ZEROEXPORT_GROUP_MAX_LEN_PM_URL); - // strncpy(mCfg->groups[topicGroup].pm_url, String(obj[F("val")]).c_str(), ZEROEXPORT_GROUP_MAX_LEN_PM_URL); - // snprintf(mCfg->groups[topicGroup].pm_url, ZEROEXPORT_GROUP_MAX_LEN_PM_URL, "%s", String(obj[F("val")]).c_str()); + // snprintf(mCfg->groups[topicGroup].pm_src, ZEROEXPORT_GROUP_MAX_LEN_PM_SRC, "%s", obj[F("val")].as()); + // strncpy(mCfg->groups[topicGroup].pm_src, obj[F("val")], ZEROEXPORT_GROUP_MAX_LEN_PM_SRC); + // strncpy(mCfg->groups[topicGroup].pm_src, String(obj[F("val")]).c_str(), ZEROEXPORT_GROUP_MAX_LEN_PM_SRC); + // snprintf(mCfg->groups[topicGroup].pm_src, ZEROEXPORT_GROUP_MAX_LEN_PM_SRC, "%s", String(obj[F("val")]).c_str()); // mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/pm_ip"; - // mLog["v"] = mCfg->groups[topicGroup].pm_url; + // mLog["v"] = mCfg->groups[topicGroup].pm_src; // } // // // "topic":"ctrl/zero/groups/+/pm_jsonPath" @@ -695,55 +690,37 @@ class ZeroExport { // } // "topic":"ctrl/zero/groups/+/battery/switch" - if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/battery/switch") != -1) { - mCfg->groups[topicGroup].battSwitch = (bool)obj["val"]; - mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/battery/switch"; - mLog["v"] = mCfg->groups[topicGroup].battSwitch; - } + else if (topic.endsWith("/battery/switch")) mCfg->groups[topicGroup].battSwitch = mLog["v"] = (bool)obj["val"]; - // "topic":"ctrl/zero/groups/+/advanced/setPoint" - if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/advanced/setPoint") != -1) { - mCfg->groups[topicGroup].setPoint = (int16_t)obj["val"]; - mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/advanced/setPoint"; - mLog["v"] = mCfg->groups[topicGroup].setPoint; - } + else if (topic.indexOf("/advanced/") != -1) + { + // "topic":"ctrl/zero/groups/+/advanced/setPoint" + if (topic.endsWith("/setPoint")) mCfg->groups[topicGroup].setPoint = mLog["v"] = (int16_t)obj["val"]; - // "topic":"ctrl/zero/groups/+/advanced/powerTolerance" - if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/advanced/powerTolerance") != -1) { - mCfg->groups[topicGroup].powerTolerance = (uint8_t)obj["val"]; - mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/advanced/powerTolerance"; - mLog["v"] = mCfg->groups[topicGroup].powerTolerance; - } + // "topic":"ctrl/zero/groups/+/advanced/powerTolerance" + else if (topic.endsWith("/powerTolerance")) mCfg->groups[topicGroup].powerTolerance = mLog["v"] = (uint8_t)obj["val"]; - // "topic":"ctrl/zero/groups/+/advanced/powerMax" - if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/advanced/powerMax") != -1) { - mCfg->groups[topicGroup].powerMax = (uint16_t)obj["val"]; - mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/advanced/powerMax"; - mLog["v"] = mCfg->groups[topicGroup].powerMax; + // "topic":"ctrl/zero/groups/+/advanced/powerMax" + else if (topic.endsWith("/powerMax")) mCfg->groups[topicGroup].powerMax = mLog["v"] = (uint16_t)obj["val"]; } - - if ((topicInverter >= 0) && (topicInverter < ZEROEXPORT_GROUP_MAX_INVERTERS)) { - // "topic":"ctrl/zero/groups/+/inverter/+/enabled" - if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/inverter/" + String(topicInverter) + "/enabled") != -1) { - mCfg->groups[topicGroup].inverters[topicInverter].enabled = (bool)obj["val"]; - mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/inverter/" + String(topicInverter) + "/enabled"; - mLog["v"] = mCfg->groups[topicGroup].inverters[topicInverter].enabled; - } - - // "topic":"ctrl/zero/groups/+/inverter/+/powerMin" - if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/inverter/" + String(topicInverter) + "/powerMin") != -1) { - mCfg->groups[topicGroup].inverters[topicInverter].powerMin = (uint16_t)obj["val"]; - mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/inverter/" + String(topicInverter) + "/powerMin"; - mLog["v"] = mCfg->groups[topicGroup].inverters[topicInverter].powerMin; - } - - // "topic":"ctrl/zero/groups/+/inverter/+/powerMax" - if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/inverter/" + String(topicInverter) + "/powerMax") != -1) { - mCfg->groups[topicGroup].inverters[topicInverter].powerMax = (uint16_t)obj["val"]; - mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/inverter/" + String(topicInverter) + "/powerMax"; - mLog["v"] = mCfg->groups[topicGroup].inverters[topicInverter].powerMax; + else if (topic.indexOf("/inverter/") != -1) + { + if ((topicInverter >= 0) && (topicInverter < ZEROEXPORT_GROUP_MAX_INVERTERS)) + { + // "topic":"ctrl/zero/groups/+/inverter/+/enabled" + if (topic.endsWith("/enabled")) mCfg->groups[topicGroup].inverters[topicInverter].enabled = mLog["v"] = (bool)obj["val"]; + + // "topic":"ctrl/zero/groups/+/inverter/+/powerMin" + else if (topic.endsWith("/powerMin")) mCfg->groups[topicGroup].inverters[topicInverter].powerMin = mLog["v"] = (uint16_t)obj["val"]; + + // "topic":"ctrl/zero/groups/+/inverter/+/powerMax" + else if (topic.endsWith("/powerMax")) mCfg->groups[topicGroup].inverters[topicInverter].powerMax = mLog["v"] = (uint16_t)obj["val"]; + else mLog["k"] = "error"; } } + else { + mLog["k"] = "error"; + } } } @@ -791,6 +768,7 @@ class ZeroExport { while (*pGroupSection != '/' && digitsCopied < 2) strGroup[digitsCopied++] = *pGroupSection++; strGroup[digitsCopied] = '\0'; int8_t group = atoi(strGroup); + mLog["getGroupFromTopic"] = group; return group; } diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 21123be6..49a7caff 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -20,6 +20,7 @@ #include "ESPAsyncWebServer.h" #include "plugins/history.h" +#include #if defined(F) && defined(ESP32) #undef F @@ -839,7 +840,7 @@ class RestApi { // Powermeter objGroup[F("pm_refresh")] = (uint8_t)mConfig->plugin.zeroExport.groups[group].pm_refresh; objGroup[F("pm_type")] = (uint8_t)mConfig->plugin.zeroExport.groups[group].pm_type; - objGroup[F("pm_url")] = String(mConfig->plugin.zeroExport.groups[group].pm_url); + objGroup[F("pm_src")] = String(mConfig->plugin.zeroExport.groups[group].pm_src); objGroup[F("pm_jsonPath")] = String(mConfig->plugin.zeroExport.groups[group].pm_jsonPath); objGroup[F("pm_user")] = String(mConfig->plugin.zeroExport.groups[group].pm_user); objGroup[F("pm_pass")] = String(mConfig->plugin.zeroExport.groups[group].pm_pass); @@ -1159,10 +1160,17 @@ class RestApi { // Powermeter mConfig->plugin.zeroExport.groups[group].pm_refresh = jsonIn[F("pm_refresh")]; mConfig->plugin.zeroExport.groups[group].pm_type = jsonIn[F("pm_type")]; - snprintf(mConfig->plugin.zeroExport.groups[group].pm_url, ZEROEXPORT_GROUP_MAX_LEN_PM_URL, "%s", jsonIn[F("pm_url")].as()); + snprintf(mConfig->plugin.zeroExport.groups[group].pm_src, ZEROEXPORT_GROUP_MAX_LEN_PM_SRC, "%s", jsonIn[F("pm_src")].as()); snprintf(mConfig->plugin.zeroExport.groups[group].pm_jsonPath, ZEROEXPORT_GROUP_MAX_LEN_PM_JSONPATH, "%s", jsonIn[F("pm_jsonPath")].as()); - snprintf(mConfig->plugin.zeroExport.groups[group].pm_user, ZEROEXPORT_GROUP_MAX_LEN_PM_USER, "%s", jsonIn[F("pm_user")].as()); - snprintf(mConfig->plugin.zeroExport.groups[group].pm_pass, ZEROEXPORT_GROUP_MAX_LEN_PM_PASS, "%s", jsonIn[F("pm_pass")].as()); + + + if (jsonIn[F("pm_pass")] != F("****")) + { + String auth = base64::encode(String(jsonIn[F("pm_user")]) + String(":") + String(jsonIn[F("pm_pass")])); + snprintf(mConfig->plugin.zeroExport.groups[group].pm_user, ZEROEXPORT_GROUP_MAX_LEN_PM_USER, "%s", String(jsonIn[F("pm_user")]).c_str()); + snprintf(mConfig->plugin.zeroExport.groups[group].pm_pass, ZEROEXPORT_GROUP_MAX_LEN_PM_PASS, "%s", auth.c_str()); + } + mConfig->plugin.zeroExport.groups[group].pm_target = jsonIn[F("pm_target")]; // Inverters for(uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) { diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 761e9f42..1b0a9f07 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -1389,25 +1389,21 @@ divRow("{#ZE_GROUP_TAB_POWERMETER_REFRESH}", ml("input", {name: "pm_refresh", class: "text", type: "number", min: "1", max: "30", step: "1", value: obj.pm_refresh}, null), ), -// TODO: URL -> IP divRow("{#ZE_GROUP_TAB_POWERMETER_TARGET}", ml("select", {name: "pm_target", class: "text", id: "pm_target"}, null), ), - divRow("{#ZE_GROUP_TAB_POWERMETER_IP}", [ - ml("input", {name: "pm_url", class: "text", type: "text", value: obj.pm_url, maxlength: "100"}, null), + divRow("{#ZE_GROUP_TAB_POWERMETER_SRC}", [ + ml("input", {name: "pm_src", class: "text", type: "text", value: obj.pm_src, maxlength: "100"}, null), ]), divRow("{#ZE_GROUP_TAB_POWERMETER_JSONPATH}", [ ml("input", {name: "pm_jsonPath", class: "text", type: "text", value: obj.pm_jsonPath}, null), ]), divRow("{#ZE_GROUP_TAB_POWERMETER_USER}", - ml("input", {name: "pm_user", class: "text", type: "text", value: "" }, null), + ml("input", {name: "pm_user", class: "text", type: "text", value: obj.pm_user }, null), ), divRow("{#ZE_GROUP_TAB_POWERMETER_PASS}", ml("input", {name: "pm_pass", class: "text", type: "password", value: "****"}, null), ), - divRow("{#ZE_GROUP_TAB_POWERMETER_TOPIC}", - ml("input", {id: 3, name: "pm_topic", class: "text", type: "text", value: ""}, 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."), @@ -1513,9 +1509,8 @@ } // add addEventListener - const selectElement = document.querySelector("#pm_type"); - //selectElement.addEventListener("change", (event) => { pm_type_dropdown() }); - selectElement.addEventListener("change", (event) => { pm_type_dropdown() }); + const se_pm_type = document.querySelector("#pm_type"); + se_pm_type.addEventListener("change", (event) => { pm_type_dropdown() }); // run event one time pm_type_dropdown(); @@ -1571,6 +1566,31 @@ } } + // add addEventListener + const se_battCfg = document.querySelector("#battCfg"); + se_battCfg.addEventListener("change", (event) => { battCfg_dropdown() }); + + // run event one time + battCfg_dropdown(); + + function battCfg_dropdown() + { + var e = document.getElementsByName("battCfg")[0]; + var value = e.options[e.selectedIndex].text; + + var divsToHide = document.getElementById("divBattery"); + + // Formular for Powermeter-DropDown + // show all DIVs and remove only what is not necessary + // 1 = pm_refresh, 2 = pm_target, 3 = pm_src, 4 = pm_jsonPath, 5 = pm_user, 6 = pm_pass + for(var i = 0; i < divsToHide.childElementCount; i++) divsToHide.childNodes[i].style.display = ''; + + if(value == "---") for(var i = 1; i < divsToHide.childElementCount; i++) divsToHide.childNodes[i].style.display = 'none'; + else if(value == "Inverter U dc") { + divsToHide.childNodes[1].style.display = 'none'; + } + } + function pm_type_dropdown() { var e = document.getElementsByName("pm_type")[0]; @@ -1580,21 +1600,27 @@ // Formular for Powermeter-DropDown // show all DIVs and remove only what is not necessary + // 1 = pm_refresh, 2 = pm_target, 3 = pm_src, 4 = pm_jsonPath, 5 = pm_user, 6 = pm_pass for(var i = 0; i < divsToHide.childElementCount; i++) divsToHide.childNodes[i].style.display = ''; if(value == "---") for(var i = 1; i < divsToHide.childElementCount; i++) divsToHide.childNodes[i].style.display = 'none'; else if(value == "Shelly") { - divsToHide.childNodes[7].style.display = 'none'; + divsToHide.childNodes[5].style.display = 'none'; + divsToHide.childNodes[6].style.display = 'none'; } else if(value == "Mqtt") { - divsToHide.childNodes[3].style.display = 'none'; + divsToHide.childNodes[1].style.display = 'none'; + divsToHide.childNodes[2].style.display = 'none'; divsToHide.childNodes[4].style.display = 'none'; divsToHide.childNodes[5].style.display = 'none'; divsToHide.childNodes[6].style.display = 'none'; } else if(value == "Tibber") { divsToHide.childNodes[4].style.display = 'none'; - divsToHide.childNodes[7].style.display = 'none'; + } + else if(value == "Shrdzm") { + divsToHide.childNodes[1].style.display = 'none'; + divsToHide.childNodes[2].style.display = 'none'; } } @@ -1611,7 +1637,7 @@ o.pm_refresh = document.getElementsByName("pm_refresh")[0].value; var e = document.getElementsByName("pm_type")[0]; o.pm_type = e.options[e.selectedIndex].value; - o.pm_url = document.getElementsByName("pm_url")[0].value; + o.pm_src = document.getElementsByName("pm_src")[0].value; o.pm_jsonPath = document.getElementsByName("pm_jsonPath")[0].value; o.pm_user = document.getElementsByName("pm_user")[0].value; o.pm_pass = document.getElementsByName("pm_pass")[0].value; @@ -1678,7 +1704,7 @@ // Powermeter o.pm_refresh = 5; o.pm_type = 0; - o.pm_url = ""; + o.pm_src = ""; o.pm_jsonPath = ""; o.pm_user = ""; o.pm_pass = ""; diff --git a/src/web/lang.json b/src/web/lang.json index 4fa5b655..1172d670 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -894,9 +894,9 @@ "de": "Typ:" }, { - "token": "ZE_GROUP_TAB_POWERMETER_IP", - "en": "IP:", - "de": "IP:" + "token": "ZE_GROUP_TAB_POWERMETER_SRC", + "en": "IP / Topic:", + "de": "IP / Topic:" }, { "token": "ZE_GROUP_TAB_POWERMETER_JSONPATH", @@ -913,11 +913,6 @@ "en": "Password:", "de": "Passwort:" }, - { - "token": "ZE_GROUP_TAB_POWERMETER_TOPIC", - "en": "Topic:", - "de": "Topic:" - }, { "token": "ZE_GROUP_TAB_POWERMETER_TARGET", "en": "Target:",