LIFX: add lifx_set_state service call (#7552)

* Move service helpers to LifxManager

* Add lifx_set_color

This is a synonym for light.turn_on except it does not actually turn on the
light unless asked to.

Thus, turn_on can be implemented just by asking.

* Rename set_color to set_state

* Support power=False with lifx_set_state
This commit is contained in:
Anders Melchiorsen 2017-05-12 18:19:51 +02:00 committed by Paulus Schoutsen
parent 416b8e0efe
commit 1ab7103aea
3 changed files with 105 additions and 35 deletions

View File

@ -9,6 +9,7 @@ import logging
import asyncio import asyncio
import sys import sys
import math import math
from os import path
from functools import partial from functools import partial
from datetime import timedelta from datetime import timedelta
import async_timeout import async_timeout
@ -16,15 +17,18 @@ import async_timeout
import voluptuous as vol import voluptuous as vol
from homeassistant.components.light import ( from homeassistant.components.light import (
Light, PLATFORM_SCHEMA, ATTR_BRIGHTNESS, ATTR_COLOR_NAME, ATTR_RGB_COLOR, Light, DOMAIN, PLATFORM_SCHEMA, LIGHT_TURN_ON_SCHEMA,
ATTR_BRIGHTNESS, ATTR_COLOR_NAME, ATTR_RGB_COLOR,
ATTR_XY_COLOR, ATTR_COLOR_TEMP, ATTR_TRANSITION, ATTR_EFFECT, ATTR_XY_COLOR, ATTR_COLOR_TEMP, ATTR_TRANSITION, ATTR_EFFECT,
SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR,
SUPPORT_XY_COLOR, SUPPORT_TRANSITION, SUPPORT_EFFECT) SUPPORT_XY_COLOR, SUPPORT_TRANSITION, SUPPORT_EFFECT)
from homeassistant.config import load_yaml_config_file
from homeassistant.util.color import ( from homeassistant.util.color import (
color_temperature_mired_to_kelvin, color_temperature_kelvin_to_mired) color_temperature_mired_to_kelvin, color_temperature_kelvin_to_mired)
from homeassistant import util from homeassistant import util
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers.event import async_track_point_in_utc_time from homeassistant.helpers.event import async_track_point_in_utc_time
from homeassistant.helpers.service import extract_entity_ids
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util import homeassistant.util.color as color_util
@ -41,7 +45,10 @@ BULB_LATENCY = 500
CONF_SERVER = 'server' CONF_SERVER = 'server'
SERVICE_LIFX_SET_STATE = 'lifx_set_state'
ATTR_HSBK = 'hsbk' ATTR_HSBK = 'hsbk'
ATTR_POWER = 'power'
BYTE_MAX = 255 BYTE_MAX = 255
SHORT_MAX = 65535 SHORT_MAX = 65535
@ -53,6 +60,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_SERVER, default='0.0.0.0'): cv.string, vol.Optional(CONF_SERVER, default='0.0.0.0'): cv.string,
}) })
LIFX_SET_STATE_SCHEMA = LIGHT_TURN_ON_SCHEMA.extend({
ATTR_POWER: cv.boolean,
})
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
@ -87,6 +98,41 @@ class LIFXManager(object):
self.hass = hass self.hass = hass
self.async_add_devices = async_add_devices self.async_add_devices = async_add_devices
@asyncio.coroutine
def async_service_handle(service):
"""Apply a service."""
tasks = []
for light in self.service_to_entities(service):
if service.service == SERVICE_LIFX_SET_STATE:
task = light.async_set_state(**service.data)
tasks.append(hass.async_add_job(task))
if tasks:
yield from asyncio.wait(tasks, loop=hass.loop)
descriptions = self.get_descriptions()
hass.services.async_register(
DOMAIN, SERVICE_LIFX_SET_STATE, async_service_handle,
descriptions.get(SERVICE_LIFX_SET_STATE),
schema=LIFX_SET_STATE_SCHEMA)
@staticmethod
def get_descriptions():
"""Load and return descriptions for our own service calls."""
return load_yaml_config_file(
path.join(path.dirname(__file__), 'services.yaml'))
def service_to_entities(self, service):
"""Return the known devices that a service call mentions."""
entity_ids = extract_entity_ids(self.hass, service)
if entity_ids:
entities = [entity for entity in self.entities.values()
if entity.entity_id in entity_ids]
else:
entities = list(self.entities.values())
return entities
@callback @callback
def register(self, device): def register(self, device):
"""Handle for newly detected bulb.""" """Handle for newly detected bulb."""
@ -298,6 +344,18 @@ class LIFXLight(Light):
@asyncio.coroutine @asyncio.coroutine
def async_turn_on(self, **kwargs): def async_turn_on(self, **kwargs):
"""Turn the device on.""" """Turn the device on."""
kwargs[ATTR_POWER] = True
yield from self.async_set_state(**kwargs)
@asyncio.coroutine
def async_turn_off(self, **kwargs):
"""Turn the device off."""
kwargs[ATTR_POWER] = False
yield from self.async_set_state(**kwargs)
@asyncio.coroutine
def async_set_state(self, **kwargs):
"""Set a color on the light and turn it on/off."""
yield from self.stop_effect() yield from self.stop_effect()
if ATTR_EFFECT in kwargs: if ATTR_EFFECT in kwargs:
@ -309,39 +367,41 @@ class LIFXLight(Light):
else: else:
fade = 0 fade = 0
# These are both False if ATTR_POWER is not set
power_on = kwargs.get(ATTR_POWER, False)
power_off = not kwargs.get(ATTR_POWER, True)
hsbk, changed_color = self.find_hsbk(**kwargs) hsbk, changed_color = self.find_hsbk(**kwargs)
_LOGGER.debug("turn_on: %s (%d) %d %d %d %d %d", _LOGGER.debug("turn_on: %s (%d) %d %d %d %d %d",
self.who, self._power, fade, *hsbk) self.who, self._power, fade, *hsbk)
if self._power == 0: if self._power == 0:
if power_off:
self.device.set_power(False, None, 0)
if changed_color: if changed_color:
self.device.set_color(hsbk, None, 0) self.device.set_color(hsbk, None, 0)
self.device.set_power(True, None, fade) if power_on:
self.device.set_power(True, None, fade)
else: else:
self.device.set_power(True, None, 0) # racing for power status if power_on:
self.device.set_power(True, None, 0)
if changed_color: if changed_color:
self.device.set_color(hsbk, None, fade) self.device.set_color(hsbk, None, fade)
if power_off:
self.device.set_power(False, None, fade)
self.update_later(0) if power_on:
if fade < BULB_LATENCY: self.update_later(0)
self.set_power(1)
self.set_color(*hsbk)
@asyncio.coroutine
def async_turn_off(self, **kwargs):
"""Turn the device off."""
yield from self.stop_effect()
if ATTR_TRANSITION in kwargs:
fade = int(kwargs[ATTR_TRANSITION] * 1000)
else: else:
fade = 0 self.update_later(fade)
self.device.set_power(False, None, fade) if fade <= BULB_LATENCY:
if power_on:
self.update_later(fade) self.set_power(1)
if fade < BULB_LATENCY: if power_off:
self.set_power(0) self.set_power(0)
if changed_color:
self.set_color(*hsbk)
@asyncio.coroutine @asyncio.coroutine
def async_update(self): def async_update(self):

