core/homeassistant/components/wled/select.py

211 lines
6.7 KiB
Python

"""Support for LED selects."""
from __future__ import annotations
from functools import partial
from wled import LiveDataOverride
from homeassistant.components.select import SelectEntity
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import WLEDConfigEntry
from .coordinator import WLEDDataUpdateCoordinator
from .entity import WLEDEntity
from .helpers import wled_exception_handler
PARALLEL_UPDATES = 1
async def async_setup_entry(
hass: HomeAssistant,
entry: WLEDConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up WLED select based on a config entry."""
coordinator = entry.runtime_data
async_add_entities(
[
WLEDLiveOverrideSelect(coordinator),
WLEDPlaylistSelect(coordinator),
WLEDPresetSelect(coordinator),
]
)
update_segments = partial(
async_update_segments,
coordinator,
set(),
async_add_entities,
)
coordinator.async_add_listener(update_segments)
update_segments()
class WLEDLiveOverrideSelect(WLEDEntity, SelectEntity):
"""Defined a WLED Live Override select."""
_attr_entity_category = EntityCategory.CONFIG
_attr_translation_key = "live_override"
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
"""Initialize WLED ."""
super().__init__(coordinator=coordinator)
self._attr_unique_id = f"{coordinator.data.info.mac_address}_live_override"
self._attr_options = [str(live.value) for live in LiveDataOverride]
@property
def current_option(self) -> str:
"""Return the current selected live override."""
return str(self.coordinator.data.state.live_data_override.value)
@wled_exception_handler
async def async_select_option(self, option: str) -> None:
"""Set WLED state to the selected live override state."""
await self.coordinator.wled.live(live=LiveDataOverride(int(option)))
class WLEDPresetSelect(WLEDEntity, SelectEntity):
"""Defined a WLED Preset select."""
_attr_translation_key = "preset"
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
"""Initialize WLED ."""
super().__init__(coordinator=coordinator)
self._attr_unique_id = f"{coordinator.data.info.mac_address}_preset"
self._attr_options = [
preset.name for preset in self.coordinator.data.presets.values()
]
@property
def available(self) -> bool:
"""Return True if entity is available."""
return len(self.coordinator.data.presets) > 0 and super().available
@property
def current_option(self) -> str | None:
"""Return the current selected preset."""
if not self.coordinator.data.state.preset_id:
return None
if preset := self.coordinator.data.presets.get(
self.coordinator.data.state.preset_id
):
return preset.name
return None
@wled_exception_handler
async def async_select_option(self, option: str) -> None:
"""Set WLED segment to the selected preset."""
await self.coordinator.wled.preset(preset=option)
class WLEDPlaylistSelect(WLEDEntity, SelectEntity):
"""Define a WLED Playlist select."""
_attr_translation_key = "playlist"
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
"""Initialize WLED playlist."""
super().__init__(coordinator=coordinator)
self._attr_unique_id = f"{coordinator.data.info.mac_address}_playlist"
self._attr_options = [
playlist.name for playlist in self.coordinator.data.playlists.values()
]
@property
def available(self) -> bool:
"""Return True if entity is available."""
return len(self.coordinator.data.playlists) > 0 and super().available
@property
def current_option(self) -> str | None:
"""Return the currently selected playlist."""
if not self.coordinator.data.state.playlist_id:
return None
if playlist := self.coordinator.data.playlists.get(
self.coordinator.data.state.playlist_id
):
return playlist.name
return None
@wled_exception_handler
async def async_select_option(self, option: str) -> None:
"""Set WLED segment to the selected playlist."""
await self.coordinator.wled.playlist(playlist=option)
class WLEDPaletteSelect(WLEDEntity, SelectEntity):
"""Defines a WLED Palette select."""
_attr_entity_category = EntityCategory.CONFIG
_attr_translation_key = "color_palette"
_segment: int
def __init__(self, coordinator: WLEDDataUpdateCoordinator, segment: int) -> None:
"""Initialize WLED ."""
super().__init__(coordinator=coordinator)
# Segment 0 uses a simpler name, which is more natural for when using
# a single segment / using WLED with one big LED strip.
if segment != 0:
self._attr_translation_key = "segment_color_palette"
self._attr_translation_placeholders = {"segment": str(segment)}
self._attr_unique_id = f"{coordinator.data.info.mac_address}_palette_{segment}"
self._attr_options = [
palette.name for palette in self.coordinator.data.palettes.values()
]
self._segment = segment
@property
def available(self) -> bool:
"""Return True if entity is available."""
try:
self.coordinator.data.state.segments[self._segment]
except KeyError:
return False
return super().available
@property
def current_option(self) -> str | None:
"""Return the current selected color palette."""
return self.coordinator.data.palettes[
int(self.coordinator.data.state.segments[self._segment].palette_id)
].name
@wled_exception_handler
async def async_select_option(self, option: str) -> None:
"""Set WLED segment to the selected color palette."""
await self.coordinator.wled.segment(segment_id=self._segment, palette=option)
@callback
def async_update_segments(
coordinator: WLEDDataUpdateCoordinator,
current_ids: set[int],
async_add_entities: AddEntitiesCallback,
) -> None:
"""Update segments."""
segment_ids = {
segment.segment_id
for segment in coordinator.data.state.segments.values()
if segment.segment_id is not None
}
new_entities: list[WLEDPaletteSelect] = []
# Process new segments, add them to Home Assistant
for segment_id in segment_ids - current_ids:
current_ids.add(segment_id)
new_entities.append(WLEDPaletteSelect(coordinator, segment_id))
async_add_entities(new_entities)