From 55cad465b209aee179ad1edfb3ee7de0ffc84342 Mon Sep 17 00:00:00 2001 From: Thibaut Date: Tue, 8 Nov 2022 00:07:02 +0100 Subject: [PATCH] Add support for AEH with adjustable temperature in Overkiz integration (#72790) * Import and clean from ha-tahoma * Fix wrong search and replace * Clean code * Use elif * Sort import * Fix imports * Update homeassistant/components/overkiz/climate_entities/atlantic_electrical_heater_with_adjustable_temperature_setpoint.py Co-authored-by: Mick Vleeshouwer * Fix import * Remove cast * Remove useless constructor * Use constant * Remove now useless conditions Co-authored-by: Mick Vleeshouwer --- .../overkiz/climate_entities/__init__.py | 4 + ...er_with_adjustable_temperature_setpoint.py | 134 ++++++++++++++++++ homeassistant/components/overkiz/const.py | 1 + 3 files changed, 139 insertions(+) create mode 100644 homeassistant/components/overkiz/climate_entities/atlantic_electrical_heater_with_adjustable_temperature_setpoint.py diff --git a/homeassistant/components/overkiz/climate_entities/__init__.py b/homeassistant/components/overkiz/climate_entities/__init__.py index 359f7629a7b..5d676e49747 100644 --- a/homeassistant/components/overkiz/climate_entities/__init__.py +++ b/homeassistant/components/overkiz/climate_entities/__init__.py @@ -2,6 +2,9 @@ from pyoverkiz.enums.ui import UIWidget from .atlantic_electrical_heater import AtlanticElectricalHeater +from .atlantic_electrical_heater_with_adjustable_temperature_setpoint import ( + AtlanticElectricalHeaterWithAdjustableTemperatureSetpoint, +) from .atlantic_electrical_towel_dryer import AtlanticElectricalTowelDryer from .atlantic_heat_recovery_ventilation import AtlanticHeatRecoveryVentilation from .atlantic_pass_apc_heating_and_cooling_zone import ( @@ -12,6 +15,7 @@ from .somfy_thermostat import SomfyThermostat WIDGET_TO_CLIMATE_ENTITY = { UIWidget.ATLANTIC_ELECTRICAL_HEATER: AtlanticElectricalHeater, + UIWidget.ATLANTIC_ELECTRICAL_HEATER_WITH_ADJUSTABLE_TEMPERATURE_SETPOINT: AtlanticElectricalHeaterWithAdjustableTemperatureSetpoint, UIWidget.ATLANTIC_ELECTRICAL_TOWEL_DRYER: AtlanticElectricalTowelDryer, UIWidget.ATLANTIC_HEAT_RECOVERY_VENTILATION: AtlanticHeatRecoveryVentilation, UIWidget.ATLANTIC_PASS_APC_HEATING_AND_COOLING_ZONE: AtlanticPassAPCHeatingAndCoolingZone, diff --git a/homeassistant/components/overkiz/climate_entities/atlantic_electrical_heater_with_adjustable_temperature_setpoint.py b/homeassistant/components/overkiz/climate_entities/atlantic_electrical_heater_with_adjustable_temperature_setpoint.py new file mode 100644 index 00000000000..80c2f418331 --- /dev/null +++ b/homeassistant/components/overkiz/climate_entities/atlantic_electrical_heater_with_adjustable_temperature_setpoint.py @@ -0,0 +1,134 @@ +"""Support for Atlantic Electrical Heater (With Adjustable Temperature Setpoint).""" +from __future__ import annotations + +from typing import Any + +from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState + +from homeassistant.components.climate import ( + PRESET_BOOST, + PRESET_COMFORT, + PRESET_ECO, + PRESET_NONE, + ClimateEntity, + ClimateEntityFeature, + HVACMode, +) +from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS + +from ..coordinator import OverkizDataUpdateCoordinator +from ..entity import OverkizEntity + +PRESET_AUTO = "auto" +PRESET_COMFORT1 = "comfort-1" +PRESET_COMFORT2 = "comfort-2" +PRESET_FROST_PROTECTION = "frost_protection" +PRESET_PROG = "prog" + + +# Map Overkiz presets to Home Assistant presets +OVERKIZ_TO_PRESET_MODE: dict[str, str] = { + OverkizCommandParam.OFF: PRESET_NONE, + OverkizCommandParam.FROSTPROTECTION: PRESET_FROST_PROTECTION, + OverkizCommandParam.ECO: PRESET_ECO, + OverkizCommandParam.COMFORT: PRESET_COMFORT, + OverkizCommandParam.COMFORT_1: PRESET_COMFORT1, + OverkizCommandParam.COMFORT_2: PRESET_COMFORT2, + OverkizCommandParam.AUTO: PRESET_AUTO, + OverkizCommandParam.BOOST: PRESET_BOOST, + OverkizCommandParam.INTERNAL: PRESET_PROG, +} + +PRESET_MODE_TO_OVERKIZ = {v: k for k, v in OVERKIZ_TO_PRESET_MODE.items()} + +# Map Overkiz HVAC modes to Home Assistant HVAC modes +OVERKIZ_TO_HVAC_MODE: dict[str, str] = { + OverkizCommandParam.ON: HVACMode.HEAT, + OverkizCommandParam.OFF: HVACMode.OFF, + OverkizCommandParam.AUTO: HVACMode.AUTO, + OverkizCommandParam.BASIC: HVACMode.HEAT, + OverkizCommandParam.STANDBY: HVACMode.OFF, + OverkizCommandParam.INTERNAL: HVACMode.AUTO, +} + +HVAC_MODE_TO_OVERKIZ = {v: k for k, v in OVERKIZ_TO_HVAC_MODE.items()} + +TEMPERATURE_SENSOR_DEVICE_INDEX = 2 + + +class AtlanticElectricalHeaterWithAdjustableTemperatureSetpoint( + OverkizEntity, ClimateEntity +): + """Representation of Atlantic Electrical Heater (With Adjustable Temperature Setpoint).""" + + _attr_hvac_modes = [*HVAC_MODE_TO_OVERKIZ] + _attr_preset_modes = [*PRESET_MODE_TO_OVERKIZ] + _attr_temperature_unit = TEMP_CELSIUS + _attr_supported_features = ( + ClimateEntityFeature.PRESET_MODE | ClimateEntityFeature.TARGET_TEMPERATURE + ) + + 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 + ) + + @property + def hvac_mode(self) -> str: + """Return hvac operation ie. heat, cool mode.""" + states = self.device.states + if (state := states[OverkizState.CORE_OPERATING_MODE]) and state.value_as_str: + return OVERKIZ_TO_HVAC_MODE[state.value_as_str] + if (state := states[OverkizState.CORE_ON_OFF]) and state.value_as_str: + return OVERKIZ_TO_HVAC_MODE[state.value_as_str] + return HVACMode.OFF + + async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None: + """Set new target hvac mode.""" + await self.executor.async_execute_command( + OverkizCommand.SET_OPERATING_MODE, HVAC_MODE_TO_OVERKIZ[hvac_mode] + ) + + @property + def preset_mode(self) -> str | None: + """Return the current preset mode, e.g., home, away, temp.""" + if ( + state := self.device.states[OverkizState.IO_TARGET_HEATING_LEVEL] + ) and state.value_as_str: + return OVERKIZ_TO_PRESET_MODE[state.value_as_str] + return None + + async def async_set_preset_mode(self, preset_mode: str) -> None: + """Set new preset mode.""" + if preset_mode in [PRESET_AUTO, PRESET_PROG]: + command = OverkizCommand.SET_OPERATING_MODE + else: + command = OverkizCommand.SET_HEATING_LEVEL + await self.executor.async_execute_command( + command, PRESET_MODE_TO_OVERKIZ[preset_mode] + ) + + @property + def target_temperature(self) -> float | None: + """Return the temperature.""" + if state := self.device.states[OverkizState.CORE_TARGET_TEMPERATURE]: + return state.value_as_float + return None + + @property + def current_temperature(self) -> float | None: + """Return the current temperature.""" + if temperature := self.temperature_device.states[OverkizState.CORE_TEMPERATURE]: + return temperature.value_as_float + return None + + async def async_set_temperature(self, **kwargs: Any) -> None: + """Set new temperature.""" + temperature = kwargs[ATTR_TEMPERATURE] + await self.executor.async_execute_command( + OverkizCommand.SET_TARGET_TEMPERATURE, temperature + ) diff --git a/homeassistant/components/overkiz/const.py b/homeassistant/components/overkiz/const.py index 4645b058182..f207fc305e0 100644 --- a/homeassistant/components/overkiz/const.py +++ b/homeassistant/components/overkiz/const.py @@ -63,6 +63,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_HEATER_WITH_ADJUSTABLE_TEMPERATURE_SETPOINT: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) UIWidget.ATLANTIC_ELECTRICAL_TOWEL_DRYER: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) UIWidget.ATLANTIC_HEAT_RECOVERY_VENTILATION: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) UIWidget.ATLANTIC_PASS_APC_DHW: Platform.WATER_HEATER, # widgetName, uiClass is WaterHeatingSystem (not supported)