Skip to content

Commit

Permalink
Enhance temperature regulation when working with internal device temp…
Browse files Browse the repository at this point in the history
…erature (#453)

* [feature/autoregulation-send-for-underlyingtemp] Do not forget regulation send when using underlying device temperature for offset

* [feature/autoregulation-send-for-underlyingtemp] Add unit test for dtemp = 0

* [feature/autoregulation-send-for-underlyingtemp] Test with dtemp lower than 0.5

* [feature/autoregulation-send-for-underlyingtemp] Comments
  • Loading branch information
jdeksup committed May 13, 2024
1 parent 6bd1b11 commit 549423b
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 2 deletions.
10 changes: 8 additions & 2 deletions custom_components/versatile_thermostat/thermostat_climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,17 @@ async def _send_regulated_temperature(self, force=False):

_LOGGER.info("%s - regulation calculation will be done", self)

# use _attr_target_temperature_step to round value if _auto_regulation_dtemp is equal to 0
regulation_step = self._auto_regulation_dtemp if self._auto_regulation_dtemp else self._attr_target_temperature_step
_LOGGER.debug("%s - usage of regulation_step: %.2f ",
self,
regulation_step)

new_regulated_temp = round_to_nearest(
self._regulation_algo.calculate_regulated_temperature(
self.current_temperature, self._cur_ext_temp
),
self._auto_regulation_dtemp,
regulation_step,
)
dtemp = new_regulated_temp - self._regulated_target_temp

Expand Down Expand Up @@ -216,7 +222,7 @@ async def _send_regulated_temperature(self, force=False):
):
offset_temp = device_temp - self.current_temperature

target_temp = round_to_nearest(self.regulated_target_temp + offset_temp, self._auto_regulation_dtemp)
target_temp = round_to_nearest(self.regulated_target_temp + offset_temp, regulation_step)

_LOGGER.debug(
"%s - The device offset temp for regulation is %.2f - internal temp is %.2f. New target is %.2f",
Expand Down
113 changes: 113 additions & 0 deletions tests/test_auto_regulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,3 +544,116 @@ async def test_over_climate_regulation_use_device_temp(
),
]
)

@pytest.mark.parametrize("expected_lingering_tasks", [True])
@pytest.mark.parametrize("expected_lingering_timers", [True])
async def test_over_climate_regulation_dtemp_null(
hass: HomeAssistant, skip_hass_states_is_state, skip_send_event
):
"""Test the regulation of an over climate thermostat with no Dtemp limitation"""

entry = MockConfigEntry(
domain=DOMAIN,
title="TheOverClimateMockName",
unique_id="uniqueId",
# This is include a medium regulation
data=PARTIAL_CLIMATE_AC_CONFIG | {CONF_AUTO_REGULATION_DTEMP: 0, CONF_STEP_TEMPERATURE: 0.1},
)

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
# 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,
):
entity = await create_thermostat(hass, entry, "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
assert entity.hvac_action == HVACAction.OFF

# change temperature so that the heating will start
await send_temperature_change_event(entity, 15, event_timestamp)
await send_ext_temperature_change_event(entity, 10, event_timestamp)

# set manual target temp
event_timestamp = now - timedelta(minutes=17)
with patch(
"custom_components.versatile_thermostat.commons.NowClass.get_now",
return_value=event_timestamp,
):
await entity.async_set_temperature(temperature=20)

fake_underlying_climate.set_hvac_action(
HVACAction.HEATING
) # simulate under cooling
assert entity.hvac_action == HVACAction.HEATING
assert entity.preset_mode == PRESET_NONE # Manual mode

# the regulated temperature should be lower
assert entity.regulated_target_temp > entity.target_temperature
assert (
entity.regulated_target_temp == 20 + 2.4
) # In medium we could go up to +3 degre
assert entity.hvac_action == HVACAction.HEATING

# change temperature so that the regulated temperature should slow down
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, 19, event_timestamp)
await send_ext_temperature_change_event(entity, 10, event_timestamp)

# the regulated temperature should be greater
assert entity.regulated_target_temp > entity.target_temperature
assert (
entity.regulated_target_temp == 20 + 0.9
)

# change temperature so that the regulated temperature should slow down
event_timestamp = now - timedelta(minutes=13)
with patch(
"custom_components.versatile_thermostat.commons.NowClass.get_now",
return_value=event_timestamp,
):
await send_temperature_change_event(entity, 20, event_timestamp)
await send_ext_temperature_change_event(entity, 10, event_timestamp)

# the regulated temperature should be greater
assert entity.regulated_target_temp > entity.target_temperature
assert (
entity.regulated_target_temp == 20 + 0.5
)

old_regulated_temp = entity.regulated_target_temp
# Test if a small temperature change is taken into account : change temperature so that dtemp < 0.5 and time is > period_min (+ 3min)
event_timestamp = now - timedelta(minutes=10)
with patch(
"custom_components.versatile_thermostat.commons.NowClass.get_now",
return_value=event_timestamp,
):
await send_temperature_change_event(entity, 19.6, event_timestamp)
await send_ext_temperature_change_event(entity, 10, event_timestamp)

# the regulated temperature should be greater. This does not work if dtemp is not null
assert entity.regulated_target_temp > old_regulated_temp

0 comments on commit 549423b

Please sign in to comment.