From b658c053ec0b02de62e7d8c15a4534103e0bdd3a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 9 Jan 2022 17:16:19 -1000 Subject: [PATCH] Add switch platform to SenseME (#63719) --- .coveragerc | 1 + homeassistant/components/senseme/const.py | 2 +- homeassistant/components/senseme/switch.py | 138 +++++++++++++++++++++ 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/senseme/switch.py diff --git a/.coveragerc b/.coveragerc index 888f67ca8c7..6f036bb9449 100644 --- a/.coveragerc +++ b/.coveragerc @@ -955,6 +955,7 @@ omit = homeassistant/components/senseme/discovery.py homeassistant/components/senseme/entity.py homeassistant/components/senseme/fan.py + homeassistant/components/senseme/switch.py homeassistant/components/sensibo/__init__.py homeassistant/components/sensibo/climate.py homeassistant/components/serial/sensor.py diff --git a/homeassistant/components/senseme/const.py b/homeassistant/components/senseme/const.py index 0d21e8ea328..eb7bc64a747 100644 --- a/homeassistant/components/senseme/const.py +++ b/homeassistant/components/senseme/const.py @@ -20,4 +20,4 @@ PRESET_MODE_WHOOSH = "Whoosh" SENSEME_DIRECTION_FORWARD = "FWD" SENSEME_DIRECTION_REVERSE = "REV" -PLATFORMS = [Platform.BINARY_SENSOR, Platform.FAN] +PLATFORMS = [Platform.BINARY_SENSOR, Platform.FAN, Platform.SWITCH] diff --git a/homeassistant/components/senseme/switch.py b/homeassistant/components/senseme/switch.py new file mode 100644 index 00000000000..b1a2038fa87 --- /dev/null +++ b/homeassistant/components/senseme/switch.py @@ -0,0 +1,138 @@ +"""Support for Big Ass Fans SenseME switch.""" +from __future__ import annotations + +from collections.abc import Callable +from dataclasses import dataclass +from typing import Any, cast + +from aiosenseme import SensemeFan +from aiosenseme.device import SensemeDevice + +from homeassistant import config_entries +from homeassistant.components.switch import ( + SwitchDeviceClass, + SwitchEntity, + SwitchEntityDescription, +) +from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import DOMAIN +from .entity import SensemeEntity + + +@dataclass +class SenseMESwitchEntityDescriptionMixin: + """Mixin for required keys.""" + + value_fn: Callable[[SensemeFan], bool] + set_fn: Callable[[SensemeFan, bool], None] + + +@dataclass +class SenseMESwitchEntityDescription( + SwitchEntityDescription, SenseMESwitchEntityDescriptionMixin +): + """Describes SenseME switch entity.""" + + +def _set_sleep_mode(device: SensemeDevice, value: bool) -> None: + device.sleep_mode = value + + +def _set_motion_fan_auto(device: SensemeDevice, value: bool) -> None: + device.motion_fan_auto = value + + +def _set_motion_light_auto(device: SensemeDevice, value: bool) -> None: + device.motion_light_auto = value + + +FAN_SWITCHS = [ + # Turning on sleep mode will disable Whoosh + SenseMESwitchEntityDescription( + key="sleep_mode", + name="Sleep Mode", + value_fn=lambda device: cast(bool, device.sleep_mode), + set_fn=_set_sleep_mode, + ), + SenseMESwitchEntityDescription( + key="motion_fan_auto", + name="Motion", + value_fn=lambda device: cast(bool, device.motion_fan_auto), + set_fn=_set_motion_fan_auto, + ), +] + +FAN_LIGHT_SWITCHES = [ + SenseMESwitchEntityDescription( + key="motion_light_auto", + name="Light Motion", + value_fn=lambda device: cast(bool, device.motion_light_auto), + set_fn=_set_motion_light_auto, + ), +] + +LIGHT_SWITCHES = [ + SenseMESwitchEntityDescription( + key="sleep_mode", + name="Sleep Mode", + value_fn=lambda device: cast(bool, device.sleep_mode), + set_fn=_set_sleep_mode, + ), + SenseMESwitchEntityDescription( + key="motion_light_auto", + name="Motion", + value_fn=lambda device: cast(bool, device.motion_light_auto), + set_fn=_set_motion_light_auto, + ), +] + + +async def async_setup_entry( + hass: HomeAssistant, + entry: config_entries.ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up SenseME fans.""" + device = hass.data[DOMAIN][entry.entry_id] + descriptions: list[SenseMESwitchEntityDescription] = [] + + if device.is_fan: + descriptions.extend(FAN_SWITCHS) + if device.has_light: + descriptions.extend(FAN_LIGHT_SWITCHES) + elif device.is_light: + descriptions.extend(LIGHT_SWITCHES) + + async_add_entities( + [HASensemeSwitch(device, description) for description in descriptions] + ) + + +class HASensemeSwitch(SensemeEntity, SwitchEntity): + """SenseME switch component.""" + + entity_description: SenseMESwitchEntityDescription + + def __init__( + self, device: SensemeFan, description: SenseMESwitchEntityDescription + ) -> None: + """Initialize the entity.""" + self.entity_description = description + self._attr_device_class = SwitchDeviceClass.SWITCH + super().__init__(device, f"{device.name} {description.name}") + self._attr_unique_id = f"{self._device.uuid}-SWITCH-{description.key}" + + @callback + def _async_update_attrs(self) -> None: + """Update attrs from device.""" + self._attr_is_on = self.entity_description.value_fn(self._device) + + async def async_turn_on(self, **kwargs: Any) -> None: + """Turn on the switch.""" + self.entity_description.set_fn(self._device, True) + + async def async_turn_off(self, **kwargs: Any) -> None: + """Turn off the switch.""" + self.entity_description.set_fn(self._device, False)