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:
parent
1c7242a37a
commit
9316f566c9
2 changed files with 55 additions and 28 deletions
|
@ -1,5 +1,6 @@
|
||||||
"""Support for WeMo device discovery."""
|
"""Support for WeMo device discovery."""
|
||||||
import asyncio
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import pywemo
|
import pywemo
|
||||||
|
@ -16,9 +17,14 @@ from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.helpers.event import async_call_later
|
from homeassistant.helpers.event import async_call_later
|
||||||
|
from homeassistant.util.async_ import gather_with_concurrency
|
||||||
|
|
||||||
from .const import DOMAIN
|
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.
|
# Mapping from Wemo model_name to domain.
|
||||||
WEMO_MODEL_DISPATCH = {
|
WEMO_MODEL_DISPATCH = {
|
||||||
"Bridge": LIGHT_DOMAIN,
|
"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
|
# Keep track of WeMo device subscriptions for push updates
|
||||||
registry = hass.data[DOMAIN]["registry"] = pywemo.SubscriptionRegistry()
|
registry = hass.data[DOMAIN]["registry"] = pywemo.SubscriptionRegistry()
|
||||||
await hass.async_add_executor_job(registry.start)
|
await hass.async_add_executor_job(registry.start)
|
||||||
|
static_conf = config.get(CONF_STATIC, [])
|
||||||
wemo_dispatcher = WemoDispatcher(entry)
|
wemo_dispatcher = WemoDispatcher(entry)
|
||||||
wemo_discovery = WemoDiscovery(hass, wemo_dispatcher)
|
wemo_discovery = WemoDiscovery(hass, wemo_dispatcher, static_conf)
|
||||||
|
|
||||||
async def async_stop_wemo(event):
|
async def async_stop_wemo(event):
|
||||||
"""Shutdown Wemo subscriptions and subscription thread on exit."""
|
"""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)
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_stop_wemo)
|
||||||
)
|
)
|
||||||
|
|
||||||
static_conf = config.get(CONF_STATIC, [])
|
# Need to do this at least once in case statics are defined and discovery is disabled
|
||||||
if static_conf:
|
await wemo_discovery.discover_statics()
|
||||||
_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)
|
|
||||||
|
|
||||||
if config.get(CONF_DISCOVERY, DEFAULT_DISCOVERY):
|
if config.get(CONF_DISCOVERY, DEFAULT_DISCOVERY):
|
||||||
await wemo_discovery.async_discover_and_schedule()
|
await wemo_discovery.async_discover_and_schedule()
|
||||||
|
@ -183,12 +180,18 @@ class WemoDiscovery:
|
||||||
ADDITIONAL_SECONDS_BETWEEN_SCANS = 10
|
ADDITIONAL_SECONDS_BETWEEN_SCANS = 10
|
||||||
MAX_SECONDS_BETWEEN_SCANS = 300
|
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."""
|
"""Initialize the WemoDiscovery."""
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._wemo_dispatcher = wemo_dispatcher
|
self._wemo_dispatcher = wemo_dispatcher
|
||||||
self._stop = None
|
self._stop = None
|
||||||
self._scan_delay = 0
|
self._scan_delay = 0
|
||||||
|
self._static_config = static_config
|
||||||
|
|
||||||
async def async_discover_and_schedule(self, *_) -> None:
|
async def async_discover_and_schedule(self, *_) -> None:
|
||||||
"""Periodically scan the network looking for WeMo devices."""
|
"""Periodically scan the network looking for WeMo devices."""
|
||||||
|
@ -198,6 +201,8 @@ class WemoDiscovery:
|
||||||
pywemo.discover_devices
|
pywemo.discover_devices
|
||||||
):
|
):
|
||||||
self._wemo_dispatcher.async_add_unique_device(self._hass, device)
|
self._wemo_dispatcher.async_add_unique_device(self._hass, device)
|
||||||
|
await self.discover_statics()
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# Run discovery more frequently after hass has just started.
|
# Run discovery more frequently after hass has just started.
|
||||||
self._scan_delay = min(
|
self._scan_delay = min(
|
||||||
|
@ -217,6 +222,22 @@ class WemoDiscovery:
|
||||||
self._stop()
|
self._stop()
|
||||||
self._stop = None
|
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):
|
def validate_static_config(host, port):
|
||||||
"""Handle a static config."""
|
"""Handle a static config."""
|
||||||
|
|
|
@ -117,20 +117,26 @@ async def test_discovery(hass, pywemo_registry):
|
||||||
with patch(
|
with patch(
|
||||||
"pywemo.discover_devices", return_value=pywemo_devices
|
"pywemo.discover_devices", return_value=pywemo_devices
|
||||||
) as mock_discovery:
|
) as mock_discovery:
|
||||||
assert await async_setup_component(
|
with patch(
|
||||||
hass, DOMAIN, {DOMAIN: {CONF_DISCOVERY: True}}
|
"homeassistant.components.wemo.WemoDiscovery.discover_statics"
|
||||||
)
|
) as mock_discover_statics:
|
||||||
await pywemo_registry.semaphore.acquire() # Returns after platform setup.
|
assert await async_setup_component(
|
||||||
mock_discovery.assert_called()
|
hass, DOMAIN, {DOMAIN: {CONF_DISCOVERY: True}}
|
||||||
pywemo_devices.append(create_device(2))
|
)
|
||||||
|
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.
|
# Test that discovery runs periodically and the async_dispatcher_send code works.
|
||||||
async_fire_time_changed(
|
async_fire_time_changed(
|
||||||
hass,
|
hass,
|
||||||
dt.utcnow()
|
dt.utcnow()
|
||||||
+ timedelta(seconds=WemoDiscovery.ADDITIONAL_SECONDS_BETWEEN_SCANS + 1),
|
+ timedelta(seconds=WemoDiscovery.ADDITIONAL_SECONDS_BETWEEN_SCANS + 1),
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
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.
|
# Verify that the expected number of devices were setup.
|
||||||
entity_reg = er.async_get(hass)
|
entity_reg = er.async_get(hass)
|
||||||
|
|
Loading…
Add table
Reference in a new issue