1 """Viessmann ViCare ventilation device."""
3 from __future__
import annotations
5 from contextlib
import suppress
9 from PyViCare.PyViCareDevice
import Device
as PyViCareDevice
10 from PyViCare.PyViCareDeviceConfig
import PyViCareDeviceConfig
11 from PyViCare.PyViCareUtils
import (
12 PyViCareInvalidDataError,
13 PyViCareNotSupportedFeatureError,
14 PyViCareRateLimitError,
16 from PyViCare.PyViCareVentilationDevice
import (
17 VentilationDevice
as PyViCareVentilationDevice,
19 from requests.exceptions
import ConnectionError
as RequestConnectionError
26 ordered_list_item_to_percentage,
27 percentage_to_ordered_list_item,
30 from .const
import DEVICE_LIST, DOMAIN
31 from .entity
import ViCareEntity
32 from .types
import ViCareDevice
33 from .utils
import get_device_serial
35 _LOGGER = logging.getLogger(__name__)
39 """ViCare preset ventilation programs.
41 As listed in https://github.com/somm15/PyViCare/blob/6c5b023ca6c8bb2d38141dd1746dc1705ec84ce8/PyViCare/PyViCareVentilationDevice.py#L37
44 LEVEL_ONE =
"levelOne"
45 LEVEL_TWO =
"levelTwo"
46 LEVEL_THREE =
"levelThree"
47 LEVEL_FOUR =
"levelFour"
51 """ViCare ventilation modes."""
53 PERMANENT =
"permanent"
54 VENTILATION =
"ventilation"
55 SENSOR_DRIVEN =
"sensor_driven"
56 SENSOR_OVERRIDE =
"sensor_override"
60 """Return the mapped ViCare ventilation mode for the Home Assistant mode."""
67 return HA_TO_VICARE_MODE_VENTILATION.get(ventilation_mode)
if mode
else None
72 """Return the mapped Home Assistant mode for the ViCare ventilation mode."""
73 for mode
in VentilationMode:
74 if HA_TO_VICARE_MODE_VENTILATION.get(
VentilationMode(mode)) == vicare_mode:
79 HA_TO_VICARE_MODE_VENTILATION = {
80 VentilationMode.PERMANENT:
"permanent",
81 VentilationMode.VENTILATION:
"ventilation",
82 VentilationMode.SENSOR_DRIVEN:
"sensorDriven",
83 VentilationMode.SENSOR_OVERRIDE:
"sensorOverride",
86 ORDERED_NAMED_FAN_SPEEDS = [
87 VentilationProgram.LEVEL_ONE,
88 VentilationProgram.LEVEL_TWO,
89 VentilationProgram.LEVEL_THREE,
90 VentilationProgram.LEVEL_FOUR,
95 device_list: list[ViCareDevice],
97 """Create ViCare climate entities for a device."""
100 for device
in device_list
101 if isinstance(device.api, PyViCareVentilationDevice)
107 config_entry: ConfigEntry,
108 async_add_entities: AddEntitiesCallback,
110 """Set up the ViCare fan platform."""
112 device_list = hass.data[DOMAIN][config_entry.entry_id][DEVICE_LIST]
115 await hass.async_add_executor_job(
123 """Representation of the ViCare ventilation device."""
125 _attr_speed_count = len(ORDERED_NAMED_FAN_SPEEDS)
126 _attr_supported_features = FanEntityFeature.SET_SPEED
127 _attr_translation_key =
"ventilation"
128 _enable_turn_on_off_backwards_compatibility =
False
132 device_serial: str |
None,
133 device_config: PyViCareDeviceConfig,
134 device: PyViCareDevice,
136 """Initialize the fan entity."""
141 supported_modes = list[str](self._api.getAvailableModes())
144 for mode
in VentilationMode
145 if VentilationMode.to_vicare_mode(mode)
in supported_modes
151 """Update state of fan."""
153 with suppress(PyViCareNotSupportedFeatureError):
155 self._api.getActiveMode()
157 with suppress(PyViCareNotSupportedFeatureError):
159 ORDERED_NAMED_FAN_SPEEDS, self._api.getActiveProgram()
161 except RequestConnectionError:
162 _LOGGER.error(
"Unable to retrieve data from ViCare server")
164 _LOGGER.error(
"Unable to decode data from ViCare server")
165 except PyViCareRateLimitError
as limit_exception:
166 _LOGGER.error(
"Vicare API rate limit exceeded: %s", limit_exception)
167 except PyViCareInvalidDataError
as invalid_data_exception:
168 _LOGGER.error(
"Invalid data from Vicare server: %s", invalid_data_exception)
172 """Return true if the entity is on."""
178 """Return the icon to use in the frontend."""
179 if hasattr(self,
"_attr_preset_mode"):
181 return "mdi:fan-clock"
183 VentilationMode.SENSOR_DRIVEN,
184 VentilationMode.SENSOR_OVERRIDE,
186 return "mdi:fan-auto"
191 level = 1 + ORDERED_NAMED_FAN_SPEEDS.index(
192 percentage_to_ordered_list_item(
197 return f
"mdi:fan-speed-{level}"
201 """Set the speed of the fan, as a percentage."""
205 level = percentage_to_ordered_list_item(ORDERED_NAMED_FAN_SPEEDS, percentage)
206 _LOGGER.debug(
"changing ventilation level to %s", level)
207 self._api.setPermanentLevel(level)
210 """Set new preset mode."""
211 target_mode = VentilationMode.to_vicare_mode(preset_mode)
212 _LOGGER.debug(
"changing ventilation mode to %s", target_mode)
213 self._api.setActiveMode(target_mode)
None set_preset_mode(self, str preset_mode)
str|None to_vicare_mode(str|None mode)
str|None from_vicare_mode(str|None vicare_mode)
None set_percentage(self, int percentage)
string _attr_translation_key
None set_preset_mode(self, str preset_mode)
None __init__(self, str|None device_serial, PyViCareDeviceConfig device_config, PyViCareDevice device)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
list[ViCareFan] _build_entities(list[ViCareDevice] device_list)
str|None get_device_serial(PyViCareDevice device)