Browse Source

ZE Bugfix

pull/1581/head
Patrick Amrhein 6 months ago
parent
commit
19f991c7a9
  1. 6
      src/config/settings.h
  2. 257
      src/plugins/zeroExport/zeroExport.h

6
src/config/settings.h

@ -279,7 +279,7 @@ typedef struct {
// //
int8_t doReboot; int8_t doReboot;
int8_t doPower; int8_t doPower;
bool doLimit; int8_t doLimit;
} zeroExportGroupInverter_t; } zeroExportGroupInverter_t;
typedef struct { typedef struct {
@ -713,9 +713,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].doReboot = -1;
mCfg.plugin.zeroExport.groups[group].inverters[inv].doPower = -1; mCfg.plugin.zeroExport.groups[group].inverters[inv].doPower = -1;
mCfg.plugin.zeroExport.groups[group].inverters[inv].doLimit = false; mCfg.plugin.zeroExport.groups[group].inverters[inv].doLimit = -1;
} }
// Battery // Battery
mCfg.plugin.zeroExport.groups[group].battEnabled = false; mCfg.plugin.zeroExport.groups[group].battEnabled = false;

257
src/plugins/zeroExport/zeroExport.h

@ -63,7 +63,7 @@ class ZeroExport {
unsigned long Tsp = millis(); unsigned long Tsp = millis();
mPowermeter.loop(&Tsp, &DoLog); mPowermeter.loop(&Tsp, &DoLog);
if (DoLog) sendLog(); // if (DoLog) sendLog();
clearLog(); clearLog();
DoLog = false; DoLog = false;
@ -247,7 +247,7 @@ class ZeroExport {
// Select all Inverter to reboot // Select all Inverter to reboot
for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) { for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
for (uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) { for (uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) {
mCfg->groups[group].inverters[inv].doReboot = true; // mCfg->groups[group].inverters[inv].doReboot = 1;
} }
} }
} }
@ -261,16 +261,26 @@ class ZeroExport {
if ((!mIsInitialized) || (!mCfg->enabled)) return; if ((!mIsInitialized) || (!mCfg->enabled)) return;
for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) { for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
for (uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) { bool DoLog = false;
if (iv->id == (uint8_t)mCfg->groups[group].inverters[inv].id) {
unsigned long bTsp = millis(); unsigned long bTsp = millis();
mLog["t"] = "resetWaitLimitAck";
mLog["g"] = group; mLog["g"] = group;
mLog["i"] = inv; mLog["t"] = "resetWaitLimitAck";
mLog["id"] = iv->id;
JsonArray logArr = mLog.createNestedArray("ix");
for (uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) {
if (iv->id == (uint8_t)mCfg->groups[group].inverters[inv].id) {
JsonObject logObj = logArr.createNestedObject();
logObj["i"] = inv;
logObj["id"] = iv->id;
mCfg->groups[group].inverters[inv].waitLimitAck = 0; mCfg->groups[group].inverters[inv].waitLimitAck = 0;
mLog["w"] = 0; logObj["wL"] = mCfg->groups[group].inverters[inv].waitLimitAck;
DoLog = true;
}
}
if (mCfg->debug) { if (mCfg->debug) {
unsigned long eTsp = millis(); unsigned long eTsp = millis();
@ -278,11 +288,10 @@ class ZeroExport {
mLog["E"] = eTsp; mLog["E"] = eTsp;
mLog["D"] = eTsp - bTsp; mLog["D"] = eTsp - bTsp;
} }
sendLog();
if(DoLog) sendLog();
clearLog(); clearLog();
return; DoLog = false;
}
}
} }
} }
@ -295,16 +304,26 @@ class ZeroExport {
if ((!mIsInitialized) || (!mCfg->enabled)) return; if ((!mIsInitialized) || (!mCfg->enabled)) return;
for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) { for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
for (uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) { bool DoLog = false;
if (iv->id == mCfg->groups[group].inverters[inv].id) {
unsigned long bTsp = millis(); unsigned long bTsp = millis();
mLog["t"] = "resetWaitPowerAck";
mLog["g"] = group; mLog["g"] = group;
mLog["i"] = inv; mLog["t"] = "resetWaitPowerAck";
mLog["id"] = iv->id;
JsonArray logArr = mLog.createNestedArray("ix");
for (uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) {
if (iv->id == mCfg->groups[group].inverters[inv].id) {
JsonObject logObj = logArr.createNestedObject();
logObj["i"] = inv;
logObj["id"] = iv->id;
mCfg->groups[group].inverters[inv].waitPowerAck = 30; mCfg->groups[group].inverters[inv].waitPowerAck = 30;
mLog["w"] = 30; logObj["wP"] = mCfg->groups[group].inverters[inv].waitPowerAck;
DoLog = true;
}
}
if (mCfg->debug) { if (mCfg->debug) {
unsigned long eTsp = millis(); unsigned long eTsp = millis();
@ -312,11 +331,10 @@ class ZeroExport {
mLog["E"] = eTsp; mLog["E"] = eTsp;
mLog["D"] = eTsp - bTsp; mLog["D"] = eTsp - bTsp;
} }
sendLog();
if(DoLog) sendLog();
clearLog(); clearLog();
return; DoLog = false;
}
}
} }
} }
@ -329,16 +347,26 @@ class ZeroExport {
if ((!mIsInitialized) || (!mCfg->enabled)) return; if ((!mIsInitialized) || (!mCfg->enabled)) return;
for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) { for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
for (uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) { bool DoLog = false;
if (iv->id == mCfg->groups[group].inverters[inv].id) {
unsigned long bTsp = millis(); unsigned long bTsp = millis();
mLog["t"] = "resetWaitRebootAck";
mLog["g"] = group; mLog["g"] = group;
mLog["i"] = inv; mLog["t"] = "resetWaitRebootAck";
mLog["id"] = iv->id;
JsonArray logArr = mLog.createNestedArray("ix");
for (uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) {
if (iv->id == mCfg->groups[group].inverters[inv].id) {
JsonObject logObj = logArr.createNestedObject();
logObj["i"] = inv;
logObj["id"] = iv->id;
mCfg->groups[group].inverters[inv].waitRebootAck = 30; mCfg->groups[group].inverters[inv].waitRebootAck = 30;
mLog["w"] = 30; logObj["wR"] = mCfg->groups[group].inverters[inv].waitRebootAck;
DoLog = true;
}
}
if (mCfg->debug) { if (mCfg->debug) {
unsigned long eTsp = millis(); unsigned long eTsp = millis();
@ -346,11 +374,10 @@ class ZeroExport {
mLog["E"] = eTsp; mLog["E"] = eTsp;
mLog["D"] = eTsp - bTsp; mLog["D"] = eTsp - bTsp;
} }
sendLog();
if(DoLog) sendLog();
clearLog(); clearLog();
return; DoLog = false;
}
}
} }
} }
@ -1004,8 +1031,8 @@ class ZeroExport {
mLog["y3"] = y3; mLog["y3"] = y3;
bool grpTarget[7] = {false, false, false, false, false, false, false}; bool grpTarget[7] = {false, false, false, false, false, false, false};
uint8_t ivId_Pmin[7] = {0, 0, 0, 0, 0, 0, 0}; int8_t ivId_Pmin[7] = {-1, -1, -1, -1, -1, -1, -1};
uint8_t ivId_Pmax[7] = {0, 0, 0, 0, 0, 0, 0}; int8_t ivId_Pmax[7] = {-1, -1, -1, -1, -1, -1, -1};
uint16_t ivPmin[7] = {65535, 65535, 65535, 65535, 65535, 65535, 65535}; uint16_t ivPmin[7] = {65535, 65535, 65535, 65535, 65535, 65535, 65535};
uint16_t ivPmax[7] = {0, 0, 0, 0, 0, 0, 0}; uint16_t ivPmax[7] = {0, 0, 0, 0, 0, 0, 0};
@ -1141,46 +1168,47 @@ class ZeroExport {
// Inverter not available -> ignore // Inverter not available -> ignore
if (!mIv[group][inv]->isAvailable()) { if (!mIv[group][inv]->isAvailable()) {
logObj["a"] = false; logObj["a"] = false;
continue;
}
logObj["dR"] = cfgGroupInv->doReboot;
logObj["wR"] = cfgGroupInv->waitRebootAck;
// Wait
if (cfgGroupInv->waitRebootAck > 0) {
result = false; result = false;
if (!mCfg->debug) *doLog = true;
continue; continue;
} }
// Reset // Reset
if ((cfgGroupInv->doReboot == 2) && (cfgGroupInv->waitRebootAck == 0)) { if ((cfgGroupInv->doReboot == 2) && (cfgGroupInv->waitRebootAck == 0)) {
/// result = false; cfgGroupInv->doReboot = -1;
cfgGroupInv->doReboot = 0; if (!mCfg->debug) {
logObj["act"] = "done"; logObj["act"] = "done";
*doLog = true;
}
continue; continue;
} }
// Calculate // Calculate
if (cfgGroupInv->doReboot == 1) { if (cfgGroupInv->doReboot == 1) {
cfgGroupInv->doReboot = 2; cfgGroupInv->doReboot = 2;
} cfgGroupInv->waitRebootAck = 120;
// Wait
if (cfgGroupInv->waitRebootAck > 0) {
logObj["w"] = cfgGroupInv->waitRebootAck;
result = false;
continue;
} }
// Inverter nothing to do -> ignore // Inverter nothing to do -> ignore
if (cfgGroupInv->doReboot == 0) { if (cfgGroupInv->doReboot == -1) {
if (!mCfg->debug) {
logObj["act"] = "nothing to do"; logObj["act"] = "nothing to do";
*doLog = true;
}
continue; continue;
} }
result = false; result = false;
*doLog = true; *doLog = true;
if (!mCfg->debug) logObj["act"] = cfgGroupInv->doReboot;
// wait for Ack
cfgGroupInv->waitRebootAck = 120;
logObj["wR"] = cfgGroupInv->waitRebootAck;
// send Command // send Command
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
JsonObject obj = doc.to<JsonObject>(); JsonObject obj = doc.to<JsonObject>();
@ -1188,7 +1216,7 @@ class ZeroExport {
obj["path"] = "ctrl"; obj["path"] = "ctrl";
obj["cmd"] = "restart"; obj["cmd"] = "restart";
mApi->ctrlRequest(obj); mApi->ctrlRequest(obj);
logObj["d"] = obj; if (!mCfg->debug) logObj["d"] = obj;
} }
return result; return result;
@ -1222,15 +1250,26 @@ class ZeroExport {
// Inverter not available -> ignore // Inverter not available -> ignore
if (!mIv[group][inv]->isAvailable()) { if (!mIv[group][inv]->isAvailable()) {
logObj["a"] = false; logObj["a"] = false;
continue;
}
logObj["dP"] = cfgGroupInv->doPower;
logObj["wP"] = cfgGroupInv->waitPowerAck;
// Wait
if (cfgGroupInv->waitPowerAck > 0) {
result = false; result = false;
if (!mCfg->debug) *doLog = true;
continue; continue;
} }
// Reset // Reset
if ((cfgGroupInv->doPower != -1) && (cfgGroupInv->waitPowerAck == 0)) { if ((cfgGroupInv->doPower != -1) && (cfgGroupInv->waitPowerAck == 0)) {
/// result = false;
cfgGroupInv->doPower = -1; cfgGroupInv->doPower = -1;
if (!mCfg->debug) {
logObj["act"] = "done"; logObj["act"] = "done";
*doLog = true;
}
continue; continue;
} }
@ -1243,7 +1282,8 @@ class ZeroExport {
(cfgGroupInv->limitNew > cfgGroupInv->powerMin) && (cfgGroupInv->limitNew > cfgGroupInv->powerMin) &&
(mIv[group][inv]->isProducing() == false)) { (mIv[group][inv]->isProducing() == false)) {
// On // On
cfgGroupInv->doPower = true; cfgGroupInv->doPower = 1;
cfgGroupInv->waitPowerAck = 120;
logObj["act"] = "on"; logObj["act"] = "on";
} }
if ( if (
@ -1252,33 +1292,23 @@ class ZeroExport {
(cfgGroupInv->limitNew < (cfgGroupInv->powerMin - 50))) && (cfgGroupInv->limitNew < (cfgGroupInv->powerMin - 50))) &&
(mIv[group][inv]->isProducing() == true)) { (mIv[group][inv]->isProducing() == true)) {
// Off // Off
cfgGroupInv->doPower = false; cfgGroupInv->doPower = 0;
cfgGroupInv->waitPowerAck = 120;
logObj["act"] = "off"; logObj["act"] = "off";
} }
// Wait // Inverter nothing to do -> ignore
if (cfgGroupInv->waitPowerAck > 0) {
logObj["w"] = cfgGroupInv->waitPowerAck;
result = false;
continue;
}
// Nothing todo
if (cfgGroupInv->doPower == -1) { if (cfgGroupInv->doPower == -1) {
if (!mCfg->debug) {
logObj["act"] = "nothing to do"; logObj["act"] = "nothing to do";
*doLog = true;
}
continue; continue;
} }
result = false; result = false;
*doLog = true; *doLog = true;
if (!mCfg->debug) logObj["act"] = cfgGroupInv->doPower;
// wait for Ack
cfgGroupInv->waitPowerAck = 120;
logObj["wP"] = cfgGroupInv->waitPowerAck;
// send Command // send Command
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
JsonObject obj = doc.to<JsonObject>(); JsonObject obj = doc.to<JsonObject>();
@ -1287,7 +1317,7 @@ class ZeroExport {
obj["path"] = "ctrl"; obj["path"] = "ctrl";
obj["cmd"] = "power"; obj["cmd"] = "power";
mApi->ctrlRequest(obj); mApi->ctrlRequest(obj);
logObj["d"] = obj; if (!mCfg->debug) logObj["d"] = obj;
} }
return result; return result;
@ -1321,15 +1351,27 @@ class ZeroExport {
// Inverter not available -> ignore // Inverter not available -> ignore
if (!mIv[group][inv]->isAvailable()) { if (!mIv[group][inv]->isAvailable()) {
logObj["a"] = false; logObj["a"] = false;
continue;
}
logObj["dL"] = cfgGroupInv->doLimit;
logObj["wL"] = cfgGroupInv->waitLimitAck;
logObj["L"] = cfgGroupInv->limit;
// Wait
if (cfgGroupInv->waitLimitAck > 0) {
result = false; result = false;
if (!mCfg->debug) *doLog = true;
continue; continue;
} }
// Reset // Reset
if ((cfgGroupInv->doLimit) && (cfgGroupInv->waitLimitAck == 0)) { if ((cfgGroupInv->doLimit != -1) && (cfgGroupInv->waitLimitAck == 0)) {
/// result = false; cfgGroupInv->doLimit = -1;
cfgGroupInv->doLimit = false; if (!mCfg->debug) {
logObj["act"] = "done"; logObj["act"] = "done";
*doLog = true;
}
continue; continue;
} }
@ -1340,23 +1382,30 @@ class ZeroExport {
cfgGroupInv->limitNew = cfgGroupInv->powerMin; cfgGroupInv->limitNew = cfgGroupInv->powerMin;
} }
// Restriction LimitNew >= Pmin // Restriction LimitNew < Pmin
if (cfgGroupInv->limitNew < cfgGroupInv->powerMin) { if (cfgGroupInv->limitNew < cfgGroupInv->powerMin) {
cfgGroupInv->limitNew = cfgGroupInv->powerMin; cfgGroupInv->limitNew = cfgGroupInv->powerMin;
} }
// Restriction LimitNew >= 2%
uint16_t power2proz = mIv[group][inv]->getMaxPower() / 100 * 2; // Restriction LimitNew < 2%
uint16_t power2proz = (mIv[group][inv]->getMaxPower() *2) / 100;
if (cfgGroupInv->limitNew < power2proz) { if (cfgGroupInv->limitNew < power2proz) {
cfgGroupInv->limitNew = power2proz; cfgGroupInv->limitNew = power2proz;
} }
// Restriction LimitNew <= Pmax // Restriction LimitNew > Pmax
if (cfgGroupInv->limitNew > cfgGroupInv->powerMax) { if (cfgGroupInv->limitNew > cfgGroupInv->powerMax) {
cfgGroupInv->limitNew = cfgGroupInv->powerMax; cfgGroupInv->limitNew = cfgGroupInv->powerMax;
} }
// Reject limit if difference < 5 W // Restriction LimitNew > 100%
/* uint16_t power100proz = mIv[group][inv]->getMaxPower();
if (cfgGroupInv->limitNew > power100proz) {
cfgGroupInv->limitNew = power100proz;
}
// Restriction deltaLimitNew < 5 W
/*
if ( if (
(cfgGroupInv->limitNew > (cfgGroupInv->powerMin + ZEROEXPORT_GROUP_WR_LIMIT_MIN_DIFF)) && (cfgGroupInv->limitNew > (cfgGroupInv->powerMin + ZEROEXPORT_GROUP_WR_LIMIT_MIN_DIFF)) &&
(cfgGroupInv->limitNew > (cfgGroupInv->limit + ZEROEXPORT_GROUP_WR_LIMIT_MIN_DIFF)) && (cfgGroupInv->limitNew > (cfgGroupInv->limit + ZEROEXPORT_GROUP_WR_LIMIT_MIN_DIFF)) &&
@ -1364,51 +1413,45 @@ class ZeroExport {
logObj["err"] = String("Diff < ") + String(ZEROEXPORT_GROUP_WR_LIMIT_MIN_DIFF) + String("W"); logObj["err"] = String("Diff < ") + String(ZEROEXPORT_GROUP_WR_LIMIT_MIN_DIFF) + String("W");
*doLog = true; *doLog = true;
return false; return false;
} }
*/ */
// Wait
if (cfgGroupInv->waitLimitAck > 0) { logObj["zeLold"] = cfgGroupInv->limit;
logObj["w"] = cfgGroupInv->waitLimitAck;
result = false; if (cfgGroupInv->limit != cfgGroupInv->limitNew) {
continue; cfgGroupInv->doLimit = 1;
cfgGroupInv->waitLimitAck = 60;
} }
// Nothing todo cfgGroupInv->limit = cfgGroupInv->limitNew;
// if (cfgGroupInv->doLimit == false) { logObj["zeL"] = cfgGroupInv->limit;
// logObj["act"] = "nothing to do";
// continue;
// }
if (cfgGroupInv->limit == cfgGroupInv->limitNew) { // Inverter nothing to do -> ignore
/// logObj["act"] = "nothing to do"; if (cfgGroupInv->doLimit == -1) {
if (!mCfg->debug) {
logObj["act"] = "nothing to do";
*doLog = true;
}
continue; continue;
} }
result = false; result = false;
*doLog = true; *doLog = true;
cfgGroupInv->doLimit = true;
if (!mCfg->debug) logObj["act"] = cfgGroupInv->doLimit;
cfgGroupInv->limit = cfgGroupInv->limitNew;
logObj["zeL"] = (uint16_t)cfgGroupInv->limit;
// wait for Ack
cfgGroupInv->waitLimitAck = 60;
logObj["wL"] = cfgGroupInv->waitLimitAck;
// send Command // send Command
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
JsonObject obj = doc.to<JsonObject>(); JsonObject obj = doc.to<JsonObject>();
obj["val"] = (uint16_t)cfgGroupInv->limit; if (cfgGroupInv->limit > 0) {
obj["val"] = cfgGroupInv->limit;
} else {
obj["val"] = 0;
}
obj["id"] = cfgGroupInv->id; obj["id"] = cfgGroupInv->id;
obj["path"] = "ctrl"; obj["path"] = "ctrl";
obj["cmd"] = "limit_nonpersistent_absolute"; obj["cmd"] = "limit_nonpersistent_absolute";
mApi->ctrlRequest(obj); mApi->ctrlRequest(obj);
logObj["d"] = obj; if (!mCfg->debug) logObj["d"] = obj;
} }
return result; return result;

Loading…
Cancel
Save