Compare commits
7 Commits
2.0.0
...
2.2.0.beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d557263311 | ||
|
|
343596fb39 | ||
|
|
7dbdcf0ee4 | ||
|
|
ade1ee4365 | ||
|
|
7b57f7da28 | ||
|
|
9fe307ba1e | ||
|
|
717c893c75 |
@@ -247,6 +247,9 @@ Le premier délai (minimal_activation_delay_sec) en sec dans le délai minimum a
|
||||
|
||||
Le deuxième délai (security_delay_min) est le délai maximal entre deux mesures de température avant de régler le préréglage sur ``security`` et d'éteindre le thermostat. Si le capteur de température ne donne plus de mesures de température, le thermostat et le radiateur s'éteindront après ce délai et le préréglage du thermostat sera réglé sur ``security``. Ceci est utile pour éviter une surchauffe si la batterie de votre capteur de température est trop faible.
|
||||
|
||||
Le troisième paramétre (security_min_on_percent) est la valeur minimal de on_percent en dessous de laquelle le préréglage sécurité ne sera pas activé.
|
||||
Mettre ce paramètre à ``0.00`` déclenchera le préréglage sécurité quelque soit la dernière consigne de chauffage, à l'inverse ``1.00`` ne déclenchera jamais le préréglage sécurité.
|
||||
|
||||
Voir [exemple de réglages](#examples-tuning) pour avoir des exemples de réglage communs
|
||||
|
||||
>  _*Notes*_
|
||||
@@ -375,7 +378,8 @@ Les attributs personnalisés sont les suivants :
|
||||
| ``motion_state`` | Le dernier état connu du capteur de mouvement. Aucun si le mouvement n'est pas configuré |
|
||||
| ``overpowering_state`` | Le dernier état connu du capteur surpuissant. Aucun si la gestion de l'alimentation n'est pas configurée |
|
||||
| ``presence_state`` | Le dernier état connu du capteur de présence. Aucun si la gestion de présence n'est pas configurée |
|
||||
| ``delay_security_min`` | Le délai avant de régler le mode de sécurité lorsque le capteur de température est éteint |
|
||||
| ``security_delay_min`` | Le délai avant de régler le mode de sécurité lorsque le capteur de température est éteint |
|
||||
| ``security_min_on_percent`` | Seuil en dessous duquel le thermostat ne passera pas en sécurité |
|
||||
| ``last_temperature_datetime`` | La date et l'heure au format ISO8866 de la dernière réception de température interne |
|
||||
| ``last_ext_temperature_datetime`` | La date et l'heure au format ISO8866 de la dernière réception de température extérieure |
|
||||
| ``**état_sécurité**`` | L'état de sécurité. vrai ou faux |
|
||||
|
||||
@@ -233,13 +233,15 @@ The first delay (minimal_activation_delay_sec) in sec in the minimum delay accep
|
||||
|
||||
The second delay (security_delay_min) is the maximal delay between two temperature measure before setting the preset to ``security`` and turning off the thermostat. If the temperature sensor is no more giving temperature measures, the thermostat and heater will turns off after this delay and the preset of the thermostat will be set to ``security``. This is useful to avoid overheating is the battery of your temperature sensor is too low.
|
||||
|
||||
The third parameter (security_min_on_percent) is the minimal on_percent value below which the security preset won't be trigger. If you set it to ``0.00`` security preset will be trigger regardeless of the heating on_percent when there is a temperature loss, at the opposite ``1.00`` will never trigger the security preset.
|
||||
|
||||
See [exemple tuning](#examples-tuning) to have some commons tuning examples
|
||||
|
||||
>  _*Notes*_
|
||||
1. The ``security`` preset is a hidden preset. You cannot select it manually or by the preset service,
|
||||
2. When the temperature sensor will comes to live and re-send temperatures, the preset will be restored to its previous value,
|
||||
3. Beware that two temperatures are needed: internal temp and external temp and each should give temperature else the thermostat will be in ``security`` preset.
|
||||
|
||||
|
||||
# Examples tuning
|
||||
|
||||
## Electrical heater
|
||||
@@ -253,7 +255,7 @@ See [exemple tuning](#examples-tuning) to have some commons tuning examples
|
||||
## Temperature sensor will battery
|
||||
- security_delay_min: 60 min (because those sensors are leazy)
|
||||
|
||||
## Reponsive temperature sensor
|
||||
## Reponsive temperature sensor
|
||||
- security_delay_min: 15 min
|
||||
|
||||
## My preset configuration
|
||||
@@ -362,6 +364,7 @@ Custom attributes are the following:
|
||||
| ``overpowering_state`` | The last known state of the overpowering sensor. None if power management is not configured |
|
||||
| ``presence_state`` | The last known state of the presence sensor. None if presence management is not configured |
|
||||
| ``security_delay_min`` | The delay before setting the security mode when temperature sensor are off |
|
||||
| ``security_min_on_percent`` | The minimal on_percent below which security preset won't be trigger |
|
||||
| ``last_temperature_datetime`` | The date and time in ISO8866 format of the last internal temperature reception |
|
||||
| ``last_ext_temperature_datetime`` | The date and time in ISO8866 format of the last external temperature reception |
|
||||
| ``security_state`` | The security state. true or false |
|
||||
|
||||
@@ -20,7 +20,7 @@ from homeassistant.helpers.restore_state import RestoreEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.util.unit_system import UnitOfTemperature
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
from homeassistant.helpers.event import (
|
||||
async_track_state_change_event,
|
||||
@@ -115,8 +115,13 @@ from .const import (
|
||||
PROPORTIONAL_FUNCTION_TPI,
|
||||
SERVICE_SET_PRESENCE,
|
||||
SERVICE_SET_PRESET_TEMPERATURE,
|
||||
SERVICE_SET_SECURITY,
|
||||
PRESET_AWAY_SUFFIX,
|
||||
CONF_SECURITY_DELAY_MIN,
|
||||
CONF_SECURITY_MIN_ON_PERCENT,
|
||||
CONF_SECURITY_DEFAULT_ON_PERCENT,
|
||||
DEFAULT_SECURITY_MIN_ON_PERCENT,
|
||||
DEFAULT_SECURITY_DEFAULT_ON_PERCENT,
|
||||
CONF_MINIMAL_ACTIVATION_DELAY,
|
||||
CONF_TEMP_MAX,
|
||||
CONF_TEMP_MIN,
|
||||
@@ -126,6 +131,7 @@ from .const import (
|
||||
CONF_THERMOSTAT_CLIMATE,
|
||||
CONF_CLIMATE,
|
||||
UnknownEntity,
|
||||
EventType,
|
||||
)
|
||||
|
||||
from .prop_algorithm import PropAlgorithm
|
||||
@@ -174,6 +180,16 @@ async def async_setup_entry(
|
||||
"service_set_preset_temperature",
|
||||
)
|
||||
|
||||
platform.async_register_entity_service(
|
||||
SERVICE_SET_SECURITY,
|
||||
{
|
||||
vol.Optional("delay_min"): cv.positive_int,
|
||||
vol.Optional("min_on_percent"): vol.Coerce(float),
|
||||
vol.Optional("default_on_percent"): vol.Coerce(float),
|
||||
},
|
||||
"service_set_security",
|
||||
)
|
||||
|
||||
|
||||
class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
"""Representation of a Versatile Thermostat device."""
|
||||
@@ -182,7 +198,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
# No more needed
|
||||
# _registry: dict[str, object] = {}
|
||||
|
||||
def __init__(self, hass, unique_id, name, entry_infos) -> None:
|
||||
def __init__(self, hass: HomeAssistant, unique_id, name, entry_infos) -> None:
|
||||
"""Initialize the thermostat."""
|
||||
|
||||
super().__init__()
|
||||
@@ -217,7 +233,10 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
self._presence_state = None
|
||||
self._overpowering_state = None
|
||||
self._should_relaunch_control_heating = None
|
||||
|
||||
self._security_delay_min = None
|
||||
self._security_min_on_percent = None
|
||||
self._security_default_on_percent = None
|
||||
self._security_state = None
|
||||
|
||||
self._thermostat_type = None
|
||||
@@ -240,7 +259,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
)
|
||||
# convert entry_infos into usable attributes
|
||||
presets = {}
|
||||
for (key, value) in CONF_PRESETS.items():
|
||||
for key, value in CONF_PRESETS.items():
|
||||
_LOGGER.debug("looking for key=%s, value=%s", key, value)
|
||||
if value in entry_infos:
|
||||
presets[key] = entry_infos.get(value)
|
||||
@@ -248,7 +267,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
_LOGGER.debug("value %s not found in Entry", value)
|
||||
|
||||
presets_away = {}
|
||||
for (key, value) in CONF_PRESETS_AWAY.items():
|
||||
for key, value in CONF_PRESETS_AWAY.items():
|
||||
_LOGGER.debug("looking for key=%s, value=%s", key, value)
|
||||
if value in entry_infos:
|
||||
presets_away[key] = entry_infos.get(value)
|
||||
@@ -306,7 +325,8 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
# self.hvac_list = [HVAC_MODE_COOL, HVAC_MODE_OFF]
|
||||
# else:
|
||||
self._hvac_list = [HVACMode.HEAT, HVACMode.OFF]
|
||||
self._unit = UnitOfTemperature.CELSIUS
|
||||
|
||||
self._unit = self._hass.config.units.temperature_unit
|
||||
# Will be restored if possible
|
||||
self._hvac_mode = None # HVAC_MODE_OFF
|
||||
self._saved_hvac_mode = self._hvac_mode
|
||||
@@ -363,6 +383,14 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
self._tpi_coef_ext = 0
|
||||
|
||||
self._security_delay_min = entry_infos.get(CONF_SECURITY_DELAY_MIN)
|
||||
self._security_min_on_percent = (
|
||||
entry_infos.get(CONF_SECURITY_MIN_ON_PERCENT)
|
||||
or DEFAULT_SECURITY_MIN_ON_PERCENT
|
||||
)
|
||||
self._security_default_on_percent = (
|
||||
entry_infos.get(CONF_SECURITY_DEFAULT_ON_PERCENT)
|
||||
or DEFAULT_SECURITY_DEFAULT_ON_PERCENT
|
||||
)
|
||||
self._minimal_activation_delay = entry_infos.get(CONF_MINIMAL_ACTIVATION_DELAY)
|
||||
self._last_temperature_mesure = datetime.now()
|
||||
self._last_ext_temperature_mesure = datetime.now()
|
||||
@@ -727,12 +755,21 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
float(old_state.attributes[ATTR_TEMPERATURE])
|
||||
)
|
||||
|
||||
if old_state.attributes.get(ATTR_PRESET_MODE) in self._attr_preset_modes:
|
||||
old_preset_mode = old_state.attributes.get(ATTR_PRESET_MODE)
|
||||
# Never restore a Power or Security preset
|
||||
if (
|
||||
old_preset_mode in self._attr_preset_modes
|
||||
and old_preset_mode not in HIDDEN_PRESETS
|
||||
):
|
||||
self._attr_preset_mode = old_state.attributes.get(ATTR_PRESET_MODE)
|
||||
self.save_preset_mode()
|
||||
else:
|
||||
self._attr_preset_mode = PRESET_NONE
|
||||
|
||||
if not self._hvac_mode and old_state.state:
|
||||
self._hvac_mode = old_state.state
|
||||
else:
|
||||
self._hvac_mode = HVACMode.OFF
|
||||
|
||||
else:
|
||||
# No previous state, try and restore defaults
|
||||
@@ -751,6 +788,9 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
if not self._hvac_mode:
|
||||
self._hvac_mode = HVACMode.OFF
|
||||
|
||||
self.send_event(EventType.PRESET_EVENT, {"preset": self._attr_preset_mode})
|
||||
self.send_event(EventType.HVAC_MODE_EVENT, {"hvac_mode": self._hvac_mode})
|
||||
|
||||
_LOGGER.info(
|
||||
"%s - restored state is target_temp=%.1f, preset_mode=%s, hvac_mode=%s",
|
||||
self,
|
||||
@@ -829,6 +869,9 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
"""Return the unit of measurement."""
|
||||
if self._is_over_climate and self._underlying_climate:
|
||||
return self._underlying_climate.temperature_unit
|
||||
|
||||
return self._unit
|
||||
|
||||
@property
|
||||
@@ -1003,8 +1046,11 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
_LOGGER.error("Unrecognized hvac mode: %s", hvac_mode)
|
||||
return
|
||||
# Ensure we update the current operation after changing the mode
|
||||
self.reset_last_temperature_time()
|
||||
|
||||
self.update_custom_attributes()
|
||||
self.async_write_ha_state()
|
||||
self.send_event(EventType.HVAC_MODE_EVENT, {"hvac_mode": self._hvac_mode})
|
||||
|
||||
async def async_set_preset_mode(self, preset_mode):
|
||||
"""Set new preset mode."""
|
||||
@@ -1025,6 +1071,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
if preset_mode == self._attr_preset_mode and not force:
|
||||
# I don't think we need to call async_write_ha_state if we didn't change the state
|
||||
return
|
||||
old_preset_mode = self._attr_preset_mode
|
||||
if preset_mode == PRESET_NONE:
|
||||
self._attr_preset_mode = PRESET_NONE
|
||||
if self._saved_target_temp:
|
||||
@@ -1040,9 +1087,21 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
self.find_preset_temp(preset_mode)
|
||||
)
|
||||
|
||||
self.save_preset_mode()
|
||||
self.reset_last_temperature_time(old_preset_mode)
|
||||
|
||||
self.save_preset_mode()
|
||||
self.recalculate()
|
||||
self.send_event(EventType.PRESET_EVENT, {"preset": self._attr_preset_mode})
|
||||
|
||||
def reset_last_temperature_time(self, old_preset_mode=None):
|
||||
"""Reset to now the last temperature time if conditions are satisfied"""
|
||||
if (
|
||||
self._attr_preset_mode not in HIDDEN_PRESETS
|
||||
and old_preset_mode not in HIDDEN_PRESETS
|
||||
):
|
||||
self._last_temperature_mesure = (
|
||||
self._last_ext_temperature_mesure
|
||||
) = datetime.now()
|
||||
|
||||
def find_preset_temp(self, preset_mode):
|
||||
"""Find the right temperature of a preset considering the presence if configured"""
|
||||
@@ -1152,7 +1211,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
async def _async_temperature_changed(self, event):
|
||||
"""Handle temperature changes."""
|
||||
new_state = event.data.get("new_state")
|
||||
_LOGGER.info(
|
||||
_LOGGER.debug(
|
||||
"%s - Temperature changed. Event.new_state is %s",
|
||||
self,
|
||||
new_state,
|
||||
@@ -1167,7 +1226,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
async def _async_ext_temperature_changed(self, event):
|
||||
"""Handle external temperature changes."""
|
||||
new_state = event.data.get("new_state")
|
||||
_LOGGER.info(
|
||||
_LOGGER.debug(
|
||||
"%s - external Temperature changed. Event.new_state is %s",
|
||||
self,
|
||||
new_state,
|
||||
@@ -1609,6 +1668,15 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
self.save_preset_mode()
|
||||
await self._async_underlying_entity_turn_off()
|
||||
await self._async_set_preset_mode_internal(PRESET_POWER)
|
||||
self.send_event(
|
||||
EventType.POWER_EVENT,
|
||||
{
|
||||
"type": "start",
|
||||
"current_power": self._current_power,
|
||||
"device_power": self._device_power,
|
||||
"current_power_max": self._current_power_max,
|
||||
},
|
||||
)
|
||||
|
||||
# Check if we need to remove the POWER preset
|
||||
if (
|
||||
@@ -1624,6 +1692,15 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
if self._is_over_climate:
|
||||
await self.restore_hvac_mode()
|
||||
await self.restore_preset_mode()
|
||||
self.send_event(
|
||||
EventType.POWER_EVENT,
|
||||
{
|
||||
"type": "end",
|
||||
"current_power": self._current_power,
|
||||
"device_power": self._device_power,
|
||||
"current_power_max": self._current_power_max,
|
||||
},
|
||||
)
|
||||
|
||||
self._overpowering_state = ret
|
||||
return self._overpowering_state
|
||||
@@ -1635,12 +1712,8 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
delta_ext_temp = (
|
||||
now - self._last_ext_temperature_mesure
|
||||
).total_seconds() / 60.0
|
||||
_LOGGER.debug(
|
||||
"%s - checking security delta_temp=%.1f delta_ext_temp=%.1f",
|
||||
self,
|
||||
delta_temp,
|
||||
delta_ext_temp,
|
||||
)
|
||||
|
||||
mode_cond = self._is_over_climate or self._hvac_mode != HVACMode.OFF
|
||||
|
||||
temp_cond: bool = (
|
||||
delta_temp > self._security_delay_min
|
||||
@@ -1653,11 +1726,12 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
switch_cond: bool = (
|
||||
not self._is_over_climate
|
||||
and self._prop_algorithm is not None
|
||||
and self._prop_algorithm.on_percent > 0.75
|
||||
and self._prop_algorithm.calculated_on_percent
|
||||
>= self._security_min_on_percent
|
||||
)
|
||||
|
||||
ret = False
|
||||
if temp_cond and climate_cond:
|
||||
if mode_cond and temp_cond and climate_cond:
|
||||
if not self._security_state:
|
||||
_LOGGER.warning(
|
||||
"%s - No temperature received for more than %.1f minutes (dt=%.1f, dext=%.1f) and underlying climate is %s. Set it into security mode",
|
||||
@@ -1669,24 +1743,64 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
)
|
||||
ret = True
|
||||
|
||||
if temp_cond and switch_cond:
|
||||
_LOGGER.debug(
|
||||
"%s - checking security delta_temp=%.1f delta_ext_temp=%.1f mod_cond=%s temp_cond=%s climate_cond=%s switch_cond=%s",
|
||||
self,
|
||||
delta_temp,
|
||||
delta_ext_temp,
|
||||
mode_cond,
|
||||
temp_cond,
|
||||
climate_cond,
|
||||
switch_cond,
|
||||
)
|
||||
|
||||
if mode_cond and temp_cond and switch_cond:
|
||||
if not self._security_state:
|
||||
_LOGGER.warning(
|
||||
"%s - No temperature received for more than %.1f minutes (dt=%.1f, dext=%.1f) and on_percent is high (%.2f). Set it into security mode",
|
||||
"%s - No temperature received for more than %.1f minutes (dt=%.1f, dext=%.1f) and on_percent (%.2f) is over defined value (%.2f). Set it into security mode",
|
||||
self,
|
||||
self._security_delay_min,
|
||||
delta_temp,
|
||||
delta_ext_temp,
|
||||
self._prop_algorithm.on_percent,
|
||||
self._security_min_on_percent,
|
||||
)
|
||||
ret = True
|
||||
|
||||
if mode_cond and temp_cond and not self._security_state:
|
||||
self.send_event(
|
||||
EventType.TEMPERATURE_EVENT,
|
||||
{
|
||||
"last_temperature_mesure": self._last_temperature_mesure.isoformat(),
|
||||
"last_ext_temperature_mesure": self._last_ext_temperature_mesure.isoformat(),
|
||||
"current_temp": self._cur_temp,
|
||||
"current_ext_temp": self._cur_ext_temp,
|
||||
"target_temp": self.target_temperature,
|
||||
},
|
||||
)
|
||||
|
||||
if not self._security_state and ret:
|
||||
self._security_state = ret
|
||||
self.save_hvac_mode()
|
||||
self.save_preset_mode()
|
||||
await self._async_set_preset_mode_internal(PRESET_SECURITY)
|
||||
await self.async_set_hvac_mode(HVACMode.OFF)
|
||||
# Turn off the underlying climate or heater if security default on_percent is 0
|
||||
if self._is_over_climate or self._security_default_on_percent <= 0.0:
|
||||
await self.async_set_hvac_mode(HVACMode.OFF)
|
||||
if self._prop_algorithm:
|
||||
self._prop_algorithm.set_security(self._security_default_on_percent)
|
||||
|
||||
self.send_event(
|
||||
EventType.SECURITY_EVENT,
|
||||
{
|
||||
"type": "start",
|
||||
"last_temperature_mesure": self._last_temperature_mesure.isoformat(),
|
||||
"last_ext_temperature_mesure": self._last_ext_temperature_mesure.isoformat(),
|
||||
"current_temp": self._cur_temp,
|
||||
"current_ext_temp": self._cur_ext_temp,
|
||||
"target_temp": self.target_temperature,
|
||||
},
|
||||
)
|
||||
|
||||
if (
|
||||
self._security_state
|
||||
@@ -1700,15 +1814,30 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
self._saved_preset_mode,
|
||||
)
|
||||
self._security_state = ret
|
||||
await self.restore_hvac_mode()
|
||||
# Restore hvac_mode if previously saved
|
||||
if self._is_over_climate or self._security_default_on_percent <= 0.0:
|
||||
await self.restore_hvac_mode()
|
||||
await self.restore_preset_mode()
|
||||
if self._prop_algorithm:
|
||||
self._prop_algorithm.unset_security()
|
||||
self.send_event(
|
||||
EventType.SECURITY_EVENT,
|
||||
{
|
||||
"type": "end",
|
||||
"last_temperature_mesure": self._last_temperature_mesure.isoformat(),
|
||||
"last_ext_temperature_mesure": self._last_ext_temperature_mesure.isoformat(),
|
||||
"current_temp": self._cur_temp,
|
||||
"current_ext_temp": self._cur_ext_temp,
|
||||
"target_temp": self.target_temperature,
|
||||
},
|
||||
)
|
||||
|
||||
return ret
|
||||
|
||||
async def _async_control_heating(self, force=False, _=None):
|
||||
"""The main function used to run the calculation at each cycle"""
|
||||
|
||||
_LOGGER.info(
|
||||
_LOGGER.debug(
|
||||
"%s - Checking new cycle. hvac_mode=%s, security_state=%s, preset_mode=%s",
|
||||
self,
|
||||
self._hvac_mode,
|
||||
@@ -1723,8 +1852,8 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
return
|
||||
|
||||
security: bool = await self.check_security()
|
||||
if security:
|
||||
_LOGGER.debug("%s - End of cycle (security)", self)
|
||||
if security and self._is_over_climate:
|
||||
_LOGGER.debug("%s - End of cycle (security and over climate)", self)
|
||||
return
|
||||
|
||||
# Stop here if we are off
|
||||
@@ -1737,7 +1866,8 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
if not self._is_over_climate:
|
||||
on_time_sec: int = self._prop_algorithm.on_time_sec
|
||||
off_time_sec: int = self._prop_algorithm.off_time_sec
|
||||
_LOGGER.info(
|
||||
|
||||
_LOGGER.debug(
|
||||
"%s - Checking new cycle. on_time_sec=%.0f, off_time_sec=%.0f, security_state=%s, preset_mode=%s",
|
||||
self,
|
||||
on_time_sec,
|
||||
@@ -1778,13 +1908,12 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
return
|
||||
|
||||
if on:
|
||||
security = (
|
||||
await self.check_security()
|
||||
or await self.check_overpowering()
|
||||
)
|
||||
if security:
|
||||
if await self.check_overpowering():
|
||||
_LOGGER.debug("%s - End of cycle (3)", self)
|
||||
return
|
||||
# Security mode could have change the on_time percent
|
||||
await self.check_security()
|
||||
time = self._prop_algorithm.on_time_sec
|
||||
|
||||
action_label = "start" if on else "stop"
|
||||
if self._should_relaunch_control_heating:
|
||||
@@ -1799,7 +1928,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
|
||||
if time > 0:
|
||||
_LOGGER.info(
|
||||
"%s - !!! %s heating for %d min %d sec",
|
||||
"%s - %s heating for %d min %d sec",
|
||||
self,
|
||||
action_label,
|
||||
time // 60,
|
||||
@@ -1894,6 +2023,8 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
"overpowering_state": self._overpowering_state,
|
||||
"presence_state": self._presence_state,
|
||||
"security_delay_min": self._security_delay_min,
|
||||
"security_min_on_percent": self._security_min_on_percent,
|
||||
"security_default_on_percent": self._security_default_on_percent,
|
||||
"last_temperature_datetime": self._last_temperature_mesure.isoformat(),
|
||||
"last_ext_temperature_datetime": self._last_ext_temperature_mesure.isoformat(),
|
||||
"security_state": self._security_state,
|
||||
@@ -1983,3 +2114,41 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
if self._attr_preset_mode == preset:
|
||||
await self._async_set_preset_mode_internal(preset, force=True)
|
||||
await self._async_control_heating(force=True)
|
||||
|
||||
async def service_set_security(self, delay_min, min_on_percent, default_on_percent):
|
||||
"""Called by a service call:
|
||||
service: versatile_thermostat.set_security
|
||||
data:
|
||||
delay_min: 15
|
||||
min_on_percent: 0.5
|
||||
default_on_percent: 0.2
|
||||
target:
|
||||
entity_id: climate.thermostat_2
|
||||
"""
|
||||
_LOGGER.info(
|
||||
"%s - Calling service_set_security, delay_min: %s, min_on_percent: %s, default_on_percent: %s",
|
||||
self,
|
||||
delay_min,
|
||||
min_on_percent,
|
||||
default_on_percent,
|
||||
)
|
||||
if delay_min:
|
||||
self._security_delay_min = delay_min
|
||||
if min_on_percent:
|
||||
self._security_min_on_percent = min_on_percent
|
||||
if default_on_percent:
|
||||
self._security_default_on_percent = default_on_percent
|
||||
|
||||
if self._prop_algorithm and self._security_state:
|
||||
self._prop_algorithm.set_security(self._security_default_on_percent)
|
||||
|
||||
await self._async_control_heating()
|
||||
self.update_custom_attributes()
|
||||
|
||||
def send_event(self, event_type: EventType, data: dict):
|
||||
"""Send an event"""
|
||||
_LOGGER.info("%s - Sending event %s with data: %s", self, event_type, data)
|
||||
data["entity_id"] = self.entity_id
|
||||
data["name"] = self.name
|
||||
data["state_attributes"] = self.state_attributes
|
||||
self._hass.bus.fire(event_type.value, data)
|
||||
|
||||
@@ -63,6 +63,10 @@ from .const import (
|
||||
CONF_PRESENCE_SENSOR,
|
||||
PROPORTIONAL_FUNCTION_TPI,
|
||||
CONF_SECURITY_DELAY_MIN,
|
||||
CONF_SECURITY_MIN_ON_PERCENT,
|
||||
CONF_SECURITY_DEFAULT_ON_PERCENT,
|
||||
DEFAULT_SECURITY_MIN_ON_PERCENT,
|
||||
DEFAULT_SECURITY_DEFAULT_ON_PERCENT,
|
||||
CONF_MINIMAL_ACTIVATION_DELAY,
|
||||
CONF_TEMP_MAX,
|
||||
CONF_TEMP_MIN,
|
||||
@@ -176,53 +180,16 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
|
||||
is_empty or self._infos.get(CONF_PRESENCE_SENSOR) is not None
|
||||
)
|
||||
|
||||
# self.hass = async_get_hass()
|
||||
# ent_reg = async_get(hass=self.hass)
|
||||
|
||||
# climates = []
|
||||
# switches = []
|
||||
# temp_sensors = []
|
||||
# power_sensors = []
|
||||
# window_sensors = []
|
||||
# presence_sensors = []
|
||||
#
|
||||
# k: str
|
||||
# for k in ent_reg.entities:
|
||||
# v: RegistryEntry = ent_reg.entities[k]
|
||||
# _LOGGER.debug("Looking entity: %s", k)
|
||||
# # if k.startswith(CLIMATE_DOMAIN) and (
|
||||
# # infos is None or k != infos.get("entity_id")
|
||||
# # ):
|
||||
# # _LOGGER.debug("Climate !")
|
||||
# # climates.append(k)
|
||||
# if k.startswith(SWITCH_DOMAIN) or k.startswith(INPUT_BOOLEAN_DOMAIN):
|
||||
# _LOGGER.debug("Switch !")
|
||||
# switches.append(k)
|
||||
# elif is_temperature_sensor(v):
|
||||
# _LOGGER.debug("Temperature sensor !")
|
||||
# temp_sensors.append(k)
|
||||
# elif is_power_sensor(v):
|
||||
# _LOGGER.debug("Power sensor !")
|
||||
# power_sensors.append(k)
|
||||
# elif k.startswith(PERSON_DOMAIN):
|
||||
# _LOGGER.debug("Presence sensor !")
|
||||
# presence_sensors.append(k)
|
||||
#
|
||||
# # window sensor and presence
|
||||
# if k.startswith(INPUT_BOOLEAN_DOMAIN) or k.startswith(BINARY_SENSOR_DOMAIN):
|
||||
# _LOGGER.debug("Window or presence sensor !")
|
||||
# window_sensors.append(k)
|
||||
# presence_sensors.append(k)
|
||||
#
|
||||
# # Special case for climates which are not in EntityRegistry
|
||||
# climates = self.find_all_climates()
|
||||
|
||||
self.STEP_USER_DATA_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_NAME): cv.string,
|
||||
vol.Required(
|
||||
CONF_THERMOSTAT_TYPE, default=CONF_THERMOSTAT_SWITCH
|
||||
): vol.In(CONF_THERMOSTAT_TYPES),
|
||||
): selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(
|
||||
options=CONF_THERMOSTAT_TYPES, translation_key="thermostat_type"
|
||||
)
|
||||
),
|
||||
vol.Required(CONF_TEMP_SENSOR): selector.EntitySelector(
|
||||
selector.EntitySelectorConfig(
|
||||
domain=[SENSOR_DOMAIN, INPUT_NUMBER_DOMAIN]
|
||||
@@ -353,6 +320,14 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
|
||||
CONF_MINIMAL_ACTIVATION_DELAY, default=10
|
||||
): cv.positive_int,
|
||||
vol.Required(CONF_SECURITY_DELAY_MIN, default=60): cv.positive_int,
|
||||
vol.Required(
|
||||
CONF_SECURITY_MIN_ON_PERCENT,
|
||||
default=DEFAULT_SECURITY_MIN_ON_PERCENT,
|
||||
): vol.Coerce(float),
|
||||
vol.Required(
|
||||
CONF_SECURITY_DEFAULT_ON_PERCENT,
|
||||
default=DEFAULT_SECURITY_DEFAULT_ON_PERCENT,
|
||||
): vol.Coerce(float),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Constants for the Versatile Thermostat integration."""
|
||||
|
||||
from enum import Enum
|
||||
from homeassistant.const import CONF_NAME
|
||||
from homeassistant.components.climate.const import (
|
||||
# PRESET_ACTIVITY,
|
||||
@@ -44,6 +45,8 @@ CONF_MINIMAL_ACTIVATION_DELAY = "minimal_activation_delay"
|
||||
CONF_TEMP_MIN = "temp_min"
|
||||
CONF_TEMP_MAX = "temp_max"
|
||||
CONF_SECURITY_DELAY_MIN = "security_delay_min"
|
||||
CONF_SECURITY_MIN_ON_PERCENT = "security_min_on_percent"
|
||||
CONF_SECURITY_DEFAULT_ON_PERCENT = "security_default_on_percent"
|
||||
CONF_THERMOSTAT_TYPE = "thermostat_type"
|
||||
CONF_THERMOSTAT_SWITCH = "thermostat_over_switch"
|
||||
CONF_THERMOSTAT_CLIMATE = "thermostat_over_climate"
|
||||
@@ -102,6 +105,8 @@ ALL_CONF = (
|
||||
CONF_TEMP_MIN,
|
||||
CONF_TEMP_MAX,
|
||||
CONF_SECURITY_DELAY_MIN,
|
||||
CONF_SECURITY_MIN_ON_PERCENT,
|
||||
CONF_SECURITY_DEFAULT_ON_PERCENT,
|
||||
CONF_THERMOSTAT_TYPE,
|
||||
CONF_THERMOSTAT_SWITCH,
|
||||
CONF_THERMOSTAT_CLIMATE,
|
||||
@@ -125,6 +130,20 @@ SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE
|
||||
|
||||
SERVICE_SET_PRESENCE = "set_presence"
|
||||
SERVICE_SET_PRESET_TEMPERATURE = "set_preset_temperature"
|
||||
SERVICE_SET_SECURITY = "set_security"
|
||||
|
||||
DEFAULT_SECURITY_MIN_ON_PERCENT = 0.5
|
||||
DEFAULT_SECURITY_DEFAULT_ON_PERCENT = 0.1
|
||||
|
||||
|
||||
class EventType(Enum):
|
||||
"""The event type that can be sent"""
|
||||
|
||||
SECURITY_EVENT: str = "versatile_thermostat_security_event"
|
||||
POWER_EVENT: str = "versatile_thermostat_power_event"
|
||||
TEMPERATURE_EVENT: str = "versatile_thermostat_temperature_event"
|
||||
HVAC_MODE_EVENT: str = "versatile_thermostat_hvac_mode_event"
|
||||
PRESET_EVENT: str = "versatile_thermostat_preset_event"
|
||||
|
||||
|
||||
class UnknownEntity(HomeAssistantError):
|
||||
|
||||
@@ -37,8 +37,11 @@ class PropAlgorithm:
|
||||
self._cycle_min = cycle_min
|
||||
self._minimal_activation_delay = minimal_activation_delay
|
||||
self._on_percent = 0
|
||||
self._calculated_on_percent = 0
|
||||
self._on_time_sec = 0
|
||||
self._off_time_sec = self._cycle_min * 60
|
||||
self._security = False
|
||||
self._default_on_percent = 0
|
||||
|
||||
def calculate(
|
||||
self, target_temp: float, current_temp: float, ext_current_temp: float
|
||||
@@ -48,7 +51,7 @@ class PropAlgorithm:
|
||||
_LOGGER.warning(
|
||||
"Proportional algorithm: calculation is not possible cause target_temp or current_temp is null. Heating will be disabled" # pylint: disable=line-too-long
|
||||
)
|
||||
self._on_percent = 0
|
||||
self._calculated_on_percent = 0
|
||||
else:
|
||||
delta_temp = target_temp - current_temp
|
||||
delta_ext_temp = (
|
||||
@@ -56,7 +59,7 @@ class PropAlgorithm:
|
||||
)
|
||||
|
||||
if self._function == PROPORTIONAL_FUNCTION_TPI:
|
||||
self._on_percent = (
|
||||
self._calculated_on_percent = (
|
||||
self._tpi_coef_int * delta_temp
|
||||
+ self._tpi_coef_ext * delta_ext_temp
|
||||
)
|
||||
@@ -65,7 +68,35 @@ class PropAlgorithm:
|
||||
"Proportional algorithm: unknown %s function. Heating will be disabled",
|
||||
self._function,
|
||||
)
|
||||
self._on_percent = 0
|
||||
self._calculated_on_percent = 0
|
||||
|
||||
self._calculate_internal()
|
||||
|
||||
_LOGGER.debug(
|
||||
"heating percent calculated for current_temp %.1f, ext_current_temp %.1f and target_temp %.1f is %.2f, on_time is %d (sec), off_time is %d (sec)", # pylint: disable=line-too-long
|
||||
current_temp if current_temp else -9999.0,
|
||||
ext_current_temp if ext_current_temp else -9999.0,
|
||||
target_temp if target_temp else -9999.0,
|
||||
self._calculated_on_percent,
|
||||
self.on_time_sec,
|
||||
self.off_time_sec,
|
||||
)
|
||||
|
||||
def _calculate_internal(self):
|
||||
"""Finish the calculation to get the on_percent in seconds"""
|
||||
|
||||
if self._security:
|
||||
_LOGGER.debug(
|
||||
"Security is On using the default_on_percent %f",
|
||||
self._default_on_percent,
|
||||
)
|
||||
self._on_percent = self._default_on_percent
|
||||
else:
|
||||
_LOGGER.debug(
|
||||
"Security is Off using the calculated_on_percent %f",
|
||||
self._calculated_on_percent,
|
||||
)
|
||||
self._on_percent = self._calculated_on_percent
|
||||
|
||||
# calculated on_time duration in seconds
|
||||
if self._on_percent > 1:
|
||||
@@ -92,21 +123,31 @@ class PropAlgorithm:
|
||||
|
||||
self._off_time_sec = self._cycle_min * 60 - self._on_time_sec
|
||||
|
||||
_LOGGER.debug(
|
||||
"heating percent calculated for current_temp %.1f, ext_current_temp %.1f and target_temp %.1f is %.2f, on_time is %d (sec), off_time is %d (sec)", # pylint: disable=line-too-long
|
||||
current_temp if current_temp else -9999.0,
|
||||
ext_current_temp if ext_current_temp else -9999.0,
|
||||
target_temp if target_temp else -9999.0,
|
||||
self._on_percent,
|
||||
self.on_time_sec,
|
||||
self.off_time_sec,
|
||||
)
|
||||
def set_security(self, default_on_percent: float):
|
||||
"""Set a default value for on_percent (used for security mode)"""
|
||||
self._security = True
|
||||
self._default_on_percent = default_on_percent
|
||||
self._calculate_internal()
|
||||
|
||||
def unset_security(self):
|
||||
"""Unset the security mode"""
|
||||
self._security = False
|
||||
self._calculate_internal()
|
||||
|
||||
@property
|
||||
def on_percent(self) -> float:
|
||||
"""Returns the percentage the heater must be ON (1 means the heater will be always on, 0 never on)""" # pylint: disable=line-too-long
|
||||
"""Returns the percentage the heater must be ON
|
||||
In security mode this value is overriden with the _default_on_percent
|
||||
(1 means the heater will be always on, 0 never on)""" # pylint: disable=line-too-long
|
||||
return round(self._on_percent, 2)
|
||||
|
||||
@property
|
||||
def calculated_on_percent(self) -> float:
|
||||
"""Returns the calculated percentage the heater must be ON
|
||||
Calculated means NOT overriden even in security mode
|
||||
(1 means the heater will be always on, 0 never on)""" # pylint: disable=line-too-long
|
||||
return round(self._calculated_on_percent, 2)
|
||||
|
||||
@property
|
||||
def on_time_sec(self) -> int:
|
||||
"""Returns the calculated time in sec the heater must be ON"""
|
||||
|
||||
@@ -1,69 +1,117 @@
|
||||
set_presence:
|
||||
name: Set presence
|
||||
description: Force the presence mode in thermostat
|
||||
target:
|
||||
entity:
|
||||
integration: versatile_thermostat
|
||||
fields:
|
||||
presence:
|
||||
name: Presence
|
||||
description: Presence setting
|
||||
required: true
|
||||
advanced: false
|
||||
example: "on"
|
||||
default: "on"
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- "on"
|
||||
- "off"
|
||||
- "home"
|
||||
- "not_home"
|
||||
name: Set presence
|
||||
description: Force the presence mode in thermostat
|
||||
target:
|
||||
entity:
|
||||
integration: versatile_thermostat
|
||||
fields:
|
||||
presence:
|
||||
name: Presence
|
||||
description: Presence setting
|
||||
required: true
|
||||
advanced: false
|
||||
example: "on"
|
||||
default: "on"
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- "on"
|
||||
- "off"
|
||||
- "home"
|
||||
- "not_home"
|
||||
|
||||
set_preset_temperature:
|
||||
name: Set temperature preset
|
||||
description: Change the target temperature of a preset
|
||||
target:
|
||||
entity:
|
||||
integration: versatile_thermostat
|
||||
fields:
|
||||
preset:
|
||||
name: Preset
|
||||
description: Preset name
|
||||
required: true
|
||||
advanced: false
|
||||
example: "comfort"
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- "eco"
|
||||
- "comfort"
|
||||
- "boost"
|
||||
temperature:
|
||||
name: Temperature when present
|
||||
description: Target temperature for the preset when present
|
||||
required: false
|
||||
advanced: false
|
||||
example: "19.5"
|
||||
default: "17"
|
||||
selector:
|
||||
number:
|
||||
min: 7
|
||||
max: 35
|
||||
step: 0.1
|
||||
unit_of_measurement: °
|
||||
mode: slider
|
||||
temperature_away:
|
||||
name: Temperature when not present
|
||||
description: Target temperature for the preset when not present
|
||||
required: false
|
||||
advanced: false
|
||||
example: "17"
|
||||
default: "15"
|
||||
selector:
|
||||
number:
|
||||
min: 7
|
||||
max: 35
|
||||
step: 0.1
|
||||
unit_of_measurement: °
|
||||
mode: slider
|
||||
name: Set temperature preset
|
||||
description: Change the target temperature of a preset
|
||||
target:
|
||||
entity:
|
||||
integration: versatile_thermostat
|
||||
fields:
|
||||
preset:
|
||||
name: Preset
|
||||
description: Preset name
|
||||
required: true
|
||||
advanced: false
|
||||
example: "comfort"
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- "eco"
|
||||
- "comfort"
|
||||
- "boost"
|
||||
temperature:
|
||||
name: Temperature when present
|
||||
description: Target temperature for the preset when present
|
||||
required: false
|
||||
advanced: false
|
||||
example: "19.5"
|
||||
default: "17"
|
||||
selector:
|
||||
number:
|
||||
min: 7
|
||||
max: 35
|
||||
step: 0.1
|
||||
unit_of_measurement: °
|
||||
mode: slider
|
||||
temperature_away:
|
||||
name: Temperature when not present
|
||||
description: Target temperature for the preset when not present
|
||||
required: false
|
||||
advanced: false
|
||||
example: "17"
|
||||
default: "15"
|
||||
selector:
|
||||
number:
|
||||
min: 7
|
||||
max: 35
|
||||
step: 0.1
|
||||
unit_of_measurement: °
|
||||
mode: slider
|
||||
|
||||
set_security:
|
||||
name: Set security
|
||||
description: Change the security parameters
|
||||
target:
|
||||
entity:
|
||||
integration: versatile_thermostat
|
||||
fields:
|
||||
delay_min:
|
||||
name: Delay in minutes
|
||||
description: Maximum allowed delay in minutes between two temperature mesures
|
||||
required: false
|
||||
advanced: false
|
||||
example: "30"
|
||||
selector:
|
||||
number:
|
||||
min: 0
|
||||
max: 9999
|
||||
unit_of_measurement: "min"
|
||||
mode: box
|
||||
min_on_percent:
|
||||
name: Minimal on_percent
|
||||
description: Minimal heating percent value for security preset activation
|
||||
required: false
|
||||
advanced: false
|
||||
example: "0.5"
|
||||
default: "0.5"
|
||||
selector:
|
||||
number:
|
||||
min: 0
|
||||
max: 1
|
||||
step: 0.05
|
||||
unit_of_measurement: "%"
|
||||
mode: slider
|
||||
default_on_percent:
|
||||
name: on_percent used in security mode
|
||||
description: The default heating percent value in security preset
|
||||
required: false
|
||||
advanced: false
|
||||
example: "0.1"
|
||||
default: "0.1"
|
||||
selector:
|
||||
number:
|
||||
min: 0
|
||||
max: 1
|
||||
step: 0.05
|
||||
unit_of_measurement: "%"
|
||||
mode: slider
|
||||
|
||||
@@ -89,7 +89,9 @@
|
||||
"description": "Configuration of advanced parameters. Leave the default values if you don't know what you are doing.\nThis parameters can lead to a very bad temperature or power regulation.",
|
||||
"data": {
|
||||
"minimal_activation_delay": "Delay in secondes under which the equipment will not be activated",
|
||||
"security_delay_min": "Maximum allowed delay in minutes between two temperature mesures. Above this delay, the thermostat will turn to a sceurity off state"
|
||||
"security_delay_min": "Maximum allowed delay in minutes between two temperature mesures. Above this delay, the thermostat will turn to a sceurity off state",
|
||||
"security_min_on_percent": "Minimal heating percent value for security preset activation. Below this amount of on_percent the thermostat won't go into security preset",
|
||||
"security_default_on_percent": "The default heating percent value in security preset. Set to 0 to switch off heater in security present"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -190,7 +192,9 @@
|
||||
"description": "Configuration of advanced parameters. Leave the default values if you don't know what you are doing.\nThis parameters can lead to a very bad temperature or power regulation.",
|
||||
"data": {
|
||||
"minimal_activation_delay": "Delay in secondes under which the equipment will not be activated",
|
||||
"security_delay_min": "Maximum allowed delay in minutes between two temperature mesures. Above this delay, the thermostat will turn to a sceurity off state"
|
||||
"security_delay_min": "Maximum allowed delay in minutes between two temperature mesures. Above this delay, the thermostat will turn to a security off state",
|
||||
"security_min_on_percent": "Minimal heating percent value for security preset activation. Below this amount of on_percent the thermostat won't go into security preset",
|
||||
"security_default_on_percent": "The default heating percent value in security preset. Set to 0 to switch off heater in security present"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -213,13 +217,27 @@
|
||||
"entity": {
|
||||
"climate": {
|
||||
"versatile_thermostat": {
|
||||
"states_attributes": {
|
||||
"state_attributes": {
|
||||
"preset_mode": {
|
||||
"power": "Shedding",
|
||||
"security": "Security"
|
||||
"state": {
|
||||
"power": "Shedding",
|
||||
"security": "Security",
|
||||
"none": "Manual"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"state_attributes": {
|
||||
"_": {
|
||||
"preset_mode": {
|
||||
"state": {
|
||||
"power": "Shedding",
|
||||
"security": "Security",
|
||||
"none": "Manual"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,9 @@
|
||||
"description": "Configuration of advanced parameters. Leave the default values if you don't know what you are doing.\nThis parameters can lead to a very bad temperature or power regulation.",
|
||||
"data": {
|
||||
"minimal_activation_delay": "Delay in secondes under which the equipment will not be activated",
|
||||
"security_delay_min": "Maximum allowed delay in minutes between two temperature mesures. Above this delay, the thermostat will turn to a sceurity off state"
|
||||
"security_delay_min": "Maximum allowed delay in minutes between two temperature mesures. Above this delay, the thermostat will turn to a sceurity off state",
|
||||
"security_min_on_percent": "Minimal heating percent value for security preset activation. Below this amount of on_percent the thermostat won't go into security preset",
|
||||
"security_default_on_percent": "The default heating percent value in security preset. Set to 0 to switch off heater in security present"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -190,7 +192,9 @@
|
||||
"description": "Configuration of advanced parameters. Leave the default values if you don't know what you are doing.\nThis parameters can lead to a very bad temperature or power regulation.",
|
||||
"data": {
|
||||
"minimal_activation_delay": "Delay in secondes under which the equipment will not be activated",
|
||||
"security_delay_min": "Maximum allowed delay in minutes between two temperature mesures. Above this delay, the thermostat will turn to a sceurity off state"
|
||||
"security_delay_min": "Maximum allowed delay in minutes between two temperature mesures. Above this delay, the thermostat will turn to a sceurity off state",
|
||||
"security_min_on_percent": "Minimal heating percent value for security preset activation. Below this amount of on_percent the thermostat won't go into security preset",
|
||||
"security_default_on_percent": "The default heating percent value in security preset. Set to 0 to switch off heater in security present"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -213,13 +217,27 @@
|
||||
"entity": {
|
||||
"climate": {
|
||||
"versatile_thermostat": {
|
||||
"states_attributes": {
|
||||
"state_attributes": {
|
||||
"preset_mode": {
|
||||
"power": "Shedding",
|
||||
"security": "Security"
|
||||
"state": {
|
||||
"power": "Shedding",
|
||||
"security": "Security",
|
||||
"none": "Manual"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"state_attributes": {
|
||||
"_": {
|
||||
"preset_mode": {
|
||||
"state": {
|
||||
"power": "Shedding",
|
||||
"security": "Security",
|
||||
"none": "Manual"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,8 +87,10 @@
|
||||
"title": "Parameters avancés",
|
||||
"description": "Configuration des paramètres avancés. Laissez les valeurs par défaut si vous ne savez pas ce que vous faites.\nCes paramètres peuvent induire des mauvais comportements du thermostat.",
|
||||
"data": {
|
||||
"minimal_activation_delay": "Délai en seondes en-dessous duquel l'équipement ne sera pas activé",
|
||||
"security_delay_min": "Délai maximal autorisé en minutes entre 2 mesures de températures. Au-dessus de ce délai, le thermostat se mettra en position éteinte de sécurité"
|
||||
"minimal_activation_delay": "Délai en secondes en-dessous duquel l'équipement ne sera pas activé",
|
||||
"security_delay_min": "Délai maximal autorisé en minutes entre 2 mesures de températures. Au-dessus de ce délai, le thermostat se mettra en position éteinte de sécurité",
|
||||
"security_min_on_percent": "Seuil minimal de pourcentage de chauffage en-dessous duquel le préréglage sécurité ne sera jamais activé",
|
||||
"security_default_on_percent": "Valeur par défaut pour le pourcentage de chauffage en mode sécurité. Mettre 0 pour éteindre le radiateur en mode sécurité"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -190,7 +192,9 @@
|
||||
"description": "Configuration des paramètres avancés. Laissez les valeurs par défaut si vous ne savez pas ce que vous faites.\nCes paramètres peuvent induire des mauvais comportements du thermostat.",
|
||||
"data": {
|
||||
"minimal_activation_delay": "Délai en seondes en-dessous duquel l'équipement ne sera pas activé",
|
||||
"security_delay_min": "Délai maximal autorisé en minutes entre 2 mesures de températures. Au-dessus de ce délai, le thermostat se mettra en position éteinte de sécurité"
|
||||
"security_delay_min": "Délai maximal autorisé en minutes entre 2 mesures de températures. Au-dessus de ce délai, le thermostat se mettra en position éteinte de sécurité",
|
||||
"security_min_on_percent": "Seuil minimal de pourcentage de chauffage en-dessous duquel le préréglage sécurité ne sera jamais activé",
|
||||
"security_default_on_percent": "Valeur par défaut pour le pourcentage de chauffage en mode sécurité. Mettre 0 pour éteindre le radiateur en mode sécurité"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -213,13 +217,27 @@
|
||||
"entity": {
|
||||
"climate": {
|
||||
"versatile_thermostat": {
|
||||
"states_attributes": {
|
||||
"state_attributes": {
|
||||
"preset_mode": {
|
||||
"power": "Délestage",
|
||||
"security": "Sécurité"
|
||||
"state": {
|
||||
"power": "Délestage",
|
||||
"security": "Sécurité",
|
||||
"none": "Manuel"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"state_attributes": {
|
||||
"_": {
|
||||
"preset_mode": {
|
||||
"state": {
|
||||
"power": "Délestage",
|
||||
"security": "Sécurité",
|
||||
"none": "Manuel"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user