From ddbfed354e2a2d878e8c730059487961f97c847f Mon Sep 17 00:00:00 2001 From: Nyro <cedric@nyro.dev> Date: Fri, 4 Nov 2022 10:42:58 +0100 Subject: [PATCH] Add Overkiz AtlanticPassAPCDHW (#78665) * Add Overkiz AtlanticPassAPCDHW * Remove unnecessary line * Improve atlantic pass_apcdhw for operation and target temprature * Remove async_execute_commands * Fix small code issues for Overkiz AtlanticPassAPCDHW * Update homeassistant/components/overkiz/const.py Co-authored-by: Mick Vleeshouwer <mick@imick.nl> * Update homeassistant/components/overkiz/water_heater_entities/atlantic_pass_apc_dhw.py Co-authored-by: Quentame <polletquentin74@me.com> * Update homeassistant/components/overkiz/water_heater_entities/atlantic_pass_apc_dhw.py Co-authored-by: Quentame <polletquentin74@me.com> * Fix small issues Co-authored-by: Mick Vleeshouwer <mick@imick.nl> Co-authored-by: Quentame <polletquentin74@me.com> --- .coveragerc | 2 + homeassistant/components/overkiz/const.py | 2 + .../components/overkiz/water_heater.py | 28 ++++ .../overkiz/water_heater_entities/__init__.py | 8 + .../atlantic_pass_apc_dhw.py | 145 ++++++++++++++++++ 5 files changed, 185 insertions(+) create mode 100644 homeassistant/components/overkiz/water_heater.py create mode 100644 homeassistant/components/overkiz/water_heater_entities/__init__.py create mode 100644 homeassistant/components/overkiz/water_heater_entities/atlantic_pass_apc_dhw.py diff --git a/.coveragerc b/.coveragerc index eb60f320a74..84f061fbd35 100644 --- a/.coveragerc +++ b/.coveragerc @@ -953,6 +953,8 @@ omit = homeassistant/components/overkiz/sensor.py homeassistant/components/overkiz/siren.py homeassistant/components/overkiz/switch.py + homeassistant/components/overkiz/water_heater.py + homeassistant/components/overkiz/water_heater_entities/* homeassistant/components/ovo_energy/__init__.py homeassistant/components/ovo_energy/const.py homeassistant/components/ovo_energy/sensor.py diff --git a/homeassistant/components/overkiz/const.py b/homeassistant/components/overkiz/const.py index 70477bbcdb2..4645b058182 100644 --- a/homeassistant/components/overkiz/const.py +++ b/homeassistant/components/overkiz/const.py @@ -32,6 +32,7 @@ PLATFORMS: list[Platform] = [ Platform.SENSOR, Platform.SIREN, Platform.SWITCH, + Platform.WATER_HEATER, ] IGNORED_OVERKIZ_DEVICES: list[UIClass | UIWidget] = [ @@ -64,6 +65,7 @@ OVERKIZ_DEVICE_TO_PLATFORM: dict[UIClass | UIWidget, Platform | None] = { 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_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) UIWidget.ATLANTIC_PASS_APC_HEATING_AND_COOLING_ZONE: 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) diff --git a/homeassistant/components/overkiz/water_heater.py b/homeassistant/components/overkiz/water_heater.py new file mode 100644 index 00000000000..e22f442c266 --- /dev/null +++ b/homeassistant/components/overkiz/water_heater.py @@ -0,0 +1,28 @@ +"""Support for Overkiz water heater devices.""" +from __future__ import annotations + +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import HomeAssistantOverkizData +from .const import DOMAIN +from .water_heater_entities import WIDGET_TO_WATER_HEATER_ENTITY + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up the Overkiz DHW from a config entry.""" + data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id] + + async_add_entities( + WIDGET_TO_WATER_HEATER_ENTITY[device.widget]( + device.device_url, data.coordinator + ) + for device in data.platforms[Platform.WATER_HEATER] + if device.widget in WIDGET_TO_WATER_HEATER_ENTITY + ) diff --git a/homeassistant/components/overkiz/water_heater_entities/__init__.py b/homeassistant/components/overkiz/water_heater_entities/__init__.py new file mode 100644 index 00000000000..e03585da56d --- /dev/null +++ b/homeassistant/components/overkiz/water_heater_entities/__init__.py @@ -0,0 +1,8 @@ +"""Water heater entities for the Overkiz (by Somfy) integration.""" +from pyoverkiz.enums.ui import UIWidget + +from .atlantic_pass_apc_dhw import AtlanticPassAPCDHW + +WIDGET_TO_WATER_HEATER_ENTITY = { + UIWidget.ATLANTIC_PASS_APC_DHW: AtlanticPassAPCDHW, +} diff --git a/homeassistant/components/overkiz/water_heater_entities/atlantic_pass_apc_dhw.py b/homeassistant/components/overkiz/water_heater_entities/atlantic_pass_apc_dhw.py new file mode 100644 index 00000000000..7c2ea6ff2d8 --- /dev/null +++ b/homeassistant/components/overkiz/water_heater_entities/atlantic_pass_apc_dhw.py @@ -0,0 +1,145 @@ +"""Support for Atlantic Pass APC DHW.""" + +from typing import Any, cast + +from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState + +from homeassistant.components.water_heater import ( + STATE_ECO, + STATE_HEAT_PUMP, + STATE_OFF, + STATE_PERFORMANCE, + WaterHeaterEntity, + WaterHeaterEntityFeature, +) +from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS + +from ..entity import OverkizEntity + + +class AtlanticPassAPCDHW(OverkizEntity, WaterHeaterEntity): + """Representation of Atlantic Pass APC DHW.""" + + _attr_temperature_unit = TEMP_CELSIUS + _attr_supported_features = ( + WaterHeaterEntityFeature.TARGET_TEMPERATURE + | WaterHeaterEntityFeature.OPERATION_MODE + | WaterHeaterEntityFeature.AWAY_MODE + ) + _attr_operation_list = [STATE_OFF, STATE_HEAT_PUMP, STATE_PERFORMANCE] + + @property + def target_temperature(self) -> float: + """Return the temperature corresponding to the PRESET.""" + if self.is_boost_mode_on: + return cast( + float, + self.executor.select_state( + OverkizState.CORE_COMFORT_TARGET_DWH_TEMPERATURE + ), + ) + + if self.is_eco_mode_on: + return cast( + float, + self.executor.select_state( + OverkizState.CORE_ECO_TARGET_DWH_TEMPERATURE + ), + ) + + return cast( + float, + self.executor.select_state(OverkizState.CORE_TARGET_DWH_TEMPERATURE), + ) + + async def async_set_temperature(self, **kwargs: Any) -> None: + """Set new temperature.""" + temperature = kwargs[ATTR_TEMPERATURE] + + if self.is_eco_mode_on: + await self.executor.async_execute_command( + OverkizCommand.SET_ECO_TARGET_DHW_TEMPERATURE, temperature + ) + await self.executor.async_execute_command( + OverkizCommand.REFRESH_ECO_TARGET_DWH_TEMPERATURE + ) + else: + await self.executor.async_execute_command( + OverkizCommand.SET_COMFORT_TARGET_DHW_TEMPERATURE, temperature + ) + await self.executor.async_execute_command( + OverkizCommand.REFRESH_COMFORT_TARGET_DWH_TEMPERATURE + ) + await self.executor.async_execute_command( + OverkizCommand.REFRESH_TARGET_DWH_TEMPERATURE + ) + + @property + def is_boost_mode_on(self) -> bool: + """Return true if boost mode is on.""" + return ( + self.executor.select_state(OverkizState.CORE_BOOST_ON_OFF) + == OverkizCommandParam.ON + ) + + @property + def is_eco_mode_on(self) -> bool: + """Return true if eco mode is on.""" + return ( + self.executor.select_state(OverkizState.IO_PASS_APCDWH_MODE) + == OverkizCommandParam.ECO + ) + + @property + def is_away_mode_on(self) -> bool: + """Return true if away mode is on.""" + return ( + self.executor.select_state(OverkizState.CORE_DWH_ON_OFF) + == OverkizCommandParam.OFF + ) + + @property + def current_operation(self) -> str: + """Return current operation.""" + if self.is_boost_mode_on: + return STATE_PERFORMANCE + if self.is_eco_mode_on: + return STATE_ECO + if self.is_away_mode_on: + return STATE_OFF + return STATE_HEAT_PUMP + + async def async_set_operation_mode(self, operation_mode: str) -> None: + """Set new operation mode.""" + boost_state = OverkizCommandParam.OFF + regular_state = OverkizCommandParam.OFF + if operation_mode == STATE_PERFORMANCE: + boost_state = OverkizCommandParam.ON + regular_state = OverkizCommandParam.ON + elif operation_mode == STATE_HEAT_PUMP: + regular_state = OverkizCommandParam.ON + + await self.executor.async_execute_command( + OverkizCommand.SET_BOOST_ON_OFF_STATE, boost_state + ) + await self.executor.async_execute_command( + OverkizCommand.SET_DHW_ON_OFF_STATE, regular_state + ) + + async def async_turn_away_mode_on(self) -> None: + """Turn away mode on.""" + await self.executor.async_execute_command( + OverkizCommand.SET_BOOST_ON_OFF_STATE, OverkizCommandParam.OFF + ) + await self.executor.async_execute_command( + OverkizCommand.SET_DHW_ON_OFF_STATE, OverkizCommandParam.OFF + ) + + async def async_turn_away_mode_off(self) -> None: + """Turn away mode off.""" + await self.executor.async_execute_command( + OverkizCommand.SET_BOOST_ON_OFF_STATE, OverkizCommandParam.OFF + ) + await self.executor.async_execute_command( + OverkizCommand.SET_DHW_ON_OFF_STATE, OverkizCommandParam.ON + ) -- GitLab