From 14e8eada36925c50083ec1e123f7fe82b3898396 Mon Sep 17 00:00:00 2001 From: ndrsnhs Date: Mon, 18 Aug 2025 08:03:13 +0200 Subject: [PATCH 1/6] add max_soc --- packages/control/bat_all.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/control/bat_all.py b/packages/control/bat_all.py index d1085b0d2b..f1a78e383c 100644 --- a/packages/control/bat_all.py +++ b/packages/control/bat_all.py @@ -214,7 +214,8 @@ def _get_charging_power_left(self): # Speicher sollte weder ge- noch entladen werden. charging_power_left = self.data.get.power else: - if self.data.get.soc < config.min_bat_soc: + # Speicher soll geladen werden um min SoC zu erreichen + if self.data.get.soc <= config.min_bat_soc: if self.data.get.power < 0: # Wenn der Speicher entladen wird, darf diese Leistung nicht zum Laden der Fahrzeuge # genutzt werden. Wenn der Speicher schneller regelt als die LP, würde sonst der Speicher @@ -235,9 +236,11 @@ def _get_charging_power_left(self): # Speicher wird geladen charging_power_left = 0 self.data.set.regulate_up = True - elif int(self.data.get.soc) == config.min_bat_soc: + # Speicher zwischen min und max SoC + elif int(self.data.get.soc) > config.min_bat_soc and int(self.data.get.soc) < config.max_bat_soc: # Speicher sollte weder ge- noch entladen werden, um den Mindest-SoC zu halten. charging_power_left = self.data.get.power + # Speicher oberhalb max SoC. Darf bis min SoC entladen werden. else: if self.data.set.power_limit is None: if config.bat_power_discharge_active: From 7a0756f2615902c48feeae1e5681e86b6c2db7f5 Mon Sep 17 00:00:00 2001 From: ndrsnhs Date: Mon, 25 Aug 2025 11:17:42 +0200 Subject: [PATCH 2/6] add hysterese --- packages/control/bat_all.py | 25 +++++++++++++++++++++++-- packages/control/general.py | 2 ++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/control/bat_all.py b/packages/control/bat_all.py index f1a78e383c..00aeafadaf 100644 --- a/packages/control/bat_all.py +++ b/packages/control/bat_all.py @@ -78,6 +78,7 @@ class Set: charging_power_left: float = field(default=0, metadata={"topic": "set/charging_power_left"}) power_limit: Optional[float] = field(default=None, metadata={"topic": "set/power_limit"}) regulate_up: bool = field(default=False, metadata={"topic": "set/regulate_up"}) + charge_up: bool = field(default=False, metadata={"topic": "set/charge_up"}) def set_factory() -> Set: @@ -216,6 +217,7 @@ def _get_charging_power_left(self): else: # Speicher soll geladen werden um min SoC zu erreichen if self.data.get.soc <= config.min_bat_soc: + self.data.set.charge_up = True if self.data.get.power < 0: # Wenn der Speicher entladen wird, darf diese Leistung nicht zum Laden der Fahrzeuge # genutzt werden. Wenn der Speicher schneller regelt als die LP, würde sonst der Speicher @@ -238,10 +240,29 @@ def _get_charging_power_left(self): self.data.set.regulate_up = True # Speicher zwischen min und max SoC elif int(self.data.get.soc) > config.min_bat_soc and int(self.data.get.soc) < config.max_bat_soc: - # Speicher sollte weder ge- noch entladen werden, um den Mindest-SoC zu halten. - charging_power_left = self.data.get.power + # Speicher soll aktiv weder ge- noch entladen werden. + # Mindest-SoC wird gehalten oder es mit weiterem vorhanden Überschuss geladen. + if self.data.set.charge_up: + charging_power_left = self.data.get.power + # Speicher darf wegen Hysterese bis min_bat_soc entladen werden. + else: + if self.data.set.power_limit is None: + if config.bat_power_discharge_active: + # Wenn der Speicher mit mehr als der erlaubten Entladeleistung entladen wird, muss das + # vom Überschuss subtrahiert werden. + charging_power_left = config.bat_power_discharge + self.data.get.power + log.debug(f"Erlaubte Entlade-Leistung nutzen {charging_power_left}W") + else: + # Speicher sollte weder ge- noch entladen werden. + charging_power_left = self.data.get.power + else: + log.debug("Keine erlaubte Entladeleistung freigeben, da der Speicher mit einer vorgegeben " + "Leistung entladen wird.") + charging_power_left = 0 + # Speicher oberhalb max SoC. Darf bis min SoC entladen werden. else: + self.data.set.charge_up = False if self.data.set.power_limit is None: if config.bat_power_discharge_active: # Wenn der Speicher mit mehr als der erlaubten Entladeleistung entladen wird, muss das diff --git a/packages/control/general.py b/packages/control/general.py index 95253b3b2f..bc7cbe37e2 100644 --- a/packages/control/general.py +++ b/packages/control/general.py @@ -34,6 +34,8 @@ class PvCharging: "topic": "chargemode_config/pv_charging/bat_power_discharge_active"}) min_bat_soc: int = field(default=50, metadata={ "topic": "chargemode_config/pv_charging/min_bat_soc"}) + max_bat_soc: int = field(default=60, metadata={ + "topic": "chargemode_config/pv_charging/max_bat_soc"}) bat_mode: BatConsiderationMode = field(default=BatConsiderationMode.EV_MODE.value, metadata={ "topic": "chargemode_config/pv_charging/bat_mode"}) switch_off_delay: int = field(default=60, metadata={ From c36a4511fe714804b7fccc84654350ad4a426073 Mon Sep 17 00:00:00 2001 From: ndrsnhs Date: Tue, 26 Aug 2025 11:20:08 +0200 Subject: [PATCH 3/6] rename variables, add tests --- packages/control/bat_all.py | 14 +++++++------- packages/control/bat_all_test.py | 10 ++++++++++ packages/control/general.py | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/control/bat_all.py b/packages/control/bat_all.py index 00aeafadaf..60ac716fb1 100644 --- a/packages/control/bat_all.py +++ b/packages/control/bat_all.py @@ -78,7 +78,7 @@ class Set: charging_power_left: float = field(default=0, metadata={"topic": "set/charging_power_left"}) power_limit: Optional[float] = field(default=None, metadata={"topic": "set/power_limit"}) regulate_up: bool = field(default=False, metadata={"topic": "set/regulate_up"}) - charge_up: bool = field(default=False, metadata={"topic": "set/charge_up"}) + hysteresis_discharge: bool = field(default=False, metadata={"topic": "set/hysteresis_discharge"}) def set_factory() -> Set: @@ -216,8 +216,8 @@ def _get_charging_power_left(self): charging_power_left = self.data.get.power else: # Speicher soll geladen werden um min SoC zu erreichen - if self.data.get.soc <= config.min_bat_soc: - self.data.set.charge_up = True + if self.data.get.soc < config.min_bat_soc: + self.data.set.hysteresis_discharge = False if self.data.get.power < 0: # Wenn der Speicher entladen wird, darf diese Leistung nicht zum Laden der Fahrzeuge # genutzt werden. Wenn der Speicher schneller regelt als die LP, würde sonst der Speicher @@ -239,10 +239,10 @@ def _get_charging_power_left(self): charging_power_left = 0 self.data.set.regulate_up = True # Speicher zwischen min und max SoC - elif int(self.data.get.soc) > config.min_bat_soc and int(self.data.get.soc) < config.max_bat_soc: + elif int(self.data.get.soc) >= config.min_bat_soc and int(self.data.get.soc) < config.max_bat_soc: # Speicher soll aktiv weder ge- noch entladen werden. - # Mindest-SoC wird gehalten oder es mit weiterem vorhanden Überschuss geladen. - if self.data.set.charge_up: + # Mindest-SoC wird gehalten oder der Speicher mit weiterem vorhanden Überschuss geladen. + if self.data.set.hysteresis_discharge is False: charging_power_left = self.data.get.power # Speicher darf wegen Hysterese bis min_bat_soc entladen werden. else: @@ -262,7 +262,7 @@ def _get_charging_power_left(self): # Speicher oberhalb max SoC. Darf bis min SoC entladen werden. else: - self.data.set.charge_up = False + self.data.set.hysteresis_discharge = True if self.data.set.power_limit is None: if config.bat_power_discharge_active: # Wenn der Speicher mit mehr als der erlaubten Entladeleistung entladen wird, muss das diff --git a/packages/control/bat_all_test.py b/packages/control/bat_all_test.py index 2256629529..1429cdd1ad 100644 --- a/packages/control/bat_all_test.py +++ b/packages/control/bat_all_test.py @@ -80,6 +80,7 @@ class Params: expected_charging_power_left: float expected_regulate_up: bool power_limit: Optional[float] = None + hysteresis_discharge: Optional[bool] = False cases = [ @@ -128,6 +129,14 @@ class Params: "Speicher-Sperre aktiv"), PvCharging(bat_mode="min_soc_bat_mode", bat_power_discharge=500, bat_power_discharge_active=True), 400, 90, 0, False, 600), + Params(("Mindest-SoC, Hysterese, EV-Vorrang, keine Speichernutzung"), + PvCharging(bat_mode="min_soc_bat_mode"), 400, 60, 400, False, hysteresis_discharge=False), + Params(("Mindest-SoC, Hysterese, Speicherentladung, Speichernutzung erlaubt"), + PvCharging(bat_mode="min_soc_bat_mode", bat_power_discharge=500, bat_power_discharge_active=True), + 400, 60, 900, False, hysteresis_discharge=True), + Params(("Mindest-SoC, Hysterese, Speicherentladung, Speichernutzung erlaubt, Speicher-Sperre aktiv"), + PvCharging(bat_mode="min_soc_bat_mode", bat_power_discharge=500, bat_power_discharge_active=True), + 400, 60, 0, False, 600, hysteresis_discharge=True), ] @@ -138,6 +147,7 @@ def test_get_charging_power_left(params: Params, caplog, data_, monkeypatch): b_all.data.get.power = params.power b_all.data.get.soc = params.soc b_all.data.set.power_limit = params.power_limit + b_all.data.set.hysteresis_discharge = params.hysteresis_discharge b = Bat(0) b.data.get.power = params.power data.data.bat_data["bat0"] = b diff --git a/packages/control/general.py b/packages/control/general.py index bc7cbe37e2..52d8bf7a7e 100644 --- a/packages/control/general.py +++ b/packages/control/general.py @@ -34,7 +34,7 @@ class PvCharging: "topic": "chargemode_config/pv_charging/bat_power_discharge_active"}) min_bat_soc: int = field(default=50, metadata={ "topic": "chargemode_config/pv_charging/min_bat_soc"}) - max_bat_soc: int = field(default=60, metadata={ + max_bat_soc: int = field(default=70, metadata={ "topic": "chargemode_config/pv_charging/max_bat_soc"}) bat_mode: BatConsiderationMode = field(default=BatConsiderationMode.EV_MODE.value, metadata={ "topic": "chargemode_config/pv_charging/bat_mode"}) From 897493ab90b873e3e32336e6db27356145494608 Mon Sep 17 00:00:00 2001 From: ndrsnhs Date: Tue, 26 Aug 2025 14:56:36 +0200 Subject: [PATCH 4/6] update config --- packages/helpermodules/update_config.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/helpermodules/update_config.py b/packages/helpermodules/update_config.py index 74bd16464b..28d08619bc 100644 --- a/packages/helpermodules/update_config.py +++ b/packages/helpermodules/update_config.py @@ -57,7 +57,7 @@ class UpdateConfig: - DATASTORE_VERSION = 99 + DATASTORE_VERSION = 100 valid_topic = [ "^openWB/bat/config/bat_control_permitted$", @@ -233,6 +233,7 @@ class UpdateConfig: "^openWB/general/chargemode_config/phase_switch_delay$", "^openWB/general/chargemode_config/pv_charging/control_range$", "^openWB/general/chargemode_config/pv_charging/min_bat_soc$", + "^openWB/general/chargemode_config/pv_charging/max_bat_soc$", "^openWB/general/chargemode_config/pv_charging/bat_power_discharge$", "^openWB/general/chargemode_config/pv_charging/bat_power_discharge_active$", "^openWB/general/chargemode_config/pv_charging/bat_power_reserve$", @@ -536,6 +537,7 @@ class UpdateConfig: ("openWB/general/chargemode_config/pv_charging/bat_power_discharge", 1000), ("openWB/general/chargemode_config/pv_charging/bat_power_discharge_active", True), ("openWB/general/chargemode_config/pv_charging/min_bat_soc", 50), + ("openWB/general/chargemode_config/pv_charging/max_bat_soc", 70), ("openWB/general/chargemode_config/pv_charging/bat_power_reserve", 200), ("openWB/general/chargemode_config/pv_charging/bat_power_reserve_active", True), ("openWB/general/chargemode_config/pv_charging/control_range", [0, 230]), @@ -2588,3 +2590,14 @@ def upgrade_datastore_98(self) -> None: MessageType.INFO, ) self.__update_topic("openWB/system/datastore_version", 99) + + def upgrade_datastore_100(self) -> None: + if "openWB/general/chargemode_config/pv_charging/max_bat_soc" not in self.all_received_topics: + # bei Aktualisierung den max_bat_soc auf min_bat_soc setzen + # Regelung verhält sich dadurch wie bisher konfiguriert + # max_bat_soc kann nicht kleiner als min_bat_soc werden + min_bat_soc = decode_payload(self.all_received_topics[ + "openWB/general/chargemode_config/pv_charging/min_bat_soc"]) + + self.__update_topic("openWB/general/chargemode_config/pv_charging/max_bat_soc", min_bat_soc) + self.__update_topic("openWB/system/datastore_version", 100) From f3090f9e51ad8d0eeb4873b4bbbc7f991e9cfb4d Mon Sep 17 00:00:00 2001 From: ndrsnhs Date: Thu, 28 Aug 2025 09:06:43 +0200 Subject: [PATCH 5/6] remove whitespace --- packages/control/bat_all.py | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/control/bat_all.py b/packages/control/bat_all.py index 60ac716fb1..676ca7fd03 100644 --- a/packages/control/bat_all.py +++ b/packages/control/bat_all.py @@ -259,7 +259,6 @@ def _get_charging_power_left(self): log.debug("Keine erlaubte Entladeleistung freigeben, da der Speicher mit einer vorgegeben " "Leistung entladen wird.") charging_power_left = 0 - # Speicher oberhalb max SoC. Darf bis min SoC entladen werden. else: self.data.set.hysteresis_discharge = True From b864b827264332231fcf52030a2f17145f33d273 Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Thu, 30 Oct 2025 15:58:54 +0100 Subject: [PATCH 6/6] fix rebase --- packages/helpermodules/update_config.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/helpermodules/update_config.py b/packages/helpermodules/update_config.py index 28d08619bc..75d1fd5f3f 100644 --- a/packages/helpermodules/update_config.py +++ b/packages/helpermodules/update_config.py @@ -2591,13 +2591,12 @@ def upgrade_datastore_98(self) -> None: ) self.__update_topic("openWB/system/datastore_version", 99) - def upgrade_datastore_100(self) -> None: - if "openWB/general/chargemode_config/pv_charging/max_bat_soc" not in self.all_received_topics: - # bei Aktualisierung den max_bat_soc auf min_bat_soc setzen - # Regelung verhält sich dadurch wie bisher konfiguriert - # max_bat_soc kann nicht kleiner als min_bat_soc werden - min_bat_soc = decode_payload(self.all_received_topics[ - "openWB/general/chargemode_config/pv_charging/min_bat_soc"]) - - self.__update_topic("openWB/general/chargemode_config/pv_charging/max_bat_soc", min_bat_soc) + def upgrade_datastore_99(self) -> None: + # bei Aktualisierung den max_bat_soc auf min_bat_soc setzen + # Regelung verhält sich dadurch wie bisher konfiguriert + # max_bat_soc kann nicht kleiner als min_bat_soc werden + min_bat_soc = decode_payload(self.all_received_topics[ + "openWB/general/chargemode_config/pv_charging/min_bat_soc"]) + + self.__update_topic("openWB/general/chargemode_config/pv_charging/max_bat_soc", min_bat_soc) self.__update_topic("openWB/system/datastore_version", 100)