From 0619069ae60932a2f912ded4187216ddb7ba0b08 Mon Sep 17 00:00:00 2001 From: jjlawren Date: Wed, 15 Sep 2021 03:07:31 -0500 Subject: [PATCH] Avoid a zeroconf race condition (#56240) --- homeassistant/components/sonos/speaker.py | 36 ++++++++++------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/sonos/speaker.py b/homeassistant/components/sonos/speaker.py index 30d107bdd8d..bf0a8c589ee 100644 --- a/homeassistant/components/sonos/speaker.py +++ b/homeassistant/components/sonos/speaker.py @@ -485,6 +485,15 @@ class SonosSpeaker: # # Speaker availability methods # + @callback + def _async_reset_seen_timer(self): + """Reset the _seen_timer scheduler.""" + if self._seen_timer: + self._seen_timer() + self._seen_timer = self.hass.helpers.event.async_call_later( + SEEN_EXPIRE_TIME.total_seconds(), self.async_unseen + ) + async def async_seen(self, soco: SoCo | None = None) -> None: """Record that this speaker was seen right now.""" if soco is not None: @@ -492,12 +501,7 @@ class SonosSpeaker: was_available = self.available - if self._seen_timer: - self._seen_timer() - - self._seen_timer = self.hass.helpers.event.async_call_later( - SEEN_EXPIRE_TIME.total_seconds(), self.async_unseen - ) + self._async_reset_seen_timer() if was_available: self.async_write_entity_states() @@ -512,8 +516,6 @@ class SonosSpeaker: if self._is_ready and not self.subscriptions_failed: done = await self.async_subscribe() if not done: - assert self._seen_timer is not None - self._seen_timer() await self.async_unseen() self.async_write_entity_states() @@ -522,10 +524,6 @@ class SonosSpeaker: self, callback_timestamp: datetime.datetime | None = None ) -> None: """Make this player unavailable when it was not seen recently.""" - if self._seen_timer: - self._seen_timer() - self._seen_timer = None - if callback_timestamp: # Called by a _seen_timer timeout, check mDNS one more time # This should not be checked in an "active" unseen scenario @@ -534,9 +532,7 @@ class SonosSpeaker: aiozeroconf = await zeroconf.async_get_async_instance(self.hass) if await aiozeroconf.async_get_service_info(MDNS_SERVICE, zcname): # We can still see the speaker via zeroconf check again later. - self._seen_timer = self.hass.helpers.event.async_call_later( - SEEN_EXPIRE_TIME.total_seconds(), self.async_unseen - ) + self._async_reset_seen_timer() return _LOGGER.debug( @@ -546,6 +542,10 @@ class SonosSpeaker: self._share_link_plugin = None + if self._seen_timer: + self._seen_timer() + self._seen_timer = None + if self._poll_timer: self._poll_timer() self._poll_timer = None @@ -565,11 +565,7 @@ class SonosSpeaker: await self.async_unsubscribe() self.soco = soco await self.async_subscribe() - if self._seen_timer: - self._seen_timer() - self._seen_timer = self.hass.helpers.event.async_call_later( - SEEN_EXPIRE_TIME.total_seconds(), self.async_unseen - ) + self._async_reset_seen_timer() self.async_write_entity_states() #