mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 20:27:08 +00:00
This reverts commit 6e52b26c06098052d379065b00f570c2a44653e1.
This commit is contained in:
parent
62d8e47c51
commit
f05f60c4c4
@ -1,4 +1,5 @@
|
||||
"""Support for WeMo device discovery."""
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
import pywemo
|
||||
@ -15,14 +16,9 @@ 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,
|
||||
@ -118,12 +114,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||
static_conf = config.get(CONF_STATIC, [])
|
||||
if static_conf:
|
||||
_LOGGER.debug("Adding statically configured WeMo devices...")
|
||||
for device in await gather_with_concurrency(
|
||||
MAX_CONCURRENCY,
|
||||
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)
|
||||
@ -192,44 +187,15 @@ class WemoDiscovery:
|
||||
self._wemo_dispatcher = wemo_dispatcher
|
||||
self._stop = None
|
||||
self._scan_delay = 0
|
||||
self._upnp_entries = set()
|
||||
|
||||
async def async_add_from_upnp_entry(self, entry: pywemo.ssdp.UPNPEntry) -> None:
|
||||
"""Create a WeMoDevice from an UPNPEntry and add it to the dispatcher.
|
||||
|
||||
Uses the self._upnp_entries set to avoid interrogating the same device
|
||||
multiple times.
|
||||
"""
|
||||
if entry in self._upnp_entries:
|
||||
return
|
||||
try:
|
||||
device = await self._hass.async_add_executor_job(
|
||||
pywemo.discovery.device_from_uuid_and_location,
|
||||
entry.udn,
|
||||
entry.location,
|
||||
)
|
||||
except pywemo.PyWeMoException as err:
|
||||
_LOGGER.error("Unable to setup WeMo %r (%s)", entry, err)
|
||||
else:
|
||||
self._wemo_dispatcher.async_add_unique_device(self._hass, device)
|
||||
self._upnp_entries.add(entry)
|
||||
|
||||
async def async_discover_and_schedule(self, *_) -> None:
|
||||
"""Periodically scan the network looking for WeMo devices."""
|
||||
_LOGGER.debug("Scanning network for WeMo devices...")
|
||||
try:
|
||||
# pywemo.ssdp.scan is a light-weight UDP UPnP scan for WeMo devices.
|
||||
entries = await self._hass.async_add_executor_job(pywemo.ssdp.scan)
|
||||
|
||||
# async_add_from_upnp_entry causes multiple HTTP requests to be sent
|
||||
# to the WeMo device for the initial setup of the WeMoDevice
|
||||
# instance. This may take some time to complete. The per-device
|
||||
# setup work is done in parallel to speed up initial setup for the
|
||||
# component.
|
||||
await gather_with_concurrency(
|
||||
MAX_CONCURRENCY,
|
||||
*[self.async_add_from_upnp_entry(entry) for entry in entries],
|
||||
)
|
||||
for device in await self._hass.async_add_executor_job(
|
||||
pywemo.discover_devices
|
||||
):
|
||||
self._wemo_dispatcher.async_add_unique_device(self._hass, device)
|
||||
finally:
|
||||
# Run discovery more frequently after hass has just started.
|
||||
self._scan_delay = min(
|
||||
|
@ -100,41 +100,28 @@ async def test_static_config_with_invalid_host(hass):
|
||||
async def test_discovery(hass, pywemo_registry):
|
||||
"""Verify that discovery dispatches devices to the platform for setup."""
|
||||
|
||||
def create_device(uuid, location):
|
||||
def create_device(counter):
|
||||
"""Create a unique mock Motion detector device for each counter value."""
|
||||
device = create_autospec(pywemo.Motion, instance=True)
|
||||
device.host = location
|
||||
device.port = MOCK_PORT
|
||||
device.name = f"{MOCK_NAME}_{uuid}"
|
||||
device.serialnumber = f"{MOCK_SERIAL_NUMBER}_{uuid}"
|
||||
device.host = f"{MOCK_HOST}_{counter}"
|
||||
device.port = MOCK_PORT + counter
|
||||
device.name = f"{MOCK_NAME}_{counter}"
|
||||
device.serialnumber = f"{MOCK_SERIAL_NUMBER}_{counter}"
|
||||
device.model_name = "Motion"
|
||||
device.get_state.return_value = 0 # Default to Off
|
||||
return device
|
||||
|
||||
def create_upnp_entry(counter):
|
||||
return pywemo.ssdp.UPNPEntry.from_response(
|
||||
"\r\n".join(
|
||||
[
|
||||
"",
|
||||
f"LOCATION: http://192.168.1.100:{counter}/setup.xml",
|
||||
f"USN: uuid:Socket-1_0-SERIAL{counter}::upnp:rootdevice",
|
||||
"",
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
upnp_entries = [create_upnp_entry(0), create_upnp_entry(1)]
|
||||
pywemo_devices = [create_device(0), create_device(1)]
|
||||
# Setup the component and start discovery.
|
||||
with patch(
|
||||
"pywemo.discovery.device_from_uuid_and_location", side_effect=create_device
|
||||
), patch("pywemo.ssdp.scan", return_value=upnp_entries) as mock_scan:
|
||||
"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_scan.assert_called()
|
||||
# Add two of the same entries to test deduplication.
|
||||
upnp_entries.extend([create_upnp_entry(2), create_upnp_entry(2)])
|
||||
mock_discovery.assert_called()
|
||||
pywemo_devices.append(create_device(2))
|
||||
|
||||
# Test that discovery runs periodically and the async_dispatcher_send code works.
|
||||
async_fire_time_changed(
|
||||
|
Loading…
x
Reference in New Issue
Block a user