Browse Source

0.8.1030011

pull/1615/head
Patrick Amrhein 9 months ago
parent
commit
e25045dbd9
  1. 50
      src/config/settings.h
  2. 2
      src/defines.h
  3. 135
      src/plugins/zeroExport/zeroExport.h
  4. 16
      src/web/RestApi.h
  5. 50
      src/web/html/setup.html
  6. 24
      src/web/lang.json

50
src/config/settings.h

@ -210,7 +210,7 @@ typedef struct {
#define ZEROEXPORT_GROUP_MAX_LEN_PM_JSONPATH 100 #define ZEROEXPORT_GROUP_MAX_LEN_PM_JSONPATH 100
#define ZEROEXPORT_GROUP_MAX_LEN_PM_USER 25 #define ZEROEXPORT_GROUP_MAX_LEN_PM_USER 25
#define ZEROEXPORT_GROUP_MAX_LEN_PM_PASS 25 #define ZEROEXPORT_GROUP_MAX_LEN_PM_PASS 25
#define ZEROEXPORT_GROUP_MAX_LEN_BATTERY_SOC 100 #define ZEROEXPORT_GROUP_MAX_LEN_BATT_TOPIC 100
#define ZEROEXPORT_GROUP_MAX_INVERTERS 3 #define ZEROEXPORT_GROUP_MAX_INVERTERS 3
#define ZEROEXPORT_POWERMETER_MAX_ERRORS 5 #define ZEROEXPORT_POWERMETER_MAX_ERRORS 5
#define ZEROEXPORT_DEF_INV_WAITINGTIME_MS 10000 #define ZEROEXPORT_DEF_INV_WAITINGTIME_MS 10000
@ -242,6 +242,13 @@ typedef enum {
L3Sum = 6, L3Sum = 6,
} zeroExportInverterTarget_t; } zeroExportInverterTarget_t;
typedef enum {
none = 0,
invUdc,
mqttU,
mqttSoC
} zeroExportBatteryCfg;
typedef enum { typedef enum {
doNone = 0, doNone = 0,
doRestart, doRestart,
@ -293,10 +300,11 @@ typedef struct {
// Inverters // Inverters
zeroExportGroupInverter_t inverters[ZEROEXPORT_GROUP_MAX_INVERTERS]; zeroExportGroupInverter_t inverters[ZEROEXPORT_GROUP_MAX_INVERTERS];
// Battery // Battery
bool battEnabled; uint8_t battCfg;
float battVoltageOn; char battTopic[ZEROEXPORT_GROUP_MAX_LEN_BATT_TOPIC];
float battVoltageOff; float battValue;
char battSoC[ZEROEXPORT_GROUP_MAX_LEN_BATTERY_SOC]; float battLimitOn;
float battLimitOff;
// Advanced // Advanced
int16_t setPoint; int16_t setPoint;
bool minimum; bool minimum;
@ -696,10 +704,10 @@ class settings {
mCfg.plugin.zeroExport.groups[group].inverters[inv].limitNew = 0; mCfg.plugin.zeroExport.groups[group].inverters[inv].limitNew = 0;
} }
// Battery // Battery
mCfg.plugin.zeroExport.groups[group].battEnabled = false; mCfg.plugin.zeroExport.groups[group].battCfg = zeroExportBatteryCfg::none;
mCfg.plugin.zeroExport.groups[group].battVoltageOn = 0; snprintf(mCfg.plugin.zeroExport.groups[group].battTopic, ZEROEXPORT_GROUP_MAX_LEN_BATT_TOPIC, "%s", DEF_ZEXPORT);
mCfg.plugin.zeroExport.groups[group].battVoltageOff = 0; mCfg.plugin.zeroExport.groups[group].battLimitOn = 0;
snprintf(mCfg.plugin.zeroExport.groups[group].battSoC, ZEROEXPORT_GROUP_MAX_LEN_BATTERY_SOC, "%s", DEF_ZEXPORT); mCfg.plugin.zeroExport.groups[group].battLimitOff = 0;
// Advanced // Advanced
mCfg.plugin.zeroExport.groups[group].setPoint = 0; mCfg.plugin.zeroExport.groups[group].setPoint = 0;
mCfg.plugin.zeroExport.groups[group].minimum = true; mCfg.plugin.zeroExport.groups[group].minimum = true;
@ -1047,10 +1055,10 @@ class settings {
jsonZeroExportGroupInverter(invArr.createNestedObject(), group, inv, set); jsonZeroExportGroupInverter(invArr.createNestedObject(), group, inv, set);
} }
// Battery // Battery
obj[F("battEnabled")] = mCfg.plugin.zeroExport.groups[group].battEnabled; obj[F("battCfg")] = mCfg.plugin.zeroExport.groups[group].battCfg;
obj[F("battVoltageOn")] = mCfg.plugin.zeroExport.groups[group].battVoltageOn; obj[F("battTopic")] = mCfg.plugin.zeroExport.groups[group].battTopic;
obj[F("battVoltageOff")] = mCfg.plugin.zeroExport.groups[group].battVoltageOff; obj[F("battLimitOn")] = mCfg.plugin.zeroExport.groups[group].battLimitOn;
obj[F("battSoC")] = mCfg.plugin.zeroExport.groups[group].battSoC; obj[F("battLimitOff")] = mCfg.plugin.zeroExport.groups[group].battLimitOff;
// Advanced // Advanced
obj[F("setPoint")] = mCfg.plugin.zeroExport.groups[group].setPoint; obj[F("setPoint")] = mCfg.plugin.zeroExport.groups[group].setPoint;
obj[F("minimum")] = mCfg.plugin.zeroExport.groups[group].minimum; obj[F("minimum")] = mCfg.plugin.zeroExport.groups[group].minimum;
@ -1085,14 +1093,14 @@ class settings {
} }
} }
// Battery // Battery
if (obj.containsKey(F("battEnabled"))) if (obj.containsKey(F("battCfg")))
getVal<bool>(obj, F("battEnabled"), &mCfg.plugin.zeroExport.groups[group].battEnabled); getVal<uint8_t>(obj, F("battCfg"), &mCfg.plugin.zeroExport.groups[group].battCfg);
if (obj.containsKey(F("battVoltageOn"))) if (obj.containsKey(F("battTopic")))
getVal<float>(obj, F("battVoltageOn"), &mCfg.plugin.zeroExport.groups[group].battVoltageOn); getChar(obj, F("battTopic"), mCfg.plugin.zeroExport.groups[group].battTopic, ZEROEXPORT_GROUP_MAX_LEN_BATT_TOPIC);
if (obj.containsKey(F("battVoltageOff"))) if (obj.containsKey(F("battLimitOn")))
getVal<float>(obj, F("battVoltageOff"), &mCfg.plugin.zeroExport.groups[group].battVoltageOff); getVal<float>(obj, F("battLimitOn"), &mCfg.plugin.zeroExport.groups[group].battLimitOn);
if (obj.containsKey(F("battSoC"))) if (obj.containsKey(F("battLimitOff")))
getChar(obj, F("battSoC"), mCfg.plugin.zeroExport.groups[group].battSoC, ZEROEXPORT_GROUP_MAX_LEN_BATTERY_SOC); getVal<float>(obj, F("battLimitOff"), &mCfg.plugin.zeroExport.groups[group].battLimitOff);
// Advanced // Advanced
if (obj.containsKey(F("setPoint"))) if (obj.containsKey(F("setPoint")))
getVal<int16_t>(obj, F("setPoint"), &mCfg.plugin.zeroExport.groups[group].setPoint); getVal<int16_t>(obj, F("setPoint"), &mCfg.plugin.zeroExport.groups[group].setPoint);

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

