From b54f2c94870cf553e2713964007b179dbd6705e9 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 28 Dec 2021 21:04:11 -0500 Subject: [PATCH] Don't throw when a Zigbee device has an unknown ZCL cluster (#62964) * Fix channel name for clusters with None ep_attribute * Correctly generate entity name based on channel names --- .../components/zha/core/channels/base.py | 3 +- homeassistant/components/zha/entity.py | 3 +- tests/components/zha/test_channels.py | 20 ++++++++++++ tests/components/zha/test_discover.py | 32 +++++++++++++++++++ 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/zha/core/channels/base.py b/homeassistant/components/zha/core/channels/base.py index b6981b4cd74..7728be8a6b2 100644 --- a/homeassistant/components/zha/core/channels/base.py +++ b/homeassistant/components/zha/core/channels/base.py @@ -103,7 +103,6 @@ class ZigbeeChannel(LogMixin): ) -> None: """Initialize ZigbeeChannel.""" self._generic_id = f"channel_0x{cluster.cluster_id:04x}" - self._channel_name = getattr(cluster, "ep_attribute", self._generic_id) self._ch_pool = ch_pool self._cluster = cluster self._id = f"{ch_pool.id}:0x{cluster.cluster_id:04x}" @@ -141,7 +140,7 @@ class ZigbeeChannel(LogMixin): @property def name(self) -> str: """Return friendly name.""" - return self._channel_name + return self.cluster.ep_attribute or self._generic_id @property def status(self): diff --git a/homeassistant/components/zha/entity.py b/homeassistant/components/zha/entity.py index ee5d2939185..0b7f95efb64 100644 --- a/homeassistant/components/zha/entity.py +++ b/homeassistant/components/zha/entity.py @@ -166,8 +166,7 @@ class ZhaEntity(BaseZhaEntity, RestoreEntity): """Init ZHA entity.""" super().__init__(unique_id, zha_device, **kwargs) ieeetail = "".join([f"{o:02x}" for o in zha_device.ieee[:4]]) - ch_names = [ch.cluster.ep_attribute for ch in channels] - ch_names = ", ".join(sorted(ch_names)) + ch_names = ", ".join(sorted(ch.name for ch in channels)) self._name: str = f"{zha_device.name} {ieeetail} {ch_names}" if self.unique_id_suffix: self._name += f" {self.unique_id_suffix}" diff --git a/tests/components/zha/test_channels.py b/tests/components/zha/test_channels.py index f4ec40fcb15..9005fd49d8f 100644 --- a/tests/components/zha/test_channels.py +++ b/tests/components/zha/test_channels.py @@ -619,3 +619,23 @@ async def test_zll_device_groups( zigpy_coordinator_device.add_to_group.await_args_list[1][0][0] == group_2.group_id ) + + +@mock.patch( + "homeassistant.components.zha.core.channels.ChannelPool.add_client_channels" +) +@mock.patch( + "homeassistant.components.zha.core.discovery.PROBE.discover_entities", + mock.MagicMock(), +) +async def test_cluster_no_ep_attribute(m1, zha_device_mock): + """Test channels for clusters without ep_attribute.""" + + zha_device = zha_device_mock( + {1: {SIG_EP_INPUT: [0x042E], SIG_EP_OUTPUT: [], SIG_EP_TYPE: 0x1234}}, + ) + + channels = zha_channels.Channels.new(zha_device) + pools = {pool.id: pool for pool in channels.pools} + assert "1:0x042e" in pools[1].all_channels + assert pools[1].all_channels["1:0x042e"].name diff --git a/tests/components/zha/test_discover.py b/tests/components/zha/test_discover.py index fd489d7c5d5..9953b6e9d15 100644 --- a/tests/components/zha/test_discover.py +++ b/tests/components/zha/test_discover.py @@ -461,3 +461,35 @@ async def test_group_probe_cleanup_called( await config_entry.async_unload(hass_disable_services) await hass_disable_services.async_block_till_done() disc.GROUP_PROBE.cleanup.assert_called() + + +@patch( + "zigpy.zcl.clusters.general.Identify.request", + new=AsyncMock(return_value=[mock.sentinel.data, zcl_f.Status.SUCCESS]), +) +@patch( + "homeassistant.components.zha.entity.ZhaEntity.entity_registry_enabled_default", + new=Mock(return_value=True), +) +async def test_channel_with_empty_ep_attribute_cluster( + hass_disable_services, + zigpy_device_mock, + zha_device_joined_restored, +): + """Test device discovery for cluster which does not have em_attribute.""" + entity_registry = homeassistant.helpers.entity_registry.async_get( + hass_disable_services + ) + + zigpy_device = zigpy_device_mock( + {1: {SIG_EP_INPUT: [0x042E], SIG_EP_OUTPUT: [], SIG_EP_TYPE: 0x1234}}, + "00:11:22:33:44:55:66:77", + "test manufacturer", + "test model", + patch_cluster=False, + ) + zha_dev = await zha_device_joined_restored(zigpy_device) + ha_entity_id = entity_registry.async_get_entity_id( + "sensor", "zha", f"{zha_dev.ieee}-1-1070" + ) + assert ha_entity_id is not None