diff --git a/homeassistant/components/overkiz/climate_entities/__init__.py b/homeassistant/components/overkiz/climate_entities/__init__.py index d44aa85d167..737ea342c40 100644 --- a/homeassistant/components/overkiz/climate_entities/__init__.py +++ b/homeassistant/components/overkiz/climate_entities/__init__.py @@ -2,11 +2,13 @@ from pyoverkiz.enums.ui import UIWidget from .atlantic_electrical_heater import AtlanticElectricalHeater +from .atlantic_electrical_towel_dryer import AtlanticElectricalTowelDryer from .atlantic_pass_apc_zone_control import AtlanticPassAPCZoneControl from .somfy_thermostat import SomfyThermostat WIDGET_TO_CLIMATE_ENTITY = { UIWidget.ATLANTIC_ELECTRICAL_HEATER: AtlanticElectricalHeater, + UIWidget.ATLANTIC_ELECTRICAL_TOWEL_DRYER: AtlanticElectricalTowelDryer, UIWidget.ATLANTIC_PASS_APC_ZONE_CONTROL: AtlanticPassAPCZoneControl, UIWidget.SOMFY_THERMOSTAT: SomfyThermostat, } diff --git a/homeassistant/components/overkiz/climate_entities/atlantic_electrical_towel_dryer.py b/homeassistant/components/overkiz/climate_entities/atlantic_electrical_towel_dryer.py new file mode 100644 index 00000000000..9a24a7bf1a9 --- /dev/null +++ b/homeassistant/components/overkiz/climate_entities/atlantic_electrical_towel_dryer.py @@ -0,0 +1,122 @@ +"""Support for Atlantic Electrical Towel Dryer.""" +from __future__ import annotations + +from typing import Any, cast + +from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState + +from homeassistant.components.climate import ClimateEntity +from homeassistant.components.climate.const import ( + PRESET_BOOST, + PRESET_NONE, + ClimateEntityFeature, + HVACMode, +) +from homeassistant.components.overkiz.coordinator import OverkizDataUpdateCoordinator +from homeassistant.components.overkiz.entity import OverkizEntity +from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS + +PRESET_DRYING = "drying" + +OVERKIZ_TO_HVAC_MODE: dict[str, str] = { + OverkizCommandParam.EXTERNAL: HVACMode.HEAT, # manu + OverkizCommandParam.INTERNAL: HVACMode.AUTO, # prog + OverkizCommandParam.STANDBY: HVACMode.OFF, +} +HVAC_MODE_TO_OVERKIZ = {v: k for k, v in OVERKIZ_TO_HVAC_MODE.items()} + +OVERKIZ_TO_PRESET_MODE: dict[str, str] = { + OverkizCommandParam.PERMANENT_HEATING: PRESET_NONE, + OverkizCommandParam.BOOST: PRESET_BOOST, + OverkizCommandParam.DRYING: PRESET_DRYING, +} + +PRESET_MODE_TO_OVERKIZ = {v: k for k, v in OVERKIZ_TO_PRESET_MODE.items()} + +TEMPERATURE_SENSOR_DEVICE_INDEX = 7 + + +class AtlanticElectricalTowelDryer(OverkizEntity, ClimateEntity): + """Representation of Atlantic Electrical Towel Dryer.""" + + _attr_hvac_modes = [*HVAC_MODE_TO_OVERKIZ] + _attr_preset_modes = [*PRESET_MODE_TO_OVERKIZ] + _attr_temperature_unit = TEMP_CELSIUS + + def __init__( + self, device_url: str, coordinator: OverkizDataUpdateCoordinator + ) -> None: + """Init method.""" + super().__init__(device_url, coordinator) + self.temperature_device = self.executor.linked_device( + TEMPERATURE_SENSOR_DEVICE_INDEX + ) + + self._attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE + + # Not all AtlanticElectricalTowelDryer models support presets, thus we need to check if the command is available + if self.executor.has_command(OverkizCommand.SET_TOWEL_DRYER_TEMPORARY_STATE): + self._attr_supported_features += ClimateEntityFeature.PRESET_MODE + + @property + def hvac_mode(self) -> str: + """Return hvac operation ie. heat, cool mode.""" + if OverkizState.CORE_OPERATING_MODE in self.device.states: + return OVERKIZ_TO_HVAC_MODE[ + cast(str, self.executor.select_state(OverkizState.CORE_OPERATING_MODE)) + ] + + return HVACMode.OFF + + async def async_set_hvac_mode(self, hvac_mode: str) -> None: + """Set new target hvac mode.""" + await self.executor.async_execute_command( + OverkizCommand.SET_TOWEL_DRYER_OPERATING_MODE, + HVAC_MODE_TO_OVERKIZ[hvac_mode], + ) + + @property + def target_temperature(self) -> None: + """Return the temperature.""" + if self.hvac_mode == HVACMode.AUTO: + self.executor.select_state(OverkizState.IO_EFFECTIVE_TEMPERATURE_SETPOINT) + else: + self.executor.select_state(OverkizState.CORE_TARGET_TEMPERATURE) + + @property + def current_temperature(self) -> float | None: + """Return the current temperature.""" + if temperature := self.temperature_device.states[OverkizState.CORE_TEMPERATURE]: + return cast(float, temperature.value) + + return None + + async def async_set_temperature(self, **kwargs: Any) -> None: + """Set new temperature.""" + temperature = kwargs[ATTR_TEMPERATURE] + + if self.hvac_mode == HVACMode.AUTO: + await self.executor.async_execute_command( + OverkizCommand.SET_DEROGATED_TARGET_TEMPERATURE, temperature + ) + else: + await self.executor.async_execute_command( + OverkizCommand.SET_TARGET_TEMPERATURE, temperature + ) + + @property + def preset_mode(self) -> str | None: + """Return the current preset mode, e.g., home, away, temp.""" + return OVERKIZ_TO_PRESET_MODE[ + cast( + str, + self.executor.select_state(OverkizState.IO_TOWEL_DRYER_TEMPORARY_STATE), + ) + ] + + async def async_set_preset_mode(self, preset_mode: str) -> None: + """Set new preset mode.""" + await self.executor.async_execute_command( + OverkizCommand.SET_TOWEL_DRYER_TEMPORARY_STATE, + PRESET_MODE_TO_OVERKIZ[preset_mode], + ) diff --git a/homeassistant/components/overkiz/const.py b/homeassistant/components/overkiz/const.py index 447ebc5ac42..9091cd35998 100644 --- a/homeassistant/components/overkiz/const.py +++ b/homeassistant/components/overkiz/const.py @@ -62,6 +62,7 @@ OVERKIZ_DEVICE_TO_PLATFORM: dict[UIClass | UIWidget, Platform | None] = { UIClass.WINDOW: Platform.COVER, UIWidget.ALARM_PANEL_CONTROLLER: Platform.ALARM_CONTROL_PANEL, # widgetName, uiClass is Alarm (not supported) UIWidget.ATLANTIC_ELECTRICAL_HEATER: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) + UIWidget.ATLANTIC_ELECTRICAL_TOWEL_DRYER: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) UIWidget.ATLANTIC_PASS_APC_ZONE_CONTROL: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) UIWidget.DOMESTIC_HOT_WATER_TANK: Platform.SWITCH, # widgetName, uiClass is WaterHeatingSystem (not supported) UIWidget.MY_FOX_ALARM_CONTROLLER: Platform.ALARM_CONTROL_PANEL, # widgetName, uiClass is Alarm (not supported)