With enable + tests + hysteresis in calculation

This commit is contained in:
Jean-Marc Collin
2024-11-01 10:24:35 +00:00
parent 5063374b97
commit f547647e24
5 changed files with 198 additions and 29 deletions

View File

@@ -3,7 +3,7 @@
"""
import logging
from datetime import datetime, timedelta
from datetime import datetime
from typing import Literal
from homeassistant.components.climate import HVACMode
@@ -13,7 +13,6 @@ from .const import (
AUTO_START_STOP_LEVEL_FAST,
AUTO_START_STOP_LEVEL_MEDIUM,
AUTO_START_STOP_LEVEL_SLOW,
CONF_AUTO_START_STOP_LEVELS,
TYPE_AUTO_START_STOP_LEVELS,
)
@@ -31,6 +30,9 @@ DT_MIN = {
# the measurement cycle (2 min)
CYCLE_SEC = 120
# A temp hysteresis to avoid rapid OFF/ON
TEMP_HYSTERESIS = 0.5
ERROR_THRESHOLD = {
AUTO_START_STOP_LEVEL_NONE: 0, # Not used
AUTO_START_STOP_LEVEL_SLOW: 10, # 10 cycle above 1° or 5 cycle above 2°, ...
@@ -146,7 +148,7 @@ class AutoStartStopDetectionAlgorithm:
if hvac_mode == HVACMode.HEAT:
if (
self._accumulated_error <= -self._error_threshold
and temp_at_dt >= target_temp
and temp_at_dt >= target_temp + TEMP_HYSTERESIS
):
_LOGGER.info(
"%s - We need to stop, there is no need for heating for a long time.",
@@ -160,7 +162,7 @@ class AutoStartStopDetectionAlgorithm:
if hvac_mode == HVACMode.COOL:
if (
self._accumulated_error >= self._error_threshold
and temp_at_dt <= target_temp
and temp_at_dt <= target_temp - TEMP_HYSTERESIS
):
_LOGGER.info(
"%s - We need to stop, there is no need for cooling for a long time.",
@@ -176,7 +178,7 @@ class AutoStartStopDetectionAlgorithm:
# check to turn on
if hvac_mode == HVACMode.OFF and saved_hvac_mode == HVACMode.HEAT:
if temp_at_dt <= target_temp:
if temp_at_dt <= target_temp - TEMP_HYSTERESIS:
_LOGGER.info(
"%s - We need to start, because it will be time to heat",
self,
@@ -190,7 +192,7 @@ class AutoStartStopDetectionAlgorithm:
return AUTO_START_STOP_ACTION_NOTHING
if hvac_mode == HVACMode.OFF and saved_hvac_mode == HVACMode.COOL:
if temp_at_dt >= target_temp:
if temp_at_dt >= target_temp + TEMP_HYSTERESIS:
_LOGGER.info(
"%s - We need to start, because it will be time to cool",
self,

View File

@@ -199,6 +199,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
"is_device_active",
"target_temperature_step",
"is_used_by_central_boiler",
"temperature_slope"
}
)
)
@@ -2633,6 +2634,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
"is_device_active": self.is_device_active,
"ema_temp": self._ema_temp,
"is_used_by_central_boiler": self.is_used_by_central_boiler,
"temperature_slope": round(self.last_temperature_slope or 0, 3),
}
@callback

View File

@@ -48,7 +48,7 @@ class AutoStartStopEnable(VersatileThermostatBaseEntity, SwitchEntity, RestoreEn
):
super().__init__(hass, unique_id, name)
self._attr_name = "Enable auto start/stop"
self._attr_unique_id = f"{self._device_name}_enbale_auto_start_stop"
self._attr_unique_id = f"{self._device_name}_enable_auto_start_stop"
self._default_value = (
entry_infos.data.get(CONF_AUTO_START_STOP_LEVEL)
!= AUTO_START_STOP_LEVEL_NONE

View File

@@ -49,6 +49,7 @@ from .const import (
RegulationParamStrong,
AUTO_FAN_DTEMP_THRESHOLD,
AUTO_FAN_DEACTIVATED_MODES,
CONF_USE_AUTO_START_STOP_FEATURE,
CONF_AUTO_START_STOP_LEVEL,
AUTO_START_STOP_LEVEL_NONE,
TYPE_AUTO_START_STOP_LEVELS,
@@ -176,9 +177,14 @@ class ThermostatOverClimate(BaseThermostat[UnderlyingClimate]):
CONF_AUTO_REGULATION_USE_DEVICE_TEMP, False
)
self._auto_start_stop_level = config_entry.get(
CONF_AUTO_START_STOP_LEVEL, AUTO_START_STOP_LEVEL_NONE
)
use_auto_start_stop = config_entry.get(CONF_USE_AUTO_START_STOP_FEATURE, False)
if use_auto_start_stop:
self._auto_start_stop_level = config_entry.get(
CONF_AUTO_START_STOP_LEVEL, AUTO_START_STOP_LEVEL_NONE
)
else:
self._auto_start_stop_level = AUTO_START_STOP_LEVEL_NONE
# Instanciate the auto start stop algo
self._auto_start_stop_algo = AutoStartStopDetectionAlgorithm(
self._auto_start_stop_level, self.name
@@ -914,7 +920,7 @@ class ThermostatOverClimate(BaseThermostat[UnderlyingClimate]):
# Check if we need to auto start/stop the Vtherm
if self.auto_start_stop_enable:
slope = (
self._window_auto_algo.last_slope or 0
self.last_temperature_slope or 0
) / 60 # to have the slope in °/min
action = self._auto_start_stop_algo.calculate_action(
self.hvac_mode,
@@ -937,13 +943,13 @@ class ThermostatOverClimate(BaseThermostat[UnderlyingClimate]):
event_type=EventType.AUTO_START_STOP_EVENT,
data={
"type": "stop",
"name:": self.name,
"name": self.name,
"cause": "Auto stop conditions reached",
"hvac_mode": self.hvac_mode,
"saved_hvac_mode": self._saved_hvac_mode,
"target_temperature": self.target_temperature,
"current_temperature": self.current_temperature,
"temperature_slope": slope,
"temperature_slope": round(slope, 3),
},
)
@@ -960,13 +966,13 @@ class ThermostatOverClimate(BaseThermostat[UnderlyingClimate]):
event_type=EventType.AUTO_START_STOP_EVENT,
data={
"type": "start",
"name:": self.name,
"name": self.name,
"cause": "Auto start conditions reached",
"hvac_mode": self.hvac_mode,
"saved_hvac_mode": self._saved_hvac_mode,
"target_temperature": self.target_temperature,
"current_temperature": self.current_temperature,
"temperature_slope": slope,
"temperature_slope": round(slope, 3),
},
)