With calculation of VTherm temp entities + test ok
This commit is contained in:
@@ -137,8 +137,6 @@ from .prop_algorithm import PropAlgorithm
|
|||||||
from .open_window_algorithm import WindowOpenDetectionAlgorithm
|
from .open_window_algorithm import WindowOpenDetectionAlgorithm
|
||||||
from .ema import ExponentialMovingAverage
|
from .ema import ExponentialMovingAverage
|
||||||
|
|
||||||
from .temp_number import TemperatureNumber
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
ConfigData = MappingProxyType[str, Any]
|
ConfigData = MappingProxyType[str, Any]
|
||||||
|
|
||||||
@@ -216,6 +214,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
|
self._entry_infos = None
|
||||||
self._attr_extra_state_attributes = {}
|
self._attr_extra_state_attributes = {}
|
||||||
|
|
||||||
self._unique_id = unique_id
|
self._unique_id = unique_id
|
||||||
@@ -288,6 +287,10 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
|
|||||||
self._is_used_by_central_boiler = False
|
self._is_used_by_central_boiler = False
|
||||||
|
|
||||||
self._support_flags = None
|
self._support_flags = None
|
||||||
|
# Preset will be initialized from Number entities
|
||||||
|
self._presets: dict[str, Any] = {} # presets
|
||||||
|
self._presets_away: dict[str, Any] = {} # presets_away
|
||||||
|
|
||||||
self._attr_preset_modes: list[str] | None
|
self._attr_preset_modes: list[str] | None
|
||||||
|
|
||||||
self.post_init(entry_infos)
|
self.post_init(entry_infos)
|
||||||
@@ -356,6 +359,8 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
|
|||||||
|
|
||||||
_LOGGER.info("%s - The merged configuration is %s", self, entry_infos)
|
_LOGGER.info("%s - The merged configuration is %s", self, entry_infos)
|
||||||
|
|
||||||
|
self._entry_infos = entry_infos
|
||||||
|
|
||||||
self._ac_mode = entry_infos.get(CONF_AC_MODE) is True
|
self._ac_mode = entry_infos.get(CONF_AC_MODE) is True
|
||||||
self._attr_max_temp = entry_infos.get(CONF_TEMP_MAX)
|
self._attr_max_temp = entry_infos.get(CONF_TEMP_MAX)
|
||||||
self._attr_min_temp = entry_infos.get(CONF_TEMP_MIN)
|
self._attr_min_temp = entry_infos.get(CONF_TEMP_MIN)
|
||||||
@@ -2649,18 +2654,68 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
|
|||||||
"""Send an event"""
|
"""Send an event"""
|
||||||
send_vtherm_event(self._hass, event_type=event_type, entity=self, data=data)
|
send_vtherm_event(self._hass, event_type=event_type, entity=self, data=data)
|
||||||
|
|
||||||
def get_temperature_number_entities(self, config_entry: ConfigData):
|
async def init_presets(self, central_config):
|
||||||
"""Creates all TemperatureNumber depending of the configuration of the Climate"""
|
"""Init all presets of the VTherm"""
|
||||||
|
# If preset central config is used and central config is set , take the presets from central config
|
||||||
|
vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api()
|
||||||
|
|
||||||
# TODO add the list of preset we want to use in the VTherm. Here we will suppose all preset will be available
|
presets: dict[str, Any] = {}
|
||||||
entity = TemperatureNumber(
|
presets_away: dict[str, Any] = {}
|
||||||
self._hass,
|
|
||||||
unique_id=config_entry.entry_id,
|
def calculate_presets(items, use_central_conf_key):
|
||||||
name=config_entry.data.get(CONF_NAME),
|
presets: dict[str, Any] = {}
|
||||||
preset_name="comfort",
|
config_id = self._unique_id
|
||||||
is_ac=False,
|
if (
|
||||||
is_away=False,
|
central_config
|
||||||
entry_infos=config_entry.data,
|
and self._entry_infos.get(use_central_conf_key, False) is True
|
||||||
|
):
|
||||||
|
config_id = central_config.entry_id
|
||||||
|
|
||||||
|
for key, preset_name in items:
|
||||||
|
_LOGGER.debug("looking for key=%s, preset_name=%s", key, preset_name)
|
||||||
|
value = vtherm_api.get_temperature_number_value(
|
||||||
|
config_id=config_id, preset_name=preset_name
|
||||||
|
)
|
||||||
|
if value is not None:
|
||||||
|
presets[key] = value
|
||||||
|
else:
|
||||||
|
_LOGGER.debug("preset_name %s not found in VTherm API", preset_name)
|
||||||
|
presets[key] = (
|
||||||
|
self._attr_max_temp if self._ac_mode else self._attr_min_temp
|
||||||
|
)
|
||||||
|
return presets
|
||||||
|
|
||||||
|
# Calculate all presets
|
||||||
|
presets = calculate_presets(
|
||||||
|
CONF_PRESETS_WITH_AC.items() if self._ac_mode else CONF_PRESETS.items(),
|
||||||
|
CONF_USE_PRESETS_CENTRAL_CONFIG,
|
||||||
)
|
)
|
||||||
|
|
||||||
return entity
|
if self._entry_infos.get(CONF_USE_PRESENCE_FEATURE) is True:
|
||||||
|
presets_away = calculate_presets(
|
||||||
|
(
|
||||||
|
CONF_PRESETS_AWAY_WITH_AC.items()
|
||||||
|
if self._ac_mode
|
||||||
|
else CONF_PRESETS_AWAY.items()
|
||||||
|
),
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG,
|
||||||
|
)
|
||||||
|
|
||||||
|
# aggregate all available presets now
|
||||||
|
self._presets: dict[str, Any] = presets
|
||||||
|
self._presets_away: dict[str, Any] = presets_away
|
||||||
|
|
||||||
|
# Calculate all possible presets
|
||||||
|
self._attr_preset_modes = [PRESET_NONE]
|
||||||
|
if len(self._presets):
|
||||||
|
self._support_flags = SUPPORT_FLAGS | ClimateEntityFeature.PRESET_MODE
|
||||||
|
|
||||||
|
for key, _ in CONF_PRESETS.items():
|
||||||
|
if self.find_preset_temp(key) > 0:
|
||||||
|
self._attr_preset_modes.append(key)
|
||||||
|
|
||||||
|
_LOGGER.debug(
|
||||||
|
"After adding presets, preset_modes to %s", self._attr_preset_modes
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
_LOGGER.debug("No preset_modes")
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ from homeassistant.core import (
|
|||||||
HomeAssistant,
|
HomeAssistant,
|
||||||
callback,
|
callback,
|
||||||
Event,
|
Event,
|
||||||
CoreState,
|
# CoreState,
|
||||||
HomeAssistantError,
|
HomeAssistantError,
|
||||||
)
|
)
|
||||||
|
|
||||||
from homeassistant.const import STATE_ON, STATE_OFF, EVENT_HOMEASSISTANT_START
|
from homeassistant.const import STATE_ON, STATE_OFF # , EVENT_HOMEASSISTANT_START
|
||||||
|
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo, DeviceEntryType
|
from homeassistant.helpers.device_registry import DeviceInfo, DeviceEntryType
|
||||||
from homeassistant.helpers.event import async_track_state_change_event
|
from homeassistant.helpers.event import async_track_state_change_event
|
||||||
@@ -386,17 +386,18 @@ class CentralBoilerBinarySensor(BinarySensorEntity):
|
|||||||
api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(self._hass)
|
api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(self._hass)
|
||||||
api.register_central_boiler(self)
|
api.register_central_boiler(self)
|
||||||
|
|
||||||
@callback
|
# Should be not more needed and replaced by vtherm_api.init_vtherm_links
|
||||||
async def _async_startup_internal(*_):
|
# @callback
|
||||||
_LOGGER.debug("%s - Calling async_startup_internal", self)
|
# async def _async_startup_internal(*_):
|
||||||
await self.listen_nb_active_vtherm_entity()
|
# _LOGGER.debug("%s - Calling async_startup_internal", self)
|
||||||
|
# await self.listen_nb_active_vtherm_entity()
|
||||||
if self.hass.state == CoreState.running:
|
#
|
||||||
await _async_startup_internal()
|
# if self.hass.state == CoreState.running:
|
||||||
else:
|
# await _async_startup_internal()
|
||||||
self.hass.bus.async_listen_once(
|
# else:
|
||||||
EVENT_HOMEASSISTANT_START, _async_startup_internal
|
# self.hass.bus.async_listen_once(
|
||||||
)
|
# EVENT_HOMEASSISTANT_START, _async_startup_internal
|
||||||
|
# )
|
||||||
|
|
||||||
async def listen_nb_active_vtherm_entity(self):
|
async def listen_nb_active_vtherm_entity(self):
|
||||||
"""Initialize the listening of state change of VTherms"""
|
"""Initialize the listening of state change of VTherms"""
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ async def async_setup_entry(
|
|||||||
elif vt_type == CONF_THERMOSTAT_VALVE:
|
elif vt_type == CONF_THERMOSTAT_VALVE:
|
||||||
entity = ThermostatOverValve(hass, unique_id, name, entry.data)
|
entity = ThermostatOverValve(hass, unique_id, name, entry.data)
|
||||||
|
|
||||||
async_add_entities([entity, entity.get_temperature_number_entities(entry)], True)
|
async_add_entities([entity], True)
|
||||||
|
|
||||||
# Add services
|
# Add services
|
||||||
platform = entity_platform.async_get_current_platform()
|
platform = entity_platform.async_get_current_platform()
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from homeassistant.helpers.device_registry import DeviceInfo, DeviceEntryType
|
|||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.util import ensure_unique_string, slugify
|
||||||
|
|
||||||
from .vtherm_api import VersatileThermostatAPI
|
from .vtherm_api import VersatileThermostatAPI
|
||||||
from .commons import VersatileThermostatBaseEntity
|
from .commons import VersatileThermostatBaseEntity
|
||||||
@@ -48,6 +48,9 @@ from .const import (
|
|||||||
CONF_PRESETS_WITH_AC_VALUES,
|
CONF_PRESETS_WITH_AC_VALUES,
|
||||||
CONF_PRESETS_AWAY_VALUES,
|
CONF_PRESETS_AWAY_VALUES,
|
||||||
CONF_PRESETS_AWAY_WITH_AC_VALUES,
|
CONF_PRESETS_AWAY_WITH_AC_VALUES,
|
||||||
|
CONF_USE_PRESETS_CENTRAL_CONFIG,
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG,
|
||||||
|
CONF_USE_PRESENCE_FEATURE,
|
||||||
overrides,
|
overrides,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -84,28 +87,45 @@ async def async_setup_entry(
|
|||||||
unique_id = entry.entry_id
|
unique_id = entry.entry_id
|
||||||
name = entry.data.get(CONF_NAME)
|
name = entry.data.get(CONF_NAME)
|
||||||
vt_type = entry.data.get(CONF_THERMOSTAT_TYPE)
|
vt_type = entry.data.get(CONF_THERMOSTAT_TYPE)
|
||||||
is_central_boiler = entry.data.get(CONF_ADD_CENTRAL_BOILER_CONTROL)
|
# is_central_boiler = entry.data.get(CONF_ADD_CENTRAL_BOILER_CONTROL)
|
||||||
|
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
if vt_type != CONF_THERMOSTAT_CENTRAL_CONFIG:
|
if vt_type != CONF_THERMOSTAT_CENTRAL_CONFIG:
|
||||||
if not is_central_boiler:
|
# Creates non central temperature entities
|
||||||
pass
|
if not entry.data.get(CONF_USE_PRESETS_CENTRAL_CONFIG, False):
|
||||||
# for preset in CONF_PRESETS_VALUES:
|
for preset in CONF_PRESETS_VALUES:
|
||||||
# entities.append(
|
entities.append(
|
||||||
# TemperatureNumber(
|
TemperatureNumber(
|
||||||
# hass, unique_id, preset, preset, False, False, entry.data
|
hass, unique_id, name, preset, False, False, entry.data
|
||||||
# )
|
)
|
||||||
# )
|
)
|
||||||
|
if entry.data.get(CONF_AC_MODE, False):
|
||||||
|
for preset in CONF_PRESETS_WITH_AC_VALUES:
|
||||||
|
entities.append(
|
||||||
|
TemperatureNumber(
|
||||||
|
hass, unique_id, name, preset, True, False, entry.data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# TODO
|
if entry.data.get(
|
||||||
# if entry.data.get(CONF_AC_MODE, False):
|
CONF_USE_PRESENCE_FEATURE, False
|
||||||
# for preset in CONF_PRESETS_WITH_AC_VALUES:
|
) is True and not entry.data.get(CONF_USE_PRESENCE_CENTRAL_CONFIG, False):
|
||||||
# entities.append(
|
for preset in CONF_PRESETS_AWAY_VALUES:
|
||||||
# TemperatureNumber(
|
entities.append(
|
||||||
# hass, unique_id, preset, preset, True, False, entry.data
|
TemperatureNumber(
|
||||||
# )
|
hass, unique_id, name, preset, False, True, entry.data
|
||||||
# )
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if entry.data.get(CONF_AC_MODE, False):
|
||||||
|
for preset in CONF_PRESETS_AWAY_WITH_AC_VALUES:
|
||||||
|
entities.append(
|
||||||
|
TemperatureNumber(
|
||||||
|
hass, unique_id, name, preset, True, True, entry.data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# For central config only
|
||||||
else:
|
else:
|
||||||
entities.append(
|
entities.append(
|
||||||
ActivateBoilerThresholdNumber(hass, unique_id, name, entry.data)
|
ActivateBoilerThresholdNumber(hass, unique_id, name, entry.data)
|
||||||
@@ -113,27 +133,27 @@ async def async_setup_entry(
|
|||||||
for preset in CONF_PRESETS_VALUES:
|
for preset in CONF_PRESETS_VALUES:
|
||||||
entities.append(
|
entities.append(
|
||||||
CentralConfigTemperatureNumber(
|
CentralConfigTemperatureNumber(
|
||||||
hass, unique_id, preset, preset, False, False, entry.data
|
hass, unique_id, name, preset, False, False, entry.data
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
for preset in CONF_PRESETS_WITH_AC_VALUES:
|
for preset in CONF_PRESETS_WITH_AC_VALUES:
|
||||||
entities.append(
|
entities.append(
|
||||||
CentralConfigTemperatureNumber(
|
CentralConfigTemperatureNumber(
|
||||||
hass, unique_id, preset, preset, True, False, entry.data
|
hass, unique_id, name, preset, True, False, entry.data
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
for preset in CONF_PRESETS_AWAY_VALUES:
|
for preset in CONF_PRESETS_AWAY_VALUES:
|
||||||
entities.append(
|
entities.append(
|
||||||
CentralConfigTemperatureNumber(
|
CentralConfigTemperatureNumber(
|
||||||
hass, unique_id, preset, preset, False, True, entry.data
|
hass, unique_id, name, preset, False, True, entry.data
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
for preset in CONF_PRESETS_AWAY_WITH_AC_VALUES:
|
for preset in CONF_PRESETS_AWAY_WITH_AC_VALUES:
|
||||||
entities.append(
|
entities.append(
|
||||||
CentralConfigTemperatureNumber(
|
CentralConfigTemperatureNumber(
|
||||||
hass, unique_id, preset, preset, True, True, entry.data
|
hass, unique_id, name, preset, True, True, entry.data
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -211,7 +231,6 @@ class CentralConfigTemperatureNumber(NumberEntity, RestoreEntity):
|
|||||||
"""Representation of one temperature number"""
|
"""Representation of one temperature number"""
|
||||||
|
|
||||||
_attr_has_entity_name = True
|
_attr_has_entity_name = True
|
||||||
# _attr_translation_key = "temperature"
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -227,7 +246,7 @@ class CentralConfigTemperatureNumber(NumberEntity, RestoreEntity):
|
|||||||
the restoration will do the trick."""
|
the restoration will do the trick."""
|
||||||
|
|
||||||
self._config_id = unique_id
|
self._config_id = unique_id
|
||||||
self._device_name = entry_infos.get(CONF_NAME)
|
self._device_name = name
|
||||||
# self._attr_name = name
|
# self._attr_name = name
|
||||||
|
|
||||||
self._attr_translation_key = preset_name
|
self._attr_translation_key = preset_name
|
||||||
@@ -236,7 +255,8 @@ class CentralConfigTemperatureNumber(NumberEntity, RestoreEntity):
|
|||||||
# "ac": "-AC" if is_ac else "",
|
# "ac": "-AC" if is_ac else "",
|
||||||
# "away": "-AWAY" if is_away else "",
|
# "away": "-AWAY" if is_away else "",
|
||||||
# }
|
# }
|
||||||
self.entity_id = f"{NUMBER_DOMAIN}.central_configuration_{preset_name}"
|
# self.entity_id = f"{NUMBER_DOMAIN}.central_configuration_{preset_name}"
|
||||||
|
self.entity_id = f"{NUMBER_DOMAIN}.{slugify(name)}_{preset_name}"
|
||||||
self._attr_unique_id = f"central_configuration_{preset_name}"
|
self._attr_unique_id = f"central_configuration_{preset_name}"
|
||||||
self._attr_device_class = NumberDeviceClass.TEMPERATURE
|
self._attr_device_class = NumberDeviceClass.TEMPERATURE
|
||||||
self._attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
|
self._attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
|
||||||
@@ -250,7 +270,7 @@ class CentralConfigTemperatureNumber(NumberEntity, RestoreEntity):
|
|||||||
# previous value
|
# previous value
|
||||||
# TODO remove this after the next major release and just keep the init min/max
|
# TODO remove this after the next major release and just keep the init min/max
|
||||||
temp = None
|
temp = None
|
||||||
if temp := entry_infos.get(preset_name, None):
|
if (temp := entry_infos.get(preset_name, None)) is not None:
|
||||||
self._attr_value = self._attr_native_value = temp
|
self._attr_value = self._attr_native_value = temp
|
||||||
else:
|
else:
|
||||||
if entry_infos.get(CONF_AC_MODE) is True:
|
if entry_infos.get(CONF_AC_MODE) is True:
|
||||||
@@ -346,7 +366,6 @@ class TemperatureNumber( # pylint: disable=abstract-method
|
|||||||
"""Representation of one temperature number"""
|
"""Representation of one temperature number"""
|
||||||
|
|
||||||
_attr_has_entity_name = True
|
_attr_has_entity_name = True
|
||||||
_attr_translation_key = "temperature"
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -360,40 +379,41 @@ class TemperatureNumber( # pylint: disable=abstract-method
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the temperature with entry_infos if available. Else
|
"""Initialize the temperature with entry_infos if available. Else
|
||||||
the restoration will do the trick."""
|
the restoration will do the trick."""
|
||||||
super().__init__(hass, unique_id, entry_infos.get(CONF_NAME))
|
super().__init__(hass, unique_id, name)
|
||||||
|
|
||||||
split = name.split("_")
|
self._attr_translation_key = preset_name
|
||||||
# self._attr_name = split[0]
|
self.entity_id = f"{NUMBER_DOMAIN}.{slugify(name)}_{preset_name}"
|
||||||
# if "_" + split[1] == PRESET_AC_SUFFIX:
|
|
||||||
# self._attr_name = self._attr_name + " AC"
|
|
||||||
|
|
||||||
# self._attr_name = self._attr_name + " temperature"
|
# self._attr_translation_placeholders = {
|
||||||
|
# "preset": preset_name,
|
||||||
self._attr_translation_placeholders = {
|
# "ac": "-AC" if is_ac else "",
|
||||||
"preset": preset_name,
|
# "away": "-AWAY" if is_away else "",
|
||||||
"ac": "-AC" if is_ac else "",
|
# }
|
||||||
"away": "-AWAY" if is_away else "",
|
self._attr_unique_id = f"{self._device_name}_{preset_name}"
|
||||||
}
|
|
||||||
self._attr_unique_id = f"{self._device_name}_{name}"
|
|
||||||
self._attr_device_class = NumberDeviceClass.TEMPERATURE
|
self._attr_device_class = NumberDeviceClass.TEMPERATURE
|
||||||
self._attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
|
self._attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
|
||||||
|
|
||||||
|
self._attr_native_step = entry_infos.get(CONF_STEP_TEMPERATURE, 0.5)
|
||||||
|
self._attr_native_min_value = entry_infos.get(CONF_TEMP_MIN)
|
||||||
|
self._attr_native_max_value = entry_infos.get(CONF_TEMP_MAX)
|
||||||
|
|
||||||
# Initialize the values if included into the entry_infos. This will do
|
# Initialize the values if included into the entry_infos. This will do
|
||||||
# the temperature migration.
|
# the temperature migration.
|
||||||
# TODO see if this should be replace by the central config if any
|
# TODO see if this should be replace by the central config if any
|
||||||
temp = None
|
temp = None
|
||||||
if temp := entry_infos.get(preset_name, None):
|
if (temp := entry_infos.get(preset_name, None)) is not None:
|
||||||
self._attr_value = self._attr_native_value = temp
|
self._attr_value = self._attr_native_value = temp
|
||||||
|
else:
|
||||||
|
if entry_infos.get(CONF_AC_MODE) is True:
|
||||||
|
self._attr_native_value = self._attr_native_max_value
|
||||||
|
else:
|
||||||
|
self._attr_native_value = self._attr_native_min_value
|
||||||
|
|
||||||
self._attr_mode = NumberMode.BOX
|
self._attr_mode = NumberMode.BOX
|
||||||
self._preset_name = preset_name
|
self._preset_name = preset_name
|
||||||
self._is_away = is_away
|
self._is_away = is_away
|
||||||
self._is_ac = is_ac
|
self._is_ac = is_ac
|
||||||
|
|
||||||
self._attr_native_step = entry_infos.get(CONF_STEP_TEMPERATURE, 0.5)
|
|
||||||
self._attr_native_min_value = entry_infos.get(CONF_TEMP_MIN)
|
|
||||||
self._attr_native_max_value = entry_infos.get(CONF_TEMP_MAX)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon(self) -> str | None:
|
def icon(self) -> str | None:
|
||||||
return PRESET_ICON_MAPPING[self._preset_name]
|
return PRESET_ICON_MAPPING[self._preset_name]
|
||||||
@@ -402,12 +422,16 @@ class TemperatureNumber( # pylint: disable=abstract-method
|
|||||||
async def async_added_to_hass(self) -> None:
|
async def async_added_to_hass(self) -> None:
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
|
|
||||||
|
# register the temp entity for this device and preset
|
||||||
|
api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(self.hass)
|
||||||
|
api.register_temperature_number(self._config_id, self._preset_name, self)
|
||||||
|
|
||||||
old_state: CoreState = await self.async_get_last_state()
|
old_state: CoreState = await self.async_get_last_state()
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"%s - Calling async_added_to_hass old_state is %s", self, old_state
|
"%s - Calling async_added_to_hass old_state is %s", self, old_state
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
if old_state is not None and (value := float(old_state.state) > 0):
|
if old_state is not None and ((value := float(old_state.state)) > 0):
|
||||||
self._attr_value = self._attr_native_value = value
|
self._attr_value = self._attr_native_value = value
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
@@ -425,12 +449,6 @@ class TemperatureNumber( # pylint: disable=abstract-method
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# @overrides
|
|
||||||
# @property
|
|
||||||
# def native_step(self) -> float | None:
|
|
||||||
# """The native step"""
|
|
||||||
# return self.my_climate.target_temperature_step
|
|
||||||
|
|
||||||
@overrides
|
@overrides
|
||||||
async def async_set_native_value(self, value: float) -> None:
|
async def async_set_native_value(self, value: float) -> None:
|
||||||
"""Change the value"""
|
"""Change the value"""
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from homeassistant.config_entries import ConfigEntry
|
|||||||
|
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
from homeassistant.components.climate import ClimateEntity, DOMAIN as CLIMATE_DOMAIN
|
from homeassistant.components.climate import ClimateEntity, DOMAIN as CLIMATE_DOMAIN
|
||||||
from homeassistant.components.number import NumberEntity, DOMAIN as NUMBER_DOMAIN
|
from homeassistant.components.number import NumberEntity
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
|||||||
+6
-1
@@ -500,7 +500,12 @@ async def create_thermostat(
|
|||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
assert entry.state is ConfigEntryState.LOADED
|
assert entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
return search_entity(hass, entity_id, CLIMATE_DOMAIN)
|
# We should reload the VTherm links
|
||||||
|
vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api()
|
||||||
|
entity = search_entity(hass, entity_id, CLIMATE_DOMAIN)
|
||||||
|
if entity:
|
||||||
|
await entity.init_presets(vtherm_api.find_central_configuration())
|
||||||
|
return entity
|
||||||
|
|
||||||
|
|
||||||
async def create_central_config( # pylint: disable=dangerous-default-value
|
async def create_central_config( # pylint: disable=dangerous-default-value
|
||||||
|
|||||||
+363
-1
@@ -14,7 +14,10 @@ from homeassistant.components.number import NumberEntity, DOMAIN as NUMBER_DOMAI
|
|||||||
|
|
||||||
from pytest_homeassistant_custom_component.common import MockConfigEntry
|
from pytest_homeassistant_custom_component.common import MockConfigEntry
|
||||||
|
|
||||||
# from custom_components.versatile_thermostat.base_thermostat import BaseThermostat
|
from custom_components.versatile_thermostat.base_thermostat import BaseThermostat
|
||||||
|
from custom_components.versatile_thermostat.thermostat_switch import (
|
||||||
|
ThermostatOverSwitch,
|
||||||
|
)
|
||||||
from custom_components.versatile_thermostat.vtherm_api import VersatileThermostatAPI
|
from custom_components.versatile_thermostat.vtherm_api import VersatileThermostatAPI
|
||||||
|
|
||||||
from .commons import *
|
from .commons import *
|
||||||
@@ -394,3 +397,362 @@ async def test_add_number_for_central_config_without_temp_restore(
|
|||||||
config_id=central_config_entry.entry_id, preset_name=preset_name
|
config_id=central_config_entry.entry_id, preset_name=preset_name
|
||||||
)
|
)
|
||||||
assert val == value
|
assert val == value
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||||
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
||||||
|
async def test_add_number_for_over_switch_use_central(
|
||||||
|
hass: HomeAssistant, skip_hass_states_is_state
|
||||||
|
):
|
||||||
|
"""Test the construction of a over switch vtherm with
|
||||||
|
use central config for PRESET and PRESENCE.
|
||||||
|
It also have old temp config value which should be not used.
|
||||||
|
So it should have no Temp NumberEntity"""
|
||||||
|
|
||||||
|
vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(hass)
|
||||||
|
|
||||||
|
temps = {
|
||||||
|
"frost_temp": 10,
|
||||||
|
"eco_temp": 17.1,
|
||||||
|
"comfort_temp": 18.1,
|
||||||
|
"boost_temp": 19.1,
|
||||||
|
"eco_ac_temp": 25.1,
|
||||||
|
"comfort_ac_temp": 23.1,
|
||||||
|
"boost_ac_temp": 21.1,
|
||||||
|
"frost_away_temp": 15.1,
|
||||||
|
"eco_away_temp": 15.2,
|
||||||
|
"comfort_away_temp": 15.3,
|
||||||
|
"boost_away_temp": 15.4,
|
||||||
|
"eco_ac_away_temp": 30.5,
|
||||||
|
"comfort_ac_away_temp": 30.6,
|
||||||
|
"boost_ac_away_temp": 30.7,
|
||||||
|
}
|
||||||
|
|
||||||
|
vtherm_entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
title="TheCentralConfigMockName",
|
||||||
|
unique_id="centralConfigUniqueId",
|
||||||
|
data={
|
||||||
|
CONF_NAME: "TheOverSwitchVTherm",
|
||||||
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
||||||
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
||||||
|
CONF_TEMP_MIN: 15,
|
||||||
|
CONF_TEMP_MAX: 30,
|
||||||
|
CONF_AC_MODE: False,
|
||||||
|
CONF_TPI_COEF_INT: 0.5,
|
||||||
|
CONF_TPI_COEF_EXT: 0.02,
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_PRESETS_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
||||||
|
}
|
||||||
|
| temps,
|
||||||
|
)
|
||||||
|
|
||||||
|
# The restore should not be used
|
||||||
|
with patch(
|
||||||
|
"homeassistant.helpers.restore_state.RestoreEntity.async_get_last_state",
|
||||||
|
return_value=State(entity_id="number.mock_valve", state="23"),
|
||||||
|
) as mock_restore_state:
|
||||||
|
vtherm_entry.add_to_hass(hass)
|
||||||
|
await hass.config_entries.async_setup(vtherm_entry.entry_id)
|
||||||
|
|
||||||
|
assert mock_restore_state.call_count == 0
|
||||||
|
|
||||||
|
assert vtherm_entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
|
# We search for NumberEntities
|
||||||
|
for preset_name, value in temps.items():
|
||||||
|
temp_entity = search_entity(
|
||||||
|
hass,
|
||||||
|
"number.central_configuration_" + preset_name,
|
||||||
|
NUMBER_DOMAIN,
|
||||||
|
)
|
||||||
|
assert temp_entity is None
|
||||||
|
|
||||||
|
# Find temp Number into vtherm_api
|
||||||
|
val = vtherm_api.get_temperature_number_value(
|
||||||
|
config_id=vtherm_entry.entry_id, preset_name=preset_name
|
||||||
|
)
|
||||||
|
assert val is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
||||||
|
async def test_add_number_for_over_switch_use_central_presence(
|
||||||
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
||||||
|
):
|
||||||
|
"""Test the construction of a over switch vtherm with
|
||||||
|
use central config for PRESET and PRESENCE.
|
||||||
|
It also have old temp config value which should be not used.
|
||||||
|
So it should have no Temp NumberEntity"""
|
||||||
|
|
||||||
|
vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(hass)
|
||||||
|
|
||||||
|
temps = {
|
||||||
|
"frost_temp": 10,
|
||||||
|
"eco_temp": 17.1,
|
||||||
|
"comfort_temp": 18.1,
|
||||||
|
"boost_temp": 19.1,
|
||||||
|
"eco_ac_temp": 25.1,
|
||||||
|
"comfort_ac_temp": 23.1,
|
||||||
|
"boost_ac_temp": 21.1,
|
||||||
|
}
|
||||||
|
temps_missing = {
|
||||||
|
"frost_away_temp": 15.1,
|
||||||
|
"eco_away_temp": 15.2,
|
||||||
|
"comfort_away_temp": 15.3,
|
||||||
|
"boost_away_temp": 15.4,
|
||||||
|
"eco_ac_away_temp": 30.5,
|
||||||
|
"comfort_ac_away_temp": 30.6,
|
||||||
|
"boost_ac_away_temp": 30.7,
|
||||||
|
}
|
||||||
|
|
||||||
|
vtherm_entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
title="TheCentralConfigMockName",
|
||||||
|
unique_id="centralConfigUniqueId",
|
||||||
|
data={
|
||||||
|
CONF_NAME: "TheOverSwitchVTherm",
|
||||||
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
||||||
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
||||||
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
||||||
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
||||||
|
CONF_TEMP_MIN: 15,
|
||||||
|
CONF_TEMP_MAX: 30,
|
||||||
|
CONF_AC_MODE: True,
|
||||||
|
CONF_TPI_COEF_INT: 0.5,
|
||||||
|
CONF_TPI_COEF_EXT: 0.02,
|
||||||
|
CONF_CYCLE_MIN: 5,
|
||||||
|
CONF_HEATER: "switch.mock_switch1",
|
||||||
|
CONF_USE_PRESENCE_FEATURE: True,
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_PRESETS_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
||||||
|
}
|
||||||
|
| temps
|
||||||
|
| temps_missing,
|
||||||
|
)
|
||||||
|
|
||||||
|
vtherm: BaseThermostat = await create_thermostat(
|
||||||
|
hass, vtherm_entry, "climate.theoverswitchvtherm"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1. We search for NumberEntities
|
||||||
|
for preset_name, value in temps.items():
|
||||||
|
temp_entity = search_entity(
|
||||||
|
hass,
|
||||||
|
"number.theoverswitchvtherm_" + preset_name,
|
||||||
|
NUMBER_DOMAIN,
|
||||||
|
)
|
||||||
|
assert temp_entity
|
||||||
|
assert temp_entity.state == value
|
||||||
|
|
||||||
|
# This test is dependent to translation en.json. If translations change
|
||||||
|
# this may fails
|
||||||
|
assert (
|
||||||
|
temp_entity.name.lower()
|
||||||
|
== preset_name.replace("_temp", "")
|
||||||
|
.replace("_ac", " ac")
|
||||||
|
.replace("_away", " away")
|
||||||
|
.lower()
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find temp Number into vtherm_api
|
||||||
|
val = vtherm_api.get_temperature_number_value(
|
||||||
|
config_id=vtherm_entry.entry_id, preset_name=preset_name
|
||||||
|
)
|
||||||
|
assert val == value
|
||||||
|
|
||||||
|
# 2. We search for NumberEntities to be missing
|
||||||
|
for preset_name, value in temps_missing.items():
|
||||||
|
temp_entity = search_entity(
|
||||||
|
hass,
|
||||||
|
"number.theoverswitchvtherm_" + preset_name,
|
||||||
|
NUMBER_DOMAIN,
|
||||||
|
)
|
||||||
|
assert temp_entity is None
|
||||||
|
|
||||||
|
# Find temp Number into vtherm_api
|
||||||
|
val = vtherm_api.get_temperature_number_value(
|
||||||
|
config_id=vtherm_entry.entry_id, preset_name=preset_name
|
||||||
|
)
|
||||||
|
assert val is None
|
||||||
|
|
||||||
|
# 3. The VTherm should be initialized with all presets and correct temperature
|
||||||
|
assert vtherm
|
||||||
|
assert isinstance(vtherm, ThermostatOverSwitch)
|
||||||
|
assert vtherm.preset_modes == [
|
||||||
|
PRESET_NONE,
|
||||||
|
PRESET_FROST_PROTECTION,
|
||||||
|
PRESET_ECO,
|
||||||
|
PRESET_COMFORT,
|
||||||
|
PRESET_BOOST,
|
||||||
|
]
|
||||||
|
|
||||||
|
assert vtherm._presets == {
|
||||||
|
PRESET_FROST_PROTECTION: temps["frost_temp"],
|
||||||
|
PRESET_ECO: temps["eco_temp"],
|
||||||
|
PRESET_COMFORT: temps["comfort_temp"],
|
||||||
|
PRESET_BOOST: temps["boost_temp"],
|
||||||
|
PRESET_ECO_AC: temps["eco_ac_temp"],
|
||||||
|
PRESET_COMFORT_AC: temps["comfort_ac_temp"],
|
||||||
|
PRESET_BOOST_AC: temps["boost_ac_temp"],
|
||||||
|
}
|
||||||
|
|
||||||
|
# Preset away should be initialized with the central config
|
||||||
|
assert vtherm._presets_away == {
|
||||||
|
PRESET_FROST_PROTECTION
|
||||||
|
+ PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["frost_away_temp"],
|
||||||
|
PRESET_ECO + PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["eco_away_temp"],
|
||||||
|
PRESET_COMFORT + PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["comfort_away_temp"],
|
||||||
|
PRESET_BOOST + PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["boost_away_temp"],
|
||||||
|
PRESET_ECO_AC + PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["eco_ac_away_temp"],
|
||||||
|
PRESET_COMFORT_AC
|
||||||
|
+ PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["comfort_ac_away_temp"],
|
||||||
|
PRESET_BOOST_AC + PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["boost_ac_away_temp"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
||||||
|
async def test_add_number_for_over_switch_use_central_presets_and_restore(
|
||||||
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
||||||
|
):
|
||||||
|
"""Test the construction of a over switch vtherm with
|
||||||
|
use central config for PRESET and PRESENCE.
|
||||||
|
It also have old temp config value which should be not used.
|
||||||
|
So it should have no Temp NumberEntity"""
|
||||||
|
|
||||||
|
vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(hass)
|
||||||
|
|
||||||
|
temps = {
|
||||||
|
"frost_away_temp": 23,
|
||||||
|
"eco_away_temp": 23,
|
||||||
|
"comfort_away_temp": 23,
|
||||||
|
"boost_away_temp": 23,
|
||||||
|
}
|
||||||
|
temps_missing = {
|
||||||
|
"frost_temp": 10,
|
||||||
|
"eco_temp": 17.1,
|
||||||
|
"comfort_temp": 18.1,
|
||||||
|
"boost_temp": 19.1,
|
||||||
|
"eco_ac_temp": 25.1,
|
||||||
|
"comfort_ac_temp": 23.1,
|
||||||
|
"boost_ac_temp": 21.1,
|
||||||
|
"eco_ac_away_temp": 30.5,
|
||||||
|
"comfort_ac_away_temp": 30.6,
|
||||||
|
"boost_ac_away_temp": 30.7,
|
||||||
|
}
|
||||||
|
|
||||||
|
vtherm_entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
title="TheCentralConfigMockName",
|
||||||
|
unique_id="centralConfigUniqueId",
|
||||||
|
data={
|
||||||
|
CONF_NAME: "TheOverSwitchVTherm",
|
||||||
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
||||||
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
||||||
|
CONF_TEMP_MIN: 15,
|
||||||
|
CONF_TEMP_MAX: 30,
|
||||||
|
CONF_AC_MODE: False,
|
||||||
|
CONF_TPI_COEF_INT: 0.5,
|
||||||
|
CONF_TPI_COEF_EXT: 0.02,
|
||||||
|
CONF_CYCLE_MIN: 5,
|
||||||
|
CONF_HEATER: "switch.mock_switch1",
|
||||||
|
CONF_USE_PRESENCE_FEATURE: True,
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_PRESETS_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
||||||
|
}
|
||||||
|
| temps
|
||||||
|
| temps_missing,
|
||||||
|
)
|
||||||
|
|
||||||
|
# The restore should not be used
|
||||||
|
with patch(
|
||||||
|
"homeassistant.helpers.restore_state.RestoreEntity.async_get_last_state",
|
||||||
|
return_value=State(entity_id="number.mock_valve", state="23"),
|
||||||
|
) as mock_restore_state:
|
||||||
|
vtherm: BaseThermostat = await create_thermostat(
|
||||||
|
hass, vtherm_entry, "climate.theoverswitchvtherm"
|
||||||
|
)
|
||||||
|
|
||||||
|
# We should try to restore all 4 temp entities
|
||||||
|
assert mock_restore_state.call_count == 4
|
||||||
|
|
||||||
|
# 1. We search for NumberEntities
|
||||||
|
for preset_name, value in temps.items():
|
||||||
|
temp_entity = search_entity(
|
||||||
|
hass,
|
||||||
|
"number.theoverswitchvtherm_" + preset_name,
|
||||||
|
NUMBER_DOMAIN,
|
||||||
|
)
|
||||||
|
assert temp_entity
|
||||||
|
assert temp_entity.state == value
|
||||||
|
|
||||||
|
# This test is dependent to translation en.json. If translations change
|
||||||
|
# this may fails
|
||||||
|
assert (
|
||||||
|
temp_entity.name.lower()
|
||||||
|
== preset_name.replace("_temp", "")
|
||||||
|
.replace("_ac", " ac")
|
||||||
|
.replace("_away", " away")
|
||||||
|
.lower()
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find temp Number into vtherm_api
|
||||||
|
val = vtherm_api.get_temperature_number_value(
|
||||||
|
config_id=vtherm_entry.entry_id, preset_name=preset_name
|
||||||
|
)
|
||||||
|
assert val == value
|
||||||
|
|
||||||
|
# 2. We search for NumberEntities to be missing
|
||||||
|
for preset_name, value in temps_missing.items():
|
||||||
|
temp_entity = search_entity(
|
||||||
|
hass,
|
||||||
|
"number.theoverswitchvtherm_" + preset_name,
|
||||||
|
NUMBER_DOMAIN,
|
||||||
|
)
|
||||||
|
assert temp_entity is None
|
||||||
|
|
||||||
|
# Find temp Number into vtherm_api
|
||||||
|
val = vtherm_api.get_temperature_number_value(
|
||||||
|
config_id=vtherm_entry.entry_id, preset_name=preset_name
|
||||||
|
)
|
||||||
|
assert val is None
|
||||||
|
|
||||||
|
# 3. The VTherm should be initialized with all presets and correct temperature
|
||||||
|
assert vtherm
|
||||||
|
assert isinstance(vtherm, ThermostatOverSwitch)
|
||||||
|
assert vtherm.preset_modes == [
|
||||||
|
PRESET_NONE,
|
||||||
|
PRESET_FROST_PROTECTION,
|
||||||
|
PRESET_ECO,
|
||||||
|
# PRESET_COMFORT, because temp is 0
|
||||||
|
PRESET_BOOST,
|
||||||
|
]
|
||||||
|
|
||||||
|
# Preset away should be empty cause we use central config for presets
|
||||||
|
assert vtherm._presets == {
|
||||||
|
PRESET_FROST_PROTECTION: FULL_CENTRAL_CONFIG["frost_temp"],
|
||||||
|
PRESET_ECO: FULL_CENTRAL_CONFIG["eco_temp"],
|
||||||
|
PRESET_COMFORT: FULL_CENTRAL_CONFIG["comfort_temp"],
|
||||||
|
PRESET_BOOST: FULL_CENTRAL_CONFIG["boost_temp"],
|
||||||
|
}
|
||||||
|
|
||||||
|
assert vtherm._presets_away == {
|
||||||
|
PRESET_FROST_PROTECTION + PRESET_AWAY_SUFFIX: temps["frost_away_temp"],
|
||||||
|
PRESET_ECO + PRESET_AWAY_SUFFIX: temps["eco_away_temp"],
|
||||||
|
PRESET_COMFORT + PRESET_AWAY_SUFFIX: temps["comfort_away_temp"],
|
||||||
|
PRESET_BOOST + PRESET_AWAY_SUFFIX: temps["boost_away_temp"],
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user