mirror of https://github.com/home-assistant/core
149 lines
4.6 KiB
Python
149 lines
4.6 KiB
Python
"""Support for EverLights lights."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import timedelta
|
|
import logging
|
|
from typing import Any
|
|
|
|
import pyeverlights
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.components.light import (
|
|
ATTR_BRIGHTNESS,
|
|
ATTR_EFFECT,
|
|
ATTR_HS_COLOR,
|
|
PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA,
|
|
ColorMode,
|
|
LightEntity,
|
|
LightEntityFeature,
|
|
)
|
|
from homeassistant.const import CONF_HOSTS
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import PlatformNotReady
|
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
|
import homeassistant.helpers.config_validation as cv
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
|
import homeassistant.util.color as color_util
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
SCAN_INTERVAL = timedelta(minutes=1)
|
|
|
|
PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA.extend(
|
|
{vol.Required(CONF_HOSTS): vol.All(cv.ensure_list, [cv.string])}
|
|
)
|
|
|
|
|
|
def color_rgb_to_int(red: int, green: int, blue: int) -> int:
|
|
"""Return a RGB color as an integer."""
|
|
return red * 256 * 256 + green * 256 + blue
|
|
|
|
|
|
def color_int_to_rgb(value: int) -> tuple[int, int, int]:
|
|
"""Return an RGB tuple from an integer."""
|
|
return (value >> 16, (value >> 8) & 0xFF, value & 0xFF)
|
|
|
|
|
|
async def async_setup_platform(
|
|
hass: HomeAssistant,
|
|
config: ConfigType,
|
|
async_add_entities: AddEntitiesCallback,
|
|
discovery_info: DiscoveryInfoType | None = None,
|
|
) -> None:
|
|
"""Set up the EverLights lights from configuration.yaml."""
|
|
lights = []
|
|
|
|
for ipaddr in config[CONF_HOSTS]:
|
|
api = pyeverlights.EverLights(ipaddr, async_get_clientsession(hass))
|
|
|
|
try:
|
|
status = await api.get_status()
|
|
|
|
effects = await api.get_all_patterns()
|
|
|
|
except pyeverlights.ConnectionError as err:
|
|
raise PlatformNotReady from err
|
|
|
|
lights.append(EverLightsLight(api, pyeverlights.ZONE_1, status, effects))
|
|
lights.append(EverLightsLight(api, pyeverlights.ZONE_2, status, effects))
|
|
|
|
async_add_entities(lights)
|
|
|
|
|
|
class EverLightsLight(LightEntity):
|
|
"""Representation of a Flux light."""
|
|
|
|
_attr_color_mode = ColorMode.HS
|
|
_attr_supported_color_modes = {ColorMode.HS}
|
|
_attr_supported_features = LightEntityFeature.EFFECT
|
|
|
|
def __init__(
|
|
self,
|
|
api: pyeverlights.EverLights,
|
|
channel: int,
|
|
status: dict[str, Any],
|
|
effects,
|
|
) -> None:
|
|
"""Initialize the light."""
|
|
self._api = api
|
|
self._channel = channel
|
|
self._status = status
|
|
self._attr_effect_list = effects
|
|
self._mac = status["mac"]
|
|
self._error_reported = False
|
|
self._attr_hs_color = (255, 255)
|
|
self._attr_brightness = 255
|
|
|
|
self._attr_name = f"EverLights {self._mac} Zone {self._channel}"
|
|
self._attr_unique_id = f"{self._mac}-{self._channel}"
|
|
|
|
@property
|
|
def is_on(self) -> bool:
|
|
"""Return true if device is on."""
|
|
return self._status[f"ch{self._channel}Active"] == 1
|
|
|
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
|
"""Turn the light on."""
|
|
hs_color = kwargs.get(ATTR_HS_COLOR, self._attr_hs_color)
|
|
brightness = kwargs.get(ATTR_BRIGHTNESS, self._attr_brightness)
|
|
effect = kwargs.get(ATTR_EFFECT)
|
|
|
|
if effect is not None:
|
|
colors = await self._api.set_pattern_by_id(self._channel, effect)
|
|
|
|
rgb = color_int_to_rgb(colors[0])
|
|
hsv = color_util.color_RGB_to_hsv(*rgb)
|
|
hs_color = hsv[:2]
|
|
brightness = hsv[2] / 100 * 255
|
|
|
|
else:
|
|
rgb = color_util.color_hsv_to_RGB(
|
|
hs_color[0], hs_color[1], brightness / 255 * 100
|
|
)
|
|
colors = [color_rgb_to_int(*rgb)]
|
|
|
|
await self._api.set_pattern(self._channel, colors)
|
|
|
|
self._attr_hs_color = hs_color
|
|
self._attr_brightness = brightness
|
|
self._attr_effect = effect
|
|
|
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
|
"""Turn the light off."""
|
|
await self._api.clear_pattern(self._channel)
|
|
|
|
async def async_update(self) -> None:
|
|
"""Synchronize state with control box."""
|
|
try:
|
|
self._status = await self._api.get_status()
|
|
except pyeverlights.ConnectionError:
|
|
if self.available:
|
|
_LOGGER.warning("EverLights control box connection lost")
|
|
self._attr_available = False
|
|
else:
|
|
if not self.available:
|
|
_LOGGER.warning("EverLights control box connection restored")
|
|
self._attr_available = True
|