135
src/plugins/zeroExport/zeroExport.h

@ -121,29 +121,40 @@ class ZeroExport {
mLog["gL"] = groupLimit; mLog["gL"] = groupLimit;
// Batteryprotection // Batteryprotection
mLog["bEn"] = CfgGroup->battEnabled; mLog["bEn"] = (uint8_t)CfgGroup->battCfg;
if (CfgGroup->battEnabled) { switch (CfgGroup->battCfg) {
case zeroExportBatteryCfg::none:
if (CfgGroup->battSwitch != true) { if (CfgGroup->battSwitch != true) {
if (CfgGroupInv->dcVoltage > CfgGroup->battVoltageOn) {
CfgGroup->battSwitch = true; CfgGroup->battSwitch = true;
mLog["bA"] = "turn on"; mLog["bA"] = "turn on";
} }
if ((CfgGroupInv->dcVoltage > CfgGroup->battVoltageOff) && (CfgGroupInv->power > 0)) { break;
case zeroExportBatteryCfg::invUdc:
case zeroExportBatteryCfg::mqttU:
case zeroExportBatteryCfg::mqttSoC:
if (CfgGroup->battSwitch != true) {
if (CfgGroup->battValue > CfgGroup->battLimitOn) {
CfgGroup->battSwitch = true;
mLog["bA"] = "turn on";
}
if ((CfgGroup->battValue > CfgGroup->battLimitOff) && (CfgGroupInv->power > 0)) {
CfgGroup->battSwitch = true; CfgGroup->battSwitch = true;
mLog["bA"] = "turn on"; mLog["bA"] = "turn on";
} }
} else { } else {
if (CfgGroupInv->dcVoltage < CfgGroup->battVoltageOff) { if (CfgGroup->battValue < CfgGroup->battLimitOff) {
CfgGroup->battSwitch = false; CfgGroup->battSwitch = false;
mLog["bA"] = "turn off"; mLog["bA"] = "turn off";
} }
} }
mLog["bU"] = ah::round1(CfgGroupInv->dcVoltage); mLog["bU"] = ah::round1(CfgGroup->battValue);
} else { break;
if (CfgGroup->battSwitch != true) { default:
CfgGroup->battSwitch = true; if (CfgGroup->battSwitch == true) {
mLog["bA"] = "turn on"; CfgGroup->battSwitch = false;
mLog["bA"] = "turn off";
} }
break;
} }
mLog["bSw"] = CfgGroup->battSwitch; mLog["bSw"] = CfgGroup->battSwitch;
@ -309,8 +320,8 @@ class ZeroExport {
} }
} }
// CfgGroupInv->actionTimer = 0; // CfgGroupInv->actionTimer = 0;
// TODO: Timer stoppen wenn Limit gesetzt wird. // TODO: Timer stoppen wenn Limit gesetzt wird.
mLog["lN"] = CfgGroupInv->limitNew; mLog["lN"] = CfgGroupInv->limitNew;
CfgGroupInv->limit = CfgGroupInv->limitNew; CfgGroupInv->limit = CfgGroupInv->limitNew;
@ -553,14 +564,24 @@ 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 // Batterieüberwachung - Überwachung über die DC-Spannung am PV-Eingang 1 des Inverters
// Bisher ist nicht geklärt ob der Inverter das Limit bestätigt hat if (CfgGroup->battCfg == zeroExportBatteryCfg::invUdc) {
// Erstmalig aufgetreten bei @knickohr am 28.04.2024 ... l=300 pM=300, p=9 if ((CfgGroup->battSwitch == false) && (CfgGroup->battValue < CfgGroupInv->dcVoltage)) {
if (CfgGroupInv->MaxPower > 0) { CfgGroup->battValue = CfgGroupInv->dcVoltage;
uint16_t limitPercent = 100 / CfgGroupInv->MaxPower * CfgGroupInv->limit; }
uint16_t powerPercent = 100 / CfgGroupInv->MaxPower * CfgGroupInv->power; if ((CfgGroup->battSwitch == true) && (CfgGroup->battValue > CfgGroupInv->dcVoltage)) {
uint16_t delta = abs(limitPercent - powerPercent); CfgGroup->battValue = CfgGroupInv->dcVoltage;
if ((delta > 10) && (CfgGroupInv->power > 0)) { }
}
// 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; mLog["delta"] = delta;
unsigned long delay = iv->getLastTs(rec) - CfgGroupInv->actionTimestamp; unsigned long delay = iv->getLastTs(rec) - CfgGroupInv->actionTimestamp;
mLog["delay"] = delay; mLog["delay"] = delay;
@ -572,8 +593,8 @@ if ((delta > 10) && (CfgGroupInv->power > 0)) {
CfgGroupInv->action = zeroExportAction_t::doRestart; CfgGroupInv->action = zeroExportAction_t::doRestart;
mLog["do"] = "doRestart"; mLog["do"] = "doRestart";
} }
} }
} }
} }
zeroExportQueue_t Entry; zeroExportQueue_t Entry;
@ -600,12 +621,15 @@ if ((delta > 10) && (CfgGroupInv->power > 0)) {
mPowermeter.onMqttConnect(); mPowermeter.onMqttConnect();
// "topic":"userdefined battSoCTopic"
for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) { for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
if (!mCfg->groups [group].enabled) continue; if (!mCfg->groups[group].enabled) continue;
if(!strcmp(mCfg->groups[group].battSoC, "")) continue; if ((!mCfg->groups[group].battCfg == zeroExportBatteryCfg::mqttU) && (!mCfg->groups[group].battCfg == zeroExportBatteryCfg::mqttSoC)) continue;
mMqtt->subscribeExtern(String(mCfg->groups[group].battSoC).c_str(), QOS_2); if (!strcmp(mCfg->groups[group].battTopic, "")) continue;
mMqtt->subscribeExtern(String(mCfg->groups[group].battTopic).c_str(), QOS_2);
} }
} }
@ -621,13 +645,22 @@ if ((delta > 10) && (CfgGroupInv->power > 0)) {
String topic = String(obj["topic"]); String topic = String(obj["topic"]);
/// TODO: Receive Message für SoC // "topic":"userdefined battSoCTopic"
// if ((topicGroup >= 0) && (topicGroup < ZEROEXPORT_MAX_GROUPS)) { for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
// if (topic.indexOf("xxx") != -1) { if (!mCfg->groups[group].enabled) continue;
if ((!mCfg->groups[group].battCfg == zeroExportBatteryCfg::mqttU) && (!mCfg->groups[group].battCfg == zeroExportBatteryCfg::mqttSoC)) continue;
// } if (!strcmp(mCfg->groups[group].battTopic, "")) continue;
// }
if (strcmp(mCfg->groups[group].battTopic, String(topic).c_str())) {
mCfg->groups[group].battValue = (bool)obj["val"];
mLog["k"] = mCfg->groups[group].battTopic;
mLog["v"] = mCfg->groups[group].battValue;
}
}
// "topic":"ctrl/zero"
if (topic.indexOf("ctrl/zero") == -1) return; if (topic.indexOf("ctrl/zero") == -1) return;
if (mCfg->debug) mLog["d"] = obj; if (mCfg->debug) mLog["d"] = obj;
@ -669,27 +702,27 @@ if ((delta > 10) && (CfgGroupInv->power > 0)) {
mLog["v"] = mCfg->groups[topicGroup].sleep; mLog["v"] = mCfg->groups[topicGroup].sleep;
} }
// Auf Eis gelegt, dafür 2 Gruppen mehr // Auf Eis gelegt, dafür 2 Gruppen mehr
// 0.8.103008.2 // 0.8.103008.2
// // "topic":"ctrl/zero/groups/+/pm_ip" // // "topic":"ctrl/zero/groups/+/pm_ip"
// if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/pm_ip") != -1) { // if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/pm_ip") != -1) {
// snprintf(mCfg->groups[topicGroup].pm_url, ZEROEXPORT_GROUP_MAX_LEN_PM_URL, "%s", obj[F("val")].as<const char *>()); // snprintf(mCfg->groups[topicGroup].pm_url, ZEROEXPORT_GROUP_MAX_LEN_PM_URL, "%s", obj[F("val")].as<const char *>());
/// TODO: /// TODO:
// snprintf(mCfg->groups[topicGroup].pm_url, ZEROEXPORT_GROUP_MAX_LEN_PM_URL, "%s", obj[F("val")].as<const char *>()); // snprintf(mCfg->groups[topicGroup].pm_url, ZEROEXPORT_GROUP_MAX_LEN_PM_URL, "%s", obj[F("val")].as<const char *>());
// strncpy(mCfg->groups[topicGroup].pm_url, obj[F("val")], ZEROEXPORT_GROUP_MAX_LEN_PM_URL); // strncpy(mCfg->groups[topicGroup].pm_url, obj[F("val")], ZEROEXPORT_GROUP_MAX_LEN_PM_URL);
// strncpy(mCfg->groups[topicGroup].pm_url, String(obj[F("val")]).c_str(), ZEROEXPORT_GROUP_MAX_LEN_PM_URL); // strncpy(mCfg->groups[topicGroup].pm_url, String(obj[F("val")]).c_str(), ZEROEXPORT_GROUP_MAX_LEN_PM_URL);
// snprintf(mCfg->groups[topicGroup].pm_url, ZEROEXPORT_GROUP_MAX_LEN_PM_URL, "%s", String(obj[F("val")]).c_str()); // snprintf(mCfg->groups[topicGroup].pm_url, ZEROEXPORT_GROUP_MAX_LEN_PM_URL, "%s", String(obj[F("val")]).c_str());
// mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/pm_ip"; // mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/pm_ip";
// mLog["v"] = mCfg->groups[topicGroup].pm_url; // mLog["v"] = mCfg->groups[topicGroup].pm_url;
// } // }
// //
// // "topic":"ctrl/zero/groups/+/pm_jsonPath" // // "topic":"ctrl/zero/groups/+/pm_jsonPath"
// if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/pm_jsonPath") != -1) { // if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/pm_jsonPath") != -1) {
/// TODO: /// TODO:
// snprintf(mCfg->groups[topicGroup].pm_jsonPath, ZEROEXPORT_GROUP_MAX_LEN_PM_JSONPATH, "%s", obj[F("val")].as<const char *>()); // snprintf(mCfg->groups[topicGroup].pm_jsonPath, ZEROEXPORT_GROUP_MAX_LEN_PM_JSONPATH, "%s", obj[F("val")].as<const char *>());
// mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/pm_jsonPath"; // mLog["k"] = "ctrl/zero/groups/" + String(topicGroup) + "/pm_jsonPath";
// mLog["v"] = mCfg->groups[topicGroup].pm_jsonPath; // mLog["v"] = mCfg->groups[topicGroup].pm_jsonPath;
// } // }
// "topic":"ctrl/zero/groups/+/battery/switch" // "topic":"ctrl/zero/groups/+/battery/switch"
if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/battery/switch") != -1) { if (topic.indexOf("ctrl/zero/groups/" + String(topicGroup) + "/battery/switch") != -1) {

