Change algo using underlying internal temp

This commit is contained in:
Jean-Marc Collin
2024-01-27 11:46:01 +00:00
parent de47a3ffe1
commit 2fe0e57231
4 changed files with 112 additions and 38 deletions

7
copy-to-forum.txt Normal file
View File

@@ -0,0 +1,7 @@
Before copying to forum you need to replace relative images by this command into VSCode:
Search :
\(images/(.*).png\)
Replace with:
(https://github.com/jmcollin78/versatile_thermostat/blob/main/images/$1.png?raw=true)

View File

@@ -194,8 +194,45 @@ class ThermostatOverClimate(BaseThermostat):
self._last_regulation_change = now
for under in self._underlyings:
# issue 348 - use device temperature if configured as offset
offset_temp = 0
device_temp = 0
if (
# regulation can use the device_temp
self.auto_regulation_use_device_temp
# and we have access to the device temp
and (device_temp := under.underlying_current_temperature) is not None
# and target is not reach (ie we need regulation)
and (
(
self.hvac_mode == HVACMode.COOL
and self.target_temperature < self.current_temperature
)
or (
self.hvac_mode == HVACMode.HEAT
and self.target_temperature > self.current_temperature
)
)
):
offset_temp = self.current_temperature - device_temp
if self.hvac_mode == HVACMode.COOL:
target_temp = self.regulated_target_temp - offset_temp
else:
target_temp = self.regulated_target_temp + offset_temp
_LOGGER.debug(
"%s - the device offset temp for regulation is %.2f - internal temp is %.2f. Nes target is %.2f",
self,
offset_temp,
device_temp,
target_temp,
)
await under.set_temperature(
self.regulated_target_temp, self._attr_max_temp, self._attr_min_temp
target_temp,
self._attr_max_temp,
self._attr_min_temp,
)
async def _send_auto_fan_mode(self):

View File

@@ -568,23 +568,9 @@ class UnderlyingClimate(UnderlyingEntity):
if not self.is_initialized:
return
# issue 348 - use device temperature if configured as offset
offset_temp = 0
if self._thermostat.auto_regulation_use_device_temp and hasattr(
self._underlying_climate, "current_temperature"
):
device_temp = self._underlying_climate.current_temperature
offset_temp = device_temp - self._thermostat.current_temperature
_LOGGER.debug(
"%s - the device offset temp for regulation is %.2f - internal temp is %.2f",
self,
offset_temp,
device_temp,
)
data = {
ATTR_ENTITY_ID: self._entity_id,
"temperature": self.cap_sent_value(temperature + offset_temp),
"temperature": self.cap_sent_value(temperature),
"target_temp_high": max_temp,
"target_temp_low": min_temp,
}
@@ -686,6 +672,18 @@ class UnderlyingClimate(UnderlyingEntity):
return False
return self._underlying_climate.is_aux_heat
@property
def underlying_current_temperature(self) -> float | None:
"""Get the underlying current_temperature if it exists
and if initialized"""
if not self.is_initialized:
return None
if not hasattr(self._underlying_climate, "current_temperature"):
return None
return self._underlying_climate.current_temperature
def turn_aux_heat_on(self) -> None:
"""Turn auxiliary heater on."""
if not self.is_initialized:

View File

@@ -421,18 +421,6 @@ async def test_over_climate_regulation_use_device_temp(
assert entity.is_regulated is True
assert entity.auto_regulation_use_device_temp is True
assert entity.hvac_mode is HVACMode.OFF
assert entity.hvac_action is HVACAction.OFF
assert entity.target_temperature == entity.min_temp
assert entity.preset_modes == [
PRESET_NONE,
PRESET_FROST_PROTECTION,
PRESET_ECO,
PRESET_COMFORT,
PRESET_BOOST,
]
assert entity.preset_mode is PRESET_NONE
# 1. Activate the heating by changing HVACMode and temperature
# Select a hvacmode, presence and preset
await entity.async_set_hvac_mode(HVACMode.HEAT)
@@ -442,7 +430,11 @@ async def test_over_climate_regulation_use_device_temp(
await send_temperature_change_event(entity, 18, event_timestamp)
await send_ext_temperature_change_event(entity, 10, event_timestamp)
# 2. set manual target temp (at now - 7) -> the regulation should occurs
# 2. set manual target temp (at now - 7) -> no regulation should occurs
# room temp is 18
# target is 16
# internal heater temp is 15
fake_underlying_climate.set_current_temperature(15)
event_timestamp = now - timedelta(minutes=7)
with patch(
"custom_components.versatile_thermostat.commons.NowClass.get_now",
@@ -456,7 +448,7 @@ async def test_over_climate_regulation_use_device_temp(
assert entity.hvac_action == HVACAction.HEATING
assert entity.preset_mode == PRESET_NONE # Manual mode
# the regulated temperature should be lower
# the regulated temperature should be higher
assert entity.regulated_target_temp < entity.target_temperature
# The calcul is the following: 16 + (16 - 18) x 0.4 (strong) + 0 x ki - 1 (device offset)
assert (
@@ -471,7 +463,8 @@ async def test_over_climate_regulation_use_device_temp(
"set_temperature",
{
"entity_id": "climate.mock_climate",
"temperature": 12.0, # because device offset is -3 (15 - 18)
# because device offset is -3 but not used because target is reach
"temperature": 15.0,
"target_temp_high": 30,
"target_temp_low": 15,
},
@@ -480,19 +473,23 @@ async def test_over_climate_regulation_use_device_temp(
)
# 3. change temperature so that the regulated temperature should slow down
fake_underlying_climate.set_current_temperature(27)
# room temp is 15
# target is 18
# internal heater temp is 13
fake_underlying_climate.set_current_temperature(13)
await entity.async_set_temperature(temperature=18)
await send_ext_temperature_change_event(entity, 9, event_timestamp)
event_timestamp = now - timedelta(minutes=5)
with patch(
"custom_components.versatile_thermostat.commons.NowClass.get_now",
return_value=event_timestamp,
), patch("homeassistant.core.ServiceRegistry.async_call") as mock_service_call:
await send_temperature_change_event(entity, 23, event_timestamp)
await send_ext_temperature_change_event(entity, 19, event_timestamp)
await send_temperature_change_event(entity, 15, event_timestamp)
# the regulated temperature should be under (device offset is -3)
assert entity.regulated_target_temp < entity.target_temperature
assert entity.regulated_target_temp == 12.5
# the regulated temperature should be under (device offset is -2)
assert entity.regulated_target_temp > entity.target_temperature
assert entity.regulated_target_temp == 19.4 # 18 + 1.4
mock_service_call.assert_has_calls(
[
@@ -501,7 +498,42 @@ async def test_over_climate_regulation_use_device_temp(
"set_temperature",
{
"entity_id": "climate.mock_climate",
"temperature": 16.5, # because device offset is +4 (27 - 23)
"temperature": 21.4, # 19.4 + 2
"target_temp_high": 30,
"target_temp_low": 15,
},
),
]
)
# 4. In cool mode
# room temp is 25
# target is 23
# internal heater temp is 27
await entity.async_set_hvac_mode(HVACMode.COOL)
await entity.async_set_temperature(temperature=23)
fake_underlying_climate.set_current_temperature(27)
await send_ext_temperature_change_event(entity, 30, event_timestamp)
event_timestamp = now - timedelta(minutes=3)
with patch(
"custom_components.versatile_thermostat.commons.NowClass.get_now",
return_value=event_timestamp,
), patch("homeassistant.core.ServiceRegistry.async_call") as mock_service_call:
await send_temperature_change_event(entity, 25, event_timestamp)
# the regulated temperature should be upper (device offset is +2)
assert entity.regulated_target_temp < entity.target_temperature
assert entity.regulated_target_temp == 22.9
mock_service_call.assert_has_calls(
[
call.service_call(
"climate",
"set_temperature",
{
"entity_id": "climate.mock_climate",
"temperature": 24.9, # 22.9 + 2° of offset
"target_temp_high": 30,
"target_temp_low": 15,
},