Browse Source

0.8.1030012

pull/1615/head
Patrick Amrhein 8 months ago
parent
commit
75687a78db
  1. 29
      src/config/settings.h
  2. 2
      src/defines.h
  3. 314
      src/plugins/zeroExport/powermeter.h
  4. 43
      src/plugins/zeroExport/zeroExport.h
  5. 4
      src/web/RestApi.h
  6. 49
      src/web/html/setup.html
  7. 10
      src/web/lang.json

29
src/config/settings.h

@ -213,7 +213,6 @@ typedef struct {
#define ZEROEXPORT_GROUP_MAX_LEN_BATT_TOPIC 100
#define ZEROEXPORT_GROUP_MAX_INVERTERS 3
#define ZEROEXPORT_POWERMETER_MAX_ERRORS 5
#define ZEROEXPORT_DEF_INV_WAITINGTIME_MS 10000
#define ZEROEXPORT_GROUP_WR_LIMIT_MIN_DIFF 2
#define ZEROEXPORT_POWERMETER_SHELLY
//#define ZEROEXPORT_POWERMETER_TASMOTA
@ -237,10 +236,7 @@ typedef enum {
L1 = 1,
L2 = 2,
L3 = 3,
L1Sum = 4,
L2Sum = 5,
L3Sum = 6,
} zeroExportInverterTarget_t;
} zeroExportPowermeterTarget;
typedef enum {
none = 0,
@ -266,7 +262,6 @@ typedef struct {
typedef struct {
bool enabled;
int8_t id;
int8_t target;
uint16_t powerMin;
uint16_t powerMax;
bool turnOff;
@ -297,6 +292,7 @@ typedef struct {
char pm_jsonPath[ZEROEXPORT_GROUP_MAX_LEN_PM_JSONPATH];
char pm_user[ZEROEXPORT_GROUP_MAX_LEN_PM_USER];
char pm_pass[ZEROEXPORT_GROUP_MAX_LEN_PM_PASS];
uint8_t pm_target;
// Inverters
zeroExportGroupInverter_t inverters[ZEROEXPORT_GROUP_MAX_INVERTERS];
// Battery
@ -317,11 +313,6 @@ typedef struct {
unsigned long lastRefresh;
uint16_t wait;
int32_t pm_P;
int32_t pm_P1;
int32_t pm_P2;
int32_t pm_P3;
bool battSwitch;
// PID controller
@ -687,11 +678,11 @@ class settings {
snprintf(mCfg.plugin.zeroExport.groups[group].pm_jsonPath, ZEROEXPORT_GROUP_MAX_LEN_PM_JSONPATH, "%s", DEF_ZEXPORT);
snprintf(mCfg.plugin.zeroExport.groups[group].pm_user, ZEROEXPORT_GROUP_MAX_LEN_PM_USER, "%s", DEF_ZEXPORT);
snprintf(mCfg.plugin.zeroExport.groups[group].pm_pass, ZEROEXPORT_GROUP_MAX_LEN_PM_PASS, "%s", DEF_ZEXPORT);
mCfg.plugin.zeroExport.groups[group].pm_target = zeroExportPowermeterTarget::Sum;
// Inverters
for(uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) {
mCfg.plugin.zeroExport.groups[group].inverters[inv].enabled = false;
mCfg.plugin.zeroExport.groups[group].inverters[inv].id = -1;
mCfg.plugin.zeroExport.groups[group].inverters[inv].target = -1;
mCfg.plugin.zeroExport.groups[group].inverters[inv].powerMin = 10;
mCfg.plugin.zeroExport.groups[group].inverters[inv].powerMax = 600;
mCfg.plugin.zeroExport.groups[group].inverters[inv].turnOff = false;
@ -720,10 +711,10 @@ class settings {
mCfg.plugin.zeroExport.groups[group].lastRun = 0;
mCfg.plugin.zeroExport.groups[group].lastRefresh = 0;
mCfg.plugin.zeroExport.groups[group].wait = 60000;
mCfg.plugin.zeroExport.groups[group].pm_P = 0;
mCfg.plugin.zeroExport.groups[group].pm_P1 = 0;
mCfg.plugin.zeroExport.groups[group].pm_P2 = 0;
mCfg.plugin.zeroExport.groups[group].pm_P3 = 0;
// mCfg.plugin.zeroExport.groups[group].pm_P = 0;
// mCfg.plugin.zeroExport.groups[group].pm_P1 = 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].power = 0;
@ -1017,7 +1008,6 @@ class settings {
if(set) {
obj[F("enabled")] = mCfg.plugin.zeroExport.groups[group].inverters[inv].enabled;
obj[F("id")] = mCfg.plugin.zeroExport.groups[group].inverters[inv].id;
obj[F("target")] = mCfg.plugin.zeroExport.groups[group].inverters[inv].target;
obj[F("powerMin")] = mCfg.plugin.zeroExport.groups[group].inverters[inv].powerMin;
obj[F("powerMax")] = mCfg.plugin.zeroExport.groups[group].inverters[inv].powerMax;
obj[F("turnOff")] = mCfg.plugin.zeroExport.groups[group].inverters[inv].turnOff;
@ -1026,8 +1016,6 @@ class settings {
getVal<bool>(obj, F("enabled"), &mCfg.plugin.zeroExport.groups[group].inverters[inv].enabled);
if (obj.containsKey(F("id")))
getVal<int8_t>(obj, F("id"), &mCfg.plugin.zeroExport.groups[group].inverters[inv].id);
if (obj.containsKey(F("target")))
getVal<int8_t>(obj, F("target"), &mCfg.plugin.zeroExport.groups[group].inverters[inv].target);
if (obj.containsKey(F("powerMin")))
getVal<uint16_t>(obj, F("powerMin"), &mCfg.plugin.zeroExport.groups[group].inverters[inv].powerMin);
if (obj.containsKey(F("powerMax")))
@ -1049,6 +1037,7 @@ class settings {
obj[F("pm_jsonPath")] = mCfg.plugin.zeroExport.groups[group].pm_jsonPath;
obj[F("pm_user")] = mCfg.plugin.zeroExport.groups[group].pm_user;
obj[F("pm_pass")] = mCfg.plugin.zeroExport.groups[group].pm_pass;
obj[F("pm_target")] = mCfg.plugin.zeroExport.groups[group].pm_target;
// Inverters
JsonArray invArr = obj.createNestedArray(F("inverters"));
for(uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) {
@ -1086,6 +1075,8 @@ class settings {
getChar(obj, F("pm_user"), mCfg.plugin.zeroExport.groups[group].pm_user, ZEROEXPORT_GROUP_MAX_LEN_PM_USER);
if (obj.containsKey(F("pm_pass")))
getChar(obj, F("pm_pass"), mCfg.plugin.zeroExport.groups[group].pm_pass, ZEROEXPORT_GROUP_MAX_LEN_PM_PASS);
if (obj.containsKey(F("pm_target")))
getVal<uint8_t>(obj, F("pm_target"), &mCfg.plugin.zeroExport.groups[group].pm_target);
// Inverters
if (obj.containsKey(F("inverters"))) {
for(uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) {

2
src/defines.h

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

314
src/plugins/zeroExport/powermeter.h

@ -26,13 +26,6 @@ typedef struct {
} OBISHandler;
#endif
typedef struct {
float P;
float P1;
float P2;
float P3;
} PowermeterBuffer_t;
class powermeter {
public:
/** powermeter
@ -70,7 +63,8 @@ class powermeter {
if (millis() - mPreviousTsp <= 1000) return; // skip when it is to fast
mPreviousTsp = millis();
PowermeterBuffer_t power;
bool result = false;
float power = 0.0;
for (u_short group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
if ((!mCfg->groups[group].enabled) || (mCfg->groups[group].sleep)) continue;
@ -81,54 +75,48 @@ class powermeter {
switch (mCfg->groups[group].pm_type) {
#if defined(ZEROEXPORT_POWERMETER_SHELLY)
case zeroExportPowermeterType_t::Shelly:
power = getPowermeterWattsShelly(*mLog, group);
result = getPowermeterWattsShelly(*mLog, group, &power);
break;
#endif
#if defined(ZEROEXPORT_POWERMETER_TASMOTA)
case zeroExportPowermeterType_t::Tasmota:
power = getPowermeterWattsTasmota(*mLog, group);
break;
#endif
#if defined(ZEROEXPORT_POWERMETER_MQTT)
case zeroExportPowermeterType_t::Mqtt:
/// power = getPowermeterWattsMqtt(*mLog, group);
continue;
result = getPowermeterWattsTasmota(*mLog, group, &power);
break;
#endif
#if defined(ZEROEXPORT_POWERMETER_HICHI)
case zeroExportPowermeterType_t::Hichi:
power = getPowermeterWattsHichi(*mLog, group);
result = getPowermeterWattsHichi(*mLog, group, &power);
break;
#endif
#if defined(ZEROEXPORT_POWERMETER_TIBBER)
case zeroExportPowermeterType_t::Tibber:
power = getPowermeterWattsTibber(*mLog, group);
result = getPowermeterWattsTibber(*mLog, group, &power);
mPreviousTsp += 2000; // Zusätzliche Pause
break;
#endif
#if defined(ZEROEXPORT_POWERMETER_SHRDZM)
case zeroExportPowermeterType_t::Shrdzm:
power = getPowermeterWattsShrdzm(*mLog, group);
result = getPowermeterWattsShrdzm(*mLog, group, &power);
break;
#endif
}
if ((power.P == 0) and (power.P1 == 0) && (power.P2 == 0) && (power.P3 == 0)) return;
bufferWrite(power, group);
// MQTT - Powermeter
if (mCfg->debug) {
if (mMqtt->isConnected()) {
// P
mqttObj["Sum"] = ah::round1(power.P);
mqttObj["L1"] = ah::round1(power.P1);
mqttObj["L2"] = ah::round1(power.P2);
mqttObj["L3"] = ah::round1(power.P3);
mMqtt->publish(String("zero/state/groups/" + String(group) + "/powermeter/P").c_str(), mqttDoc.as<std::string>().c_str(), false);
mqttDoc.clear();
// W (TODO)
if (result) {
bufferWrite(power, group);
// MQTT - Powermeter
if (mCfg->debug) {
if (mMqtt->isConnected()) {
// P
mqttObj["Sum"] = ah::round1(power);
// mqttObj["L1"] = ah::round1(power.P1);
// mqttObj["L2"] = ah::round1(power.P2);
// mqttObj["L3"] = ah::round1(power.P3);
mMqtt->publish(String("zero/state/groups/" + String(group) + "/powermeter/P").c_str(), mqttDoc.as<std::string>().c_str(), false);
mqttDoc.clear();
// W (TODO)
}
}
}
}
@ -139,24 +127,33 @@ class 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;
float getDataAVG(uint8_t group) {
float avg = 0.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 += mPowermeterBuffer[group][i];
}
avg.P = avg.P / 5;
avg.P1 = avg.P1 / 5;
avg.P2 = avg.P2 / 5;
avg.P3 = avg.P3 / 5;
avg = avg / 5.0;
return avg;
}
/** groupGetPowermeter
* Holt die Daten vom Powermeter
* @param group
* @returns true/false
*/
float getDataMIN(uint8_t group) {
float min = 0.0;
for (int i = 0; i < 5; i++) {
if (i == 0) min = mPowermeterBuffer[group][i];
if ( min > mPowermeterBuffer[group][i]) min = mPowermeterBuffer[group][i];
}
return min;
}
/**
*
*/
@ -193,11 +190,8 @@ class powermeter {
if (strcmp(mCfg->groups[group].pm_jsonPath, String(topic).c_str())) continue;
PowermeterBuffer_t power;
power.P = (uint16_t)obj["val"];
power.P1 = power.P2 = power.P3 = (uint16_t)obj["val"] / 3;
if ((power.P == 0) and (power.P1 == 0) && (power.P2 == 0) && (power.P3 == 0)) return;
float power = 0.0;
power = (uint16_t)obj["val"];
bufferWrite(power, group);
@ -205,10 +199,10 @@ class powermeter {
if (mCfg->debug) {
if (mMqtt->isConnected()) {
// P
mqttObj["Sum"] = ah::round1(power.P);
mqttObj["L1"] = ah::round1(power.P1);
mqttObj["L2"] = ah::round1(power.P2);
mqttObj["L3"] = ah::round1(power.P3);
mqttObj["Sum"] = ah::round1(power);
/// mqttObj["L1"] = ah::round1(power.P1);
/// mqttObj["L2"] = ah::round1(power.P2);
/// mqttObj["L3"] = ah::round1(power.P3);
mMqtt->publish(String("zero/state/groups/" + String(group) + "/powermeter/P").c_str(), mqttDoc.as<std::string>().c_str(), false);
mqttDoc.clear();
@ -253,7 +247,7 @@ class powermeter {
unsigned long mPreviousTsp = 0;
PowermeterBuffer_t mPowermeterBuffer[ZEROEXPORT_MAX_GROUPS][5] = {0};
float mPowermeterBuffer[ZEROEXPORT_MAX_GROUPS][5] = {0};
short mPowermeterBufferPos[ZEROEXPORT_MAX_GROUPS] = {0};
StaticJsonDocument<512> mqttDoc; // DynamicJsonDocument mqttDoc(512);
@ -279,10 +273,7 @@ class powermeter {
* @param group
* @returns true/false
*/
PowermeterBuffer_t getPowermeterWattsShelly(JsonObject logObj, uint8_t group) {
PowermeterBuffer_t result;
result.P = result.P1 = result.P2 = result.P3 = 0;
bool getPowermeterWattsShelly(JsonObject logObj, uint8_t group, float *power) {
logObj["mod"] = "getPowermeterWattsShelly";
setHeader(&http);
@ -294,97 +285,69 @@ class powermeter {
if (http.GET() == HTTP_CODE_OK) {
// Parsing
// http.getSize());
// TODO: Umstellen auf dynamische Größe
DynamicJsonDocument doc(2048);
DeserializationError error = deserializeJson(doc, http.getString());
if (error) {
logObj["err"] = "deserializeJson: " + String(error.c_str());
return result;
return false;
} else {
if (doc.containsKey(F("total_power"))) {
// Shelly 3EM
result.P = doc["total_power"];
} else if (doc.containsKey(F("em:0"))) {
// Shelly pro 3EM
result.P = doc["em:0"]["total_act_power"];
} else if (doc.containsKey(F("total_act_power"))) {
// Shelly pro 3EM
result.P = doc["total_act_power"];
} else {
// Keine Daten
result.P = 0;
}
if (doc.containsKey(F("emeters"))) {
// Shelly 3EM
result.P1 = doc["emeters"][0]["power"];
} else if (doc.containsKey(F("em:0"))) {
// Shelly pro 3EM
result.P1 = doc["em:0"]["a_act_power"];
} else if (doc.containsKey(F("a_act_power"))) {
// Shelly pro 3EM
result.P1 = doc["a_act_power"];
} else if (doc.containsKey(F("switch:0"))) {
// Shelly plus1pm plus2pm
result.P1 = doc["switch:0"]["apower"];
result.P += result.P1;
} else if (doc.containsKey(F("apower"))) {
// Shelly Alternative
result.P1 = doc["apower"];
result.P += result.P1;
} else {
// Keine Daten
result.P1 = 0;
}
if (doc.containsKey(F("emeters"))) {
// Shelly 3EM
result.P2 = doc["emeters"][1]["power"];
} else if (doc.containsKey(F("em:0"))) {
// Shelly pro 3EM
result.P2 = doc["em:0"]["b_act_power"];
} else if (doc.containsKey(F("b_act_power"))) {
// Shelly pro 3EM
result.P2 = doc["b_act_power"];
} else if (doc.containsKey(F("switch:1"))) {
// Shelly plus1pm plus2pm
result.P2 = doc["switch.1"]["apower"];
result.P += result.P2;
//} else if (doc.containsKey(F("apower"))) {
// Shelly Alternative
// mCfg->groups[group].pmPowerL2 = doc["apower"];
// mCfg->groups[group].pmPower += mCfg->groups[group].pmPowerL2;
// ret = true;
} else {
// Keine Daten
result.P2 = 0;
}
if (doc.containsKey(F("emeters"))) {
// Shelly 3EM
result.P3 = doc["emeters"][2]["power"];
} else if (doc.containsKey(F("em:0"))) {
// Shelly pro 3EM
result.P3 = doc["em:0"]["c_act_power"];
} else if (doc.containsKey(F("c_act_power"))) {
// Shelly pro 3EM
result.P3 = doc["c_act_power"];
} else if (doc.containsKey(F("switch:2"))) {
// Shelly plus1pm plus2pm
result.P3 = doc["switch:2"]["apower"];
result.P += result.P3;
//} else if (doc.containsKey(F("apower"))) {
// Shelly Alternative
// mCfg->groups[group].pmPowerL3 = doc["apower"];
// mCfg->groups[group].pmPower += mCfg->groups[group].pmPowerL3;
// result = true;
} else {
// Keine Daten
result.P3 = 0;
switch (mCfg->groups[group].pm_target) {
case zeroExportPowermeterTarget::L1:
if (doc.containsKey(F("emeters"))) {
// Shelly 3EM
*power = doc["emeters"][0]["power"];
} else if (doc.containsKey(F("em:0"))) {
// Shelly pro 3EM
*power = doc["em:0"]["a_act_power"];
} else if (doc.containsKey(F("a_act_power"))) {
// Shelly pro 3EM
*power = doc["a_act_power"];
}
break;
case zeroExportPowermeterTarget::L2:
if (doc.containsKey(F("emeters"))) {
// Shelly 3EM
*power = doc["emeters"][1]["power"];
} else if (doc.containsKey(F("em:0"))) {
// Shelly pro 3EM
*power = doc["em:0"]["b_act_power"];
} else if (doc.containsKey(F("b_act_power"))) {
// Shelly pro 3EM
*power = doc["b_act_power"];
}
break;
case zeroExportPowermeterTarget::L3:
if (doc.containsKey(F("emeters"))) {
// Shelly 3EM
*power = doc["emeters"][2]["power"];
} else if (doc.containsKey(F("em:0"))) {
// Shelly pro 3EM
*power = doc["em:0"]["c_act_power"];
} else if (doc.containsKey(F("c_act_power"))) {
// Shelly pro 3EM
*power = doc["c_act_power"];
}
break;
case zeroExportPowermeterTarget::Sum:
default:
if (doc.containsKey(F("total_power"))) {
// Shelly 3EM
*power = doc["total_power"];
} else if (doc.containsKey(F("em:0"))) {
// Shelly pro 3EM
*power = doc["em:0"]["total_act_power"];
} else if (doc.containsKey(F("total_act_power"))) {
// Shelly pro 3EM
*power = doc["total_act_power"];
}
break;
}
}
}
http.end();
return result;
return true;
}
#endif
@ -395,10 +358,7 @@ class powermeter {
* @param group
* @returns true/false
*/
PowermeterBuffer_t getPowermeterWattsTasmota(JsonObject logObj, uint8_t group) {
PowermeterBuffer_t result;
result.P = result.P1 = result.P2 = result.P3 = 0;
bool getPowermeterWattsTasmota(JsonObject logObj, uint8_t group, float *power) {
logObj["mod"] = "getPowermeterWattsTasmota";
/*
// TODO: nicht komplett
@ -459,31 +419,10 @@ class powermeter {
}
http.end();
*/
return result;
return false;
}
#endif
/// #if defined(ZEROEXPORT_POWERMETER_MQTT)
/// /** getPowermeterWattsMqtt
/// * ...
/// * @param logObj
/// * @param group
/// * @returns true/false
/// */
/// PowermeterBuffer_t getPowermeterWattsMqtt(JsonObject logObj, uint8_t group) {
/// PowermeterBuffer_t result;
/// result.P = result.P1 = result.P2 = result.P3 = 0;
///
/// logObj["mod"] = "getPowermeterWattsMqtt";
///
/// // topic for powermeter?
/// result.P = mCfg->groups[group].pm_P;
/// result.P1 = result.P2 = result.P3 = mCfg->groups[group].pm_P / 3;
///
/// return result;
/// }
/// #endif
#if defined(ZEROEXPORT_POWERMETER_HICHI)
/** getPowermeterWattsHichi
* ...
@ -491,10 +430,7 @@ class powermeter {
* @param group
* @returns true/false
*/
PowermeterBuffer_t getPowermeterWattsHichi(JsonObject logObj, uint8_t group) {
PowermeterBuffer_t result;
result.P = result.P1 = result.P2 = result.P3 = 0;
bool getPowermeterWattsHichi(JsonObject logObj, uint8_t group, float *power) {
logObj["mod"] = "getPowermeterWattsHichi";
// Hier neuer Code - Anfang
@ -503,7 +439,7 @@ class powermeter {
// Hier neuer Code - Ende
return result;
return false;
}
#endif
@ -545,11 +481,10 @@ class powermeter {
{{0x01, 0x00, 0x01, 0x08, 0x00, 0xff}, &smlOBISWh, &_powerMeterImport},
{{0x01, 0x00, 0x02, 0x08, 0x00, 0xff}, &smlOBISWh, &_powerMeterExport}};
PowermeterBuffer_t getPowermeterWattsTibber(JsonObject logObj, uint8_t group) {
bool getPowermeterWattsTibber(JsonObject logObj, uint8_t group, float *power) {
mPreviousTsp = mPreviousTsp + 2000; // Zusätzliche Pause
PowermeterBuffer_t result;
result.P = result.P1 = result.P2 = result.P3 = 0;
bool result = false;
logObj["mod"] = "getPowermeterWattsTibber";
@ -580,14 +515,8 @@ class powermeter {
switch (smlCurrentState) {
case SML_FINAL:
result.P = _powerMeterTotal;
result.P1 = _powerMeter1Power;
result.P2 = _powerMeter2Power;
result.P3 = _powerMeter3Power;
if (!(_powerMeter1Power && _powerMeter2Power && _powerMeter3Power)) {
result.P1 = result.P2 = result.P3 = _powerMeterTotal / 3;
}
*power = _powerMeterTotal;
result = true;
break;
case SML_LISTEND:
// check handlers on last received list
@ -616,10 +545,7 @@ class powermeter {
* @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?
*/
PowermeterBuffer_t getPowermeterWattsShrdzm(JsonObject logObj, uint8_t group) {
PowermeterBuffer_t result;
result.P = result.P1 = result.P2 = result.P3 = 0;
bool getPowermeterWattsShrdzm(JsonObject logObj, uint8_t group, float *power) {
logObj["mod"] = "getPowermeterWattsShrdzm";
setHeader(&http);
@ -636,27 +562,23 @@ class powermeter {
DeserializationError error = deserializeJson(doc, http.getString());
if (error) {
logObj["err"] = "deserializeJson: " + String(error.c_str());
return result;
return false;
} 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;
*power = doc["16.7.0"];
}
}
}
http.end();
return result;
return true;
}
#endif
/**
*
*/
void bufferWrite(PowermeterBuffer_t raw, short group) {
void bufferWrite(float raw, short group) {
mPowermeterBuffer[group][mPowermeterBufferPos[group]] = raw;
mPowermeterBufferPos[group]++;
if (mPowermeterBufferPos[group] >= 5) mPowermeterBufferPos[group] = 0;

43
src/plugins/zeroExport/zeroExport.h

@ -166,45 +166,10 @@ class ZeroExport {
// Regelgröße x in Watt
int16_t x = 0.0;
int16_t xSum = 0.0;
switch (CfgGroupInv->target) {
case zeroExportInverterTarget_t::Sum:
x = mPowermeter.getDataAVG(group).P;
break;
case zeroExportInverterTarget_t::L1:
x = mPowermeter.getDataAVG(group).P1;
break;
case zeroExportInverterTarget_t::L2:
x = mPowermeter.getDataAVG(group).P2;
break;
case zeroExportInverterTarget_t::L3:
x = mPowermeter.getDataAVG(group).P3;
break;
case zeroExportInverterTarget_t::L1Sum:
x = mPowermeter.getDataAVG(group).P1;
xSum = mPowermeter.getDataAVG(group).P;
xSum -= mPowermeter.getDataAVG(group).P2;
xSum -= mPowermeter.getDataAVG(group).P3;
if (xSum > x) x = xSum;
break;
case zeroExportInverterTarget_t::L2Sum:
x = mPowermeter.getDataAVG(group).P2;
xSum = mPowermeter.getDataAVG(group).P;
xSum -= mPowermeter.getDataAVG(group).P1;
xSum -= mPowermeter.getDataAVG(group).P3;
if (xSum > x) x = xSum;
break;
case zeroExportInverterTarget_t::L3Sum:
x = mPowermeter.getDataAVG(group).P3;
xSum = mPowermeter.getDataAVG(group).P;
xSum -= mPowermeter.getDataAVG(group).P1;
xSum -= mPowermeter.getDataAVG(group).P2;
if (xSum > x) x = xSum;
break;
default:
x = w;
// TODO: ErrorLog
break;
if (CfgGroup->minimum) {
x = mPowermeter.getDataMIN(group);
} else {
x = mPowermeter.getDataAVG(group);
}
mLog["x"] = x;

4
src/web/RestApi.h

@ -843,6 +843,7 @@ class RestApi {
objGroup[F("pm_jsonPath")] = String(mConfig->plugin.zeroExport.groups[group].pm_jsonPath);
objGroup[F("pm_user")] = String(mConfig->plugin.zeroExport.groups[group].pm_user);
objGroup[F("pm_pass")] = String(mConfig->plugin.zeroExport.groups[group].pm_pass);
objGroup[F("pm_target")] = (uint8_t)mConfig->plugin.zeroExport.groups[group].pm_target;
// Inverters
objGroup[F("max_inverters")] = ZEROEXPORT_GROUP_MAX_INVERTERS;
JsonArray arrInv = objGroup.createNestedArray(F("inverters"));
@ -850,7 +851,6 @@ class RestApi {
JsonObject objGroupInv = arrInv.createNestedObject();
objGroupInv[F("enabled")] = (bool)mConfig->plugin.zeroExport.groups[group].inverters[inv].enabled;
objGroupInv[F("id")] = (int8_t)mConfig->plugin.zeroExport.groups[group].inverters[inv].id;
objGroupInv[F("target")] = (int8_t)mConfig->plugin.zeroExport.groups[group].inverters[inv].target;
objGroupInv[F("powerMin")] = (uint16_t)mConfig->plugin.zeroExport.groups[group].inverters[inv].powerMin;
objGroupInv[F("powerMax")] = (uint16_t)mConfig->plugin.zeroExport.groups[group].inverters[inv].powerMax;
objGroupInv[F("turnOff")] = (uint16_t)mConfig->plugin.zeroExport.groups[group].inverters[inv].turnOff;
@ -1163,11 +1163,11 @@ class RestApi {
snprintf(mConfig->plugin.zeroExport.groups[group].pm_jsonPath, ZEROEXPORT_GROUP_MAX_LEN_PM_JSONPATH, "%s", jsonIn[F("pm_jsonPath")].as<const char*>());
snprintf(mConfig->plugin.zeroExport.groups[group].pm_user, ZEROEXPORT_GROUP_MAX_LEN_PM_USER, "%s", jsonIn[F("pm_user")].as<const char*>());
snprintf(mConfig->plugin.zeroExport.groups[group].pm_pass, ZEROEXPORT_GROUP_MAX_LEN_PM_PASS, "%s", jsonIn[F("pm_pass")].as<const char*>());
mConfig->plugin.zeroExport.groups[group].pm_target = jsonIn[F("pm_target")];
// Inverters
for(uint8_t inv = 0; inv < ZEROEXPORT_GROUP_MAX_INVERTERS; inv++) {
mConfig->plugin.zeroExport.groups[group].inverters[inv].enabled = jsonIn[F("inverters")][inv][F("enabled")];
mConfig->plugin.zeroExport.groups[group].inverters[inv].id = jsonIn[F("inverters")][inv][F("id")];
mConfig->plugin.zeroExport.groups[group].inverters[inv].target = jsonIn[F("inverters")][inv][F("target")];
mConfig->plugin.zeroExport.groups[group].inverters[inv].powerMin = jsonIn[F("inverters")][inv][F("powerMin")];
mConfig->plugin.zeroExport.groups[group].inverters[inv].powerMax = jsonIn[F("inverters")][inv][F("powerMax")];
mConfig->plugin.zeroExport.groups[group].inverters[inv].turnOff = jsonIn[F("inverters")][inv][F("turnOff")];

49
src/web/html/setup.html

@ -1321,7 +1321,6 @@
ml("th", {style: "width: 10%;"}, ml("input", {name: "invMax", id: "invMax", type: "hidden", value: maxInv}, null)),
ml("th", {style: "width: 10%;"}, "{#ZE_GROUP_TAB_INVERTER_ENABLED}"),
ml("th", {}, "{#ZE_GROUP_TAB_INVERTER_NAME}"),
ml("th", {}, "{#ZE_GROUP_TAB_INVERTER_SUM}"),
ml("th", {style: "width: 15%;"}, "{#ZE_GROUP_TAB_INVERTER_POWERMIN}"),
ml("th", {style: "width: 15%;"}, "{#ZE_GROUP_TAB_INVERTER_POWERMAX}"),
ml("th", {style: "width: 5%;"}, "{#ZE_GROUP_TAB_INVERTER_TURNOFF}"),
@ -1340,11 +1339,6 @@
ml("select", {name: "invId"+inv, class: "text", id: "invId"+inv}, null),
]),
),
ml("td", {},
ml("div", {}, [
ml("select", {name: "invTarget"+inv, class: "text", id: "invTarget"+inv}, null),
]),
),
ml("td", {},
ml("div", {}, [
ml("input", {name: "invPowerMin"+inv, class: "text", id: "invPowerMin"+inv, type: "number", min: "0", max: "65535"}, null)
@ -1407,6 +1401,9 @@
divRow("{#ZE_GROUP_TAB_POWERMETER_PASS}",
ml("input", {name: "pm_pass", class: "text", type: "password", value: "****"}, null),
),
divRow("{#ZE_GROUP_TAB_POWERMETER_TARGET}",
ml("select", {name: "pm_target", class: "text", id: "pm_target"}, null),
),
// TODO: Uebersetzen mit lang.json und auf die entsprechende Dokuseite verlinken
divRow("Hinweis: ",
ml("a", {href: "https://docs.ahoydtu.de/de/latest/zeroExport.html"}, "Bitte beachten Sie die Ausf&uuml;llhinweise in der Dokumentation."),
@ -1480,6 +1477,8 @@
modal("{#ZE_GROUP_EDIT_MODAL}: " + obj.id, html);
// ser.dispatchEvent(new Event('change'));
// Tab_Powermeter
// - pm_type
// Inhalt fuer pm_type aus config laden und in eine Funktion ausgliedern
var e = document.getElementById("pm_type");
selDelAllOpt(e);
@ -1496,6 +1495,18 @@
e.selectedIndex = i;
}
}
// - pm_target
var e = document.getElementById("pm_target");
selDelAllOpt(e);
e.appendChild(opt("0", "Sum"));
e.appendChild(opt("1", "L1"));
e.appendChild(opt("2", "L2"));
e.appendChild(opt("3", "L3"));
for (var i = 0; i < e.options.length; i++) {
if (e.options[i].value == obj.pm_target) {
e.selectedIndex = i;
}
}
// Tab_Inverters
// - Enabled
@ -1517,25 +1528,6 @@
}
}
}
// - Target
for (var inv = 0; inv < maxInv; inv++) {
var e = document.getElementById("invTarget"+inv);
selDelAllOpt(e);
// TODO: ?bersetzen?
e.appendChild(opt("-1", "---"));
e.appendChild(opt("0", "Sum"));
e.appendChild(opt("1", "L1"));
e.appendChild(opt("2", "L2"));
e.appendChild(opt("3", "L3"));
e.appendChild(opt("4", "L1 + Sum"));
e.appendChild(opt("5", "L2 + Sum"));
e.appendChild(opt("6", "L3 + Sum"));
for (var i = 0; i < e.options.length; i++) {
if (e.options[i].value == obj.inverters[inv].target) {
e.selectedIndex = i;
}
}
}
// - powerMin
for (var inv = 0; inv < maxInv; inv++) {
var e = document.getElementById("invPowerMin"+inv);
@ -1583,6 +1575,8 @@
o.pm_jsonPath = document.getElementsByName("pm_jsonPath")[0].value;
o.pm_user = document.getElementsByName("pm_user")[0].value;
o.pm_pass = document.getElementsByName("pm_pass")[0].value;
var e = document.getElementsByName("pm_target")[0];
o.pm_target = e.options[e.selectedIndex].value;
// Inverters
o.invMax = document.getElementById("invMax").value;
o.inverters = [];
@ -1591,8 +1585,6 @@
q.enabled = document.getElementById("invEnabled"+inv).checked;
var e = document.getElementById("invId"+inv);
q.id = e.options[e.selectedIndex].value;
var e = document.getElementById("invTarget"+inv);
q.target = e.options[e.selectedIndex].value;
q.powerMin = document.getElementById("invPowerMin"+inv).value;
q.powerMax = document.getElementById("invPowerMax"+inv).value;
q.turnOff = document.getElementById("invTurnOff"+inv).checked;
@ -1650,6 +1642,7 @@
o.pm_jsonPath = "";
o.pm_user = "";
o.pm_pass = "";
o.pm_target = 0;
// Inverters
o.invMax = obj.inverters.length;
o.inverters = [];
@ -1658,8 +1651,6 @@
q.enabled = false;
var e = document.getElementById("invId"+inv);
q.id = -1;
var e = document.getElementById("invTarget"+inv);
q.target = -1;
q.powerMin = 0;
q.powerMax = 0;
q.turnOff = false;

10
src/web/lang.json

@ -913,6 +913,11 @@
"en": "Password:",
"de": "Passwort:"
},
{
"token": "ZE_GROUP_TAB_POWERMETER_TARGET",
"en": "Target:",
"de": "Ziel:"
},
{
"token": "ZE_GROUP_TAB_INVERTER",
"en": "Inverter",
@ -928,11 +933,6 @@
"en": "Name",
"de": "Name"
},
{
"token": "ZE_GROUP_TAB_INVERTER_SUM",
"en": "Sum",
"de": "Gesamt"
},
{
"token": "ZE_GROUP_TAB_INVERTER_POWERMIN",
"en": "Power (Min)",

Loading…
Cancel
Save