diff --git a/packages/control/bat_all.py b/packages/control/bat_all.py index 353aad0c50..2dae1f760a 100644 --- a/packages/control/bat_all.py +++ b/packages/control/bat_all.py @@ -65,6 +65,12 @@ class ManualMode(Enum): MANUAL_DISCHARGE = "manual_discharge" # in DE nicht erlaubt +class CurrentState(Enum): + STARTUP = "startup" + ACTIVE = "active" + IDLE = "idle" + + @dataclass class Config: configured: bool = field(default=False, metadata={"topic": "config/configured"}) @@ -76,8 +82,8 @@ class Config: metadata={"topic": "config/bat_control_condition"}) manual_mode: str = field(default=ManualMode.MANUAL_DISABLE.value, metadata={"topic": "config/manual_mode"}) - bat_control_min_soc: str = field(default=5, metadata={"topic": "config/bat_control_min_soc"}) - bat_control_max_soc: str = field(default=90, metadata={"topic": "config/bat_control_max_soc"}) + bat_control_min_soc: int = field(default=10, metadata={"topic": "config/bat_control_min_soc"}) + bat_control_max_soc: int = field(default=90, metadata={"topic": "config/bat_control_max_soc"}) price_limit_activated: bool = field(default=False, metadata={"topic": "config/price_limit_activated"}) price_charge_activated: bool = field(default=False, metadata={"topic": "config/price_charge_activated"}) price_limit: float = field(default=0.30, metadata={"topic": "config/price_limit"}) @@ -111,6 +117,8 @@ class Set: power_limit: Optional[float] = field(default=None, metadata={"topic": "set/power_limit"}) regulate_up: bool = field(default=False, metadata={"topic": "set/regulate_up"}) hysteresis_discharge: bool = field(default=False, metadata={"topic": "set/hysteresis_discharge"}) + current_state: str = field(default=CurrentState.STARTUP.value, metadata={"topic": "set/current_state"}) + set_limit: bool = field(default=False, metadata={"topic": "set/set_limit"}) def set_factory() -> Set: @@ -585,6 +593,21 @@ def get_power_limit(self): self.data.set.power_limit = None log.debug("Speicher-Leistung nicht begrenzen") + if ((self.data.config.bat_control_permitted is False or + self.data.config.bat_control_activated is False) + and self.data.set.current_state == CurrentState.STARTUP.value): + self.data.set.set_limit = False + elif (self.data.set.current_state == CurrentState.IDLE.value and + charge_mode == BatChargeMode.BAT_SELF_REGULATION): + self.data.set.set_limit = False + else: + self.data.set.set_limit = True + + if charge_mode == BatChargeMode.BAT_SELF_REGULATION: + self.data.set.current_state = CurrentState.IDLE.value + else: + self.data.set.current_state = CurrentState.ACTIVE.value + def get_controllable_bat_components() -> List: bat_components = [] diff --git a/packages/control/bat_all_test.py b/packages/control/bat_all_test.py index 0b43a7560d..ee9cf5fe4e 100644 --- a/packages/control/bat_all_test.py +++ b/packages/control/bat_all_test.py @@ -18,6 +18,7 @@ @pytest.fixture(autouse=True) def data_fixture() -> None: + data.data_init(Mock()) data.data.general_data = General() data.data.cp_all_data = Mock(spec=AllChargepoints, data=Mock( spec=AllChargepointData, get=Mock(spec=AllGet, power=0))) @@ -194,7 +195,7 @@ class BatControlParams: bat_control_permitted: bool = True bat_control_activated: bool = True max_charge_power: float = 5000 - max_discharge_power: float = 5000 + max_discharge_power: float = -5000 bat_control_min_soc: float = 10.0 bat_control_max_soc: float = 90.0 price_limit_activated: bool = False diff --git a/packages/control/process.py b/packages/control/process.py index 2386276f2f..bfd0f407eb 100644 --- a/packages/control/process.py +++ b/packages/control/process.py @@ -62,13 +62,14 @@ def process_algorithm_results(self) -> None: cp.remember_previous_values() except Exception: log.exception("Fehler im Process-Modul für Ladepunkt "+str(cp)) - for bat_component in get_controllable_bat_components(): - modules_threads.append( - Thread( - target=set_power_limit_wrapper, - args=(bat_component, - data.data.bat_data[f"bat{bat_component.component_config.id}"].data.set.power_limit), - name=f"set power limit {bat_component.component_config.id}")) + if data.data.bat_all_data.data.set.set_limit: + for bat_component in get_controllable_bat_components(): + modules_threads.append( + Thread( + target=set_power_limit_wrapper, + args=(bat_component, + data.data.bat_data[f"bat{bat_component.component_config.id}"].data.set.power_limit), + name=f"set power limit {bat_component.component_config.id}")) for action in data.data.io_actions.actions.values(): if isinstance(action, DimmingDirectControl): for d in action.config.configuration.devices: diff --git a/packages/helpermodules/setdata.py b/packages/helpermodules/setdata.py index b7ad123c60..4ba7a0f63c 100644 --- a/packages/helpermodules/setdata.py +++ b/packages/helpermodules/setdata.py @@ -673,9 +673,10 @@ def process_bat_topic(self, msg: mqtt.MQTTMessage): "openWB/set/bat/set/regulate_up" in msg.topic or "openWB/set/bat/set/hysteresis_discharge" in msg.topic): self._validate_value(msg, bool) - elif (re.search("openWB/set/bat/[0-9]+/get/max_charge_power$", msg.topic) is not None or - re.search("openWB/set/bat/[0-9]+/get/max_discharge_power$", msg.topic) is not None): + elif re.search("^openWB/set/bat/[0-9]+/get/max_charge_power$", msg.topic) is not None: self._validate_value(msg, float, [(0, float("inf"))]) + elif re.search("^openWB/set/bat/[0-9]+/get/max_discharge_power$", msg.topic) is not None: + self._validate_value(msg, float, [(None, 0)]) elif (re.search("openWB/set/bat/[0-9]+/get/state_str$", msg.topic) is not None): self._validate_value(msg, str) elif ("openWB/set/bat/config/price_limit" in msg.topic or diff --git a/packages/helpermodules/update_config.py b/packages/helpermodules/update_config.py index 4d208a84ef..3384fdd9ef 100644 --- a/packages/helpermodules/update_config.py +++ b/packages/helpermodules/update_config.py @@ -57,7 +57,7 @@ class UpdateConfig: - DATASTORE_VERSION = 120 + DATASTORE_VERSION = 121 valid_topic = [ "^openWB/bat/config/bat_control_permitted$", @@ -3058,3 +3058,13 @@ def upgrade(topic: str, payload) -> Optional[dict]: return {topic: mode} self._loop_all_received_topics(upgrade) self._append_datastore_version(120) + + def upgrade_datastore_121(self) -> None: + def upgrade(topic: str, payload) -> Optional[dict]: + if re.search(r"^openWB/bat/[0-9]+/get/max_discharge_power$", topic) is not None: + payload = decode_payload(payload) + if isinstance(payload, (int, float)): + payload = -abs(payload) + return {topic: payload} + self._loop_all_received_topics(upgrade) + self._append_datastore_version(121)