Files
core/homeassistant/components/twinkly/light.py
T

186 lines
6.6 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.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import TwinklyConfigEntry, TwinklyCoordinator
from .const import (
DEV_LED_PROFILE,
DEV_MODEL,
DEV_NAME,
DEV_PROFILE_RGB,
DEV_PROFILE_RGBW,
DOMAIN,
)
_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(CoordinatorEntity[TwinklyCoordinator], LightEntity):
"""Implementation of the light for the Twinkly service."""
_attr_has_entity_name = True
_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 = mac = 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
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, mac)},
connections={(CONNECTION_NETWORK_MAC, mac)},
manufacturer="LEDWORKS",
model=device_info[DEV_MODEL],
name=device_info[DEV_NAME],
sw_version=coordinator.software_version,
)
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()