2013-12-11 00:07:30 -08:00
|
|
|
"""
|
2014-01-04 17:55:05 -08:00
|
|
|
homeassistant.components.light
|
2013-12-11 00:07:30 -08:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
Provides functionality to interact with lights.
|
2014-03-26 00:08:50 -07:00
|
|
|
|
|
|
|
It offers the following services:
|
|
|
|
|
|
|
|
TURN_OFF - Turns one or multiple lights off.
|
|
|
|
|
|
|
|
Supports following parameters:
|
|
|
|
- transition
|
|
|
|
Integer that represents the time the light should take to transition to
|
|
|
|
the new state.
|
|
|
|
- entity_id
|
|
|
|
String or list of strings that point at entity_ids of lights.
|
|
|
|
|
|
|
|
TURN_ON - Turns one or multiple lights on and change attributes.
|
|
|
|
|
|
|
|
Supports following parameters:
|
|
|
|
- transition
|
|
|
|
Integer that represents the time the light should take to transition to
|
|
|
|
the new state.
|
|
|
|
|
|
|
|
- entity_id
|
|
|
|
String or list of strings that point at entity_ids of lights.
|
|
|
|
|
|
|
|
- profile
|
|
|
|
String with the name of one of the built-in profiles (relax, energize,
|
|
|
|
concentrate, reading) or one of the custom profiles defined in
|
|
|
|
light_profiles.csv in the current working directory.
|
|
|
|
|
|
|
|
Light profiles define a xy color and a brightness.
|
|
|
|
|
|
|
|
If a profile is given and a brightness or xy color then the profile values
|
|
|
|
will be overwritten.
|
|
|
|
|
|
|
|
- xy_color
|
|
|
|
A list containing two floats representing the xy color you want the light
|
|
|
|
to be.
|
|
|
|
|
|
|
|
- rgb_color
|
|
|
|
A list containing three integers representing the xy color you want the
|
|
|
|
light to be.
|
|
|
|
|
|
|
|
- brightness
|
|
|
|
Integer between 0 and 255 representing how bright you want the light to be.
|
|
|
|
|
2013-12-11 00:07:30 -08:00
|
|
|
"""
|
|
|
|
|
|
|
|
import logging
|
2014-03-15 00:24:28 -07:00
|
|
|
import socket
|
2013-12-11 00:07:30 -08:00
|
|
|
from datetime import datetime, timedelta
|
2014-03-16 15:00:59 -07:00
|
|
|
from collections import namedtuple
|
2014-03-26 00:08:50 -07:00
|
|
|
import os
|
|
|
|
import csv
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-08-13 14:28:45 +02:00
|
|
|
import homeassistant as ha
|
2013-12-11 00:07:30 -08:00
|
|
|
import homeassistant.util as util
|
2014-11-09 15:12:23 -08:00
|
|
|
from homeassistant.components import (
|
|
|
|
ToggleDevice, group, extract_entity_ids, STATE_ON,
|
|
|
|
SERVICE_TURN_ON, SERVICE_TURN_OFF, ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME)
|
2014-03-15 00:24:28 -07:00
|
|
|
|
2013-12-11 00:07:30 -08:00
|
|
|
|
|
|
|
DOMAIN = "light"
|
2014-08-13 14:28:45 +02:00
|
|
|
DEPENDENCIES = []
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-01-19 23:37:40 -08:00
|
|
|
GROUP_NAME_ALL_LIGHTS = 'all_lights'
|
|
|
|
ENTITY_ID_ALL_LIGHTS = group.ENTITY_ID_FORMAT.format(
|
|
|
|
GROUP_NAME_ALL_LIGHTS)
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-01-19 23:37:40 -08:00
|
|
|
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
2013-12-11 00:07:30 -08:00
|
|
|
|
|
|
|
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
|
|
|
|
2014-03-16 15:00:59 -07:00
|
|
|
# integer that represents transition time in seconds to make change
|
|
|
|
ATTR_TRANSITION = "transition"
|
|
|
|
|
|
|
|
# lists holding color values
|
|
|
|
ATTR_RGB_COLOR = "rgb_color"
|
|
|
|
ATTR_XY_COLOR = "xy_color"
|
|
|
|
|
|
|
|
# int with value 0 .. 255 representing brightness of the light
|
|
|
|
ATTR_BRIGHTNESS = "brightness"
|
|
|
|
|
2014-03-26 00:08:50 -07:00
|
|
|
# String representing a profile (built-in ones or external defined)
|
|
|
|
ATTR_PROFILE = "profile"
|
|
|
|
|
2014-09-20 21:19:39 -05:00
|
|
|
PHUE_CONFIG_FILE = "phue.conf"
|
2014-03-26 00:08:50 -07:00
|
|
|
LIGHT_PROFILES_FILE = "light_profiles.csv"
|
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-04-24 00:40:45 -07:00
|
|
|
def is_on(hass, entity_id=None):
|
2013-12-11 00:07:30 -08:00
|
|
|
""" Returns if the lights are on based on the statemachine. """
|
2014-01-20 23:23:02 -08:00
|
|
|
entity_id = entity_id or ENTITY_ID_ALL_LIGHTS
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-04-24 00:40:45 -07:00
|
|
|
return hass.states.is_state(entity_id, STATE_ON)
|
2013-12-11 00:07:30 -08:00
|
|
|
|
|
|
|
|
2014-03-16 15:00:59 -07:00
|
|
|
# pylint: disable=too-many-arguments
|
2014-04-24 00:40:45 -07:00
|
|
|
def turn_on(hass, entity_id=None, transition=None, brightness=None,
|
2014-03-26 00:08:50 -07:00
|
|
|
rgb_color=None, xy_color=None, profile=None):
|
2013-12-11 00:07:30 -08:00
|
|
|
""" Turns all or specified light on. """
|
|
|
|
data = {}
|
|
|
|
|
2014-01-20 23:23:02 -08:00
|
|
|
if entity_id:
|
2014-03-15 00:24:28 -07:00
|
|
|
data[ATTR_ENTITY_ID] = entity_id
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-03-26 00:08:50 -07:00
|
|
|
if profile:
|
|
|
|
data[ATTR_PROFILE] = profile
|
|
|
|
|
2014-03-16 15:00:59 -07:00
|
|
|
if transition is not None:
|
|
|
|
data[ATTR_TRANSITION] = transition
|
|
|
|
|
|
|
|
if brightness is not None:
|
|
|
|
data[ATTR_BRIGHTNESS] = brightness
|
|
|
|
|
2014-03-26 00:08:50 -07:00
|
|
|
if rgb_color:
|
2014-03-16 15:00:59 -07:00
|
|
|
data[ATTR_RGB_COLOR] = rgb_color
|
|
|
|
|
2014-03-26 00:08:50 -07:00
|
|
|
if xy_color:
|
2014-03-16 15:00:59 -07:00
|
|
|
data[ATTR_XY_COLOR] = xy_color
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-04-24 00:40:45 -07:00
|
|
|
hass.call_service(DOMAIN, SERVICE_TURN_ON, data)
|
2013-12-11 00:07:30 -08:00
|
|
|
|
|
|
|
|
2014-04-24 00:40:45 -07:00
|
|
|
def turn_off(hass, entity_id=None, transition=None):
|
2013-12-11 00:07:30 -08:00
|
|
|
""" Turns all or specified light off. """
|
|
|
|
data = {}
|
|
|
|
|
2014-01-20 23:23:02 -08:00
|
|
|
if entity_id:
|
2014-03-15 00:24:28 -07:00
|
|
|
data[ATTR_ENTITY_ID] = entity_id
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-03-16 15:00:59 -07:00
|
|
|
if transition is not None:
|
|
|
|
data[ATTR_TRANSITION] = transition
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-04-24 00:40:45 -07:00
|
|
|
hass.call_service(DOMAIN, SERVICE_TURN_OFF, data)
|
2013-12-11 00:07:30 -08:00
|
|
|
|
|
|
|
|
2014-03-26 00:08:50 -07:00
|
|
|
# pylint: disable=too-many-branches, too-many-locals
|
2014-08-13 14:28:45 +02:00
|
|
|
def setup(hass, config):
|
2013-12-11 00:07:30 -08:00
|
|
|
""" Exposes light control via statemachine and services. """
|
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
if not util.validate_config(config, {DOMAIN: [ha.CONF_TYPE]}, _LOGGER):
|
2014-08-13 14:28:45 +02:00
|
|
|
return False
|
|
|
|
|
|
|
|
light_type = config[DOMAIN][ha.CONF_TYPE]
|
|
|
|
|
|
|
|
if light_type == 'hue':
|
2014-11-09 15:12:23 -08:00
|
|
|
light_init = get_hue_lights
|
2014-08-13 14:28:45 +02:00
|
|
|
|
|
|
|
else:
|
2014-11-09 15:12:23 -08:00
|
|
|
_LOGGER.error("Unknown light type specified: %s", light_type)
|
2014-08-13 14:28:45 +02:00
|
|
|
|
|
|
|
return False
|
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
lights = light_init(hass, config[DOMAIN])
|
2014-03-16 15:00:59 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
if len(lights) == 0:
|
|
|
|
_LOGGER.error("No lights found")
|
|
|
|
return False
|
2014-03-16 15:00:59 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
ent_to_light = {}
|
2014-03-16 15:00:59 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
no_name_count = 1
|
2014-03-16 15:00:59 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
for light in lights:
|
|
|
|
name = light.get_name()
|
2014-03-15 00:24:28 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
if name is None:
|
|
|
|
name = "Light #{}".format(no_name_count)
|
|
|
|
no_name_count += 1
|
2014-01-04 17:55:05 -08:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
entity_id = util.ensure_unique_string(
|
|
|
|
ENTITY_ID_FORMAT.format(util.slugify(name)),
|
|
|
|
list(ent_to_light.keys()))
|
2014-03-26 00:08:50 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
light.entity_id = entity_id
|
|
|
|
ent_to_light[entity_id] = light
|
2014-01-04 17:55:05 -08:00
|
|
|
|
2014-03-26 00:08:50 -07:00
|
|
|
# Load built-in profiles and custom profiles
|
2014-09-20 21:19:39 -05:00
|
|
|
profile_paths = [os.path.join(os.path.dirname(__file__),
|
|
|
|
LIGHT_PROFILES_FILE),
|
|
|
|
hass.get_config_path(LIGHT_PROFILES_FILE)]
|
2014-03-26 00:08:50 -07:00
|
|
|
profiles = {}
|
|
|
|
|
2014-09-20 21:19:39 -05:00
|
|
|
for profile_path in profile_paths:
|
2014-03-26 00:08:50 -07:00
|
|
|
|
2014-09-20 21:19:39 -05:00
|
|
|
if os.path.isfile(profile_path):
|
|
|
|
with open(profile_path) as inp:
|
2014-03-26 00:08:50 -07:00
|
|
|
reader = csv.reader(inp)
|
|
|
|
|
|
|
|
# Skip the header
|
|
|
|
next(reader, None)
|
|
|
|
|
|
|
|
try:
|
|
|
|
for profile_id, color_x, color_y, brightness in reader:
|
|
|
|
profiles[profile_id] = (float(color_x), float(color_y),
|
|
|
|
int(brightness))
|
|
|
|
|
|
|
|
except ValueError:
|
|
|
|
# ValueError if not 4 values per row
|
|
|
|
# ValueError if convert to float/int failed
|
2014-11-09 15:12:23 -08:00
|
|
|
_LOGGER.error(
|
2014-11-08 13:57:08 -08:00
|
|
|
"Error parsing light profiles from %s", profile_path)
|
2014-03-26 00:08:50 -07:00
|
|
|
|
|
|
|
return False
|
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
# pylint: disable=unused-argument
|
|
|
|
def update_lights_state(now):
|
|
|
|
""" Update the states of all the lights. """
|
|
|
|
for light in lights:
|
|
|
|
light.update_ha_state(hass)
|
|
|
|
|
|
|
|
update_lights_state(None)
|
|
|
|
|
|
|
|
# Track all lights in a group
|
|
|
|
group.setup_group(
|
|
|
|
hass, GROUP_NAME_ALL_LIGHTS, ent_to_light.keys(), False)
|
|
|
|
|
2014-01-04 17:55:05 -08:00
|
|
|
def handle_light_service(service):
|
2013-12-11 00:07:30 -08:00
|
|
|
""" Hande a turn light on or off service call. """
|
2014-03-16 15:00:59 -07:00
|
|
|
# Get and validate data
|
|
|
|
dat = service.data
|
|
|
|
|
2014-03-24 20:34:35 -07:00
|
|
|
# Convert the entity ids to valid light ids
|
2014-11-09 15:12:23 -08:00
|
|
|
lights = [ent_to_light[entity_id] for entity_id
|
|
|
|
in extract_entity_ids(hass, service)
|
|
|
|
if entity_id in ent_to_light]
|
2014-03-24 20:34:35 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
if not lights:
|
|
|
|
lights = list(ent_to_light.values())
|
2014-03-16 15:00:59 -07:00
|
|
|
|
2014-03-26 00:08:50 -07:00
|
|
|
transition = util.convert(dat.get(ATTR_TRANSITION), int)
|
2014-03-16 15:00:59 -07:00
|
|
|
|
|
|
|
if service.service == SERVICE_TURN_OFF:
|
2014-11-09 15:12:23 -08:00
|
|
|
for light in lights:
|
|
|
|
light.turn_off(transition=transition)
|
2013-12-11 00:07:30 -08:00
|
|
|
|
|
|
|
else:
|
2014-03-16 15:00:59 -07:00
|
|
|
# Processing extra data for turn light on request
|
|
|
|
|
2014-03-26 00:08:50 -07:00
|
|
|
# We process the profile first so that we get the desired
|
|
|
|
# behavior that extra service data attributes overwrite
|
|
|
|
# profile values
|
|
|
|
profile = profiles.get(dat.get(ATTR_PROFILE))
|
|
|
|
|
|
|
|
if profile:
|
2014-04-14 23:48:00 -07:00
|
|
|
*color, bright = profile
|
2014-03-26 00:08:50 -07:00
|
|
|
else:
|
2014-04-14 23:48:00 -07:00
|
|
|
color, bright = None, None
|
2014-03-26 00:08:50 -07:00
|
|
|
|
|
|
|
if ATTR_BRIGHTNESS in dat:
|
|
|
|
bright = util.convert(dat.get(ATTR_BRIGHTNESS), int)
|
2014-03-16 15:00:59 -07:00
|
|
|
|
2014-03-26 00:08:50 -07:00
|
|
|
if ATTR_XY_COLOR in dat:
|
2014-03-16 15:00:59 -07:00
|
|
|
try:
|
|
|
|
# xy_color should be a list containing 2 floats
|
2014-04-14 23:48:00 -07:00
|
|
|
xy_color = dat.get(ATTR_XY_COLOR)
|
2014-03-16 15:00:59 -07:00
|
|
|
|
|
|
|
if len(xy_color) == 2:
|
2014-04-14 23:48:00 -07:00
|
|
|
color = [float(val) for val in xy_color]
|
2014-03-16 15:00:59 -07:00
|
|
|
|
|
|
|
except (TypeError, ValueError):
|
2014-04-14 23:48:00 -07:00
|
|
|
# TypeError if xy_color is not iterable
|
2014-03-16 15:00:59 -07:00
|
|
|
# ValueError if value could not be converted to float
|
|
|
|
pass
|
|
|
|
|
2014-03-26 00:08:50 -07:00
|
|
|
if ATTR_RGB_COLOR in dat:
|
2014-03-16 15:00:59 -07:00
|
|
|
try:
|
|
|
|
# rgb_color should be a list containing 3 ints
|
2014-04-14 23:48:00 -07:00
|
|
|
rgb_color = dat.get(ATTR_RGB_COLOR)
|
2014-03-16 15:00:59 -07:00
|
|
|
|
|
|
|
if len(rgb_color) == 3:
|
2014-04-14 23:48:00 -07:00
|
|
|
color = util.color_RGB_to_xy(int(rgb_color[0]),
|
|
|
|
int(rgb_color[1]),
|
|
|
|
int(rgb_color[2]))
|
2014-03-16 15:00:59 -07:00
|
|
|
|
|
|
|
except (TypeError, ValueError):
|
2014-04-14 23:48:00 -07:00
|
|
|
# TypeError if rgb_color is not iterable
|
2014-03-26 00:08:50 -07:00
|
|
|
# ValueError if not all values can be converted to int
|
2014-03-24 20:34:35 -07:00
|
|
|
pass
|
2014-03-16 15:00:59 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
for light in lights:
|
|
|
|
light.turn_on(transition=transition, brightness=bright,
|
|
|
|
xy_color=color)
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
for light in lights:
|
|
|
|
light.update_ha_state(hass, True)
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-03-15 00:24:28 -07:00
|
|
|
# Update light state every 30 seconds
|
2014-04-24 00:40:45 -07:00
|
|
|
hass.track_time_change(update_lights_state, second=[0, 30])
|
2014-03-15 00:24:28 -07:00
|
|
|
|
|
|
|
# Listen for light on and light off service calls
|
2014-04-24 00:40:45 -07:00
|
|
|
hass.services.register(DOMAIN, SERVICE_TURN_ON,
|
|
|
|
handle_light_service)
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-04-24 00:40:45 -07:00
|
|
|
hass.services.register(DOMAIN, SERVICE_TURN_OFF,
|
|
|
|
handle_light_service)
|
2013-12-11 00:07:30 -08:00
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
def get_hue_lights(hass, config):
|
|
|
|
""" Gets the Hue lights. """
|
|
|
|
host = config.get(ha.CONF_HOST, None)
|
2014-03-16 15:00:59 -07:00
|
|
|
|
|
|
|
try:
|
2014-11-09 15:12:23 -08:00
|
|
|
# Pylint does not play nice if not every folders has an __init__.py
|
|
|
|
# pylint: disable=no-name-in-module, import-error
|
|
|
|
import homeassistant.external.phue.phue as phue
|
|
|
|
except ImportError:
|
|
|
|
_LOGGER.exception("Hue:Error while importing dependency phue.")
|
2014-01-12 12:35:10 -08:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
return []
|
2014-08-13 14:28:45 +02:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
try:
|
|
|
|
bridge = phue.Bridge(
|
|
|
|
host, config_file_path=hass.get_config_path(PHUE_CONFIG_FILE))
|
|
|
|
except socket.error: # Error connecting using Phue
|
|
|
|
_LOGGER.exception((
|
|
|
|
"Hue:Error while connecting to the bridge. "
|
|
|
|
"Did you follow the instructions to set it up?"))
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
return []
|
2014-03-16 15:00:59 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
lights = {}
|
2014-01-12 12:35:10 -08:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
def update_lights(force_reload=False):
|
|
|
|
""" Updates the light states. """
|
|
|
|
now = datetime.now()
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-03-15 00:24:28 -07:00
|
|
|
try:
|
2014-11-09 15:12:23 -08:00
|
|
|
time_scans = now - update_lights.last_updated
|
|
|
|
|
|
|
|
# force_reload == True, return if updated in last second
|
|
|
|
# force_reload == False, return if last update was less then
|
|
|
|
# MIN_TIME_BETWEEN_SCANS ago
|
|
|
|
if force_reload and time_scans.seconds < 1 or \
|
|
|
|
not force_reload and time_scans < MIN_TIME_BETWEEN_SCANS:
|
|
|
|
return
|
|
|
|
except AttributeError:
|
|
|
|
# First time we run last_updated is not set, continue as usual
|
2014-03-16 15:00:59 -07:00
|
|
|
pass
|
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
update_lights.last_updated = now
|
2014-01-12 12:35:10 -08:00
|
|
|
|
2014-03-15 00:24:28 -07:00
|
|
|
try:
|
2014-11-09 15:12:23 -08:00
|
|
|
api = bridge.get_api()
|
2014-03-16 15:00:59 -07:00
|
|
|
except socket.error:
|
|
|
|
# socket.error when we cannot reach Hue
|
2014-11-09 15:12:23 -08:00
|
|
|
_LOGGER.exception("Hue:Cannot reach the bridge")
|
|
|
|
return
|
2014-03-16 15:00:59 -07:00
|
|
|
|
|
|
|
api_states = api.get('lights')
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-03-16 15:00:59 -07:00
|
|
|
if not isinstance(api_states, dict):
|
2014-11-09 15:12:23 -08:00
|
|
|
_LOGGER.error("Hue:Got unexpected result from Hue API")
|
|
|
|
return
|
2014-03-16 15:00:59 -07:00
|
|
|
|
|
|
|
for light_id, info in api_states.items():
|
2014-11-09 15:12:23 -08:00
|
|
|
if light_id not in lights:
|
|
|
|
lights[light_id] = HueLight(int(light_id), info,
|
|
|
|
bridge, update_lights)
|
|
|
|
else:
|
|
|
|
lights[light_id].info = info
|
|
|
|
|
|
|
|
update_lights()
|
|
|
|
|
|
|
|
return list(lights.values())
|
2014-03-16 15:00:59 -07:00
|
|
|
|
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
class HueLight(ToggleDevice):
|
|
|
|
""" Represents a Hue light """
|
2014-03-16 15:00:59 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
def __init__(self, light_id, info, bridge, update_lights):
|
|
|
|
self.light_id = light_id
|
|
|
|
self.info = info
|
|
|
|
self.bridge = bridge
|
|
|
|
self.update_lights = update_lights
|
|
|
|
|
|
|
|
def get_name(self):
|
|
|
|
""" Get the mame of the Hue light. """
|
|
|
|
return self.info['name']
|
|
|
|
|
|
|
|
def turn_on(self, **kwargs):
|
2013-12-11 00:07:30 -08:00
|
|
|
""" Turn the specified or all lights on. """
|
2014-03-16 15:00:59 -07:00
|
|
|
command = {'on': True}
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
if kwargs.get('transition') is not None:
|
2014-03-16 15:00:59 -07:00
|
|
|
# Transition time is in 1/10th seconds and cannot exceed
|
|
|
|
# 900 seconds.
|
2014-11-09 15:12:23 -08:00
|
|
|
command['transitiontime'] = min(9000, kwargs['transition'] * 10)
|
2014-03-16 15:00:59 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
if kwargs.get('brightness') is not None:
|
|
|
|
command['bri'] = kwargs['brightness']
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
if kwargs.get('xy_color') is not None:
|
|
|
|
command['xy'] = kwargs['xy_color']
|
2014-03-16 15:00:59 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
self.bridge.set_light(self.light_id, command)
|
2014-03-16 15:00:59 -07:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
def turn_off(self, **kwargs):
|
2014-03-16 15:00:59 -07:00
|
|
|
""" Turn the specified or all lights off. """
|
|
|
|
command = {'on': False}
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
if kwargs.get('transition') is not None:
|
2013-12-11 00:07:30 -08:00
|
|
|
# Transition time is in 1/10th seconds and cannot exceed
|
2014-01-12 12:35:10 -08:00
|
|
|
# 900 seconds.
|
2014-11-09 15:12:23 -08:00
|
|
|
command['transitiontime'] = min(9000, kwargs['transition'] * 10)
|
|
|
|
|
|
|
|
self.bridge.set_light(self.light_id, command)
|
|
|
|
|
|
|
|
def is_on(self):
|
|
|
|
""" True if device is on. """
|
|
|
|
self.update_lights()
|
|
|
|
|
|
|
|
return self.info['state']['reachable'] and self.info['state']['on']
|
|
|
|
|
|
|
|
def get_state_attributes(self):
|
|
|
|
""" Returns optional state attributes. """
|
|
|
|
attr = {
|
|
|
|
ATTR_FRIENDLY_NAME: self.get_name()
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.is_on():
|
|
|
|
attr[ATTR_BRIGHTNESS] = self.info['state']['bri']
|
|
|
|
attr[ATTR_XY_COLOR] = self.info['state']['xy']
|
|
|
|
|
|
|
|
return attr
|
2013-12-11 00:07:30 -08:00
|
|
|
|
2014-11-09 15:12:23 -08:00
|
|
|
def update(self):
|
|
|
|
""" Synchronize state with bridge. """
|
|
|
|
self.update_lights(True)
|