diff --git a/homewizard_energy/models.py b/homewizard_energy/models.py index 1e76086..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 @@ -667,6 +670,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 +691,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..8beabd0 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), ], ) @@ -129,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): 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):