"""Scene platform for LedGrab — scene presets as voice-activatable scenes. Scene presets are also exposed as ``button.*`` entities (see button.py) for dashboard use. Buttons, however, are NOT in the set of entity domains that Alexa / Google Assistant / HomeKit expose to voice assistants — ``scene.*`` is. This platform adds a ``scene.*`` entity per preset so "Alexa, turn on Movie Night" works, while leaving the buttons in place for existing dashboards. """ from __future__ import annotations import logging from typing import Any from homeassistant.components.scene import Scene from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import DOMAIN, DATA_COORDINATOR from .coordinator import LedGrabCoordinator _LOGGER = logging.getLogger(__name__) async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up a scene entity per scene preset.""" data = hass.data[DOMAIN][entry.entry_id] coordinator: LedGrabCoordinator = data[DATA_COORDINATOR] entities: list[Scene] = [] if coordinator.data: for preset in coordinator.data.get("scene_presets", []): entities.append(LedGrabScene(coordinator, preset, entry.entry_id)) async_add_entities(entities) class LedGrabScene(CoordinatorEntity, Scene): """A scene preset exposed as a HA scene (voice-friendly).""" # Full standalone name so utterances like "turn on Movie Night" match, # instead of the " " composite that has_entity_name gives. _attr_has_entity_name = False _attr_icon = "mdi:palette" def __init__( self, coordinator: LedGrabCoordinator, preset: dict[str, Any], entry_id: str, ) -> None: """Initialize the scene.""" super().__init__(coordinator) self._preset_id = preset["id"] self._entry_id = entry_id # Distinct from the button's unique_id so both can coexist. self._attr_unique_id = f"{entry_id}_scene_entity_{preset['id']}" self._attr_name = preset["name"] @property def device_info(self) -> dict[str, Any]: """All scene entities belong to the same Scenes device as the buttons.""" return {"identifiers": {(DOMAIN, f"{self._entry_id}_scenes")}} @property def available(self) -> bool: """Return if the underlying preset still exists.""" if not self.coordinator.data: return False return self._preset_id in { p["id"] for p in self.coordinator.data.get("scene_presets", []) } async def async_activate(self, **kwargs: Any) -> None: """Activate the scene preset.""" await self.coordinator.activate_scene(self._preset_id)