Try auto window new algo
This commit is contained in:
@@ -506,17 +506,15 @@ class RegulatedTemperatureSensor(VersatileThermostatBaseEntity, SensorEntity):
|
|||||||
"""Called when my climate have change"""
|
"""Called when my climate have change"""
|
||||||
_LOGGER.debug("%s - climate state change", self._attr_unique_id)
|
_LOGGER.debug("%s - climate state change", self._attr_unique_id)
|
||||||
|
|
||||||
if math.isnan(self.my_climate.regulated_target_temp) or math.isinf(
|
new_temp = self.my_climate.regulated_target_temp
|
||||||
self.my_climate.regulated_target_temp
|
if new_temp is None:
|
||||||
):
|
return
|
||||||
raise ValueError(
|
|
||||||
f"Sensor has illegal state {self.my_climate.regulated_target_temp}"
|
if math.isnan(new_temp) or math.isinf(new_temp):
|
||||||
)
|
raise ValueError(f"Sensor has illegal state {new_temp}")
|
||||||
|
|
||||||
old_state = self._attr_native_value
|
old_state = self._attr_native_value
|
||||||
self._attr_native_value = round(
|
self._attr_native_value = round(new_temp, self.suggested_display_precision)
|
||||||
self.my_climate.regulated_target_temp, self.suggested_display_precision
|
|
||||||
)
|
|
||||||
if old_state != self._attr_native_value:
|
if old_state != self._attr_native_value:
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
return
|
return
|
||||||
@@ -559,15 +557,15 @@ class EMATemperatureSensor(VersatileThermostatBaseEntity, SensorEntity):
|
|||||||
"""Called when my climate have change"""
|
"""Called when my climate have change"""
|
||||||
_LOGGER.debug("%s - climate state change", self._attr_unique_id)
|
_LOGGER.debug("%s - climate state change", self._attr_unique_id)
|
||||||
|
|
||||||
if math.isnan(self.my_climate.ema_temperature) or math.isinf(
|
new_ema = self.my_climate.ema_temperature
|
||||||
self.my_climate.ema_temperature
|
if new_ema is None:
|
||||||
):
|
return
|
||||||
raise ValueError(
|
|
||||||
f"Sensor has illegal state {self.my_climate.ema_temperature}"
|
if math.isnan(new_ema) or math.isinf(new_ema):
|
||||||
)
|
raise ValueError(f"Sensor has illegal state {new_ema}")
|
||||||
|
|
||||||
old_state = self._attr_native_value
|
old_state = self._attr_native_value
|
||||||
self._attr_native_value = self.my_climate.ema_temperature
|
self._attr_native_value = new_ema
|
||||||
if old_state != self._attr_native_value:
|
if old_state != self._attr_native_value:
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -363,12 +363,12 @@ async def test_over_climate_regulation_limitations(
|
|||||||
"custom_components.versatile_thermostat.commons.NowClass.get_now",
|
"custom_components.versatile_thermostat.commons.NowClass.get_now",
|
||||||
return_value=event_timestamp,
|
return_value=event_timestamp,
|
||||||
):
|
):
|
||||||
await send_temperature_change_event(entity, 16, event_timestamp)
|
await send_temperature_change_event(entity, 15, event_timestamp)
|
||||||
await send_ext_temperature_change_event(entity, 12, event_timestamp)
|
await send_ext_temperature_change_event(entity, 12, event_timestamp)
|
||||||
|
|
||||||
# the regulated should have been done
|
# the regulated should have been done
|
||||||
assert entity.regulated_target_temp != old_regulated_temp
|
assert entity.regulated_target_temp != old_regulated_temp
|
||||||
assert entity.regulated_target_temp >= entity.target_temperature
|
assert entity.regulated_target_temp >= entity.target_temperature
|
||||||
assert (
|
assert (
|
||||||
entity.regulated_target_temp == 17 + 0.5
|
entity.regulated_target_temp == 17 + 1.5
|
||||||
) # 0.7 without round_to_nearest
|
) # 0.7 without round_to_nearest
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
""" Test the OpenWindow algorithm """
|
""" Test the OpenWindow algorithm """
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from custom_components.versatile_thermostat.open_window_algorithm import WindowOpenDetectionAlgorithm
|
from custom_components.versatile_thermostat.open_window_algorithm import (
|
||||||
|
WindowOpenDetectionAlgorithm,
|
||||||
|
)
|
||||||
|
|
||||||
from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import
|
from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import
|
||||||
|
|
||||||
@@ -19,18 +21,28 @@ async def test_open_window_algo(
|
|||||||
tz = get_tz(hass) # pylint: disable=invalid-name
|
tz = get_tz(hass) # pylint: disable=invalid-name
|
||||||
now = datetime.now(tz)
|
now = datetime.now(tz)
|
||||||
|
|
||||||
event_timestamp = now - timedelta(minutes=5)
|
event_timestamp = now - timedelta(minutes=10)
|
||||||
last_slope = the_algo.add_temp_measurement(
|
last_slope = the_algo.add_temp_measurement(
|
||||||
temperature=10, datetime_measure=event_timestamp
|
temperature=10, datetime_measure=event_timestamp
|
||||||
)
|
)
|
||||||
|
|
||||||
# We need at least 2 measurement
|
# We need at least 4 measurement
|
||||||
assert last_slope is None
|
assert last_slope is None
|
||||||
assert the_algo.last_slope is None
|
assert the_algo.last_slope is None
|
||||||
assert the_algo.is_window_close_detected() is False
|
assert the_algo.is_window_close_detected() is False
|
||||||
assert the_algo.is_window_open_detected() is False
|
assert the_algo.is_window_open_detected() is False
|
||||||
|
|
||||||
event_timestamp = now - timedelta(minutes=4)
|
event_timestamp = now - timedelta(minutes=9)
|
||||||
|
last_slope = the_algo.add_temp_measurement(
|
||||||
|
temperature=10, datetime_measure=event_timestamp
|
||||||
|
)
|
||||||
|
|
||||||
|
event_timestamp = now - timedelta(minutes=8)
|
||||||
|
last_slope = the_algo.add_temp_measurement(
|
||||||
|
temperature=10, datetime_measure=event_timestamp
|
||||||
|
)
|
||||||
|
|
||||||
|
event_timestamp = now - timedelta(minutes=7)
|
||||||
last_slope = the_algo.add_temp_measurement(
|
last_slope = the_algo.add_temp_measurement(
|
||||||
temperature=10, datetime_measure=event_timestamp
|
temperature=10, datetime_measure=event_timestamp
|
||||||
)
|
)
|
||||||
@@ -41,19 +53,19 @@ async def test_open_window_algo(
|
|||||||
assert the_algo.is_window_close_detected() is True
|
assert the_algo.is_window_close_detected() is True
|
||||||
assert the_algo.is_window_open_detected() is False
|
assert the_algo.is_window_open_detected() is False
|
||||||
|
|
||||||
event_timestamp = now - timedelta(minutes=3)
|
event_timestamp = now - timedelta(minutes=6)
|
||||||
last_slope = the_algo.add_temp_measurement(
|
last_slope = the_algo.add_temp_measurement(
|
||||||
temperature=9, datetime_measure=event_timestamp
|
temperature=9, datetime_measure=event_timestamp
|
||||||
)
|
)
|
||||||
|
|
||||||
# A slope is calculated
|
# A slope is calculated
|
||||||
assert last_slope == -0.5
|
assert last_slope == -0.8
|
||||||
assert the_algo.last_slope == -0.5
|
assert the_algo.last_slope == -0.8
|
||||||
assert the_algo.is_window_close_detected() is False
|
assert the_algo.is_window_close_detected() is False
|
||||||
assert the_algo.is_window_open_detected() is False
|
assert the_algo.is_window_open_detected() is False
|
||||||
|
|
||||||
# A new temperature with 2 degre less in one minute (value will be rejected)
|
# A new temperature with 2 degre less in one minute (value will be rejected)
|
||||||
event_timestamp = now - timedelta(minutes=2)
|
event_timestamp = now - timedelta(minutes=5)
|
||||||
last_slope = the_algo.add_temp_measurement(
|
last_slope = the_algo.add_temp_measurement(
|
||||||
temperature=7, datetime_measure=event_timestamp
|
temperature=7, datetime_measure=event_timestamp
|
||||||
)
|
)
|
||||||
@@ -65,7 +77,7 @@ async def test_open_window_algo(
|
|||||||
assert the_algo.is_window_open_detected() is True
|
assert the_algo.is_window_open_detected() is True
|
||||||
|
|
||||||
# A new temperature with 1 degre less
|
# A new temperature with 1 degre less
|
||||||
event_timestamp = now - timedelta(minutes=1)
|
event_timestamp = now - timedelta(minutes=4)
|
||||||
last_slope = the_algo.add_temp_measurement(
|
last_slope = the_algo.add_temp_measurement(
|
||||||
temperature=6, datetime_measure=event_timestamp
|
temperature=6, datetime_measure=event_timestamp
|
||||||
)
|
)
|
||||||
@@ -77,7 +89,7 @@ async def test_open_window_algo(
|
|||||||
assert the_algo.is_window_open_detected() is True
|
assert the_algo.is_window_open_detected() is True
|
||||||
|
|
||||||
# A new temperature with 0 degre less
|
# A new temperature with 0 degre less
|
||||||
event_timestamp = now - timedelta(minutes=0)
|
event_timestamp = now - timedelta(minutes=3)
|
||||||
last_slope = the_algo.add_temp_measurement(
|
last_slope = the_algo.add_temp_measurement(
|
||||||
temperature=6, datetime_measure=event_timestamp
|
temperature=6, datetime_measure=event_timestamp
|
||||||
)
|
)
|
||||||
@@ -89,7 +101,7 @@ async def test_open_window_algo(
|
|||||||
assert the_algo.is_window_open_detected() is False
|
assert the_algo.is_window_open_detected() is False
|
||||||
|
|
||||||
# A new temperature with 1 degre more
|
# A new temperature with 1 degre more
|
||||||
event_timestamp = now + timedelta(minutes=1)
|
event_timestamp = now + timedelta(minutes=2)
|
||||||
last_slope = the_algo.add_temp_measurement(
|
last_slope = the_algo.add_temp_measurement(
|
||||||
temperature=7, datetime_measure=event_timestamp
|
temperature=7, datetime_measure=event_timestamp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -477,6 +477,14 @@ async def test_window_auto_auto_stop(hass: HomeAssistant, skip_hass_states_is_st
|
|||||||
|
|
||||||
assert entity.window_state is STATE_OFF
|
assert entity.window_state is STATE_OFF
|
||||||
|
|
||||||
|
# Initialize the slope algo with 2 measurements
|
||||||
|
# event_timestamp = now - timedelta(minutes=9)
|
||||||
|
# await send_temperature_change_event(entity, 19, event_timestamp)
|
||||||
|
# event_timestamp = now - timedelta(minutes=8)
|
||||||
|
# await send_temperature_change_event(entity, 19, event_timestamp)
|
||||||
|
# event_timestamp = now - timedelta(minutes=7)
|
||||||
|
# await send_temperature_change_event(entity, 19, event_timestamp)
|
||||||
|
|
||||||
# Make the temperature down
|
# Make the temperature down
|
||||||
with patch(
|
with patch(
|
||||||
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
|
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
|
||||||
@@ -486,6 +494,7 @@ async def test_window_auto_auto_stop(hass: HomeAssistant, skip_hass_states_is_st
|
|||||||
"custom_components.versatile_thermostat.underlyings.UnderlyingClimate.is_device_active",
|
"custom_components.versatile_thermostat.underlyings.UnderlyingClimate.is_device_active",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
):
|
):
|
||||||
|
# This is the 3rd measurment. Slope is not ready
|
||||||
event_timestamp = now - timedelta(minutes=4)
|
event_timestamp = now - timedelta(minutes=4)
|
||||||
await send_temperature_change_event(entity, 19, event_timestamp)
|
await send_temperature_change_event(entity, 19, event_timestamp)
|
||||||
|
|
||||||
@@ -531,7 +540,7 @@ async def test_window_auto_auto_stop(hass: HomeAssistant, skip_hass_states_is_st
|
|||||||
assert entity.window_auto_state == STATE_ON
|
assert entity.window_auto_state == STATE_ON
|
||||||
assert entity.hvac_mode is HVACMode.OFF
|
assert entity.hvac_mode is HVACMode.OFF
|
||||||
|
|
||||||
# Waits for automatic disable
|
# Waits for automatic disable
|
||||||
with patch(
|
with patch(
|
||||||
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
|
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
|
||||||
) as mock_send_event, patch(
|
) as mock_send_event, patch(
|
||||||
|
|||||||
Reference in New Issue
Block a user