feat(playlists): expose scene playlists as Home Assistant entities
One device per scene playlist (model "Scene Playlist"), each with: - a switch (start/stop; the server cycles one playlist at a time, so starting one stops any other) - a "Current Scene" sensor that resolves the active preset name from scene_presets while this playlist is cycling - an "Items" diagnostic sensor (configured scene count; no state_class) The coordinator reads scene_playlists plus the flat playlist_state from the /api/v1/snapshot payload and gains start_playlist()/stop_playlist(); __init__ registers and prunes per-playlist devices and reloads on playlist-id changes; the event listener also refreshes on the playlist_state_changed WS event. Shared device/lookup/running-state plumbing lives in a new LedGrabPlaylistEntity base (entity.py) used by both the switch and the sensors. Adds en/ru translation keys. Note: this also lands the in-progress coordinator migration from the per-request fan-out to the single /api/v1/snapshot poll that was already present in the working tree. Requires the led-grab server /api/v1/snapshot to emit scene_playlists + playlist_state (companion server change, tracked separately).
This commit is contained in:
@@ -113,6 +113,22 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
)
|
||||
current_identifiers.add(scenes_identifier)
|
||||
|
||||
# One device per scene playlist — groups its switch + stats sensors.
|
||||
scene_playlists = (
|
||||
coordinator.data.get("scene_playlists", []) if coordinator.data else []
|
||||
)
|
||||
for playlist in scene_playlists:
|
||||
playlist_identifier = (DOMAIN, playlist["id"])
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=entry.entry_id,
|
||||
identifiers={playlist_identifier},
|
||||
name=playlist.get("name", playlist["id"]),
|
||||
manufacturer=server_name,
|
||||
model="Scene Playlist",
|
||||
configuration_url=server_url,
|
||||
)
|
||||
current_identifiers.add(playlist_identifier)
|
||||
|
||||
# One device per sync clock — groups its switch/number/button/sensor.
|
||||
sync_clocks = coordinator.data.get("sync_clocks", []) if coordinator.data else []
|
||||
for clock in sync_clocks:
|
||||
@@ -140,37 +156,45 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
DATA_EVENT_LISTENER: event_listener,
|
||||
}
|
||||
|
||||
# Track target, scene, and sync-clock IDs to detect changes
|
||||
# Track target, scene, playlist, and sync-clock IDs to detect changes
|
||||
known_target_ids = set(coordinator.data.get("targets", {}).keys() if coordinator.data else [])
|
||||
known_scene_ids = set(
|
||||
p["id"] for p in (coordinator.data.get("scene_presets", []) if coordinator.data else [])
|
||||
)
|
||||
known_playlist_ids = set(
|
||||
p["id"] for p in (coordinator.data.get("scene_playlists", []) if coordinator.data else [])
|
||||
)
|
||||
known_clock_ids = set(
|
||||
c["id"] for c in (coordinator.data.get("sync_clocks", []) if coordinator.data else [])
|
||||
)
|
||||
|
||||
def _on_coordinator_update() -> None:
|
||||
"""Detect target/scene/clock list changes and trigger reload."""
|
||||
nonlocal known_target_ids, known_scene_ids, known_clock_ids
|
||||
"""Detect target/scene/playlist/clock list changes and trigger reload."""
|
||||
nonlocal known_target_ids, known_scene_ids, known_playlist_ids, known_clock_ids
|
||||
|
||||
if not coordinator.data:
|
||||
return
|
||||
|
||||
targets = coordinator.data.get("targets", {})
|
||||
|
||||
# Reload if target, scene, or sync-clock list changed
|
||||
# Reload if target, scene, playlist, or sync-clock list changed
|
||||
current_ids = set(targets.keys())
|
||||
current_scene_ids = set(p["id"] for p in coordinator.data.get("scene_presets", []))
|
||||
current_playlist_ids = set(p["id"] for p in coordinator.data.get("scene_playlists", []))
|
||||
current_clock_ids = set(c["id"] for c in coordinator.data.get("sync_clocks", []))
|
||||
if (
|
||||
current_ids != known_target_ids
|
||||
or current_scene_ids != known_scene_ids
|
||||
or current_playlist_ids != known_playlist_ids
|
||||
or current_clock_ids != known_clock_ids
|
||||
):
|
||||
known_target_ids = current_ids
|
||||
known_scene_ids = current_scene_ids
|
||||
known_playlist_ids = current_playlist_ids
|
||||
known_clock_ids = current_clock_ids
|
||||
_LOGGER.info("Target, scene, or sync-clock list changed, reloading integration")
|
||||
_LOGGER.info(
|
||||
"Target, scene, playlist, or sync-clock list changed, reloading integration"
|
||||
)
|
||||
hass.async_create_task(hass.config_entries.async_reload(entry.entry_id))
|
||||
|
||||
coordinator.async_add_listener(_on_coordinator_update)
|
||||
|
||||
Reference in New Issue
Block a user