From fc11c3c2e5ebb1bfc968ee776fbc370476efba52 Mon Sep 17 00:00:00 2001 From: Duco Sebel <74970928+DCSBL@users.noreply.github.com> Date: Thu, 21 May 2026 14:10:02 +0200 Subject: [PATCH 1/3] Add support for predictive mode --- homewizard_energy/models.py | 3 +++ tests/v2/__snapshots__/test_v2_batteries.ambr | 3 +++ tests/v2/fixtures/HWE-P1/batteries_2_3_0.json | 10 ++++++++++ tests/v2/test_v2_batteries.py | 4 +++- 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/v2/fixtures/HWE-P1/batteries_2_3_0.json diff --git a/homewizard_energy/models.py b/homewizard_energy/models.py index 1e76086..a94c278 100644 --- a/homewizard_energy/models.py +++ b/homewizard_energy/models.py @@ -667,6 +667,8 @@ def from_mode( ) case Batteries.Mode.TO_FULL: return BatteriesUpdate(mode=Batteries.Mode.TO_FULL) + case Batteries.Mode.PREDICTIVE: + return BatteriesUpdate(mode=Batteries.Mode.PREDICTIVE) case Batteries.Mode.STANDBY: return BatteriesUpdate(mode=Batteries.Mode.STANDBY, permissions=[]) @@ -686,6 +688,7 @@ class Mode(StrEnum): ZERO = "zero" TO_FULL = "to_full" + PREDICTIVE = "predictive" STANDBY = "standby" ZERO_CHARGE_ONLY = "zero_charge_only" ZERO_DISCHARGE_ONLY = "zero_discharge_only" diff --git a/tests/v2/__snapshots__/test_v2_batteries.ambr b/tests/v2/__snapshots__/test_v2_batteries.ambr index 0aa593d..45408ed 100644 --- a/tests/v2/__snapshots__/test_v2_batteries.ambr +++ b/tests/v2/__snapshots__/test_v2_batteries.ambr @@ -11,3 +11,6 @@ # name: test_batteries[HWE-P1-fixtures0].1 Batteries(mode=, permissions=[, ], power_w=-404.0, target_power_w=-400.0, max_consumption_w=1600.0, max_production_w=800.0, battery_count=2) # --- +# name: test_batteries[HWE-P1-fixtures0].2 + Batteries(mode=, permissions=[, ], power_w=-404.0, target_power_w=-400.0, max_consumption_w=1600.0, max_production_w=800.0, battery_count=2) +# --- diff --git a/tests/v2/fixtures/HWE-P1/batteries_2_3_0.json b/tests/v2/fixtures/HWE-P1/batteries_2_3_0.json new file mode 100644 index 0000000..b7eae06 --- /dev/null +++ b/tests/v2/fixtures/HWE-P1/batteries_2_3_0.json @@ -0,0 +1,10 @@ +{ + "mode": "predictive", + "permissions": ["charge_allowed", "discharge_allowed"], + "charge_to_full": false, + "battery_count": 2, + "power_w": -404, + "target_power_w": -400, + "max_consumption_w": 1600, + "max_production_w": 800 +} diff --git a/tests/v2/test_v2_batteries.py b/tests/v2/test_v2_batteries.py index 46a882c..b68fa53 100644 --- a/tests/v2/test_v2_batteries.py +++ b/tests/v2/test_v2_batteries.py @@ -15,7 +15,7 @@ @pytest.mark.parametrize( ("model", "fixtures"), [ - ("HWE-P1", ["batteries_2_1_0", "batteries_2_2_0"]), + ("HWE-P1", ["batteries_2_1_0", "batteries_2_2_0", "batteries_2_3_0"]), ("HWE-KWH1", ["batteries"]), ("HWE-KWH3", ["batteries"]), ], @@ -72,6 +72,7 @@ def test_batteries_battery_count_optional(): [Batteries.Permissions.DISCHARGE_ALLOWED], ), (Batteries.Mode.TO_FULL, Batteries.Mode.TO_FULL, None), + (Batteries.Mode.PREDICTIVE, Batteries.Mode.PREDICTIVE, None), (Batteries.Mode.STANDBY, Batteries.Mode.STANDBY, []), ], ) @@ -111,6 +112,7 @@ def test_batteries_update_modes_and_permissions( (Batteries.Mode.TO_FULL, [], Batteries.Mode.TO_FULL), (Batteries.Mode.ZERO, None, Batteries.Mode.ZERO), (Batteries.Mode.STANDBY, None, Batteries.Mode.STANDBY), + (Batteries.Mode.PREDICTIVE, None, Batteries.Mode.PREDICTIVE), (Batteries.Mode.TO_FULL, None, Batteries.Mode.TO_FULL), ], ) From f1746de782de67eeaa80a1fddba4c4fd18979f77 Mon Sep 17 00:00:00 2001 From: Duco Sebel <74970928+DCSBL@users.noreply.github.com> Date: Thu, 21 May 2026 14:16:38 +0200 Subject: [PATCH 2/3] Add extra test --- tests/v2/test_v2_batteries.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/v2/test_v2_batteries.py b/tests/v2/test_v2_batteries.py index b68fa53..8beabd0 100644 --- a/tests/v2/test_v2_batteries.py +++ b/tests/v2/test_v2_batteries.py @@ -131,6 +131,40 @@ def test_set_mode_based_on_permissions(mode, permissions, expected_mode): assert model.mode == expected_mode +@pytest.mark.parametrize( + "permissions", + [ + ([]), + ([Batteries.Permissions.DISCHARGE_ALLOWED]), + ( + [ + Batteries.Permissions.CHARGE_ALLOWED, + ] + ), + ( + [ + Batteries.Permissions.CHARGE_ALLOWED, + Batteries.Permissions.DISCHARGE_ALLOWED, + ] + ), + ], +) +def test_predictive_mode_with_various_permissions(permissions): + """Test setting Batteries mode to PREDICTIVE with various permissions.""" + model = Batteries.from_dict( + { + "mode": "predictive", + "permissions": permissions, + "power_w": 0.0, + "target_power_w": 0.0, + "max_consumption_w": 0.0, + "max_production_w": 0.0, + } + ) + assert model.mode == Batteries.Mode.PREDICTIVE + assert model.permissions == permissions + + def test_set_batteries_update_with_invalid_permissions_raises(): """Test BatteriesUpdate with invalid permissions raises ValueError.""" with pytest.raises(ValueError): From 5d8d8c99e0eed9ab77e621462628b22887710f15 Mon Sep 17 00:00:00 2001 From: Duco Sebel <74970928+DCSBL@users.noreply.github.com> Date: Thu, 21 May 2026 16:02:03 +0200 Subject: [PATCH 3/3] Update 'supported_battery_modes' --- homewizard_energy/models.py | 3 ++ tests/v2/test_v2_device.py | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/homewizard_energy/models.py b/homewizard_energy/models.py index a94c278..8825f6e 100644 --- a/homewizard_energy/models.py +++ b/homewizard_energy/models.py @@ -203,6 +203,9 @@ def supported_battery_modes(self) -> list[Batteries.Mode] | None: Batteries.Mode.ZERO_DISCHARGE_ONLY, ] + if self.api_version >= AwesomeVersion("2.3.0"): + modes += [Batteries.Mode.PREDICTIVE] + return modes diff --git a/tests/v2/test_v2_device.py b/tests/v2/test_v2_device.py index 074ed72..86b0cf2 100644 --- a/tests/v2/test_v2_device.py +++ b/tests/v2/test_v2_device.py @@ -153,6 +153,66 @@ async def test_device_support_functions( Batteries.Mode.ZERO_DISCHARGE_ONLY, ], ), + ( + Model.P1_METER, + "2.3.0", + [ + Batteries.Mode.ZERO, + Batteries.Mode.TO_FULL, + Batteries.Mode.STANDBY, + Batteries.Mode.ZERO_CHARGE_ONLY, + Batteries.Mode.ZERO_DISCHARGE_ONLY, + Batteries.Mode.PREDICTIVE, + ], + ), + ( + Model.ENERGY_METER_1_PHASE, + "2.3.0", + [ + Batteries.Mode.ZERO, + Batteries.Mode.TO_FULL, + Batteries.Mode.STANDBY, + Batteries.Mode.ZERO_CHARGE_ONLY, + Batteries.Mode.ZERO_DISCHARGE_ONLY, + Batteries.Mode.PREDICTIVE, + ], + ), + ( + Model.ENERGY_METER_3_PHASE, + "2.3.0", + [ + Batteries.Mode.ZERO, + Batteries.Mode.TO_FULL, + Batteries.Mode.STANDBY, + Batteries.Mode.ZERO_CHARGE_ONLY, + Batteries.Mode.ZERO_DISCHARGE_ONLY, + Batteries.Mode.PREDICTIVE, + ], + ), + ( + Model.ENERGY_METER_EASTRON_SDM230, + "2.3.0", + [ + Batteries.Mode.ZERO, + Batteries.Mode.TO_FULL, + Batteries.Mode.STANDBY, + Batteries.Mode.ZERO_CHARGE_ONLY, + Batteries.Mode.ZERO_DISCHARGE_ONLY, + Batteries.Mode.PREDICTIVE, + ], + ), + ( + Model.ENERGY_METER_EASTRON_SDM630, + "2.3.0", + [ + Batteries.Mode.ZERO, + Batteries.Mode.TO_FULL, + Batteries.Mode.STANDBY, + Batteries.Mode.ZERO_CHARGE_ONLY, + Batteries.Mode.ZERO_DISCHARGE_ONLY, + Batteries.Mode.PREDICTIVE, + ], + ), ], ) def test_supported_battery_modes(product_type, api_version, expected_modes):