Browse Source

0.8.1030008

pull/1615/head
Patrick Amrhein 9 months ago
parent
commit
06b34b16c4
  1. 3
      src/config/settings.h
  2. 2
      src/defines.h
  3. 51
      src/plugins/zeroExport/powermeter.h
  4. 91
      src/plugins/zeroExport/zeroExport.h

3
src/config/settings.h

@ -265,6 +265,8 @@ typedef struct {
// //
zeroExportAction_t action; zeroExportAction_t action;
int8_t actionTimer;
unsigned long actionTimestamp;
uint16_t power; uint16_t power;
uint16_t MaxPower; uint16_t MaxPower;
int32_t limit; int32_t limit;
@ -682,6 +684,7 @@ class settings {
// //
mCfg.plugin.zeroExport.groups[group].inverters[inv].waitAck = 0; mCfg.plugin.zeroExport.groups[group].inverters[inv].waitAck = 0;
mCfg.plugin.zeroExport.groups[group].inverters[inv].action = zeroExportAction_t::doNone; mCfg.plugin.zeroExport.groups[group].inverters[inv].action = zeroExportAction_t::doNone;
mCfg.plugin.zeroExport.groups[group].inverters[inv].actionTimer = 0;;
mCfg.plugin.zeroExport.groups[group].inverters[inv].dcVoltage = 0; mCfg.plugin.zeroExport.groups[group].inverters[inv].dcVoltage = 0;
mCfg.plugin.zeroExport.groups[group].inverters[inv].limit = 0; mCfg.plugin.zeroExport.groups[group].inverters[inv].limit = 0;
mCfg.plugin.zeroExport.groups[group].inverters[inv].limitNew = 0; mCfg.plugin.zeroExport.groups[group].inverters[inv].limitNew = 0;

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 1030007 #define VERSION_PATCH 1030008
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {
uint8_t ch; uint8_t ch;

51
src/plugins/zeroExport/powermeter.h

@ -109,6 +109,8 @@ class powermeter {
#endif #endif
} }
if ((power.P == 0) and (power.P1 == 0) && (power.P2 == 0) && (power.P3 == 0)) return;
bufferWrite(power, group); bufferWrite(power, group);
// MQTT - Powermeter // MQTT - Powermeter
@ -153,6 +155,19 @@ class powermeter {
* *
*/ */
void onMqttConnect(void) { void onMqttConnect(void) {
#if defined(ZEROEXPORT_POWERMETER_MQTT)
for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
if (mCfg->groups[group].pm_type == zeroExportPowermeterType_t::Mqtt) {
// if (String(mCfg->groups[group].pm_jsonPath) == "") return;
mMqtt->subscribe(String(mCfg->groups[group].pm_jsonPath).c_str(), QOS_2);
}
}
#endif /*defined(ZEROEXPORT_POWERMETER_MQTT)*/
} }
/** /**
@ -163,17 +178,39 @@ class powermeter {
#if defined(ZEROEXPORT_POWERMETER_MQTT) #if defined(ZEROEXPORT_POWERMETER_MQTT)
// topic for powermeter? // topic for powermeter?
for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) { // for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
if (mCfg->groups[group].pm_type == zeroExportPowermeterType_t::Mqtt) { // if (mCfg->groups[group].pm_type == zeroExportPowermeterType_t::Mqtt) {
// mLog["mqttDevice"] = "topicInverter"; // // mLog["mqttDevice"] = "topicInverter";
if (!topic.equals(mCfg->groups[group].pm_jsonPath)) return; // if (!topic.equals(mCfg->groups[group].pm_jsonPath)) return;
mCfg->groups[group].pm_P = (int32_t)obj["val"]; // mCfg->groups[group].pm_P = (int32_t)obj["val"];
} // }
} // }
#endif /*defined(ZEROEXPORT_POWERMETER_MQTT)*/ #endif /*defined(ZEROEXPORT_POWERMETER_MQTT)*/
} }
private: private:
/** mqttSubscribe
* when a MQTT Msg is needed to subscribe, then a publish is leading
* @param gr
* @param payload
* @returns void
*/
void mqttSubscribe(String gr, String payload) {
// mqttPublish(gr, payload);
mMqtt->subscribe(gr.c_str(), QOS_2);
}
/** mqttPublish
* when a MQTT Msg is needed to Publish, but not to subscribe.
* @param gr
* @param payload
* @param retain
* @returns void
*/
void mqttPublish(String gr, String payload, bool retain = false) {
mMqtt->publish(gr.c_str(), payload.c_str(), retain);
}
HTTPClient http; HTTPClient http;
zeroExport_t *mCfg; zeroExport_t *mCfg;

91
src/plugins/zeroExport/zeroExport.h

