From 0b5d937968df6925c44260e730bf38aa47c1cc8c Mon Sep 17 00:00:00 2001 From: Jean-Marc Collin Date: Sat, 4 Jan 2025 09:39:42 +0000 Subject: [PATCH] All tests ok --- tests/commons.py | 6 + tests/test_binary_sensors.py | 63 ++++++---- tests/test_bugs.py | 59 +++++++-- tests/test_central_config.py | 54 ++++---- tests/test_central_power_manager.py | 2 +- tests/test_multiple_switch.py | 183 ++++++++++++++++------------ 6 files changed, 231 insertions(+), 136 deletions(-) diff --git a/tests/commons.py b/tests/commons.py index 7a54d3d..ca78cf7 100644 --- a/tests/commons.py +++ b/tests/commons.py @@ -1111,3 +1111,9 @@ class SideEffects: def add_or_update_side_effect(self, key: str, new_value: Any): """Update the value of a side effect""" self._current_side_effects[key] = new_value + + +async def do_central_power_refresh(hass): + """Do a central power refresh""" + await VersatileThermostatAPI.get_vtherm_api().central_power_manager.refresh_state() + return hass.async_block_till_done() diff --git a/tests/test_binary_sensors.py b/tests/test_binary_sensors.py index 2829566..c39e3ed 100644 --- a/tests/test_binary_sensors.py +++ b/tests/test_binary_sensors.py @@ -1,4 +1,4 @@ -# pylint: disable=wildcard-import, unused-wildcard-import, unused-argument, line-too-long +# pylint: disable=wildcard-import, unused-wildcard-import, unused-argument, line-too-long, protected-access """ Test the normal start of a Thermostat """ from unittest.mock import patch @@ -107,9 +107,16 @@ async def test_overpowering_binary_sensors( skip_hass_states_is_state, skip_turn_on_off_heater, skip_send_event, + init_central_power_manager, ): """Test the overpowering binary sensors in thermostat type""" + temps = { + "eco": 17, + "comfort": 18, + "boost": 19, + } + entry = MockConfigEntry( domain=DOMAIN, title="TheOverSwitchMockName", @@ -122,9 +129,6 @@ async def test_overpowering_binary_sensors( CONF_CYCLE_MIN: 5, CONF_TEMP_MIN: 15, CONF_TEMP_MAX: 30, - "eco_temp": 17, - "comfort_temp": 18, - "boost_temp": 19, CONF_USE_WINDOW_FEATURE: False, CONF_USE_MOTION_FEATURE: False, CONF_USE_POWER_FEATURE: True, @@ -136,15 +140,13 @@ async def test_overpowering_binary_sensors( CONF_MINIMAL_ACTIVATION_DELAY: 30, CONF_SAFETY_DELAY_MIN: 5, CONF_SAFETY_MIN_ON_PERCENT: 0.3, - CONF_POWER_SENSOR: "sensor.mock_power_sensor", - CONF_MAX_POWER_SENSOR: "sensor.mock_power_max_sensor", CONF_DEVICE_POWER: 100, CONF_PRESET_POWER: 12, }, ) entity: BaseThermostat = await create_thermostat( - hass, entry, "climate.theoverswitchmockname" + hass, entry, "climate.theoverswitchmockname", temps ) assert entity @@ -153,7 +155,8 @@ async def test_overpowering_binary_sensors( ) assert overpowering_binary_sensor - now: datetime = datetime.now(tz=get_tz(hass)) + now: datetime = NowClass.get_now(hass) + VersatileThermostatAPI.get_vtherm_api()._set_now(now) # Overpowering should be not set because poer have not been received await entity.async_set_preset_mode(PRESET_COMFORT) @@ -166,22 +169,40 @@ async def test_overpowering_binary_sensors( assert overpowering_binary_sensor.state is STATE_OFF assert overpowering_binary_sensor.device_class == BinarySensorDeviceClass.POWER - await send_power_change_event(entity, 100, now) - await send_max_power_change_event(entity, 150, now) - assert entity.power_manager.is_overpowering_detected is True - assert entity.power_manager.overpowering_state is STATE_ON + # Send power mesurement + side_effects = SideEffects( + { + "sensor.the_power_sensor": State("sensor.the_power_sensor", 100), + "sensor.the_max_power_sensor": State("sensor.the_max_power_sensor", 150), + }, + State("unknown.entity_id", "unknown"), + ) + # fmt:off + with patch("homeassistant.core.StateMachine.get", side_effect=side_effects.get_side_effects()): + # fmt: on + await send_power_change_event(entity, 100, now) + await send_max_power_change_event(entity, 150, now) - # Simulate the event reception - await overpowering_binary_sensor.async_my_climate_changed() - assert overpowering_binary_sensor.state == STATE_ON + assert entity.power_manager.is_overpowering_detected is True + assert entity.power_manager.overpowering_state is STATE_ON + + # Simulate the event reception + await overpowering_binary_sensor.async_my_climate_changed() + assert overpowering_binary_sensor.state == STATE_ON # set max power to a low value - await send_max_power_change_event(entity, 201, now) - assert entity.power_manager.is_overpowering_detected is False - assert entity.power_manager.overpowering_state is STATE_OFF - # Simulate the event reception - await overpowering_binary_sensor.async_my_climate_changed() - assert overpowering_binary_sensor.state == STATE_OFF + side_effects.add_or_update_side_effect("sensor.the_max_power_sensor", State("sensor.the_max_power_sensor", 201)) + # fmt:off + with patch("homeassistant.core.StateMachine.get", side_effect=side_effects.get_side_effects()): + # fmt: on + now = now + timedelta(seconds=61) + VersatileThermostatAPI.get_vtherm_api()._set_now(now) + await send_max_power_change_event(entity, 201, now) + assert entity.power_manager.is_overpowering_detected is False + assert entity.power_manager.overpowering_state is STATE_OFF + # Simulate the event reception + await overpowering_binary_sensor.async_my_climate_changed() + assert overpowering_binary_sensor.state == STATE_OFF @pytest.mark.parametrize("expected_lingering_tasks", [True]) diff --git a/tests/test_bugs.py b/tests/test_bugs.py index 4ceba72..6df6bf6 100644 --- a/tests/test_bugs.py +++ b/tests/test_bugs.py @@ -266,7 +266,9 @@ async def test_bug_272( @pytest.mark.parametrize("expected_lingering_tasks", [True]) @pytest.mark.parametrize("expected_lingering_timers", [True]) -async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state): +async def test_bug_407( + hass: HomeAssistant, skip_hass_states_is_state, init_central_power_manager +): """Test the followin case in power management: 1. a heater is active (heating). So the power consumption takes the heater power into account. We suppose the power consumption is near the threshold, 2. the user switch preset let's say from Comfort to Boost, @@ -275,6 +277,12 @@ async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state): """ + temps = { + "eco": 17, + "comfort": 18, + "boost": 19, + } + entry = MockConfigEntry( domain=DOMAIN, title="TheOverSwitchMockName", @@ -287,9 +295,6 @@ async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state): CONF_CYCLE_MIN: 5, CONF_TEMP_MIN: 15, CONF_TEMP_MAX: 30, - "eco_temp": 17, - "comfort_temp": 18, - "boost_temp": 19, CONF_USE_WINDOW_FEATURE: False, CONF_USE_MOTION_FEATURE: False, CONF_USE_POWER_FEATURE: True, @@ -301,34 +306,43 @@ async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state): CONF_MINIMAL_ACTIVATION_DELAY: 30, CONF_SAFETY_DELAY_MIN: 5, CONF_SAFETY_MIN_ON_PERCENT: 0.3, - CONF_POWER_SENSOR: "sensor.mock_power_sensor", - CONF_MAX_POWER_SENSOR: "sensor.mock_power_max_sensor", CONF_DEVICE_POWER: 100, CONF_PRESET_POWER: 12, }, ) entity: ThermostatOverSwitch = await create_thermostat( - hass, entry, "climate.theoverswitchmockname" + hass, entry, "climate.theoverswitchmockname", temps ) assert entity tpi_algo = entity._prop_algorithm assert tpi_algo - tz = get_tz(hass) # pylint: disable=invalid-name - now: datetime = datetime.now(tz=tz) + now: datetime = NowClass.get_now(hass) + VersatileThermostatAPI.get_vtherm_api()._set_now(now) await send_temperature_change_event(entity, 16, now) await send_ext_temperature_change_event(entity, 10, now) # 1. An already active heater will not switch to overpowering + side_effects = SideEffects( + { + "sensor.the_power_sensor": State("sensor.the_power_sensor", 100), + "sensor.the_max_power_sensor": State("sensor.the_max_power_sensor", 110), + }, + State("unknown.entity_id", "unknown"), + ) + with patch( "homeassistant.core.ServiceRegistry.async_call" ) as mock_service_call, patch( "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.is_device_active", new_callable=PropertyMock, return_value=True, + ), patch( + "homeassistant.core.StateMachine.get", + side_effect=side_effects.get_side_effects(), ): await entity.async_set_hvac_mode(HVACMode.HEAT) await entity.async_set_preset_mode(PRESET_COMFORT) @@ -337,14 +351,15 @@ async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state): assert entity.power_manager.overpowering_state is STATE_UNKNOWN assert entity.target_temperature == 18 # waits that the heater starts - await asyncio.sleep(0.1) + await hass.async_block_till_done() + assert mock_service_call.call_count >= 1 assert entity.is_device_active is True # Send power max mesurement - await send_max_power_change_event(entity, 110, datetime.now()) + await send_max_power_change_event(entity, 110, now) # Send power mesurement (theheater is already in the power measurement) - await send_power_change_event(entity, 100, datetime.now()) + await send_power_change_event(entity, 100, now) # No overpowering yet assert entity.power_manager.is_overpowering_detected is False # All configuration is complete and power is < power_max @@ -359,11 +374,22 @@ async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state): "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.is_device_active", new_callable=PropertyMock, return_value=True, + ), patch( + "homeassistant.core.StateMachine.get", + side_effect=side_effects.get_side_effects(), ): + now = now + timedelta(seconds=61) + VersatileThermostatAPI.get_vtherm_api()._set_now(now) + # change preset to Boost await entity.async_set_preset_mode(PRESET_BOOST) # waits that the heater starts await asyncio.sleep(0.1) + # doesn't work for call_later + # await hass.async_block_till_done() + + # simulate a refresh for central power (not necessary) + await do_central_power_refresh(hass) assert entity.power_manager.is_overpowering_detected is False assert entity.hvac_mode is HVACMode.HEAT @@ -379,12 +405,21 @@ async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state): "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.is_device_active", new_callable=PropertyMock, return_value=False, + ), patch( + "homeassistant.core.StateMachine.get", + side_effect=side_effects.get_side_effects(), ): + now = now + timedelta(seconds=61) + VersatileThermostatAPI.get_vtherm_api()._set_now(now) + # change preset to Boost await entity.async_set_preset_mode(PRESET_COMFORT) # waits that the heater starts await asyncio.sleep(0.1) + # simulate a refresh for central power (not necessary) + await do_central_power_refresh(hass) + assert entity.power_manager.is_overpowering_detected is True assert entity.hvac_mode is HVACMode.HEAT assert entity.preset_mode is PRESET_POWER diff --git a/tests/test_central_config.py b/tests/test_central_config.py index 11cf3bb..2785157 100644 --- a/tests/test_central_config.py +++ b/tests/test_central_config.py @@ -188,6 +188,18 @@ async def test_full_over_switch_wo_central_config( hass: HomeAssistant, skip_hass_states_is_state, init_vtherm_api ): """Tests that a VTherm without any central_configuration is working with its own attributes""" + + temps = { + "frost": 10, + "eco": 17, + "comfort": 18, + "boost": 21, + "frost_away": 13, + "eco_away": 13, + "comfort_away": 13, + "boost_away": 13, + } + # Add a Switch VTherm entry = MockConfigEntry( domain=DOMAIN, @@ -202,19 +214,11 @@ async def test_full_over_switch_wo_central_config( CONF_TEMP_MIN: 8, CONF_TEMP_MAX: 18, CONF_STEP_TEMPERATURE: 0.3, - "frost_temp": 10, - "eco_temp": 17, - "comfort_temp": 18, - "boost_temp": 21, - "frost_away_temp": 13, - "eco_away_temp": 13, - "comfort_away_temp": 13, - "boost_away_temp": 13, CONF_USE_WINDOW_FEATURE: True, CONF_USE_MOTION_FEATURE: True, CONF_USE_POWER_FEATURE: True, CONF_USE_PRESENCE_FEATURE: True, - CONF_HEATER: "switch.mock_switch", + CONF_UNDERLYING_LIST: ["switch.mock_switch"], CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI, CONF_INVERSE_SWITCH: False, CONF_TPI_COEF_INT: 0.3, @@ -233,8 +237,6 @@ async def test_full_over_switch_wo_central_config( CONF_MOTION_PRESET: "comfort", CONF_NO_MOTION_PRESET: "eco", CONF_MOTION_SENSOR: "binary_sensor.mock_motion_sensor", - CONF_POWER_SENSOR: "sensor.mock_power_sensor", - CONF_MAX_POWER_SENSOR: "sensor.mock_max_power_sensor", CONF_PRESENCE_SENSOR: "binary_sensor.mock_presence_sensor", CONF_USE_MAIN_CENTRAL_CONFIG: False, CONF_USE_TPI_CENTRAL_CONFIG: False, @@ -249,7 +251,7 @@ async def test_full_over_switch_wo_central_config( with patch("homeassistant.core.ServiceRegistry.async_call"): entity: ThermostatOverSwitch = await create_thermostat( - hass, entry, "climate.theoverswitchmockname" + hass, entry, "climate.theoverswitchmockname", temps ) assert entity assert entity.name == "TheOverSwitchMockName" @@ -300,10 +302,13 @@ async def test_full_over_switch_wo_central_config( assert entity.motion_manager.motion_preset == "comfort" assert entity.motion_manager.no_motion_preset == "eco" - assert entity.power_manager.power_sensor_entity_id == "sensor.mock_power_sensor" assert ( - entity.power_manager.max_power_sensor_entity_id - == "sensor.mock_max_power_sensor" + VersatileThermostatAPI.get_vtherm_api().central_power_manager.power_sensor_entity_id + is None + ) + assert ( + VersatileThermostatAPI.get_vtherm_api().central_power_manager.max_power_sensor_entity_id + is None ) assert ( @@ -317,7 +322,7 @@ async def test_full_over_switch_wo_central_config( @pytest.mark.parametrize("expected_lingering_tasks", [True]) @pytest.mark.parametrize("expected_lingering_timers", [True]) async def test_full_over_switch_with_central_config( - hass: HomeAssistant, skip_hass_states_is_state, init_central_config + hass: HomeAssistant, skip_hass_states_is_state, init_central_power_manager ): """Tests that a VTherm with central_configuration is working with the central_config attributes""" # Add a Switch VTherm @@ -334,15 +339,11 @@ async def test_full_over_switch_with_central_config( CONF_TEMP_MIN: 8, CONF_TEMP_MAX: 18, CONF_STEP_TEMPERATURE: 0.3, - "frost_temp": 10, - "eco_temp": 17, - "comfort_temp": 18, - "boost_temp": 21, CONF_USE_WINDOW_FEATURE: True, CONF_USE_MOTION_FEATURE: True, CONF_USE_POWER_FEATURE: True, CONF_USE_PRESENCE_FEATURE: True, - CONF_HEATER: "switch.mock_switch", + CONF_UNDERLYING_LIST: ["switch.mock_switch"], CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI, CONF_INVERSE_SWITCH: False, CONF_TPI_COEF_INT: 0.3, @@ -361,8 +362,6 @@ async def test_full_over_switch_with_central_config( CONF_MOTION_PRESET: "comfort", CONF_NO_MOTION_PRESET: "eco", CONF_MOTION_SENSOR: "binary_sensor.mock_motion_sensor", - CONF_POWER_SENSOR: "sensor.mock_power_sensor", - CONF_MAX_POWER_SENSOR: "sensor.mock_max_power_sensor", CONF_PRESENCE_SENSOR: "binary_sensor.mock_presence_sensor", CONF_USE_MAIN_CENTRAL_CONFIG: True, CONF_USE_TPI_CENTRAL_CONFIG: True, @@ -426,10 +425,13 @@ async def test_full_over_switch_with_central_config( assert entity.motion_manager.motion_preset == "boost" assert entity.motion_manager.no_motion_preset == "frost" - assert entity.power_manager.power_sensor_entity_id == "sensor.mock_power_sensor" assert ( - entity.power_manager.max_power_sensor_entity_id - == "sensor.mock_max_power_sensor" + VersatileThermostatAPI.get_vtherm_api().central_power_manager.power_sensor_entity_id + == "sensor.the_power_sensor" + ) + assert ( + VersatileThermostatAPI.get_vtherm_api().central_power_manager.max_power_sensor_entity_id + == "sensor.the_max_power_sensor" ) assert ( diff --git a/tests/test_central_power_manager.py b/tests/test_central_power_manager.py index 4bdd374..29b68b9 100644 --- a/tests/test_central_power_manager.py +++ b/tests/test_central_power_manager.py @@ -229,7 +229,7 @@ async def test_central_power_manageer_find_vtherms( "is_overpowering_detected": False, }, ], - {}, + {"vtherm1": False}, ), # Simple trivial shedding ( diff --git a/tests/test_multiple_switch.py b/tests/test_multiple_switch.py index b8f848a..75c23a3 100644 --- a/tests/test_multiple_switch.py +++ b/tests/test_multiple_switch.py @@ -721,10 +721,14 @@ async def test_multiple_climates_underlying_changes_not_aligned( @pytest.mark.parametrize("expected_lingering_tasks", [True]) @pytest.mark.parametrize("expected_lingering_timers", [True]) async def test_multiple_switch_power_management( - hass: HomeAssistant, skip_hass_states_is_state + hass: HomeAssistant, skip_hass_states_is_state, init_central_power_manager ): """Test the Power management""" - + temps = { + "eco": 17, + "comfort": 18, + "boost": 19, + } entry = MockConfigEntry( domain=DOMAIN, title="TheOverSwitchMockName", @@ -737,17 +741,16 @@ async def test_multiple_switch_power_management( CONF_CYCLE_MIN: 8, CONF_TEMP_MIN: 15, CONF_TEMP_MAX: 30, - "eco_temp": 17, - "comfort_temp": 18, - "boost_temp": 19, CONF_USE_WINDOW_FEATURE: False, CONF_USE_MOTION_FEATURE: False, CONF_USE_POWER_FEATURE: True, CONF_USE_PRESENCE_FEATURE: False, - CONF_HEATER: "switch.mock_switch1", - CONF_HEATER_2: "switch.mock_switch2", - CONF_HEATER_3: "switch.mock_switch3", - CONF_HEATER_4: "switch.mock_switch4", + CONF_UNDERLYING_LIST: [ + "switch.mock_switch1", + "switch.mock_switch2", + "switch.mock_switch3", + "switch.mock_switch4", + ], CONF_HEATER_KEEP_ALIVE: 0, CONF_MINIMAL_ACTIVATION_DELAY: 30, CONF_SAFETY_DELAY_MIN: 5, @@ -755,15 +758,13 @@ async def test_multiple_switch_power_management( CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI, CONF_TPI_COEF_INT: 0.3, CONF_TPI_COEF_EXT: 0.01, - CONF_POWER_SENSOR: "sensor.mock_power_sensor", - CONF_MAX_POWER_SENSOR: "sensor.mock_power_max_sensor", CONF_DEVICE_POWER: 100, CONF_PRESET_POWER: 12, }, ) entity: BaseThermostat = await create_thermostat( - hass, entry, "climate.theover4switchmockname" + hass, entry, "climate.theover4switchmockname", temps ) assert entity assert entity.is_over_climate is False @@ -772,6 +773,9 @@ async def test_multiple_switch_power_management( tpi_algo = entity._prop_algorithm assert tpi_algo + now: datetime = NowClass.get_now(hass) + VersatileThermostatAPI.get_vtherm_api()._set_now(now) + await entity.async_set_hvac_mode(HVACMode.HEAT) await entity.async_set_preset_mode(PRESET_BOOST) assert entity.hvac_mode is HVACMode.HEAT @@ -780,76 +784,103 @@ async def test_multiple_switch_power_management( assert entity.target_temperature == 19 # 1. Send power mesurement - await send_power_change_event(entity, 50, datetime.now()) + side_effects = SideEffects( + { + "sensor.the_power_sensor": State("sensor.the_power_sensor", 50), + "sensor.the_max_power_sensor": State("sensor.the_max_power_sensor", 300), + }, + State("unknown.entity_id", "unknown"), + ) + # Send power max mesurement - await send_max_power_change_event(entity, 300, datetime.now()) - assert entity.power_manager.is_overpowering_detected is False - # All configuration is complete and power is < power_max - assert entity.preset_mode is PRESET_BOOST - assert entity.power_manager.overpowering_state is STATE_OFF + # fmt:off + with patch("homeassistant.core.StateMachine.get", side_effect=side_effects.get_side_effects()): + # fmt: on + now = now + timedelta(seconds=61) + VersatileThermostatAPI.get_vtherm_api()._set_now(now) + + await send_power_change_event(entity, 50, datetime.now()) + await send_max_power_change_event(entity, 300, datetime.now()) + assert entity.power_manager.is_overpowering_detected is False + # All configuration is complete and power is < power_max + assert entity.preset_mode is PRESET_BOOST + assert entity.power_manager.overpowering_state is STATE_OFF # 2. Send power max mesurement too low and HVACMode is on - with patch( - "custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event" - ) as mock_send_event, patch( - "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.turn_on" - ) as mock_heater_on, patch( - "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.turn_off" - ) as mock_heater_off: - # 100 of the device / 4 -> 25, current power 50 so max is 75 - await send_max_power_change_event(entity, 74, datetime.now()) - assert entity.power_manager.is_overpowering_detected is True - # All configuration is complete and power is > power_max we switch to POWER preset - assert entity.preset_mode is PRESET_POWER - assert entity.power_manager.overpowering_state is STATE_ON - assert entity.target_temperature == 12 + side_effects.add_or_update_side_effect("sensor.the_max_power_sensor", State("sensor.the_max_power_sensor", 74)) - assert mock_send_event.call_count == 2 - mock_send_event.assert_has_calls( - [ - call.send_event(EventType.PRESET_EVENT, {"preset": PRESET_POWER}), - call.send_event( - EventType.POWER_EVENT, - { - "type": "start", - "current_power": 50, - "device_power": 100, - "current_max_power": 74, - "current_power_consumption": 25.0, - }, - ), - ], - any_order=True, - ) - assert mock_heater_on.call_count == 0 - assert mock_heater_off.call_count == 4 # The fourth are shutdown + with patch( + "custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event" + ) as mock_send_event, patch( + "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.turn_on" + ) as mock_heater_on, patch( + "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.turn_off" + ) as mock_heater_off: + + now = now + timedelta(seconds=61) + VersatileThermostatAPI.get_vtherm_api()._set_now(now) + # 100 of the device / 4 -> 25, current power 50 so max is 75 + await send_max_power_change_event(entity, 74, datetime.now()) + assert entity.power_manager.is_overpowering_detected is True + # All configuration is complete and power is > power_max we switch to POWER preset + assert entity.preset_mode is PRESET_POWER + assert entity.power_manager.overpowering_state is STATE_ON + assert entity.target_temperature == 12 + + assert mock_send_event.call_count == 2 + mock_send_event.assert_has_calls( + [ + call.send_event(EventType.PRESET_EVENT, {"preset": PRESET_POWER}), + call.send_event( + EventType.POWER_EVENT, + { + "type": "start", + "current_power": 50, + "device_power": 100, + "current_max_power": 74, + "current_power_consumption": 25.0, + }, + ), + ], + any_order=True, + ) + assert mock_heater_on.call_count == 0 + assert mock_heater_off.call_count == 4 # The fourth are shutdown # 3. change PRESET - with patch( - "custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event" - ) as mock_send_event: - await entity.async_set_preset_mode(PRESET_ECO) - assert entity.preset_mode is PRESET_ECO - # No change - assert entity.power_manager.overpowering_state is STATE_ON + with patch( + "custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event" + ) as mock_send_event: + now = now + timedelta(seconds=61) + VersatileThermostatAPI.get_vtherm_api()._set_now(now) + + await entity.async_set_preset_mode(PRESET_ECO) + assert entity.preset_mode is PRESET_ECO + # No change + assert entity.power_manager.overpowering_state is STATE_ON # 4. Send hugh power max mesurement to release overpowering - with patch( - "custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event" - ) as mock_send_event, patch( - "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.turn_on" - ) as mock_heater_on, patch( - "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.turn_off" - ) as mock_heater_off: - # 100 of the device / 4 -> 25, current power 50 so max is 75. With 150 no overheating - await send_max_power_change_event(entity, 150, datetime.now()) - assert entity.power_manager.is_overpowering_detected is False - # All configuration is complete and power is > power_max we switch to POWER preset - assert entity.preset_mode is PRESET_ECO - assert entity.power_manager.overpowering_state is STATE_OFF - assert entity.target_temperature == 17 + side_effects.add_or_update_side_effect("sensor.the_max_power_sensor", State("sensor.the_max_power_sensor", 150)) - assert ( - mock_heater_on.call_count == 0 - ) # The fourth are not restarted because temperature is enought - assert mock_heater_off.call_count == 0 + with patch( + "custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event" + ) as mock_send_event, patch( + "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.turn_on" + ) as mock_heater_on, patch( + "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.turn_off" + ) as mock_heater_off: + now = now + timedelta(seconds=61) + VersatileThermostatAPI.get_vtherm_api()._set_now(now) + + # 100 of the device / 4 -> 25, current power 50 so max is 75. With 150 no overheating + await send_max_power_change_event(entity, 150, datetime.now()) + assert entity.power_manager.is_overpowering_detected is False + # All configuration is complete and power is > power_max we switch to POWER preset + assert entity.preset_mode is PRESET_ECO + assert entity.power_manager.overpowering_state is STATE_OFF + assert entity.target_temperature == 17 + + assert ( + mock_heater_on.call_count == 0 + ) # The fourth are not restarted because temperature is enought + assert mock_heater_off.call_count == 0