diff --git a/.coveragerc b/.coveragerc index eb60f320a749dd73e008aa8e3f5ef8eca24ea38a..84f061fbd35b166adb3bd2f6ed3edf8a554b55d7 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 70477bbcdb2d8da6e250125ea8f74dc07aac451a..4645b058182aedd79cba37c5206437cfb9b45442 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 0000000000000000000000000000000000000000..e22f442c2662e378aeec8682df94c92712093404 --- /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 0000000000000000000000000000000000000000..e03585da56d93c07d2062d36935b191ac79544a9 --- /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 0000000000000000000000000000000000000000..7c2ea6ff2d8d647980be4fd7f89874ab0f5a4c60 --- /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 + )