From cf6fb7bf3991bbcdbbcd85ca3821506cac449459 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Mon, 27 Dec 2021 03:35:59 -0800 Subject: [PATCH] Add light entity to Overkiz integration (#62835) --- .coveragerc | 1 + homeassistant/components/overkiz/const.py | 2 + homeassistant/components/overkiz/light.py | 109 ++++++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 homeassistant/components/overkiz/light.py diff --git a/.coveragerc b/.coveragerc index 2113ea0c202..f409745475f 100644 --- a/.coveragerc +++ b/.coveragerc @@ -807,6 +807,7 @@ omit = homeassistant/components/overkiz/coordinator.py homeassistant/components/overkiz/entity.py homeassistant/components/overkiz/executor.py + homeassistant/components/overkiz/light.py homeassistant/components/overkiz/lock.py homeassistant/components/overkiz/number.py homeassistant/components/overkiz/sensor.py diff --git a/homeassistant/components/overkiz/const.py b/homeassistant/components/overkiz/const.py index f1d1d0fdb74..543cd1e187a 100644 --- a/homeassistant/components/overkiz/const.py +++ b/homeassistant/components/overkiz/const.py @@ -19,6 +19,7 @@ UPDATE_INTERVAL_ALL_ASSUMED_STATE: Final = timedelta(minutes=60) PLATFORMS: list[Platform] = [ Platform.BUTTON, + Platform.LIGHT, Platform.LOCK, Platform.NUMBER, Platform.SENSOR, @@ -32,4 +33,5 @@ IGNORED_OVERKIZ_DEVICES: list[UIClass | UIWidget] = [ # Used to map the Somfy widget and ui_class to the Home Assistant platform OVERKIZ_DEVICE_TO_PLATFORM: dict[UIClass | UIWidget, Platform] = { UIClass.DOOR_LOCK: Platform.LOCK, + UIClass.LIGHT: Platform.LIGHT, } diff --git a/homeassistant/components/overkiz/light.py b/homeassistant/components/overkiz/light.py new file mode 100644 index 00000000000..63510f67567 --- /dev/null +++ b/homeassistant/components/overkiz/light.py @@ -0,0 +1,109 @@ +"""Support for Overkiz lights.""" +from __future__ import annotations + +from typing import Any + +from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState + +from homeassistant.components.light import ( + ATTR_BRIGHTNESS, + ATTR_RGB_COLOR, + COLOR_MODE_BRIGHTNESS, + COLOR_MODE_ONOFF, + COLOR_MODE_RGB, + LightEntity, +) +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 .coordinator import OverkizDataUpdateCoordinator +from .entity import OverkizEntity + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +): + """Set up the Overkiz lights from a config entry.""" + data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id] + + async_add_entities( + OverkizLight(device.device_url, data.coordinator) + for device in data.platforms[Platform.LIGHT] + ) + + +class OverkizLight(OverkizEntity, LightEntity): + """Representation of an Overkiz Light.""" + + def __init__( + self, device_url: str, coordinator: OverkizDataUpdateCoordinator + ) -> None: + """Initialize a device.""" + super().__init__(device_url, coordinator) + + self._attr_supported_color_modes = set() + + if self.executor.has_command(OverkizCommand.SET_RGB): + self._attr_supported_color_modes.add(COLOR_MODE_RGB) + if self.executor.has_command(OverkizCommand.SET_INTENSITY): + self._attr_supported_color_modes.add(COLOR_MODE_BRIGHTNESS) + if not self.supported_color_modes: + self._attr_supported_color_modes = {COLOR_MODE_ONOFF} + + @property + def is_on(self) -> bool: + """Return true if light is on.""" + return ( + self.executor.select_state(OverkizState.CORE_ON_OFF) + == OverkizCommandParam.ON + ) + + @property + def rgb_color(self) -> tuple[int, int, int] | None: + """Return the rgb color value [int, int, int] (0-255).""" + red = self.executor.select_state(OverkizState.CORE_RED_COLOR_INTENSITY) + green = self.executor.select_state(OverkizState.CORE_GREEN_COLOR_INTENSITY) + blue = self.executor.select_state(OverkizState.CORE_BLUE_COLOR_INTENSITY) + + if red is None or green is None or blue is None: + return None + + return (int(red), int(green), int(blue)) + + @property + def brightness(self) -> int | None: + """Return the brightness of this light (0-255).""" + if brightness := self.executor.select_state(OverkizState.CORE_LIGHT_INTENSITY): + return round(int(brightness) * 255 / 100) + + return None + + async def async_turn_on(self, **kwargs: Any) -> None: + """Turn the light on.""" + rgb_color = kwargs.get(ATTR_RGB_COLOR) + brightness = kwargs.get(ATTR_BRIGHTNESS) + + if rgb_color is not None: + await self.executor.async_execute_command( + OverkizCommand.SET_RGB, + *[round(float(c)) for c in kwargs[ATTR_RGB_COLOR]], + ) + return + + if brightness is not None: + await self.executor.async_execute_command( + OverkizCommand.SET_INTENSITY, round(float(brightness) / 255 * 100) + ) + return + + await self.executor.async_execute_command(OverkizCommand.ON) + + async def async_turn_off(self, **kwargs: Any) -> None: + """Turn the light off.""" + await self.executor.async_execute_command(OverkizCommand.OFF)