2019-11-06 22:55:39 +00:00
|
|
|
"""Support for LED lights."""
|
2021-03-18 14:08:35 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2020-06-03 15:18:50 +00:00
|
|
|
from functools import partial
|
2021-06-09 11:31:31 +00:00
|
|
|
from typing import Any, Tuple, cast
|
2020-03-23 20:21:35 +00:00
|
|
|
|
|
|
|
import voluptuous as vol
|
2019-11-06 22:55:39 +00:00
|
|
|
|
|
|
|
from homeassistant.components.light import (
|
|
|
|
ATTR_BRIGHTNESS,
|
|
|
|
ATTR_EFFECT,
|
2021-06-09 11:31:31 +00:00
|
|
|
ATTR_RGB_COLOR,
|
|
|
|
ATTR_RGBW_COLOR,
|
2019-11-06 22:55:39 +00:00
|
|
|
ATTR_TRANSITION,
|
2021-06-09 11:31:31 +00:00
|
|
|
COLOR_MODE_BRIGHTNESS,
|
|
|
|
COLOR_MODE_RGB,
|
|
|
|
COLOR_MODE_RGBW,
|
2019-11-06 22:55:39 +00:00
|
|
|
SUPPORT_EFFECT,
|
|
|
|
SUPPORT_TRANSITION,
|
2020-04-26 16:49:41 +00:00
|
|
|
LightEntity,
|
2019-11-06 22:55:39 +00:00
|
|
|
)
|
|
|
|
from homeassistant.config_entries import ConfigEntry
|
2021-04-22 15:04:28 +00:00
|
|
|
from homeassistant.core import HomeAssistant, callback
|
2020-03-23 20:21:35 +00:00
|
|
|
from homeassistant.helpers import config_validation as cv, entity_platform
|
2021-04-30 18:38:59 +00:00
|
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
2020-06-03 15:18:50 +00:00
|
|
|
from homeassistant.helpers.entity_registry import (
|
|
|
|
async_get_registry as async_get_entity_registry,
|
|
|
|
)
|
2019-11-06 22:55:39 +00:00
|
|
|
|
2021-05-26 12:08:09 +00:00
|
|
|
from . import WLEDDataUpdateCoordinator, WLEDEntity, wled_exception_handler
|
2019-11-06 22:55:39 +00:00
|
|
|
from .const import (
|
|
|
|
ATTR_COLOR_PRIMARY,
|
|
|
|
ATTR_INTENSITY,
|
|
|
|
ATTR_ON,
|
|
|
|
ATTR_PALETTE,
|
|
|
|
ATTR_PLAYLIST,
|
|
|
|
ATTR_PRESET,
|
2020-03-23 20:21:35 +00:00
|
|
|
ATTR_REVERSE,
|
2019-11-06 22:55:39 +00:00
|
|
|
ATTR_SEGMENT_ID,
|
|
|
|
ATTR_SPEED,
|
|
|
|
DOMAIN,
|
2020-03-23 20:21:35 +00:00
|
|
|
SERVICE_EFFECT,
|
2020-10-25 11:44:26 +00:00
|
|
|
SERVICE_PRESET,
|
2019-11-06 22:55:39 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
PARALLEL_UPDATES = 1
|
|
|
|
|
|
|
|
|
|
|
|
async def async_setup_entry(
|
2021-04-22 15:04:28 +00:00
|
|
|
hass: HomeAssistant,
|
2019-11-06 22:55:39 +00:00
|
|
|
entry: ConfigEntry,
|
2021-04-30 18:38:59 +00:00
|
|
|
async_add_entities: AddEntitiesCallback,
|
2019-11-06 22:55:39 +00:00
|
|
|
) -> None:
|
|
|
|
"""Set up WLED light based on a config entry."""
|
2020-03-13 12:19:05 +00:00
|
|
|
coordinator: WLEDDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
2019-11-06 22:55:39 +00:00
|
|
|
|
2021-05-03 14:46:42 +00:00
|
|
|
platform = entity_platform.async_get_current_platform()
|
2021-05-09 17:34:21 +00:00
|
|
|
|
2020-03-23 20:21:35 +00:00
|
|
|
platform.async_register_entity_service(
|
|
|
|
SERVICE_EFFECT,
|
|
|
|
{
|
|
|
|
vol.Optional(ATTR_EFFECT): vol.Any(cv.positive_int, cv.string),
|
|
|
|
vol.Optional(ATTR_INTENSITY): vol.All(
|
|
|
|
vol.Coerce(int), vol.Range(min=0, max=255)
|
|
|
|
),
|
2020-10-13 12:12:01 +00:00
|
|
|
vol.Optional(ATTR_PALETTE): vol.Any(cv.positive_int, cv.string),
|
2020-03-23 20:21:35 +00:00
|
|
|
vol.Optional(ATTR_REVERSE): cv.boolean,
|
|
|
|
vol.Optional(ATTR_SPEED): vol.All(
|
|
|
|
vol.Coerce(int), vol.Range(min=0, max=255)
|
|
|
|
),
|
|
|
|
},
|
|
|
|
"async_effect",
|
|
|
|
)
|
|
|
|
|
2020-10-25 11:44:26 +00:00
|
|
|
platform.async_register_entity_service(
|
|
|
|
SERVICE_PRESET,
|
|
|
|
{
|
|
|
|
vol.Required(ATTR_PRESET): vol.All(
|
|
|
|
vol.Coerce(int), vol.Range(min=-1, max=65535)
|
|
|
|
),
|
|
|
|
},
|
|
|
|
"async_preset",
|
|
|
|
)
|
|
|
|
|
2020-06-03 15:18:50 +00:00
|
|
|
update_segments = partial(
|
|
|
|
async_update_segments, entry, coordinator, {}, async_add_entities
|
|
|
|
)
|
2019-11-06 22:55:39 +00:00
|
|
|
|
2020-06-03 15:18:50 +00:00
|
|
|
coordinator.async_add_listener(update_segments)
|
|
|
|
update_segments()
|
2019-11-06 22:55:39 +00:00
|
|
|
|
|
|
|
|
2021-05-26 12:08:09 +00:00
|
|
|
class WLEDMasterLight(WLEDEntity, LightEntity):
|
2020-06-07 21:37:58 +00:00
|
|
|
"""Defines a WLED master light."""
|
|
|
|
|
2021-06-09 11:31:31 +00:00
|
|
|
_attr_color_mode = COLOR_MODE_BRIGHTNESS
|
2021-05-26 12:08:09 +00:00
|
|
|
_attr_icon = "mdi:led-strip-variant"
|
2021-06-09 11:31:31 +00:00
|
|
|
_attr_supported_features = SUPPORT_TRANSITION
|
2020-06-07 21:37:58 +00:00
|
|
|
|
2021-05-26 12:08:09 +00:00
|
|
|
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
|
|
|
|
"""Initialize WLED master light."""
|
|
|
|
super().__init__(coordinator=coordinator)
|
|
|
|
self._attr_name = f"{coordinator.data.info.name} Master"
|
|
|
|
self._attr_unique_id = coordinator.data.info.mac_address
|
2021-06-09 11:31:31 +00:00
|
|
|
self._attr_supported_color_modes = {COLOR_MODE_BRIGHTNESS}
|
2020-06-07 21:37:58 +00:00
|
|
|
|
|
|
|
@property
|
2021-03-18 14:08:35 +00:00
|
|
|
def brightness(self) -> int | None:
|
2020-06-07 21:37:58 +00:00
|
|
|
"""Return the brightness of this light between 1..255."""
|
|
|
|
return self.coordinator.data.state.brightness
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_on(self) -> bool:
|
|
|
|
"""Return the state of the light."""
|
|
|
|
return bool(self.coordinator.data.state.on)
|
|
|
|
|
|
|
|
@wled_exception_handler
|
|
|
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
|
|
|
"""Turn off the light."""
|
2021-05-09 17:34:21 +00:00
|
|
|
data: dict[str, bool | int] = {ATTR_ON: False}
|
2020-06-07 21:37:58 +00:00
|
|
|
|
|
|
|
if ATTR_TRANSITION in kwargs:
|
|
|
|
# WLED uses 100ms per unit, so 10 = 1 second.
|
|
|
|
data[ATTR_TRANSITION] = round(kwargs[ATTR_TRANSITION] * 10)
|
|
|
|
|
2021-06-08 20:38:20 +00:00
|
|
|
await self.coordinator.wled.master(**data) # type: ignore[arg-type]
|
2020-06-07 21:37:58 +00:00
|
|
|
|
|
|
|
@wled_exception_handler
|
|
|
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
|
|
|
"""Turn on the light."""
|
2021-05-09 17:34:21 +00:00
|
|
|
data: dict[str, bool | int] = {ATTR_ON: True}
|
2020-06-07 21:37:58 +00:00
|
|
|
|
|
|
|
if ATTR_TRANSITION in kwargs:
|
|
|
|
# WLED uses 100ms per unit, so 10 = 1 second.
|
|
|
|
data[ATTR_TRANSITION] = round(kwargs[ATTR_TRANSITION] * 10)
|
|
|
|
|
|
|
|
if ATTR_BRIGHTNESS in kwargs:
|
|
|
|
data[ATTR_BRIGHTNESS] = kwargs[ATTR_BRIGHTNESS]
|
|
|
|
|
2021-06-08 20:38:20 +00:00
|
|
|
await self.coordinator.wled.master(**data) # type: ignore[arg-type]
|
2020-06-07 21:37:58 +00:00
|
|
|
|
2021-03-27 12:04:30 +00:00
|
|
|
async def async_effect(
|
|
|
|
self,
|
|
|
|
effect: int | str | None = None,
|
|
|
|
intensity: int | None = None,
|
|
|
|
palette: int | str | None = None,
|
|
|
|
reverse: bool | None = None,
|
|
|
|
speed: int | None = None,
|
|
|
|
) -> None:
|
|
|
|
"""Set the effect of a WLED light."""
|
|
|
|
# Master light does not have an effect setting.
|
|
|
|
|
|
|
|
@wled_exception_handler
|
|
|
|
async def async_preset(
|
|
|
|
self,
|
|
|
|
preset: int,
|
|
|
|
) -> None:
|
|
|
|
"""Set a WLED light to a saved preset."""
|
|
|
|
data = {ATTR_PRESET: preset}
|
|
|
|
|
|
|
|
await self.coordinator.wled.preset(**data)
|
|
|
|
|
2020-06-07 21:37:58 +00:00
|
|
|
|
2021-05-26 12:08:09 +00:00
|
|
|
class WLEDSegmentLight(WLEDEntity, LightEntity):
|
2020-06-07 21:37:58 +00:00
|
|
|
"""Defines a WLED light based on a segment."""
|
2019-11-06 22:55:39 +00:00
|
|
|
|
2021-06-09 11:31:31 +00:00
|
|
|
_attr_supported_features = SUPPORT_EFFECT | SUPPORT_TRANSITION
|
2021-05-26 12:08:09 +00:00
|
|
|
_attr_icon = "mdi:led-strip-variant"
|
|
|
|
|
|
|
|
def __init__(self, coordinator: WLEDDataUpdateCoordinator, segment: int) -> None:
|
2020-06-07 21:37:58 +00:00
|
|
|
"""Initialize WLED segment light."""
|
2021-05-26 12:08:09 +00:00
|
|
|
super().__init__(coordinator=coordinator)
|
2020-03-13 12:19:05 +00:00
|
|
|
self._rgbw = coordinator.data.info.leds.rgbw
|
2021-06-09 11:31:31 +00:00
|
|
|
self._wv = coordinator.data.info.leds.wv
|
2019-11-06 22:55:39 +00:00
|
|
|
self._segment = segment
|
|
|
|
|
2020-06-07 21:37:58 +00:00
|
|
|
# If this is the one and only segment, use a simpler name
|
2021-05-26 12:08:09 +00:00
|
|
|
self._attr_name = f"{coordinator.data.info.name} Segment {segment}"
|
2020-06-07 21:37:58 +00:00
|
|
|
if len(coordinator.data.state.segments) == 1:
|
2021-05-26 12:08:09 +00:00
|
|
|
self._attr_name = coordinator.data.info.name
|
2019-11-06 22:55:39 +00:00
|
|
|
|
2021-05-26 12:08:09 +00:00
|
|
|
self._attr_unique_id = (
|
|
|
|
f"{self.coordinator.data.info.mac_address}_{self._segment}"
|
2020-03-13 12:19:05 +00:00
|
|
|
)
|
2019-11-06 22:55:39 +00:00
|
|
|
|
2021-06-09 11:31:31 +00:00
|
|
|
self._attr_color_mode = COLOR_MODE_RGB
|
|
|
|
self._attr_supported_color_modes = {COLOR_MODE_RGB}
|
|
|
|
if self._rgbw and self._wv:
|
|
|
|
self._attr_color_mode = COLOR_MODE_RGBW
|
|
|
|
self._attr_supported_color_modes = {COLOR_MODE_RGBW}
|
|
|
|
|
2020-06-03 15:18:50 +00:00
|
|
|
@property
|
|
|
|
def available(self) -> bool:
|
|
|
|
"""Return True if entity is available."""
|
|
|
|
try:
|
|
|
|
self.coordinator.data.state.segments[self._segment]
|
|
|
|
except IndexError:
|
|
|
|
return False
|
|
|
|
|
|
|
|
return super().available
|
|
|
|
|
2020-03-13 12:19:05 +00:00
|
|
|
@property
|
2021-03-18 14:08:35 +00:00
|
|
|
def extra_state_attributes(self) -> dict[str, Any] | None:
|
2020-03-13 12:19:05 +00:00
|
|
|
"""Return the state attributes of the entity."""
|
2021-06-08 20:38:20 +00:00
|
|
|
playlist: int | None = self.coordinator.data.state.playlist
|
2020-03-13 12:19:05 +00:00
|
|
|
if playlist == -1:
|
|
|
|
playlist = None
|
|
|
|
|
2021-06-08 20:38:20 +00:00
|
|
|
preset: int | None = self.coordinator.data.state.preset
|
2020-03-13 12:19:05 +00:00
|
|
|
if preset == -1:
|
|
|
|
preset = None
|
|
|
|
|
2020-03-23 20:21:35 +00:00
|
|
|
segment = self.coordinator.data.state.segments[self._segment]
|
2020-03-13 12:19:05 +00:00
|
|
|
return {
|
2020-03-23 20:21:35 +00:00
|
|
|
ATTR_INTENSITY: segment.intensity,
|
|
|
|
ATTR_PALETTE: segment.palette.name,
|
2020-03-13 12:19:05 +00:00
|
|
|
ATTR_PLAYLIST: playlist,
|
|
|
|
ATTR_PRESET: preset,
|
2020-03-23 20:21:35 +00:00
|
|
|
ATTR_REVERSE: segment.reverse,
|
|
|
|
ATTR_SPEED: segment.speed,
|
2020-03-13 12:19:05 +00:00
|
|
|
}
|
2019-11-06 22:55:39 +00:00
|
|
|
|
|
|
|
@property
|
2021-06-09 11:31:31 +00:00
|
|
|
def rgb_color(self) -> tuple[int, int, int] | None:
|
|
|
|
"""Return the color value."""
|
|
|
|
return self.coordinator.data.state.segments[self._segment].color_primary[:3]
|
|
|
|
|
|
|
|
@property
|
|
|
|
def rgbw_color(self) -> tuple[int, int, int, int] | None:
|
|
|
|
"""Return the color value."""
|
|
|
|
return cast(
|
|
|
|
Tuple[int, int, int, int],
|
|
|
|
self.coordinator.data.state.segments[self._segment].color_primary,
|
|
|
|
)
|
2019-11-06 22:55:39 +00:00
|
|
|
|
|
|
|
@property
|
2021-03-18 14:08:35 +00:00
|
|
|
def effect(self) -> str | None:
|
2019-11-06 22:55:39 +00:00
|
|
|
"""Return the current effect of the light."""
|
2020-03-13 12:19:05 +00:00
|
|
|
return self.coordinator.data.state.segments[self._segment].effect.name
|
2019-11-06 22:55:39 +00:00
|
|
|
|
|
|
|
@property
|
2021-03-18 14:08:35 +00:00
|
|
|
def brightness(self) -> int | None:
|
2019-11-06 22:55:39 +00:00
|
|
|
"""Return the brightness of this light between 1..255."""
|
2020-06-07 21:37:58 +00:00
|
|
|
state = self.coordinator.data.state
|
|
|
|
|
|
|
|
# If this is the one and only segment, calculate brightness based
|
|
|
|
# on the master and segment brightness
|
|
|
|
if len(state.segments) == 1:
|
|
|
|
return int(
|
|
|
|
(state.segments[self._segment].brightness * state.brightness) / 255
|
|
|
|
)
|
|
|
|
|
|
|
|
return state.segments[self._segment].brightness
|
2019-11-06 22:55:39 +00:00
|
|
|
|
|
|
|
@property
|
2021-03-18 14:08:35 +00:00
|
|
|
def effect_list(self) -> list[str]:
|
2019-11-06 22:55:39 +00:00
|
|
|
"""Return the list of supported effects."""
|
2020-03-13 12:19:05 +00:00
|
|
|
return [effect.name for effect in self.coordinator.data.effects]
|
2019-11-06 22:55:39 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def is_on(self) -> bool:
|
|
|
|
"""Return the state of the light."""
|
2020-06-07 21:37:58 +00:00
|
|
|
state = self.coordinator.data.state
|
|
|
|
|
|
|
|
# If there is a single segment, take master into account
|
|
|
|
if len(state.segments) == 1 and not state.on:
|
|
|
|
return False
|
|
|
|
|
|
|
|
return bool(state.segments[self._segment].on)
|
2019-11-06 22:55:39 +00:00
|
|
|
|
2020-03-13 12:19:05 +00:00
|
|
|
@wled_exception_handler
|
2019-11-06 22:55:39 +00:00
|
|
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
|
|
|
"""Turn off the light."""
|
2021-05-09 17:34:21 +00:00
|
|
|
data: dict[str, bool | int] = {ATTR_ON: False}
|
2020-01-04 21:44:28 +00:00
|
|
|
|
|
|
|
if ATTR_TRANSITION in kwargs:
|
2020-01-08 20:03:36 +00:00
|
|
|
# WLED uses 100ms per unit, so 10 = 1 second.
|
|
|
|
data[ATTR_TRANSITION] = round(kwargs[ATTR_TRANSITION] * 10)
|
2020-01-04 21:44:28 +00:00
|
|
|
|
2020-06-07 21:37:58 +00:00
|
|
|
# If there is a single segment, control via the master
|
|
|
|
if len(self.coordinator.data.state.segments) == 1:
|
2021-06-08 20:38:20 +00:00
|
|
|
await self.coordinator.wled.master(**data) # type: ignore[arg-type]
|
2020-06-07 21:37:58 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
data[ATTR_SEGMENT_ID] = self._segment
|
2021-06-08 20:38:20 +00:00
|
|
|
await self.coordinator.wled.segment(**data) # type: ignore[arg-type]
|
2019-11-06 22:55:39 +00:00
|
|
|
|
2020-03-13 12:19:05 +00:00
|
|
|
@wled_exception_handler
|
2019-11-06 22:55:39 +00:00
|
|
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
|
|
|
"""Turn on the light."""
|
2021-05-09 17:34:21 +00:00
|
|
|
data: dict[str, Any] = {
|
|
|
|
ATTR_ON: True,
|
|
|
|
ATTR_SEGMENT_ID: self._segment,
|
|
|
|
}
|
2019-11-06 22:55:39 +00:00
|
|
|
|
2021-06-09 11:31:31 +00:00
|
|
|
if ATTR_RGB_COLOR in kwargs:
|
|
|
|
data[ATTR_COLOR_PRIMARY] = kwargs[ATTR_RGB_COLOR]
|
2019-11-06 22:55:39 +00:00
|
|
|
|
2021-06-09 11:31:31 +00:00
|
|
|
if ATTR_RGBW_COLOR in kwargs:
|
|
|
|
data[ATTR_COLOR_PRIMARY] = kwargs[ATTR_RGBW_COLOR]
|
2019-11-06 22:55:39 +00:00
|
|
|
|
|
|
|
if ATTR_TRANSITION in kwargs:
|
2020-01-08 20:03:36 +00:00
|
|
|
# WLED uses 100ms per unit, so 10 = 1 second.
|
|
|
|
data[ATTR_TRANSITION] = round(kwargs[ATTR_TRANSITION] * 10)
|
2019-11-06 22:55:39 +00:00
|
|
|
|
|
|
|
if ATTR_BRIGHTNESS in kwargs:
|
|
|
|
data[ATTR_BRIGHTNESS] = kwargs[ATTR_BRIGHTNESS]
|
|
|
|
|
|
|
|
if ATTR_EFFECT in kwargs:
|
|
|
|
data[ATTR_EFFECT] = kwargs[ATTR_EFFECT]
|
|
|
|
|
2020-06-07 21:37:58 +00:00
|
|
|
# When only 1 segment is present, switch along the master, and use
|
|
|
|
# the master for power/brightness control.
|
|
|
|
if len(self.coordinator.data.state.segments) == 1:
|
|
|
|
master_data = {ATTR_ON: True}
|
|
|
|
if ATTR_BRIGHTNESS in data:
|
|
|
|
master_data[ATTR_BRIGHTNESS] = data[ATTR_BRIGHTNESS]
|
|
|
|
data[ATTR_BRIGHTNESS] = 255
|
|
|
|
|
|
|
|
if ATTR_TRANSITION in data:
|
|
|
|
master_data[ATTR_TRANSITION] = data[ATTR_TRANSITION]
|
|
|
|
del data[ATTR_TRANSITION]
|
|
|
|
|
|
|
|
await self.coordinator.wled.segment(**data)
|
|
|
|
await self.coordinator.wled.master(**master_data)
|
|
|
|
return
|
|
|
|
|
|
|
|
await self.coordinator.wled.segment(**data)
|
2020-03-23 20:21:35 +00:00
|
|
|
|
|
|
|
@wled_exception_handler
|
|
|
|
async def async_effect(
|
|
|
|
self,
|
2021-03-18 14:08:35 +00:00
|
|
|
effect: int | str | None = None,
|
|
|
|
intensity: int | None = None,
|
|
|
|
palette: int | str | None = None,
|
|
|
|
reverse: bool | None = None,
|
|
|
|
speed: int | None = None,
|
2020-03-23 20:21:35 +00:00
|
|
|
) -> None:
|
|
|
|
"""Set the effect of a WLED light."""
|
2021-05-09 17:34:21 +00:00
|
|
|
data: dict[str, bool | int | str | None] = {ATTR_SEGMENT_ID: self._segment}
|
2020-03-23 20:21:35 +00:00
|
|
|
|
|
|
|
if effect is not None:
|
|
|
|
data[ATTR_EFFECT] = effect
|
|
|
|
|
|
|
|
if intensity is not None:
|
|
|
|
data[ATTR_INTENSITY] = intensity
|
|
|
|
|
2020-10-13 12:12:01 +00:00
|
|
|
if palette is not None:
|
|
|
|
data[ATTR_PALETTE] = palette
|
|
|
|
|
2020-03-23 20:21:35 +00:00
|
|
|
if reverse is not None:
|
|
|
|
data[ATTR_REVERSE] = reverse
|
|
|
|
|
|
|
|
if speed is not None:
|
|
|
|
data[ATTR_SPEED] = speed
|
|
|
|
|
2021-06-08 20:38:20 +00:00
|
|
|
await self.coordinator.wled.segment(**data) # type: ignore[arg-type]
|
2020-06-03 15:18:50 +00:00
|
|
|
|
2020-10-25 11:44:26 +00:00
|
|
|
@wled_exception_handler
|
|
|
|
async def async_preset(
|
|
|
|
self,
|
|
|
|
preset: int,
|
|
|
|
) -> None:
|
|
|
|
"""Set a WLED light to a saved preset."""
|
|
|
|
data = {ATTR_PRESET: preset}
|
|
|
|
|
|
|
|
await self.coordinator.wled.preset(**data)
|
|
|
|
|
2020-06-03 15:18:50 +00:00
|
|
|
|
|
|
|
@callback
|
|
|
|
def async_update_segments(
|
|
|
|
entry: ConfigEntry,
|
|
|
|
coordinator: WLEDDataUpdateCoordinator,
|
2021-05-09 17:34:21 +00:00
|
|
|
current: dict[int, WLEDSegmentLight | WLEDMasterLight],
|
2020-06-03 15:18:50 +00:00
|
|
|
async_add_entities,
|
|
|
|
) -> None:
|
|
|
|
"""Update segments."""
|
|
|
|
segment_ids = {light.segment_id for light in coordinator.data.state.segments}
|
|
|
|
current_ids = set(current)
|
|
|
|
|
2020-06-07 21:37:58 +00:00
|
|
|
# Discard master (if present)
|
|
|
|
current_ids.discard(-1)
|
|
|
|
|
2020-06-03 15:18:50 +00:00
|
|
|
# Process new segments, add them to Home Assistant
|
2020-06-07 21:37:58 +00:00
|
|
|
new_entities = []
|
2020-06-03 15:18:50 +00:00
|
|
|
for segment_id in segment_ids - current_ids:
|
2021-05-26 12:08:09 +00:00
|
|
|
current[segment_id] = WLEDSegmentLight(coordinator, segment_id)
|
2020-06-07 21:37:58 +00:00
|
|
|
new_entities.append(current[segment_id])
|
2020-06-03 15:18:50 +00:00
|
|
|
|
2020-06-07 21:37:58 +00:00
|
|
|
# More than 1 segment now? Add master controls
|
|
|
|
if len(current_ids) < 2 and len(segment_ids) > 1:
|
2021-05-26 12:08:09 +00:00
|
|
|
current[-1] = WLEDMasterLight(coordinator)
|
2020-06-07 21:37:58 +00:00
|
|
|
new_entities.append(current[-1])
|
|
|
|
|
|
|
|
if new_entities:
|
|
|
|
async_add_entities(new_entities)
|
2020-06-03 15:18:50 +00:00
|
|
|
|
|
|
|
# Process deleted segments, remove them from Home Assistant
|
|
|
|
for segment_id in current_ids - segment_ids:
|
|
|
|
coordinator.hass.async_create_task(
|
2020-06-07 21:37:58 +00:00
|
|
|
async_remove_entity(segment_id, coordinator, current)
|
|
|
|
)
|
|
|
|
|
|
|
|
# Remove master if there is only 1 segment left
|
|
|
|
if len(current_ids) > 1 and len(segment_ids) < 2:
|
|
|
|
coordinator.hass.async_create_task(
|
|
|
|
async_remove_entity(-1, coordinator, current)
|
2020-06-03 15:18:50 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2020-06-07 21:37:58 +00:00
|
|
|
async def async_remove_entity(
|
|
|
|
index: int,
|
2020-06-03 15:18:50 +00:00
|
|
|
coordinator: WLEDDataUpdateCoordinator,
|
2021-05-09 17:34:21 +00:00
|
|
|
current: dict[int, WLEDSegmentLight | WLEDMasterLight],
|
2020-06-03 15:18:50 +00:00
|
|
|
) -> None:
|
|
|
|
"""Remove WLED segment light from Home Assistant."""
|
2020-06-07 21:37:58 +00:00
|
|
|
entity = current[index]
|
2021-02-08 09:45:46 +00:00
|
|
|
await entity.async_remove(force_remove=True)
|
2020-06-03 15:18:50 +00:00
|
|
|
registry = await async_get_entity_registry(coordinator.hass)
|
|
|
|
if entity.entity_id in registry.entities:
|
|
|
|
registry.async_remove(entity.entity_id)
|
2020-06-07 21:37:58 +00:00
|
|
|
del current[index]
|