Add config entry for LIFX (#17201)

* Add config entry for LIFX

* Use list for dependencies

* Obsolete the platform config

* Use DOMAIN

* Use async_create_task
This commit is contained in:
Anders Melchiorsen 2018-10-07 23:14:53 +02:00 committed by Martin Hjelmare
parent 06a64c0167
commit 086c71525e
7 changed files with 160 additions and 24 deletions

View File

@ -63,7 +63,6 @@ homeassistant/components/device_tracker/huawei_router.py @abmantis
homeassistant/components/device_tracker/tile.py @bachya
homeassistant/components/history_graph.py @andrey-git
homeassistant/components/influx.py @fabaff
homeassistant/components/light/lifx.py @amelchio
homeassistant/components/light/lifx_legacy.py @amelchio
homeassistant/components/light/tplink.py @rytilahti
homeassistant/components/light/yeelight.py @rytilahti
@ -180,6 +179,10 @@ homeassistant/components/*/knx.py @Julius2342
homeassistant/components/konnected.py @heythisisnate
homeassistant/components/*/konnected.py @heythisisnate
# L
homeassistant/components/lifx.py @amelchio
homeassistant/components/*/lifx.py @amelchio
# M
homeassistant/components/matrix.py @tinloaf
homeassistant/components/*/matrix.py @tinloaf

View File

@ -0,0 +1,15 @@
{
"config": {
"abort": {
"no_devices_found": "No LIFX devices found on the network.",
"single_instance_allowed": "Only a single configuration of LIFX is possible."
},
"step": {
"confirm": {
"description": "Do you want to set up LIFX?",
"title": "LIFX"
}
},
"title": "LIFX"
}
}

View File

@ -0,0 +1,97 @@
"""Component to embed LIFX."""
import asyncio
import socket
import async_timeout
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant import config_entries
from homeassistant.helpers import config_entry_flow
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
DOMAIN = 'lifx'
REQUIREMENTS = ['aiolifx==0.6.3']
CONF_SERVER = 'server'
CONF_BROADCAST = 'broadcast'
CONFIG_SCHEMA = vol.Schema({
DOMAIN: {
LIGHT_DOMAIN: {
vol.Optional(CONF_SERVER): cv.string,
vol.Optional(CONF_BROADCAST): cv.string,
}
}
}, extra=vol.ALLOW_EXTRA)
async def async_setup(hass, config):
"""Set up the LIFX component."""
conf = config.get(DOMAIN)
hass.data[DOMAIN] = conf or {}
if conf is not None:
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 LIFX from a config entry."""
hass.async_create_task(hass.config_entries.async_forward_entry_setup(
entry, LIGHT_DOMAIN))
return True
async def _async_has_devices(hass):
"""Return if there are devices that can be discovered."""
import aiolifx
manager = DiscoveryManager()
lifx_discovery = aiolifx.LifxDiscovery(hass.loop, manager)
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(
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

@ -0,0 +1,15 @@
{
"config": {
"title": "LIFX",
"step": {
"confirm": {
"title": "LIFX",
"description": "Do you want to set up LIFX?"
}
},
"abort": {
"single_instance_allowed": "Only a single configuration of LIFX is possible.",
"no_devices_found": "No LIFX devices found on the network."
}
}
}

View File

@ -5,6 +5,7 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/light.lifx/
"""
import asyncio
import socket
from datetime import timedelta
from functools import partial
import logging
@ -17,10 +18,12 @@ from homeassistant import util
from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_COLOR_NAME, ATTR_COLOR_TEMP,
ATTR_EFFECT, ATTR_HS_COLOR, ATTR_KELVIN, ATTR_RGB_COLOR, ATTR_TRANSITION,
ATTR_XY_COLOR, COLOR_GROUP, DOMAIN, LIGHT_TURN_ON_SCHEMA, PLATFORM_SCHEMA,
ATTR_XY_COLOR, COLOR_GROUP, DOMAIN, LIGHT_TURN_ON_SCHEMA,
SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT,
SUPPORT_TRANSITION, VALID_BRIGHTNESS, VALID_BRIGHTNESS_PCT, Light,
preprocess_turn_on_alternatives)
from homeassistant.components.lifx import (
DOMAIN as LIFX_DOMAIN, CONF_SERVER, CONF_BROADCAST)
from homeassistant.const import ATTR_ENTITY_ID, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv
@ -30,23 +33,16 @@ import homeassistant.util.color as color_util
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['aiolifx==0.6.3', 'aiolifx_effects==0.2.1']
DEPENDENCIES = ['lifx']
REQUIREMENTS = ['aiolifx_effects==0.2.1']
UDP_BROADCAST_PORT = 56700
SCAN_INTERVAL = timedelta(seconds=10)
DISCOVERY_INTERVAL = 60
MESSAGE_TIMEOUT = 1.0
MESSAGE_RETRIES = 8
UNAVAILABLE_GRACE = 90
CONF_SERVER = 'server'
CONF_BROADCAST = 'broadcast'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_SERVER, default='0.0.0.0'): cv.string,
vol.Optional(CONF_BROADCAST, default='255.255.255.255'): cv.string,
})
SERVICE_LIFX_SET_STATE = 'lifx_set_state'
ATTR_INFRARED = 'infrared'
@ -138,24 +134,33 @@ async def async_setup_platform(hass,
config,
async_add_entities,
discovery_info=None):
"""Set up the LIFX platform."""
"""Set up the LIFX light platform. Obsolete."""
_LOGGER.warning('LIFX no longer works with light platform configuration.')
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up LIFX from a config entry."""
if sys.platform == 'win32':
_LOGGER.warning("The lifx platform is known to not work on Windows. "
"Consider using the lifx_legacy platform instead")
server_addr = config.get(CONF_SERVER)
config = hass.data[LIFX_DOMAIN].get(DOMAIN, {})
lifx_manager = LIFXManager(hass, async_add_entities)
lifx_discovery = aiolifx().LifxDiscovery(
hass.loop,
lifx_manager,
discovery_interval=DISCOVERY_INTERVAL,
broadcast_ip=config.get(CONF_BROADCAST))
coro = hass.loop.create_datagram_endpoint(
lambda: lifx_discovery, local_addr=(server_addr, UDP_BROADCAST_PORT))
broadcast_ip = config.get(CONF_BROADCAST)
kwargs = {'discovery_interval': DISCOVERY_INTERVAL}
if broadcast_ip:
kwargs['broadcast_ip'] = broadcast_ip
lifx_discovery = aiolifx().LifxDiscovery(hass.loop, lifx_manager, **kwargs)
hass.async_add_job(coro)
kwargs = {'family': socket.AF_INET}
local_addr = config.get(CONF_SERVER)
if local_addr is not None:
kwargs['local_addr'] = (local_addr, 0)
coro = hass.loop.create_datagram_endpoint(lambda: lifx_discovery, **kwargs)
hass.async_create_task(coro)
@callback
def cleanup(event):
@ -225,7 +230,7 @@ class LIFXManager:
for light in self.service_to_entities(service):
if service.service == SERVICE_LIFX_SET_STATE:
task = light.set_state(**service.data)
tasks.append(self.hass.async_add_job(task))
tasks.append(self.hass.async_create_task(task))
if tasks:
await asyncio.wait(tasks, loop=self.hass.loop)

View File

@ -142,6 +142,7 @@ FLOWS = [
'hue',
'ifttt',
'ios',
'lifx',
'mqtt',
'nest',
'openuv',

View File

@ -106,7 +106,7 @@ aiohue==1.5.0
# homeassistant.components.sensor.imap
aioimaplib==0.7.13
# homeassistant.components.light.lifx
# homeassistant.components.lifx
aiolifx==0.6.3
# homeassistant.components.light.lifx