From 1d095a3ba1f78dfdc85080ddf49c868634e5ad42 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 2 Apr 2021 16:38:29 -1000 Subject: [PATCH 1/3] Only listen for zeroconf when the esphome device cannot connect Followup to #48129 --- homeassistant/components/esphome/__init__.py | 26 +++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/esphome/__init__.py b/homeassistant/components/esphome/__init__.py index 02d6309fe7f02f..5e7a5f31117d97 100644 --- a/homeassistant/components/esphome/__init__.py +++ b/homeassistant/components/esphome/__init__.py @@ -239,6 +239,8 @@ def __init__( # Flag to check if the device is connected self._connected = True self._connected_lock = asyncio.Lock() + self._zc_lock = asyncio.Lock() + self._zc_listening = False # Event the different strategies use for issuing a reconnect attempt. self._reconnect_event = asyncio.Event() # The task containing the infinite reconnect loop while running @@ -293,6 +295,7 @@ async def _wait_and_start_reconnect(self): if tries == 1: _LOGGER.info("Trying to reconnect to %s in the background", self._host) _LOGGER.debug("Retrying %s in %d seconds", self._host, wait_time) + await self._start_zc_listen() await asyncio.sleep(wait_time) async with self._wait_task_lock: self._wait_task = None @@ -332,6 +335,7 @@ async def _try_connect(self): self._tries = 0 async with self._connected_lock: self._connected = True + await self._stop_zc_listen() self._hass.async_create_task(self._on_login()) async def _reconnect_once(self): @@ -375,9 +379,6 @@ async def start(self): # Create reconnection loop outside of HA's tracked tasks in order # not to delay startup. self._loop_task = self._hass.loop.create_task(self._reconnect_loop()) - # Listen for mDNS records so we can reconnect directly if a received mDNS record - # indicates the node is up again - await self._hass.async_add_executor_job(self._zc.add_listener, self, None) async with self._connected_lock: self._connected = False @@ -388,11 +389,28 @@ async def stop(self): if self._loop_task is not None: self._loop_task.cancel() self._loop_task = None - await self._hass.async_add_executor_job(self._zc.remove_listener, self) async with self._wait_task_lock: if self._wait_task is not None: self._wait_task.cancel() self._wait_task = None + await self._stop_zc_listen() + + async def _start_zc_listen(self): + """Listen for mDNS records. + + This listener allows us to schedule a reconnect as soon as a + received mDNS record indicates the node is up again. + """ + async with self._zc_lock: + await self._hass.async_add_executor_job(self._zc.add_listener, self, None) + self._zc_listening = True + + async def _stop_zc_listen(self): + """Stop listening for zeroconf updates.""" + async with self._zc_lock: + if self._zc_listening: + await self._hass.async_add_executor_job(self._zc.remove_listener, self) + self._zc_listening = False @callback def stop_callback(self): From c011ff1f9711dc39c32982bf38c49834f52b80ae Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 2 Apr 2021 16:47:31 -1000 Subject: [PATCH 2/3] check for existing listen --- homeassistant/components/esphome/__init__.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/esphome/__init__.py b/homeassistant/components/esphome/__init__.py index 5e7a5f31117d97..41793b7cd2023b 100644 --- a/homeassistant/components/esphome/__init__.py +++ b/homeassistant/components/esphome/__init__.py @@ -402,8 +402,11 @@ async def _start_zc_listen(self): received mDNS record indicates the node is up again. """ async with self._zc_lock: - await self._hass.async_add_executor_job(self._zc.add_listener, self, None) - self._zc_listening = True + if not self._zc_listening: + await self._hass.async_add_executor_job( + self._zc.add_listener, self, None + ) + self._zc_listening = True async def _stop_zc_listen(self): """Stop listening for zeroconf updates.""" From 07a6abbaa4b63f0c7e0068c1fcdf8542c055b6d1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 2 Apr 2021 16:55:42 -1000 Subject: [PATCH 3/3] speed up reconnect --- homeassistant/components/esphome/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/esphome/__init__.py b/homeassistant/components/esphome/__init__.py index 41793b7cd2023b..0caf00af8ef0d5 100644 --- a/homeassistant/components/esphome/__init__.py +++ b/homeassistant/components/esphome/__init__.py @@ -272,6 +272,7 @@ async def _on_disconnect(self): self._entry_data.disconnect_callbacks = [] self._entry_data.available = False self._entry_data.async_update_device_state(self._hass) + await self._start_zc_listen() # Reset tries async with self._tries_lock: @@ -295,7 +296,6 @@ async def _wait_and_start_reconnect(self): if tries == 1: _LOGGER.info("Trying to reconnect to %s in the background", self._host) _LOGGER.debug("Retrying %s in %d seconds", self._host, wait_time) - await self._start_zc_listen() await asyncio.sleep(wait_time) async with self._wait_task_lock: self._wait_task = None @@ -318,6 +318,7 @@ async def _try_connect(self): self._host, error, ) + await self._start_zc_listen() # Schedule re-connect in event loop in order not to delay HA # startup. First connect is scheduled in tracked tasks. async with self._wait_task_lock: