diff --git a/include/Configuration.h b/include/Configuration.h index e52db7e6a..e27c36a2b 100644 --- a/include/Configuration.h +++ b/include/Configuration.h @@ -158,6 +158,7 @@ struct BATTERY_CONFIG_T { uint16_t ZendureMaxOutput; bool ZendureAutoShutdown; bool ZendureForceLimit; + uint16_t ZendureOutputLimit; }; using BatteryConfig = struct BATTERY_CONFIG_T; diff --git a/include/ZendureBattery.h b/include/ZendureBattery.h index 04af3290c..2abb992a2 100644 --- a/include/ZendureBattery.h +++ b/include/ZendureBattery.h @@ -121,6 +121,7 @@ class ZendureBattery : public BatteryProvider { protected: void timesync(); static String parseVersion(uint32_t version); + uint16_t calcOutputLimit(uint16_t limit); private: void calculateEfficiency(); diff --git a/include/defaults.h b/include/defaults.h index 99374e6b6..3500a7ff2 100644 --- a/include/defaults.h +++ b/include/defaults.h @@ -162,6 +162,7 @@ #define BATTERY_ZENDURE_MAX_OUTPUT 800 #define BATTERY_ZENDURE_AUTO_SHUTDOWN 1 #define BATTERY_ZENDURE_FORCE_LIMIT 0 +#define BATTERY_ZENDURE_OUTPUT_LIMIT BATTERY_ZENDURE_MAX_OUTPUT #define HUAWEI_ENABLED false #define HUAWEI_CAN_CONTROLLER_FREQUENCY 8000000UL diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 5f2b2226b..dba349384 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -101,6 +101,7 @@ void ConfigurationClass::serializeBatteryConfig(BatteryConfig const& source, Jso target["zendure_max_output"] = config.Battery.ZendureMaxOutput; target["zendure_auto_shutdown"] = config.Battery.ZendureAutoShutdown; target["zendure_force_limit"] = config.Battery.ZendureForceLimit; + target["zendure_output_limit"] = config.Battery.ZendureOutputLimit; } bool ConfigurationClass::write() @@ -400,6 +401,7 @@ void ConfigurationClass::deserializeBatteryConfig(JsonObject const& source, Batt target.ZendureMaxOutput = source["zendure_max_output"] | BATTERY_ZENDURE_MAX_OUTPUT; target.ZendureAutoShutdown = source["zendure_auto_shutdown"] | BATTERY_ZENDURE_AUTO_SHUTDOWN; target.ZendureForceLimit = source["zendure_force_limit"] | BATTERY_ZENDURE_FORCE_LIMIT; + target.ZendureOutputLimit = source["zendure_output_limit"] | BATTERY_ZENDURE_OUTPUT_LIMIT; } bool ConfigurationClass::read() diff --git a/src/ZendureBattery.cpp b/src/ZendureBattery.cpp index 240a6b7ff..279f433fb 100644 --- a/src/ZendureBattery.cpp +++ b/src/ZendureBattery.cpp @@ -113,7 +113,7 @@ bool ZendureBattery::init(bool verboseLogging) prop[ZENDURE_REPORT_MAX_SOC] = config.Battery.ZendureMaxSoC * 10; prop[ZENDURE_REPORT_MIN_SOC] = config.Battery.ZendureMinSoC * 10; if (config.Battery.ZendureForceLimit){ - prop[ZENDURE_REPORT_OUTPUT_LIMIT] = config.Battery.ZendureMaxOutput; + prop[ZENDURE_REPORT_OUTPUT_LIMIT] = calcOutputLimit(min(config.Battery.ZendureMaxOutput, config.Battery.ZendureOutputLimit)); } prop[ZENDURE_REPORT_INVERSE_MAX_POWER] = config.Battery.ZendureMaxOutput; prop[ZENDURE_REPORT_SMART_MODE] = 0; // should be disabled @@ -196,6 +196,17 @@ void ZendureBattery::loop() } } +uint16_t ZendureBattery::calcOutputLimit(uint16_t limit) +{ + if (limit >= 100 || limit == 0){ + return limit; + } + + uint16_t base = limit / 30U; + uint16_t remain = (limit % 30U) / 15U; + return 30 * base + 30 * remain; +} + uint16_t ZendureBattery::setOutputLimit(uint16_t limit) { if (_topicWrite.isEmpty()) { @@ -203,11 +214,7 @@ uint16_t ZendureBattery::setOutputLimit(uint16_t limit) } if (_stats->_output_limit != limit){ - if (limit < 100 && limit != 0){ - uint16_t base = limit / 30U; - uint16_t remain = (limit % 30U) / 15U; - limit = 30 * base + 30 * remain; - } + limit = calcOutputLimit(limit); MqttSettings.publishGeneric(_topicWrite, "{\"properties\": {\"" ZENDURE_REPORT_OUTPUT_LIMIT "\": " + String(limit) + "} }", false, 0); } diff --git a/webapp/src/locales/de.json b/webapp/src/locales/de.json index b2f501673..7bc20994f 100644 --- a/webapp/src/locales/de.json +++ b/webapp/src/locales/de.json @@ -711,11 +711,12 @@ "ZendureBypassModeAutomatic": "Automatisch", "ZendureBypassModeAlwaysOff": "Dauerhaft Ausgeschaltet", "ZendureBypassModeAlwaysOn": "Dauerhaft Eingeschaltet", - "ZendureMaxOutput": "Limitierung Ausgangsleistung", + "ZendureMaxOutput": "Wechselrichter Eingangsleistung", "ZendureAutoShutdown": "Automatisches Herunterfahren", "ZendureAutoShutdownDescription": "Das Batteriemanagementsystem wird bei Fehlender Ladespannung nach erreichen der unteren Entladegrenze automatisch heruntergefahren", "ZendureForceLimit": "Ausgangsleistung Vorgeben", - "ZendureForceLimitDescription": "Die angegeben Ausgangsleistung auch als Sollwert vorgeben. ACHTUNG: Damit ist keine dynamisch Steuerung mehr möglich!", + "ZendureForceLimitDescription": "Ausgangsleistung fest vorgeben. ACHTUNG: Damit ist keine dynamisch Steuerung mehr möglich!", + "ZendureOutputLimit": "Ausgangsleistung", "Percent": "%", "Watt": "W" }, diff --git a/webapp/src/locales/en.json b/webapp/src/locales/en.json index 1dae9cb95..fba4e537d 100644 --- a/webapp/src/locales/en.json +++ b/webapp/src/locales/en.json @@ -714,11 +714,12 @@ "ZendureBypassModeAutomatic": "Automatic", "ZendureBypassModeAlwaysOff": "Always Off", "ZendureBypassModeAlwaysOn": "Always On", - "ZendureMaxOutput": "Maximum output power", + "ZendureMaxOutput": "Inverter input power", "ZendureAutoShutdown": "Automatic shutdown", "ZendureAutoShutdownDescription": "If no charge voltage is available, the battery managent system will be shutdown after reaching the minimum charge level", "ZendureForceLimit": "Force Setpoint", - "ZendureForceLimitDescription": "Also use given output power as setpoint. WARNING: This prevents dynmic control!", + "ZendureForceLimitDescription": "Use fixed output power. WARNING: This prevents dynamic control!", + "ZendureOutputLimit": "Output power", "Percent": "%", "Watt": "W" }, diff --git a/webapp/src/locales/fr.json b/webapp/src/locales/fr.json index 6f361b1dc..dd5342ad8 100644 --- a/webapp/src/locales/fr.json +++ b/webapp/src/locales/fr.json @@ -637,11 +637,12 @@ "ZendureBypassModeAutomatic": "Automatic", "ZendureBypassModeAlwaysOff": "Always Off", "ZendureBypassModeAlwaysOn": "Always On", - "ZendureMaxOutput": "Maximum output power", + "ZendureMaxOutput": "Inverter input power", "ZendureAutoShutdown": "Automatic shutdown", "ZendureAutoShutdownDescription": "If no charge voltage is available, the battery managent system will be shutdown after reaching the minimum charge level", "ZendureForceLimit": "Force Setpoint", - "ZendureForceLimitDescription": "Also use given output power as setpoint. WARNING: This prevents dynmic control!", + "ZendureForceLimitDescription": "Use fixed output power. WARNING: This prevents dynamic control!", + "ZendureOutputLimit": "Output power", "Percent": "%", "Watt": "W" }, diff --git a/webapp/src/types/BatteryConfig.ts b/webapp/src/types/BatteryConfig.ts index 241ac165d..f8c2d653f 100644 --- a/webapp/src/types/BatteryConfig.ts +++ b/webapp/src/types/BatteryConfig.ts @@ -24,4 +24,5 @@ export interface BatteryConfig { zendure_max_output: number; zendure_auto_shutdown: boolean; zendure_force_limit: boolean; + zendure_output_limit: number; } diff --git a/webapp/src/views/BatteryAdminView.vue b/webapp/src/views/BatteryAdminView.vue index ceff02b45..d898eac24 100644 --- a/webapp/src/views/BatteryAdminView.vue +++ b/webapp/src/views/BatteryAdminView.vue @@ -252,6 +252,17 @@ :tooltip="$t('batteryadmin.ZendureForceLimitDescription')" /> + + (value >= 100 || value == 0 || value == 30 || value == 60 || value == 90) || 'Value must be 0,30,60,90 or >= 100' + //], }; }, created() {