Cleanup async_track_state_change and augment docstring (#37251)
* Cleanup async_track_state_change and augment docstrings. Skip from_state and to_state matching in async_track_state_change when they are None Optimize the state change listener for the most common use case: no to_state and from_state matching. * Update benchmark to be more realistic (previously we assumed only one entity was present in the whole instance) * Add more tests to ensure behavior is preserved * Ensure new behavior matches test * remove MATCH_ALL from zone automation since its the default anyways * Might as well use async_track_state_change_event instead since MATCH_ALL is removed
This commit is contained in:
parent
2088092f7c
commit
34ccb6588c
4 changed files with 163 additions and 32 deletions
|
@ -72,10 +72,16 @@ def async_track_state_change(
|
|||
|
||||
Returns a function that can be called to remove the listener.
|
||||
|
||||
If entity_ids are not MATCH_ALL along with from_state and to_state
|
||||
being None, async_track_state_change_event should be used instead
|
||||
as it is slightly faster.
|
||||
|
||||
Must be run within the event loop.
|
||||
"""
|
||||
match_from_state = process_state_match(from_state)
|
||||
match_to_state = process_state_match(to_state)
|
||||
if from_state is not None:
|
||||
match_from_state = process_state_match(from_state)
|
||||
if to_state is not None:
|
||||
match_to_state = process_state_match(to_state)
|
||||
|
||||
# Ensure it is a lowercase list with entity ids we want to match on
|
||||
if entity_ids == MATCH_ALL:
|
||||
|
@ -88,21 +94,27 @@ def async_track_state_change(
|
|||
@callback
|
||||
def state_change_listener(event: Event) -> None:
|
||||
"""Handle specific state changes."""
|
||||
old_state = event.data.get("old_state")
|
||||
if old_state is not None:
|
||||
old_state = old_state.state
|
||||
if from_state is not None:
|
||||
old_state = event.data.get("old_state")
|
||||
if old_state is not None:
|
||||
old_state = old_state.state
|
||||
|
||||
new_state = event.data.get("new_state")
|
||||
if new_state is not None:
|
||||
new_state = new_state.state
|
||||
if not match_from_state(old_state):
|
||||
return
|
||||
if to_state is not None:
|
||||
new_state = event.data.get("new_state")
|
||||
if new_state is not None:
|
||||
new_state = new_state.state
|
||||
|
||||
if match_from_state(old_state) and match_to_state(new_state):
|
||||
hass.async_run_job(
|
||||
action,
|
||||
event.data.get("entity_id"),
|
||||
event.data.get("old_state"),
|
||||
event.data.get("new_state"),
|
||||
)
|
||||
if not match_to_state(new_state):
|
||||
return
|
||||
|
||||
hass.async_run_job(
|
||||
action,
|
||||
event.data.get("entity_id"),
|
||||
event.data.get("old_state"),
|
||||
event.data.get("new_state"),
|
||||
)
|
||||
|
||||
if entity_ids != MATCH_ALL:
|
||||
# If we have a list of entity ids we use
|
||||
|
@ -565,5 +577,5 @@ def process_state_match(
|
|||
if isinstance(parameter, str) or not hasattr(parameter, "__iter__"):
|
||||
return lambda state: state == parameter
|
||||
|
||||
parameter_tuple = tuple(parameter)
|
||||
return lambda state: state in parameter_tuple
|
||||
parameter_set = set(parameter)
|
||||
return lambda state: state in parameter_set
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue