ZHA: Successful pairing feedback (#32456)
This commit is contained in:
parent
76fec90fec
commit
e416f17e4d
6 changed files with 56 additions and 3 deletions
|
@ -251,3 +251,9 @@ ZHA_GW_MSG_LOG_OUTPUT = "log_output"
|
|||
ZHA_GW_MSG_RAW_INIT = "raw_device_initialized"
|
||||
ZHA_GW_RADIO = "radio"
|
||||
ZHA_GW_RADIO_DESCRIPTION = "radio_description"
|
||||
|
||||
EFFECT_BLINK = 0x00
|
||||
EFFECT_BREATHE = 0x01
|
||||
EFFECT_OKAY = 0x02
|
||||
|
||||
EFFECT_DEFAULT_VARIANT = 0x00
|
||||
|
|
|
@ -48,6 +48,8 @@ from .const import (
|
|||
CLUSTER_COMMANDS_SERVER,
|
||||
CLUSTER_TYPE_IN,
|
||||
CLUSTER_TYPE_OUT,
|
||||
EFFECT_DEFAULT_VARIANT,
|
||||
EFFECT_OKAY,
|
||||
POWER_BATTERY_OR_UNKNOWN,
|
||||
POWER_MAINS_POWERED,
|
||||
SIGNAL_AVAILABLE,
|
||||
|
@ -342,6 +344,11 @@ class ZHADevice(LogMixin):
|
|||
entry = self.gateway.zha_storage.async_create_or_update(self)
|
||||
self.debug("stored in registry: %s", entry)
|
||||
|
||||
if self._channels.identify_ch is not None:
|
||||
await self._channels.identify_ch.trigger_effect(
|
||||
EFFECT_OKAY, EFFECT_DEFAULT_VARIANT
|
||||
)
|
||||
|
||||
async def async_initialize(self, from_cache=False):
|
||||
"""Initialize channels."""
|
||||
self.debug("started initialization")
|
||||
|
|
|
@ -19,6 +19,9 @@ from .core.const import (
|
|||
CHANNEL_ON_OFF,
|
||||
DATA_ZHA,
|
||||
DATA_ZHA_DISPATCHERS,
|
||||
EFFECT_BLINK,
|
||||
EFFECT_BREATHE,
|
||||
EFFECT_DEFAULT_VARIANT,
|
||||
SIGNAL_ADD_ENTITIES,
|
||||
SIGNAL_ATTR_UPDATED,
|
||||
SIGNAL_SET_LEVEL,
|
||||
|
@ -38,7 +41,7 @@ UPDATE_COLORLOOP_DIRECTION = 0x2
|
|||
UPDATE_COLORLOOP_TIME = 0x4
|
||||
UPDATE_COLORLOOP_HUE = 0x8
|
||||
|
||||
FLASH_EFFECTS = {light.FLASH_SHORT: 0x00, light.FLASH_LONG: 0x01}
|
||||
FLASH_EFFECTS = {light.FLASH_SHORT: EFFECT_BLINK, light.FLASH_LONG: EFFECT_BREATHE}
|
||||
|
||||
UNSUPPORTED_ATTRIBUTE = 0x86
|
||||
SCAN_INTERVAL = timedelta(minutes=60)
|
||||
|
@ -287,7 +290,7 @@ class Light(ZhaEntity, light.Light):
|
|||
|
||||
if flash is not None and self._supported_features & light.SUPPORT_FLASH:
|
||||
result = await self._identify_channel.trigger_effect(
|
||||
FLASH_EFFECTS[flash], 0 # effect identifier, effect variant
|
||||
FLASH_EFFECTS[flash], EFFECT_DEFAULT_VARIANT
|
||||
)
|
||||
t_log["trigger_effect"] = result
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ class FakeEndpoint:
|
|||
self.model = model
|
||||
self.profile_id = zigpy.profiles.zha.PROFILE_ID
|
||||
self.device_type = None
|
||||
self.request = CoroutineMock()
|
||||
|
||||
def add_input_cluster(self, cluster_id):
|
||||
"""Add an input cluster."""
|
||||
|
|
|
@ -166,7 +166,9 @@ def zha_device_restored(hass, zigpy_app_controller, setup_zha):
|
|||
@pytest.fixture(params=["zha_device_joined", "zha_device_restored"])
|
||||
def zha_device_joined_restored(request):
|
||||
"""Join or restore ZHA device."""
|
||||
return request.getfixturevalue(request.param)
|
||||
named_method = request.getfixturevalue(request.param)
|
||||
named_method.name = request.param
|
||||
return named_method
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
import re
|
||||
from unittest import mock
|
||||
|
||||
import asynctest
|
||||
import pytest
|
||||
import zigpy.quirks
|
||||
import zigpy.types
|
||||
import zigpy.zcl.clusters.closures
|
||||
import zigpy.zcl.clusters.general
|
||||
import zigpy.zcl.clusters.security
|
||||
import zigpy.zcl.foundation as zcl_f
|
||||
|
||||
import homeassistant.components.zha.binary_sensor
|
||||
import homeassistant.components.zha.core.channels as zha_channels
|
||||
|
@ -48,6 +51,12 @@ def channels_mock(zha_device_mock):
|
|||
return _mock
|
||||
|
||||
|
||||
@asynctest.patch(
|
||||
"zigpy.zcl.clusters.general.Identify.request",
|
||||
new=asynctest.CoroutineMock(
|
||||
return_value=[mock.sentinel.data, zcl_f.Status.SUCCESS]
|
||||
),
|
||||
)
|
||||
@pytest.mark.parametrize("device", DEVICES)
|
||||
async def test_devices(
|
||||
device, hass, zigpy_device_mock, monkeypatch, zha_device_joined_restored
|
||||
|
@ -66,6 +75,10 @@ async def test_devices(
|
|||
node_descriptor=device["node_descriptor"],
|
||||
)
|
||||
|
||||
cluster_identify = _get_first_identify_cluster(zigpy_device)
|
||||
if cluster_identify:
|
||||
cluster_identify.request.reset_mock()
|
||||
|
||||
orig_new_entity = zha_channels.ChannelPool.async_new_entity
|
||||
_dispatch = mock.MagicMock(wraps=orig_new_entity)
|
||||
try:
|
||||
|
@ -81,6 +94,21 @@ async def test_devices(
|
|||
ent for ent in entity_ids if ent.split(".")[0] in zha_const.COMPONENTS
|
||||
}
|
||||
|
||||
if cluster_identify:
|
||||
called = int(zha_device_joined_restored.name == "zha_device_joined")
|
||||
assert cluster_identify.request.call_count == called
|
||||
assert cluster_identify.request.await_count == called
|
||||
if called:
|
||||
assert cluster_identify.request.call_args == mock.call(
|
||||
False,
|
||||
64,
|
||||
(zigpy.types.uint8_t, zigpy.types.uint8_t),
|
||||
2,
|
||||
0,
|
||||
expect_reply=True,
|
||||
manufacturer=None,
|
||||
)
|
||||
|
||||
event_channels = {
|
||||
ch.id for pool in zha_dev.channels.pools for ch in pool.relay_channels.values()
|
||||
}
|
||||
|
@ -108,6 +136,12 @@ async def test_devices(
|
|||
assert entity_cls.__name__ == entity_map[key]["entity_class"]
|
||||
|
||||
|
||||
def _get_first_identify_cluster(zigpy_device):
|
||||
for endpoint in list(zigpy_device.endpoints.values())[1:]:
|
||||
if hasattr(endpoint, "identify"):
|
||||
return endpoint.identify
|
||||
|
||||
|
||||
@mock.patch(
|
||||
"homeassistant.components.zha.core.discovery.ProbeEndpoint.discover_by_device_type"
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue