"""Support for Overkiz switches.""" from __future__ import annotations from collections.abc import Callable from dataclasses import dataclass from typing import Any, cast from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState from pyoverkiz.enums.ui import UIClass, UIWidget from pyoverkiz.types import StateType as OverkizStateType from homeassistant.components.switch import ( SwitchDeviceClass, SwitchEntity, SwitchEntityDescription, ) from homeassistant.config_entries import ConfigEntry from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import HomeAssistantOverkizData from .const import DOMAIN, IGNORED_OVERKIZ_DEVICES from .entity import OverkizDescriptiveEntity @dataclass class OverkizSwitchDescriptionMixin: """Define an entity description mixin for switch entities.""" turn_on: str turn_off: str @dataclass class OverkizSwitchDescription(SwitchEntityDescription, OverkizSwitchDescriptionMixin): """Class to describe an Overkiz switch.""" is_on: Callable[[Callable[[str], OverkizStateType]], bool] | None = None turn_on_args: OverkizStateType | list[OverkizStateType] | None = None turn_off_args: OverkizStateType | list[OverkizStateType] | None = None SWITCH_DESCRIPTIONS: list[OverkizSwitchDescription] = [ OverkizSwitchDescription( key=UIWidget.DOMESTIC_HOT_WATER_TANK, turn_on=OverkizCommand.SET_FORCE_HEATING, turn_on_args=OverkizCommandParam.ON, turn_off=OverkizCommand.SET_FORCE_HEATING, turn_off_args=OverkizCommandParam.OFF, is_on=lambda select_state: ( select_state(OverkizState.IO_FORCE_HEATING) == OverkizCommandParam.ON ), icon="mdi:water-boiler", ), OverkizSwitchDescription( key=UIClass.ON_OFF, turn_on=OverkizCommand.ON, turn_off=OverkizCommand.OFF, is_on=lambda select_state: ( select_state(OverkizState.CORE_ON_OFF) == OverkizCommandParam.ON ), device_class=SwitchDeviceClass.OUTLET, ), OverkizSwitchDescription( key=UIClass.SWIMMING_POOL, turn_on=OverkizCommand.ON, turn_off=OverkizCommand.OFF, is_on=lambda select_state: ( select_state(OverkizState.CORE_ON_OFF) == OverkizCommandParam.ON ), icon="mdi:pool", ), OverkizSwitchDescription( key=UIWidget.RTD_INDOOR_SIREN, turn_on=OverkizCommand.ON, turn_off=OverkizCommand.OFF, icon="mdi:bell", ), OverkizSwitchDescription( key=UIWidget.RTD_OUTDOOR_SIREN, turn_on=OverkizCommand.ON, turn_off=OverkizCommand.OFF, icon="mdi:bell", ), OverkizSwitchDescription( key=UIWidget.STATELESS_ALARM_CONTROLLER, turn_on=OverkizCommand.ALARM_ON, turn_off=OverkizCommand.ALARM_OFF, icon="mdi:shield-lock", ), OverkizSwitchDescription( key=UIWidget.STATELESS_EXTERIOR_HEATING, turn_on=OverkizCommand.ON, turn_off=OverkizCommand.OFF, icon="mdi:radiator", ), OverkizSwitchDescription( key=UIWidget.MY_FOX_SECURITY_CAMERA, name="Camera shutter", turn_on=OverkizCommand.OPEN, turn_off=OverkizCommand.CLOSE, icon="mdi:camera-lock", is_on=lambda select_state: ( select_state(OverkizState.MYFOX_SHUTTER_STATUS) == OverkizCommandParam.OPENED ), entity_category=EntityCategory.CONFIG, ), OverkizSwitchDescription( key=UIWidget.DYNAMIC_SHUTTER, name="Silent mode", turn_on=OverkizCommand.ACTIVATE_OPTION, turn_on_args=OverkizCommandParam.SILENCE, turn_off=OverkizCommand.DEACTIVATE_OPTION, turn_off_args=OverkizCommandParam.SILENCE, is_on=lambda select_state: ( OverkizCommandParam.SILENCE in cast(list, select_state(OverkizState.CORE_ACTIVATED_OPTIONS)) ), icon="mdi:feather", ), ] SUPPORTED_DEVICES = { description.key: description for description in SWITCH_DESCRIPTIONS } async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up the Overkiz switch from a config entry.""" data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id] entities: list[OverkizSwitch] = [] for device in data.coordinator.data.values(): if ( device.widget in IGNORED_OVERKIZ_DEVICES or device.ui_class in IGNORED_OVERKIZ_DEVICES ): continue if description := SUPPORTED_DEVICES.get(device.widget) or SUPPORTED_DEVICES.get( device.ui_class ): entities.append( OverkizSwitch( device.device_url, data.coordinator, description, ) ) async_add_entities(entities) class OverkizSwitch(OverkizDescriptiveEntity, SwitchEntity): """Representation of an Overkiz Switch.""" entity_description: OverkizSwitchDescription @property def is_on(self) -> bool | None: """Return True if entity is on.""" if self.entity_description.is_on: return self.entity_description.is_on(self.executor.select_state) return None async def async_turn_on(self, **kwargs: Any) -> None: """Turn the entity on.""" await self.executor.async_execute_command( self.entity_description.turn_on, self.entity_description.turn_on_args, ) async def async_turn_off(self, **kwargs: Any) -> None: """Turn the entity off.""" await self.executor.async_execute_command( self.entity_description.turn_off, self.entity_description.turn_off_args, )