From 0e57f0f6578a16da0bbd5b1f7d78202a53c8c432 Mon Sep 17 00:00:00 2001 From: Patrick Amrhein Date: Wed, 3 Apr 2024 11:16:30 +0200 Subject: [PATCH] ZE add powermeter Shrdzm --- src/config/settings.h | 10 ++--- src/plugins/zeroExport/powermeter.h | 64 +++++++++++++++++++++++++++++ src/web/html/setup.html | 11 ++--- 3 files changed, 75 insertions(+), 10 deletions(-) diff --git a/src/config/settings.h b/src/config/settings.h index 1bc7fc91..ac8e40af 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -215,12 +215,11 @@ typedef struct { #define ZEROEXPORT_DEF_INV_WAITINGTIME_MS 10000 #define ZEROEXPORT_GROUP_WR_LIMIT_MIN_DIFF 5 #define ZEROEXPORT_POWERMETER_SHELLY -#define ZEROEXPORT_POWERMETER_TASMOTA -#define ZEROEXPORT_POWERMETER_MQTT -#define ZEROEXPORT_POWERMETER_HICHI +//#define ZEROEXPORT_POWERMETER_TASMOTA +//#define ZEROEXPORT_POWERMETER_MQTT +//#define ZEROEXPORT_POWERMETER_HICHI #define ZEROEXPORT_POWERMETER_TIBBER - - +#define ZEROEXPORT_POWERMETER_SHRDZM enum class zeroExportState : uint8_t { INIT, @@ -247,6 +246,7 @@ typedef enum { Mqtt = 3, Hichi = 4, Tibber = 5, + Shrdzm = 6, } zeroExportPowermeterType_t; typedef enum { diff --git a/src/plugins/zeroExport/powermeter.h b/src/plugins/zeroExport/powermeter.h index 4191bc69..a83d1b50 100644 --- a/src/plugins/zeroExport/powermeter.h +++ b/src/plugins/zeroExport/powermeter.h @@ -84,6 +84,11 @@ class powermeter { case zeroExportPowermeterType_t::Tibber: power = getPowermeterWattsTibber(*mLog, group); break; +#endif +#if defined(ZEROEXPORT_POWERMETER_SHRDZM) + case zeroExportPowermeterType_t::Shrdzm: + power = getPowermeterWattsShrdzm(*mLog, group); + break; #endif } @@ -502,6 +507,65 @@ class powermeter { } #endif +#if defined(ZEROEXPORT_POWERMETER_SHRDZM) + /** getPowermeterWattsShrdzm + * ... + * @param logObj + * @param group + * @returns true/false + * @TODO: Username & Passwort wird mittels base64 verschlüsselt. Dies wird für die Authentizierung benötigt. Wichtig diese im WebUI unkenntlich zu machen und base64 im eeprom zu speichern, statt klartext. + * @TODO: Abfrage Interval einbauen. Info: Datei-Size kann auch mal 0-bytes sein! + * Quelle: https://cms.shrdzm.com + * Abfrage: http://IP/getLastData?user=XXXXXX&password=YYYYYY + * Ergebnis: {"1.8.0":"21561001","2.8.0":"44477","3.8.1":"64037","4.8.1":"6021512","1.7.0":"277","2.7.0":"0","3.7.0":"0","4.7.0":"184","1.128.0":"0","16.7.0":"277","uptime":"0000:07:35:38"} + */ + PowermeterBuffer_t getPowermeterWattsShrdzm(JsonObject logObj, uint8_t group) { + PowermeterBuffer_t result; + result.P = result.P1 = result.P2 = result.P3 = 0; + + logObj["mod"] = "getPowermeterWattsShrdzm"; + + HTTPClient http; + http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + http.setUserAgent("Ahoy-Agent"); + // TODO: Ahoy-0.8.850024-zero + http.setConnectTimeout(500); + http.setTimeout(1000); + 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("?user=") + String(mCfg->groups[group].pm_user) + + String("&password=") + String(mCfg->groups[group].pm_pass)); + + http.begin(url); + + if (http.GET() == HTTP_CODE_OK && http.getSize() > 0) { + // Parsing + DynamicJsonDocument doc(512); + DeserializationError error = deserializeJson(doc, http.getString()); + if (error) { + logObj["err"] = "deserializeJson: " + String(error.c_str()); + return result; + } else { + if (doc.containsKey(F("16.7.0"))) { + result.P = doc["16.7.0"]; + } + + if (!(result.P1 && result.P2 && result.P3)) { + result.P1 = result.P2 = result.P3 = result.P / 3; + } + + } + } + http.end(); + + return result; + } +#endif + void bufferWrite(PowermeterBuffer_t raw, short group) { mPowermeterBuffer[group][mPowermeterBufferPos[group]] = raw; mPowermeterBufferPos[group]++; diff --git a/src/web/html/setup.html b/src/web/html/setup.html index db474150..0e84133a 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -1462,16 +1462,17 @@ modal("{#ZE_GROUP_EDIT_MODAL}: " + obj.id, html); // ser.dispatchEvent(new Event('change')); -// Inhalt f?r pm_type aus config laden und in eine Funktion ausgliedern +// Inhalt fuer pm_type aus config laden und in eine Funktion ausgliedern var e = document.getElementById("pm_type"); selDelAllOpt(e); -// TODO: ?bersetzen? +// TODO: uebersetzen? e.appendChild(opt("0", "---")); e.appendChild(opt("1", "Shelly")); - e.appendChild(opt("2", "Tasmota")); - e.appendChild(opt("3", "Mqtt")); - e.appendChild(opt("4", "Hichi")); + //e.appendChild(opt("2", "Tasmota")); + //e.appendChild(opt("3", "Mqtt")); + //e.appendChild(opt("4", "Hichi")); e.appendChild(opt("5", "Tibber")); + e.appendChild(opt("6", "Shrdzm")); for (var i = 0; i < e.options.length; i++) { if (e.options[i].value == obj.pm_type) { e.selectedIndex = i;