mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 12:47:08 +00:00
Add an event_filter to google_assistant state reporting (#115160)
* adjust * fix test since it happens sooner now * remove debug * remove unneeded test change * reduce * reduce
This commit is contained in:
parent
89a2c89fe2
commit
af1023074e
@ -4,12 +4,19 @@ from __future__ import annotations
|
||||
|
||||
from collections import deque
|
||||
import logging
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from uuid import uuid4
|
||||
|
||||
from homeassistant.const import MATCH_ALL
|
||||
from homeassistant.core import CALLBACK_TYPE, HassJob, HomeAssistant, State, callback
|
||||
from homeassistant.helpers.event import async_call_later, async_track_state_change
|
||||
from homeassistant.const import EVENT_STATE_CHANGED
|
||||
from homeassistant.core import (
|
||||
CALLBACK_TYPE,
|
||||
Event,
|
||||
EventStateChangedData,
|
||||
HassJob,
|
||||
HomeAssistant,
|
||||
callback,
|
||||
)
|
||||
from homeassistant.helpers.event import async_call_later
|
||||
from homeassistant.helpers.significant_change import create_checker
|
||||
|
||||
from .const import DOMAIN
|
||||
@ -31,7 +38,9 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@callback
|
||||
def async_enable_report_state(hass: HomeAssistant, google_config: AbstractConfig):
|
||||
def async_enable_report_state(
|
||||
hass: HomeAssistant, google_config: AbstractConfig
|
||||
) -> CALLBACK_TYPE:
|
||||
"""Enable state and notification reporting."""
|
||||
checker = None
|
||||
unsub_pending: CALLBACK_TYPE | None = None
|
||||
@ -60,33 +69,36 @@ def async_enable_report_state(hass: HomeAssistant, google_config: AbstractConfig
|
||||
|
||||
report_states_job = HassJob(report_states)
|
||||
|
||||
async def async_entity_state_listener(
|
||||
changed_entity: str, old_state: State | None, new_state: State | None
|
||||
) -> None:
|
||||
nonlocal unsub_pending, checker
|
||||
|
||||
if not hass.is_running:
|
||||
return
|
||||
|
||||
if not new_state:
|
||||
return
|
||||
|
||||
if not google_config.should_expose(new_state):
|
||||
return
|
||||
|
||||
if not (
|
||||
entity := async_get_google_entity_if_supported_cached(
|
||||
@callback
|
||||
def _async_entity_state_filter(data: EventStateChangedData) -> bool:
|
||||
return bool(
|
||||
hass.is_running
|
||||
and (new_state := data["new_state"])
|
||||
and google_config.should_expose(new_state)
|
||||
and async_get_google_entity_if_supported_cached(
|
||||
hass, google_config, new_state
|
||||
)
|
||||
):
|
||||
return
|
||||
)
|
||||
|
||||
async def _async_entity_state_listener(event: Event[EventStateChangedData]) -> None:
|
||||
"""Handle state changes."""
|
||||
nonlocal unsub_pending, checker
|
||||
data = event.data
|
||||
new_state = data["new_state"]
|
||||
if TYPE_CHECKING:
|
||||
assert new_state is not None # verified in filter
|
||||
entity = async_get_google_entity_if_supported_cached(
|
||||
hass, google_config, new_state
|
||||
)
|
||||
if TYPE_CHECKING:
|
||||
assert entity is not None # verified in filter
|
||||
|
||||
# We only trigger notifications on changes in the state value, not attributes.
|
||||
# This is mainly designed for our event entity types
|
||||
# We need to synchronize notifications using a `SYNC` response,
|
||||
# together with other state changes.
|
||||
if (
|
||||
old_state
|
||||
(old_state := data["old_state"])
|
||||
and old_state.state != new_state.state
|
||||
and (notifications := entity.notifications_serialize()) is not None
|
||||
):
|
||||
@ -106,6 +118,7 @@ def async_enable_report_state(hass: HomeAssistant, google_config: AbstractConfig
|
||||
result,
|
||||
)
|
||||
|
||||
changed_entity = data["entity_id"]
|
||||
try:
|
||||
entity_data = entity.query_serialize()
|
||||
except SmartHomeError as err:
|
||||
@ -173,7 +186,12 @@ def async_enable_report_state(hass: HomeAssistant, google_config: AbstractConfig
|
||||
|
||||
await google_config.async_report_state_all({"devices": {"states": entities}})
|
||||
|
||||
unsub = async_track_state_change(hass, MATCH_ALL, async_entity_state_listener)
|
||||
unsub = hass.bus.async_listen(
|
||||
EVENT_STATE_CHANGED,
|
||||
_async_entity_state_listener,
|
||||
event_filter=_async_entity_state_filter,
|
||||
run_immediately=True,
|
||||
)
|
||||
|
||||
unsub = async_call_later(
|
||||
hass, INITIAL_REPORT_DELAY, HassJob(initial_report, cancel_on_shutdown=True)
|
||||
|
@ -216,6 +216,10 @@ async def test_report_notifications(
|
||||
hass, datetime.fromisoformat("2023-08-01T01:01:00+00:00")
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
for call in mock_report_state.mock_calls:
|
||||
if "states" in call[1][0]["devices"]:
|
||||
states = call[1][0]["devices"]["states"]
|
||||
assert states["event.doorbell"] == {"online": True}
|
||||
|
||||
# Test the notification request failed
|
||||
caplog.clear()
|
||||
@ -233,12 +237,10 @@ async def test_report_notifications(
|
||||
hass, datetime.fromisoformat("2023-08-01T01:03:00+00:00")
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert len(mock_report_state.mock_calls) == 2
|
||||
assert len(mock_report_state.mock_calls) == 1
|
||||
for call in mock_report_state.mock_calls:
|
||||
if "notifications" in call[1][0]["devices"]:
|
||||
notifications = call[1][0]["devices"]["notifications"]
|
||||
elif "states" in call[1][0]["devices"]:
|
||||
states = call[1][0]["devices"]["states"]
|
||||
assert notifications["event.doorbell"] == {
|
||||
"ObjectDetection": {
|
||||
"objects": {"unclassified": 1},
|
||||
@ -246,7 +248,6 @@ async def test_report_notifications(
|
||||
"detectionTimestamp": epoc_event_time * 1000,
|
||||
}
|
||||
}
|
||||
assert states["event.doorbell"] == {"online": True}
|
||||
assert "Sending event notification for entity event.doorbell" in caplog.text
|
||||
assert (
|
||||
"Unable to send notification with result code: 500, check log for more info"
|
||||
|
Loading…
x
Reference in New Issue
Block a user