Simplify EVENT_STATE_REPORTED (#120508)

pull/120541/head
Erik Montnemery 2024-06-26 11:23:26 +02:00 committed by GitHub
parent 2c48843739
commit d589eaf440
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 23 additions and 27 deletions

View File

@ -18,7 +18,7 @@ from .util.hass_dict import HassKey
from .util.signal_type import SignalType from .util.signal_type import SignalType
if TYPE_CHECKING: if TYPE_CHECKING:
from .core import EventStateChangedData from .core import EventStateChangedData, EventStateReportedData
from .helpers.typing import NoEventData from .helpers.typing import NoEventData
APPLICATION_NAME: Final = "HomeAssistant" APPLICATION_NAME: Final = "HomeAssistant"
@ -321,7 +321,7 @@ EVENT_LOGGING_CHANGED: Final = "logging_changed"
EVENT_SERVICE_REGISTERED: Final = "service_registered" EVENT_SERVICE_REGISTERED: Final = "service_registered"
EVENT_SERVICE_REMOVED: Final = "service_removed" EVENT_SERVICE_REMOVED: Final = "service_removed"
EVENT_STATE_CHANGED: EventType[EventStateChangedData] = EventType("state_changed") EVENT_STATE_CHANGED: EventType[EventStateChangedData] = EventType("state_changed")
EVENT_STATE_REPORTED: Final = "state_reported" EVENT_STATE_REPORTED: EventType[EventStateReportedData] = EventType("state_reported")
EVENT_THEMES_UPDATED: Final = "themes_updated" EVENT_THEMES_UPDATED: Final = "themes_updated"
EVENT_PANELS_UPDATED: Final = "panels_updated" EVENT_PANELS_UPDATED: Final = "panels_updated"
EVENT_LOVELACE_UPDATED: Final = "lovelace_updated" EVENT_LOVELACE_UPDATED: Final = "lovelace_updated"

View File

@ -159,13 +159,27 @@ class ConfigSource(enum.StrEnum):
class EventStateChangedData(TypedDict): class EventStateChangedData(TypedDict):
"""EventStateChanged data.""" """EVENT_STATE_CHANGED data.
A state changed event is fired when on state write when the state is changed.
"""
entity_id: str entity_id: str
old_state: State | None old_state: State | None
new_state: State | None new_state: State | None
class EventStateReportedData(TypedDict):
"""EVENT_STATE_REPORTED data.
A state reported event is fired when on state write when the state is unchanged.
"""
entity_id: str
old_last_reported: datetime.datetime
new_state: State | None
# SOURCE_* are deprecated as of Home Assistant 2022.2, use ConfigSource instead # SOURCE_* are deprecated as of Home Assistant 2022.2, use ConfigSource instead
_DEPRECATED_SOURCE_DISCOVERED = DeprecatedConstantEnum( _DEPRECATED_SOURCE_DISCOVERED = DeprecatedConstantEnum(
ConfigSource.DISCOVERED, "2025.1" ConfigSource.DISCOVERED, "2025.1"
@ -1604,27 +1618,8 @@ class EventBus:
raise HomeAssistantError( raise HomeAssistantError(
f"Event filter is required for event {event_type}" f"Event filter is required for event {event_type}"
) )
# Special case for EVENT_STATE_REPORTED, we also want to listen to
# EVENT_STATE_CHANGED
self._listeners[EVENT_STATE_REPORTED].append(filterable_job)
self._listeners[EVENT_STATE_CHANGED].append(filterable_job)
return functools.partial(
self._async_remove_multiple_listeners,
(EVENT_STATE_REPORTED, EVENT_STATE_CHANGED),
filterable_job,
)
return self._async_listen_filterable_job(event_type, filterable_job) return self._async_listen_filterable_job(event_type, filterable_job)
@callback
def _async_remove_multiple_listeners(
self,
keys: Iterable[EventType[_DataT] | str],
filterable_job: _FilterableJobType[Any],
) -> None:
"""Remove multiple listeners for specific event_types."""
for key in keys:
self._async_remove_listener(key, filterable_job)
@callback @callback
def _async_listen_filterable_job( def _async_listen_filterable_job(
self, self,
@ -2278,7 +2273,8 @@ class StateMachine:
old_last_reported = old_state.last_reported # type: ignore[union-attr] old_last_reported = old_state.last_reported # type: ignore[union-attr]
old_state.last_reported = now # type: ignore[union-attr] old_state.last_reported = now # type: ignore[union-attr]
old_state.last_reported_timestamp = timestamp # type: ignore[union-attr] old_state.last_reported_timestamp = timestamp # type: ignore[union-attr]
self._bus.async_fire_internal( # Avoid creating an EventStateReportedData
self._bus.async_fire_internal( # type: ignore[misc]
EVENT_STATE_REPORTED, EVENT_STATE_REPORTED,
{ {
"entity_id": entity_id, "entity_id": entity_id,

View File

@ -3385,24 +3385,24 @@ async def test_statemachine_report_state(hass: HomeAssistant) -> None:
hass.states.async_set("light.bowl", "on", None, True) hass.states.async_set("light.bowl", "on", None, True)
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(state_changed_events) == 1 assert len(state_changed_events) == 1
assert len(state_reported_events) == 2 assert len(state_reported_events) == 1
hass.states.async_set("light.bowl", "off") hass.states.async_set("light.bowl", "off")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(state_changed_events) == 2 assert len(state_changed_events) == 2
assert len(state_reported_events) == 3 assert len(state_reported_events) == 1
hass.states.async_remove("light.bowl") hass.states.async_remove("light.bowl")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(state_changed_events) == 3 assert len(state_changed_events) == 3
assert len(state_reported_events) == 4 assert len(state_reported_events) == 1
unsub() unsub()
hass.states.async_set("light.bowl", "on") hass.states.async_set("light.bowl", "on")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(state_changed_events) == 4 assert len(state_changed_events) == 4
assert len(state_reported_events) == 4 assert len(state_reported_events) == 1
async def test_report_state_listener_restrictions(hass: HomeAssistant) -> None: async def test_report_state_listener_restrictions(hass: HomeAssistant) -> None: