mirror of https://github.com/home-assistant/core
211 lines
6.7 KiB
Python
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)
|