View File

@ -2,16 +2,13 @@
import logging import logging
import asyncio import asyncio
import random import random
from os import path
import voluptuous as vol import voluptuous as vol
from homeassistant.components.light import ( from homeassistant.components.light import (
DOMAIN, ATTR_BRIGHTNESS, ATTR_COLOR_NAME, ATTR_RGB_COLOR, ATTR_EFFECT, DOMAIN, ATTR_BRIGHTNESS, ATTR_COLOR_NAME, ATTR_RGB_COLOR, ATTR_EFFECT,
ATTR_TRANSITION) ATTR_TRANSITION)
from homeassistant.config import load_yaml_config_file
from homeassistant.const import (ATTR_ENTITY_ID) from homeassistant.const import (ATTR_ENTITY_ID)
from homeassistant.helpers.service import extract_entity_ids
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -73,19 +70,12 @@ def setup(hass, lifx_manager):
@asyncio.coroutine @asyncio.coroutine
def async_service_handle(service): def async_service_handle(service):
"""Apply a service.""" """Apply a service."""
entity_ids = extract_entity_ids(hass, service) entities = lifx_manager.service_to_entities(service)
if entity_ids: if entities:
devices = [entity for entity in lifx_manager.entities.values() yield from start_effect(hass, entities,
if entity.entity_id in entity_ids]
else:
devices = list(lifx_manager.entities.values())
if devices:
yield from start_effect(hass, devices,
service.service, **service.data) service.service, **service.data)
descriptions = load_yaml_config_file( descriptions = lifx_manager.get_descriptions()
path.join(path.dirname(__file__), 'services.yaml'))
hass.services.async_register( hass.services.async_register(
DOMAIN, SERVICE_EFFECT_BREATHE, async_service_handle, DOMAIN, SERVICE_EFFECT_BREATHE, async_service_handle,

View File

@ -1,3 +1,23 @@
lifx_set_state:
description: Set a color/brightness and possibliy turn the light on/off
fields:
entity_id:
description: Name(s) of entities to set a state on
example: 'light.garage'
'...':
description: All turn_on parameters can be used to specify a color
transition:
description: Duration in seconds it takes to get to the final state
example: 10
power:
description: Turn the light on (True) or off (False). Leave out to keep the power as it is.
example: True
lifx_effect_breathe: lifx_effect_breathe:
description: Run a breathe effect by fading to a color and back. description: Run a breathe effect by fading to a color and back.