From 5ae207001ff9459f91ed85a63129d71e04b8cdfc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 12 Mar 2024 07:49:17 -1000 Subject: [PATCH] Avoid multiple executor jobs to add wemo devices (#112484) --- homeassistant/components/wemo/wemo_device.py | 29 ++++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/wemo/wemo_device.py b/homeassistant/components/wemo/wemo_device.py index f2bd93fa2b1..fae4f87c239 100644 --- a/homeassistant/components/wemo/wemo_device.py +++ b/homeassistant/components/wemo/wemo_device.py @@ -6,7 +6,7 @@ import asyncio from dataclasses import dataclass, fields from datetime import timedelta import logging -from typing import Literal +from typing import TYPE_CHECKING, Literal from pywemo import Insight, LongPressMixin, WeMoDevice from pywemo.exceptions import ActionException, PyWeMoException @@ -92,7 +92,7 @@ class DeviceCoordinator(DataUpdateCoordinator[None]): # pylint: disable=hass-en options: Options | None = None - def __init__(self, hass: HomeAssistant, wemo: WeMoDevice, device_id: str) -> None: + def __init__(self, hass: HomeAssistant, wemo: WeMoDevice) -> None: """Initialize DeviceCoordinator.""" super().__init__( hass, @@ -102,11 +102,16 @@ class DeviceCoordinator(DataUpdateCoordinator[None]): # pylint: disable=hass-en ) self.hass = hass self.wemo = wemo - self.device_id = device_id + self.device_id: str | None = None self.device_info = _create_device_info(wemo) self.supports_long_press = isinstance(wemo, LongPressMixin) self.update_lock = asyncio.Lock() + @callback + def async_setup(self, device_id: str) -> None: + """Set up the device coordinator.""" + self.device_id = device_id + def subscription_callback( self, _device: WeMoDevice, event_type: str, params: str ) -> None: @@ -130,6 +135,9 @@ class DeviceCoordinator(DataUpdateCoordinator[None]): # pylint: disable=hass-en async def async_shutdown(self) -> None: """Unregister push subscriptions and remove from coordinators dict.""" await super().async_shutdown() + if TYPE_CHECKING: + # mypy doesn't known that the device_id is set in async_setup. + assert self.device_id is not None del _async_coordinators(self.hass)[self.device_id] assert self.options # Always set by async_register_device. if self.options.enable_subscription: @@ -222,7 +230,10 @@ class DeviceCoordinator(DataUpdateCoordinator[None]): # pylint: disable=hass-en async def _async_update_data(self) -> None: """Update WeMo state.""" # No need to poll if the device will push updates. - if not self.should_poll: + # The device_id will not be set until after the first + # update so we should not check should_poll until after + # the device_id is set. + if self.device_id and not self.should_poll: return # If an update is in progress, we don't do anything. @@ -266,15 +277,15 @@ async def async_register_device( hass: HomeAssistant, config_entry: ConfigEntry, wemo: WeMoDevice ) -> DeviceCoordinator: """Register a device with home assistant and enable pywemo event callbacks.""" - # Ensure proper communication with the device and get the initial state. - await hass.async_add_executor_job(wemo.get_state, True) - + device = DeviceCoordinator(hass, wemo) + await device.async_refresh() + if not device.last_update_success and device.last_exception: + raise device.last_exception device_registry = async_get_device_registry(hass) entry = device_registry.async_get_or_create( config_entry_id=config_entry.entry_id, **_create_device_info(wemo) ) - - device = DeviceCoordinator(hass, wemo, entry.id) + device.async_setup(device_id=entry.id) _async_coordinators(hass)[entry.id] = device config_entry.async_on_unload(