16
src/web/RestApi.h

@ -856,10 +856,10 @@ class RestApi {
objGroupInv[F("turnOff")] = (uint16_t)mConfig->plugin.zeroExport.groups[group].inverters[inv].turnOff; objGroupInv[F("turnOff")] = (uint16_t)mConfig->plugin.zeroExport.groups[group].inverters[inv].turnOff;
} }
// Battery // Battery
objGroup[F("battEnabled")] = (bool)mConfig->plugin.zeroExport.groups[group].battEnabled; objGroup[F("battCfg")] = (uint8_t)mConfig->plugin.zeroExport.groups[group].battCfg;
objGroup[F("battVoltageOn")] = ah::round1((float)mConfig->plugin.zeroExport.groups[group].battVoltageOn); objGroup[F("battTopic")] = String(mConfig->plugin.zeroExport.groups[group].battTopic);
objGroup[F("battVoltageOff")] = ah::round1((float)mConfig->plugin.zeroExport.groups[group].battVoltageOff); objGroup[F("battLimitOn")] = ah::round1((float)mConfig->plugin.zeroExport.groups[group].battLimitOn);
objGroup[F("battSoC")] = String(mConfig->plugin.zeroExport.groups[group].battSoC); objGroup[F("battLimitOff")] = ah::round1((float)mConfig->plugin.zeroExport.groups[group].battLimitOff);
// Advanced // Advanced
objGroup[F("setPoint")] = (int16_t)mConfig->plugin.zeroExport.groups[group].setPoint; objGroup[F("setPoint")] = (int16_t)mConfig->plugin.zeroExport.groups[group].setPoint;
objGroup[F("minimum")] = (bool)mConfig->plugin.zeroExport.groups[group].minimum; objGroup[F("minimum")] = (bool)mConfig->plugin.zeroExport.groups[group].minimum;
@ -1173,10 +1173,10 @@ class RestApi {
mConfig->plugin.zeroExport.groups[group].inverters[inv].turnOff = jsonIn[F("inverters")][inv][F("turnOff")]; mConfig->plugin.zeroExport.groups[group].inverters[inv].turnOff = jsonIn[F("inverters")][inv][F("turnOff")];
} }
// Battery // Battery
mConfig->plugin.zeroExport.groups[group].battEnabled = jsonIn[F("battEnabled")]; mConfig->plugin.zeroExport.groups[group].battCfg = jsonIn[F("battCfg")];
mConfig->plugin.zeroExport.groups[group].battVoltageOn = jsonIn[F("battVoltageOn")]; snprintf(mConfig->plugin.zeroExport.groups[group].battTopic, ZEROEXPORT_GROUP_MAX_LEN_BATT_TOPIC, "%s", jsonIn[F("battTopic")].as<const char*>());
mConfig->plugin.zeroExport.groups[group].battVoltageOff = jsonIn[F("battVoltageOff")]; mConfig->plugin.zeroExport.groups[group].battLimitOn = jsonIn[F("battLimitOn")];
snprintf(mConfig->plugin.zeroExport.groups[group].battSoC, ZEROEXPORT_GROUP_MAX_LEN_BATTERY_SOC, "%s", jsonIn[F("battSoC")].as<const char*>()); mConfig->plugin.zeroExport.groups[group].battLimitOff = jsonIn[F("battLimitOff")];
// Advanced // Advanced
mConfig->plugin.zeroExport.groups[group].setPoint = jsonIn[F("setPoint")]; mConfig->plugin.zeroExport.groups[group].setPoint = jsonIn[F("setPoint")];
mConfig->plugin.zeroExport.groups[group].minimum = jsonIn[F("minimum")]; mConfig->plugin.zeroExport.groups[group].minimum = jsonIn[F("minimum")];

