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;
int8_t actionTimer;
unsigned long actionTimestamp;
uint16_t power;
uint16_t MaxPower;
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].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].limit = 0;
mCfg.plugin.zeroExport.groups[group].inverters[inv].limitNew = 0;

2
src/defines.h

@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
#define VERSION_PATCH 1030007
#define VERSION_PATCH 1030008
//-------------------------------------
typedef struct {
uint8_t ch;

51
src/plugins/zeroExport/powermeter.h

@ -109,6 +109,8 @@ class powermeter {
#endif
}
if ((power.P == 0) and (power.P1 == 0) && (power.P2 == 0) && (power.P3 == 0)) return;
bufferWrite(power, group);
// MQTT - Powermeter
@ -153,6 +155,19 @@ class powermeter {
*
*/
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)
// topic for powermeter?
for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
if (mCfg->groups[group].pm_type == zeroExportPowermeterType_t::Mqtt) {
// mLog["mqttDevice"] = "topicInverter";
if (!topic.equals(mCfg->groups[group].pm_jsonPath)) return;
mCfg->groups[group].pm_P = (int32_t)obj["val"];
}
}
// for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
// if (mCfg->groups[group].pm_type == zeroExportPowermeterType_t::Mqtt) {
// // mLog["mqttDevice"] = "topicInverter";
// if (!topic.equals(mCfg->groups[group].pm_jsonPath)) return;
// mCfg->groups[group].pm_P = (int32_t)obj["val"];
// }
// }
#endif /*defined(ZEROEXPORT_POWERMETER_MQTT)*/
}
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;
zeroExport_t *mCfg;

91
src/plugins/zeroExport/zeroExport.h

@ -239,35 +239,35 @@ class ZeroExport {
// Regelbegrenzung
// 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
CfgGroupInv->limitNew += y;
// Check
if (CfgGroupInv->action == zeroExportAction_t::doNone) {
// 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 ((CfgGroup->battSwitch == true) && (CfgGroupInv->power == 0) && (mCfg->sleep != true) && (CfgGroup->sleep != true)) {
CfgGroupInv->action = zeroExportAction_t::doTurnOn;
mLog["do"] = "doTurnOn";
if ((CfgGroup->battSwitch == true) && (CfgGroupInv->limitNew > CfgGroupInv->powerMin) && (CfgGroupInv->power == 0) && (mCfg->sleep != true) && (CfgGroup->sleep != true)) {
if (CfgGroupInv->actionTimer < 0) CfgGroupInv->actionTimer = 0;
if (CfgGroupInv->actionTimer == 0) CfgGroupInv->actionTimer = 1;
if (CfgGroupInv->actionTimer > 10) {
CfgGroupInv->action = zeroExportAction_t::doTurnOn;
mLog["do"] = "doTurnOn";
}
}
if (((CfgGroup->battSwitch == false) || (CfgGroupInv->limitNew < 0)) && (CfgGroupInv->power > 0)) {
CfgGroupInv->action = zeroExportAction_t::doTurnOff;
mLog["do"] = "doTurnOff";
// TODO: hier kommt eine CheckBox je Gruppe rein, die es verhindert, dass Inv ausgeschaltet werden.
if ((CfgGroupInv->limitNew <= 0) && (CfgGroupInv->power > 0)) {
if (CfgGroupInv->actionTimer > 0) CfgGroupInv->actionTimer = 0;
if (CfgGroupInv->actionTimer == 0) CfgGroupInv->actionTimer = -1;
if (CfgGroupInv->actionTimer < 30) {
CfgGroupInv->action = zeroExportAction_t::doTurnOff;
mLog["do"] = "doTurnOff";
}
}
if (((mCfg->sleep == true) || (CfgGroup->sleep == true)) && (CfgGroupInv->power > 0)) {
if (((CfgGroup->battSwitch == false) || (mCfg->sleep == true) || (CfgGroup->sleep == true)) && (CfgGroupInv->power > 0)) {
CfgGroupInv->action = zeroExportAction_t::doTurnOff;
mLog["do"] = "sleep";
}
}
mLog["doT"] = CfgGroupInv->action;
if (CfgGroupInv->action == zeroExportAction_t::doNone) {
mLog["l"] = CfgGroupInv->limit;
@ -302,6 +302,16 @@ class ZeroExport {
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;
CfgGroupInv->limit = CfgGroupInv->limitNew;
@ -316,6 +326,8 @@ class ZeroExport {
mApp->triggerTickSend(iv->id);
CfgGroupInv->waitAck = 120;
CfgGroupInv->action = zeroExportAction_t::doNone;
CfgGroupInv->actionTimer = 0;
CfgGroupInv->actionTimestamp = Tsp;
}
break;
case zeroExportAction_t::doTurnOn:
@ -323,6 +335,8 @@ class ZeroExport {
mApp->triggerTickSend(iv->id);
CfgGroupInv->waitAck = 120;
CfgGroupInv->action = zeroExportAction_t::doNone;
CfgGroupInv->actionTimer = 0;
CfgGroupInv->actionTimestamp = Tsp;
}
break;
case zeroExportAction_t::doTurnOff:
@ -330,20 +344,19 @@ class ZeroExport {
mApp->triggerTickSend(iv->id);
CfgGroupInv->waitAck = 120;
CfgGroupInv->action = zeroExportAction_t::doNone;
CfgGroupInv->actionTimer = 0;
CfgGroupInv->actionTimestamp = Tsp;
}
break;
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[1] = AbsolutNonPersistent;
if (iv->setDevControlRequest(ActivePowerContr)) {
mApp->triggerTickSend(iv->id);
CfgGroupInv->waitAck = 60;
CfgGroupInv->action = zeroExportAction_t::doNone;
CfgGroupInv->actionTimer = 0;
CfgGroupInv->actionTimestamp = Tsp;
}
break;
default:
@ -382,6 +395,9 @@ class ZeroExport {
if (mCfg->groups[group].inverters[inv].waitAck > 0) {
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);
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;
@ -560,6 +598,12 @@ class ZeroExport {
*/
void onMqttConnect(void) {
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
@ -570,6 +614,9 @@ class ZeroExport {
void onMqttMessage(JsonObject obj) {
if (!mIsInitialized) return;
if (mCfg->debug) mLog["d"] = obj;
sendLog();
clearLog();
mPowermeter.onMqttMessage(obj);
String topic = String(obj["topic"]);

Loading…
Cancel
Save