Home Assistant Unofficial Reference 2024.12.1
water_heater.py
Go to the documentation of this file.
1 """Viessmann ViCare water_heater device."""
2 
3 from __future__ import annotations
4 
5 from contextlib import suppress
6 import logging
7 from typing import Any
8 
9 from PyViCare.PyViCareDevice import Device as PyViCareDevice
10 from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig
11 from PyViCare.PyViCareHeatingDevice import HeatingCircuit as PyViCareHeatingCircuit
12 from PyViCare.PyViCareUtils import (
13  PyViCareInvalidDataError,
14  PyViCareNotSupportedFeatureError,
15  PyViCareRateLimitError,
16 )
17 import requests
18 
20  WaterHeaterEntity,
21  WaterHeaterEntityFeature,
22 )
23 from homeassistant.config_entries import ConfigEntry
24 from homeassistant.const import ATTR_TEMPERATURE, PRECISION_TENTHS, UnitOfTemperature
25 from homeassistant.core import HomeAssistant
26 from homeassistant.helpers.entity_platform import AddEntitiesCallback
27 
28 from .const import DEVICE_LIST, DOMAIN
29 from .entity import ViCareEntity
30 from .types import ViCareDevice
31 from .utils import get_circuits, get_device_serial
32 
33 _LOGGER = logging.getLogger(__name__)
34 
35 VICARE_MODE_DHW = "dhw"
36 VICARE_MODE_HEATING = "heating"
37 VICARE_MODE_DHWANDHEATING = "dhwAndHeating"
38 VICARE_MODE_DHWANDHEATINGCOOLING = "dhwAndHeatingCooling"
39 VICARE_MODE_FORCEDREDUCED = "forcedReduced"
40 VICARE_MODE_FORCEDNORMAL = "forcedNormal"
41 VICARE_MODE_OFF = "standby"
42 
43 VICARE_TEMP_WATER_MIN = 10
44 VICARE_TEMP_WATER_MAX = 60
45 
46 OPERATION_MODE_ON = "on"
47 OPERATION_MODE_OFF = "off"
48 
49 VICARE_TO_HA_HVAC_DHW = {
50  VICARE_MODE_DHW: OPERATION_MODE_ON,
51  VICARE_MODE_DHWANDHEATING: OPERATION_MODE_ON,
52  VICARE_MODE_DHWANDHEATINGCOOLING: OPERATION_MODE_ON,
53  VICARE_MODE_HEATING: OPERATION_MODE_OFF,
54  VICARE_MODE_FORCEDREDUCED: OPERATION_MODE_OFF,
55  VICARE_MODE_FORCEDNORMAL: OPERATION_MODE_ON,
56  VICARE_MODE_OFF: OPERATION_MODE_OFF,
57 }
58 
59 HA_TO_VICARE_HVAC_DHW = {
60  OPERATION_MODE_OFF: VICARE_MODE_OFF,
61  OPERATION_MODE_ON: VICARE_MODE_DHW,
62 }
63 
64 
66  device_list: list[ViCareDevice],
67 ) -> list[ViCareWater]:
68  """Create ViCare domestic hot water entities for a device."""
69 
70  return [
72  get_device_serial(device.api),
73  device.config,
74  device.api,
75  circuit,
76  )
77  for device in device_list
78  for circuit in get_circuits(device.api)
79  ]
80 
81 
83  hass: HomeAssistant,
84  config_entry: ConfigEntry,
85  async_add_entities: AddEntitiesCallback,
86 ) -> None:
87  """Set up the ViCare water heater platform."""
88  device_list = hass.data[DOMAIN][config_entry.entry_id][DEVICE_LIST]
89 
91  await hass.async_add_executor_job(
92  _build_entities,
93  device_list,
94  )
95  )
96 
97 
99  """Representation of the ViCare domestic hot water device."""
100 
101  _attr_precision = PRECISION_TENTHS
102  _attr_supported_features = WaterHeaterEntityFeature.TARGET_TEMPERATURE
103  _attr_temperature_unit = UnitOfTemperature.CELSIUS
104  _attr_min_temp = VICARE_TEMP_WATER_MIN
105  _attr_max_temp = VICARE_TEMP_WATER_MAX
106  _attr_operation_list = list(HA_TO_VICARE_HVAC_DHW)
107  _attr_translation_key = "domestic_hot_water"
108  _current_mode: str | None = None
109 
110  def __init__(
111  self,
112  device_serial: str | None,
113  device_config: PyViCareDeviceConfig,
114  device: PyViCareDevice,
115  circuit: PyViCareHeatingCircuit,
116  ) -> None:
117  """Initialize the DHW water_heater device."""
118  super().__init__(circuit.id, device_serial, device_config, device)
119  self._circuit_circuit = circuit
120  self._attributes: dict[str, Any] = {}
121 
122  def update(self) -> None:
123  """Let HA know there has been an update from the ViCare API."""
124  try:
125  with suppress(PyViCareNotSupportedFeatureError):
126  self._attr_current_temperature_attr_current_temperature = (
127  self._api.getDomesticHotWaterStorageTemperature()
128  )
129 
130  with suppress(PyViCareNotSupportedFeatureError):
131  self._attr_target_temperature_attr_target_temperature = (
132  self._api.getDomesticHotWaterDesiredTemperature()
133  )
134 
135  with suppress(PyViCareNotSupportedFeatureError):
136  self._current_mode_current_mode = self._circuit_circuit.getActiveMode()
137 
138  except requests.exceptions.ConnectionError:
139  _LOGGER.error("Unable to retrieve data from ViCare server")
140  except PyViCareRateLimitError as limit_exception:
141  _LOGGER.error("Vicare API rate limit exceeded: %s", limit_exception)
142  except ValueError:
143  _LOGGER.error("Unable to decode data from ViCare server")
144  except PyViCareInvalidDataError as invalid_data_exception:
145  _LOGGER.error("Invalid data from Vicare server: %s", invalid_data_exception)
146 
147  def set_temperature(self, **kwargs: Any) -> None:
148  """Set new target temperatures."""
149  if (temp := kwargs.get(ATTR_TEMPERATURE)) is not None:
150  self._api.setDomesticHotWaterTemperature(temp)
151  self._attr_target_temperature_attr_target_temperature = temp
152 
153  @property
154  def current_operation(self) -> str | None:
155  """Return current operation ie. heat, cool, idle."""
156  if self._current_mode_current_mode is None:
157  return None
158  return VICARE_TO_HA_HVAC_DHW.get(self._current_mode_current_mode, None)
None __init__(self, str|None device_serial, PyViCareDeviceConfig device_config, PyViCareDevice device, PyViCareHeatingCircuit circuit)
str|None get_device_serial(PyViCareDevice device)
Definition: utils.py:35
list[PyViCareHeatingDeviceComponent] get_circuits(PyViCareDevice device)
Definition: utils.py:81
list[ViCareWater] _build_entities(list[ViCareDevice] device_list)
Definition: water_heater.py:67
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: water_heater.py:86