Add an event filter to the alexa state report state change listener (#115076)
Co-authored-by: jbouwh <jan@jbsoft.nl>pull/114546/head
parent
f617000920
commit
5630b3611d
|
@ -13,10 +13,16 @@ from uuid import uuid4
|
|||
import aiohttp
|
||||
|
||||
from homeassistant.components import event
|
||||
from homeassistant.const import MATCH_ALL, STATE_ON
|
||||
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, State, callback
|
||||
from homeassistant.const import EVENT_STATE_CHANGED, STATE_ON
|
||||
from homeassistant.core import (
|
||||
CALLBACK_TYPE,
|
||||
Event,
|
||||
EventStateChangedData,
|
||||
HomeAssistant,
|
||||
State,
|
||||
callback,
|
||||
)
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.event import async_track_state_change
|
||||
from homeassistant.helpers.significant_change import create_checker
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.util.json import JsonObjectType, json_loads_object
|
||||
|
@ -265,28 +271,35 @@ async def async_enable_proactive_mode(
|
|||
|
||||
checker = await create_checker(hass, DOMAIN, extra_significant_check)
|
||||
|
||||
async def async_entity_state_listener(
|
||||
changed_entity: str,
|
||||
old_state: State | None,
|
||||
new_state: State | None,
|
||||
) -> None:
|
||||
@callback
|
||||
def _async_entity_state_filter(data: EventStateChangedData) -> bool:
|
||||
if not hass.is_running:
|
||||
return
|
||||
return False
|
||||
|
||||
if not new_state:
|
||||
return
|
||||
if not (new_state := data["new_state"]):
|
||||
return False
|
||||
|
||||
if new_state.domain not in ENTITY_ADAPTERS:
|
||||
return
|
||||
return False
|
||||
|
||||
changed_entity = data["entity_id"]
|
||||
if not smart_home_config.should_expose(changed_entity):
|
||||
_LOGGER.debug("Not exposing %s because filtered by config", changed_entity)
|
||||
return
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
async def _async_entity_state_listener(
|
||||
event_: Event[EventStateChangedData],
|
||||
) -> None:
|
||||
data = event_.data
|
||||
new_state = data["new_state"]
|
||||
if TYPE_CHECKING:
|
||||
assert new_state is not None
|
||||
|
||||
alexa_changed_entity: AlexaEntity = ENTITY_ADAPTERS[new_state.domain](
|
||||
hass, smart_home_config, new_state
|
||||
)
|
||||
|
||||
# Determine how entity should be reported on
|
||||
should_report = False
|
||||
should_doorbell = False
|
||||
|
@ -303,6 +316,7 @@ async def async_enable_proactive_mode(
|
|||
return
|
||||
|
||||
if should_doorbell:
|
||||
old_state = data["old_state"]
|
||||
if (
|
||||
new_state.domain == event.DOMAIN
|
||||
or new_state.state == STATE_ON
|
||||
|
@ -324,7 +338,12 @@ async def async_enable_proactive_mode(
|
|||
hass, smart_home_config, alexa_changed_entity, alexa_properties
|
||||
)
|
||||
|
||||
return async_track_state_change(hass, MATCH_ALL, async_entity_state_listener)
|
||||
return hass.bus.async_listen(
|
||||
EVENT_STATE_CHANGED,
|
||||
_async_entity_state_listener,
|
||||
event_filter=_async_entity_state_filter,
|
||||
run_immediately=True,
|
||||
)
|
||||
|
||||
|
||||
async def async_send_changereport_message(
|
||||
|
|
|
@ -185,14 +185,14 @@ async def test_report_state_unsets_authorized_on_error(
|
|||
config = get_default_config(hass)
|
||||
await state_report.async_enable_proactive_mode(hass, config)
|
||||
|
||||
config._store.set_authorized.assert_not_called()
|
||||
|
||||
hass.states.async_set(
|
||||
"binary_sensor.test_contact",
|
||||
"off",
|
||||
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
|
||||
)
|
||||
|
||||
config._store.set_authorized.assert_not_called()
|
||||
|
||||
# To trigger event listener
|
||||
await hass.async_block_till_done()
|
||||
config._store.set_authorized.assert_called_once_with(False)
|
||||
|
@ -215,15 +215,15 @@ async def test_report_state_unsets_authorized_on_access_token_error(
|
|||
|
||||
await state_report.async_enable_proactive_mode(hass, config)
|
||||
|
||||
hass.states.async_set(
|
||||
"binary_sensor.test_contact",
|
||||
"off",
|
||||
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
|
||||
)
|
||||
|
||||
config._store.set_authorized.assert_not_called()
|
||||
|
||||
with patch.object(config, "async_get_access_token", AsyncMock(side_effect=exc)):
|
||||
hass.states.async_set(
|
||||
"binary_sensor.test_contact",
|
||||
"off",
|
||||
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
|
||||
)
|
||||
|
||||
# To trigger event listener
|
||||
await hass.async_block_till_done()
|
||||
config._store.set_authorized.assert_called_once_with(False)
|
||||
|
@ -731,39 +731,39 @@ async def test_proactive_mode_filter_states(
|
|||
assert len(aioclient_mock.mock_calls) == 0
|
||||
|
||||
# hass not running should not report
|
||||
current_state = hass.state
|
||||
hass.set_state(core.CoreState.stopping)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
hass.states.async_set(
|
||||
"binary_sensor.test_contact",
|
||||
"off",
|
||||
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
|
||||
)
|
||||
|
||||
current_state = hass.state
|
||||
hass.set_state(core.CoreState.stopping)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
hass.set_state(current_state)
|
||||
assert len(aioclient_mock.mock_calls) == 0
|
||||
|
||||
# unsupported entity should not report
|
||||
hass.states.async_set(
|
||||
"binary_sensor.test_contact",
|
||||
"on",
|
||||
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
|
||||
)
|
||||
with patch.dict(
|
||||
"homeassistant.components.alexa.state_report.ENTITY_ADAPTERS", {}, clear=True
|
||||
):
|
||||
hass.states.async_set(
|
||||
"binary_sensor.test_contact",
|
||||
"on",
|
||||
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
assert len(aioclient_mock.mock_calls) == 0
|
||||
|
||||
# Not exposed by config should not report
|
||||
hass.states.async_set(
|
||||
"binary_sensor.test_contact",
|
||||
"off",
|
||||
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
|
||||
)
|
||||
with patch.object(config, "should_expose", return_value=False):
|
||||
hass.states.async_set(
|
||||
"binary_sensor.test_contact",
|
||||
"off",
|
||||
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
assert len(aioclient_mock.mock_calls) == 0
|
||||
|
|
Loading…
Reference in New Issue