Browse Source

0.8.970010-zero

0.8.970010-zero
pull/1557/head
tictrick 1 year ago
committed by GitHub
parent
commit
5c3814509d
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      src/app.cpp
  2. 117
      src/config/settings.h
  3. 2
      src/defines.h
  4. 267
      src/plugins/zeroExport/powermeter.h
  5. 1623
      src/plugins/zeroExport/zeroExport.h
  6. 1
      src/publisher/pubMqtt.h
  7. 2
      src/web/RestApi.h

6
src/app.cpp

@ -235,7 +235,7 @@ void app::regularTickers(void) {
// Plugin ZeroExport // Plugin ZeroExport
#if defined(PLUGIN_ZEROEXPORT) #if defined(PLUGIN_ZEROEXPORT)
everySec(std::bind(&ZeroExportType::tickerSecond, &mZeroExport), "ZeroExport"); everySec(std::bind(&ZeroExportType::tickSecond, &mZeroExport), "ZeroExport");
#endif #endif
// Plugin ZeroExport - Ende // Plugin ZeroExport - Ende
@ -423,6 +423,10 @@ void app::tickMinute(void) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void app::tickMidnight(void) { void app::tickMidnight(void) {
#if defined(PLUGIN_ZEROEXPORT)
mZeroExport.tickMidnight();
#endif /*defined(PLUGIN_ZEROEXPORT)*/
uint32_t localTime = gTimezone.toLocal(mTimestamp); uint32_t localTime = gTimezone.toLocal(mTimestamp);
uint32_t nxtTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time uint32_t nxtTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time
onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2"); onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2");

117
src/config/settings.h

@ -188,7 +188,7 @@ typedef struct {
// Plugin ZeroExport // Plugin ZeroExport
#if defined(PLUGIN_ZEROEXPORT) #if defined(PLUGIN_ZEROEXPORT)
#define ZEROEXPORT_DEV_POWERMETER //#define ZEROEXPORT_DEV_POWERMETER
#define ZEROEXPORT_MAX_GROUPS 6 #define ZEROEXPORT_MAX_GROUPS 6
#define ZEROEXPORT_GROUP_MAX_LEN_NAME 25 #define ZEROEXPORT_GROUP_MAX_LEN_NAME 25
#define ZEROEXPORT_GROUP_MAX_LEN_PM_URL 100 #define ZEROEXPORT_GROUP_MAX_LEN_PM_URL 100
@ -203,19 +203,18 @@ typedef struct {
enum class zeroExportState : uint8_t { enum class zeroExportState : uint8_t {
INIT, INIT,
WAIT,
PUBLISH,
WAITREFRESH, WAITREFRESH,
GETINVERTERACKS,
GETINVERTERDATA, GETINVERTERDATA,
BATTERYPROTECTION, BATTERYPROTECTION,
GETPOWERMETER, GETPOWERMETER,
CONTROLLER, CONTROLLER,
PROGNOSE, PROGNOSE,
AUFTEILEN, AUFTEILEN,
SETLIMIT,
SETPOWER,
SETREBOOT, SETREBOOT,
SETPOWER,
SETLIMIT,
PUBLISH,
EMERGENCY,
FINISH, FINISH,
ERROR ERROR
}; };
@ -228,22 +227,7 @@ typedef enum {
Hichi = 4, Hichi = 4,
Tibber = 5, Tibber = 5,
} zeroExportPowermeterType_t; } zeroExportPowermeterType_t;
/*
typedef struct {
uint8_t type;
uint8_t ip;
uint8_t url;
bool login;
uint8_t username;
uint8_t password;
uint8_t group;
uint8_t phase;
uint16_t nextRun;
uint16_t interval;
uint8_t error;
uint16_t power;
} zeroExportPowermeter_t;
*/
typedef enum { typedef enum {
Sum = 0, Sum = 0,
L1 = 1, L1 = 1,
@ -262,20 +246,25 @@ typedef struct {
uint16_t powerMax; uint16_t powerMax;
// //
float power; int32_t power;
float limit; int32_t limit;
float limitNew; int32_t limitNew;
uint8_t waitLimitAck; uint8_t waitLimitAck;
uint8_t waitPowerAck; uint8_t waitPowerAck;
uint8_t waitRebootAck; uint8_t waitRebootAck;
unsigned long limitTsp; unsigned long limitTsp;
float dcVoltage; float dcVoltage;
bool state; bool state;
//
int8_t doReboot;
int8_t doPower;
bool doLimit;
} zeroExportGroupInverter_t; } zeroExportGroupInverter_t;
typedef struct { typedef struct {
// General // General
bool enabled; bool enabled;
bool sleep;
char name[ZEROEXPORT_GROUP_MAX_LEN_NAME]; char name[ZEROEXPORT_GROUP_MAX_LEN_NAME];
// Powermeter // Powermeter
uint8_t pm_type; uint8_t pm_type;
@ -296,62 +285,46 @@ typedef struct {
uint16_t powerMax; uint16_t powerMax;
// //
zeroExportState stateLast;
zeroExportState state; zeroExportState state;
zeroExportState stateNext; // zeroExportState stateNext;
unsigned long lastRun; unsigned long lastRun;
unsigned long lastRefresh; unsigned long lastRefresh;
// bool waitForAck; uint16_t wait;
float eSum;
float eSum1;
float eSum2;
float eSum3;
float eOld;
float eOld1;
float eOld2;
float eOld3;
float Kp;
float Ki;
float Kd;
float pm_P[5]; int32_t pm_P;
float pm_P1[5]; int32_t pm_P1;
float pm_P2[5]; int32_t pm_P2;
float pm_P3[5]; int32_t pm_P3;
uint8_t pm_iIn = 0;
uint8_t pm_iOut = 0;
float pmPower;
float pmPowerL1;
float pmPowerL2;
float pmPowerL3;
bool publishPower = false; bool publishPower = false;
bool battSwitch; bool battSwitch;
float grpPower;
float grpPowerL1; // PID controller
float grpPowerL2; int32_t eSum;
float grpPowerL3; int32_t eSum1;
// float grpLimit; int32_t eSum2;
// float grpLimitL1; int32_t eSum3;
// float grpLimitL2; int32_t eOld;
// float grpLimitL3; int32_t eOld1;
int32_t eOld2;
// uint16_t power; // Aktueller Verbrauch int32_t eOld3;
// uint16_t powerLimitAkt; // Aktuelles Limit float Kp;
// uint16_t powerHyst; // Hysterese float Ki;
float Kd;
int32_t y;
int32_t y1;
int32_t y2;
int32_t y3;
} zeroExportGroup_t; } zeroExportGroup_t;
typedef struct { typedef struct {
bool enabled; bool enabled;
bool sleep;
bool log_over_webserial; bool log_over_webserial;
bool log_over_mqtt; bool log_over_mqtt;
bool debug; bool debug;
zeroExportGroup_t groups[ZEROEXPORT_MAX_GROUPS]; zeroExportGroup_t groups[ZEROEXPORT_MAX_GROUPS];
// uint8_t query_device; // 0 - Tibber, 1 - Shelly, 2 - other (rs232?) // uint8_t query_device; // 0 - Tibber, 1 - Shelly, 2 - other (rs232?)
// char monitor_url[ZEXPORT_ADDR_LEN]; // char monitor_url[ZEXPORT_ADDR_LEN];
// char json_path[ZEXPORT_ADDR_LEN]; // char json_path[ZEXPORT_ADDR_LEN];
@ -675,12 +648,14 @@ class settings {
// Plugin ZeroExport // Plugin ZeroExport
#if defined(PLUGIN_ZEROEXPORT) #if defined(PLUGIN_ZEROEXPORT)
mCfg.plugin.zeroExport.enabled = false; mCfg.plugin.zeroExport.enabled = false;
mCfg.plugin.zeroExport.sleep = false;
mCfg.plugin.zeroExport.log_over_webserial = false; mCfg.plugin.zeroExport.log_over_webserial = false;
mCfg.plugin.zeroExport.log_over_mqtt = false; mCfg.plugin.zeroExport.log_over_mqtt = false;
mCfg.plugin.zeroExport.debug = false; mCfg.plugin.zeroExport.debug = false;
for(uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) { for(uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
// General // General
mCfg.plugin.zeroExport.groups[group].enabled = false; mCfg.plugin.zeroExport.groups[group].enabled = false;
mCfg.plugin.zeroExport.groups[group].sleep = false;
snprintf(mCfg.plugin.zeroExport.groups[group].name, ZEROEXPORT_GROUP_MAX_LEN_NAME, "%s", DEF_ZEXPORT); snprintf(mCfg.plugin.zeroExport.groups[group].name, ZEROEXPORT_GROUP_MAX_LEN_NAME, "%s", DEF_ZEXPORT);
// Powermeter // Powermeter
mCfg.plugin.zeroExport.groups[group].pm_type = zeroExportPowermeterType_t::None; mCfg.plugin.zeroExport.groups[group].pm_type = zeroExportPowermeterType_t::None;
@ -699,6 +674,9 @@ class settings {
mCfg.plugin.zeroExport.groups[group].inverters[inv].waitLimitAck = false; mCfg.plugin.zeroExport.groups[group].inverters[inv].waitLimitAck = false;
mCfg.plugin.zeroExport.groups[group].inverters[inv].waitPowerAck = false; mCfg.plugin.zeroExport.groups[group].inverters[inv].waitPowerAck = false;
mCfg.plugin.zeroExport.groups[group].inverters[inv].waitRebootAck = false; mCfg.plugin.zeroExport.groups[group].inverters[inv].waitRebootAck = false;
mCfg.plugin.zeroExport.groups[group].inverters[inv].doReboot = false;
mCfg.plugin.zeroExport.groups[group].inverters[inv].doPower = -1;
mCfg.plugin.zeroExport.groups[group].inverters[inv].doLimit = false;
} }
// Battery // Battery
mCfg.plugin.zeroExport.groups[group].battEnabled = false; mCfg.plugin.zeroExport.groups[group].battEnabled = false;
@ -716,10 +694,11 @@ class settings {
mCfg.plugin.zeroExport.groups[group].state = zeroExportState::INIT; mCfg.plugin.zeroExport.groups[group].state = zeroExportState::INIT;
mCfg.plugin.zeroExport.groups[group].lastRun = 0; mCfg.plugin.zeroExport.groups[group].lastRun = 0;
mCfg.plugin.zeroExport.groups[group].lastRefresh = 0; mCfg.plugin.zeroExport.groups[group].lastRefresh = 0;
mCfg.plugin.zeroExport.groups[group].pmPower = 0; mCfg.plugin.zeroExport.groups[group].wait = 0;
mCfg.plugin.zeroExport.groups[group].pmPowerL1 = 0; mCfg.plugin.zeroExport.groups[group].pm_P = 0;
mCfg.plugin.zeroExport.groups[group].pmPowerL2 = 0; mCfg.plugin.zeroExport.groups[group].pm_P1 = 0;
mCfg.plugin.zeroExport.groups[group].pmPowerL3 = 0; mCfg.plugin.zeroExport.groups[group].pm_P2 = 0;
mCfg.plugin.zeroExport.groups[group].pm_P3 = 0;
mCfg.plugin.zeroExport.groups[group].battSwitch = false; mCfg.plugin.zeroExport.groups[group].battSwitch = false;
} }

2
src/defines.h

@ -13,7 +13,7 @@
//------------------------------------- //-------------------------------------
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 8 #define VERSION_MINOR 8
#define VERSION_PATCH 970009 #define VERSION_PATCH 970010
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {

267
src/plugins/zeroExport/powermeter.h

@ -21,6 +21,13 @@ typedef struct {
float *Arg; float *Arg;
} OBISHandler; } OBISHandler;
typedef struct {
float P;
float P1;
float P2;
float P3;
} PowermeterBuffer_t;
class powermeter { class powermeter {
public: public:
powermeter() { powermeter() {
@ -29,44 +36,69 @@ class powermeter {
~powermeter() { ~powermeter() {
} }
bool setup(zeroExport_t *cfg /*Hier muss noch geklärt werden was gebraucht wird*/) { bool setup(zeroExport_t *cfg, JsonObject *log /*Hier muss noch geklärt werden was gebraucht wird*/) {
mCfg = cfg; mCfg = cfg;
mLog = log;
return true; return true;
} }
void loop(void) { /** loop
} * abfrage der gruppen um die aktuellen Werte (Zähler) zu ermitteln.
/** groupGetPowermeter
* Holt die Daten vom Powermeter
* @param group
* @returns true/false
*/ */
bool getData(JsonObject logObj, uint8_t group) { void loop(void)
bool result = false; {
switch (mCfg->groups[group].pm_type) { unsigned long Tsp = millis();
case 1: if(Tsp - mPreviousTsp <= 1000) return; // skip when it is to fast
result = getPowermeterWattsShelly(logObj, group); mPreviousTsp = Tsp;
PowermeterBuffer_t power;
for (u_short group = 0; group < ZEROEXPORT_MAX_GROUPS; group++)
{
switch (mCfg->groups[group].pm_type) {
case zeroExportPowermeterType_t::Shelly:
power = getPowermeterWattsShelly(*mLog, group);
break; break;
case 2: case zeroExportPowermeterType_t::Tasmota:
result = getPowermeterWattsTasmota(logObj, group); power = getPowermeterWattsTasmota(*mLog, group);
break; break;
case 3: case zeroExportPowermeterType_t::Mqtt:
result = getPowermeterWattsMqtt(logObj, group); power = getPowermeterWattsMqtt(*mLog, group);
break; break;
case 4: case zeroExportPowermeterType_t::Hichi:
result = getPowermeterWattsHichi(logObj, group); power = getPowermeterWattsHichi(*mLog, group);
break; break;
case 5: case zeroExportPowermeterType_t::Tibber:
result = getPowermeterWattsTibber(logObj, group); power = getPowermeterWattsTibber(*mLog, group);
break; break;
}
bufferWrite(power, group);
} }
if (!result) { }
logObj["err"] = "type: " + String(mCfg->groups[group].pm_type);
/** groupGetPowermeter
* Holt die Daten vom Powermeter
* @param group
* @returns true/false
*/
PowermeterBuffer_t getDataAVG(uint8_t group) {
PowermeterBuffer_t avg;
avg.P = avg.P1 = avg.P2 = avg.P2 = avg.P3 = 0;
for (int i = 0; i < 5; i++)
{
avg.P += mPowermeterBuffer[group][i].P;
avg.P1 += mPowermeterBuffer[group][i].P1;
avg.P2 += mPowermeterBuffer[group][i].P2;
avg.P3 += mPowermeterBuffer[group][i].P3;
} }
avg.P = avg.P / 5;
avg.P1 = avg.P1 / 5;
avg.P2 = avg.P2 / 5;
avg.P3 = avg.P3 / 5;
return result; return avg;
} }
private: private:
@ -76,23 +108,18 @@ class powermeter {
* @param group * @param group
* @returns true/false * @returns true/false
*/ */
bool getPowermeterWattsShelly(JsonObject logObj, uint8_t group) { PowermeterBuffer_t getPowermeterWattsShelly(JsonObject logObj, uint8_t group) {
bool result = false; PowermeterBuffer_t result;
result.P = result.P1 = result.P2 = result.P3 = 0;
logObj["mod"] = "getPowermeterWattsShelly"; logObj["mod"] = "getPowermeterWattsShelly";
mCfg->groups[group].pmPower = 0;
mCfg->groups[group].pmPowerL1 = 0;
mCfg->groups[group].pmPowerL2 = 0;
mCfg->groups[group].pmPowerL3 = 0;
HTTPClient http; HTTPClient http;
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
http.setUserAgent("Ahoy-Agent"); http.setUserAgent("Ahoy-Agent");
// TODO: Ahoy-0.8.850024-zero // TODO: Ahoy-0.8.850024-zero
http.setConnectTimeout(1000); http.setConnectTimeout(500);
http.setTimeout(1000); http.setTimeout(1000);
// TODO: Timeout von 1000 reduzieren?
http.addHeader("Content-Type", "application/json"); http.addHeader("Content-Type", "application/json");
http.addHeader("Accept", "application/json"); http.addHeader("Accept", "application/json");
@ -107,57 +134,48 @@ class powermeter {
DeserializationError error = deserializeJson(doc, http.getString()); DeserializationError error = deserializeJson(doc, http.getString());
if (error) { if (error) {
logObj["err"] = "deserializeJson: " + String(error.c_str()); logObj["err"] = "deserializeJson: " + String(error.c_str());
return false; return result;
} else { } else {
if (doc.containsKey(F("total_power"))) { if (doc.containsKey(F("total_power"))) {
// Shelly 3EM // Shelly 3EM
mCfg->groups[group].pmPower = doc["total_power"]; result.P = doc["total_power"];
result = true;
} else if (doc.containsKey(F("em:0"))) { } else if (doc.containsKey(F("em:0"))) {
// Shelly pro 3EM // Shelly pro 3EM
mCfg->groups[group].pmPower = doc["em:0"]["total_act_power"]; result.P = doc["em:0"]["total_act_power"];
result = true;
} else { } else {
// Keine Daten // Keine Daten
mCfg->groups[group].pmPower = 0; result.P = 0;
} }
if (doc.containsKey(F("emeters"))) { if (doc.containsKey(F("emeters"))) {
// Shelly 3EM // Shelly 3EM
mCfg->groups[group].pmPowerL1 = doc["emeters"][0]["power"]; result.P1 = doc["emeters"][0]["power"];
result = true;
} else if (doc.containsKey(F("em:0"))) { } else if (doc.containsKey(F("em:0"))) {
// Shelly pro 3EM // Shelly pro 3EM
mCfg->groups[group].pmPowerL1 = doc["em:0"]["a_act_power"]; result.P1 = doc["em:0"]["a_act_power"];
result = true;
} else if (doc.containsKey(F("switch:0"))) { } else if (doc.containsKey(F("switch:0"))) {
// Shelly plus1pm plus2pm // Shelly plus1pm plus2pm
mCfg->groups[group].pmPowerL1 = doc["switch:0"]["apower"]; result.P1 = doc["switch:0"]["apower"];
mCfg->groups[group].pmPower += mCfg->groups[group].pmPowerL1; result.P += result.P1;
result = true;
} else if (doc.containsKey(F("apower"))) { } else if (doc.containsKey(F("apower"))) {
// Shelly Alternative // Shelly Alternative
mCfg->groups[group].pmPowerL1 = doc["apower"]; result.P1 = doc["apower"];
mCfg->groups[group].pmPower += mCfg->groups[group].pmPowerL1; result.P += result.P1;
result = true;
} else { } else {
// Keine Daten // Keine Daten
mCfg->groups[group].pmPowerL1 = 0; result.P1 = 0;
} }
if (doc.containsKey(F("emeters"))) { if (doc.containsKey(F("emeters"))) {
// Shelly 3EM // Shelly 3EM
mCfg->groups[group].pmPowerL2 = doc["emeters"][1]["power"]; result.P2 = doc["emeters"][1]["power"];
result = true;
} else if (doc.containsKey(F("em:0"))) { } else if (doc.containsKey(F("em:0"))) {
// Shelly pro 3EM // Shelly pro 3EM
mCfg->groups[group].pmPowerL2 = doc["em:0"]["b_act_power"]; result.P2 = doc["em:0"]["b_act_power"];
result = true;
} else if (doc.containsKey(F("switch:1"))) { } else if (doc.containsKey(F("switch:1"))) {
// Shelly plus1pm plus2pm // Shelly plus1pm plus2pm
mCfg->groups[group].pmPowerL2 = doc["switch.1"]["apower"]; result.P2 = doc["switch.1"]["apower"];
mCfg->groups[group].pmPower += mCfg->groups[group].pmPowerL2; result.P += result.P2;
result = true;
//} else if (doc.containsKey(F("apower"))) { //} else if (doc.containsKey(F("apower"))) {
// Shelly Alternative // Shelly Alternative
// mCfg->groups[group].pmPowerL2 = doc["apower"]; // mCfg->groups[group].pmPowerL2 = doc["apower"];
@ -165,22 +183,19 @@ class powermeter {
// ret = true; // ret = true;
} else { } else {
// Keine Daten // Keine Daten
mCfg->groups[group].pmPowerL2 = 0; result.P2 = 0;
} }
if (doc.containsKey(F("emeters"))) { if (doc.containsKey(F("emeters"))) {
// Shelly 3EM // Shelly 3EM
mCfg->groups[group].pmPowerL3 = doc["emeters"][2]["power"]; result.P3 = doc["emeters"][2]["power"];
result = true;
} else if (doc.containsKey(F("em:0"))) { } else if (doc.containsKey(F("em:0"))) {
// Shelly pro 3EM // Shelly pro 3EM
mCfg->groups[group].pmPowerL3 = doc["em:0"]["c_act_power"]; result.P3 = doc["em:0"]["c_act_power"];
result = true;
} else if (doc.containsKey(F("switch:2"))) { } else if (doc.containsKey(F("switch:2"))) {
// Shelly plus1pm plus2pm // Shelly plus1pm plus2pm
mCfg->groups[group].pmPowerL3 = doc["switch:2"]["apower"]; result.P3 = doc["switch:2"]["apower"];
mCfg->groups[group].pmPower += mCfg->groups[group].pmPowerL3; result.P += result.P3;
result = true;
//} else if (doc.containsKey(F("apower"))) { //} else if (doc.containsKey(F("apower"))) {
// Shelly Alternative // Shelly Alternative
// mCfg->groups[group].pmPowerL3 = doc["apower"]; // mCfg->groups[group].pmPowerL3 = doc["apower"];
@ -188,17 +203,11 @@ class powermeter {
// result = true; // result = true;
} else { } else {
// Keine Daten // Keine Daten
mCfg->groups[group].pmPowerL3 = 0; result.P3 = 0;
} }
} }
} }
http.end(); http.end();
logObj["P"] = mCfg->groups[group].pmPower;
logObj["P1"] = mCfg->groups[group].pmPowerL1;
logObj["P2"] = mCfg->groups[group].pmPowerL2;
logObj["P3"] = mCfg->groups[group].pmPowerL3;
return result; return result;
} }
@ -250,17 +259,11 @@ class powermeter {
* } * }
* } * }
*/ */
bool getPowermeterWattsTasmota(JsonObject logObj, uint8_t group) { PowermeterBuffer_t getPowermeterWattsTasmota(JsonObject logObj, uint8_t group) {
bool result = false; PowermeterBuffer_t result;
result.P = result.P1 = result.P2 = result.P3 = 0;
logObj["mod"] = "getPowermeterWattsTasmota"; logObj["mod"] = "getPowermeterWattsTasmota";
mCfg->groups[group].pmPower = 0;
mCfg->groups[group].pmPowerL1 = 0;
mCfg->groups[group].pmPowerL2 = 0;
mCfg->groups[group].pmPowerL3 = 0;
result = true;
/* /*
// TODO: nicht komplett // TODO: nicht komplett
@ -329,28 +332,18 @@ class powermeter {
* @param group * @param group
* @returns true/false * @returns true/false
*/ */
bool getPowermeterWattsMqtt(JsonObject logObj, uint8_t group) { PowermeterBuffer_t getPowermeterWattsMqtt(JsonObject logObj, uint8_t group) {
bool result = false; PowermeterBuffer_t result;
result.P = result.P1 = result.P2 = result.P3 = 0;
logObj["mod"] = "getPowermeterWattsMqtt"; logObj["mod"] = "getPowermeterWattsMqtt";
mCfg->groups[group].pmPower = 0;
mCfg->groups[group].pmPowerL1 = 0;
mCfg->groups[group].pmPowerL2 = 0;
mCfg->groups[group].pmPowerL3 = 0;
// Hier neuer Code - Anfang // Hier neuer Code - Anfang
// TODO: Noch nicht komplett
result = true; // TODO: Noch nicht komplett
// Hier neuer Code - Ende // Hier neuer Code - Ende
logObj["P"] = mCfg->groups[group].pmPower;
logObj["P1"] = mCfg->groups[group].pmPowerL1;
logObj["P2"] = mCfg->groups[group].pmPowerL2;
logObj["P3"] = mCfg->groups[group].pmPowerL3;
return result; return result;
} }
@ -360,28 +353,18 @@ class powermeter {
* @param group * @param group
* @returns true/false * @returns true/false
*/ */
bool getPowermeterWattsHichi(JsonObject logObj, uint8_t group) { PowermeterBuffer_t getPowermeterWattsHichi(JsonObject logObj, uint8_t group) {
bool result = false; PowermeterBuffer_t result;
result.P = result.P1 = result.P2 = result.P3 = 0;
logObj["mod"] = "getPowermeterWattsHichi"; logObj["mod"] = "getPowermeterWattsHichi";
mCfg->groups[group].pmPower = 0;
mCfg->groups[group].pmPowerL1 = 0;
mCfg->groups[group].pmPowerL2 = 0;
mCfg->groups[group].pmPowerL3 = 0;
// Hier neuer Code - Anfang // Hier neuer Code - Anfang
// TODO: Noch nicht komplett
result = true; // TODO: Noch nicht komplett
// Hier neuer Code - Ende // Hier neuer Code - Ende
logObj["P"] = mCfg->groups[group].pmPower;
logObj["P1"] = mCfg->groups[group].pmPowerL1;
logObj["P2"] = mCfg->groups[group].pmPowerL2;
logObj["P3"] = mCfg->groups[group].pmPowerL3;
return result; return result;
} }
@ -391,6 +374,7 @@ class powermeter {
* @param group * @param group
* @returns true/false * @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: 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!
*/ */
sml_states_t currentState; sml_states_t currentState;
@ -415,7 +399,6 @@ class powermeter {
07 01 00 02 08 01 ff #objName: OBIS-Kennzahl für Wirkenergie Einspeisung Tarif1 07 01 00 02 08 01 ff #objName: OBIS-Kennzahl für Wirkenergie Einspeisung Tarif1
07 01 00 02 08 02 ff #objName: OBIS-Kennzahl für Wirkenergie Einspeisung Tarif2 07 01 00 02 08 02 ff #objName: OBIS-Kennzahl für Wirkenergie Einspeisung Tarif2
*/ */
const std::list<OBISHandler> smlHandlerList{ const std::list<OBISHandler> smlHandlerList{
{{0x01, 0x00, 0x10, 0x07, 0x00, 0xff}, &smlOBISW, &_powerMeterTotal}, // total - OBIS-Kennzahl für momentane Gesamtwirkleistung {{0x01, 0x00, 0x10, 0x07, 0x00, 0xff}, &smlOBISW, &_powerMeterTotal}, // total - OBIS-Kennzahl für momentane Gesamtwirkleistung
@ -426,18 +409,19 @@ class powermeter {
{{0x01, 0x00, 0x01, 0x08, 0x00, 0xff}, &smlOBISWh, &_powerMeterImport}, {{0x01, 0x00, 0x01, 0x08, 0x00, 0xff}, &smlOBISWh, &_powerMeterImport},
{{0x01, 0x00, 0x02, 0x08, 0x00, 0xff}, &smlOBISWh, &_powerMeterExport}}; {{0x01, 0x00, 0x02, 0x08, 0x00, 0xff}, &smlOBISWh, &_powerMeterExport}};
bool getPowermeterWattsTibber(JsonObject logObj, uint8_t group) { PowermeterBuffer_t getPowermeterWattsTibber(JsonObject logObj, uint8_t group) {
bool result = false; mPreviousTsp = mPreviousTsp + 2000; // Zusätzliche Pause
PowermeterBuffer_t result;
result.P = result.P1 = result.P2 = result.P3 = 0;
mCfg->groups[group].pmPower = 0; logObj["mod"] = "getPowermeterWattsTibber";
mCfg->groups[group].pmPowerL1 = 0;
mCfg->groups[group].pmPowerL2 = 0;
mCfg->groups[group].pmPowerL3 = 0;
HTTPClient http; HTTPClient http;
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
http.setUserAgent("Ahoy-Agent"); http.setUserAgent("Ahoy-Agent");
http.setConnectTimeout(1000); // TODO: Ahoy-0.8.850024-zero
http.setConnectTimeout(500);
http.setTimeout(1000); http.setTimeout(1000);
http.addHeader("Content-Type", "application/json"); http.addHeader("Content-Type", "application/json");
http.addHeader("Accept", "application/json"); http.addHeader("Accept", "application/json");
@ -448,35 +432,25 @@ class powermeter {
http.begin(url); http.begin(url);
http.addHeader("Authorization", "Basic " + auth); http.addHeader("Authorization", "Basic " + auth);
if (http.GET() == HTTP_CODE_OK) { if (http.GET() == HTTP_CODE_OK && http.getSize() > 0) {
String myString = http.getString(); String myString = http.getString();
char floatBuffer[20];
double readVal = 0; double readVal = 0;
unsigned char c; unsigned char c;
for (int i = 0; i < http.getSize(); ++i) { for (int i = 0; i < http.getSize(); ++i) {
c = myString[i]; c = myString[i];
sml_states_t smlCurrentState = smlState(c); sml_states_t smlCurrentState = smlState(c);
switch (smlCurrentState) { switch (smlCurrentState) {
case SML_FINAL: case SML_FINAL:
mCfg->groups[group].pmPower = _powerMeterTotal; result.P = _powerMeterTotal;
result.P1 = _powerMeter1Power;
mCfg->groups[group].pmPowerL1 = _powerMeter1Power; result.P2 = _powerMeter2Power;
mCfg->groups[group].pmPowerL2 = _powerMeter2Power; result.P3 = _powerMeter3Power;
mCfg->groups[group].pmPowerL3 = _powerMeter3Power;
if(! (_powerMeter1Power && _powerMeter2Power && _powerMeter3Power)) if(! (_powerMeter1Power && _powerMeter2Power && _powerMeter3Power)) {
{ result.P1 = result.P2 = result.P3 = _powerMeterTotal / 3;
mCfg->groups[group].pmPowerL1 = _powerMeterTotal / 3;
mCfg->groups[group].pmPowerL2 = _powerMeterTotal / 3;
mCfg->groups[group].pmPowerL3 = _powerMeterTotal / 3;
} }
// TODO: Ein return an dieser Stelle verhindert das ordnungsgemäße http.end()
result = true;
// return true;
break; break;
case SML_LISTEND: case SML_LISTEND:
// check handlers on last received list // check handlers on last received list
@ -490,18 +464,25 @@ class powermeter {
} }
} }
} }
http.end();
logObj["P"] = mCfg->groups[group].pmPower;
logObj["P1"] = mCfg->groups[group].pmPowerL1;
logObj["P2"] = mCfg->groups[group].pmPowerL2;
logObj["P3"] = mCfg->groups[group].pmPowerL3;
http.end();
return result; return result;
} }
private: void bufferWrite(PowermeterBuffer_t raw, short group)
{
mPowermeterBuffer[group][mPowermeterBufferPos[group]] = raw;
mPowermeterBufferPos[group]++;
if(mPowermeterBufferPos[group] >= 5) mPowermeterBufferPos[group] = 0;
}
zeroExport_t *mCfg; zeroExport_t *mCfg;
JsonObject *mLog;
unsigned long mPreviousTsp = 0;
PowermeterBuffer_t mPowermeterBuffer[ZEROEXPORT_MAX_GROUPS][5] = { 0 };
short mPowermeterBufferPos[ZEROEXPORT_MAX_GROUPS] = { 0 };
}; };
// TODO: Vorlagen für Powermeter-Analyse // TODO: Vorlagen für Powermeter-Analyse

1623
src/plugins/zeroExport/zeroExport.h

File diff suppressed because it is too large

1
src/publisher/pubMqtt.h

@ -311,6 +311,7 @@ class PubMqtt {
DynamicJsonDocument json(128); DynamicJsonDocument json(128);
JsonObject root = json.to<JsonObject>(); JsonObject root = json.to<JsonObject>();
root["topic"] = String(topic);
bool limitAbs = false; bool limitAbs = false;
if(len > 0) { if(len > 0) {

2
src/web/RestApi.h

@ -1158,9 +1158,7 @@ class RestApi {
mConfig->plugin.zeroExport.groups[group].Ki = jsonIn[F("Ki")]; mConfig->plugin.zeroExport.groups[group].Ki = jsonIn[F("Ki")];
mConfig->plugin.zeroExport.groups[group].Kd = jsonIn[F("Kd")]; mConfig->plugin.zeroExport.groups[group].Kd = jsonIn[F("Kd")];
// Global // Global
mConfig->plugin.zeroExport.groups[group].stateLast = zeroExportState::INIT;
mConfig->plugin.zeroExport.groups[group].state = zeroExportState::INIT; mConfig->plugin.zeroExport.groups[group].state = zeroExportState::INIT;
mConfig->plugin.zeroExport.groups[group].stateNext = zeroExportState::INIT;
mApp->saveSettings(false); // without reboot mApp->saveSettings(false); // without reboot
} }
#endif #endif

Loading…
Cancel
Save