Expose method to set last activated on scene (#146884)

This commit is contained in:
Thomas D
2025-08-26 13:44:07 +02:00
committed by GitHub
parent 5bb96f7f06
commit ce523fc91d

View File

@@ -12,15 +12,16 @@ import voluptuous as vol
from homeassistant.components.light import ATTR_TRANSITION from homeassistant.components.light import ATTR_TRANSITION
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PLATFORM, SERVICE_TURN_ON, STATE_UNAVAILABLE from homeassistant.const import CONF_PLATFORM, SERVICE_TURN_ON, STATE_UNAVAILABLE
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant, callback
from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
from homeassistant.util.async_ import run_callback_threadsafe
from homeassistant.util.hass_dict import HassKey from homeassistant.util.hass_dict import HassKey
DOMAIN: Final = "scene" DOMAIN: Final = "scene"
DATA_COMPONENT: HassKey[EntityComponent[Scene]] = HassKey(DOMAIN) DATA_COMPONENT: HassKey[EntityComponent[BaseScene]] = HassKey(DOMAIN)
STATES: Final = "states" STATES: Final = "states"
@@ -62,7 +63,7 @@ PLATFORM_SCHEMA = vol.Schema(
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the scenes.""" """Set up the scenes."""
component = hass.data[DATA_COMPONENT] = EntityComponent[Scene]( component = hass.data[DATA_COMPONENT] = EntityComponent[BaseScene](
logging.getLogger(__name__), DOMAIN, hass logging.getLogger(__name__), DOMAIN, hass
) )
@@ -93,8 +94,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await hass.data[DATA_COMPONENT].async_unload_entry(entry) return await hass.data[DATA_COMPONENT].async_unload_entry(entry)
class Scene(RestoreEntity): class BaseScene(RestoreEntity):
"""A scene is a group of entities and the states we want them to be.""" """Base type for scenes."""
_attr_should_poll = False _attr_should_poll = False
__last_activated: str | None = None __last_activated: str | None = None
@@ -108,14 +109,14 @@ class Scene(RestoreEntity):
return self.__last_activated return self.__last_activated
@final @final
async def _async_activate(self, **kwargs: Any) -> None: def _record_activation(self) -> None:
"""Activate scene. run_callback_threadsafe(self.hass.loop, self._async_record_activation).result()
Should not be overridden, handle setting last press timestamp. @final
""" @callback
def _async_record_activation(self) -> None:
"""Update the activation timestamp."""
self.__last_activated = dt_util.utcnow().isoformat() self.__last_activated = dt_util.utcnow().isoformat()
self.async_write_ha_state()
await self.async_activate(**kwargs)
async def async_internal_added_to_hass(self) -> None: async def async_internal_added_to_hass(self) -> None:
"""Call when the scene is added to hass.""" """Call when the scene is added to hass."""
@@ -128,6 +129,10 @@ class Scene(RestoreEntity):
): ):
self.__last_activated = state.state self.__last_activated = state.state
async def _async_activate(self, **kwargs: Any) -> None:
"""Activate scene."""
raise NotImplementedError
def activate(self, **kwargs: Any) -> None: def activate(self, **kwargs: Any) -> None:
"""Activate scene. Try to get entities into requested state.""" """Activate scene. Try to get entities into requested state."""
raise NotImplementedError raise NotImplementedError
@@ -137,3 +142,17 @@ class Scene(RestoreEntity):
task = self.hass.async_add_executor_job(ft.partial(self.activate, **kwargs)) task = self.hass.async_add_executor_job(ft.partial(self.activate, **kwargs))
if task: if task:
await task await task
class Scene(BaseScene):
"""A scene is a group of entities and the states we want them to be."""
@final
async def _async_activate(self, **kwargs: Any) -> None:
"""Activate scene.
Should not be overridden, handle setting last press timestamp.
"""
self._async_record_activation()
self.async_write_ha_state()
await self.async_activate(**kwargs)