Improve Wemo config entry support, add device info (#30963)
* Improve config entry support, add device info * async_dispatch_connect * Fix I/O in event loop * Do not raise PlatformNotReady inside dispatcher * Make main discovery process async * Do discovery as part of set up. * Greatly simplify set up * Add parallel updates to fan&switch * mini cleanup * Address comments
This commit is contained in:
parent
90e811df20
commit
f14d34560e
5 changed files with 206 additions and 189 deletions
|
@ -1,4 +1,5 @@
|
|||
"""Support for WeMo device discovery."""
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
import pywemo
|
||||
|
@ -6,9 +7,9 @@ import requests
|
|||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.discovery import SERVICE_WEMO
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.helpers import config_validation as cv, discovery
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
|
@ -26,9 +27,6 @@ WEMO_MODEL_DISPATCH = {
|
|||
"Socket": "switch",
|
||||
}
|
||||
|
||||
SUBSCRIPTION_REGISTRY = None
|
||||
KNOWN_DEVICES = []
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -70,9 +68,13 @@ CONFIG_SCHEMA = vol.Schema(
|
|||
)
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
async def async_setup(hass, config):
|
||||
"""Set up for WeMo devices."""
|
||||
hass.data[DOMAIN] = config
|
||||
hass.data[DOMAIN] = {
|
||||
"config": config.get(DOMAIN, {}),
|
||||
"registry": None,
|
||||
"pending": {},
|
||||
}
|
||||
|
||||
if DOMAIN in config:
|
||||
hass.async_create_task(
|
||||
|
@ -86,106 +88,103 @@ def setup(hass, config):
|
|||
|
||||
async def async_setup_entry(hass, entry):
|
||||
"""Set up a wemo config entry."""
|
||||
|
||||
config = hass.data[DOMAIN]
|
||||
|
||||
# Keep track of WeMo devices
|
||||
devices = []
|
||||
config = hass.data[DOMAIN].pop("config")
|
||||
|
||||
# Keep track of WeMo device subscriptions for push updates
|
||||
global SUBSCRIPTION_REGISTRY
|
||||
SUBSCRIPTION_REGISTRY = pywemo.SubscriptionRegistry()
|
||||
await hass.async_add_executor_job(SUBSCRIPTION_REGISTRY.start)
|
||||
registry = hass.data[DOMAIN]["registry"] = pywemo.SubscriptionRegistry()
|
||||
await hass.async_add_executor_job(registry.start)
|
||||
|
||||
def stop_wemo(event):
|
||||
"""Shutdown Wemo subscriptions and subscription thread on exit."""
|
||||
_LOGGER.debug("Shutting down WeMo event subscriptions")
|
||||
SUBSCRIPTION_REGISTRY.stop()
|
||||
registry.stop()
|
||||
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_wemo)
|
||||
|
||||
def setup_url_for_device(device):
|
||||
"""Determine setup.xml url for given device."""
|
||||
return f"http://{device.host}:{device.port}/setup.xml"
|
||||
devices = {}
|
||||
|
||||
def setup_url_for_address(host, port):
|
||||
"""Determine setup.xml url for given host and port pair."""
|
||||
if not port:
|
||||
port = pywemo.ouimeaux_device.probe_wemo(host)
|
||||
|
||||
if not port:
|
||||
return None
|
||||
|
||||
return f"http://{host}:{port}/setup.xml"
|
||||
|
||||
def discovery_dispatch(service, discovery_info):
|
||||
"""Dispatcher for incoming WeMo discovery events."""
|
||||
# name, model, location, mac
|
||||
model_name = discovery_info.get("model_name")
|
||||
serial = discovery_info.get("serial")
|
||||
|
||||
# Only register a device once
|
||||
if serial in KNOWN_DEVICES:
|
||||
_LOGGER.debug("Ignoring known device %s %s", service, discovery_info)
|
||||
return
|
||||
|
||||
_LOGGER.debug("Discovered unique WeMo device: %s", serial)
|
||||
KNOWN_DEVICES.append(serial)
|
||||
|
||||
component = WEMO_MODEL_DISPATCH.get(model_name, "switch")
|
||||
|
||||
discovery.load_platform(hass, component, DOMAIN, discovery_info, config)
|
||||
|
||||
discovery.async_listen(hass, SERVICE_WEMO, discovery_dispatch)
|
||||
|
||||
def discover_wemo_devices(now):
|
||||
"""Run discovery for WeMo devices."""
|
||||
_LOGGER.debug("Beginning WeMo device discovery...")
|
||||
static_conf = config.get(CONF_STATIC, [])
|
||||
if static_conf:
|
||||
_LOGGER.debug("Adding statically configured WeMo devices...")
|
||||
for host, port in config.get(DOMAIN, {}).get(CONF_STATIC, []):
|
||||
url = setup_url_for_address(host, port)
|
||||
|
||||
if not url:
|
||||
_LOGGER.error(
|
||||
"Unable to get description url for WeMo at: %s",
|
||||
f"{host}:{port}" if port else host,
|
||||
)
|
||||
for device in await asyncio.gather(
|
||||
*[
|
||||
hass.async_add_executor_job(validate_static_config, host, port)
|
||||
for host, port in static_conf
|
||||
]
|
||||
):
|
||||
if device is None:
|
||||
continue
|
||||
|
||||
try:
|
||||
device = pywemo.discovery.device_from_description(url, None)
|
||||
except (
|
||||
requests.exceptions.ConnectionError,
|
||||
requests.exceptions.Timeout,
|
||||
) as err:
|
||||
_LOGGER.error("Unable to access WeMo at %s (%s)", url, err)
|
||||
continue
|
||||
devices.setdefault(device.serialnumber, device)
|
||||
|
||||
if not [d[1] for d in devices if d[1].serialnumber == device.serialnumber]:
|
||||
devices.append((url, device))
|
||||
if config.get(CONF_DISCOVERY, DEFAULT_DISCOVERY):
|
||||
_LOGGER.debug("Scanning network for WeMo devices...")
|
||||
for device in await hass.async_add_executor_job(pywemo.discover_devices):
|
||||
devices.setdefault(
|
||||
device.serialnumber, device,
|
||||
)
|
||||
|
||||
if config.get(DOMAIN, {}).get(CONF_DISCOVERY, DEFAULT_DISCOVERY):
|
||||
_LOGGER.debug("Scanning network for WeMo devices...")
|
||||
for device in pywemo.discover_devices():
|
||||
if not [
|
||||
d[1] for d in devices if d[1].serialnumber == device.serialnumber
|
||||
]:
|
||||
devices.append((setup_url_for_device(device), device))
|
||||
loaded_components = set()
|
||||
|
||||
for url, device in devices:
|
||||
_LOGGER.debug("Adding WeMo device at %s:%i", device.host, device.port)
|
||||
for device in devices.values():
|
||||
_LOGGER.debug(
|
||||
"Adding WeMo device at %s:%i (%s)",
|
||||
device.host,
|
||||
device.port,
|
||||
device.serialnumber,
|
||||
)
|
||||
|
||||
discovery_info = {
|
||||
"model_name": device.model_name,
|
||||
"serial": device.serialnumber,
|
||||
"mac_address": device.mac,
|
||||
"ssdp_description": url,
|
||||
}
|
||||
component = WEMO_MODEL_DISPATCH.get(device.model_name, "switch")
|
||||
|
||||
discovery_dispatch(SERVICE_WEMO, discovery_info)
|
||||
# Three cases:
|
||||
# - First time we see component, we need to load it and initialize the backlog
|
||||
# - Component is being loaded, add to backlog
|
||||
# - Component is loaded, backlog is gone, dispatch discovery
|
||||
|
||||
_LOGGER.debug("WeMo device discovery has finished")
|
||||
if component not in loaded_components:
|
||||
hass.data[DOMAIN]["pending"][component] = [device]
|
||||
loaded_components.add(component)
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setup(entry, component)
|
||||
)
|
||||
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, discover_wemo_devices)
|
||||
elif component in hass.data[DOMAIN]["pending"]:
|
||||
hass.data[DOMAIN]["pending"].append(device)
|
||||
|
||||
else:
|
||||
async_dispatcher_send(
|
||||
hass, f"{DOMAIN}.{component}", device,
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def validate_static_config(host, port):
|
||||
"""Handle a static config."""
|
||||
url = setup_url_for_address(host, port)
|
||||
|
||||
if not url:
|
||||
_LOGGER.error(
|
||||
"Unable to get description url for WeMo at: %s",
|
||||
f"{host}:{port}" if port else host,
|
||||
)
|
||||
return None
|
||||
|
||||
try:
|
||||
device = pywemo.discovery.device_from_description(url, None)
|
||||
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout,) as err:
|
||||
_LOGGER.error("Unable to access WeMo at %s (%s)", url, err)
|
||||
return None
|
||||
|
||||
return device
|
||||
|
||||
|
||||
def setup_url_for_address(host, port):
|
||||
"""Determine setup.xml url for given host and port pair."""
|
||||
if not port:
|
||||
port = pywemo.ouimeaux_device.probe_wemo(host)
|
||||
|
||||
if not port:
|
||||
return None
|
||||
|
||||
return f"http://{host}:{port}/setup.xml"
|
||||
|
|
|
@ -3,41 +3,36 @@ import asyncio
|
|||
import logging
|
||||
|
||||
import async_timeout
|
||||
from pywemo import discovery
|
||||
import requests
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||
from homeassistant.exceptions import PlatformNotReady
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
|
||||
from . import SUBSCRIPTION_REGISTRY
|
||||
from .const import DOMAIN as WEMO_DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
"""Register discovered WeMo binary sensors."""
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Set up WeMo binary sensors."""
|
||||
|
||||
if discovery_info is not None:
|
||||
location = discovery_info["ssdp_description"]
|
||||
mac = discovery_info["mac_address"]
|
||||
async def _discovered_wemo(device):
|
||||
"""Handle a discovered Wemo device."""
|
||||
async_add_entities([WemoBinarySensor(device)])
|
||||
|
||||
try:
|
||||
device = discovery.device_from_description(location, mac)
|
||||
except (
|
||||
requests.exceptions.ConnectionError,
|
||||
requests.exceptions.Timeout,
|
||||
) as err:
|
||||
_LOGGER.error("Unable to access %s (%s)", location, err)
|
||||
raise PlatformNotReady
|
||||
async_dispatcher_connect(hass, f"{WEMO_DOMAIN}.binary_sensor", _discovered_wemo)
|
||||
|
||||
if device:
|
||||
add_entities([WemoBinarySensor(hass, device)])
|
||||
await asyncio.gather(
|
||||
*[
|
||||
_discovered_wemo(device)
|
||||
for device in hass.data[WEMO_DOMAIN]["pending"].pop("binary_sensor")
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class WemoBinarySensor(BinarySensorDevice):
|
||||
"""Representation a WeMo binary sensor."""
|
||||
|
||||
def __init__(self, hass, device):
|
||||
def __init__(self, device):
|
||||
"""Initialize the WeMo sensor."""
|
||||
self.wemo = device
|
||||
self._state = None
|
||||
|
@ -67,7 +62,7 @@ class WemoBinarySensor(BinarySensorDevice):
|
|||
# Define inside async context so we know our event loop
|
||||
self._update_lock = asyncio.Lock()
|
||||
|
||||
registry = SUBSCRIPTION_REGISTRY
|
||||
registry = self.hass.data[WEMO_DOMAIN]["registry"]
|
||||
await self.hass.async_add_executor_job(registry.register, self.wemo)
|
||||
registry.on(self.wemo, None, self._subscription_callback)
|
||||
|
||||
|
@ -126,3 +121,13 @@ class WemoBinarySensor(BinarySensorDevice):
|
|||
def available(self):
|
||||
"""Return true if sensor is available."""
|
||||
return self._available
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
"""Return the device info."""
|
||||
return {
|
||||
"name": self.wemo.name,
|
||||
"identifiers": {(WEMO_DOMAIN, self.wemo.serialnumber)},
|
||||
"model": self.wemo.model_name,
|
||||
"manufacturer": "Belkin",
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ from datetime import timedelta
|
|||
import logging
|
||||
|
||||
import async_timeout
|
||||
from pywemo import discovery
|
||||
import requests
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.fan import (
|
||||
|
@ -17,14 +15,17 @@ from homeassistant.components.fan import (
|
|||
FanEntity,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID
|
||||
from homeassistant.exceptions import PlatformNotReady
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
|
||||
from . import SUBSCRIPTION_REGISTRY
|
||||
from .const import DOMAIN, SERVICE_RESET_FILTER_LIFE, SERVICE_SET_HUMIDITY
|
||||
from .const import (
|
||||
DOMAIN as WEMO_DOMAIN,
|
||||
SERVICE_RESET_FILTER_LIFE,
|
||||
SERVICE_SET_HUMIDITY,
|
||||
)
|
||||
|
||||
SCAN_INTERVAL = timedelta(seconds=10)
|
||||
DATA_KEY = "fan.wemo"
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -91,36 +92,30 @@ SET_HUMIDITY_SCHEMA = vol.Schema(
|
|||
RESET_FILTER_LIFE_SCHEMA = vol.Schema({vol.Required(ATTR_ENTITY_ID): cv.entity_ids})
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
"""Set up discovered WeMo humidifiers."""
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Set up WeMo binary sensors."""
|
||||
entities = []
|
||||
|
||||
if DATA_KEY not in hass.data:
|
||||
hass.data[DATA_KEY] = {}
|
||||
async def _discovered_wemo(device):
|
||||
"""Handle a discovered Wemo device."""
|
||||
entity = WemoHumidifier(device)
|
||||
entities.append(entity)
|
||||
async_add_entities([entity])
|
||||
|
||||
if discovery_info is None:
|
||||
return
|
||||
async_dispatcher_connect(hass, f"{WEMO_DOMAIN}.fan", _discovered_wemo)
|
||||
|
||||
location = discovery_info["ssdp_description"]
|
||||
mac = discovery_info["mac_address"]
|
||||
|
||||
try:
|
||||
device = WemoHumidifier(discovery.device_from_description(location, mac))
|
||||
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as err:
|
||||
_LOGGER.error("Unable to access %s (%s)", location, err)
|
||||
raise PlatformNotReady
|
||||
|
||||
hass.data[DATA_KEY][device.entity_id] = device
|
||||
add_entities([device])
|
||||
await asyncio.gather(
|
||||
*[
|
||||
_discovered_wemo(device)
|
||||
for device in hass.data[WEMO_DOMAIN]["pending"].pop("fan")
|
||||
]
|
||||
)
|
||||
|
||||
def service_handle(service):
|
||||
"""Handle the WeMo humidifier services."""
|
||||
entity_ids = service.data.get(ATTR_ENTITY_ID)
|
||||
|
||||
humidifiers = [
|
||||
device
|
||||
for device in hass.data[DATA_KEY].values()
|
||||
if device.entity_id in entity_ids
|
||||
]
|
||||
humidifiers = [entity for entity in entities if entity.entity_id in entity_ids]
|
||||
|
||||
if service.service == SERVICE_SET_HUMIDITY:
|
||||
target_humidity = service.data.get(ATTR_TARGET_HUMIDITY)
|
||||
|
@ -132,12 +127,12 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||
humidifier.reset_filter_life()
|
||||
|
||||
# Register service(s)
|
||||
hass.services.register(
|
||||
DOMAIN, SERVICE_SET_HUMIDITY, service_handle, schema=SET_HUMIDITY_SCHEMA
|
||||
hass.services.async_register(
|
||||
WEMO_DOMAIN, SERVICE_SET_HUMIDITY, service_handle, schema=SET_HUMIDITY_SCHEMA
|
||||
)
|
||||
|
||||
hass.services.register(
|
||||
DOMAIN,
|
||||
hass.services.async_register(
|
||||
WEMO_DOMAIN,
|
||||
SERVICE_RESET_FILTER_LIFE,
|
||||
service_handle,
|
||||
schema=RESET_FILTER_LIFE_SCHEMA,
|
||||
|
@ -199,6 +194,16 @@ class WemoHumidifier(FanEntity):
|
|||
"""Return true if switch is available."""
|
||||
return self._available
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
"""Return the device info."""
|
||||
return {
|
||||
"name": self.wemo.name,
|
||||
"identifiers": {(WEMO_DOMAIN, self.wemo.serialnumber)},
|
||||
"model": self.wemo.model_name,
|
||||
"manufacturer": "Belkin",
|
||||
}
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Return the icon of device based on its type."""
|
||||
|
@ -236,7 +241,7 @@ class WemoHumidifier(FanEntity):
|
|||
# Define inside async context so we know our event loop
|
||||
self._update_lock = asyncio.Lock()
|
||||
|
||||
registry = SUBSCRIPTION_REGISTRY
|
||||
registry = self.hass.data[WEMO_DOMAIN]["registry"]
|
||||
await self.hass.async_add_executor_job(registry.register, self.wemo)
|
||||
registry.on(self.wemo, None, self._subscription_callback)
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@ from datetime import timedelta
|
|||
import logging
|
||||
|
||||
import async_timeout
|
||||
from pywemo import discovery
|
||||
import requests
|
||||
|
||||
from homeassistant import util
|
||||
from homeassistant.components.light import (
|
||||
|
@ -19,10 +17,10 @@ from homeassistant.components.light import (
|
|||
SUPPORT_TRANSITION,
|
||||
Light,
|
||||
)
|
||||
from homeassistant.exceptions import PlatformNotReady
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
import homeassistant.util.color as color_util
|
||||
|
||||
from . import SUBSCRIPTION_REGISTRY
|
||||
from .const import DOMAIN as WEMO_DOMAIN
|
||||
|
||||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
||||
MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(milliseconds=100)
|
||||
|
@ -34,29 +32,29 @@ SUPPORT_WEMO = (
|
|||
)
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
"""Set up discovered WeMo switches."""
|
||||
|
||||
if discovery_info is not None:
|
||||
location = discovery_info["ssdp_description"]
|
||||
mac = discovery_info["mac_address"]
|
||||
|
||||
try:
|
||||
device = discovery.device_from_description(location, mac)
|
||||
except (
|
||||
requests.exceptions.ConnectionError,
|
||||
requests.exceptions.Timeout,
|
||||
) as err:
|
||||
_LOGGER.error("Unable to access %s (%s)", location, err)
|
||||
raise PlatformNotReady
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Set up WeMo lights."""
|
||||
|
||||
async def _discovered_wemo(device):
|
||||
"""Handle a discovered Wemo device."""
|
||||
if device.model_name == "Dimmer":
|
||||
add_entities([WemoDimmer(device)])
|
||||
async_add_entities([WemoDimmer(device)])
|
||||
else:
|
||||
setup_bridge(device, add_entities)
|
||||
await hass.async_add_executor_job(
|
||||
setup_bridge, hass, device, async_add_entities
|
||||
)
|
||||
|
||||
async_dispatcher_connect(hass, f"{WEMO_DOMAIN}.light", _discovered_wemo)
|
||||
|
||||
await asyncio.gather(
|
||||
*[
|
||||
_discovered_wemo(device)
|
||||
for device in hass.data[WEMO_DOMAIN]["pending"].pop("light")
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def setup_bridge(bridge, add_entities):
|
||||
def setup_bridge(hass, bridge, async_add_entities):
|
||||
"""Set up a WeMo link."""
|
||||
lights = {}
|
||||
|
||||
|
@ -73,7 +71,7 @@ def setup_bridge(bridge, add_entities):
|
|||
new_lights.append(lights[light_id])
|
||||
|
||||
if new_lights:
|
||||
add_entities(new_lights)
|
||||
hass.add_job(async_add_entities, new_lights)
|
||||
|
||||
update_lights()
|
||||
|
||||
|
@ -110,6 +108,16 @@ class WemoLight(Light):
|
|||
"""Return the name of the light."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
"""Return the device info."""
|
||||
return {
|
||||
"name": self.wemo.name,
|
||||
"identifiers": {(WEMO_DOMAIN, self.wemo.serialnumber)},
|
||||
"model": self.wemo.model_name,
|
||||
"manufacturer": "Belkin",
|
||||
}
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
"""Return the brightness of this light between 0..255."""
|
||||
|
@ -235,7 +243,7 @@ class WemoDimmer(Light):
|
|||
# Define inside async context so we know our event loop
|
||||
self._update_lock = asyncio.Lock()
|
||||
|
||||
registry = SUBSCRIPTION_REGISTRY
|
||||
registry = self.hass.data[WEMO_DOMAIN]["registry"]
|
||||
await self.hass.async_add_executor_job(registry.register, self.wemo)
|
||||
registry.on(self.wemo, None, self._subscription_callback)
|
||||
|
||||
|
|
|
@ -4,18 +4,16 @@ from datetime import datetime, timedelta
|
|||
import logging
|
||||
|
||||
import async_timeout
|
||||
from pywemo import discovery
|
||||
import requests
|
||||
|
||||
from homeassistant.components.switch import SwitchDevice
|
||||
from homeassistant.const import STATE_OFF, STATE_ON, STATE_STANDBY, STATE_UNKNOWN
|
||||
from homeassistant.exceptions import PlatformNotReady
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.util import convert
|
||||
|
||||
from . import SUBSCRIPTION_REGISTRY
|
||||
from .const import DOMAIN
|
||||
from .const import DOMAIN as WEMO_DOMAIN
|
||||
|
||||
SCAN_INTERVAL = timedelta(seconds=10)
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -32,24 +30,21 @@ WEMO_OFF = 0
|
|||
WEMO_STANDBY = 8
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
"""Set up discovered WeMo switches."""
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Set up WeMo switches."""
|
||||
|
||||
if discovery_info is not None:
|
||||
location = discovery_info["ssdp_description"]
|
||||
mac = discovery_info["mac_address"]
|
||||
async def _discovered_wemo(device):
|
||||
"""Handle a discovered Wemo device."""
|
||||
async_add_entities([WemoSwitch(device)])
|
||||
|
||||
try:
|
||||
device = discovery.device_from_description(location, mac)
|
||||
except (
|
||||
requests.exceptions.ConnectionError,
|
||||
requests.exceptions.Timeout,
|
||||
) as err:
|
||||
_LOGGER.error("Unable to access %s (%s)", location, err)
|
||||
raise PlatformNotReady
|
||||
async_dispatcher_connect(hass, f"{WEMO_DOMAIN}.switch", _discovered_wemo)
|
||||
|
||||
if device:
|
||||
add_entities([WemoSwitch(device)])
|
||||
await asyncio.gather(
|
||||
*[
|
||||
_discovered_wemo(device)
|
||||
for device in hass.data[WEMO_DOMAIN]["pending"].pop("switch")
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class WemoSwitch(SwitchDevice):
|
||||
|
@ -97,7 +92,12 @@ class WemoSwitch(SwitchDevice):
|
|||
@property
|
||||
def device_info(self):
|
||||
"""Return the device info."""
|
||||
return {"name": self._name, "identifiers": {(DOMAIN, self._serialnumber)}}
|
||||
return {
|
||||
"name": self.wemo.name,
|
||||
"identifiers": {(WEMO_DOMAIN, self.wemo.serialnumber)},
|
||||
"model": self.wemo.model_name,
|
||||
"manufacturer": "Belkin",
|
||||
}
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
|
@ -200,7 +200,7 @@ class WemoSwitch(SwitchDevice):
|
|||
# Define inside async context so we know our event loop
|
||||
self._update_lock = asyncio.Lock()
|
||||
|
||||
registry = SUBSCRIPTION_REGISTRY
|
||||
registry = self.hass.data[WEMO_DOMAIN]["registry"]
|
||||
await self.hass.async_add_job(registry.register, self.wemo)
|
||||
registry.on(self.wemo, None, self._subscription_callback)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue