From ade1ee43651b7c17d65cde0add8c3e766d474f1e Mon Sep 17 00:00:00 2001 From: Jean-Marc Collin Date: Sat, 11 Feb 2023 10:34:45 +0100 Subject: [PATCH] Missing translations for preset mode Power and Security #46 Set preset internal #45 Notify (send event messages) when something important happens #43 Enhancing Security mode #42 Rename None preset to Manual #3 --- .../versatile_thermostat/climate.py | 166 ++++++++++++++---- .../versatile_thermostat/config_flow.py | 63 ++----- .../versatile_thermostat/const.py | 14 ++ .../versatile_thermostat/prop_algorithm.py | 67 +++++-- .../versatile_thermostat/strings.json | 15 +- .../versatile_thermostat/translations/en.json | 15 +- .../versatile_thermostat/translations/fr.json | 15 +- 7 files changed, 250 insertions(+), 105 deletions(-) diff --git a/custom_components/versatile_thermostat/climate.py b/custom_components/versatile_thermostat/climate.py index 4f6bdaa..0e67eec 100644 --- a/custom_components/versatile_thermostat/climate.py +++ b/custom_components/versatile_thermostat/climate.py @@ -20,7 +20,6 @@ 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 from homeassistant.helpers.event import ( async_track_state_change_event, @@ -118,6 +117,9 @@ from .const import ( 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, @@ -127,6 +129,7 @@ from .const import ( CONF_THERMOSTAT_CLIMATE, CONF_CLIMATE, UnknownEntity, + EventType, ) from .prop_algorithm import PropAlgorithm @@ -183,7 +186,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__() @@ -218,9 +221,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_delay_min = None + self._security_min_on_percent = None + self._security_default_on_percent = None self._security_state = None self._thermostat_type = None @@ -243,7 +247,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) @@ -251,7 +255,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) @@ -367,7 +371,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) + 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() @@ -732,7 +743,12 @@ 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() @@ -756,6 +772,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, @@ -1011,12 +1030,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._last_temperature_mesure = ( - self._last_ext_temperature_mesure - ) = datetime.now() + 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.""" @@ -1052,11 +1070,18 @@ class VersatileThermostat(ClimateEntity, RestoreEntity): self.find_preset_temp(preset_mode) ) - self._last_temperature_mesure = ( - self._last_ext_temperature_mesure - ) = datetime.now() + self.reset_last_temperature_time() + self.save_preset_mode() self.recalculate() + self.send_event(EventType.PRESET_EVENT, {"preset": self._attr_preset_mode}) + + def reset_last_temperature_time(self): + """Reset to now the last temperature time if conditions are satisfied""" + if self._attr_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""" @@ -1623,6 +1648,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 ( @@ -1638,6 +1672,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 @@ -1649,12 +1692,6 @@ 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, - ) temp_cond: bool = ( delta_temp > self._security_delay_min @@ -1667,7 +1704,8 @@ 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 > self._security_min_on_percent + and self._prop_algorithm.calculated_on_percent + > self._security_min_on_percent ) ret = False @@ -1683,6 +1721,16 @@ class VersatileThermostat(ClimateEntity, RestoreEntity): ) ret = True + _LOGGER.debug( + "%s - checking security delta_temp=%.1f delta_ext_temp=%.1f temp_cond=%s climate_cond=%s switch_cond=%s", + self, + delta_temp, + delta_ext_temp, + temp_cond, + climate_cond, + switch_cond, + ) + if temp_cond and switch_cond: if not self._security_state: _LOGGER.warning( @@ -1696,12 +1744,40 @@ class VersatileThermostat(ClimateEntity, RestoreEntity): ) ret = True + if not self._security_state and temp_cond: + 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 @@ -1715,15 +1791,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, @@ -1738,8 +1829,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 @@ -1752,7 +1843,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, @@ -1793,13 +1885,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: @@ -1814,7 +1905,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, @@ -1910,6 +2001,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity): "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, @@ -1999,3 +2091,11 @@ 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) + + 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) diff --git a/custom_components/versatile_thermostat/config_flow.py b/custom_components/versatile_thermostat/config_flow.py index e1798f0..cebbe7d 100644 --- a/custom_components/versatile_thermostat/config_flow.py +++ b/custom_components/versatile_thermostat/config_flow.py @@ -64,6 +64,9 @@ from .const import ( 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, @@ -177,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] @@ -350,9 +316,18 @@ class VersatileThermostatBaseConfigFlow(FlowHandler): self.STEP_ADVANCED_DATA_SCHEMA = vol.Schema( { - vol.Required(CONF_MINIMAL_ACTIVATION_DELAY, default=10): cv.positive_int, + vol.Required( + 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=0.75): vol.Coerce(float), + 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), } ) diff --git a/custom_components/versatile_thermostat/const.py b/custom_components/versatile_thermostat/const.py index 4d3f3e1..e75f4de 100644 --- a/custom_components/versatile_thermostat/const.py +++ b/custom_components/versatile_thermostat/const.py @@ -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, @@ -45,6 +46,7 @@ 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" @@ -104,6 +106,7 @@ ALL_CONF = ( 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, @@ -128,6 +131,17 @@ SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE SERVICE_SET_PRESENCE = "set_presence" SERVICE_SET_PRESET_TEMPERATURE = "set_preset_temperature" +DEFAULT_SECURITY_MIN_ON_PERCENT = 0.5 +DEFAULT_SECURITY_DEFAULT_ON_PERCENT = 0.1 + + +class EventType(Enum): + 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): """Error to indicate there is an unknown entity_id given.""" diff --git a/custom_components/versatile_thermostat/prop_algorithm.py b/custom_components/versatile_thermostat/prop_algorithm.py index bfa24a9..8b1f3d5 100644 --- a/custom_components/versatile_thermostat/prop_algorithm.py +++ b/custom_components/versatile_thermostat/prop_algorithm.py @@ -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""" diff --git a/custom_components/versatile_thermostat/strings.json b/custom_components/versatile_thermostat/strings.json index 61c36d5..dccfe24 100644 --- a/custom_components/versatile_thermostat/strings.json +++ b/custom_components/versatile_thermostat/strings.json @@ -90,7 +90,8 @@ "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_min_on_percent": "Minimal On-Percent value for security preset activation. Below this amount of on_percent the thermostat won't go into security preset" + "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" } } }, @@ -192,7 +193,8 @@ "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 security off state", - "security_min_on_percent": "Minimal On-Percent value for security preset activation. Below this amount of on_percent the thermostat won't go into security preset" + "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" } } }, @@ -215,10 +217,13 @@ "entity": { "climate": { "versatile_thermostat": { - "states_attributes": { + "state_attributes": { "preset_mode": { - "power": "Shedding", - "security": "Security" + "state": { + "power": "Shedding", + "security": "Security", + "none": "Manual" + } } } } diff --git a/custom_components/versatile_thermostat/translations/en.json b/custom_components/versatile_thermostat/translations/en.json index 1ad4286..629067d 100644 --- a/custom_components/versatile_thermostat/translations/en.json +++ b/custom_components/versatile_thermostat/translations/en.json @@ -90,7 +90,8 @@ "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_min_on_percent": "Minimal On-Percent value for security preset activation. Below this amount of on_percent the thermostat won't go into security preset" + "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" } } }, @@ -192,7 +193,8 @@ "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_min_on_percent": "Minimal On-Percent value for security preset activation. Below this amount of on_percent the thermostat won't go into security preset" + "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" } } }, @@ -215,10 +217,13 @@ "entity": { "climate": { "versatile_thermostat": { - "states_attributes": { + "state_attributes": { "preset_mode": { - "power": "Shedding", - "security": "Security" + "state": { + "power": "Shedding", + "security": "Security", + "none": "Manual" + } } } } diff --git a/custom_components/versatile_thermostat/translations/fr.json b/custom_components/versatile_thermostat/translations/fr.json index 6711f7d..0603a56 100644 --- a/custom_components/versatile_thermostat/translations/fr.json +++ b/custom_components/versatile_thermostat/translations/fr.json @@ -89,7 +89,8 @@ "data": { "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 de chauffage en-dessous duquel le préréglage sécurité ne sera jamais activé." + "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é" } } }, @@ -192,7 +193,8 @@ "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_min_on_percent": "Seuil de chauffage en-dessous duquel le préréglage sécurité ne sera jamais activé." + "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é" } } }, @@ -215,10 +217,13 @@ "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" + } } } }