From 6204765835ca81f4812c76ea704d68335982e242 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Mon, 5 Apr 2021 00:21:47 -0400 Subject: [PATCH] Implement Ignore list for poll control configuration on Ikea devices (#48667) Co-authored-by: Hmmbob <33529490+hmmbob@users.noreply.github.com> --- .../components/zha/core/channels/general.py | 11 ++++++- tests/components/zha/test_channels.py | 32 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/zha/core/channels/general.py b/homeassistant/components/zha/core/channels/general.py index 626596e1a3e..6ef0bd9e665 100644 --- a/homeassistant/components/zha/core/channels/general.py +++ b/homeassistant/components/zha/core/channels/general.py @@ -391,6 +391,9 @@ class PollControl(ZigbeeChannel): CHECKIN_INTERVAL = 55 * 60 * 4 # 55min CHECKIN_FAST_POLL_TIMEOUT = 2 * 4 # 2s LONG_POLL = 6 * 4 # 6s + _IGNORED_MANUFACTURER_ID = { + 4476, + } # IKEA async def async_configure_channel_specific(self) -> None: """Configure channel: set check-in interval.""" @@ -416,7 +419,13 @@ class PollControl(ZigbeeChannel): async def check_in_response(self, tsn: int) -> None: """Respond to checkin command.""" await self.checkin_response(True, self.CHECKIN_FAST_POLL_TIMEOUT, tsn=tsn) - await self.set_long_poll_interval(self.LONG_POLL) + if self._ch_pool.manufacturer_code not in self._IGNORED_MANUFACTURER_ID: + await self.set_long_poll_interval(self.LONG_POLL) + + @callback + def skip_manufacturer_id(self, manufacturer_code: int) -> None: + """Block a specific manufacturer id from changing default polling.""" + self._IGNORED_MANUFACTURER_ID.add(manufacturer_code) @registries.ZIGBEE_CHANNEL_REGISTRY.register(general.PowerConfiguration.cluster_id) diff --git a/tests/components/zha/test_channels.py b/tests/components/zha/test_channels.py index ec5128fdb5e..a391439a239 100644 --- a/tests/components/zha/test_channels.py +++ b/tests/components/zha/test_channels.py @@ -492,6 +492,38 @@ async def test_poll_control_cluster_command(hass, poll_control_device): assert data["device_id"] == poll_control_device.device_id +async def test_poll_control_ignore_list(hass, poll_control_device): + """Test poll control channel ignore list.""" + set_long_poll_mock = AsyncMock() + poll_control_ch = poll_control_device.channels.pools[0].all_channels["1:0x0020"] + cluster = poll_control_ch.cluster + + with mock.patch.object(cluster, "set_long_poll_interval", set_long_poll_mock): + await poll_control_ch.check_in_response(33) + + assert set_long_poll_mock.call_count == 1 + + set_long_poll_mock.reset_mock() + poll_control_ch.skip_manufacturer_id(4151) + with mock.patch.object(cluster, "set_long_poll_interval", set_long_poll_mock): + await poll_control_ch.check_in_response(33) + + assert set_long_poll_mock.call_count == 0 + + +async def test_poll_control_ikea(hass, poll_control_device): + """Test poll control channel ignore list for ikea.""" + set_long_poll_mock = AsyncMock() + poll_control_ch = poll_control_device.channels.pools[0].all_channels["1:0x0020"] + cluster = poll_control_ch.cluster + + poll_control_device.device.node_desc.manufacturer_code = 4476 + with mock.patch.object(cluster, "set_long_poll_interval", set_long_poll_mock): + await poll_control_ch.check_in_response(33) + + assert set_long_poll_mock.call_count == 0 + + @pytest.fixture def zigpy_zll_device(zigpy_device_mock): """ZLL device fixture."""