"""Support for Roborock switch.""" from __future__ import annotations from collections.abc import Callable from dataclasses import dataclass import logging from typing import Any from roborock.devices.traits.v1 import PropertiesApi from roborock.devices.traits.v1.common import RoborockSwitchBase from roborock.exceptions import RoborockException from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from .const import DOMAIN from .coordinator import RoborockConfigEntry, RoborockDataUpdateCoordinator from .entity import RoborockEntityV1 _LOGGER = logging.getLogger(__name__) PARALLEL_UPDATES = 0 @dataclass(frozen=True, kw_only=True) class RoborockSwitchDescription(SwitchEntityDescription): """Class to describe a Roborock switch entity.""" trait: Callable[[PropertiesApi], RoborockSwitchBase | None] # If it is a dock entity is_dock_entity: bool = False SWITCH_DESCRIPTIONS: list[RoborockSwitchDescription] = [ RoborockSwitchDescription( trait=lambda traits: traits.child_lock, key="child_lock", translation_key="child_lock", entity_category=EntityCategory.CONFIG, is_dock_entity=True, ), RoborockSwitchDescription( trait=lambda traits: traits.flow_led_status, key="status_indicator", translation_key="status_indicator", entity_category=EntityCategory.CONFIG, is_dock_entity=True, ), RoborockSwitchDescription( trait=lambda traits: traits.dnd, key="dnd_switch", translation_key="dnd_switch", entity_category=EntityCategory.CONFIG, ), RoborockSwitchDescription( trait=lambda traits: traits.valley_electricity_timer, key="off_peak_switch", translation_key="off_peak_switch", entity_category=EntityCategory.CONFIG, entity_registry_enabled_default=False, ), ] async def async_setup_entry( hass: HomeAssistant, config_entry: RoborockConfigEntry, async_add_entities: AddConfigEntryEntitiesCallback, ) -> None: """Set up Roborock switch platform.""" async_add_entities( [ RoborockSwitch( f"{description.key}_{coordinator.duid_slug}", coordinator, description, trait, ) for coordinator in config_entry.runtime_data.v1 for description in SWITCH_DESCRIPTIONS if (trait := description.trait(coordinator.properties_api)) is not None ] ) class RoborockSwitch(RoborockEntityV1, SwitchEntity): """A class to let you turn functionality on Roborock devices on and off that does need a coordinator.""" entity_description: RoborockSwitchDescription def __init__( self, unique_id: str, coordinator: RoborockDataUpdateCoordinator, entity_description: RoborockSwitchDescription, trait: RoborockSwitchBase, ) -> None: """Initialize the entity.""" self.entity_description = entity_description super().__init__( unique_id, ( coordinator.device_info if not entity_description.is_dock_entity else coordinator.dock_device_info ), coordinator.properties_api.command, ) self._trait = trait async def async_turn_off(self, **kwargs: Any) -> None: """Turn off the switch.""" try: await self._trait.disable() except RoborockException as err: raise HomeAssistantError( translation_domain=DOMAIN, translation_key="update_options_failed", ) from err async def async_turn_on(self, **kwargs: Any) -> None: """Turn on the switch.""" try: await self._trait.enable() except RoborockException as err: raise HomeAssistantError( translation_domain=DOMAIN, translation_key="update_options_failed", ) from err @property def is_on(self) -> bool | None: """Return True if entity is on.""" return self._trait.is_on