From 2ad0ebe7aaa7f602a1785d32f2a599de0ddd8e87 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 10 Dec 2021 23:23:09 -1000 Subject: [PATCH] Ensure bulbs are still reported offline if an update is deferred (#226) --- flux_led/aiodevice.py | 7 +++++++ tests_aio.py | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/flux_led/aiodevice.py b/flux_led/aiodevice.py index 568ae33a..e41a47bc 100644 --- a/flux_led/aiodevice.py +++ b/flux_led/aiodevice.py @@ -192,11 +192,13 @@ async def async_update(self) -> None: # then no need to poll except for the interval # to make sure the device is still responding if self._protocol.state_push_updates: + self._async_raise_if_offline() return elif self._protocol.power_push_updates: # If the device pushes power updates # then no need to poll except for the interval # to make sure the device is still responding + self._async_raise_if_offline() return self._last_update_time = now if self._updates_without_response == MAX_UPDATES_WITHOUT_RESPONSE: @@ -208,6 +210,11 @@ async def async_update(self) -> None: await self._async_send_state_query() self._updates_without_response += 1 + def _async_raise_if_offline(self) -> None: + """Raise RuntimeError if the bulb is offline.""" + if not self.available: + raise RuntimeError("Bulb not responding, too soon to retry") + async def async_set_levels( self, r: Optional[int] = None, diff --git a/tests_aio.py b/tests_aio.py index 2ec6c4c7..1b5ddb4d 100644 --- a/tests_aio.py +++ b/tests_aio.py @@ -1060,6 +1060,25 @@ def _updated_callback(*args, **kwargs): await asyncio.sleep(0) assert len(transport.mock_calls) == 0 + transport.reset_mock() + for _ in range(4): + light._last_update_time = aiodevice.NEVER_TIME + await light.async_update() + await asyncio.sleep(0) + assert len(transport.mock_calls) == 4 + + light._last_update_time = aiodevice.NEVER_TIME + for _ in range(4): + # First failure should keep the device in + # a failure state until we get to an update + # time + with pytest.raises(RuntimeError): + await light.async_update() + + # Should not raise now that bulb has recovered + light._last_update_time = aiodevice.NEVER_TIME + await light.async_update() + @pytest.mark.asyncio async def test_async_scanner(mock_discovery_aio_protocol):