1 """Number for ViCare."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from contextlib
import suppress
7 from dataclasses
import dataclass
11 from PyViCare.PyViCareDevice
import Device
as PyViCareDevice
12 from PyViCare.PyViCareDeviceConfig
import PyViCareDeviceConfig
13 from PyViCare.PyViCareHeatingDevice
import (
14 HeatingDeviceWithComponent
as PyViCareHeatingDeviceComponent,
16 from PyViCare.PyViCareUtils
import (
17 PyViCareInvalidDataError,
18 PyViCareNotSupportedFeatureError,
19 PyViCareRateLimitError,
21 from requests.exceptions
import ConnectionError
as RequestConnectionError
26 NumberEntityDescription,
33 from .const
import DEVICE_LIST, DOMAIN
34 from .entity
import ViCareEntity
35 from .types
import HeatingProgram, ViCareDevice, ViCareRequiredKeysMixin
36 from .utils
import get_circuits, get_device_serial, is_supported
38 _LOGGER = logging.getLogger(__name__)
41 @dataclass(frozen=True)
43 """Describes ViCare number entity."""
45 value_getter: Callable[[PyViCareDevice], float]
46 value_setter: Callable[[PyViCareDevice, float], Any] |
None =
None
47 min_value_getter: Callable[[PyViCareDevice], float |
None] |
None =
None
48 max_value_getter: Callable[[PyViCareDevice], float |
None] |
None =
None
49 stepping_getter: Callable[[PyViCareDevice], float |
None] |
None =
None
52 DEVICE_ENTITY_DESCRIPTIONS: tuple[ViCareNumberEntityDescription, ...] = (
54 key=
"dhw_temperature",
55 translation_key=
"dhw_temperature",
56 entity_category=EntityCategory.CONFIG,
57 device_class=NumberDeviceClass.TEMPERATURE,
58 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
59 value_getter=
lambda api: api.getDomesticHotWaterConfiguredTemperature(),
60 value_setter=
lambda api, value: api.setDomesticHotWaterTemperature(value),
61 min_value_getter=
lambda api: api.getDomesticHotWaterMinTemperature(),
62 max_value_getter=
lambda api: api.getDomesticHotWaterMaxTemperature(),
66 key=
"dhw_secondary_temperature",
67 translation_key=
"dhw_secondary_temperature",
68 entity_category=EntityCategory.CONFIG,
69 device_class=NumberDeviceClass.TEMPERATURE,
70 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
71 value_getter=
lambda api: api.getDomesticHotWaterConfiguredTemperature2(),
72 value_setter=
lambda api, value: api.setDomesticHotWaterTemperature2(value),
79 key=
"dhw_hysteresis_switch_on",
80 translation_key=
"dhw_hysteresis_switch_on",
81 entity_category=EntityCategory.CONFIG,
82 device_class=NumberDeviceClass.TEMPERATURE,
83 native_unit_of_measurement=UnitOfTemperature.KELVIN,
84 value_getter=
lambda api: api.getDomesticHotWaterHysteresisSwitchOn(),
85 value_setter=
lambda api, value: api.setDomesticHotWaterHysteresisSwitchOn(
88 min_value_getter=
lambda api: api.getDomesticHotWaterHysteresisSwitchOnMin(),
89 max_value_getter=
lambda api: api.getDomesticHotWaterHysteresisSwitchOnMax(),
90 stepping_getter=
lambda api: api.getDomesticHotWaterHysteresisSwitchOnStepping(),
93 key=
"dhw_hysteresis_switch_off",
94 translation_key=
"dhw_hysteresis_switch_off",
95 entity_category=EntityCategory.CONFIG,
96 device_class=NumberDeviceClass.TEMPERATURE,
97 native_unit_of_measurement=UnitOfTemperature.KELVIN,
98 value_getter=
lambda api: api.getDomesticHotWaterHysteresisSwitchOff(),
99 value_setter=
lambda api, value: api.setDomesticHotWaterHysteresisSwitchOff(
102 min_value_getter=
lambda api: api.getDomesticHotWaterHysteresisSwitchOffMin(),
103 max_value_getter=
lambda api: api.getDomesticHotWaterHysteresisSwitchOffMax(),
104 stepping_getter=
lambda api: api.getDomesticHotWaterHysteresisSwitchOffStepping(),
109 CIRCUIT_ENTITY_DESCRIPTIONS: tuple[ViCareNumberEntityDescription, ...] = (
111 key=
"heating curve shift",
112 translation_key=
"heating_curve_shift",
113 entity_category=EntityCategory.CONFIG,
114 device_class=NumberDeviceClass.TEMPERATURE,
115 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
116 value_getter=
lambda api: api.getHeatingCurveShift(),
117 value_setter=
lambda api, shift: (
118 api.setHeatingCurve(shift, api.getHeatingCurveSlope())
120 min_value_getter=
lambda api: api.getHeatingCurveShiftMin(),
121 max_value_getter=
lambda api: api.getHeatingCurveShiftMax(),
122 stepping_getter=
lambda api: api.getHeatingCurveShiftStepping(),
123 native_min_value=-13,
128 key=
"heating curve slope",
129 translation_key=
"heating_curve_slope",
130 entity_category=EntityCategory.CONFIG,
131 value_getter=
lambda api: api.getHeatingCurveSlope(),
132 value_setter=
lambda api, slope: (
133 api.setHeatingCurve(api.getHeatingCurveShift(), slope)
135 min_value_getter=
lambda api: api.getHeatingCurveSlopeMin(),
136 max_value_getter=
lambda api: api.getHeatingCurveSlopeMax(),
137 stepping_getter=
lambda api: api.getHeatingCurveSlopeStepping(),
138 native_min_value=0.2,
139 native_max_value=3.5,
143 key=
"normal_temperature",
144 translation_key=
"normal_temperature",
145 entity_category=EntityCategory.CONFIG,
146 device_class=NumberDeviceClass.TEMPERATURE,
147 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
148 value_getter=
lambda api: api.getDesiredTemperatureForProgram(
149 HeatingProgram.NORMAL
151 value_setter=
lambda api, value: api.setProgramTemperature(
152 HeatingProgram.NORMAL, value
154 min_value_getter=
lambda api: api.getProgramMinTemperature(
155 HeatingProgram.NORMAL
157 max_value_getter=
lambda api: api.getProgramMaxTemperature(
158 HeatingProgram.NORMAL
160 stepping_getter=
lambda api: api.getProgramStepping(HeatingProgram.NORMAL),
163 key=
"reduced_temperature",
164 translation_key=
"reduced_temperature",
165 entity_category=EntityCategory.CONFIG,
166 device_class=NumberDeviceClass.TEMPERATURE,
167 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
168 value_getter=
lambda api: api.getDesiredTemperatureForProgram(
169 HeatingProgram.REDUCED
171 value_setter=
lambda api, value: api.setProgramTemperature(
172 HeatingProgram.REDUCED, value
174 min_value_getter=
lambda api: api.getProgramMinTemperature(
175 HeatingProgram.REDUCED
177 max_value_getter=
lambda api: api.getProgramMaxTemperature(
178 HeatingProgram.REDUCED
180 stepping_getter=
lambda api: api.getProgramStepping(HeatingProgram.REDUCED),
183 key=
"comfort_temperature",
184 translation_key=
"comfort_temperature",
185 entity_category=EntityCategory.CONFIG,
186 device_class=NumberDeviceClass.TEMPERATURE,
187 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
188 value_getter=
lambda api: api.getDesiredTemperatureForProgram(
189 HeatingProgram.COMFORT
191 value_setter=
lambda api, value: api.setProgramTemperature(
192 HeatingProgram.COMFORT, value
194 min_value_getter=
lambda api: api.getProgramMinTemperature(
195 HeatingProgram.COMFORT
197 max_value_getter=
lambda api: api.getProgramMaxTemperature(
198 HeatingProgram.COMFORT
200 stepping_getter=
lambda api: api.getProgramStepping(HeatingProgram.COMFORT),
203 key=
"normal_heating_temperature",
204 translation_key=
"normal_heating_temperature",
205 entity_category=EntityCategory.CONFIG,
206 device_class=NumberDeviceClass.TEMPERATURE,
207 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
208 value_getter=
lambda api: api.getDesiredTemperatureForProgram(
209 HeatingProgram.NORMAL_HEATING
211 value_setter=
lambda api, value: api.setProgramTemperature(
212 HeatingProgram.NORMAL_HEATING, value
214 min_value_getter=
lambda api: api.getProgramMinTemperature(
215 HeatingProgram.NORMAL_HEATING
217 max_value_getter=
lambda api: api.getProgramMaxTemperature(
218 HeatingProgram.NORMAL_HEATING
220 stepping_getter=
lambda api: api.getProgramStepping(
221 HeatingProgram.NORMAL_HEATING
225 key=
"reduced_heating_temperature",
226 translation_key=
"reduced_heating_temperature",
227 entity_category=EntityCategory.CONFIG,
228 device_class=NumberDeviceClass.TEMPERATURE,
229 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
230 value_getter=
lambda api: api.getDesiredTemperatureForProgram(
231 HeatingProgram.REDUCED_HEATING
233 value_setter=
lambda api, value: api.setProgramTemperature(
234 HeatingProgram.REDUCED_HEATING, value
236 min_value_getter=
lambda api: api.getProgramMinTemperature(
237 HeatingProgram.REDUCED_HEATING
239 max_value_getter=
lambda api: api.getProgramMaxTemperature(
240 HeatingProgram.REDUCED_HEATING
242 stepping_getter=
lambda api: api.getProgramStepping(
243 HeatingProgram.REDUCED_HEATING
247 key=
"comfort_heating_temperature",
248 translation_key=
"comfort_heating_temperature",
249 entity_category=EntityCategory.CONFIG,
250 device_class=NumberDeviceClass.TEMPERATURE,
251 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
252 value_getter=
lambda api: api.getDesiredTemperatureForProgram(
253 HeatingProgram.COMFORT_HEATING
255 value_setter=
lambda api, value: api.setProgramTemperature(
256 HeatingProgram.COMFORT_HEATING, value
258 min_value_getter=
lambda api: api.getProgramMinTemperature(
259 HeatingProgram.COMFORT_HEATING
261 max_value_getter=
lambda api: api.getProgramMaxTemperature(
262 HeatingProgram.COMFORT_HEATING
264 stepping_getter=
lambda api: api.getProgramStepping(
265 HeatingProgram.COMFORT_HEATING
269 key=
"normal_cooling_temperature",
270 translation_key=
"normal_cooling_temperature",
271 entity_category=EntityCategory.CONFIG,
272 device_class=NumberDeviceClass.TEMPERATURE,
273 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
274 value_getter=
lambda api: api.getDesiredTemperatureForProgram(
275 HeatingProgram.NORMAL_COOLING
277 value_setter=
lambda api, value: api.setProgramTemperature(
278 HeatingProgram.NORMAL_COOLING, value
280 min_value_getter=
lambda api: api.getProgramMinTemperature(
281 HeatingProgram.NORMAL_COOLING
283 max_value_getter=
lambda api: api.getProgramMaxTemperature(
284 HeatingProgram.NORMAL_COOLING
286 stepping_getter=
lambda api: api.getProgramStepping(
287 HeatingProgram.NORMAL_COOLING
291 key=
"reduced_cooling_temperature",
292 translation_key=
"reduced_cooling_temperature",
293 entity_category=EntityCategory.CONFIG,
294 device_class=NumberDeviceClass.TEMPERATURE,
295 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
296 value_getter=
lambda api: api.getDesiredTemperatureForProgram(
297 HeatingProgram.REDUCED_COOLING
299 value_setter=
lambda api, value: api.setProgramTemperature(
300 HeatingProgram.REDUCED_COOLING, value
302 min_value_getter=
lambda api: api.getProgramMinTemperature(
303 HeatingProgram.REDUCED_COOLING
305 max_value_getter=
lambda api: api.getProgramMaxTemperature(
306 HeatingProgram.REDUCED_COOLING
308 stepping_getter=
lambda api: api.getProgramStepping(
309 HeatingProgram.REDUCED_COOLING
313 key=
"comfort_cooling_temperature",
314 translation_key=
"comfort_cooling_temperature",
315 entity_category=EntityCategory.CONFIG,
316 device_class=NumberDeviceClass.TEMPERATURE,
317 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
318 value_getter=
lambda api: api.getDesiredTemperatureForProgram(
319 HeatingProgram.COMFORT_COOLING
321 value_setter=
lambda api, value: api.setProgramTemperature(
322 HeatingProgram.COMFORT_COOLING, value
324 min_value_getter=
lambda api: api.getProgramMinTemperature(
325 HeatingProgram.COMFORT_COOLING
327 max_value_getter=
lambda api: api.getProgramMaxTemperature(
328 HeatingProgram.COMFORT_COOLING
330 stepping_getter=
lambda api: api.getProgramStepping(
331 HeatingProgram.COMFORT_COOLING
338 device_list: list[ViCareDevice],
339 ) -> list[ViCareNumber]:
340 """Create ViCare number entities for a device."""
342 entities: list[ViCareNumber] = []
343 for device
in device_list:
352 for description
in DEVICE_ENTITY_DESCRIPTIONS
353 if is_supported(description.key, description, device.api)
365 for description
in CIRCUIT_ENTITY_DESCRIPTIONS
373 config_entry: ConfigEntry,
374 async_add_entities: AddEntitiesCallback,
376 """Create the ViCare number devices."""
377 device_list = hass.data[DOMAIN][config_entry.entry_id][DEVICE_LIST]
380 await hass.async_add_executor_job(
388 """Representation of a ViCare number."""
390 entity_description: ViCareNumberEntityDescription
394 description: ViCareNumberEntityDescription,
395 device_serial: str |
None,
396 device_config: PyViCareDeviceConfig,
397 device: PyViCareDevice,
398 component: PyViCareHeatingDeviceComponent |
None =
None,
400 """Initialize the number."""
402 description.key, device_serial, device_config, device, component
408 """Return True if entity is available."""
418 """Update state of number."""
420 with suppress(PyViCareNotSupportedFeatureError):
439 except RequestConnectionError:
440 _LOGGER.error(
"Unable to retrieve data from ViCare server")
442 _LOGGER.error(
"Unable to decode data from ViCare server")
443 except PyViCareRateLimitError
as limit_exception:
444 _LOGGER.error(
"Vicare API rate limit exceeded: %s", limit_exception)
445 except PyViCareInvalidDataError
as invalid_data_exception:
446 _LOGGER.error(
"Invalid data from Vicare server: %s", invalid_data_exception)
450 fn: Callable[[PyViCareDevice], float |
None] |
None,
451 api: PyViCareHeatingDeviceComponent,
453 return None if fn
is None else fn(api)
None set_native_value(self, float value)
None __init__(self, ViCareNumberEntityDescription description, str|None device_serial, PyViCareDeviceConfig device_config, PyViCareDevice device, PyViCareHeatingDeviceComponent|None component=None)
None schedule_update_ha_state(self, bool force_refresh=False)
float|None _get_value(Callable[[PyViCareDevice], float|None]|None fn, PyViCareHeatingDeviceComponent api)
list[ViCareNumber] _build_entities(list[ViCareDevice] device_list)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
str|None get_device_serial(PyViCareDevice device)
bool is_supported(str name, ViCareRequiredKeysMixin entity_description, vicare_device)
list[PyViCareHeatingDeviceComponent] get_circuits(PyViCareDevice device)