mirror of
https://github.com/home-assistant/core
synced 2024-07-21 10:44:07 +00:00
Add async_track_state_reported_event to fix integration performance regression (#120622)
split from https://github.com/home-assistant/core/pull/120621
This commit is contained in:
parent
f189d87fe9
commit
a5a631148e
|
@ -17,6 +17,7 @@ from typing import TYPE_CHECKING, Any, Concatenate, Generic, TypeVar
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
EVENT_CORE_CONFIG_UPDATE,
|
EVENT_CORE_CONFIG_UPDATE,
|
||||||
EVENT_STATE_CHANGED,
|
EVENT_STATE_CHANGED,
|
||||||
|
EVENT_STATE_REPORTED,
|
||||||
MATCH_ALL,
|
MATCH_ALL,
|
||||||
SUN_EVENT_SUNRISE,
|
SUN_EVENT_SUNRISE,
|
||||||
SUN_EVENT_SUNSET,
|
SUN_EVENT_SUNSET,
|
||||||
|
@ -26,6 +27,7 @@ from homeassistant.core import (
|
||||||
Event,
|
Event,
|
||||||
# Explicit reexport of 'EventStateChangedData' for backwards compatibility
|
# Explicit reexport of 'EventStateChangedData' for backwards compatibility
|
||||||
EventStateChangedData as EventStateChangedData, # noqa: PLC0414
|
EventStateChangedData as EventStateChangedData, # noqa: PLC0414
|
||||||
|
EventStateReportedData,
|
||||||
HassJob,
|
HassJob,
|
||||||
HassJobType,
|
HassJobType,
|
||||||
HomeAssistant,
|
HomeAssistant,
|
||||||
|
@ -57,6 +59,9 @@ from .typing import TemplateVarsType
|
||||||
_TRACK_STATE_CHANGE_DATA: HassKey[_KeyedEventData[EventStateChangedData]] = HassKey(
|
_TRACK_STATE_CHANGE_DATA: HassKey[_KeyedEventData[EventStateChangedData]] = HassKey(
|
||||||
"track_state_change_data"
|
"track_state_change_data"
|
||||||
)
|
)
|
||||||
|
_TRACK_STATE_REPORTED_DATA: HassKey[_KeyedEventData[EventStateReportedData]] = HassKey(
|
||||||
|
"track_state_reported_data"
|
||||||
|
)
|
||||||
_TRACK_STATE_ADDED_DOMAIN_DATA: HassKey[_KeyedEventData[EventStateChangedData]] = (
|
_TRACK_STATE_ADDED_DOMAIN_DATA: HassKey[_KeyedEventData[EventStateChangedData]] = (
|
||||||
HassKey("track_state_added_domain_data")
|
HassKey("track_state_added_domain_data")
|
||||||
)
|
)
|
||||||
|
@ -324,8 +329,8 @@ def async_track_state_change_event(
|
||||||
@callback
|
@callback
|
||||||
def _async_dispatch_entity_id_event(
|
def _async_dispatch_entity_id_event(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
callbacks: dict[str, list[HassJob[[Event[EventStateChangedData]], Any]]],
|
callbacks: dict[str, list[HassJob[[Event[_TypedDictT]], Any]]],
|
||||||
event: Event[EventStateChangedData],
|
event: Event[_TypedDictT],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Dispatch to listeners."""
|
"""Dispatch to listeners."""
|
||||||
if not (callbacks_list := callbacks.get(event.data["entity_id"])):
|
if not (callbacks_list := callbacks.get(event.data["entity_id"])):
|
||||||
|
@ -342,10 +347,10 @@ def _async_dispatch_entity_id_event(
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_state_change_filter(
|
def _async_state_filter(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
callbacks: dict[str, list[HassJob[[Event[EventStateChangedData]], Any]]],
|
callbacks: dict[str, list[HassJob[[Event[_TypedDictT]], Any]]],
|
||||||
event_data: EventStateChangedData,
|
event_data: _TypedDictT,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Filter state changes by entity_id."""
|
"""Filter state changes by entity_id."""
|
||||||
return event_data["entity_id"] in callbacks
|
return event_data["entity_id"] in callbacks
|
||||||
|
@ -355,7 +360,7 @@ _KEYED_TRACK_STATE_CHANGE = _KeyedEventTracker(
|
||||||
key=_TRACK_STATE_CHANGE_DATA,
|
key=_TRACK_STATE_CHANGE_DATA,
|
||||||
event_type=EVENT_STATE_CHANGED,
|
event_type=EVENT_STATE_CHANGED,
|
||||||
dispatcher_callable=_async_dispatch_entity_id_event,
|
dispatcher_callable=_async_dispatch_entity_id_event,
|
||||||
filter_callable=_async_state_change_filter,
|
filter_callable=_async_state_filter,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -372,6 +377,26 @@ def _async_track_state_change_event(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_KEYED_TRACK_STATE_REPORTED = _KeyedEventTracker(
|
||||||
|
key=_TRACK_STATE_REPORTED_DATA,
|
||||||
|
event_type=EVENT_STATE_REPORTED,
|
||||||
|
dispatcher_callable=_async_dispatch_entity_id_event,
|
||||||
|
filter_callable=_async_state_filter,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def async_track_state_reported_event(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_ids: str | Iterable[str],
|
||||||
|
action: Callable[[Event[EventStateReportedData]], Any],
|
||||||
|
job_type: HassJobType | None = None,
|
||||||
|
) -> CALLBACK_TYPE:
|
||||||
|
"""Track EVENT_STATE_REPORTED by entity_id without lowercasing."""
|
||||||
|
return _async_track_event(
|
||||||
|
_KEYED_TRACK_STATE_REPORTED, hass, entity_ids, action, job_type
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _remove_empty_listener() -> None:
|
def _remove_empty_listener() -> None:
|
||||||
"""Remove a listener that does nothing."""
|
"""Remove a listener that does nothing."""
|
||||||
|
|
|
@ -15,7 +15,13 @@ import pytest
|
||||||
|
|
||||||
from homeassistant.const import MATCH_ALL
|
from homeassistant.const import MATCH_ALL
|
||||||
import homeassistant.core as ha
|
import homeassistant.core as ha
|
||||||
from homeassistant.core import Event, EventStateChangedData, HomeAssistant, callback
|
from homeassistant.core import (
|
||||||
|
Event,
|
||||||
|
EventStateChangedData,
|
||||||
|
EventStateReportedData,
|
||||||
|
HomeAssistant,
|
||||||
|
callback,
|
||||||
|
)
|
||||||
from homeassistant.exceptions import TemplateError
|
from homeassistant.exceptions import TemplateError
|
||||||
from homeassistant.helpers.device_registry import EVENT_DEVICE_REGISTRY_UPDATED
|
from homeassistant.helpers.device_registry import EVENT_DEVICE_REGISTRY_UPDATED
|
||||||
from homeassistant.helpers.entity_registry import EVENT_ENTITY_REGISTRY_UPDATED
|
from homeassistant.helpers.entity_registry import EVENT_ENTITY_REGISTRY_UPDATED
|
||||||
|
@ -34,6 +40,7 @@ from homeassistant.helpers.event import (
|
||||||
async_track_state_change_event,
|
async_track_state_change_event,
|
||||||
async_track_state_change_filtered,
|
async_track_state_change_filtered,
|
||||||
async_track_state_removed_domain,
|
async_track_state_removed_domain,
|
||||||
|
async_track_state_reported_event,
|
||||||
async_track_sunrise,
|
async_track_sunrise,
|
||||||
async_track_sunset,
|
async_track_sunset,
|
||||||
async_track_template,
|
async_track_template,
|
||||||
|
@ -4907,3 +4914,26 @@ async def test_track_point_in_time_repr(
|
||||||
assert "Exception in callback _TrackPointUTCTime" in caplog.text
|
assert "Exception in callback _TrackPointUTCTime" in caplog.text
|
||||||
assert "._raise_exception" in caplog.text
|
assert "._raise_exception" in caplog.text
|
||||||
await hass.async_block_till_done(wait_background_tasks=True)
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_async_track_state_reported_event(hass: HomeAssistant) -> None:
|
||||||
|
"""Test async_track_state_reported_event."""
|
||||||
|
tracker_called: list[ha.State] = []
|
||||||
|
|
||||||
|
@ha.callback
|
||||||
|
def single_run_callback(event: Event[EventStateReportedData]) -> None:
|
||||||
|
new_state = event.data["new_state"]
|
||||||
|
tracker_called.append(new_state)
|
||||||
|
|
||||||
|
unsub = async_track_state_reported_event(
|
||||||
|
hass, ["light.bowl", "light.top"], single_run_callback
|
||||||
|
)
|
||||||
|
hass.states.async_set("light.bowl", "on")
|
||||||
|
hass.states.async_set("light.top", "on")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(tracker_called) == 0
|
||||||
|
hass.states.async_set("light.bowl", "on")
|
||||||
|
hass.states.async_set("light.top", "on")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(tracker_called) == 2
|
||||||
|
unsub()
|
||||||
|
|
Loading…
Reference in a new issue