diff --git a/homeassistant/components/discovery/__init__.py b/homeassistant/components/discovery/__init__.py index 0541b5d223a19f..a7c306ad241147 100644 --- a/homeassistant/components/discovery/__init__.py +++ b/homeassistant/components/discovery/__init__.py @@ -58,7 +58,6 @@ SERVICE_MOBILE_APP: ('mobile_app', None), SERVICE_HASS_IOS_APP: ('ios', None), SERVICE_NETGEAR: ('device_tracker', None), - SERVICE_WEMO: ('wemo', None), SERVICE_HASSIO: ('hassio', None), SERVICE_APPLE_TV: ('apple_tv', None), SERVICE_ENIGMA2: ('media_player', 'enigma2'), @@ -94,19 +93,20 @@ SERVICE_DLNA_DMR: ('media_player', 'dlna_dmr'), } -MIGRATED_SERVICE_HANDLERS = { - 'axis': None, - 'deconz': None, - 'esphome': None, - 'ikea_tradfri': None, - 'homekit': None, - 'philips_hue': None -} +MIGRATED_SERVICE_HANDLERS = [ + 'axis', + 'deconz', + 'esphome', + 'ikea_tradfri', + 'homekit', + 'philips_hue', + SERVICE_WEMO, +] DEFAULT_ENABLED = list(CONFIG_ENTRY_HANDLERS) + list(SERVICE_HANDLERS) + \ - list(MIGRATED_SERVICE_HANDLERS) + MIGRATED_SERVICE_HANDLERS DEFAULT_DISABLED = list(OPTIONAL_SERVICE_HANDLERS) + \ - list(MIGRATED_SERVICE_HANDLERS) + MIGRATED_SERVICE_HANDLERS CONF_IGNORE = 'ignore' CONF_ENABLE = 'enable' diff --git a/homeassistant/components/wemo/__init__.py b/homeassistant/components/wemo/__init__.py index d921075bc1a6f9..8353b52b9f0d37 100644 --- a/homeassistant/components/wemo/__init__.py +++ b/homeassistant/components/wemo/__init__.py @@ -4,6 +4,7 @@ import requests import voluptuous as vol +from homeassistant import config_entries from homeassistant.components.discovery import SERVICE_WEMO from homeassistant.helpers import config_validation as cv from homeassistant.helpers import discovery @@ -68,22 +69,35 @@ def coerce_host_port(value): def setup(hass, config): """Set up for WeMo devices.""" + hass.data[DOMAIN] = config + + if DOMAIN in config: + hass.async_create_task(hass.config_entries.flow.async_init( + DOMAIN, context={'source': config_entries.SOURCE_IMPORT})) + + return True + + +async def async_setup_entry(hass, entry): + """Set up a wemo config entry.""" import pywemo + config = hass.data[DOMAIN] + # Keep track of WeMo devices devices = [] # Keep track of WeMo device subscriptions for push updates global SUBSCRIPTION_REGISTRY SUBSCRIPTION_REGISTRY = pywemo.SubscriptionRegistry() - SUBSCRIPTION_REGISTRY.start() + await hass.async_add_executor_job(SUBSCRIPTION_REGISTRY.start) def stop_wemo(event): """Shutdown Wemo subscriptions and subscription thread on exit.""" _LOGGER.debug("Shutting down WeMo event subscriptions") SUBSCRIPTION_REGISTRY.stop() - hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_wemo) + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_wemo) def setup_url_for_device(device): """Determine setup.xml url for given device.""" @@ -119,7 +133,7 @@ def discovery_dispatch(service, discovery_info): discovery.load_platform( hass, component, DOMAIN, discovery_info, config) - discovery.listen(hass, SERVICE_WEMO, discovery_dispatch) + discovery.async_listen(hass, SERVICE_WEMO, discovery_dispatch) def discover_wemo_devices(now): """Run discovery for WeMo devices.""" @@ -145,7 +159,7 @@ def discover_wemo_devices(now): if d[1].serialnumber == device.serialnumber]: devices.append((url, device)) - if config.get(DOMAIN, {}).get(CONF_DISCOVERY): + 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 @@ -168,6 +182,7 @@ def discover_wemo_devices(now): _LOGGER.debug("WeMo device discovery has finished") - hass.bus.listen_once(EVENT_HOMEASSISTANT_START, discover_wemo_devices) + hass.bus.async_listen_once( + EVENT_HOMEASSISTANT_START, discover_wemo_devices) return True diff --git a/homeassistant/components/wemo/config_flow.py b/homeassistant/components/wemo/config_flow.py new file mode 100644 index 00000000000000..61094dbab3209b --- /dev/null +++ b/homeassistant/components/wemo/config_flow.py @@ -0,0 +1,15 @@ +"""Config flow for Wemo.""" +from homeassistant.helpers import config_entry_flow +from homeassistant import config_entries +from . import DOMAIN + + +async def _async_has_devices(hass): + """Return if there are devices that can be discovered.""" + import pywemo + + return bool(pywemo.discover_devices()) + + +config_entry_flow.register_discovery_flow( + DOMAIN, 'Wemo', _async_has_devices, config_entries.CONN_CLASS_LOCAL_PUSH) diff --git a/homeassistant/components/wemo/manifest.json b/homeassistant/components/wemo/manifest.json index 238be891886859..c610c28da394f0 100644 --- a/homeassistant/components/wemo/manifest.json +++ b/homeassistant/components/wemo/manifest.json @@ -1,10 +1,16 @@ { "domain": "wemo", "name": "Wemo", + "config_flow": true, "documentation": "https://www.home-assistant.io/components/wemo", "requirements": [ "pywemo==0.4.34" ], + "ssdp": { + "manufacturer": [ + "Belkin International Inc." + ] + }, "dependencies": [], "codeowners": [ "@sqldiablo" diff --git a/homeassistant/components/wemo/strings.json b/homeassistant/components/wemo/strings.json new file mode 100644 index 00000000000000..d4b40817cb395c --- /dev/null +++ b/homeassistant/components/wemo/strings.json @@ -0,0 +1,15 @@ +{ + "config": { + "title": "Wemo", + "step": { + "confirm": { + "title": "Wemo", + "description": "Do you want to set up Wemo?" + } + }, + "abort": { + "single_instance_allowed": "Only a single configuration of Wemo is possible.", + "no_devices_found": "No Wemo devices found on the network." + } + } +} diff --git a/homeassistant/generated/config_flows.py b/homeassistant/generated/config_flows.py index 41b03264c4f5be..955cdf3c8c4dcc 100644 --- a/homeassistant/generated/config_flows.py +++ b/homeassistant/generated/config_flows.py @@ -50,6 +50,7 @@ "twilio", "unifi", "upnp", + "wemo", "zha", "zone", "zwave" diff --git a/homeassistant/generated/ssdp.py b/homeassistant/generated/ssdp.py index e4c4b1e9eb30e2..63dbe7616db370 100644 --- a/homeassistant/generated/ssdp.py +++ b/homeassistant/generated/ssdp.py @@ -7,6 +7,9 @@ SSDP = { "device_type": {}, "manufacturer": { + "Belkin International Inc.": [ + "wemo" + ], "Royal Philips Electronics": [ "deconz", "hue" diff --git a/script/hassfest/ssdp.py b/script/hassfest/ssdp.py index b13bc66a8f02e2..9c745e5b033687 100644 --- a/script/hassfest/ssdp.py +++ b/script/hassfest/ssdp.py @@ -43,7 +43,9 @@ def generate_and_validate(integrations: Dict[str, Integration]): try: with open(str(integration.path / "config_flow.py")) as fp: - if ' async_step_ssdp(' not in fp.read(): + content = fp.read() + if (' async_step_ssdp(' not in content and + 'register_discovery_flow' not in content): integration.add_error( 'ssdp', 'Config flow has no async_step_ssdp') continue