mirror of
https://github.com/home-assistant/core.git
synced 2026-07-12 17:18:04 +01:00
Fix ZHA device trigger cache not resolving quirks (#175895)
This commit is contained in:
committed by
Franck Nijhof
parent
c91e899283
commit
00c5bcd1d3
@@ -9,6 +9,7 @@ from yarl import URL
|
||||
from zha.application.const import BAUD_RATES, RadioType
|
||||
from zha.application.gateway import Gateway
|
||||
from zha.application.helpers import ZHAData
|
||||
from zha.quirks import DEVICE_REGISTRY
|
||||
from zha.zigbee.device import get_device_automation_triggers
|
||||
from zigpy.config import CONF_DATABASE, CONF_DEVICE, CONF_DEVICE_PATH
|
||||
from zigpy.exceptions import NetworkSettingsInconsistent, TransientConnectionError
|
||||
@@ -158,11 +159,15 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
||||
|
||||
zha_gateway = await Gateway.async_from_config(zha_lib_data)
|
||||
|
||||
# Load and cache device trigger information early
|
||||
# Load and cache device trigger information early. Quirks were registered by
|
||||
# `Gateway.async_from_config` above, so pass the resolver to quirk devices
|
||||
# and surface quirk-defined triggers (e.g. remote button presses).
|
||||
device_registry = dr.async_get(hass)
|
||||
radio_mgr = ZhaRadioManager.from_config_entry(hass, config_entry)
|
||||
|
||||
async with radio_mgr.create_zigpy_app(connect=False) as app:
|
||||
async with radio_mgr.create_zigpy_app(
|
||||
connect=False, device_resolver=DEVICE_REGISTRY.resolve
|
||||
) as app:
|
||||
for dev in app.devices.values():
|
||||
dev_entry = device_registry.async_get_device(
|
||||
identifiers={(DOMAIN, str(dev.ieee))},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""ZHA radio manager."""
|
||||
|
||||
import asyncio
|
||||
from collections.abc import AsyncGenerator
|
||||
from collections.abc import AsyncGenerator, Callable
|
||||
import contextlib
|
||||
from contextlib import suppress
|
||||
import copy
|
||||
@@ -22,6 +22,7 @@ from zigpy.config import (
|
||||
CONF_NWK_BACKUP_ENABLED,
|
||||
SCHEMA_DEVICE,
|
||||
)
|
||||
import zigpy.device
|
||||
from zigpy.exceptions import NetworkNotFormed
|
||||
|
||||
from homeassistant import config_entries
|
||||
@@ -174,9 +175,17 @@ class ZhaRadioManager:
|
||||
|
||||
@contextlib.asynccontextmanager
|
||||
async def create_zigpy_app(
|
||||
self, *, connect: bool = True
|
||||
self,
|
||||
*,
|
||||
connect: bool = True,
|
||||
device_resolver: Callable[[zigpy.device.Device], zigpy.device.Device]
|
||||
| None = None,
|
||||
) -> AsyncGenerator[ControllerApplication]:
|
||||
"""Connect to the radio with the current config and then clean up."""
|
||||
"""Connect to the radio with the current config and then clean up.
|
||||
|
||||
`device_resolver` is forwarded to zigpy so devices loaded from the
|
||||
database are quirk-resolved to get quirk-defined device triggers.
|
||||
"""
|
||||
assert self.radio_type is not None
|
||||
|
||||
config = get_zha_data(self.hass).yaml_config
|
||||
@@ -201,7 +210,10 @@ class ZhaRadioManager:
|
||||
app_config[CONF_USE_THREAD] = False
|
||||
|
||||
app = await self.radio_type.controller.new(
|
||||
app_config, auto_form=False, start_radio=False
|
||||
app_config,
|
||||
auto_form=False,
|
||||
start_radio=False,
|
||||
device_resolver=device_resolver,
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
"""ZHA device automation trigger tests."""
|
||||
|
||||
from collections.abc import Callable, Coroutine
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from zha.application.const import ATTR_ENDPOINT_ID
|
||||
from zha.application.const import ATTR_ENDPOINT_ID, RadioType
|
||||
from zha.quirks import DEVICE_REGISTRY
|
||||
from zigpy.application import ControllerApplication
|
||||
from zigpy.device import Device as ZigpyDevice
|
||||
import zigpy.profiles.zha
|
||||
@@ -558,3 +559,28 @@ async def test_validate_trigger_config_unloaded_bad_info(
|
||||
)
|
||||
|
||||
assert "Unable to find trigger" in caplog.text
|
||||
|
||||
|
||||
async def test_device_trigger_cache_built_with_quirk_resolver(
|
||||
zigpy_app_controller: ControllerApplication,
|
||||
setup_zha: Callable[..., Coroutine[None]],
|
||||
) -> None:
|
||||
"""Test the early device trigger cache is built with quirk resolution.
|
||||
|
||||
Regression test: without quirk resolution, quirk-defined triggers (e.g.
|
||||
remote button presses) are missing whenever the cache is used as a
|
||||
fallback (i.e. before ZHA has finished loading).
|
||||
"""
|
||||
with patch.object(
|
||||
RadioType.ezsp.controller,
|
||||
"new",
|
||||
AsyncMock(return_value=zigpy_app_controller),
|
||||
) as mock_new:
|
||||
await setup_zha()
|
||||
|
||||
# Both the trigger cache app and the gateway app must quirk-resolve devices
|
||||
assert len(mock_new.await_args_list) == 2
|
||||
assert all(
|
||||
call.kwargs.get("device_resolver") == DEVICE_REGISTRY.resolve
|
||||
for call in mock_new.await_args_list
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user