diff --git a/include/Configuration.h b/include/Configuration.h
index 3b99c38bb..49b1c60cc 100644
--- a/include/Configuration.h
+++ b/include/Configuration.h
@@ -145,6 +145,8 @@ struct BATTERY_CONFIG_T {
BatteryVoltageUnit MqttVoltageUnit;
bool EnableDischargeCurrentLimit;
float DischargeCurrentLimit;
+ float DischargeCurrentLimitBelowSoc;
+ float DischargeCurrentLimitBelowVoltage;
bool UseBatteryReportedDischargeCurrentLimit;
char MqttDischargeCurrentTopic[MQTT_MAX_TOPIC_STRLEN + 1];
char MqttDischargeCurrentJsonPath[BATTERY_JSON_MAX_PATH_STRLEN + 1];
diff --git a/include/defaults.h b/include/defaults.h
index 2ab8ec9e8..40ee5af12 100644
--- a/include/defaults.h
+++ b/include/defaults.h
@@ -156,6 +156,8 @@
#define BATTERY_JKBMS_POLLING_INTERVAL 5
#define BATTERY_ENABLE_DISCHARGE_CURRENT_LIMIT false
#define BATTERY_DISCHARGE_CURRENT_LIMIT 0.0
+#define BATTERY_DISCHARGE_CURRENT_LIMIT_BELOW_SOC 100.0
+#define BATTERY_DISCHARGE_CURRENT_LIMIT_BELOW_VOLTAGE 60.0
#define BATTERY_USE_BATTERY_REPORTED_DISCHARGE_CURRENT_LIMIT false
#define HUAWEI_ENABLED false
diff --git a/src/Battery.cpp b/src/Battery.cpp
index 7483c1de4..106888e2b 100644
--- a/src/Battery.cpp
+++ b/src/Battery.cpp
@@ -91,14 +91,26 @@ float BatteryClass::getDischargeCurrentLimit()
if (!config.Battery.EnableDischargeCurrentLimit) { return FLT_MAX; }
auto dischargeCurrentLimit = config.Battery.DischargeCurrentLimit;
- auto dischargeCurrentValid = dischargeCurrentLimit > 0.0f;
-
+ auto dischargeCurrentLimitValid = dischargeCurrentLimit > 0.0f;
+ auto dischargeCurrentLimitBelowSoc = config.Battery.DischargeCurrentLimitBelowSoc;
+ auto dischargeCurrentLimitBelowVoltage = config.Battery.DischargeCurrentLimitBelowVoltage;
+ auto statsSoCValid = getStats()->getSoCAgeSeconds() <= 60 && !config.PowerLimiter.IgnoreSoc;
+ auto statsSoC = statsSoCValid ? getStats()->getSoC() : 100.0; // fail open so we use voltage instead
+ auto statsVoltageValid = getStats()->getVoltageAgeSeconds() <= 60;
+ auto statsVoltage = statsVoltageValid ? getStats()->getVoltage() : 0.0; // fail closed
auto statsCurrentLimit = getStats()->getDischargeCurrentLimit();
auto statsLimitValid = config.Battery.UseBatteryReportedDischargeCurrentLimit
&& statsCurrentLimit >= 0.0f
&& getStats()->getDischargeCurrentLimitAgeSeconds() <= 60;
- if (statsLimitValid && dischargeCurrentValid) {
+
+ if (statsSoC > dischargeCurrentLimitBelowSoc && statsVoltage > dischargeCurrentLimitBelowVoltage) {
+ // Above SoC and Voltage thresholds, ignore custom limit.
+ // Battery-provided limit will still be applied.
+ dischargeCurrentLimitValid = false;
+ }
+
+ if (statsLimitValid && dischargeCurrentLimitValid) {
// take the lowest limit
return min(statsCurrentLimit, dischargeCurrentLimit);
}
@@ -107,7 +119,7 @@ float BatteryClass::getDischargeCurrentLimit()
return statsCurrentLimit;
}
- if (dischargeCurrentValid) {
+ if (dischargeCurrentLimitValid) {
return dischargeCurrentLimit;
}
diff --git a/src/Configuration.cpp b/src/Configuration.cpp
index 61ee7758d..b260ccee2 100644
--- a/src/Configuration.cpp
+++ b/src/Configuration.cpp
@@ -88,6 +88,8 @@ void ConfigurationClass::serializeBatteryConfig(BatteryConfig const& source, Jso
target["mqtt_voltage_unit"] = config.Battery.MqttVoltageUnit;
target["enable_discharge_current_limit"] = config.Battery.EnableDischargeCurrentLimit;
target["discharge_current_limit"] = config.Battery.DischargeCurrentLimit;
+ target["discharge_current_limit_below_soc"] = config.Battery.DischargeCurrentLimitBelowSoc;
+ target["discharge_current_limit_below_voltage"] = config.Battery.DischargeCurrentLimitBelowVoltage;
target["use_battery_reported_discharge_current_limit"] = config.Battery.UseBatteryReportedDischargeCurrentLimit;
target["mqtt_discharge_current_topic"] = config.Battery.MqttDischargeCurrentTopic;
target["mqtt_discharge_current_json_path"] = config.Battery.MqttDischargeCurrentJsonPath;
@@ -383,6 +385,8 @@ void ConfigurationClass::deserializeBatteryConfig(JsonObject const& source, Batt
target.MqttVoltageUnit = source["mqtt_voltage_unit"] | BatteryVoltageUnit::Volts;
target.EnableDischargeCurrentLimit = source["enable_discharge_current_limit"] | BATTERY_ENABLE_DISCHARGE_CURRENT_LIMIT;
target.DischargeCurrentLimit = source["discharge_current_limit"] | BATTERY_DISCHARGE_CURRENT_LIMIT;
+ target.DischargeCurrentLimitBelowSoc = source["discharge_current_limit_below_soc"] | BATTERY_DISCHARGE_CURRENT_LIMIT_BELOW_SOC;
+ target.DischargeCurrentLimitBelowVoltage = source["discharge_current_limit_below_voltage"] | BATTERY_DISCHARGE_CURRENT_LIMIT_BELOW_VOLTAGE;
target.UseBatteryReportedDischargeCurrentLimit = source["use_battery_reported_discharge_current_limit"] | BATTERY_USE_BATTERY_REPORTED_DISCHARGE_CURRENT_LIMIT;
strlcpy(target.MqttDischargeCurrentTopic, source["mqtt_discharge_current_topic"] | "", sizeof(config.Battery.MqttDischargeCurrentTopic));
strlcpy(target.MqttDischargeCurrentJsonPath, source["mqtt_discharge_current_json_path"] | "", sizeof(config.Battery.MqttDischargeCurrentJsonPath));
diff --git a/webapp/src/locales/de.json b/webapp/src/locales/de.json
index 1a16673b3..b2d7de185 100644
--- a/webapp/src/locales/de.json
+++ b/webapp/src/locales/de.json
@@ -724,6 +724,10 @@
"DischargeCurrentLimitConfiguration": "Einstellungen Entladestromlimit",
"LimitDischargeCurrent": "Entladestrom limitieren",
"DischargeCurrentLimit": "max. Entladestrom",
+ "DischargeCurrentLimitBelowSoc": "Limitieren unter SoC",
+ "DischargeCurrentLimitBelowSocInfo": "Das Entladestromlimit wird nur unter dieser SoC-Schwelle angewendet (nicht verwendet falls 'Batterie SoC ignorieren' aktiviert ist).",
+ "DischargeCurrentLimitBelowVoltage": "Limitieren unter Spannung",
+ "DischargeCurrentLimitBelowVoltageInfo": "Das Entladestromlimit wird nur unter dieser Spannungs-Schwelle angewendet (wenn SoC ignoriert oder nicht verfügbar).",
"UseBatteryReportedDischargeCurrentLimit": "Von der Batterie übermitteltes Limit verwenden",
"BatteryReportedDischargeCurrentLimitInfo": "Hinweis: Das niedrigste Limit wird angewendet, wobei das von der Batterie übermittelte Entladestromlimit nur verwendet wird, wenn in der letzten Minute ein Update eingegangen ist; andernfalls dient das zuvor festgelegte Limit als Fallback.",
"MqttDischargeCurrentTopic": "Topic für Entladestromlimit",
diff --git a/webapp/src/locales/en.json b/webapp/src/locales/en.json
index 69a288778..425ad9972 100644
--- a/webapp/src/locales/en.json
+++ b/webapp/src/locales/en.json
@@ -727,6 +727,10 @@
"DischargeCurrentLimitConfiguration": "Discharge Current Limit Settings",
"LimitDischargeCurrent": "Limit Discharge Current",
"DischargeCurrentLimit": "max. Discharge Current",
+ "DischargeCurrentLimitBelowSoc": "Apply limit below SoC",
+ "DischargeCurrentLimitBelowSocInfo": "The discharge current limit is not applied above this SoC (not used if 'Ignore Battery SoC' is enabled).",
+ "DischargeCurrentLimitBelowVoltage": "Apply limit below voltage",
+ "DischargeCurrentLimitBelowVoltageInfo": "The discharge current limit is not applied above this voltage (used if SoC ignored or unavailable).",
"UseBatteryReportedDischargeCurrentLimit": "Use Battery-Reported limit",
"BatteryReportedDischargeCurrentLimitInfo": "Hint: The lowest limit will be applied, with the battery-reported discharge current limit used only if an update was received in the last minute; otherwise, the previously specified limit will act as a fallback.",
"MqttDischargeCurrentTopic": "Discharge Current Limit Value Topic",
diff --git a/webapp/src/types/BatteryConfig.ts b/webapp/src/types/BatteryConfig.ts
index a781b74a0..67792a710 100644
--- a/webapp/src/types/BatteryConfig.ts
+++ b/webapp/src/types/BatteryConfig.ts
@@ -11,6 +11,8 @@ export interface BatteryConfig {
mqtt_voltage_unit: number;
enable_discharge_current_limit: boolean;
discharge_current_limit: number;
+ discharge_current_limit_below_soc: number;
+ discharge_current_limit_below_voltage: number;
use_battery_reported_discharge_current_limit: boolean;
mqtt_discharge_current_topic: string;
mqtt_discharge_current_json_path: string;
diff --git a/webapp/src/views/BatteryAdminView.vue b/webapp/src/views/BatteryAdminView.vue
index 4a07357c7..b55b88e51 100644
--- a/webapp/src/views/BatteryAdminView.vue
+++ b/webapp/src/views/BatteryAdminView.vue
@@ -141,6 +141,28 @@
postfix="A"
/>
+
+
+
+