Rescan static wemo (#49934)

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
CantankerousBullMoose 2021-05-17 03:18:14 -07:00 committed by GitHub
parent 1c7242a37a
commit 9316f566c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 28 deletions

View File

@ -1,5 +1,6 @@
"""Support for WeMo device discovery."""
import asyncio
from __future__ import annotations
import logging
import pywemo
@ -16,9 +17,14 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.event import async_call_later
from homeassistant.util.async_ import gather_with_concurrency
from .const import DOMAIN
# Max number of devices to initialize at once. This limit is in place to
# avoid tying up too many executor threads with WeMo device setup.
MAX_CONCURRENCY = 3
# Mapping from Wemo model_name to domain.
WEMO_MODEL_DISPATCH = {
"Bridge": LIGHT_DOMAIN,
@ -99,9 +105,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
# Keep track of WeMo device subscriptions for push updates
registry = hass.data[DOMAIN]["registry"] = pywemo.SubscriptionRegistry()
await hass.async_add_executor_job(registry.start)
static_conf = config.get(CONF_STATIC, [])
wemo_dispatcher = WemoDispatcher(entry)
wemo_discovery = WemoDiscovery(hass, wemo_dispatcher)
wemo_discovery = WemoDiscovery(hass, wemo_dispatcher, static_conf)
async def async_stop_wemo(event):
"""Shutdown Wemo subscriptions and subscription thread on exit."""
@ -113,17 +119,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_stop_wemo)
)
static_conf = config.get(CONF_STATIC, [])
if static_conf:
_LOGGER.debug("Adding statically configured WeMo devices")
for device in await asyncio.gather(
*[
hass.async_add_executor_job(validate_static_config, host, port)
for host, port in static_conf
]
):
if device:
wemo_dispatcher.async_add_unique_device(hass, device)
# Need to do this at least once in case statics are defined and discovery is disabled
await wemo_discovery.discover_statics()
if config.get(CONF_DISCOVERY, DEFAULT_DISCOVERY):
await wemo_discovery.async_discover_and_schedule()
@ -183,12 +180,18 @@ class WemoDiscovery:
ADDITIONAL_SECONDS_BETWEEN_SCANS = 10
MAX_SECONDS_BETWEEN_SCANS = 300
def __init__(self, hass: HomeAssistant, wemo_dispatcher: WemoDispatcher) -> None:
def __init__(
self,
hass: HomeAssistant,
wemo_dispatcher: WemoDispatcher,
static_config: list[tuple[[str, str | None]]],
) -> None:
"""Initialize the WemoDiscovery."""
self._hass = hass
self._wemo_dispatcher = wemo_dispatcher
self._stop = None
self._scan_delay = 0
self._static_config = static_config
async def async_discover_and_schedule(self, *_) -> None:
"""Periodically scan the network looking for WeMo devices."""
@ -198,6 +201,8 @@ class WemoDiscovery:
pywemo.discover_devices
):
self._wemo_dispatcher.async_add_unique_device(self._hass, device)
await self.discover_statics()
finally:
# Run discovery more frequently after hass has just started.
self._scan_delay = min(
@ -217,6 +222,22 @@ class WemoDiscovery:
self._stop()
self._stop = None
async def discover_statics(self):
"""Initialize or Re-Initialize connections to statically configured devices."""
if self._static_config:
_LOGGER.debug("Adding statically configured WeMo devices")
for device in await gather_with_concurrency(
MAX_CONCURRENCY,
*[
self._hass.async_add_executor_job(
validate_static_config, host, port
)
for host, port in self._static_config
],
):
if device:
self._wemo_dispatcher.async_add_unique_device(self._hass, device)
def validate_static_config(host, port):
"""Handle a static config."""

View File

@ -117,20 +117,26 @@ async def test_discovery(hass, pywemo_registry):
with patch(
"pywemo.discover_devices", return_value=pywemo_devices
) as mock_discovery:
assert await async_setup_component(
hass, DOMAIN, {DOMAIN: {CONF_DISCOVERY: True}}
)
await pywemo_registry.semaphore.acquire() # Returns after platform setup.
mock_discovery.assert_called()
pywemo_devices.append(create_device(2))
with patch(
"homeassistant.components.wemo.WemoDiscovery.discover_statics"
) as mock_discover_statics:
assert await async_setup_component(
hass, DOMAIN, {DOMAIN: {CONF_DISCOVERY: True}}
)
await pywemo_registry.semaphore.acquire() # Returns after platform setup.
mock_discovery.assert_called()
mock_discover_statics.assert_called()
pywemo_devices.append(create_device(2))
# Test that discovery runs periodically and the async_dispatcher_send code works.
async_fire_time_changed(
hass,
dt.utcnow()
+ timedelta(seconds=WemoDiscovery.ADDITIONAL_SECONDS_BETWEEN_SCANS + 1),
)
await hass.async_block_till_done()
# Test that discovery runs periodically and the async_dispatcher_send code works.
async_fire_time_changed(
hass,
dt.utcnow()
+ timedelta(seconds=WemoDiscovery.ADDITIONAL_SECONDS_BETWEEN_SCANS + 1),
)
await hass.async_block_till_done()
# Test that discover_statics runs during discovery
assert mock_discover_statics.call_count == 3
# Verify that the expected number of devices were setup.
entity_reg = er.async_get(hass)