From d971cc6aed8e092844f422a373e5ba3cfd1aaa94 Mon Sep 17 00:00:00 2001 From: Jean-Marc Collin Date: Thu, 31 Oct 2024 11:48:01 +0000 Subject: [PATCH] Add change_preset test --- tests/test_auto_start_stop.py | 198 ++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) diff --git a/tests/test_auto_start_stop.py b/tests/test_auto_start_stop.py index 9324f70..f689875 100644 --- a/tests/test_auto_start_stop.py +++ b/tests/test_auto_start_stop.py @@ -723,3 +723,201 @@ async def test_auto_start_stop_fast_ac_vtherm( ) ] ) + + +@pytest.mark.parametrize("expected_lingering_tasks", [True]) +@pytest.mark.parametrize("expected_lingering_timers", [True]) +async def test_auto_start_stop_medium_heat_vtherm_preset_change( + hass: HomeAssistant, skip_hass_states_is_state +): + """Test than auto-start/stop restart a VTherm stopped upon preset_change (in fast mode)""" + + # vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(hass) + + # The temperatures to set + temps = { + "frost": 7.0, + "eco": 17.0, + "comfort": 19.0, + "boost": 21.0, + "eco_ac": 27.0, + "comfort_ac": 25.0, + "boost_ac": 23.0, + "frost_away": 7.1, + "eco_away": 17.1, + "comfort_away": 19.1, + "boost_away": 21.1, + "eco_ac_away": 27.1, + "comfort_ac_away": 25.1, + "boost_ac_away": 23.1, + } + + config_entry = MockConfigEntry( + domain=DOMAIN, + title="TheOverClimateMockName", + unique_id="overClimateUniqueId", + data={ + CONF_NAME: "overClimate", + CONF_TEMP_SENSOR: "sensor.mock_temp_sensor", + CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_CLIMATE, + CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor", + CONF_CYCLE_MIN: 5, + CONF_TEMP_MIN: 15, + CONF_TEMP_MAX: 30, + CONF_USE_WINDOW_FEATURE: False, + CONF_USE_MOTION_FEATURE: False, + CONF_USE_POWER_FEATURE: False, + CONF_USE_PRESENCE_FEATURE: True, + CONF_PRESENCE_SENSOR: "binary_sensor.presence_sensor", + CONF_CLIMATE: "climate.mock_climate", + CONF_MINIMAL_ACTIVATION_DELAY: 30, + CONF_SECURITY_DELAY_MIN: 5, + CONF_SECURITY_MIN_ON_PERCENT: 0.3, + CONF_AUTO_FAN_MODE: CONF_AUTO_FAN_TURBO, + CONF_AC_MODE: True, + CONF_AUTO_START_STOP_LEVEL: AUTO_START_STOP_LEVEL_FAST, + }, + ) + + fake_underlying_climate = MockClimate( + hass=hass, + unique_id="mock_climate", + name="mock_climate", + hvac_modes=[HVACMode.OFF, HVACMode.COOL, HVACMode.HEAT], + ) + + with patch( + "custom_components.versatile_thermostat.underlyings.UnderlyingClimate.find_underlying_climate", + return_value=fake_underlying_climate, + ): + vtherm: ThermostatOverClimate = await create_thermostat( + hass, config_entry, "climate.overclimate" + ) + + assert vtherm is not None + + # Initialize all temps + await set_all_climate_preset_temp(hass, vtherm, temps, "overclimate") + + # Check correct initialization of auto_start_stop attributes + assert ( + vtherm._attr_extra_state_attributes["auto_start_stop_level"] + == AUTO_START_STOP_LEVEL_FAST + ) + + assert vtherm._attr_extra_state_attributes["auto_start_stop_dtmin"] == 7 + + # 1. Vtherm auto-start/stop should be in MEDIUM mode + assert vtherm.auto_start_stop_level == AUTO_START_STOP_LEVEL_FAST + + tz = get_tz(hass) # pylint: disable=invalid-name + now: datetime = datetime.now(tz=tz) + + # 2. Set mode to Heat and preset to Comfort + await send_presence_change_event(vtherm, True, False, now) + await send_temperature_change_event(vtherm, 16, now, True) + await vtherm.async_set_hvac_mode(HVACMode.HEAT) + await vtherm.async_set_preset_mode(PRESET_ECO) + await hass.async_block_till_done() + + assert vtherm.target_temperature == 17.0 + # VTherm should be heating + assert vtherm.hvac_mode == HVACMode.HEAT + + # 3. Set current temperature to 21 5 min later to auto-stop + now = now + timedelta(minutes=5) + with patch( + "custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event" + ) as mock_send_event: + vtherm._set_now(now) + await send_temperature_change_event(vtherm, 19, now, True) + await hass.async_block_till_done() + + # VTherm should have been stopped + assert vtherm.hvac_mode == HVACMode.OFF + + assert vtherm._auto_start_stop_algo.accumulated_error == -2 + + # a message should have been sent + assert mock_send_event.call_count >= 1 + mock_send_event.assert_has_calls( + [ + call( + event_type=EventType.AUTO_START_STOP_EVENT, + data={ + "type": "stop", + "cause": "Auto stop conditions reached", + "hvac_mode": HVACMode.OFF, + "saved_hvac_mode": HVACMode.HEAT, + "target_temperature": 17.0, + "current_temperature": 19.0, + "temperature_slope": 18.0, + }, + ) + ] + ) + + mock_send_event.assert_has_calls( + [ + call( + EventType.HVAC_MODE_EVENT, + { + "hvac_mode": HVACMode.OFF, + }, + ) + ] + ) + + # 4.1 reduce the slope + now = now + timedelta(minutes=5) + await send_temperature_change_event(vtherm, 19, now, True) + + now = now + timedelta(minutes=5) + await send_temperature_change_event(vtherm, 18, now, True) + + now = now + timedelta(minutes=5) + await send_temperature_change_event(vtherm, 17, now, True) + + # 4. Change preset to auto restart the Vtherm + now = now + timedelta(minutes=10) + with patch( + "custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event" + ) as mock_send_event: + vtherm._set_now(now) + await vtherm.async_set_preset_mode(PRESET_BOOST) + await hass.async_block_till_done() + assert vtherm.target_temperature == 21 + + assert vtherm._auto_start_stop_algo.accumulated_error == 2 + + # VTherm should have been restarted + assert vtherm.hvac_mode == HVACMode.HEAT + # a message should have been sent + assert mock_send_event.call_count >= 1 + mock_send_event.assert_has_calls( + [ + call( + event_type=EventType.AUTO_START_STOP_EVENT, + data={ + "type": "start", + "cause": "Auto start conditions reached", + "hvac_mode": HVACMode.HEAT, + "saved_hvac_mode": HVACMode.HEAT, # saved don't change + "target_temperature": 21.0, + "current_temperature": 17.0, + "temperature_slope": -5.19, + }, + ) + ] + ) + + mock_send_event.assert_has_calls( + [ + call( + EventType.HVAC_MODE_EVENT, + { + "hvac_mode": HVACMode.HEAT, + }, + ) + ] + )