50
src/web/html/setup.html

@ -1364,8 +1364,6 @@
} }
// Tab_Battery // Tab_Battery
var cb_battEnabled = ml("input", {name: "battEnabled", type: "checkbox"}, null);
cb_battEnabled.checked = (obj.battEnabled);
// Tab_Advanced // Tab_Advanced
var cb_minimum = ml("input", {name: "minimum", type: "checkbox"}, null); var cb_minimum = ml("input", {name: "minimum", type: "checkbox"}, null);
@ -1432,10 +1430,18 @@
]), ]),
// Battery // Battery
ml("div", {id: "div{#ZE_GROUP_TAB_BATTERY}", class: "tab-content hide"}, [ ml("div", {id: "div{#ZE_GROUP_TAB_BATTERY}", class: "tab-content hide"}, [
divRow("{#ZE_GROUP_TAB_BATTERY_ENABLED}", cb_battEnabled), divRow("{#ZE_GROUP_TAB_BATTERY_CFG}",
divRow("{#ZE_GROUP_TAB_BATTERY_VOLTAGEON}", ml("input", {name: "battVoltageOn", class: "text", type: "number", min: "0", max: "100", step: "0.1", value: obj.battVoltageOn}, null)), ml("select", {name: "battCfg", class: "text", id: "battCfg"}, null),
divRow("{#ZE_GROUP_TAB_BATTERY_VOLTAGEOFF}", ml("input", {name: "battVoltageOff", class: "text", type: "number", min: "0", max: "100", step: "0.1", value: obj.battVoltageOff}, null)), ),
divRow("{#ZE_GROUP_TAB_BATTERY_SOC}", ml("input", {name: "battSoC", class: "text", type: "text", value: obj.battSoC}, null)), divRow("{#ZE_GROUP_TAB_BATTERY_TOPIC}",
ml("input", {name: "battTopic", class: "text", type: "text", value: obj.battTopic}, null),
),
divRow("{#ZE_GROUP_TAB_BATTERY_LIMITON}",
ml("input", {name: "battLimitOn", class: "text", type: "number", min: "0", max: "100", step: "0.1", value: obj.battLimitOn}, null),
),
divRow("{#ZE_GROUP_TAB_BATTERY_LIMITOFF}",
ml("input", {name: "battLimitOff", class: "text", type: "number", min: "0", max: "100", step: "0.1", value: obj.battLimitOff}, null),
),
divRow("{#ZE_GROUP_TAB_BATTERY_ONOFF}", ml("input", {name: "battSwitch", id: "battSwitch", class: "btn", type: "button", value: "{#BTN_ONOFF}", onclick: battOnOff()}, null)), divRow("{#ZE_GROUP_TAB_BATTERY_ONOFF}", ml("input", {name: "battSwitch", id: "battSwitch", class: "btn", type: "button", value: "{#BTN_ONOFF}", onclick: battOnOff()}, null)),
// TODO: Uebersetzen mit lang.json und auf die entsprechende Dokuseite verlinken // TODO: Uebersetzen mit lang.json und auf die entsprechende Dokuseite verlinken
divRow("Hinweis: ", divRow("Hinweis: ",
@ -1546,6 +1552,21 @@
e.checked = (obj.inverters[inv].turnOff); e.checked = (obj.inverters[inv].turnOff);
} }
// Tab_Battery
// battCfg
var e = document.getElementById("battCfg");
selDelAllOpt(e);
// TODO: uebersetzen?
e.appendChild(opt("0", "---"));
e.appendChild(opt("1", "Inverter U dc"));
e.appendChild(opt("2", "MQTT U"));
e.appendChild(opt("3", "MQTT Soc"));
for (var i = 0; i < e.options.length; i++) {
if (e.options[i].value == obj.battCfg) {
e.selectedIndex = i;
}
}
function save() { function save() {
var o = new Object(); var o = new Object();
o.cmd = "ze_save_group" o.cmd = "ze_save_group"
@ -1578,10 +1599,11 @@
o.inverters.push(q); o.inverters.push(q);
} }
// Battery // Battery
o.battEnabled = document.getElementsByName("battEnabled")[0].checked; var e = document.getElementsByName("battCfg")[0];
o.battVoltageOn = document.getElementsByName("battVoltageOn")[0].value; o.battCfg = e.options[e.selectedIndex].value;
o.battVoltageOff = document.getElementsByName("battVoltageOff")[0].value; o.battTopic = document.getElementsByName("battTopic")[0].value;
o.battSoC = document.getElementsByName("battSoC")[0].value; o.battLimitOn = document.getElementsByName("battLimitOn")[0].value;
o.battLimitOff = document.getElementsByName("battLimitOff")[0].value;
// Advanced // Advanced
o.setPoint = document.getElementsByName("setPoint")[0].value; o.setPoint = document.getElementsByName("setPoint")[0].value;
o.minimum = document.getElementsByName("minimum")[0].checked; o.minimum = document.getElementsByName("minimum")[0].checked;
@ -1644,10 +1666,10 @@
o.inverters.push(q); o.inverters.push(q);
} }
// Battery // Battery
o.battEnabled = false; o.battCfg = 0;
o.battVoltageOn = 0; o.battTopic = "";
o.battVoltageOff = 0; o.battLimitOn = 0;
o.battSoC = ""; o.battLimitOff = 0;
// Advanced // Advanced
o.setPoint = 0; o.setPoint = 0;
o.minimum = true; o.minimum = true;

24
src/web/lang.json

@ -954,24 +954,24 @@
"de": "Batterie" "de": "Batterie"
}, },
{ {
"token": "ZE_GROUP_TAB_BATTERY_ENABLED", "token": "ZE_GROUP_TAB_BATTERY_CFG",
"en": "Enabled:", "en": "Mode:",
"de": "Aktiviert:" "de": "Modus:"
}, },
{ {
"token": "ZE_GROUP_TAB_BATTERY_VOLTAGEON", "token": "ZE_GROUP_TAB_BATTERY_TOPIC",
"en": "Voltage on (Volt):", "en": "Topic:",
"de": "Spannung Ein (Volt):" "de": "Topic:"
}, },
{ {
"token": "ZE_GROUP_TAB_BATTERY_VOLTAGEOFF", "token": "ZE_GROUP_TAB_BATTERY_LIMITON",
"en": "Voltage off (Volt):", "en": "Limit On:",
"de": "Spannung Aus (Volt):" "de": "Limit Ein:"
}, },
{ {
"token": "ZE_GROUP_TAB_BATTERY_SOC", "token": "ZE_GROUP_TAB_BATTERY_LIMITOFF",
"en": "SoC % (MQTT Topic):", "en": "Limit Off:",
"de": "SoC (MQTT Topic):" "de": "Limit Aus:"
}, },
{ {
"token": "ZE_GROUP_TAB_BATTERY_ONOFF", "token": "ZE_GROUP_TAB_BATTERY_ONOFF",

Loading…
Cancel
Save