diff --git a/homeassistant/components/overkiz/binary_sensor.py b/homeassistant/components/overkiz/binary_sensor.py index c37afc9cb0c..8ea86e03e8c 100644 --- a/homeassistant/components/overkiz/binary_sensor.py +++ b/homeassistant/components/overkiz/binary_sensor.py @@ -109,17 +109,20 @@ BINARY_SENSOR_DESCRIPTIONS: list[OverkizBinarySensorDescription] = [ key=OverkizState.CORE_HEATING_STATUS, name="Heating status", device_class=BinarySensorDeviceClass.HEAT, - value_fn=lambda state: state == OverkizCommandParam.ON, + value_fn=lambda state: cast(str, state).lower() + in (OverkizCommandParam.ON, OverkizCommandParam.HEATING), ), OverkizBinarySensorDescription( key=OverkizState.MODBUSLINK_DHW_ABSENCE_MODE, name="Absence mode", - value_fn=lambda state: state == OverkizCommandParam.ON, + value_fn=lambda state: state + in (OverkizCommandParam.ON, OverkizCommandParam.PROG), ), OverkizBinarySensorDescription( key=OverkizState.MODBUSLINK_DHW_BOOST_MODE, name="Boost mode", - value_fn=lambda state: state == OverkizCommandParam.ON, + value_fn=lambda state: state + in (OverkizCommandParam.ON, OverkizCommandParam.PROG), ), ] diff --git a/homeassistant/components/overkiz/water_heater.py b/homeassistant/components/overkiz/water_heater.py index c76f6d5099f..99bfb279e4c 100644 --- a/homeassistant/components/overkiz/water_heater.py +++ b/homeassistant/components/overkiz/water_heater.py @@ -9,7 +9,11 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import HomeAssistantOverkizData from .const import DOMAIN -from .water_heater_entities import WIDGET_TO_WATER_HEATER_ENTITY +from .entity import OverkizEntity +from .water_heater_entities import ( + CONTROLLABLE_NAME_TO_WATER_HEATER_ENTITY, + WIDGET_TO_WATER_HEATER_ENTITY, +) async def async_setup_entry( @@ -19,11 +23,20 @@ async def async_setup_entry( ) -> None: """Set up the Overkiz DHW from a config entry.""" data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id] + entities: list[OverkizEntity] = [] - 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 - ) + for device in data.platforms[Platform.WATER_HEATER]: + if device.controllable_name in CONTROLLABLE_NAME_TO_WATER_HEATER_ENTITY: + entities.append( + CONTROLLABLE_NAME_TO_WATER_HEATER_ENTITY[device.controllable_name]( + device.device_url, data.coordinator + ) + ) + elif device.widget in WIDGET_TO_WATER_HEATER_ENTITY: + entities.append( + WIDGET_TO_WATER_HEATER_ENTITY[device.widget]( + device.device_url, data.coordinator + ) + ) + + async_add_entities(entities) diff --git a/homeassistant/components/overkiz/water_heater_entities/__init__.py b/homeassistant/components/overkiz/water_heater_entities/__init__.py index 6f6539ef659..fdc41f213c6 100644 --- a/homeassistant/components/overkiz/water_heater_entities/__init__.py +++ b/homeassistant/components/overkiz/water_heater_entities/__init__.py @@ -2,6 +2,9 @@ from pyoverkiz.enums.ui import UIWidget +from .atlantic_domestic_hot_water_production_mlb_component import ( + AtlanticDomesticHotWaterProductionMBLComponent, +) from .atlantic_pass_apc_dhw import AtlanticPassAPCDHW from .domestic_hot_water_production import DomesticHotWaterProduction from .hitachi_dhw import HitachiDHW @@ -11,3 +14,7 @@ WIDGET_TO_WATER_HEATER_ENTITY = { UIWidget.DOMESTIC_HOT_WATER_PRODUCTION: DomesticHotWaterProduction, UIWidget.HITACHI_DHW: HitachiDHW, } + +CONTROLLABLE_NAME_TO_WATER_HEATER_ENTITY = { + "modbuslink:AtlanticDomesticHotWaterProductionMBLComponent": AtlanticDomesticHotWaterProductionMBLComponent, +} diff --git a/homeassistant/components/overkiz/water_heater_entities/atlantic_domestic_hot_water_production_mlb_component.py b/homeassistant/components/overkiz/water_heater_entities/atlantic_domestic_hot_water_production_mlb_component.py new file mode 100644 index 00000000000..de995a2bd1a --- /dev/null +++ b/homeassistant/components/overkiz/water_heater_entities/atlantic_domestic_hot_water_production_mlb_component.py @@ -0,0 +1,182 @@ +"""Support for AtlanticDomesticHotWaterProductionMBLComponent.""" + +from typing import Any, cast + +from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState + +from homeassistant.components.water_heater import ( + STATE_ECO, + STATE_OFF, + STATE_PERFORMANCE, + WaterHeaterEntity, + WaterHeaterEntityFeature, +) +from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature + +from .. import OverkizDataUpdateCoordinator +from ..entity import OverkizEntity + + +class AtlanticDomesticHotWaterProductionMBLComponent(OverkizEntity, WaterHeaterEntity): + """Representation of AtlanticDomesticHotWaterProductionMBLComponent (modbuslink).""" + + _attr_temperature_unit = UnitOfTemperature.CELSIUS + _attr_supported_features = ( + WaterHeaterEntityFeature.TARGET_TEMPERATURE + | WaterHeaterEntityFeature.OPERATION_MODE + | WaterHeaterEntityFeature.AWAY_MODE + | WaterHeaterEntityFeature.ON_OFF + ) + _attr_operation_list = [ + OverkizCommandParam.PERFORMANCE, + OverkizCommandParam.ECO, + OverkizCommandParam.MANUAL, + ] + + def __init__( + self, device_url: str, coordinator: OverkizDataUpdateCoordinator + ) -> None: + """Init method.""" + super().__init__(device_url, coordinator) + self._attr_max_temp = cast( + float, + self.executor.select_state( + OverkizState.CORE_MAXIMAL_TEMPERATURE_MANUAL_MODE + ), + ) + self._attr_min_temp = cast( + float, + self.executor.select_state( + OverkizState.CORE_MINIMAL_TEMPERATURE_MANUAL_MODE + ), + ) + + @property + def current_temperature(self) -> float: + """Return the current temperature.""" + return cast( + float, + self.executor.select_state( + OverkizState.MODBUSLINK_MIDDLE_WATER_TEMPERATURE + ), + ) + + @property + def target_temperature(self) -> float: + """Return the temperature corresponding to the PRESET.""" + return cast( + float, + self.executor.select_state(OverkizState.CORE_WATER_TARGET_TEMPERATURE), + ) + + 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_DHW_TEMPERATURE, temperature + ) + + @property + def is_boost_mode_on(self) -> bool: + """Return true if boost mode is on.""" + return self.executor.select_state(OverkizState.MODBUSLINK_DHW_BOOST_MODE) in ( + OverkizCommandParam.ON, + OverkizCommandParam.PROG, + ) + + @property + def is_eco_mode_on(self) -> bool: + """Return true if eco mode is on.""" + return self.executor.select_state(OverkizState.MODBUSLINK_DHW_MODE) in ( + OverkizCommandParam.MANUAL_ECO_ACTIVE, + OverkizCommandParam.AUTO_MODE, + ) + + @property + def is_away_mode_on(self) -> bool: + """Return true if away mode is on.""" + return ( + self.executor.select_state(OverkizState.MODBUSLINK_DHW_ABSENCE_MODE) + == OverkizCommandParam.ON + ) + + @property + def current_operation(self) -> str: + """Return current operation.""" + if self.is_away_mode_on: + return STATE_OFF + + if self.is_boost_mode_on: + return STATE_PERFORMANCE + + if self.is_eco_mode_on: + return STATE_ECO + + if ( + cast(str, self.executor.select_state(OverkizState.MODBUSLINK_DHW_MODE)) + == OverkizCommandParam.MANUAL_ECO_INACTIVE + ): + return OverkizCommandParam.MANUAL + + return STATE_OFF + + async def async_set_operation_mode(self, operation_mode: str) -> None: + """Set new operation mode.""" + if operation_mode in (STATE_PERFORMANCE, OverkizCommandParam.BOOST): + if self.is_away_mode_on: + await self.async_turn_away_mode_off() + await self.async_turn_boost_mode_on() + elif operation_mode in ( + OverkizCommandParam.ECO, + OverkizCommandParam.MANUAL_ECO_ACTIVE, + ): + if self.is_away_mode_on: + await self.async_turn_away_mode_off() + if self.is_boost_mode_on: + await self.async_turn_boost_mode_off() + await self.executor.async_execute_command( + OverkizCommand.SET_DHW_MODE, OverkizCommandParam.AUTO_MODE + ) + elif operation_mode in ( + OverkizCommandParam.MANUAL, + OverkizCommandParam.MANUAL_ECO_INACTIVE, + ): + if self.is_away_mode_on: + await self.async_turn_away_mode_off() + if self.is_boost_mode_on: + await self.async_turn_boost_mode_off() + await self.executor.async_execute_command( + OverkizCommand.SET_DHW_MODE, OverkizCommandParam.MANUAL_ECO_INACTIVE + ) + else: + if self.is_away_mode_on: + await self.async_turn_away_mode_off() + if self.is_boost_mode_on: + await self.async_turn_boost_mode_off() + await self.executor.async_execute_command( + OverkizCommand.SET_DHW_MODE, operation_mode + ) + + async def async_turn_away_mode_on(self) -> None: + """Turn away mode on.""" + await self.executor.async_execute_command( + OverkizCommand.SET_ABSENCE_MODE, OverkizCommandParam.ON + ) + + async def async_turn_away_mode_off(self) -> None: + """Turn away mode off.""" + await self.executor.async_execute_command( + OverkizCommand.SET_ABSENCE_MODE, OverkizCommandParam.OFF + ) + + async def async_turn_boost_mode_on(self) -> None: + """Turn boost mode on.""" + await self.executor.async_execute_command( + OverkizCommand.SET_BOOST_MODE, OverkizCommandParam.ON + ) + + async def async_turn_boost_mode_off(self) -> None: + """Turn boost mode off.""" + await self.executor.async_execute_command( + OverkizCommand.SET_BOOST_MODE, OverkizCommandParam.OFF + )