core/homeassistant/components/twinkly/light.py

169 lines
6.1 KiB
Python

"""The Twinkly light component."""
from __future__ import annotations
import logging
from typing import Any
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_EFFECT,
ATTR_RGB_COLOR,
ATTR_RGBW_COLOR,
ColorMode,
LightEntity,
LightEntityFeature,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import TwinklyConfigEntry, TwinklyCoordinator
from .const import DEV_LED_PROFILE, DEV_PROFILE_RGB, DEV_PROFILE_RGBW
from .entity import TwinklyEntity
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: TwinklyConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Setups an entity from a config entry (UI config flow)."""
entity = TwinklyLight(config_entry.runtime_data)
async_add_entities([entity], update_before_add=True)
class TwinklyLight(TwinklyEntity, LightEntity):
"""Implementation of the light for the Twinkly service."""
_attr_name = None
_attr_translation_key = "light"
def __init__(self, coordinator: TwinklyCoordinator) -> None:
"""Initialize a TwinklyLight entity."""
super().__init__(coordinator)
device_info = coordinator.data.device_info
self._attr_unique_id = device_info["mac"]
if device_info.get(DEV_LED_PROFILE) == DEV_PROFILE_RGBW:
self._attr_supported_color_modes = {ColorMode.RGBW}
self._attr_color_mode = ColorMode.RGBW
self._attr_rgbw_color = (255, 255, 255, 0)
elif device_info.get(DEV_LED_PROFILE) == DEV_PROFILE_RGB:
self._attr_supported_color_modes = {ColorMode.RGB}
self._attr_color_mode = ColorMode.RGB
self._attr_rgb_color = (255, 255, 255)
else:
self._attr_supported_color_modes = {ColorMode.BRIGHTNESS}
self._attr_color_mode = ColorMode.BRIGHTNESS
self.client = coordinator.client
if coordinator.supports_effects:
self._attr_supported_features = LightEntityFeature.EFFECT
self._update_attr()
@property
def effect(self) -> str | None:
"""Return the current effect."""
if (current_movie_id := self.coordinator.data.current_movie) is not None:
return (
f"{current_movie_id} {self.coordinator.data.movies[current_movie_id]}"
)
return None
@property
def effect_list(self) -> list[str]:
"""Return the list of saved effects."""
return [
f"{identifier} {name}"
for identifier, name in self.coordinator.data.movies.items()
]
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn device on."""
if ATTR_BRIGHTNESS in kwargs:
brightness = int(int(kwargs[ATTR_BRIGHTNESS]) / 2.55)
# If brightness is 0, the twinkly will only "disable" the brightness,
# which means that it will be 100%.
if brightness == 0:
await self.client.turn_off()
return
await self.client.set_brightness(brightness)
if (
ATTR_RGBW_COLOR in kwargs
and kwargs[ATTR_RGBW_COLOR] != self._attr_rgbw_color
):
await self.client.interview()
if LightEntityFeature.EFFECT & self.supported_features:
# Static color only supports rgb
await self.client.set_static_colour(
(
kwargs[ATTR_RGBW_COLOR][0],
kwargs[ATTR_RGBW_COLOR][1],
kwargs[ATTR_RGBW_COLOR][2],
)
)
await self.client.set_mode("color")
self.client.default_mode = "color"
else:
await self.client.set_cycle_colours(
(
kwargs[ATTR_RGBW_COLOR][3],
kwargs[ATTR_RGBW_COLOR][0],
kwargs[ATTR_RGBW_COLOR][1],
kwargs[ATTR_RGBW_COLOR][2],
)
)
await self.client.set_mode("movie")
self.client.default_mode = "movie"
self._attr_rgbw_color = kwargs[ATTR_RGBW_COLOR]
if ATTR_RGB_COLOR in kwargs and kwargs[ATTR_RGB_COLOR] != self._attr_rgb_color:
await self.client.interview()
if LightEntityFeature.EFFECT & self.supported_features:
await self.client.set_static_colour(kwargs[ATTR_RGB_COLOR])
await self.client.set_mode("color")
self.client.default_mode = "color"
else:
await self.client.set_cycle_colours(kwargs[ATTR_RGB_COLOR])
await self.client.set_mode("movie")
self.client.default_mode = "movie"
self._attr_rgb_color = kwargs[ATTR_RGB_COLOR]
if (
ATTR_EFFECT in kwargs
and LightEntityFeature.EFFECT & self.supported_features
):
movie_id = kwargs[ATTR_EFFECT].split(" ")[0]
if (
self.coordinator.data.current_movie is None
or int(movie_id) != self.coordinator.data.current_movie
):
await self.client.interview()
await self.client.set_current_movie(int(movie_id))
await self.client.set_mode("movie")
self.client.default_mode = "movie"
if not self._attr_is_on:
await self.client.turn_on()
await self.coordinator.async_refresh()
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn device off."""
await self.client.turn_off()
await self.coordinator.async_refresh()
def _update_attr(self) -> None:
"""Update the entity attributes."""
self._attr_is_on = self.coordinator.data.is_on
self._attr_brightness = self.coordinator.data.brightness
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
self._update_attr()
super()._handle_coordinator_update()