@ -239,35 +239,35 @@ class ZeroExport {
// Regelbegrenzung // Regelbegrenzung
// TODO: Hier könnte man den maximalen Sprung begrenzen // TODO: Hier könnte man den maximalen Sprung begrenzen
// Keine Regelung wenn Maximalleistung des Inverters unbekannt ist
if (CfgGroupInv->MaxPower == 0) {
y = 0;
mLog["yK"] = y;
}
// Stellgröße y in W // Stellgröße y in W
CfgGroupInv->limitNew += y; CfgGroupInv->limitNew += y;
// Check // Check
if (CfgGroupInv->action == zeroExportAction_t::doNone) { if (CfgGroupInv->action == zeroExportAction_t::doNone) {
// if ((CfgGroup->battSwitch == true) && (CfgGroupInv->limitNew > CfgGroupInv->powerMin) && (CfgGroupInv->power == 0) && (mCfg->sleep != true) && (CfgGroup->sleep != true)) { if ((CfgGroup->battSwitch == true) && (CfgGroupInv->limitNew > CfgGroupInv->powerMin) && (CfgGroupInv->power == 0) && (mCfg->sleep != true) && (CfgGroup->sleep != true)) {
// TODO: Schlägt fehl, weil wenn MaxPower = 0 wird y auf 0 gesetzt und damit ist limitNew = powerMin if (CfgGroupInv->actionTimer < 0) CfgGroupInv->actionTimer = 0;
if ((CfgGroup->battSwitch == true) && (CfgGroupInv->power == 0) && (mCfg->sleep != true) && (CfgGroup->sleep != true)) { if (CfgGroupInv->actionTimer == 0) CfgGroupInv->actionTimer = 1;
CfgGroupInv->action = zeroExportAction_t::doTurnOn; if (CfgGroupInv->actionTimer > 10) {
mLog["do"] = "doTurnOn"; CfgGroupInv->action = zeroExportAction_t::doTurnOn;
mLog["do"] = "doTurnOn";
}
} }
// TODO: hier kommt eine CheckBox je Gruppe rein, die es verhindert, dass Inv ausgeschaltet werden.
if (((CfgGroup->battSwitch == false) || (CfgGroupInv->limitNew < 0)) && (CfgGroupInv->power > 0)) { if ((CfgGroupInv->limitNew <= 0) && (CfgGroupInv->power > 0)) {
CfgGroupInv->action = zeroExportAction_t::doTurnOff; if (CfgGroupInv->actionTimer > 0) CfgGroupInv->actionTimer = 0;
mLog["do"] = "doTurnOff"; if (CfgGroupInv->actionTimer == 0) CfgGroupInv->actionTimer = -1;
if (CfgGroupInv->actionTimer < 30) {
CfgGroupInv->action = zeroExportAction_t::doTurnOff;
mLog["do"] = "doTurnOff";
}
} }
if (((CfgGroup->battSwitch == false) || (mCfg->sleep == true) || (CfgGroup->sleep == true)) && (CfgGroupInv->power > 0)) {
if (((mCfg->sleep == true) || (CfgGroup->sleep == true)) && (CfgGroupInv->power > 0)) {
CfgGroupInv->action = zeroExportAction_t::doTurnOff; CfgGroupInv->action = zeroExportAction_t::doTurnOff;
mLog["do"] = "sleep"; mLog["do"] = "sleep";
} }
} }
mLog["doT"] = CfgGroupInv->action;
if (CfgGroupInv->action == zeroExportAction_t::doNone) { if (CfgGroupInv->action == zeroExportAction_t::doNone) {
mLog["l"] = CfgGroupInv->limit; mLog["l"] = CfgGroupInv->limit;
@ -302,6 +302,16 @@ class ZeroExport {
if (CfgGroupInv->limit != CfgGroupInv->limitNew) CfgGroupInv->action = zeroExportAction_t::doActivePowerContr; if (CfgGroupInv->limit != CfgGroupInv->limitNew) CfgGroupInv->action = zeroExportAction_t::doActivePowerContr;
if ((CfgGroupInv->limit == powerMin) && (CfgGroupInv->power == 0)) {
CfgGroupInv->action = zeroExportAction_t::doNone;
if (!mCfg->debug) {
clearLog();
return;
}
}
// CfgGroupInv->actionTimer = 0;
// TODO: Timer stoppen wenn Limit gesetzt wird.
mLog["lN"] = CfgGroupInv->limitNew; mLog["lN"] = CfgGroupInv->limitNew;
CfgGroupInv->limit = CfgGroupInv->limitNew; CfgGroupInv->limit = CfgGroupInv->limitNew;
@ -316,6 +326,8 @@ class ZeroExport {
mApp->triggerTickSend(iv->id); mApp->triggerTickSend(iv->id);
CfgGroupInv->waitAck = 120; CfgGroupInv->waitAck = 120;
CfgGroupInv->action = zeroExportAction_t::doNone; CfgGroupInv->action = zeroExportAction_t::doNone;
CfgGroupInv->actionTimer = 0;
CfgGroupInv->actionTimestamp = Tsp;
} }
break; break;
case zeroExportAction_t::doTurnOn: case zeroExportAction_t::doTurnOn:
@ -323,6 +335,8 @@ class ZeroExport {
mApp->triggerTickSend(iv->id); mApp->triggerTickSend(iv->id);
CfgGroupInv->waitAck = 120; CfgGroupInv->waitAck = 120;
CfgGroupInv->action = zeroExportAction_t::doNone; CfgGroupInv->action = zeroExportAction_t::doNone;
CfgGroupInv->actionTimer = 0;
CfgGroupInv->actionTimestamp = Tsp;
} }
break; break;
case zeroExportAction_t::doTurnOff: case zeroExportAction_t::doTurnOff:
@ -330,20 +344,19 @@ class ZeroExport {
mApp->triggerTickSend(iv->id); mApp->triggerTickSend(iv->id);
CfgGroupInv->waitAck = 120; CfgGroupInv->waitAck = 120;
CfgGroupInv->action = zeroExportAction_t::doNone; CfgGroupInv->action = zeroExportAction_t::doNone;
CfgGroupInv->actionTimer = 0;
CfgGroupInv->actionTimestamp = Tsp;
} }
break; break;
case zeroExportAction_t::doActivePowerContr: case zeroExportAction_t::doActivePowerContr:
if ((CfgGroupInv->limit <= CfgGroupInv->powerMin) && (CfgGroupInv->power == 0)) {
clearLog();
return;
}
iv->powerLimit[0] = static_cast<uint16_t>(CfgGroupInv->limit * 10.0); iv->powerLimit[0] = static_cast<uint16_t>(CfgGroupInv->limit * 10.0);
iv->powerLimit[1] = AbsolutNonPersistent; iv->powerLimit[1] = AbsolutNonPersistent;
if (iv->setDevControlRequest(ActivePowerContr)) { if (iv->setDevControlRequest(ActivePowerContr)) {
mApp->triggerTickSend(iv->id); mApp->triggerTickSend(iv->id);
CfgGroupInv->waitAck = 60; CfgGroupInv->waitAck = 60;
CfgGroupInv->action = zeroExportAction_t::doNone; CfgGroupInv->action = zeroExportAction_t::doNone;
CfgGroupInv->actionTimer = 0;
CfgGroupInv->actionTimestamp = Tsp;
} }
break; break;
default: default:
@ -382,6 +395,9 @@ class ZeroExport {
if (mCfg->groups[group].inverters[inv].waitAck > 0) { if (mCfg->groups[group].inverters[inv].waitAck > 0) {
mCfg->groups[group].inverters[inv].waitAck--; mCfg->groups[group].inverters[inv].waitAck--;
} }
if (mCfg->groups[group].inverters[inv].actionTimer > 0) mCfg->groups[group].inverters[inv].actionTimer++;
if (mCfg->groups[group].inverters[inv].actionTimer < 0) mCfg->groups[group].inverters[inv].actionTimer--;
} }
} }
} }
@ -537,6 +553,28 @@ class ZeroExport {
CfgGroupInv->dcVoltage = iv->getChannelFieldValue(CH1, FLD_UDC, rec); CfgGroupInv->dcVoltage = iv->getChannelFieldValue(CH1, FLD_UDC, rec);
mLog["bU"] = ah::round1(CfgGroupInv->dcVoltage); mLog["bU"] = ah::round1(CfgGroupInv->dcVoltage);
// Fallschirm 2: Für nicht übernommene Limits bzw. nicht regelnde Inverter
// Bisher ist nicht geklärt ob der Inverter das Limit bestätigt hat
// Erstmalig aufgetreten bei @knickohr am 28.04.2024 ... l=300 pM=300, p=9
if (CfgGroupInv->MaxPower > 0) {
uint16_t limitPercent = 100 / CfgGroupInv->MaxPower * CfgGroupInv->limit;
uint16_t powerPercent = 100 / CfgGroupInv->MaxPower * CfgGroupInv->power;
uint16_t delta = abs(limitPercent - powerPercent);
if ((delta > 10) && (CfgGroupInv->power > 0)) {
mLog["delta"] = delta;
unsigned long delay = iv->getLastTs(rec) - CfgGroupInv->actionTimestamp;
mLog["delay"] = delay;
if (delay > 30000) {
CfgGroupInv->action = zeroExportAction_t::doActivePowerContr;
mLog["do"] = "doActivePowerContr";
}
if (delay > 60000) {
CfgGroupInv->action = zeroExportAction_t::doRestart;
mLog["do"] = "doRestart";
}
}
}
} }
zeroExportQueue_t Entry; zeroExportQueue_t Entry;
@ -560,6 +598,12 @@ class ZeroExport {
*/ */
void onMqttConnect(void) { void onMqttConnect(void) {
mPowermeter.onMqttConnect(); mPowermeter.onMqttConnect();
for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
// if (String(mCfg->groups[group].battSoC) == "") return;
mMqtt->subscribe(String(mCfg->groups[group].battSoC).c_str(), QOS_2);
}
} }
/** onMqttMessage /** onMqttMessage
@ -570,6 +614,9 @@ class ZeroExport {
void onMqttMessage(JsonObject obj) { void onMqttMessage(JsonObject obj) {
if (!mIsInitialized) return; if (!mIsInitialized) return;
if (mCfg->debug) mLog["d"] = obj;
sendLog();
clearLog();
mPowermeter.onMqttMessage(obj); mPowermeter.onMqttMessage(obj);
String topic = String(obj["topic"]); String topic = String(obj["topic"]);

Loading…
Cancel
Save