diff --git a/custom_components/solar_optimizer/managed_device.py b/custom_components/solar_optimizer/managed_device.py index ed007b8..5711e25 100644 --- a/custom_components/solar_optimizer/managed_device.py +++ b/custom_components/solar_optimizer/managed_device.py @@ -416,10 +416,17 @@ def is_usable(self) -> bool: @property def should_be_forced_offpeak(self) -> bool: """True is we are offpeak and the max_on_time is not exceeded""" - return ( - self.now.time() >= self._offpeak_time - or self.now.time() < self._coordinator.raz_time - ) and self._on_time_sec < self._max_on_time_per_day_sec + if self._offpeak_time >= self._coordinator.raz_time: + return ( + self.now.time() >= self._offpeak_time + or self.now.time() < self._coordinator.raz_time + ) and self._on_time_sec < self._max_on_time_per_day_sec + else: + return ( + self.now.time() >= self._offpeak_time + and self.now.time() < self._coordinator.raz_time + and self._on_time_sec < self._max_on_time_per_day_sec + ) @property def is_waiting(self): diff --git a/custom_components/solar_optimizer/sensor.py b/custom_components/solar_optimizer/sensor.py index 11d8079..0930dc8 100644 --- a/custom_components/solar_optimizer/sensor.py +++ b/custom_components/solar_optimizer/sensor.py @@ -324,6 +324,7 @@ def update_custom_attributes(self): "max_on_time_hms": seconds_to_hms(self._device.max_on_time_per_day_sec), "raz_time": self._coordinator.raz_time, "should_be_forced_offpeak": self._device.should_be_forced_offpeak, + "offpeak_time": self._device.offpeak_time, } @property diff --git a/tests/conftest.py b/tests/conftest.py index fa64825..c09d18a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -240,3 +240,45 @@ async def init_solar_optimizer_with_2_devices_min_on_time_ok( hass, "solar_optimizer", config_2_devices_min_on_time_ok ) return hass.data[DOMAIN]["coordinator"] + + +@pytest.fixture(name="config_devices_offpeak_morning") +def define_config_devices_offpeak_morning(): + """Define a configuration with 1 devices which have its offpeak_time on morning""" + + return { + "solar_optimizer": { + "algorithm": { + "initial_temp": 1000, + "min_temp": 0.1, + "cooling_factor": 0.95, + "max_iteration_number": 1000, + }, + "devices": [ + { + "name": "Equipement A", + "entity_id": "input_boolean.fake_device_a", + "power_max": 1000, + "check_usable_template": "{{ True }}", + "duration_min": 2, + "duration_stop_min": 1, + "action_mode": "service_call", + "activation_service": "input_boolean/turn_on", + "deactivation_service": "input_boolean/turn_off", + "battery_soc_threshold": 30, + "max_on_time_per_day_min": 10, + "min_on_time_per_day_min": 5, + "offpeak_time": "01:00", + } + ], + } + } + + +@pytest.fixture(name="init_solar_optimizer_with_devices_offpeak_morning") +async def init_solar_optimizer_with_devices_offpeak_morning( + hass, config_devices_offpeak_morning +) -> SolarOptimizerCoordinator: + """Initialization of Solar Optimizer with 2 managed device""" + await async_setup_component(hass, "solar_optimizer", config_devices_offpeak_morning) + return hass.data[DOMAIN]["coordinator"] diff --git a/tests/test_config_flow.py b/tests/test_config_flow.py index c6f3c5c..cfb8c90 100644 --- a/tests/test_config_flow.py +++ b/tests/test_config_flow.py @@ -34,13 +34,22 @@ async def test_empty_config(hass: HomeAssistant): @pytest.mark.parametrize( "power_consumption,power_production,sell_cost,buy_cost, raz_time", - itertools.product( - ["sensor.power_consumption", "input_number.power_consumption"], - ["sensor.power_production", "input_number.power_production"], - ["sensor.sell_cost", "input_number.sell_cost"], - ["sensor.buy_cost", "input_number.buy_cost"], - ["00:00", "04:00"], - ), + [ + ( + "sensor.power_consumption", + "sensor.power_production", + "sensor.sell_cost", + "sensor.buy_cost", + "00:00", + ), + ( + "input_number.power_consumption", + "input_number.power_production", + "input_number.sell_cost", + "input_number.buy_cost", + "04:00", + ), + ], ) async def test_config_inputs_wo_battery( hass: HomeAssistant, diff --git a/tests/test_min_in_time.py b/tests/test_min_in_time.py index 8bc7f17..f61b0b9 100644 --- a/tests/test_min_in_time.py +++ b/tests/test_min_in_time.py @@ -154,6 +154,38 @@ async def test_min_on_time_config_ko_2( assert coordinator is None +@pytest.mark.parametrize( + "current_datetime, should_be_forced_offpeak", + [ + (datetime(2024, 11, 10, 10, 00, 00), False), + (datetime(2024, 11, 10, 0, 59, 00), False), + (datetime(2024, 11, 10, 1, 0, 00), True), + ], +) +async def test_min_on_time_config_ko_3( + hass: HomeAssistant, + init_solar_optimizer_with_devices_offpeak_morning, + init_solar_optimizer_entry, + current_datetime, + should_be_forced_offpeak, +): + """Testing min_in_time with min requires offpeak_time < raz_time""" + + coordinator: SolarOptimizerCoordinator = ( + init_solar_optimizer_with_devices_offpeak_morning + ) + + assert coordinator is not None + + assert len(coordinator.devices) == 1 + device = coordinator.devices[0] + assert device.offpeak_time == time(1, 0, 0) + + device._set_now(current_datetime.replace(tzinfo=get_tz(hass))) + + assert device.should_be_forced_offpeak is should_be_forced_offpeak + + async def test_nominal_use_min_on_time( hass: HomeAssistant, init_solar_optimizer_with_2_devices_min_on_time_ok,