mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +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
|
from collections import deque
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import TYPE_CHECKING, Any
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from homeassistant.const import MATCH_ALL
|
from homeassistant.const import EVENT_STATE_CHANGED
|
||||||
from homeassistant.core import CALLBACK_TYPE, HassJob, HomeAssistant, State, callback
|
from homeassistant.core import (
|
||||||
from homeassistant.helpers.event import async_call_later, async_track_state_change
|
CALLBACK_TYPE,
|
||||||
|
Event,
|
||||||
|
EventStateChangedData,
|
||||||
|
HassJob,
|
||||||
|
HomeAssistant,
|
||||||
|
callback,
|
||||||
|
)
|
||||||
|
from homeassistant.helpers.event import async_call_later
|
||||||
from homeassistant.helpers.significant_change import create_checker
|
from homeassistant.helpers.significant_change import create_checker
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
@ -31,7 +38,9 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
@callback
|
@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."""
|
"""Enable state and notification reporting."""
|
||||||
checker = None
|
checker = None
|
||||||
unsub_pending: CALLBACK_TYPE | None = 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)
|
report_states_job = HassJob(report_states)
|
||||||
|
|
||||||
async def async_entity_state_listener(
|
@callback
|
||||||
changed_entity: str, old_state: State | None, new_state: State | None
|
def _async_entity_state_filter(data: EventStateChangedData) -> bool:
|
||||||
) -> None:
|
return bool(
|
||||||
nonlocal unsub_pending, checker
|
hass.is_running
|
||||||
|
and (new_state := data["new_state"])
|
||||||
if not hass.is_running:
|
and google_config.should_expose(new_state)
|
||||||
return
|
and async_get_google_entity_if_supported_cached(
|
||||||
|
|
||||||
if not new_state:
|
|
||||||
return
|
|
||||||
|
|
||||||
if not google_config.should_expose(new_state):
|
|
||||||
return
|
|
||||||
|
|
||||||
if not (
|
|
||||||
entity := async_get_google_entity_if_supported_cached(
|
|
||||||
hass, google_config, new_state
|
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.
|
# We only trigger notifications on changes in the state value, not attributes.
|
||||||
# This is mainly designed for our event entity types
|
# This is mainly designed for our event entity types
|
||||||
# We need to synchronize notifications using a `SYNC` response,
|
# We need to synchronize notifications using a `SYNC` response,
|
||||||
# together with other state changes.
|
# together with other state changes.
|
||||||
if (
|
if (
|
||||||
old_state
|
(old_state := data["old_state"])
|
||||||
and old_state.state != new_state.state
|
and old_state.state != new_state.state
|
||||||
and (notifications := entity.notifications_serialize()) is not None
|
and (notifications := entity.notifications_serialize()) is not None
|
||||||
):
|
):
|
||||||
@ -106,6 +118,7 @@ def async_enable_report_state(hass: HomeAssistant, google_config: AbstractConfig
|
|||||||
result,
|
result,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
changed_entity = data["entity_id"]
|
||||||
try:
|
try:
|
||||||
entity_data = entity.query_serialize()
|
entity_data = entity.query_serialize()
|
||||||
except SmartHomeError as err:
|
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}})
|
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(
|
unsub = async_call_later(
|
||||||
hass, INITIAL_REPORT_DELAY, HassJob(initial_report, cancel_on_shutdown=True)
|
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")
|
hass, datetime.fromisoformat("2023-08-01T01:01:00+00:00")
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
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
|
# Test the notification request failed
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
@ -233,12 +237,10 @@ async def test_report_notifications(
|
|||||||
hass, datetime.fromisoformat("2023-08-01T01:03:00+00:00")
|
hass, datetime.fromisoformat("2023-08-01T01:03:00+00:00")
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
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:
|
for call in mock_report_state.mock_calls:
|
||||||
if "notifications" in call[1][0]["devices"]:
|
if "notifications" in call[1][0]["devices"]:
|
||||||
notifications = call[1][0]["devices"]["notifications"]
|
notifications = call[1][0]["devices"]["notifications"]
|
||||||
elif "states" in call[1][0]["devices"]:
|
|
||||||
states = call[1][0]["devices"]["states"]
|
|
||||||
assert notifications["event.doorbell"] == {
|
assert notifications["event.doorbell"] == {
|
||||||
"ObjectDetection": {
|
"ObjectDetection": {
|
||||||
"objects": {"unclassified": 1},
|
"objects": {"unclassified": 1},
|
||||||
@ -246,7 +248,6 @@ async def test_report_notifications(
|
|||||||
"detectionTimestamp": epoc_event_time * 1000,
|
"detectionTimestamp": epoc_event_time * 1000,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert states["event.doorbell"] == {"online": True}
|
|
||||||
assert "Sending event notification for entity event.doorbell" in caplog.text
|
assert "Sending event notification for entity event.doorbell" in caplog.text
|
||||||
assert (
|
assert (
|
||||||
"Unable to send notification with result code: 500, check log for more info"
|
"Unable to send notification with result code: 500, check log for more info"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user