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 sys
import math
from os import path
from functools import partial
from datetime import timedelta
import async_timeout
@ -16,15 +17,18 @@ import async_timeout
import voluptuous as vol
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,
SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR,
SUPPORT_XY_COLOR, SUPPORT_TRANSITION, SUPPORT_EFFECT)
from homeassistant.config import load_yaml_config_file
from homeassistant.util.color import (
color_temperature_mired_to_kelvin, color_temperature_kelvin_to_mired)
from homeassistant import util
from homeassistant.core import callback
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.util.color as color_util
@ -41,7 +45,10 @@ BULB_LATENCY = 500
CONF_SERVER = 'server'
SERVICE_LIFX_SET_STATE = 'lifx_set_state'
ATTR_HSBK = 'hsbk'
ATTR_POWER = 'power'
BYTE_MAX = 255
SHORT_MAX = 65535
@ -53,6 +60,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
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
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
@ -87,6 +98,41 @@ class LIFXManager(object):
self.hass = hass
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
def register(self, device):
"""Handle for newly detected bulb."""
@ -298,6 +344,18 @@ class LIFXLight(Light):
@asyncio.coroutine
def async_turn_on(self, **kwargs):
"""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()
if ATTR_EFFECT in kwargs:
@ -309,39 +367,41 @@ class LIFXLight(Light):
else:
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)
_LOGGER.debug("turn_on: %s (%d) %d %d %d %d %d",
self.who, self._power, fade, *hsbk)
if self._power == 0:
if power_off:
self.device.set_power(False, None, 0)
if changed_color:
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:
self.device.set_power(True, None, 0) # racing for power status
if power_on:
self.device.set_power(True, None, 0)
if changed_color:
self.device.set_color(hsbk, None, fade)
if power_off:
self.device.set_power(False, None, fade)
self.update_later(0)
if fade < BULB_LATENCY:
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)
if power_on:
self.update_later(0)
else:
fade = 0
self.update_later(fade)
self.device.set_power(False, None, fade)
self.update_later(fade)
if fade < BULB_LATENCY:
self.set_power(0)
if fade <= BULB_LATENCY:
if power_on:
self.set_power(1)
if power_off:
self.set_power(0)
if changed_color:
self.set_color(*hsbk)
@asyncio.coroutine
def async_update(self):

View File

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