From 7d5ced55d3a95cc2455d45266e55b133f1ebb813 Mon Sep 17 00:00:00 2001 From: Jean-Marc Collin Date: Tue, 31 Oct 2023 09:30:07 +0000 Subject: [PATCH] Add regulation limitations tests --- tests/test_auto_regulation.py | 107 ++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/tests/test_auto_regulation.py b/tests/test_auto_regulation.py index eed8f02..f9c333c 100644 --- a/tests/test_auto_regulation.py +++ b/tests/test_auto_regulation.py @@ -223,3 +223,110 @@ async def test_over_climate_regulation_ac_mode(hass: HomeAssistant, skip_hass_st # the regulated temperature should be greater assert entity.regulated_target_temp > entity.target_temperature assert entity.regulated_target_temp == 25+0.4 + +@pytest.mark.parametrize("expected_lingering_tasks", [True]) +@pytest.mark.parametrize("expected_lingering_timers", [True]) +async def test_over_climate_regulation_limitations(hass: HomeAssistant, skip_hass_states_is_state, skip_send_event): + """Test the limitations of the regulation of an over climate thermostat: + 1. test the period_min parameter: do not send regulation event too frequently + 2. test the dtemp parameter: do not send regulation event if offset temp is lower than dtemp + """ + + entry = MockConfigEntry( + domain=DOMAIN, + title="TheOverClimateMockName", + unique_id="uniqueId", + # This is include a medium regulation, dtemp=0.5, period_min=2 + data=PARTIAL_CLIMATE_CONFIG, + ) + + tz = get_tz(hass) # pylint: disable=invalid-name + now: datetime = datetime.now(tz=tz) + + fake_underlying_climate = MockClimate(hass, "mockUniqueId", "MockClimateName", {}) + + # Creates the regulated VTherm over climate at t-20 + # change temperature so that the heating will start + event_timestamp = now - timedelta(minutes=20) + + with patch( + "custom_components.versatile_thermostat.commons.NowClass.get_now", return_value=event_timestamp + ), patch( + "custom_components.versatile_thermostat.underlyings.UnderlyingClimate.find_underlying_climate", + return_value=fake_underlying_climate, + ): + entry.add_to_hass(hass) + await hass.config_entries.async_setup(entry.entry_id) + assert entry.state is ConfigEntryState.LOADED + + def find_my_entity(entity_id) -> ClimateEntity: + """Find my new entity""" + component: EntityComponent[ClimateEntity] = hass.data[CLIMATE_DOMAIN] + for entity in component.entities: + if entity.entity_id == entity_id: + return entity + + entity:ThermostatOverClimate = find_my_entity("climate.theoverclimatemockname") + + assert entity + assert isinstance(entity, ThermostatOverClimate) + + assert entity.name == "TheOverClimateMockName" + assert entity.is_over_climate is True + assert entity.is_regulated is True + + # Activate the heating by changing HVACMode and temperature + # Select a hvacmode, presence and preset + await entity.async_set_hvac_mode(HVACMode.HEAT) + assert entity.hvac_mode is HVACMode.HEAT + + # it is cold today + await send_temperature_change_event(entity, 15, event_timestamp) + await send_ext_temperature_change_event(entity, 10, event_timestamp) + + # set manual target temp (at now - 19) -> the regulation should be ignored because too early + event_timestamp = now - timedelta(minutes=19) + with patch( + "custom_components.versatile_thermostat.commons.NowClass.get_now", return_value=event_timestamp + ): + await entity.async_set_temperature(temperature=18) + + fake_underlying_climate.set_hvac_action(HVACAction.HEATING) # simulate under heating + assert entity.hvac_action == HVACAction.HEATING + + # the regulated temperature should be unchanged + assert entity.regulated_target_temp == 15 + + # set manual target temp (at now - 18) -> the regulation should be taken into account + event_timestamp = now - timedelta(minutes=18) + with patch( + "custom_components.versatile_thermostat.commons.NowClass.get_now", return_value=event_timestamp + ): + await entity.async_set_temperature(temperature=17) + assert entity.regulated_target_temp > entity.target_temperature + assert entity.regulated_target_temp == 18+0.7 # In medium we could go up to +3 degre + old_regulated_temp = entity.regulated_target_temp + + # change temperature so that dtemp < 0.5 and time is > period_min (+ 3min) + event_timestamp = now - timedelta(minutes=15) + with patch( + "custom_components.versatile_thermostat.commons.NowClass.get_now", return_value=event_timestamp + ): + await send_temperature_change_event(entity, 16, event_timestamp) + await send_ext_temperature_change_event(entity, 10, event_timestamp) + + # the regulated temperature should be under + assert entity.regulated_target_temp == old_regulated_temp + + # change temperature so that dtemp > 0.5 and time is > period_min (+ 3min) + event_timestamp = now - timedelta(minutes=12) + with patch( + "custom_components.versatile_thermostat.commons.NowClass.get_now", return_value=event_timestamp + ): + await send_temperature_change_event(entity, 18, event_timestamp) + await send_ext_temperature_change_event(entity, 12, event_timestamp) + + # the regulated should have been done + assert entity.regulated_target_temp != old_regulated_temp + assert entity.regulated_target_temp > entity.target_temperature + assert entity.regulated_target_temp == 17 + 0.7 \ No newline at end of file