Scan all network interfaces for LIFX bulbs (#17530)

This commit is contained in:
Anders Melchiorsen 2018-10-17 10:50:13 +02:00 committed by Paulus Schoutsen
parent 326787ef1a
commit 1e4463957d
3 changed files with 32 additions and 64 deletions

View file

@ -1,8 +1,4 @@
"""Component to embed LIFX.""" """Component to embed LIFX."""
import asyncio
import socket
import async_timeout
import voluptuous as vol import voluptuous as vol
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
@ -12,17 +8,20 @@ from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
DOMAIN = 'lifx' DOMAIN = 'lifx'
REQUIREMENTS = ['aiolifx==0.6.3'] REQUIREMENTS = ['aiolifx==0.6.5']
CONF_SERVER = 'server' CONF_SERVER = 'server'
CONF_BROADCAST = 'broadcast' CONF_BROADCAST = 'broadcast'
INTERFACE_SCHEMA = vol.Schema({
vol.Optional(CONF_SERVER): cv.string,
vol.Optional(CONF_BROADCAST): cv.string,
})
CONFIG_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.Schema({
DOMAIN: { DOMAIN: {
LIGHT_DOMAIN: { LIGHT_DOMAIN:
vol.Optional(CONF_SERVER): cv.string, vol.Schema(vol.All(cv.ensure_list, [INTERFACE_SCHEMA])),
vol.Optional(CONF_BROADCAST): cv.string,
}
} }
}, extra=vol.ALLOW_EXTRA) }, extra=vol.ALLOW_EXTRA)
@ -51,47 +50,9 @@ async def _async_has_devices(hass):
"""Return if there are devices that can be discovered.""" """Return if there are devices that can be discovered."""
import aiolifx import aiolifx
manager = DiscoveryManager() lifx_ip_addresses = await aiolifx.LifxScan(hass.loop).scan()
lifx_discovery = aiolifx.LifxDiscovery(hass.loop, manager) return len(lifx_ip_addresses) > 0
coro = hass.loop.create_datagram_endpoint(
lambda: lifx_discovery,
family=socket.AF_INET)
hass.async_create_task(coro)
has_devices = await manager.found_devices()
lifx_discovery.cleanup()
return has_devices
config_entry_flow.register_discovery_flow( config_entry_flow.register_discovery_flow(
DOMAIN, 'LIFX', _async_has_devices, config_entries.CONN_CLASS_LOCAL_POLL) DOMAIN, 'LIFX', _async_has_devices, config_entries.CONN_CLASS_LOCAL_POLL)
class DiscoveryManager:
"""Temporary LIFX manager for discovering any bulb."""
def __init__(self):
"""Initialize the manager."""
self._event = asyncio.Event()
async def found_devices(self):
"""Return whether any device could be discovered."""
try:
async with async_timeout.timeout(2):
await self._event.wait()
# Let bulbs recover from the discovery
await asyncio.sleep(1)
return True
except asyncio.TimeoutError:
return False
def register(self, bulb):
"""Handle aiolifx detected bulb."""
self._event.set()
def unregister(self, bulb):
"""Handle aiolifx disappearing bulbs."""
pass

View file

@ -5,7 +5,6 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/light.lifx/ https://home-assistant.io/components/light.lifx/
""" """
import asyncio import asyncio
import socket
from datetime import timedelta from datetime import timedelta
from functools import partial from functools import partial
import logging import logging
@ -145,23 +144,31 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
_LOGGER.warning("The lifx platform is known to not work on Windows. " _LOGGER.warning("The lifx platform is known to not work on Windows. "
"Consider using the lifx_legacy platform instead") "Consider using the lifx_legacy platform instead")
config = hass.data[LIFX_DOMAIN].get(DOMAIN, {}) # Priority 1: manual config
interfaces = hass.data[LIFX_DOMAIN].get(DOMAIN)
if not interfaces:
# Priority 2: scanned interfaces
lifx_ip_addresses = await aiolifx().LifxScan(hass.loop).scan()
interfaces = [{CONF_SERVER: ip} for ip in lifx_ip_addresses]
if not interfaces:
# Priority 3: default interface
interfaces = [{}]
lifx_manager = LIFXManager(hass, async_add_entities) lifx_manager = LIFXManager(hass, async_add_entities)
broadcast_ip = config.get(CONF_BROADCAST) for interface in interfaces:
kwargs = {'discovery_interval': DISCOVERY_INTERVAL} kwargs = {'discovery_interval': DISCOVERY_INTERVAL}
if broadcast_ip: broadcast_ip = interface.get(CONF_BROADCAST)
kwargs['broadcast_ip'] = broadcast_ip if broadcast_ip:
lifx_discovery = aiolifx().LifxDiscovery(hass.loop, lifx_manager, **kwargs) kwargs['broadcast_ip'] = broadcast_ip
lifx_discovery = aiolifx().LifxDiscovery(
hass.loop, lifx_manager, **kwargs)
kwargs = {'family': socket.AF_INET} kwargs = {}
local_addr = config.get(CONF_SERVER) listen_ip = interface.get(CONF_SERVER)
if local_addr is not None: if listen_ip:
kwargs['local_addr'] = (local_addr, 0) kwargs['listen_ip'] = listen_ip
coro = hass.loop.create_datagram_endpoint(lambda: lifx_discovery, **kwargs) lifx_discovery.start(**kwargs)
hass.async_create_task(coro)
@callback @callback
def cleanup(event): def cleanup(event):

View file

@ -110,7 +110,7 @@ aiohue==1.5.0
aioimaplib==0.7.13 aioimaplib==0.7.13
# homeassistant.components.lifx # homeassistant.components.lifx
aiolifx==0.6.3 aiolifx==0.6.5
# homeassistant.components.light.lifx # homeassistant.components.light.lifx
aiolifx_effects==0.2.1 aiolifx_effects==0.2.1