ZHA: Successful pairing feedback (#32456)

This commit is contained in:
Alexei Chetroi 2020-03-04 19:27:37 -05:00 committed by GitHub
parent 76fec90fec
commit e416f17e4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 56 additions and 3 deletions

View File

@ -251,3 +251,9 @@ ZHA_GW_MSG_LOG_OUTPUT = "log_output"
ZHA_GW_MSG_RAW_INIT = "raw_device_initialized" ZHA_GW_MSG_RAW_INIT = "raw_device_initialized"
ZHA_GW_RADIO = "radio" ZHA_GW_RADIO = "radio"
ZHA_GW_RADIO_DESCRIPTION = "radio_description" ZHA_GW_RADIO_DESCRIPTION = "radio_description"
EFFECT_BLINK = 0x00
EFFECT_BREATHE = 0x01
EFFECT_OKAY = 0x02
EFFECT_DEFAULT_VARIANT = 0x00

View File

@ -48,6 +48,8 @@ from .const import (
CLUSTER_COMMANDS_SERVER, CLUSTER_COMMANDS_SERVER,
CLUSTER_TYPE_IN, CLUSTER_TYPE_IN,
CLUSTER_TYPE_OUT, CLUSTER_TYPE_OUT,
EFFECT_DEFAULT_VARIANT,
EFFECT_OKAY,
POWER_BATTERY_OR_UNKNOWN, POWER_BATTERY_OR_UNKNOWN,
POWER_MAINS_POWERED, POWER_MAINS_POWERED,
SIGNAL_AVAILABLE, SIGNAL_AVAILABLE,
@ -342,6 +344,11 @@ class ZHADevice(LogMixin):
entry = self.gateway.zha_storage.async_create_or_update(self) entry = self.gateway.zha_storage.async_create_or_update(self)
self.debug("stored in registry: %s", entry) 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): async def async_initialize(self, from_cache=False):
"""Initialize channels.""" """Initialize channels."""
self.debug("started initialization") self.debug("started initialization")

View File

@ -19,6 +19,9 @@ from .core.const import (
CHANNEL_ON_OFF, CHANNEL_ON_OFF,
DATA_ZHA, DATA_ZHA,
DATA_ZHA_DISPATCHERS, DATA_ZHA_DISPATCHERS,
EFFECT_BLINK,
EFFECT_BREATHE,
EFFECT_DEFAULT_VARIANT,
SIGNAL_ADD_ENTITIES, SIGNAL_ADD_ENTITIES,
SIGNAL_ATTR_UPDATED, SIGNAL_ATTR_UPDATED,
SIGNAL_SET_LEVEL, SIGNAL_SET_LEVEL,
@ -38,7 +41,7 @@ UPDATE_COLORLOOP_DIRECTION = 0x2
UPDATE_COLORLOOP_TIME = 0x4 UPDATE_COLORLOOP_TIME = 0x4
UPDATE_COLORLOOP_HUE = 0x8 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 UNSUPPORTED_ATTRIBUTE = 0x86
SCAN_INTERVAL = timedelta(minutes=60) 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: if flash is not None and self._supported_features & light.SUPPORT_FLASH:
result = await self._identify_channel.trigger_effect( 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 t_log["trigger_effect"] = result

View File

@ -29,6 +29,7 @@ class FakeEndpoint:
self.model = model self.model = model
self.profile_id = zigpy.profiles.zha.PROFILE_ID self.profile_id = zigpy.profiles.zha.PROFILE_ID
self.device_type = None self.device_type = None
self.request = CoroutineMock()
def add_input_cluster(self, cluster_id): def add_input_cluster(self, cluster_id):
"""Add an input cluster.""" """Add an input cluster."""

View File

@ -166,7 +166,9 @@ def zha_device_restored(hass, zigpy_app_controller, setup_zha):
@pytest.fixture(params=["zha_device_joined", "zha_device_restored"]) @pytest.fixture(params=["zha_device_joined", "zha_device_restored"])
def zha_device_joined_restored(request): def zha_device_joined_restored(request):
"""Join or restore ZHA device.""" """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 @pytest.fixture

View File

@ -3,11 +3,14 @@
import re import re
from unittest import mock from unittest import mock
import asynctest
import pytest import pytest
import zigpy.quirks import zigpy.quirks
import zigpy.types
import zigpy.zcl.clusters.closures import zigpy.zcl.clusters.closures
import zigpy.zcl.clusters.general import zigpy.zcl.clusters.general
import zigpy.zcl.clusters.security import zigpy.zcl.clusters.security
import zigpy.zcl.foundation as zcl_f
import homeassistant.components.zha.binary_sensor import homeassistant.components.zha.binary_sensor
import homeassistant.components.zha.core.channels as zha_channels import homeassistant.components.zha.core.channels as zha_channels
@ -48,6 +51,12 @@ def channels_mock(zha_device_mock):
return _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) @pytest.mark.parametrize("device", DEVICES)
async def test_devices( async def test_devices(
device, hass, zigpy_device_mock, monkeypatch, zha_device_joined_restored device, hass, zigpy_device_mock, monkeypatch, zha_device_joined_restored
@ -66,6 +75,10 @@ async def test_devices(
node_descriptor=device["node_descriptor"], 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 orig_new_entity = zha_channels.ChannelPool.async_new_entity
_dispatch = mock.MagicMock(wraps=orig_new_entity) _dispatch = mock.MagicMock(wraps=orig_new_entity)
try: try:
@ -81,6 +94,21 @@ async def test_devices(
ent for ent in entity_ids if ent.split(".")[0] in zha_const.COMPONENTS 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 = { event_channels = {
ch.id for pool in zha_dev.channels.pools for ch in pool.relay_channels.values() 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"] 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( @mock.patch(
"homeassistant.components.zha.core.discovery.ProbeEndpoint.discover_by_device_type" "homeassistant.components.zha.core.discovery.ProbeEndpoint.discover_by_device_type"
) )