Use hue/sat as internal light color interface (#11288)

* Accept and report both xy and RGB color for lights

* Fix demo light supported_features

* Add new XY color util functions

* Always make color changes available as xy and RGB

* Always expose color as RGB and XY

* Consolidate color supported_features

* Test fixes

* Additional test fix

* Use hue/sat as the hass core color interface

* Tests updates

* Assume MQTT RGB devices need full RGB brightness

* Convert new platforms

* More migration

* Use float for HS API

* Fix backwards conversion for KNX lights

* Adjust limitless min saturation for new scale
This commit is contained in:
Adam Mills 2018-03-18 18:00:29 -04:00 committed by Paulus Schoutsen
parent 6b059489a6
commit 89c7c80e42
57 changed files with 898 additions and 965 deletions

View File

@ -438,9 +438,7 @@ class _LightCapabilities(_AlexaEntity):
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
if supported & light.SUPPORT_BRIGHTNESS: if supported & light.SUPPORT_BRIGHTNESS:
yield _AlexaBrightnessController(self.entity) yield _AlexaBrightnessController(self.entity)
if supported & light.SUPPORT_RGB_COLOR: if supported & light.SUPPORT_COLOR:
yield _AlexaColorController(self.entity)
if supported & light.SUPPORT_XY_COLOR:
yield _AlexaColorController(self.entity) yield _AlexaColorController(self.entity)
if supported & light.SUPPORT_COLOR_TEMP: if supported & light.SUPPORT_COLOR_TEMP:
yield _AlexaColorTemperatureController(self.entity) yield _AlexaColorTemperatureController(self.entity)
@ -842,25 +840,16 @@ def async_api_adjust_brightness(hass, config, request, entity):
@asyncio.coroutine @asyncio.coroutine
def async_api_set_color(hass, config, request, entity): def async_api_set_color(hass, config, request, entity):
"""Process a set color request.""" """Process a set color request."""
supported = entity.attributes.get(ATTR_SUPPORTED_FEATURES)
rgb = color_util.color_hsb_to_RGB( rgb = color_util.color_hsb_to_RGB(
float(request[API_PAYLOAD]['color']['hue']), float(request[API_PAYLOAD]['color']['hue']),
float(request[API_PAYLOAD]['color']['saturation']), float(request[API_PAYLOAD]['color']['saturation']),
float(request[API_PAYLOAD]['color']['brightness']) float(request[API_PAYLOAD]['color']['brightness'])
) )
if supported & light.SUPPORT_RGB_COLOR > 0:
yield from hass.services.async_call(entity.domain, SERVICE_TURN_ON, { yield from hass.services.async_call(entity.domain, SERVICE_TURN_ON, {
ATTR_ENTITY_ID: entity.entity_id, ATTR_ENTITY_ID: entity.entity_id,
light.ATTR_RGB_COLOR: rgb, light.ATTR_RGB_COLOR: rgb,
}, blocking=False) }, blocking=False)
else:
xyz = color_util.color_RGB_to_xy(*rgb)
yield from hass.services.async_call(entity.domain, SERVICE_TURN_ON, {
ATTR_ENTITY_ID: entity.entity_id,
light.ATTR_XY_COLOR: (xyz[0], xyz[1]),
light.ATTR_BRIGHTNESS: xyz[2],
}, blocking=False)
return api_message(request) return api_message(request)

View File

@ -243,7 +243,7 @@ class ColorSpectrumTrait(_Trait):
if domain != light.DOMAIN: if domain != light.DOMAIN:
return False return False
return features & (light.SUPPORT_RGB_COLOR | light.SUPPORT_XY_COLOR) return features & light.SUPPORT_COLOR
def sync_attributes(self): def sync_attributes(self):
"""Return color spectrum attributes for a sync request.""" """Return color spectrum attributes for a sync request."""
@ -254,13 +254,11 @@ class ColorSpectrumTrait(_Trait):
"""Return color spectrum query attributes.""" """Return color spectrum query attributes."""
response = {} response = {}
# No need to handle XY color because light component will always color_hs = self.state.attributes.get(light.ATTR_HS_COLOR)
# convert XY to RGB if possible (which is when brightness is available) if color_hs is not None:
color_rgb = self.state.attributes.get(light.ATTR_RGB_COLOR)
if color_rgb is not None:
response['color'] = { response['color'] = {
'spectrumRGB': int(color_util.color_rgb_to_hex( 'spectrumRGB': int(color_util.color_rgb_to_hex(
color_rgb[0], color_rgb[1], color_rgb[2]), 16), *color_util.color_hs_to_RGB(*color_hs)), 16),
} }
return response return response
@ -274,11 +272,12 @@ class ColorSpectrumTrait(_Trait):
"""Execute a color spectrum command.""" """Execute a color spectrum command."""
# Convert integer to hex format and left pad with 0's till length 6 # Convert integer to hex format and left pad with 0's till length 6
hex_value = "{0:06x}".format(params['color']['spectrumRGB']) hex_value = "{0:06x}".format(params['color']['spectrumRGB'])
color = color_util.rgb_hex_to_rgb_list(hex_value) color = color_util.color_RGB_to_hs(
*color_util.rgb_hex_to_rgb_list(hex_value))
await hass.services.async_call(light.DOMAIN, SERVICE_TURN_ON, { await hass.services.async_call(light.DOMAIN, SERVICE_TURN_ON, {
ATTR_ENTITY_ID: self.state.entity_id, ATTR_ENTITY_ID: self.state.entity_id,
light.ATTR_RGB_COLOR: color light.ATTR_HS_COLOR: color
}, blocking=True) }, blocking=True)

View File

@ -2,10 +2,8 @@
import logging import logging
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_RGB_COLOR, ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, SUPPORT_COLOR)
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR)
from homeassistant.const import ATTR_SUPPORTED_FEATURES, STATE_ON, STATE_OFF from homeassistant.const import ATTR_SUPPORTED_FEATURES, STATE_ON, STATE_OFF
from homeassistant.util.color import color_RGB_to_hsv, color_hsv_to_RGB
from . import TYPES from . import TYPES
from .accessories import HomeAccessory, add_preload_service from .accessories import HomeAccessory, add_preload_service
@ -40,7 +38,7 @@ class Light(HomeAccessory):
.attributes.get(ATTR_SUPPORTED_FEATURES) .attributes.get(ATTR_SUPPORTED_FEATURES)
if self._features & SUPPORT_BRIGHTNESS: if self._features & SUPPORT_BRIGHTNESS:
self.chars.append(CHAR_BRIGHTNESS) self.chars.append(CHAR_BRIGHTNESS)
if self._features & SUPPORT_RGB_COLOR: if self._features & SUPPORT_COLOR:
self.chars.append(CHAR_HUE) self.chars.append(CHAR_HUE)
self.chars.append(CHAR_SATURATION) self.chars.append(CHAR_SATURATION)
self._hue = None self._hue = None
@ -102,15 +100,15 @@ class Light(HomeAccessory):
def set_color(self): def set_color(self):
"""Set color if call came from HomeKit.""" """Set color if call came from HomeKit."""
# Handle RGB Color # Handle Color
if self._features & SUPPORT_RGB_COLOR and self._flag[CHAR_HUE] and \ if self._features & SUPPORT_COLOR and self._flag[CHAR_HUE] and \
self._flag[CHAR_SATURATION]: self._flag[CHAR_SATURATION]:
color = color_hsv_to_RGB(self._hue, self._saturation, 100) color = (self._hue, self._saturation)
_LOGGER.debug('%s: Set rgb_color to %s', self._entity_id, color) _LOGGER.debug('%s: Set hs_color to %s', self._entity_id, color)
self._flag.update({ self._flag.update({
CHAR_HUE: False, CHAR_SATURATION: False, RGB_COLOR: True}) CHAR_HUE: False, CHAR_SATURATION: False, RGB_COLOR: True})
self._hass.components.light.turn_on( self._hass.components.light.turn_on(
self._entity_id, rgb_color=color) self._entity_id, hs_color=color)
def update_state(self, entity_id=None, old_state=None, new_state=None): def update_state(self, entity_id=None, old_state=None, new_state=None):
"""Update light after state change.""" """Update light after state change."""
@ -134,15 +132,11 @@ class Light(HomeAccessory):
should_callback=False) should_callback=False)
self._flag[CHAR_BRIGHTNESS] = False self._flag[CHAR_BRIGHTNESS] = False
# Handle RGB Color # Handle Color
if CHAR_SATURATION in self.chars and CHAR_HUE in self.chars: if CHAR_SATURATION in self.chars and CHAR_HUE in self.chars:
rgb_color = new_state.attributes.get(ATTR_RGB_COLOR) hue, saturation = new_state.attributes.get(ATTR_HS_COLOR)
current_color = color_hsv_to_RGB(self._hue, self._saturation, 100)\ if not self._flag[RGB_COLOR] and (
if self._hue and self._saturation else [None] * 3 hue != self._hue or saturation != self._saturation):
if not self._flag[RGB_COLOR] and \
isinstance(rgb_color, (list, tuple)) and \
tuple(rgb_color) != current_color:
hue, saturation, _ = color_RGB_to_hsv(*rgb_color)
self.char_hue.set_value(hue, should_callback=False) self.char_hue.set_value(hue, should_callback=False)
self.char_saturation.set_value(saturation, self.char_saturation.set_value(saturation,
should_callback=False) should_callback=False)

View File

@ -40,9 +40,8 @@ SUPPORT_BRIGHTNESS = 1
SUPPORT_COLOR_TEMP = 2 SUPPORT_COLOR_TEMP = 2
SUPPORT_EFFECT = 4 SUPPORT_EFFECT = 4
SUPPORT_FLASH = 8 SUPPORT_FLASH = 8
SUPPORT_RGB_COLOR = 16 SUPPORT_COLOR = 16
SUPPORT_TRANSITION = 32 SUPPORT_TRANSITION = 32
SUPPORT_XY_COLOR = 64
SUPPORT_WHITE_VALUE = 128 SUPPORT_WHITE_VALUE = 128
# Integer that represents transition time in seconds to make change. # Integer that represents transition time in seconds to make change.
@ -51,6 +50,7 @@ ATTR_TRANSITION = "transition"
# Lists holding color values # Lists holding color values
ATTR_RGB_COLOR = "rgb_color" ATTR_RGB_COLOR = "rgb_color"
ATTR_XY_COLOR = "xy_color" ATTR_XY_COLOR = "xy_color"
ATTR_HS_COLOR = "hs_color"
ATTR_COLOR_TEMP = "color_temp" ATTR_COLOR_TEMP = "color_temp"
ATTR_KELVIN = "kelvin" ATTR_KELVIN = "kelvin"
ATTR_MIN_MIREDS = "min_mireds" ATTR_MIN_MIREDS = "min_mireds"
@ -86,8 +86,9 @@ LIGHT_PROFILES_FILE = "light_profiles.csv"
PROP_TO_ATTR = { PROP_TO_ATTR = {
'brightness': ATTR_BRIGHTNESS, 'brightness': ATTR_BRIGHTNESS,
'color_temp': ATTR_COLOR_TEMP, 'color_temp': ATTR_COLOR_TEMP,
'rgb_color': ATTR_RGB_COLOR, 'min_mireds': ATTR_MIN_MIREDS,
'xy_color': ATTR_XY_COLOR, 'max_mireds': ATTR_MAX_MIREDS,
'hs_color': ATTR_HS_COLOR,
'white_value': ATTR_WHITE_VALUE, 'white_value': ATTR_WHITE_VALUE,
'effect_list': ATTR_EFFECT_LIST, 'effect_list': ATTR_EFFECT_LIST,
'effect': ATTR_EFFECT, 'effect': ATTR_EFFECT,
@ -111,6 +112,11 @@ LIGHT_TURN_ON_SCHEMA = vol.Schema({
vol.Exclusive(ATTR_XY_COLOR, COLOR_GROUP): vol.Exclusive(ATTR_XY_COLOR, COLOR_GROUP):
vol.All(vol.ExactSequence((cv.small_float, cv.small_float)), vol.All(vol.ExactSequence((cv.small_float, cv.small_float)),
vol.Coerce(tuple)), vol.Coerce(tuple)),
vol.Exclusive(ATTR_HS_COLOR, COLOR_GROUP):
vol.All(vol.ExactSequence(
(vol.All(vol.Coerce(float), vol.Range(min=0, max=360)),
vol.All(vol.Coerce(float), vol.Range(min=0, max=100)))),
vol.Coerce(tuple)),
vol.Exclusive(ATTR_COLOR_TEMP, COLOR_GROUP): vol.Exclusive(ATTR_COLOR_TEMP, COLOR_GROUP):
vol.All(vol.Coerce(int), vol.Range(min=1)), vol.All(vol.Coerce(int), vol.Range(min=1)),
vol.Exclusive(ATTR_KELVIN, COLOR_GROUP): vol.Exclusive(ATTR_KELVIN, COLOR_GROUP):
@ -149,13 +155,13 @@ def is_on(hass, entity_id=None):
@bind_hass @bind_hass
def turn_on(hass, entity_id=None, transition=None, brightness=None, def turn_on(hass, entity_id=None, transition=None, brightness=None,
brightness_pct=None, rgb_color=None, xy_color=None, brightness_pct=None, rgb_color=None, xy_color=None, hs_color=None,
color_temp=None, kelvin=None, white_value=None, color_temp=None, kelvin=None, white_value=None,
profile=None, flash=None, effect=None, color_name=None): profile=None, flash=None, effect=None, color_name=None):
"""Turn all or specified light on.""" """Turn all or specified light on."""
hass.add_job( hass.add_job(
async_turn_on, hass, entity_id, transition, brightness, brightness_pct, async_turn_on, hass, entity_id, transition, brightness, brightness_pct,
rgb_color, xy_color, color_temp, kelvin, white_value, rgb_color, xy_color, hs_color, color_temp, kelvin, white_value,
profile, flash, effect, color_name) profile, flash, effect, color_name)
@ -163,8 +169,9 @@ def turn_on(hass, entity_id=None, transition=None, brightness=None,
@bind_hass @bind_hass
def async_turn_on(hass, entity_id=None, transition=None, brightness=None, def async_turn_on(hass, entity_id=None, transition=None, brightness=None,
brightness_pct=None, rgb_color=None, xy_color=None, brightness_pct=None, rgb_color=None, xy_color=None,
color_temp=None, kelvin=None, white_value=None, hs_color=None, color_temp=None, kelvin=None,
profile=None, flash=None, effect=None, color_name=None): white_value=None, profile=None, flash=None, effect=None,
color_name=None):
"""Turn all or specified light on.""" """Turn all or specified light on."""
data = { data = {
key: value for key, value in [ key: value for key, value in [
@ -175,6 +182,7 @@ def async_turn_on(hass, entity_id=None, transition=None, brightness=None,
(ATTR_BRIGHTNESS_PCT, brightness_pct), (ATTR_BRIGHTNESS_PCT, brightness_pct),
(ATTR_RGB_COLOR, rgb_color), (ATTR_RGB_COLOR, rgb_color),
(ATTR_XY_COLOR, xy_color), (ATTR_XY_COLOR, xy_color),
(ATTR_HS_COLOR, hs_color),
(ATTR_COLOR_TEMP, color_temp), (ATTR_COLOR_TEMP, color_temp),
(ATTR_KELVIN, kelvin), (ATTR_KELVIN, kelvin),
(ATTR_WHITE_VALUE, white_value), (ATTR_WHITE_VALUE, white_value),
@ -254,6 +262,14 @@ def preprocess_turn_on_alternatives(params):
if brightness_pct is not None: if brightness_pct is not None:
params[ATTR_BRIGHTNESS] = int(255 * brightness_pct/100) params[ATTR_BRIGHTNESS] = int(255 * brightness_pct/100)
xy_color = params.pop(ATTR_XY_COLOR, None)
if xy_color is not None:
params[ATTR_HS_COLOR] = color_util.color_xy_to_hs(*xy_color)
rgb_color = params.pop(ATTR_RGB_COLOR, None)
if rgb_color is not None:
params[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color)
class SetIntentHandler(intent.IntentHandler): class SetIntentHandler(intent.IntentHandler):
"""Handle set color intents.""" """Handle set color intents."""
@ -281,7 +297,7 @@ class SetIntentHandler(intent.IntentHandler):
if 'color' in slots: if 'color' in slots:
intent.async_test_feature( intent.async_test_feature(
state, SUPPORT_RGB_COLOR, 'changing colors') state, SUPPORT_COLOR, 'changing colors')
service_data[ATTR_RGB_COLOR] = slots['color']['value'] service_data[ATTR_RGB_COLOR] = slots['color']['value']
# Use original passed in value of the color because we don't have # Use original passed in value of the color because we don't have
# human readable names for that internally. # human readable names for that internally.
@ -428,13 +444,8 @@ class Light(ToggleEntity):
return None return None
@property @property
def xy_color(self): def hs_color(self):
"""Return the XY color value [float, float].""" """Return the hue and saturation color value [float, float]."""
return None
@property
def rgb_color(self):
"""Return the RGB color value [int, int, int]."""
return None return None
@property @property
@ -484,11 +495,12 @@ class Light(ToggleEntity):
if value is not None: if value is not None:
data[attr] = value data[attr] = value
if ATTR_RGB_COLOR not in data and ATTR_XY_COLOR in data and \ # Expose current color also as RGB and XY
ATTR_BRIGHTNESS in data: if ATTR_HS_COLOR in data:
data[ATTR_RGB_COLOR] = color_util.color_xy_brightness_to_RGB( data[ATTR_RGB_COLOR] = color_util.color_hs_to_RGB(
data[ATTR_XY_COLOR][0], data[ATTR_XY_COLOR][1], *data[ATTR_HS_COLOR])
data[ATTR_BRIGHTNESS]) data[ATTR_XY_COLOR] = color_util.color_hs_to_xy(
*data[ATTR_HS_COLOR])
return data return data

View File

@ -8,8 +8,9 @@ import logging
from homeassistant.components.abode import AbodeDevice, DOMAIN as ABODE_DOMAIN from homeassistant.components.abode import AbodeDevice, DOMAIN as ABODE_DOMAIN
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_BRIGHTNESS, ATTR_HS_COLOR,
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, Light) SUPPORT_BRIGHTNESS, SUPPORT_COLOR, Light)
import homeassistant.util.color as color_util
DEPENDENCIES = ['abode'] DEPENDENCIES = ['abode']
@ -44,10 +45,12 @@ class AbodeLight(AbodeDevice, Light):
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn on the light.""" """Turn on the light."""
if (ATTR_RGB_COLOR in kwargs and if (ATTR_HS_COLOR in kwargs and
self._device.is_dimmable and self._device.has_color): self._device.is_dimmable and self._device.has_color):
self._device.set_color(kwargs[ATTR_RGB_COLOR]) self._device.set_color(color_util.color_hs_to_RGB(
elif ATTR_BRIGHTNESS in kwargs and self._device.is_dimmable: *kwargs[ATTR_HS_COLOR]))
if ATTR_BRIGHTNESS in kwargs and self._device.is_dimmable:
self._device.set_level(kwargs[ATTR_BRIGHTNESS]) self._device.set_level(kwargs[ATTR_BRIGHTNESS])
else: else:
self._device.switch_on() self._device.switch_on()
@ -68,16 +71,16 @@ class AbodeLight(AbodeDevice, Light):
return self._device.brightness return self._device.brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Return the color of the light.""" """Return the color of the light."""
if self._device.is_dimmable and self._device.has_color: if self._device.is_dimmable and self._device.has_color:
return self._device.color return color_util.color_RGB_to_hs(*self._device.color)
@property @property
def supported_features(self): def supported_features(self):
"""Flag supported features.""" """Flag supported features."""
if self._device.is_dimmable and self._device.has_color: if self._device.is_dimmable and self._device.has_color:
return SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR return SUPPORT_BRIGHTNESS | SUPPORT_COLOR
elif self._device.is_dimmable: elif self._device.is_dimmable:
return SUPPORT_BRIGHTNESS return SUPPORT_BRIGHTNESS

View File

@ -9,9 +9,11 @@ import logging
import voluptuous as vol import voluptuous as vol
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_RGB_COLOR, SUPPORT_RGB_COLOR, Light, PLATFORM_SCHEMA) ATTR_BRIGHTNESS, ATTR_HS_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR, Light,
PLATFORM_SCHEMA)
from homeassistant.const import CONF_NAME from homeassistant.const import CONF_NAME
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util
REQUIREMENTS = ['blinkstick==1.1.8'] REQUIREMENTS = ['blinkstick==1.1.8']
@ -21,7 +23,7 @@ CONF_SERIAL = 'serial'
DEFAULT_NAME = 'Blinkstick' DEFAULT_NAME = 'Blinkstick'
SUPPORT_BLINKSTICK = SUPPORT_RGB_COLOR SUPPORT_BLINKSTICK = SUPPORT_BRIGHTNESS | SUPPORT_COLOR
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_SERIAL): cv.string, vol.Required(CONF_SERIAL): cv.string,
@ -39,7 +41,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
stick = blinkstick.find_by_serial(serial) stick = blinkstick.find_by_serial(serial)
add_devices([BlinkStickLight(stick, name)]) add_devices([BlinkStickLight(stick, name)], True)
class BlinkStickLight(Light): class BlinkStickLight(Light):
@ -50,7 +52,8 @@ class BlinkStickLight(Light):
self._stick = stick self._stick = stick
self._name = name self._name = name
self._serial = stick.get_serial() self._serial = stick.get_serial()
self._rgb_color = stick.get_color() self._hs_color = None
self._brightness = None
@property @property
def should_poll(self): def should_poll(self):
@ -63,14 +66,19 @@ class BlinkStickLight(Light):
return self._name return self._name
@property @property
def rgb_color(self): def brightness(self):
"""Read back the brightness of the light."""
return self._brightness
@property
def hs_color(self):
"""Read back the color of the light.""" """Read back the color of the light."""
return self._rgb_color return self._hs_color
@property @property
def is_on(self): def is_on(self):
"""Check whether any of the LEDs colors are non-zero.""" """Return True if entity is on."""
return sum(self._rgb_color) > 0 return self._brightness > 0
@property @property
def supported_features(self): def supported_features(self):
@ -79,18 +87,24 @@ class BlinkStickLight(Light):
def update(self): def update(self):
"""Read back the device state.""" """Read back the device state."""
self._rgb_color = self._stick.get_color() rgb_color = self._stick.get_color()
hsv = color_util.color_RGB_to_hsv(*rgb_color)
self._hs_color = hsv[:2]
self._brightness = hsv[2]
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn the device on.""" """Turn the device on."""
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
self._rgb_color = kwargs[ATTR_RGB_COLOR] self._hs_color = kwargs[ATTR_HS_COLOR]
if ATTR_BRIGHTNESS in kwargs:
self._brightness = kwargs[ATTR_BRIGHTNESS]
else: else:
self._rgb_color = [255, 255, 255] self._brightness = 255
self._stick.set_color(red=self._rgb_color[0], rgb_color = color_util.color_hsv_to_RGB(
green=self._rgb_color[1], self._hs_color[0], self._hs_color[1], self._brightness / 255 * 100)
blue=self._rgb_color[2]) self._stick.set_color(
red=rgb_color[0], green=rgb_color[1], blue=rgb_color[2])
def turn_off(self, **kwargs): def turn_off(self, **kwargs):
"""Turn the device off.""" """Turn the device off."""

View File

@ -10,15 +10,16 @@ import voluptuous as vol
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, ATTR_RGB_COLOR, SUPPORT_RGB_COLOR, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, ATTR_HS_COLOR, SUPPORT_COLOR,
Light, PLATFORM_SCHEMA) Light, PLATFORM_SCHEMA)
from homeassistant.const import CONF_NAME from homeassistant.const import CONF_NAME
import homeassistant.util.color as color_util
REQUIREMENTS = ['blinkt==0.1.0'] REQUIREMENTS = ['blinkt==0.1.0']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SUPPORT_BLINKT = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR) SUPPORT_BLINKT = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR)
DEFAULT_NAME = 'blinkt' DEFAULT_NAME = 'blinkt'
@ -55,7 +56,7 @@ class BlinktLight(Light):
self._index = index self._index = index
self._is_on = False self._is_on = False
self._brightness = 255 self._brightness = 255
self._rgb_color = [255, 255, 255] self._hs_color = [0, 0]
@property @property
def name(self): def name(self):
@ -71,12 +72,9 @@ class BlinktLight(Light):
return self._brightness return self._brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Read back the color of the light. """Read back the color of the light."""
return self._hs_color
Returns [r, g, b] list with values in range of 0-255.
"""
return self._rgb_color
@property @property
def supported_features(self): def supported_features(self):
@ -100,16 +98,17 @@ class BlinktLight(Light):
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Instruct the light to turn on and set correct brightness & color.""" """Instruct the light to turn on and set correct brightness & color."""
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
self._rgb_color = kwargs[ATTR_RGB_COLOR] self._hs_color = kwargs[ATTR_HS_COLOR]
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
self._brightness = kwargs[ATTR_BRIGHTNESS] self._brightness = kwargs[ATTR_BRIGHTNESS]
percent_bright = (self._brightness / 255) percent_bright = (self._brightness / 255)
rgb_color = color_util.color_hs_to_RGB(*self._hs_color)
self._blinkt.set_pixel(self._index, self._blinkt.set_pixel(self._index,
self._rgb_color[0], rgb_color[0],
self._rgb_color[1], rgb_color[1],
self._rgb_color[2], rgb_color[2],
percent_bright) percent_bright)
self._blinkt.show() self._blinkt.show()

View File

@ -7,12 +7,12 @@ https://home-assistant.io/components/light.deconz/
from homeassistant.components.deconz import ( from homeassistant.components.deconz import (
DOMAIN as DATA_DECONZ, DATA_DECONZ_ID) DOMAIN as DATA_DECONZ, DATA_DECONZ_ID)
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_HS_COLOR,
ATTR_TRANSITION, ATTR_XY_COLOR, EFFECT_COLORLOOP, FLASH_LONG, FLASH_SHORT, ATTR_TRANSITION, EFFECT_COLORLOOP, FLASH_LONG, FLASH_SHORT,
SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT,
SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, SUPPORT_XY_COLOR, Light) SUPPORT_FLASH, SUPPORT_TRANSITION, Light)
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.util.color import color_RGB_to_xy import homeassistant.util.color as color_util
DEPENDENCIES = ['deconz'] DEPENDENCIES = ['deconz']
@ -51,8 +51,7 @@ class DeconzLight(Light):
self._features |= SUPPORT_COLOR_TEMP self._features |= SUPPORT_COLOR_TEMP
if self._light.xy is not None: if self._light.xy is not None:
self._features |= SUPPORT_RGB_COLOR self._features |= SUPPORT_COLOR
self._features |= SUPPORT_XY_COLOR
if self._light.effect is not None: if self._light.effect is not None:
self._features |= SUPPORT_EFFECT self._features |= SUPPORT_EFFECT
@ -124,14 +123,8 @@ class DeconzLight(Light):
if ATTR_COLOR_TEMP in kwargs: if ATTR_COLOR_TEMP in kwargs:
data['ct'] = kwargs[ATTR_COLOR_TEMP] data['ct'] = kwargs[ATTR_COLOR_TEMP]
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
xyb = color_RGB_to_xy( data['xy'] = color_util.color_hs_to_xy(*kwargs[ATTR_HS_COLOR])
*(int(val) for val in kwargs[ATTR_RGB_COLOR]))
data['xy'] = xyb[0], xyb[1]
data['bri'] = xyb[2]
if ATTR_XY_COLOR in kwargs:
data['xy'] = kwargs[ATTR_XY_COLOR]
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
data['bri'] = kwargs[ATTR_BRIGHTNESS] data['bri'] = kwargs[ATTR_BRIGHTNESS]

View File

@ -7,14 +7,13 @@ https://home-assistant.io/components/demo/
import random import random
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_HS_COLOR,
ATTR_RGB_COLOR, ATTR_WHITE_VALUE, ATTR_XY_COLOR, SUPPORT_BRIGHTNESS, ATTR_WHITE_VALUE, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT,
SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_RGB_COLOR, SUPPORT_WHITE_VALUE, SUPPORT_COLOR, SUPPORT_WHITE_VALUE, Light)
Light)
LIGHT_COLORS = [ LIGHT_COLORS = [
[237, 224, 33], (56, 86),
[255, 63, 111], (345, 75),
] ]
LIGHT_EFFECT_LIST = ['rainbow', 'none'] LIGHT_EFFECT_LIST = ['rainbow', 'none']
@ -22,7 +21,7 @@ LIGHT_EFFECT_LIST = ['rainbow', 'none']
LIGHT_TEMPS = [240, 380] LIGHT_TEMPS = [240, 380]
SUPPORT_DEMO = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT | SUPPORT_DEMO = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT |
SUPPORT_RGB_COLOR | SUPPORT_WHITE_VALUE) SUPPORT_COLOR | SUPPORT_WHITE_VALUE)
def setup_platform(hass, config, add_devices_callback, discovery_info=None): def setup_platform(hass, config, add_devices_callback, discovery_info=None):
@ -40,17 +39,16 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
class DemoLight(Light): class DemoLight(Light):
"""Representation of a demo light.""" """Representation of a demo light."""
def __init__(self, unique_id, name, state, available=False, rgb=None, def __init__(self, unique_id, name, state, available=False, hs_color=None,
ct=None, brightness=180, xy_color=(.5, .5), white=200, ct=None, brightness=180, white=200, effect_list=None,
effect_list=None, effect=None): effect=None):
"""Initialize the light.""" """Initialize the light."""
self._unique_id = unique_id self._unique_id = unique_id
self._name = name self._name = name
self._state = state self._state = state
self._rgb = rgb self._hs_color = hs_color
self._ct = ct or random.choice(LIGHT_TEMPS) self._ct = ct or random.choice(LIGHT_TEMPS)
self._brightness = brightness self._brightness = brightness
self._xy_color = xy_color
self._white = white self._white = white
self._effect_list = effect_list self._effect_list = effect_list
self._effect = effect self._effect = effect
@ -83,14 +81,9 @@ class DemoLight(Light):
return self._brightness return self._brightness
@property @property
def xy_color(self) -> tuple: def hs_color(self) -> tuple:
"""Return the XY color value [float, float].""" """Return the hs color value."""
return self._xy_color return self._hs_color
@property
def rgb_color(self) -> tuple:
"""Return the RBG color value."""
return self._rgb
@property @property
def color_temp(self) -> int: def color_temp(self) -> int:
@ -126,8 +119,8 @@ class DemoLight(Light):
"""Turn the light on.""" """Turn the light on."""
self._state = True self._state = True
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
self._rgb = kwargs[ATTR_RGB_COLOR] self._hs_color = kwargs[ATTR_HS_COLOR]
if ATTR_COLOR_TEMP in kwargs: if ATTR_COLOR_TEMP in kwargs:
self._ct = kwargs[ATTR_COLOR_TEMP] self._ct = kwargs[ATTR_COLOR_TEMP]
@ -135,9 +128,6 @@ class DemoLight(Light):
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
self._brightness = kwargs[ATTR_BRIGHTNESS] self._brightness = kwargs[ATTR_BRIGHTNESS]
if ATTR_XY_COLOR in kwargs:
self._xy_color = kwargs[ATTR_XY_COLOR]
if ATTR_WHITE_VALUE in kwargs: if ATTR_WHITE_VALUE in kwargs:
self._white = kwargs[ATTR_WHITE_VALUE] self._white = kwargs[ATTR_WHITE_VALUE]

View File

@ -12,10 +12,11 @@ import voluptuous as vol
from homeassistant.const import CONF_DEVICES, CONF_NAME, CONF_PROTOCOL from homeassistant.const import CONF_DEVICES, CONF_NAME, CONF_PROTOCOL
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_EFFECT, EFFECT_COLORLOOP, ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_EFFECT, EFFECT_COLORLOOP,
EFFECT_RANDOM, SUPPORT_BRIGHTNESS, SUPPORT_EFFECT, EFFECT_RANDOM, SUPPORT_BRIGHTNESS, SUPPORT_EFFECT,
SUPPORT_RGB_COLOR, Light, PLATFORM_SCHEMA) SUPPORT_COLOR, Light, PLATFORM_SCHEMA)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util
REQUIREMENTS = ['flux_led==0.21'] REQUIREMENTS = ['flux_led==0.21']
@ -27,7 +28,7 @@ ATTR_MODE = 'mode'
DOMAIN = 'flux_led' DOMAIN = 'flux_led'
SUPPORT_FLUX_LED = (SUPPORT_BRIGHTNESS | SUPPORT_EFFECT | SUPPORT_FLUX_LED = (SUPPORT_BRIGHTNESS | SUPPORT_EFFECT |
SUPPORT_RGB_COLOR) SUPPORT_COLOR)
MODE_RGB = 'rgb' MODE_RGB = 'rgb'
MODE_RGBW = 'rgbw' MODE_RGBW = 'rgbw'
@ -183,9 +184,9 @@ class FluxLight(Light):
return self._bulb.brightness return self._bulb.brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Return the color property.""" """Return the color property."""
return self._bulb.getRgb() return color_util.color_RGB_to_hs(*self._bulb.getRgb())
@property @property
def supported_features(self): def supported_features(self):
@ -202,7 +203,8 @@ class FluxLight(Light):
if not self.is_on: if not self.is_on:
self._bulb.turnOn() self._bulb.turnOn()
rgb = kwargs.get(ATTR_RGB_COLOR) hs_color = kwargs.get(ATTR_HS_COLOR)
rgb = color_util.color_hs_to_RGB(*hs_color)
brightness = kwargs.get(ATTR_BRIGHTNESS) brightness = kwargs.get(ATTR_BRIGHTNESS)
effect = kwargs.get(ATTR_EFFECT) effect = kwargs.get(ATTR_EFFECT)

View File

@ -19,12 +19,11 @@ from homeassistant.const import (STATE_ON, ATTR_ENTITY_ID, CONF_NAME,
from homeassistant.helpers.event import async_track_state_change from homeassistant.helpers.event import async_track_state_change
from homeassistant.helpers.typing import HomeAssistantType, ConfigType from homeassistant.helpers.typing import HomeAssistantType, ConfigType
from homeassistant.components.light import ( from homeassistant.components.light import (
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_TRANSITION,
SUPPORT_TRANSITION, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_XY_COLOR, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_WHITE_VALUE, PLATFORM_SCHEMA,
SUPPORT_WHITE_VALUE, PLATFORM_SCHEMA, ATTR_BRIGHTNESS, ATTR_XY_COLOR, ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_WHITE_VALUE, ATTR_COLOR_TEMP,
ATTR_RGB_COLOR, ATTR_WHITE_VALUE, ATTR_COLOR_TEMP, ATTR_MIN_MIREDS, ATTR_MIN_MIREDS, ATTR_MAX_MIREDS, ATTR_EFFECT_LIST, ATTR_EFFECT,
ATTR_MAX_MIREDS, ATTR_EFFECT_LIST, ATTR_EFFECT, ATTR_FLASH, ATTR_FLASH, ATTR_TRANSITION)
ATTR_TRANSITION)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -37,8 +36,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
}) })
SUPPORT_GROUP_LIGHT = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT SUPPORT_GROUP_LIGHT = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT
| SUPPORT_FLASH | SUPPORT_RGB_COLOR | SUPPORT_TRANSITION | SUPPORT_FLASH | SUPPORT_COLOR | SUPPORT_TRANSITION
| SUPPORT_XY_COLOR | SUPPORT_WHITE_VALUE) | SUPPORT_WHITE_VALUE)
async def async_setup_platform(hass: HomeAssistantType, config: ConfigType, async def async_setup_platform(hass: HomeAssistantType, config: ConfigType,
@ -58,8 +57,7 @@ class LightGroup(light.Light):
self._is_on = False # type: bool self._is_on = False # type: bool
self._available = False # type: bool self._available = False # type: bool
self._brightness = None # type: Optional[int] self._brightness = None # type: Optional[int]
self._xy_color = None # type: Optional[Tuple[float, float]] self._hs_color = None # type: Optional[Tuple[float, float]]
self._rgb_color = None # type: Optional[Tuple[int, int, int]]
self._color_temp = None # type: Optional[int] self._color_temp = None # type: Optional[int]
self._min_mireds = 154 # type: Optional[int] self._min_mireds = 154 # type: Optional[int]
self._max_mireds = 500 # type: Optional[int] self._max_mireds = 500 # type: Optional[int]
@ -108,14 +106,9 @@ class LightGroup(light.Light):
return self._brightness return self._brightness
@property @property
def xy_color(self) -> Optional[Tuple[float, float]]: def hs_color(self) -> Optional[Tuple[float, float]]:
"""Return the XY color value [float, float].""" """Return the HS color value [float, float]."""
return self._xy_color return self._hs_color
@property
def rgb_color(self) -> Optional[Tuple[int, int, int]]:
"""Return the RGB color value [int, int, int]."""
return self._rgb_color
@property @property
def color_temp(self) -> Optional[int]: def color_temp(self) -> Optional[int]:
@ -164,11 +157,8 @@ class LightGroup(light.Light):
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
data[ATTR_BRIGHTNESS] = kwargs[ATTR_BRIGHTNESS] data[ATTR_BRIGHTNESS] = kwargs[ATTR_BRIGHTNESS]
if ATTR_XY_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
data[ATTR_XY_COLOR] = kwargs[ATTR_XY_COLOR] data[ATTR_HS_COLOR] = kwargs[ATTR_HS_COLOR]
if ATTR_RGB_COLOR in kwargs:
data[ATTR_RGB_COLOR] = kwargs[ATTR_RGB_COLOR]
if ATTR_COLOR_TEMP in kwargs: if ATTR_COLOR_TEMP in kwargs:
data[ATTR_COLOR_TEMP] = kwargs[ATTR_COLOR_TEMP] data[ATTR_COLOR_TEMP] = kwargs[ATTR_COLOR_TEMP]
@ -210,13 +200,8 @@ class LightGroup(light.Light):
self._brightness = _reduce_attribute(on_states, ATTR_BRIGHTNESS) self._brightness = _reduce_attribute(on_states, ATTR_BRIGHTNESS)
self._xy_color = _reduce_attribute( self._hs_color = _reduce_attribute(
on_states, ATTR_XY_COLOR, reduce=_mean_tuple) on_states, ATTR_HS_COLOR, reduce=_mean_tuple)
self._rgb_color = _reduce_attribute(
on_states, ATTR_RGB_COLOR, reduce=_mean_tuple)
if self._rgb_color is not None:
self._rgb_color = tuple(map(int, self._rgb_color))
self._white_value = _reduce_attribute(on_states, ATTR_WHITE_VALUE) self._white_value = _reduce_attribute(on_states, ATTR_WHITE_VALUE)

View File

@ -4,13 +4,13 @@ Support for the Hive devices.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/light.hive/ https://home-assistant.io/components/light.hive/
""" """
import colorsys
from homeassistant.components.hive import DATA_HIVE from homeassistant.components.hive import DATA_HIVE
from homeassistant.components.light import (ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, from homeassistant.components.light import (ATTR_BRIGHTNESS, ATTR_COLOR_TEMP,
ATTR_RGB_COLOR, ATTR_HS_COLOR,
SUPPORT_BRIGHTNESS, SUPPORT_BRIGHTNESS,
SUPPORT_COLOR_TEMP, SUPPORT_COLOR_TEMP,
SUPPORT_RGB_COLOR, Light) SUPPORT_COLOR, Light)
import homeassistant.util.color as color_util
DEPENDENCIES = ['hive'] DEPENDENCIES = ['hive']
@ -75,10 +75,11 @@ class HiveDeviceLight(Light):
return self.session.light.get_color_temp(self.node_id) return self.session.light.get_color_temp(self.node_id)
@property @property
def rgb_color(self) -> tuple: def hs_color(self) -> tuple:
"""Return the RBG color value.""" """Return the hs color value."""
if self.light_device_type == "colourtuneablelight": if self.light_device_type == "colourtuneablelight":
return self.session.light.get_color(self.node_id) rgb = self.session.light.get_color(self.node_id)
return color_util.color_RGB_to_hs(*rgb)
@property @property
def is_on(self): def is_on(self):
@ -99,15 +100,11 @@ class HiveDeviceLight(Light):
if ATTR_COLOR_TEMP in kwargs: if ATTR_COLOR_TEMP in kwargs:
tmp_new_color_temp = kwargs.get(ATTR_COLOR_TEMP) tmp_new_color_temp = kwargs.get(ATTR_COLOR_TEMP)
new_color_temp = round(1000000 / tmp_new_color_temp) new_color_temp = round(1000000 / tmp_new_color_temp)
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
get_new_color = kwargs.get(ATTR_RGB_COLOR) get_new_color = kwargs.get(ATTR_HS_COLOR)
tmp_new_color = colorsys.rgb_to_hsv(get_new_color[0], hue = int(get_new_color[0])
get_new_color[1], saturation = int(get_new_color[1])
get_new_color[2]) new_color = (hue, saturation, 100)
hue = int(round(tmp_new_color[0] * 360))
saturation = int(round(tmp_new_color[1] * 100))
value = int(round((tmp_new_color[2] / 255) * 100))
new_color = (hue, saturation, value)
self.session.light.turn_on(self.node_id, self.light_device_type, self.session.light.turn_on(self.node_id, self.light_device_type,
new_brightness, new_color_temp, new_brightness, new_color_temp,
@ -132,7 +129,7 @@ class HiveDeviceLight(Light):
supported_features = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP) supported_features = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP)
elif self.light_device_type == "colourtuneablelight": elif self.light_device_type == "colourtuneablelight":
supported_features = ( supported_features = (
SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR) SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_COLOR)
return supported_features return supported_features

View File

@ -13,12 +13,11 @@ import async_timeout
import homeassistant.components.hue as hue import homeassistant.components.hue as hue
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH,
ATTR_TRANSITION, ATTR_XY_COLOR, EFFECT_COLORLOOP, EFFECT_RANDOM, ATTR_TRANSITION, ATTR_HS_COLOR, EFFECT_COLORLOOP, EFFECT_RANDOM,
FLASH_LONG, FLASH_SHORT, SUPPORT_BRIGHTNESS, FLASH_LONG, FLASH_SHORT, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP,
SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_RGB_COLOR, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_COLOR, SUPPORT_TRANSITION,
SUPPORT_TRANSITION, SUPPORT_XY_COLOR, Light) Light)
import homeassistant.util.color as color_util
DEPENDENCIES = ['hue'] DEPENDENCIES = ['hue']
SCAN_INTERVAL = timedelta(seconds=5) SCAN_INTERVAL = timedelta(seconds=5)
@ -28,8 +27,7 @@ _LOGGER = logging.getLogger(__name__)
SUPPORT_HUE_ON_OFF = (SUPPORT_FLASH | SUPPORT_TRANSITION) SUPPORT_HUE_ON_OFF = (SUPPORT_FLASH | SUPPORT_TRANSITION)
SUPPORT_HUE_DIMMABLE = (SUPPORT_HUE_ON_OFF | SUPPORT_BRIGHTNESS) SUPPORT_HUE_DIMMABLE = (SUPPORT_HUE_ON_OFF | SUPPORT_BRIGHTNESS)
SUPPORT_HUE_COLOR_TEMP = (SUPPORT_HUE_DIMMABLE | SUPPORT_COLOR_TEMP) SUPPORT_HUE_COLOR_TEMP = (SUPPORT_HUE_DIMMABLE | SUPPORT_COLOR_TEMP)
SUPPORT_HUE_COLOR = (SUPPORT_HUE_DIMMABLE | SUPPORT_EFFECT | SUPPORT_HUE_COLOR = (SUPPORT_HUE_DIMMABLE | SUPPORT_EFFECT | SUPPORT_COLOR)
SUPPORT_RGB_COLOR | SUPPORT_XY_COLOR)
SUPPORT_HUE_EXTENDED = (SUPPORT_HUE_COLOR_TEMP | SUPPORT_HUE_COLOR) SUPPORT_HUE_EXTENDED = (SUPPORT_HUE_COLOR_TEMP | SUPPORT_HUE_COLOR)
SUPPORT_HUE = { SUPPORT_HUE = {
@ -228,11 +226,17 @@ class HueLight(Light):
return self.light.state.get('bri') return self.light.state.get('bri')
@property @property
def xy_color(self): def hs_color(self):
"""Return the XY color value.""" """Return the hs color value."""
if self.is_group: if self.is_group:
return self.light.action.get('xy') return (
return self.light.state.get('xy') self.light.action.get('hue') / 65535 * 360,
self.light.action.get('sat') / 255 * 100,
)
return (
self.light.state.get('hue') / 65535 * 360,
self.light.state.get('sat') / 255 * 100,
)
@property @property
def color_temp(self): def color_temp(self):
@ -272,25 +276,9 @@ class HueLight(Light):
if ATTR_TRANSITION in kwargs: if ATTR_TRANSITION in kwargs:
command['transitiontime'] = int(kwargs[ATTR_TRANSITION] * 10) command['transitiontime'] = int(kwargs[ATTR_TRANSITION] * 10)
if ATTR_XY_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
if self.is_osram: command['hue'] = int(kwargs[ATTR_HS_COLOR][0] / 360 * 65535)
color_hue, sat = color_util.color_xy_to_hs( command['sat'] = int(kwargs[ATTR_HS_COLOR][1] / 100 * 255)
*kwargs[ATTR_XY_COLOR])
command['hue'] = color_hue / 360 * 65535
command['sat'] = sat / 100 * 255
else:
command['xy'] = kwargs[ATTR_XY_COLOR]
elif ATTR_RGB_COLOR in kwargs:
if self.is_osram:
hsv = color_util.color_RGB_to_hsv(
*(int(val) for val in kwargs[ATTR_RGB_COLOR]))
command['hue'] = hsv[0] / 360 * 65535
command['sat'] = hsv[1] / 100 * 255
command['bri'] = hsv[2] / 100 * 255
else:
xyb = color_util.color_RGB_to_xy(
*(int(val) for val in kwargs[ATTR_RGB_COLOR]))
command['xy'] = xyb[0], xyb[1]
elif ATTR_COLOR_TEMP in kwargs: elif ATTR_COLOR_TEMP in kwargs:
temp = kwargs[ATTR_COLOR_TEMP] temp = kwargs[ATTR_COLOR_TEMP]
command['ct'] = max(self.min_mireds, min(temp, self.max_mireds)) command['ct'] = max(self.min_mireds, min(temp, self.max_mireds))

View File

@ -11,10 +11,11 @@ import socket
import voluptuous as vol import voluptuous as vol
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_EFFECT, SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_EFFECT, SUPPORT_BRIGHTNESS,
SUPPORT_RGB_COLOR, SUPPORT_EFFECT, Light, PLATFORM_SCHEMA) SUPPORT_COLOR, SUPPORT_EFFECT, Light, PLATFORM_SCHEMA)
from homeassistant.const import (CONF_HOST, CONF_PORT, CONF_NAME) from homeassistant.const import (CONF_HOST, CONF_PORT, CONF_NAME)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -40,7 +41,7 @@ DEFAULT_EFFECT_LIST = ['HDMI', 'Cinema brighten lights', 'Cinema dim lights',
'Color traces', 'UDP multicast listener', 'Color traces', 'UDP multicast listener',
'UDP listener', 'X-Mas'] 'UDP listener', 'X-Mas']
SUPPORT_HYPERION = (SUPPORT_RGB_COLOR | SUPPORT_BRIGHTNESS | SUPPORT_EFFECT) SUPPORT_HYPERION = (SUPPORT_COLOR | SUPPORT_BRIGHTNESS | SUPPORT_EFFECT)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string, vol.Required(CONF_HOST): cv.string,
@ -107,9 +108,9 @@ class Hyperion(Light):
return self._brightness return self._brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Return last RGB color value set.""" """Return last color value set."""
return self._rgb_color return color_util.color_RGB_to_hs(*self._rgb_color)
@property @property
def is_on(self): def is_on(self):
@ -138,8 +139,8 @@ class Hyperion(Light):
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn the lights on.""" """Turn the lights on."""
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
rgb_color = kwargs[ATTR_RGB_COLOR] rgb_color = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR])
elif self._rgb_mem == [0, 0, 0]: elif self._rgb_mem == [0, 0, 0]:
rgb_color = self._default_color rgb_color = self._default_color
else: else:

View File

@ -10,8 +10,8 @@ import math
import voluptuous as vol import voluptuous as vol
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_RGB_COLOR, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_HS_COLOR,
SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, SUPPORT_EFFECT, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR, SUPPORT_EFFECT,
PLATFORM_SCHEMA, Light) PLATFORM_SCHEMA, Light)
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
@ -77,9 +77,9 @@ class IGloLamp(Light):
self._lamp.min_kelvin)) self._lamp.min_kelvin))
@property @property
def rgb_color(self): def hs_color(self):
"""Return the RGB value.""" """Return the hs value."""
return self._lamp.state()['rgb'] return color_util.color_RGB_to_hsv(*self._lamp.state()['rgb'])
@property @property
def effect(self): def effect(self):
@ -95,7 +95,7 @@ class IGloLamp(Light):
def supported_features(self): def supported_features(self):
"""Flag supported features.""" """Flag supported features."""
return (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | return (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP |
SUPPORT_RGB_COLOR | SUPPORT_EFFECT) SUPPORT_COLOR | SUPPORT_EFFECT)
@property @property
def is_on(self): def is_on(self):
@ -111,8 +111,8 @@ class IGloLamp(Light):
self._lamp.brightness(brightness) self._lamp.brightness(brightness)
return return
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
rgb = kwargs[ATTR_RGB_COLOR] rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR])
self._lamp.rgb(*rgb) self._lamp.rgb(*rgb)
return return

View File

@ -9,11 +9,12 @@ import voluptuous as vol
from homeassistant.components.knx import ATTR_DISCOVER_DEVICES, DATA_KNX from homeassistant.components.knx import ATTR_DISCOVER_DEVICES, DATA_KNX
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_RGB_COLOR, PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS, ATTR_HS_COLOR, PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS,
SUPPORT_RGB_COLOR, Light) SUPPORT_COLOR, Light)
from homeassistant.const import CONF_NAME from homeassistant.const import CONF_NAME
from homeassistant.core import callback from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util
CONF_ADDRESS = 'address' CONF_ADDRESS = 'address'
CONF_STATE_ADDRESS = 'state_address' CONF_STATE_ADDRESS = 'state_address'
@ -114,15 +115,10 @@ class KNXLight(Light):
None None
@property @property
def xy_color(self): def hs_color(self):
"""Return the XY color value [float, float].""" """Return the HS color value."""
return None
@property
def rgb_color(self):
"""Return the RBG color value."""
if self.device.supports_color: if self.device.supports_color:
return self.device.current_color return color_util.color_RGB_to_hs(*self.device.current_color)
return None return None
@property @property
@ -157,7 +153,7 @@ class KNXLight(Light):
if self.device.supports_brightness: if self.device.supports_brightness:
flags |= SUPPORT_BRIGHTNESS flags |= SUPPORT_BRIGHTNESS
if self.device.supports_color: if self.device.supports_color:
flags |= SUPPORT_RGB_COLOR flags |= SUPPORT_COLOR
return flags return flags
async def async_turn_on(self, **kwargs): async def async_turn_on(self, **kwargs):
@ -165,9 +161,10 @@ class KNXLight(Light):
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
if self.device.supports_brightness: if self.device.supports_brightness:
await self.device.set_brightness(int(kwargs[ATTR_BRIGHTNESS])) await self.device.set_brightness(int(kwargs[ATTR_BRIGHTNESS]))
elif ATTR_RGB_COLOR in kwargs: elif ATTR_HS_COLOR in kwargs:
if self.device.supports_color: if self.device.supports_color:
await self.device.set_color(kwargs[ATTR_RGB_COLOR]) await self.device.set_color(color_util.color_hs_to_RGB(
*kwargs[ATTR_HS_COLOR]))
else: else:
await self.device.set_on() await self.device.set_on()

View File

@ -16,10 +16,10 @@ import voluptuous as vol
from homeassistant import util from homeassistant import util
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_COLOR_NAME, ATTR_COLOR_TEMP, ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_COLOR_NAME, ATTR_COLOR_TEMP,
ATTR_EFFECT, ATTR_KELVIN, ATTR_RGB_COLOR, ATTR_TRANSITION, ATTR_XY_COLOR, ATTR_EFFECT, ATTR_HS_COLOR, ATTR_KELVIN, ATTR_RGB_COLOR, ATTR_TRANSITION,
DOMAIN, LIGHT_TURN_ON_SCHEMA, PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS, ATTR_XY_COLOR, COLOR_GROUP, DOMAIN, LIGHT_TURN_ON_SCHEMA, PLATFORM_SCHEMA,
SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT,
SUPPORT_XY_COLOR, VALID_BRIGHTNESS, VALID_BRIGHTNESS_PCT, Light, SUPPORT_TRANSITION, VALID_BRIGHTNESS, VALID_BRIGHTNESS_PCT, Light,
preprocess_turn_on_alternatives) preprocess_turn_on_alternatives)
from homeassistant.const import ATTR_ENTITY_ID, EVENT_HOMEASSISTANT_STOP from homeassistant.const import ATTR_ENTITY_ID, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import callback from homeassistant.core import callback
@ -87,11 +87,22 @@ LIFX_EFFECT_SCHEMA = vol.Schema({
LIFX_EFFECT_PULSE_SCHEMA = LIFX_EFFECT_SCHEMA.extend({ LIFX_EFFECT_PULSE_SCHEMA = LIFX_EFFECT_SCHEMA.extend({
ATTR_BRIGHTNESS: VALID_BRIGHTNESS, ATTR_BRIGHTNESS: VALID_BRIGHTNESS,
ATTR_BRIGHTNESS_PCT: VALID_BRIGHTNESS_PCT, ATTR_BRIGHTNESS_PCT: VALID_BRIGHTNESS_PCT,
ATTR_COLOR_NAME: cv.string, vol.Exclusive(ATTR_COLOR_NAME, COLOR_GROUP): cv.string,
ATTR_RGB_COLOR: vol.All(vol.ExactSequence((cv.byte, cv.byte, cv.byte)), vol.Exclusive(ATTR_RGB_COLOR, COLOR_GROUP):
vol.All(vol.ExactSequence((cv.byte, cv.byte, cv.byte)),
vol.Coerce(tuple)), vol.Coerce(tuple)),
ATTR_COLOR_TEMP: vol.All(vol.Coerce(int), vol.Range(min=1)), vol.Exclusive(ATTR_XY_COLOR, COLOR_GROUP):
ATTR_KELVIN: vol.All(vol.Coerce(int), vol.Range(min=0)), vol.All(vol.ExactSequence((cv.small_float, cv.small_float)),
vol.Coerce(tuple)),
vol.Exclusive(ATTR_HS_COLOR, COLOR_GROUP):
vol.All(vol.ExactSequence(
(vol.All(vol.Coerce(float), vol.Range(min=0, max=360)),
vol.All(vol.Coerce(float), vol.Range(min=0, max=100)))),
vol.Coerce(tuple)),
vol.Exclusive(ATTR_COLOR_TEMP, COLOR_GROUP):
vol.All(vol.Coerce(int), vol.Range(min=1)),
vol.Exclusive(ATTR_KELVIN, COLOR_GROUP):
vol.All(vol.Coerce(int), vol.Range(min=0)),
ATTR_PERIOD: vol.All(vol.Coerce(float), vol.Range(min=0.05)), ATTR_PERIOD: vol.All(vol.Coerce(float), vol.Range(min=0.05)),
ATTR_CYCLES: vol.All(vol.Coerce(float), vol.Range(min=1)), ATTR_CYCLES: vol.All(vol.Coerce(float), vol.Range(min=1)),
ATTR_MODE: vol.In(PULSE_MODES), ATTR_MODE: vol.In(PULSE_MODES),
@ -168,16 +179,8 @@ def find_hsbk(**kwargs):
preprocess_turn_on_alternatives(kwargs) preprocess_turn_on_alternatives(kwargs)
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
hue, saturation, brightness = \ hue, saturation = kwargs[ATTR_HS_COLOR]
color_util.color_RGB_to_hsv(*kwargs[ATTR_RGB_COLOR])
hue = int(hue / 360 * 65535)
saturation = int(saturation / 100 * 65535)
brightness = int(brightness / 100 * 65535)
kelvin = 3500
if ATTR_XY_COLOR in kwargs:
hue, saturation = color_util.color_xy_to_hs(*kwargs[ATTR_XY_COLOR])
hue = int(hue / 360 * 65535) hue = int(hue / 360 * 65535)
saturation = int(saturation / 100 * 65535) saturation = int(saturation / 100 * 65535)
kelvin = 3500 kelvin = 3500
@ -585,7 +588,7 @@ class LIFXColor(LIFXLight):
def supported_features(self): def supported_features(self):
"""Flag supported features.""" """Flag supported features."""
support = super().supported_features support = super().supported_features
support |= SUPPORT_RGB_COLOR | SUPPORT_XY_COLOR support |= SUPPORT_COLOR
return support return support
@property @property
@ -598,15 +601,12 @@ class LIFXColor(LIFXLight):
] ]
@property @property
def rgb_color(self): def hs_color(self):
"""Return the RGB value.""" """Return the hs value."""
hue, sat, bri, _ = self.device.color hue, sat, _, _ = self.device.color
hue = hue / 65535 * 360 hue = hue / 65535 * 360
sat = sat / 65535 * 100 sat = sat / 65535 * 100
bri = bri / 65535 * 100 return (hue, sat)
return color_util.color_hsv_to_RGB(hue, sat, bri)
class LIFXStrip(LIFXColor): class LIFXStrip(LIFXColor):

View File

@ -7,14 +7,13 @@ not yet support Windows.
For more details about this platform, please refer to the documentation at 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 colorsys
import logging import logging
import voluptuous as vol import voluptuous as vol
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_TRANSITION, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR, ATTR_TRANSITION,
SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR,
SUPPORT_TRANSITION, Light, PLATFORM_SCHEMA) SUPPORT_TRANSITION, Light, PLATFORM_SCHEMA)
from homeassistant.helpers.event import track_time_change from homeassistant.helpers.event import track_time_change
from homeassistant.util.color import ( from homeassistant.util.color import (
@ -37,7 +36,7 @@ TEMP_MAX_HASS = 500
TEMP_MIN = 2500 TEMP_MIN = 2500
TEMP_MIN_HASS = 154 TEMP_MIN_HASS = 154
SUPPORT_LIFX = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR | SUPPORT_LIFX = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_COLOR |
SUPPORT_TRANSITION) SUPPORT_TRANSITION)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@ -129,17 +128,6 @@ class LIFX(object):
self._liffylights.probe(address) self._liffylights.probe(address)
def convert_rgb_to_hsv(rgb):
"""Convert Home Assistant RGB values to HSV values."""
red, green, blue = [_ / BYTE_MAX for _ in rgb]
hue, saturation, brightness = colorsys.rgb_to_hsv(red, green, blue)
return [int(hue * SHORT_MAX),
int(saturation * SHORT_MAX),
int(brightness * SHORT_MAX)]
class LIFXLight(Light): class LIFXLight(Light):
"""Representation of a LIFX light.""" """Representation of a LIFX light."""
@ -170,11 +158,9 @@ class LIFXLight(Light):
return self._ip return self._ip
@property @property
def rgb_color(self): def hs_color(self):
"""Return the RGB value.""" """Return the hs value."""
_LOGGER.debug( return (self._hue / 65535 * 360, self._sat / 65535 * 100)
"rgb_color: [%d %d %d]", self._rgb[0], self._rgb[1], self._rgb[2])
return self._rgb
@property @property
def brightness(self): def brightness(self):
@ -209,13 +195,13 @@ class LIFXLight(Light):
else: else:
fade = 0 fade = 0
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
hue, saturation, brightness = \ hue, saturation = kwargs[ATTR_HS_COLOR]
convert_rgb_to_hsv(kwargs[ATTR_RGB_COLOR]) hue = hue / 360 * 65535
saturation = saturation / 100 * 65535
else: else:
hue = self._hue hue = self._hue
saturation = self._sat saturation = self._sat
brightness = self._bri
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
brightness = kwargs[ATTR_BRIGHTNESS] * (BYTE_MAX + 1) brightness = kwargs[ATTR_BRIGHTNESS] * (BYTE_MAX + 1)
@ -265,16 +251,3 @@ class LIFXLight(Light):
self._sat = sat self._sat = sat
self._bri = bri self._bri = bri
self._kel = kel self._kel = kel
red, green, blue = colorsys.hsv_to_rgb(hue / SHORT_MAX,
sat / SHORT_MAX,
bri / SHORT_MAX)
red = int(red * BYTE_MAX)
green = int(green * BYTE_MAX)
blue = int(blue * BYTE_MAX)
_LOGGER.debug("set_color: %d %d %d %d [%d %d %d]",
hue, sat, bri, kel, red, green, blue)
self._rgb = [red, green, blue]

View File

@ -12,12 +12,13 @@ import voluptuous as vol
from homeassistant.const import ( from homeassistant.const import (
CONF_NAME, CONF_HOST, CONF_PORT, CONF_TYPE, STATE_ON) CONF_NAME, CONF_HOST, CONF_PORT, CONF_TYPE, STATE_ON)
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_HS_COLOR,
ATTR_TRANSITION, EFFECT_COLORLOOP, EFFECT_WHITE, FLASH_LONG, ATTR_TRANSITION, EFFECT_COLORLOOP, EFFECT_WHITE, FLASH_LONG,
SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH,
SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, Light, PLATFORM_SCHEMA) SUPPORT_COLOR, SUPPORT_TRANSITION, Light, PLATFORM_SCHEMA)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.util.color import color_temperature_mired_to_kelvin from homeassistant.util.color import (
color_temperature_mired_to_kelvin, color_hs_to_RGB)
from homeassistant.helpers.restore_state import async_get_last_state from homeassistant.helpers.restore_state import async_get_last_state
REQUIREMENTS = ['limitlessled==1.1.0'] REQUIREMENTS = ['limitlessled==1.1.0']
@ -40,19 +41,19 @@ LED_TYPE = ['rgbw', 'rgbww', 'white', 'bridge-led', 'dimmer']
EFFECT_NIGHT = 'night' EFFECT_NIGHT = 'night'
RGB_BOUNDARY = 40 MIN_SATURATION = 10
WHITE = [255, 255, 255] WHITE = [0, 0]
SUPPORT_LIMITLESSLED_WHITE = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_LIMITLESSLED_WHITE = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP |
SUPPORT_TRANSITION) SUPPORT_TRANSITION)
SUPPORT_LIMITLESSLED_DIMMER = (SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION) SUPPORT_LIMITLESSLED_DIMMER = (SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION)
SUPPORT_LIMITLESSLED_RGB = (SUPPORT_BRIGHTNESS | SUPPORT_EFFECT | SUPPORT_LIMITLESSLED_RGB = (SUPPORT_BRIGHTNESS | SUPPORT_EFFECT |
SUPPORT_FLASH | SUPPORT_RGB_COLOR | SUPPORT_FLASH | SUPPORT_COLOR |
SUPPORT_TRANSITION) SUPPORT_TRANSITION)
SUPPORT_LIMITLESSLED_RGBWW = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_LIMITLESSLED_RGBWW = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP |
SUPPORT_EFFECT | SUPPORT_FLASH | SUPPORT_EFFECT | SUPPORT_FLASH |
SUPPORT_RGB_COLOR | SUPPORT_TRANSITION) SUPPORT_COLOR | SUPPORT_TRANSITION)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_BRIDGES): vol.All(cv.ensure_list, [ vol.Required(CONF_BRIDGES): vol.All(cv.ensure_list, [
@ -239,7 +240,7 @@ class LimitlessLEDGroup(Light):
return self._temperature return self._temperature
@property @property
def rgb_color(self): def hs_color(self):
"""Return the color property.""" """Return the color property."""
return self._color return self._color
@ -282,17 +283,17 @@ class LimitlessLEDGroup(Light):
self._brightness = kwargs[ATTR_BRIGHTNESS] self._brightness = kwargs[ATTR_BRIGHTNESS]
args['brightness'] = self.limitlessled_brightness() args['brightness'] = self.limitlessled_brightness()
if ATTR_RGB_COLOR in kwargs and self._supported & SUPPORT_RGB_COLOR: if ATTR_HS_COLOR in kwargs and self._supported & SUPPORT_COLOR:
self._color = kwargs[ATTR_RGB_COLOR] self._color = kwargs[ATTR_HS_COLOR]
# White is a special case. # White is a special case.
if min(self._color) > 256 - RGB_BOUNDARY: if self._color[1] < MIN_SATURATION:
pipeline.white() pipeline.white()
self._color = WHITE self._color = WHITE
else: else:
args['color'] = self.limitlessled_color() args['color'] = self.limitlessled_color()
if ATTR_COLOR_TEMP in kwargs: if ATTR_COLOR_TEMP in kwargs:
if self._supported & SUPPORT_RGB_COLOR: if self._supported & SUPPORT_COLOR:
pipeline.white() pipeline.white()
self._color = WHITE self._color = WHITE
if self._supported & SUPPORT_COLOR_TEMP: if self._supported & SUPPORT_COLOR_TEMP:
@ -333,6 +334,6 @@ class LimitlessLEDGroup(Light):
return self._brightness / 255 return self._brightness / 255
def limitlessled_color(self): def limitlessled_color(self):
"""Convert Home Assistant RGB list to Color tuple.""" """Convert Home Assistant HS list to RGB Color tuple."""
from limitlessled import Color from limitlessled import Color
return Color(*tuple(self._color)) return Color(color_hs_to_RGB(*tuple(self._color)))

View File

@ -12,10 +12,9 @@ import voluptuous as vol
from homeassistant.core import callback from homeassistant.core import callback
import homeassistant.components.mqtt as mqtt import homeassistant.components.mqtt as mqtt
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_RGB_COLOR, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_HS_COLOR,
ATTR_WHITE_VALUE, ATTR_XY_COLOR, Light, SUPPORT_BRIGHTNESS, ATTR_WHITE_VALUE, Light, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP,
SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_RGB_COLOR, SUPPORT_EFFECT, SUPPORT_COLOR, SUPPORT_WHITE_VALUE)
SUPPORT_WHITE_VALUE, SUPPORT_XY_COLOR)
from homeassistant.const import ( from homeassistant.const import (
CONF_BRIGHTNESS, CONF_COLOR_TEMP, CONF_EFFECT, CONF_NAME, CONF_BRIGHTNESS, CONF_COLOR_TEMP, CONF_EFFECT, CONF_NAME,
CONF_OPTIMISTIC, CONF_PAYLOAD_OFF, CONF_PAYLOAD_ON, CONF_OPTIMISTIC, CONF_PAYLOAD_OFF, CONF_PAYLOAD_ON,
@ -25,6 +24,7 @@ from homeassistant.components.mqtt import (
CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS, CONF_RETAIN, CONF_STATE_TOPIC, CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS, CONF_RETAIN, CONF_STATE_TOPIC,
MqttAvailability) MqttAvailability)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -191,14 +191,13 @@ class MqttLight(MqttAvailability, Light):
self._on_command_type = on_command_type self._on_command_type = on_command_type
self._state = False self._state = False
self._brightness = None self._brightness = None
self._rgb = None self._hs = None
self._color_temp = None self._color_temp = None
self._effect = None self._effect = None
self._white_value = None self._white_value = None
self._xy = None
self._supported_features = 0 self._supported_features = 0
self._supported_features |= ( self._supported_features |= (
topic[CONF_RGB_COMMAND_TOPIC] is not None and SUPPORT_RGB_COLOR) topic[CONF_RGB_COMMAND_TOPIC] is not None and SUPPORT_COLOR)
self._supported_features |= ( self._supported_features |= (
topic[CONF_BRIGHTNESS_COMMAND_TOPIC] is not None and topic[CONF_BRIGHTNESS_COMMAND_TOPIC] is not None and
SUPPORT_BRIGHTNESS) SUPPORT_BRIGHTNESS)
@ -212,7 +211,7 @@ class MqttLight(MqttAvailability, Light):
topic[CONF_WHITE_VALUE_COMMAND_TOPIC] is not None and topic[CONF_WHITE_VALUE_COMMAND_TOPIC] is not None and
SUPPORT_WHITE_VALUE) SUPPORT_WHITE_VALUE)
self._supported_features |= ( self._supported_features |= (
topic[CONF_XY_COMMAND_TOPIC] is not None and SUPPORT_XY_COLOR) topic[CONF_XY_COMMAND_TOPIC] is not None and SUPPORT_COLOR)
@asyncio.coroutine @asyncio.coroutine
def async_added_to_hass(self): def async_added_to_hass(self):
@ -263,19 +262,18 @@ class MqttLight(MqttAvailability, Light):
@callback @callback
def rgb_received(topic, payload, qos): def rgb_received(topic, payload, qos):
"""Handle new MQTT messages for RGB.""" """Handle new MQTT messages for RGB."""
self._rgb = [int(val) for val in rgb = [int(val) for val in
templates[CONF_RGB](payload).split(',')] templates[CONF_RGB](payload).split(',')]
self._hs = color_util.color_RGB_to_hs(*rgb)
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
if self._topic[CONF_RGB_STATE_TOPIC] is not None: if self._topic[CONF_RGB_STATE_TOPIC] is not None:
yield from mqtt.async_subscribe( yield from mqtt.async_subscribe(
self.hass, self._topic[CONF_RGB_STATE_TOPIC], rgb_received, self.hass, self._topic[CONF_RGB_STATE_TOPIC], rgb_received,
self._qos) self._qos)
self._rgb = [255, 255, 255] self._hs = (0, 0)
if self._topic[CONF_RGB_COMMAND_TOPIC] is not None: if self._topic[CONF_RGB_COMMAND_TOPIC] is not None:
self._rgb = [255, 255, 255] self._hs = (0, 0)
else:
self._rgb = None
@callback @callback
def color_temp_received(topic, payload, qos): def color_temp_received(topic, payload, qos):
@ -330,19 +328,18 @@ class MqttLight(MqttAvailability, Light):
@callback @callback
def xy_received(topic, payload, qos): def xy_received(topic, payload, qos):
"""Handle new MQTT messages for color.""" """Handle new MQTT messages for color."""
self._xy = [float(val) for val in xy_color = [float(val) for val in
templates[CONF_XY](payload).split(',')] templates[CONF_XY](payload).split(',')]
self._hs = color_util.color_xy_to_hs(*xy_color)
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
if self._topic[CONF_XY_STATE_TOPIC] is not None: if self._topic[CONF_XY_STATE_TOPIC] is not None:
yield from mqtt.async_subscribe( yield from mqtt.async_subscribe(
self.hass, self._topic[CONF_XY_STATE_TOPIC], xy_received, self.hass, self._topic[CONF_XY_STATE_TOPIC], xy_received,
self._qos) self._qos)
self._xy = [1, 1] self._hs = (0, 0)
if self._topic[CONF_XY_COMMAND_TOPIC] is not None: if self._topic[CONF_XY_COMMAND_TOPIC] is not None:
self._xy = [1, 1] self._hs = (0, 0)
else:
self._xy = None
@property @property
def brightness(self): def brightness(self):
@ -350,9 +347,9 @@ class MqttLight(MqttAvailability, Light):
return self._brightness return self._brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Return the RGB color value.""" """Return the hs color value."""
return self._rgb return self._hs
@property @property
def color_temp(self): def color_temp(self):
@ -364,11 +361,6 @@ class MqttLight(MqttAvailability, Light):
"""Return the white property.""" """Return the white property."""
return self._white_value return self._white_value
@property
def xy_color(self):
"""Return the RGB color value."""
return self._xy
@property @property
def should_poll(self): def should_poll(self):
"""No polling needed for a MQTT light.""" """No polling needed for a MQTT light."""
@ -426,24 +418,43 @@ class MqttLight(MqttAvailability, Light):
kwargs[ATTR_BRIGHTNESS] = self._brightness if \ kwargs[ATTR_BRIGHTNESS] = self._brightness if \
self._brightness else 255 self._brightness else 255
if ATTR_RGB_COLOR in kwargs and \ if ATTR_HS_COLOR in kwargs and \
self._topic[CONF_RGB_COMMAND_TOPIC] is not None: self._topic[CONF_RGB_COMMAND_TOPIC] is not None:
hs_color = kwargs[ATTR_HS_COLOR]
brightness = kwargs.get(
ATTR_BRIGHTNESS, self._brightness if self._brightness else 255)
rgb = color_util.color_hsv_to_RGB(
hs_color[0], hs_color[1], brightness / 255 * 100)
tpl = self._templates[CONF_RGB_COMMAND_TEMPLATE] tpl = self._templates[CONF_RGB_COMMAND_TEMPLATE]
if tpl: if tpl:
colors = ('red', 'green', 'blue') rgb_color_str = tpl.async_render({
variables = {key: val for key, val in 'red': rgb[0],
zip(colors, kwargs[ATTR_RGB_COLOR])} 'green': rgb[1],
rgb_color_str = tpl.async_render(variables) 'blue': rgb[2],
})
else: else:
rgb_color_str = '{},{},{}'.format(*kwargs[ATTR_RGB_COLOR]) rgb_color_str = '{},{},{}'.format(*rgb)
mqtt.async_publish( mqtt.async_publish(
self.hass, self._topic[CONF_RGB_COMMAND_TOPIC], self.hass, self._topic[CONF_RGB_COMMAND_TOPIC],
rgb_color_str, self._qos, self._retain) rgb_color_str, self._qos, self._retain)
if self._optimistic_rgb: if self._optimistic_rgb:
self._rgb = kwargs[ATTR_RGB_COLOR] self._hs = kwargs[ATTR_HS_COLOR]
should_update = True
if ATTR_HS_COLOR in kwargs and \
self._topic[CONF_XY_COMMAND_TOPIC] is not None:
xy_color = color_util.color_hs_to_xy(*kwargs[ATTR_HS_COLOR])
mqtt.async_publish(
self.hass, self._topic[CONF_XY_COMMAND_TOPIC],
'{},{}'.format(*xy_color), self._qos,
self._retain)
if self._optimistic_xy:
self._hs = kwargs[ATTR_HS_COLOR]
should_update = True should_update = True
if ATTR_BRIGHTNESS in kwargs and \ if ATTR_BRIGHTNESS in kwargs and \
@ -493,18 +504,6 @@ class MqttLight(MqttAvailability, Light):
self._white_value = kwargs[ATTR_WHITE_VALUE] self._white_value = kwargs[ATTR_WHITE_VALUE]
should_update = True should_update = True
if ATTR_XY_COLOR in kwargs and \
self._topic[CONF_XY_COMMAND_TOPIC] is not None:
mqtt.async_publish(
self.hass, self._topic[CONF_XY_COMMAND_TOPIC],
'{},{}'.format(*kwargs[ATTR_XY_COLOR]), self._qos,
self._retain)
if self._optimistic_xy:
self._xy = kwargs[ATTR_XY_COLOR]
should_update = True
if self._on_command_type == 'last': if self._on_command_type == 'last':
mqtt.async_publish(self.hass, self._topic[CONF_COMMAND_TOPIC], mqtt.async_publish(self.hass, self._topic[CONF_COMMAND_TOPIC],
self._payload['on'], self._qos, self._retain) self._payload['on'], self._qos, self._retain)

View File

@ -13,10 +13,10 @@ from homeassistant.core import callback
import homeassistant.components.mqtt as mqtt import homeassistant.components.mqtt as mqtt
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH,
ATTR_RGB_COLOR, ATTR_TRANSITION, ATTR_WHITE_VALUE, ATTR_XY_COLOR, ATTR_TRANSITION, ATTR_WHITE_VALUE, ATTR_HS_COLOR,
FLASH_LONG, FLASH_SHORT, Light, PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS, FLASH_LONG, FLASH_SHORT, Light, PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS,
SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_RGB_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_COLOR,
SUPPORT_TRANSITION, SUPPORT_WHITE_VALUE, SUPPORT_XY_COLOR) SUPPORT_TRANSITION, SUPPORT_WHITE_VALUE)
from homeassistant.components.light.mqtt import CONF_BRIGHTNESS_SCALE from homeassistant.components.light.mqtt import CONF_BRIGHTNESS_SCALE
from homeassistant.const import ( from homeassistant.const import (
CONF_BRIGHTNESS, CONF_COLOR_TEMP, CONF_EFFECT, CONF_BRIGHTNESS, CONF_COLOR_TEMP, CONF_EFFECT,
@ -26,6 +26,7 @@ from homeassistant.components.mqtt import (
CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS, CONF_RETAIN, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS, CONF_RETAIN,
MqttAvailability) MqttAvailability)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -143,31 +144,26 @@ class MqttJson(MqttAvailability, Light):
else: else:
self._effect = None self._effect = None
if rgb: if rgb or xy:
self._rgb = [0, 0, 0] self._hs = [0, 0]
else: else:
self._rgb = None self._hs = None
if white_value: if white_value:
self._white_value = 255 self._white_value = 255
else: else:
self._white_value = None self._white_value = None
if xy:
self._xy = [1, 1]
else:
self._xy = None
self._flash_times = flash_times self._flash_times = flash_times
self._brightness_scale = brightness_scale self._brightness_scale = brightness_scale
self._supported_features = (SUPPORT_TRANSITION | SUPPORT_FLASH) self._supported_features = (SUPPORT_TRANSITION | SUPPORT_FLASH)
self._supported_features |= (rgb and SUPPORT_RGB_COLOR) self._supported_features |= (rgb and SUPPORT_COLOR)
self._supported_features |= (brightness and SUPPORT_BRIGHTNESS) self._supported_features |= (brightness and SUPPORT_BRIGHTNESS)
self._supported_features |= (color_temp and SUPPORT_COLOR_TEMP) self._supported_features |= (color_temp and SUPPORT_COLOR_TEMP)
self._supported_features |= (effect and SUPPORT_EFFECT) self._supported_features |= (effect and SUPPORT_EFFECT)
self._supported_features |= (white_value and SUPPORT_WHITE_VALUE) self._supported_features |= (white_value and SUPPORT_WHITE_VALUE)
self._supported_features |= (xy and SUPPORT_XY_COLOR) self._supported_features |= (xy and SUPPORT_COLOR)
@asyncio.coroutine @asyncio.coroutine
def async_added_to_hass(self): def async_added_to_hass(self):
@ -184,17 +180,26 @@ class MqttJson(MqttAvailability, Light):
elif values['state'] == 'OFF': elif values['state'] == 'OFF':
self._state = False self._state = False
if self._rgb is not None: if self._hs is not None:
try: try:
red = int(values['color']['r']) red = int(values['color']['r'])
green = int(values['color']['g']) green = int(values['color']['g'])
blue = int(values['color']['b']) blue = int(values['color']['b'])
self._rgb = [red, green, blue] self._hs = color_util.color_RGB_to_hs(red, green, blue)
except KeyError: except KeyError:
pass pass
except ValueError: except ValueError:
_LOGGER.warning("Invalid RGB color value received") _LOGGER.warning("Invalid RGB color value received")
try:
x_color = float(values['color']['x'])
y_color = float(values['color']['y'])
self._hs = color_util.color_xy_to_hs(x_color, y_color)
except KeyError:
pass
except ValueError:
_LOGGER.warning("Invalid XY color value received")
if self._brightness is not None: if self._brightness is not None:
try: try:
@ -230,17 +235,6 @@ class MqttJson(MqttAvailability, Light):
except ValueError: except ValueError:
_LOGGER.warning("Invalid white value received") _LOGGER.warning("Invalid white value received")
if self._xy is not None:
try:
x_color = float(values['color']['x'])
y_color = float(values['color']['y'])
self._xy = [x_color, y_color]
except KeyError:
pass
except ValueError:
_LOGGER.warning("Invalid XY color value received")
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
if self._topic[CONF_STATE_TOPIC] is not None: if self._topic[CONF_STATE_TOPIC] is not None:
@ -269,20 +263,15 @@ class MqttJson(MqttAvailability, Light):
return self._effect_list return self._effect_list
@property @property
def rgb_color(self): def hs_color(self):
"""Return the RGB color value.""" """Return the hs color value."""
return self._rgb return self._hs
@property @property
def white_value(self): def white_value(self):
"""Return the white property.""" """Return the white property."""
return self._white_value return self._white_value
@property
def xy_color(self):
"""Return the XY color value."""
return self._xy
@property @property
def should_poll(self): def should_poll(self):
"""No polling needed for a MQTT light.""" """No polling needed for a MQTT light."""
@ -318,15 +307,23 @@ class MqttJson(MqttAvailability, Light):
message = {'state': 'ON'} message = {'state': 'ON'}
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
hs_color = kwargs[ATTR_HS_COLOR]
brightness = kwargs.get(
ATTR_BRIGHTNESS, self._brightness if self._brightness else 255)
rgb = color_util.color_hsv_to_RGB(
hs_color[0], hs_color[1], brightness / 255 * 100)
xy_color = color_util.color_hs_to_xy(*kwargs[ATTR_HS_COLOR])
message['color'] = { message['color'] = {
'r': kwargs[ATTR_RGB_COLOR][0], 'r': rgb[0],
'g': kwargs[ATTR_RGB_COLOR][1], 'g': rgb[1],
'b': kwargs[ATTR_RGB_COLOR][2] 'b': rgb[2],
'x': xy_color[0],
'y': xy_color[1],
} }
if self._optimistic: if self._optimistic:
self._rgb = kwargs[ATTR_RGB_COLOR] self._hs = kwargs[ATTR_HS_COLOR]
should_update = True should_update = True
if ATTR_FLASH in kwargs: if ATTR_FLASH in kwargs:
@ -370,16 +367,6 @@ class MqttJson(MqttAvailability, Light):
self._white_value = kwargs[ATTR_WHITE_VALUE] self._white_value = kwargs[ATTR_WHITE_VALUE]
should_update = True should_update = True
if ATTR_XY_COLOR in kwargs:
message['color'] = {
'x': kwargs[ATTR_XY_COLOR][0],
'y': kwargs[ATTR_XY_COLOR][1]
}
if self._optimistic:
self._xy = kwargs[ATTR_XY_COLOR]
should_update = True
mqtt.async_publish( mqtt.async_publish(
self.hass, self._topic[CONF_COMMAND_TOPIC], json.dumps(message), self.hass, self._topic[CONF_COMMAND_TOPIC], json.dumps(message),
self._qos, self._retain) self._qos, self._retain)

View File

@ -12,15 +12,16 @@ from homeassistant.core import callback
import homeassistant.components.mqtt as mqtt import homeassistant.components.mqtt as mqtt
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH,
ATTR_RGB_COLOR, ATTR_TRANSITION, ATTR_WHITE_VALUE, Light, PLATFORM_SCHEMA, ATTR_HS_COLOR, ATTR_TRANSITION, ATTR_WHITE_VALUE, Light, PLATFORM_SCHEMA,
SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH,
SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, SUPPORT_WHITE_VALUE) SUPPORT_COLOR, SUPPORT_TRANSITION, SUPPORT_WHITE_VALUE)
from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC, STATE_ON, STATE_OFF from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC, STATE_ON, STATE_OFF
from homeassistant.components.mqtt import ( from homeassistant.components.mqtt import (
CONF_AVAILABILITY_TOPIC, CONF_STATE_TOPIC, CONF_COMMAND_TOPIC, CONF_AVAILABILITY_TOPIC, CONF_STATE_TOPIC, CONF_COMMAND_TOPIC,
CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS, CONF_RETAIN, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS, CONF_RETAIN,
MqttAvailability) MqttAvailability)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -142,9 +143,9 @@ class MqttTemplate(MqttAvailability, Light):
if (self._templates[CONF_RED_TEMPLATE] is not None and if (self._templates[CONF_RED_TEMPLATE] is not None and
self._templates[CONF_GREEN_TEMPLATE] is not None and self._templates[CONF_GREEN_TEMPLATE] is not None and
self._templates[CONF_BLUE_TEMPLATE] is not None): self._templates[CONF_BLUE_TEMPLATE] is not None):
self._rgb = [0, 0, 0] self._hs = [0, 0]
else: else:
self._rgb = None self._hs = None
self._effect = None self._effect = None
for tpl in self._templates.values(): for tpl in self._templates.values():
@ -186,17 +187,18 @@ class MqttTemplate(MqttAvailability, Light):
except ValueError: except ValueError:
_LOGGER.warning("Invalid color temperature value received") _LOGGER.warning("Invalid color temperature value received")
if self._rgb is not None: if self._hs is not None:
try: try:
self._rgb[0] = int( red = int(
self._templates[CONF_RED_TEMPLATE]. self._templates[CONF_RED_TEMPLATE].
async_render_with_possible_json_value(payload)) async_render_with_possible_json_value(payload))
self._rgb[1] = int( green = int(
self._templates[CONF_GREEN_TEMPLATE]. self._templates[CONF_GREEN_TEMPLATE].
async_render_with_possible_json_value(payload)) async_render_with_possible_json_value(payload))
self._rgb[2] = int( blue = int(
self._templates[CONF_BLUE_TEMPLATE]. self._templates[CONF_BLUE_TEMPLATE].
async_render_with_possible_json_value(payload)) async_render_with_possible_json_value(payload))
self._hs = color_util.color_RGB_to_hs(red, green, blue)
except ValueError: except ValueError:
_LOGGER.warning("Invalid color value received") _LOGGER.warning("Invalid color value received")
@ -236,9 +238,9 @@ class MqttTemplate(MqttAvailability, Light):
return self._color_temp return self._color_temp
@property @property
def rgb_color(self): def hs_color(self):
"""Return the RGB color value [int, int, int].""" """Return the hs color value [int, int]."""
return self._rgb return self._hs
@property @property
def white_value(self): def white_value(self):
@ -300,13 +302,18 @@ class MqttTemplate(MqttAvailability, Light):
if self._optimistic: if self._optimistic:
self._color_temp = kwargs[ATTR_COLOR_TEMP] self._color_temp = kwargs[ATTR_COLOR_TEMP]
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
values['red'] = kwargs[ATTR_RGB_COLOR][0] hs_color = kwargs[ATTR_HS_COLOR]
values['green'] = kwargs[ATTR_RGB_COLOR][1] brightness = kwargs.get(
values['blue'] = kwargs[ATTR_RGB_COLOR][2] ATTR_BRIGHTNESS, self._brightness if self._brightness else 255)
rgb = color_util.color_hsv_to_RGB(
hs_color[0], hs_color[1], brightness / 255 * 100)
values['red'] = rgb[0]
values['green'] = rgb[1]
values['blue'] = rgb[2]
if self._optimistic: if self._optimistic:
self._rgb = kwargs[ATTR_RGB_COLOR] self._hs = kwargs[ATTR_HS_COLOR]
if ATTR_WHITE_VALUE in kwargs: if ATTR_WHITE_VALUE in kwargs:
values['white_value'] = int(kwargs[ATTR_WHITE_VALUE]) values['white_value'] = int(kwargs[ATTR_WHITE_VALUE])
@ -360,8 +367,8 @@ class MqttTemplate(MqttAvailability, Light):
features = (SUPPORT_FLASH | SUPPORT_TRANSITION) features = (SUPPORT_FLASH | SUPPORT_TRANSITION)
if self._brightness is not None: if self._brightness is not None:
features = features | SUPPORT_BRIGHTNESS features = features | SUPPORT_BRIGHTNESS
if self._rgb is not None: if self._hs is not None:
features = features | SUPPORT_RGB_COLOR features = features | SUPPORT_COLOR
if self._effect_list is not None: if self._effect_list is not None:
features = features | SUPPORT_EFFECT features = features | SUPPORT_EFFECT
if self._color_temp is not None: if self._color_temp is not None:

View File

@ -6,12 +6,13 @@ https://home-assistant.io/components/light.mysensors/
""" """
from homeassistant.components import mysensors from homeassistant.components import mysensors
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_WHITE_VALUE, DOMAIN, ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_WHITE_VALUE, DOMAIN,
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, SUPPORT_WHITE_VALUE, Light) SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_WHITE_VALUE, Light)
from homeassistant.const import STATE_OFF, STATE_ON from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.util.color import rgb_hex_to_rgb_list from homeassistant.util.color import rgb_hex_to_rgb_list
import homeassistant.util.color as color_util
SUPPORT_MYSENSORS = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR | SUPPORT_MYSENSORS = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR |
SUPPORT_WHITE_VALUE) SUPPORT_WHITE_VALUE)
@ -35,7 +36,7 @@ class MySensorsLight(mysensors.MySensorsEntity, Light):
super().__init__(*args) super().__init__(*args)
self._state = None self._state = None
self._brightness = None self._brightness = None
self._rgb = None self._hs = None
self._white = None self._white = None
@property @property
@ -44,9 +45,9 @@ class MySensorsLight(mysensors.MySensorsEntity, Light):
return self._brightness return self._brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Return the RGB color value [int, int, int].""" """Return the hs color value [int, int]."""
return self._rgb return self._hs
@property @property
def white_value(self): def white_value(self):
@ -103,10 +104,10 @@ class MySensorsLight(mysensors.MySensorsEntity, Light):
def _turn_on_rgb_and_w(self, hex_template, **kwargs): def _turn_on_rgb_and_w(self, hex_template, **kwargs):
"""Turn on RGB or RGBW child device.""" """Turn on RGB or RGBW child device."""
rgb = self._rgb rgb = color_util.color_hs_to_RGB(*self._hs)
white = self._white white = self._white
hex_color = self._values.get(self.value_type) hex_color = self._values.get(self.value_type)
new_rgb = kwargs.get(ATTR_RGB_COLOR) new_rgb = color_util.color_hs_to_RGB(*kwargs.get(ATTR_HS_COLOR))
new_white = kwargs.get(ATTR_WHITE_VALUE) new_white = kwargs.get(ATTR_WHITE_VALUE)
if new_rgb is None and new_white is None: if new_rgb is None and new_white is None:
@ -126,7 +127,7 @@ class MySensorsLight(mysensors.MySensorsEntity, Light):
if self.gateway.optimistic: if self.gateway.optimistic:
# optimistically assume that light has changed state # optimistically assume that light has changed state
self._rgb = rgb self._hs = color_util.color_RGB_to_hs(*rgb)
self._white = white self._white = white
self._values[self.value_type] = hex_color self._values[self.value_type] = hex_color
@ -160,7 +161,7 @@ class MySensorsLight(mysensors.MySensorsEntity, Light):
color_list = rgb_hex_to_rgb_list(value) color_list = rgb_hex_to_rgb_list(value)
if len(color_list) > 3: if len(color_list) > 3:
self._white = color_list.pop() self._white = color_list.pop()
self._rgb = color_list self._hs = color_util.color_RGB_to_hs(*color_list)
class MySensorsLightDimmer(MySensorsLight): class MySensorsLightDimmer(MySensorsLight):

View File

@ -11,10 +11,9 @@ import voluptuous as vol
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.components.light import ( from homeassistant.components.light import (
Light, PLATFORM_SCHEMA, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, Light, PLATFORM_SCHEMA, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS,
SUPPORT_EFFECT, ATTR_EFFECT, SUPPORT_FLASH, SUPPORT_RGB_COLOR, SUPPORT_EFFECT, ATTR_EFFECT, SUPPORT_FLASH, SUPPORT_COLOR,
ATTR_RGB_COLOR) ATTR_HS_COLOR)
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_NAME, STATE_UNKNOWN from homeassistant.const import CONF_HOST, CONF_MAC, CONF_NAME, STATE_UNKNOWN
from homeassistant.util.color import color_RGB_to_hsv, color_hsv_to_RGB
REQUIREMENTS = ['python-mystrom==0.3.8'] REQUIREMENTS = ['python-mystrom==0.3.8']
@ -24,7 +23,7 @@ DEFAULT_NAME = 'myStrom bulb'
SUPPORT_MYSTROM = ( SUPPORT_MYSTROM = (
SUPPORT_BRIGHTNESS | SUPPORT_EFFECT | SUPPORT_FLASH | SUPPORT_BRIGHTNESS | SUPPORT_EFFECT | SUPPORT_FLASH |
SUPPORT_RGB_COLOR SUPPORT_COLOR
) )
EFFECT_RAINBOW = 'rainbow' EFFECT_RAINBOW = 'rainbow'
@ -91,9 +90,9 @@ class MyStromLight(Light):
return self._brightness return self._brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Return the color of the light.""" """Return the color of the light."""
return color_hsv_to_RGB(self._color_h, self._color_s, self._brightness) return self._color_h, self._color_s
@property @property
def available(self) -> bool: def available(self) -> bool:
@ -117,12 +116,8 @@ class MyStromLight(Light):
brightness = kwargs.get(ATTR_BRIGHTNESS, 255) brightness = kwargs.get(ATTR_BRIGHTNESS, 255)
effect = kwargs.get(ATTR_EFFECT) effect = kwargs.get(ATTR_EFFECT)
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
# New color, compute from RGB color_h, color_s = kwargs[ATTR_HS_COLOR]
color_h, color_s, brightness = color_RGB_to_hsv(
*kwargs[ATTR_RGB_COLOR]
)
brightness = brightness / 100 * 255
elif ATTR_BRIGHTNESS in kwargs: elif ATTR_BRIGHTNESS in kwargs:
# Brightness update, keep color # Brightness update, keep color
color_h, color_s = self._color_h, self._color_s color_h, color_s = self._color_h, self._color_s

View File

@ -13,15 +13,15 @@ import voluptuous as vol
from homeassistant import util from homeassistant import util
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_RGB_COLOR, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_HS_COLOR,
ATTR_TRANSITION, ATTR_XY_COLOR, EFFECT_RANDOM, PLATFORM_SCHEMA, ATTR_TRANSITION, EFFECT_RANDOM, PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS,
SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_RGB_COLOR, SUPPORT_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_TRANSITION,
SUPPORT_TRANSITION, SUPPORT_XY_COLOR, Light) Light)
from homeassistant.const import CONF_HOST from homeassistant.const import CONF_HOST
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.util.color import ( from homeassistant.util.color import (
color_temperature_kelvin_to_mired, color_temperature_mired_to_kelvin, color_temperature_kelvin_to_mired, color_temperature_mired_to_kelvin)
color_xy_brightness_to_RGB) import homeassistant.util.color as color_util
REQUIREMENTS = ['lightify==1.0.6.1'] REQUIREMENTS = ['lightify==1.0.6.1']
@ -35,8 +35,8 @@ MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(milliseconds=100)
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
SUPPORT_OSRAMLIGHTIFY = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_OSRAMLIGHTIFY = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP |
SUPPORT_EFFECT | SUPPORT_RGB_COLOR | SUPPORT_EFFECT | SUPPORT_COLOR |
SUPPORT_TRANSITION | SUPPORT_XY_COLOR) SUPPORT_TRANSITION)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string, vol.Required(CONF_HOST): cv.string,
@ -113,7 +113,7 @@ class Luminary(Light):
self.update_lights = update_lights self.update_lights = update_lights
self._luminary = luminary self._luminary = luminary
self._brightness = None self._brightness = None
self._rgb = [None] self._hs = None
self._name = None self._name = None
self._temperature = None self._temperature = None
self._state = False self._state = False
@ -125,9 +125,9 @@ class Luminary(Light):
return self._name return self._name
@property @property
def rgb_color(self): def hs_color(self):
"""Last RGB color value set.""" """Last hs color value set."""
return self._rgb return self._hs
@property @property
def color_temp(self): def color_temp(self):
@ -158,42 +158,24 @@ class Luminary(Light):
"""Turn the device on.""" """Turn the device on."""
if ATTR_TRANSITION in kwargs: if ATTR_TRANSITION in kwargs:
transition = int(kwargs[ATTR_TRANSITION] * 10) transition = int(kwargs[ATTR_TRANSITION] * 10)
_LOGGER.debug("turn_on requested transition time for light: "
"%s is: %s", self._name, transition)
else: else:
transition = 0 transition = 0
_LOGGER.debug("turn_on requested transition time for light: "
"%s is: %s", self._name, transition)
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
self._brightness = kwargs[ATTR_BRIGHTNESS] self._brightness = kwargs[ATTR_BRIGHTNESS]
_LOGGER.debug("turn_on requested brightness for light: %s is: %s ",
self._name, self._brightness)
self._luminary.set_luminance( self._luminary.set_luminance(
int(self._brightness / 2.55), transition) int(self._brightness / 2.55), transition)
else: else:
self._luminary.set_onoff(1) self._luminary.set_onoff(1)
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
red, green, blue = kwargs[ATTR_RGB_COLOR] red, green, blue = \
_LOGGER.debug("turn_on requested ATTR_RGB_COLOR for light:" color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR])
" %s is: %s %s %s ",
self._name, red, green, blue)
self._luminary.set_rgb(red, green, blue, transition)
if ATTR_XY_COLOR in kwargs:
x_mired, y_mired = kwargs[ATTR_XY_COLOR]
_LOGGER.debug("turn_on requested ATTR_XY_COLOR for light:"
" %s is: %s,%s", self._name, x_mired, y_mired)
red, green, blue = color_xy_brightness_to_RGB(
x_mired, y_mired, self._brightness)
self._luminary.set_rgb(red, green, blue, transition) self._luminary.set_rgb(red, green, blue, transition)
if ATTR_COLOR_TEMP in kwargs: if ATTR_COLOR_TEMP in kwargs:
color_t = kwargs[ATTR_COLOR_TEMP] color_t = kwargs[ATTR_COLOR_TEMP]
kelvin = int(color_temperature_mired_to_kelvin(color_t)) kelvin = int(color_temperature_mired_to_kelvin(color_t))
_LOGGER.debug("turn_on requested set_temperature for light: "
"%s: %s", self._name, kelvin)
self._luminary.set_temperature(kelvin, transition) self._luminary.set_temperature(kelvin, transition)
if ATTR_EFFECT in kwargs: if ATTR_EFFECT in kwargs:
@ -202,23 +184,16 @@ class Luminary(Light):
self._luminary.set_rgb( self._luminary.set_rgb(
random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255),
random.randrange(0, 255), transition) random.randrange(0, 255), transition)
_LOGGER.debug("turn_on requested random effect for light: "
"%s with transition %s", self._name, transition)
self.schedule_update_ha_state() self.schedule_update_ha_state()
def turn_off(self, **kwargs): def turn_off(self, **kwargs):
"""Turn the device off.""" """Turn the device off."""
_LOGGER.debug("Attempting to turn off light: %s", self._name)
if ATTR_TRANSITION in kwargs: if ATTR_TRANSITION in kwargs:
transition = int(kwargs[ATTR_TRANSITION] * 10) transition = int(kwargs[ATTR_TRANSITION] * 10)
_LOGGER.debug("turn_off requested transition time for light:"
" %s is: %s ", self._name, transition)
self._luminary.set_luminance(0, transition) self._luminary.set_luminance(0, transition)
else: else:
transition = 0 transition = 0
_LOGGER.debug("turn_off requested transition time for light:"
" %s is: %s ", self._name, transition)
self._luminary.set_onoff(0) self._luminary.set_onoff(0)
self.schedule_update_ha_state() self.schedule_update_ha_state()
@ -240,7 +215,8 @@ class OsramLightifyLight(Luminary):
"""Update status of a light.""" """Update status of a light."""
super().update() super().update()
self._state = self._luminary.on() self._state = self._luminary.on()
self._rgb = self._luminary.rgb() rgb = self._luminary.rgb()
self._hs = color_util.color_RGB_to_hs(*rgb)
o_temp = self._luminary.temp() o_temp = self._luminary.temp()
if o_temp == 0: if o_temp == 0:
self._temperature = None self._temperature = None
@ -270,7 +246,8 @@ class OsramLightifyGroup(Luminary):
self._light_ids = self._luminary.lights() self._light_ids = self._luminary.lights()
light = self._bridge.lights()[self._light_ids[0]] light = self._bridge.lights()[self._light_ids[0]]
self._brightness = int(light.lum() * 2.55) self._brightness = int(light.lum() * 2.55)
self._rgb = light.rgb() rgb = light.rgb()
self._hs = color_util.color_RGB_to_hs(*rgb)
o_temp = light.temp() o_temp = light.temp()
if o_temp == 0: if o_temp == 0:
self._temperature = None self._temperature = None

View File

@ -11,15 +11,16 @@ import voluptuous as vol
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, ATTR_RGB_COLOR, SUPPORT_RGB_COLOR, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, ATTR_HS_COLOR, SUPPORT_COLOR,
Light, PLATFORM_SCHEMA) Light, PLATFORM_SCHEMA)
from homeassistant.const import CONF_NAME from homeassistant.const import CONF_NAME
import homeassistant.util.color as color_util
REQUIREMENTS = ['piglow==1.2.4'] REQUIREMENTS = ['piglow==1.2.4']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SUPPORT_PIGLOW = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR) SUPPORT_PIGLOW = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR)
DEFAULT_NAME = 'Piglow' DEFAULT_NAME = 'Piglow'
@ -50,7 +51,7 @@ class PiglowLight(Light):
self._name = name self._name = name
self._is_on = False self._is_on = False
self._brightness = 255 self._brightness = 255
self._rgb_color = [255, 255, 255] self._hs_color = [0, 0]
@property @property
def name(self): def name(self):
@ -63,9 +64,9 @@ class PiglowLight(Light):
return self._brightness return self._brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Read back the color of the light.""" """Read back the color of the light."""
return self._rgb_color return self._hs_color
@property @property
def supported_features(self): def supported_features(self):
@ -93,15 +94,15 @@ class PiglowLight(Light):
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
self._brightness = kwargs[ATTR_BRIGHTNESS] self._brightness = kwargs[ATTR_BRIGHTNESS]
percent_bright = (self._brightness / 255)
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
self._rgb_color = kwargs[ATTR_RGB_COLOR] self._hs_color = kwargs[ATTR_HS_COLOR]
self._piglow.red(int(self._rgb_color[0] * percent_bright))
self._piglow.green(int(self._rgb_color[1] * percent_bright)) rgb = color_util.color_hsv_to_RGB(
self._piglow.blue(int(self._rgb_color[2] * percent_bright)) self._hs_color[0], self._hs_color[1], self._brightness / 255 * 100)
else: self._piglow.red(rgb[0])
self._piglow.all(self._brightness) self._piglow.green(rgb[1])
self._piglow.blue(rgb[2])
self._piglow.show() self._piglow.show()
self._is_on = True self._is_on = True
self.schedule_update_ha_state() self.schedule_update_ha_state()

View File

@ -10,9 +10,10 @@ import voluptuous as vol
from homeassistant.const import CONF_NAME, CONF_TYPE from homeassistant.const import CONF_NAME, CONF_TYPE
from homeassistant.components.light import ( from homeassistant.components.light import (
Light, ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_TRANSITION, Light, ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_TRANSITION,
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, PLATFORM_SCHEMA) SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_TRANSITION, PLATFORM_SCHEMA)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util
REQUIREMENTS = ['pwmled==1.2.1'] REQUIREMENTS = ['pwmled==1.2.1']
@ -33,10 +34,10 @@ CONF_LED_TYPE_RGB = 'rgb'
CONF_LED_TYPE_RGBW = 'rgbw' CONF_LED_TYPE_RGBW = 'rgbw'
CONF_LED_TYPES = [CONF_LED_TYPE_SIMPLE, CONF_LED_TYPE_RGB, CONF_LED_TYPE_RGBW] CONF_LED_TYPES = [CONF_LED_TYPE_SIMPLE, CONF_LED_TYPE_RGB, CONF_LED_TYPE_RGBW]
DEFAULT_COLOR = [255, 255, 255] DEFAULT_COLOR = [0, 0]
SUPPORT_SIMPLE_LED = (SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION) SUPPORT_SIMPLE_LED = (SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION)
SUPPORT_RGB_LED = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR | SUPPORT_TRANSITION) SUPPORT_RGB_LED = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR | SUPPORT_TRANSITION)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_LEDS): vol.All(cv.ensure_list, [ vol.Required(CONF_LEDS): vol.All(cv.ensure_list, [
@ -169,7 +170,7 @@ class PwmRgbLed(PwmSimpleLed):
self._color = DEFAULT_COLOR self._color = DEFAULT_COLOR
@property @property
def rgb_color(self): def hs_color(self):
"""Return the color property.""" """Return the color property."""
return self._color return self._color
@ -180,8 +181,8 @@ class PwmRgbLed(PwmSimpleLed):
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn on a LED.""" """Turn on a LED."""
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
self._color = kwargs[ATTR_RGB_COLOR] self._color = kwargs[ATTR_HS_COLOR]
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
self._brightness = kwargs[ATTR_BRIGHTNESS] self._brightness = kwargs[ATTR_BRIGHTNESS]
@ -209,4 +210,5 @@ def _from_hass_brightness(brightness):
def _from_hass_color(color): def _from_hass_color(color):
"""Convert Home Assistant RGB list to Color tuple.""" """Convert Home Assistant RGB list to Color tuple."""
from pwmled import Color from pwmled import Color
return Color(*tuple(color)) rgb = color_util.color_hs_to_RGB(*color)
return Color(*tuple(rgb))

View File

@ -10,15 +10,16 @@ import voluptuous as vol
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, ATTR_RGB_COLOR, SUPPORT_RGB_COLOR, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, ATTR_HS_COLOR, SUPPORT_COLOR,
Light, PLATFORM_SCHEMA) Light, PLATFORM_SCHEMA)
from homeassistant.const import CONF_NAME from homeassistant.const import CONF_NAME
import homeassistant.util.color as color_util
REQUIREMENTS = ['sense-hat==2.2.0'] REQUIREMENTS = ['sense-hat==2.2.0']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SUPPORT_SENSEHAT = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR) SUPPORT_SENSEHAT = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR)
DEFAULT_NAME = 'sensehat' DEFAULT_NAME = 'sensehat'
@ -49,7 +50,7 @@ class SenseHatLight(Light):
self._name = name self._name = name
self._is_on = False self._is_on = False
self._brightness = 255 self._brightness = 255
self._rgb_color = [255, 255, 255] self._hs_color = [0, 0]
@property @property
def name(self): def name(self):
@ -62,12 +63,9 @@ class SenseHatLight(Light):
return self._brightness return self._brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Read back the color of the light. """Read back the color of the light."""
return self._hs_color
Returns [r, g, b] list with values in range of 0-255.
"""
return self._rgb_color
@property @property
def supported_features(self): def supported_features(self):
@ -93,14 +91,13 @@ class SenseHatLight(Light):
"""Instruct the light to turn on and set correct brightness & color.""" """Instruct the light to turn on and set correct brightness & color."""
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
self._brightness = kwargs[ATTR_BRIGHTNESS] self._brightness = kwargs[ATTR_BRIGHTNESS]
percent_bright = (self._brightness / 255)
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
self._rgb_color = kwargs[ATTR_RGB_COLOR] self._hs_color = kwargs[ATTR_HS_COLOR]
self._sensehat.clear(int(self._rgb_color[0] * percent_bright), rgb = color_util.color_hsv_to_RGB(
int(self._rgb_color[1] * percent_bright), self._hs_color[0], self._hs_color[1], self._brightness / 255 * 100)
int(self._rgb_color[2] * percent_bright)) self._sensehat.clear(*rgb)
self._is_on = True self._is_on = True
self.schedule_update_ha_state() self.schedule_update_ha_state()

View File

@ -8,10 +8,11 @@ import logging
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_BRIGHTNESS, ATTR_HS_COLOR,
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, Light) SUPPORT_BRIGHTNESS, SUPPORT_COLOR, Light)
from homeassistant.components.skybell import ( from homeassistant.components.skybell import (
DOMAIN as SKYBELL_DOMAIN, SkybellDevice) DOMAIN as SKYBELL_DOMAIN, SkybellDevice)
import homeassistant.util.color as color_util
DEPENDENCIES = ['skybell'] DEPENDENCIES = ['skybell']
@ -54,8 +55,9 @@ class SkybellLight(SkybellDevice, Light):
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn on the light.""" """Turn on the light."""
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
self._device.led_rgb = kwargs[ATTR_RGB_COLOR] rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR])
self._device.led_rgb = rgb
elif ATTR_BRIGHTNESS in kwargs: elif ATTR_BRIGHTNESS in kwargs:
self._device.led_intensity = _to_skybell_level( self._device.led_intensity = _to_skybell_level(
kwargs[ATTR_BRIGHTNESS]) kwargs[ATTR_BRIGHTNESS])
@ -77,11 +79,11 @@ class SkybellLight(SkybellDevice, Light):
return _to_hass_level(self._device.led_intensity) return _to_hass_level(self._device.led_intensity)
@property @property
def rgb_color(self): def hs_color(self):
"""Return the color of the light.""" """Return the color of the light."""
return self._device.led_rgb return color_util.color_RGB_to_hs(*self._device.led_rgb)
@property @property
def supported_features(self): def supported_features(self):
"""Flag supported features.""" """Flag supported features."""
return SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR return SUPPORT_BRIGHTNESS | SUPPORT_COLOR

View File

@ -10,15 +10,16 @@ import voluptuous as vol
from homeassistant.const import CONF_DEVICES, CONF_NAME, CONF_PASSWORD from homeassistant.const import CONF_DEVICES, CONF_NAME, CONF_PASSWORD
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, ATTR_BRIGHTNESS, ATTR_HS_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR,
Light, PLATFORM_SCHEMA) Light, PLATFORM_SCHEMA)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util
REQUIREMENTS = ['tikteck==0.4'] REQUIREMENTS = ['tikteck==0.4']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SUPPORT_TIKTECK_LED = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR) SUPPORT_TIKTECK_LED = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR)
DEVICE_SCHEMA = vol.Schema({ DEVICE_SCHEMA = vol.Schema({
vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_NAME): cv.string,
@ -57,7 +58,7 @@ class TikteckLight(Light):
self._address = device['address'] self._address = device['address']
self._password = device['password'] self._password = device['password']
self._brightness = 255 self._brightness = 255
self._rgb = [255, 255, 255] self._hs = [0, 0]
self._state = False self._state = False
self.is_valid = True self.is_valid = True
self._bulb = tikteck.tikteck( self._bulb = tikteck.tikteck(
@ -88,9 +89,9 @@ class TikteckLight(Light):
return self._brightness return self._brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Return the color property.""" """Return the color property."""
return self._rgb return self._hs
@property @property
def supported_features(self): def supported_features(self):
@ -115,16 +116,17 @@ class TikteckLight(Light):
"""Turn the specified light on.""" """Turn the specified light on."""
self._state = True self._state = True
rgb = kwargs.get(ATTR_RGB_COLOR) hs_color = kwargs.get(ATTR_HS_COLOR)
brightness = kwargs.get(ATTR_BRIGHTNESS) brightness = kwargs.get(ATTR_BRIGHTNESS)
if rgb is not None: if hs_color is not None:
self._rgb = rgb self._hs = hs_color
if brightness is not None: if brightness is not None:
self._brightness = brightness self._brightness = brightness
self.set_state(self._rgb[0], self._rgb[1], self._rgb[2], rgb = color_util.color_hs_to_RGB(*self._hs)
self.brightness)
self.set_state(rgb[0], rgb[1], rgb[2], self.brightness)
self.schedule_update_ha_state() self.schedule_update_ha_state()
def turn_off(self, **kwargs): def turn_off(self, **kwargs):

View File

@ -5,23 +5,20 @@ For more details about this component, please refer to the documentation at
https://home-assistant.io/components/light.tplink/ https://home-assistant.io/components/light.tplink/
""" """
import logging import logging
import colorsys
import time import time
import voluptuous as vol import voluptuous as vol
from homeassistant.const import (CONF_HOST, CONF_NAME) from homeassistant.const import (CONF_HOST, CONF_NAME)
from homeassistant.components.light import ( from homeassistant.components.light import (
Light, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_KELVIN, ATTR_RGB_COLOR, Light, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_KELVIN, ATTR_HS_COLOR,
SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, PLATFORM_SCHEMA) SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR, PLATFORM_SCHEMA)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.util.color import \ from homeassistant.util.color import \
color_temperature_mired_to_kelvin as mired_to_kelvin color_temperature_mired_to_kelvin as mired_to_kelvin
from homeassistant.util.color import ( from homeassistant.util.color import (
color_temperature_kelvin_to_mired as kelvin_to_mired) color_temperature_kelvin_to_mired as kelvin_to_mired)
from typing import Tuple
REQUIREMENTS = ['pyHS100==0.3.0'] REQUIREMENTS = ['pyHS100==0.3.0']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -56,22 +53,6 @@ def brightness_from_percentage(percent):
return (percent*255.0)/100.0 return (percent*255.0)/100.0
# Travis-CI runs too old astroid https://github.com/PyCQA/pylint/issues/1212
# pylint: disable=invalid-sequence-index
def rgb_to_hsv(rgb: Tuple[float, float, float]) -> Tuple[int, int, int]:
"""Convert RGB tuple (values 0-255) to HSV (degrees, %, %)."""
hue, sat, value = colorsys.rgb_to_hsv(rgb[0]/255, rgb[1]/255, rgb[2]/255)
return int(hue * 360), int(sat * 100), int(value * 100)
# Travis-CI runs too old astroid https://github.com/PyCQA/pylint/issues/1212
# pylint: disable=invalid-sequence-index
def hsv_to_rgb(hsv: Tuple[float, float, float]) -> Tuple[int, int, int]:
"""Convert HSV tuple (degrees, %, %) to RGB (values 0-255)."""
red, green, blue = colorsys.hsv_to_rgb(hsv[0]/360, hsv[1]/100, hsv[2]/100)
return int(red * 255), int(green * 255), int(blue * 255)
class TPLinkSmartBulb(Light): class TPLinkSmartBulb(Light):
"""Representation of a TPLink Smart Bulb.""" """Representation of a TPLink Smart Bulb."""
@ -83,7 +64,7 @@ class TPLinkSmartBulb(Light):
self._available = True self._available = True
self._color_temp = None self._color_temp = None
self._brightness = None self._brightness = None
self._rgb = None self._hs = None
self._supported_features = 0 self._supported_features = 0
self._emeter_params = {} self._emeter_params = {}
@ -114,9 +95,10 @@ class TPLinkSmartBulb(Light):
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness or 255) brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness or 255)
self.smartbulb.brightness = brightness_to_percentage(brightness) self.smartbulb.brightness = brightness_to_percentage(brightness)
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
rgb = kwargs.get(ATTR_RGB_COLOR) hue, sat = kwargs.get(ATTR_HS_COLOR)
self.smartbulb.hsv = rgb_to_hsv(rgb) hsv = (hue, sat, 100)
self.smartbulb.hsv = hsv
def turn_off(self, **kwargs): def turn_off(self, **kwargs):
"""Turn the light off.""" """Turn the light off."""
@ -133,9 +115,9 @@ class TPLinkSmartBulb(Light):
return self._brightness return self._brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Return the color in RGB.""" """Return the color."""
return self._rgb return self._hs
@property @property
def is_on(self): def is_on(self):
@ -168,8 +150,9 @@ class TPLinkSmartBulb(Light):
self._color_temp = kelvin_to_mired( self._color_temp = kelvin_to_mired(
self.smartbulb.color_temp) self.smartbulb.color_temp)
if self._supported_features & SUPPORT_RGB_COLOR: if self._supported_features & SUPPORT_COLOR:
self._rgb = hsv_to_rgb(self.smartbulb.hsv) hue, sat, _ = self.smartbulb.hsv
self._hs = (hue, sat)
if self.smartbulb.has_emeter: if self.smartbulb.has_emeter:
self._emeter_params[ATTR_CURRENT_POWER_W] = '{:.1f}'.format( self._emeter_params[ATTR_CURRENT_POWER_W] = '{:.1f}'.format(
@ -203,4 +186,4 @@ class TPLinkSmartBulb(Light):
if self.smartbulb.is_variable_color_temp: if self.smartbulb.is_variable_color_temp:
self._supported_features += SUPPORT_COLOR_TEMP self._supported_features += SUPPORT_COLOR_TEMP
if self.smartbulb.is_color: if self.smartbulb.is_color:
self._supported_features += SUPPORT_RGB_COLOR self._supported_features += SUPPORT_COLOR

View File

@ -10,9 +10,9 @@ import logging
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.const import ATTR_BATTERY_LEVEL from homeassistant.const import ATTR_BATTERY_LEVEL
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_TRANSITION, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR, ATTR_TRANSITION,
SUPPORT_BRIGHTNESS, SUPPORT_TRANSITION, SUPPORT_COLOR_TEMP, SUPPORT_BRIGHTNESS, SUPPORT_TRANSITION, SUPPORT_COLOR_TEMP,
SUPPORT_RGB_COLOR, Light) SUPPORT_COLOR, Light)
from homeassistant.components.light import \ from homeassistant.components.light import \
PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA
from homeassistant.components.tradfri import KEY_GATEWAY, KEY_TRADFRI_GROUPS, \ from homeassistant.components.tradfri import KEY_GATEWAY, KEY_TRADFRI_GROUPS, \
@ -157,7 +157,7 @@ class TradfriLight(Light):
self._light_control = None self._light_control = None
self._light_data = None self._light_data = None
self._name = None self._name = None
self._rgb_color = None self._hs_color = None
self._features = SUPPORTED_FEATURES self._features = SUPPORTED_FEATURES
self._temp_supported = False self._temp_supported = False
self._available = True self._available = True
@ -237,9 +237,9 @@ class TradfriLight(Light):
) )
@property @property
def rgb_color(self): def hs_color(self):
"""RGB color of the light.""" """HS color of the light."""
return self._rgb_color return self._hs_color
@asyncio.coroutine @asyncio.coroutine
def async_turn_off(self, **kwargs): def async_turn_off(self, **kwargs):
@ -252,12 +252,12 @@ class TradfriLight(Light):
Instruct the light to turn on. Instruct the light to turn on.
After adding "self._light_data.hexcolor is not None" After adding "self._light_data.hexcolor is not None"
for ATTR_RGB_COLOR, this also supports Philips Hue bulbs. for ATTR_HS_COLOR, this also supports Philips Hue bulbs.
""" """
if ATTR_RGB_COLOR in kwargs and self._light_data.hex_color is not None: if ATTR_HS_COLOR in kwargs and self._light_data.hex_color is not None:
rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR])
yield from self._api( yield from self._api(
self._light.light_control.set_rgb_color( self._light.light_control.set_rgb_color(*rgb))
*kwargs[ATTR_RGB_COLOR]))
elif ATTR_COLOR_TEMP in kwargs and \ elif ATTR_COLOR_TEMP in kwargs and \
self._light_data.hex_color is not None and \ self._light_data.hex_color is not None and \
@ -309,17 +309,17 @@ class TradfriLight(Light):
self._light_control = light.light_control self._light_control = light.light_control
self._light_data = light.light_control.lights[0] self._light_data = light.light_control.lights[0]
self._name = light.name self._name = light.name
self._rgb_color = None self._hs_color = None
self._features = SUPPORTED_FEATURES self._features = SUPPORTED_FEATURES
if self._light.device_info.manufacturer == IKEA: if self._light.device_info.manufacturer == IKEA:
if self._light_control.can_set_kelvin: if self._light_control.can_set_kelvin:
self._features |= SUPPORT_COLOR_TEMP self._features |= SUPPORT_COLOR_TEMP
if self._light_control.can_set_color: if self._light_control.can_set_color:
self._features |= SUPPORT_RGB_COLOR self._features |= SUPPORT_COLOR
else: else:
if self._light_data.hex_color is not None: if self._light_data.hex_color is not None:
self._features |= SUPPORT_RGB_COLOR self._features |= SUPPORT_COLOR
self._temp_supported = self._light.device_info.manufacturer \ self._temp_supported = self._light.device_info.manufacturer \
in ALLOWED_TEMPERATURES in ALLOWED_TEMPERATURES
@ -328,7 +328,8 @@ class TradfriLight(Light):
def _observe_update(self, tradfri_device): def _observe_update(self, tradfri_device):
"""Receive new state data for this light.""" """Receive new state data for this light."""
self._refresh(tradfri_device) self._refresh(tradfri_device)
self._rgb_color = color_util.rgb_hex_to_rgb_list( rgb = color_util.rgb_hex_to_rgb_list(
self._light_data.hex_color_inferred self._light_data.hex_color_inferred
) )
self._hs_color = color_util.color_RGB_to_hs(*rgb)
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()

View File

@ -7,10 +7,11 @@ https://home-assistant.io/components/light.vera/
import logging import logging
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ENTITY_ID_FORMAT, ATTR_BRIGHTNESS, ATTR_HS_COLOR, ENTITY_ID_FORMAT,
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, Light) SUPPORT_BRIGHTNESS, SUPPORT_COLOR, Light)
from homeassistant.components.vera import ( from homeassistant.components.vera import (
VERA_CONTROLLER, VERA_DEVICES, VeraDevice) VERA_CONTROLLER, VERA_DEVICES, VeraDevice)
import homeassistant.util.color as color_util
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -42,7 +43,7 @@ class VeraLight(VeraDevice, Light):
return self._brightness return self._brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Return the color of the light.""" """Return the color of the light."""
return self._color return self._color
@ -50,13 +51,14 @@ class VeraLight(VeraDevice, Light):
def supported_features(self): def supported_features(self):
"""Flag supported features.""" """Flag supported features."""
if self._color: if self._color:
return SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR return SUPPORT_BRIGHTNESS | SUPPORT_COLOR
return SUPPORT_BRIGHTNESS return SUPPORT_BRIGHTNESS
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn the light on.""" """Turn the light on."""
if ATTR_RGB_COLOR in kwargs and self._color: if ATTR_HS_COLOR in kwargs and self._color:
self.vera_device.set_color(kwargs[ATTR_RGB_COLOR]) rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR])
self.vera_device.set_color(rgb)
elif ATTR_BRIGHTNESS in kwargs and self.vera_device.is_dimmable: elif ATTR_BRIGHTNESS in kwargs and self.vera_device.is_dimmable:
self.vera_device.set_brightness(kwargs[ATTR_BRIGHTNESS]) self.vera_device.set_brightness(kwargs[ATTR_BRIGHTNESS])
else: else:
@ -83,4 +85,5 @@ class VeraLight(VeraDevice, Light):
# If it is dimmable, both functions exist. In case color # If it is dimmable, both functions exist. In case color
# is not supported, it will return None # is not supported, it will return None
self._brightness = self.vera_device.get_brightness() self._brightness = self.vera_device.get_brightness()
self._color = self.vera_device.get_color() rgb = self.vera_device.get_color()
self._color = color_util.color_RGB_to_hs(*rgb) if rgb else None

View File

@ -9,12 +9,11 @@ import logging
from datetime import timedelta from datetime import timedelta
import homeassistant.util as util import homeassistant.util as util
import homeassistant.util.color as color_util
from homeassistant.components.light import ( from homeassistant.components.light import (
Light, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_TRANSITION, Light, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR, ATTR_TRANSITION,
ATTR_XY_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR, SUPPORT_TRANSITION)
SUPPORT_TRANSITION, SUPPORT_XY_COLOR)
from homeassistant.loader import get_component from homeassistant.loader import get_component
import homeassistant.util.color as color_util
DEPENDENCIES = ['wemo'] DEPENDENCIES = ['wemo']
@ -23,8 +22,8 @@ MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(milliseconds=100)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SUPPORT_WEMO = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR | SUPPORT_WEMO = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_COLOR |
SUPPORT_TRANSITION | SUPPORT_XY_COLOR) SUPPORT_TRANSITION)
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
@ -89,9 +88,10 @@ class WemoLight(Light):
return self.device.state.get('level', 255) return self.device.state.get('level', 255)
@property @property
def xy_color(self): def hs_color(self):
"""Return the XY color values of this light.""" """Return the hs color values of this light."""
return self.device.state.get('color_xy') xy_color = self.device.state.get('color_xy')
return color_util.color_xy_to_hs(*xy_color) if xy_color else None
@property @property
def color_temp(self): def color_temp(self):
@ -112,17 +112,11 @@ class WemoLight(Light):
"""Turn the light on.""" """Turn the light on."""
transitiontime = int(kwargs.get(ATTR_TRANSITION, 0)) transitiontime = int(kwargs.get(ATTR_TRANSITION, 0))
if ATTR_XY_COLOR in kwargs: hs_color = kwargs.get(ATTR_HS_COLOR)
xycolor = kwargs[ATTR_XY_COLOR]
elif ATTR_RGB_COLOR in kwargs:
xycolor = color_util.color_RGB_to_xy(
*(int(val) for val in kwargs[ATTR_RGB_COLOR]))
kwargs.setdefault(ATTR_BRIGHTNESS, xycolor[2])
else:
xycolor = None
if xycolor is not None: if hs_color is not None:
self.device.set_color(xycolor, transition=transitiontime) xy_color = color_util.color_hs_to_xy(*hs_color)
self.device.set_color(xy_color, transition=transitiontime)
if ATTR_COLOR_TEMP in kwargs: if ATTR_COLOR_TEMP in kwargs:
colortemp = kwargs[ATTR_COLOR_TEMP] colortemp = kwargs[ATTR_COLOR_TEMP]

View File

@ -8,8 +8,8 @@ import asyncio
import colorsys import colorsys
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR, SUPPORT_BRIGHTNESS,
SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, Light) SUPPORT_COLOR_TEMP, SUPPORT_COLOR, Light)
from homeassistant.components.wink import DOMAIN, WinkDevice from homeassistant.components.wink import DOMAIN, WinkDevice
from homeassistant.util import color as color_util from homeassistant.util import color as color_util
from homeassistant.util.color import \ from homeassistant.util.color import \
@ -17,7 +17,7 @@ from homeassistant.util.color import \
DEPENDENCIES = ['wink'] DEPENDENCIES = ['wink']
SUPPORT_WINK = SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR SUPPORT_WINK = SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_COLOR
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
@ -72,11 +72,11 @@ class WinkLight(WinkDevice, Light):
return r_value, g_value, b_value return r_value, g_value, b_value
@property @property
def xy_color(self): def hs_color(self):
"""Define current bulb color in CIE 1931 (XY) color space.""" """Define current bulb color."""
if not self.wink.supports_xy_color(): if not self.wink.supports_xy_color():
return None return None
return self.wink.color_xy() return color_util.color_xy_to_hs(*self.wink.color_xy())
@property @property
def color_temp(self): def color_temp(self):
@ -94,21 +94,17 @@ class WinkLight(WinkDevice, Light):
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn the switch on.""" """Turn the switch on."""
brightness = kwargs.get(ATTR_BRIGHTNESS) brightness = kwargs.get(ATTR_BRIGHTNESS)
rgb_color = kwargs.get(ATTR_RGB_COLOR) hs_color = kwargs.get(ATTR_HS_COLOR)
color_temp_mired = kwargs.get(ATTR_COLOR_TEMP) color_temp_mired = kwargs.get(ATTR_COLOR_TEMP)
state_kwargs = { state_kwargs = {}
}
if rgb_color: if hs_color:
if self.wink.supports_xy_color(): if self.wink.supports_xy_color():
xyb = color_util.color_RGB_to_xy(*rgb_color) xy_color = color_util.color_hs_to_xy(*hs_color)
state_kwargs['color_xy'] = xyb[0], xyb[1] state_kwargs['color_xy'] = xy_color
state_kwargs['brightness'] = xyb[2]
if self.wink.supports_hue_saturation(): if self.wink.supports_hue_saturation():
hsv = colorsys.rgb_to_hsv( state_kwargs['color_hue_saturation'] = hs_color
rgb_color[0], rgb_color[1], rgb_color[2])
state_kwargs['color_hue_saturation'] = hsv[0], hsv[1]
if color_temp_mired: if color_temp_mired:
state_kwargs['color_kelvin'] = mired_to_kelvin(color_temp_mired) state_kwargs['color_kelvin'] = mired_to_kelvin(color_temp_mired)

View File

@ -4,9 +4,10 @@ import struct
import binascii import binascii
from homeassistant.components.xiaomi_aqara import (PY_XIAOMI_GATEWAY, from homeassistant.components.xiaomi_aqara import (PY_XIAOMI_GATEWAY,
XiaomiDevice) XiaomiDevice)
from homeassistant.components.light import (ATTR_BRIGHTNESS, ATTR_RGB_COLOR, from homeassistant.components.light import (ATTR_BRIGHTNESS, ATTR_HS_COLOR,
SUPPORT_BRIGHTNESS, SUPPORT_BRIGHTNESS,
SUPPORT_RGB_COLOR, Light) SUPPORT_COLOR, Light)
import homeassistant.util.color as color_util
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -29,7 +30,7 @@ class XiaomiGatewayLight(XiaomiDevice, Light):
def __init__(self, device, name, xiaomi_hub): def __init__(self, device, name, xiaomi_hub):
"""Initialize the XiaomiGatewayLight.""" """Initialize the XiaomiGatewayLight."""
self._data_key = 'rgb' self._data_key = 'rgb'
self._rgb = (255, 255, 255) self._hs = (0, 0)
self._brightness = 180 self._brightness = 180
XiaomiDevice.__init__(self, device, name, xiaomi_hub) XiaomiDevice.__init__(self, device, name, xiaomi_hub)
@ -64,7 +65,7 @@ class XiaomiGatewayLight(XiaomiDevice, Light):
rgb = rgba[1:] rgb = rgba[1:]
self._brightness = int(255 * brightness / 100) self._brightness = int(255 * brightness / 100)
self._rgb = rgb self._hs = color_util.color_RGB_to_hs(*rgb)
self._state = True self._state = True
return True return True
@ -74,24 +75,25 @@ class XiaomiGatewayLight(XiaomiDevice, Light):
return self._brightness return self._brightness
@property @property
def rgb_color(self): def hs_color(self):
"""Return the RBG color value.""" """Return the hs color value."""
return self._rgb return self._hs
@property @property
def supported_features(self): def supported_features(self):
"""Return the supported features.""" """Return the supported features."""
return SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR return SUPPORT_BRIGHTNESS | SUPPORT_COLOR
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn the light on.""" """Turn the light on."""
if ATTR_RGB_COLOR in kwargs: if ATTR_HS_COLOR in kwargs:
self._rgb = kwargs[ATTR_RGB_COLOR] self._hs = kwargs[ATTR_HS_COLOR]
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
self._brightness = int(100 * kwargs[ATTR_BRIGHTNESS] / 255) self._brightness = int(100 * kwargs[ATTR_BRIGHTNESS] / 255)
rgba = (self._brightness,) + self._rgb rgb = color_util.color_hs_to_RGB(*self._hs)
rgba = (self._brightness,) + rgb
rgbhex = binascii.hexlify(struct.pack('BBBB', *rgba)).decode("ASCII") rgbhex = binascii.hexlify(struct.pack('BBBB', *rgba)).decode("ASCII")
rgbhex = int(rgbhex, 16) rgbhex = int(rgbhex, 16)

View File

@ -5,26 +5,20 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/light.yeelight/ https://home-assistant.io/components/light.yeelight/
""" """
import logging import logging
import colorsys
from typing import Tuple
import voluptuous as vol import voluptuous as vol
from homeassistant.util.color import ( from homeassistant.util.color import (
color_temperature_mired_to_kelvin as mired_to_kelvin, color_temperature_mired_to_kelvin as mired_to_kelvin,
color_temperature_kelvin_to_mired as kelvin_to_mired, color_temperature_kelvin_to_mired as kelvin_to_mired)
color_temperature_to_rgb,
color_RGB_to_xy,
color_xy_brightness_to_RGB)
from homeassistant.const import CONF_DEVICES, CONF_NAME from homeassistant.const import CONF_DEVICES, CONF_NAME
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_TRANSITION, ATTR_COLOR_TEMP, ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_TRANSITION, ATTR_COLOR_TEMP,
ATTR_FLASH, ATTR_XY_COLOR, FLASH_SHORT, FLASH_LONG, ATTR_EFFECT, ATTR_FLASH, FLASH_SHORT, FLASH_LONG, ATTR_EFFECT, SUPPORT_BRIGHTNESS,
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, SUPPORT_XY_COLOR, SUPPORT_COLOR, SUPPORT_TRANSITION, SUPPORT_COLOR_TEMP, SUPPORT_FLASH,
SUPPORT_TRANSITION, SUPPORT_EFFECT, Light, PLATFORM_SCHEMA)
SUPPORT_COLOR_TEMP, SUPPORT_FLASH, SUPPORT_EFFECT,
Light, PLATFORM_SCHEMA)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util
REQUIREMENTS = ['yeelight==0.4.0'] REQUIREMENTS = ['yeelight==0.4.0']
@ -53,8 +47,7 @@ SUPPORT_YEELIGHT = (SUPPORT_BRIGHTNESS |
SUPPORT_FLASH) SUPPORT_FLASH)
SUPPORT_YEELIGHT_RGB = (SUPPORT_YEELIGHT | SUPPORT_YEELIGHT_RGB = (SUPPORT_YEELIGHT |
SUPPORT_RGB_COLOR | SUPPORT_COLOR |
SUPPORT_XY_COLOR |
SUPPORT_EFFECT | SUPPORT_EFFECT |
SUPPORT_COLOR_TEMP) SUPPORT_COLOR_TEMP)
@ -98,14 +91,6 @@ YEELIGHT_EFFECT_LIST = [
EFFECT_STOP] EFFECT_STOP]
# Travis-CI runs too old astroid https://github.com/PyCQA/pylint/issues/1212
# pylint: disable=invalid-sequence-index
def hsv_to_rgb(hsv: Tuple[float, float, float]) -> Tuple[int, int, int]:
"""Convert HSV tuple (degrees, %, %) to RGB (values 0-255)."""
red, green, blue = colorsys.hsv_to_rgb(hsv[0]/360, hsv[1]/100, hsv[2]/100)
return int(red * 255), int(green * 255), int(blue * 255)
def _cmd(func): def _cmd(func):
"""Define a wrapper to catch exceptions from the bulb.""" """Define a wrapper to catch exceptions from the bulb."""
def _wrap(self, *args, **kwargs): def _wrap(self, *args, **kwargs):
@ -157,8 +142,7 @@ class YeelightLight(Light):
self._brightness = None self._brightness = None
self._color_temp = None self._color_temp = None
self._is_on = None self._is_on = None
self._rgb = None self._hs = None
self._xy = None
@property @property
def available(self) -> bool: def available(self) -> bool:
@ -209,38 +193,32 @@ class YeelightLight(Light):
return kelvin_to_mired(YEELIGHT_RGB_MIN_KELVIN) return kelvin_to_mired(YEELIGHT_RGB_MIN_KELVIN)
return kelvin_to_mired(YEELIGHT_MIN_KELVIN) return kelvin_to_mired(YEELIGHT_MIN_KELVIN)
def _get_rgb_from_properties(self): def _get_hs_from_properties(self):
rgb = self._properties.get('rgb', None) rgb = self._properties.get('rgb', None)
color_mode = self._properties.get('color_mode', None) color_mode = self._properties.get('color_mode', None)
if not rgb or not color_mode: if not rgb or not color_mode:
return rgb return None
color_mode = int(color_mode) color_mode = int(color_mode)
if color_mode == 2: # color temperature if color_mode == 2: # color temperature
temp_in_k = mired_to_kelvin(self._color_temp) temp_in_k = mired_to_kelvin(self._color_temp)
return color_temperature_to_rgb(temp_in_k) return color_util.color_temperature_to_hs(temp_in_k)
if color_mode == 3: # hsv if color_mode == 3: # hsv
hue = int(self._properties.get('hue')) hue = int(self._properties.get('hue'))
sat = int(self._properties.get('sat')) sat = int(self._properties.get('sat'))
val = int(self._properties.get('bright')) return (hue / 360 * 65536, sat / 100 * 255)
return hsv_to_rgb((hue, sat, val))
rgb = int(rgb) rgb = int(rgb)
blue = rgb & 0xff blue = rgb & 0xff
green = (rgb >> 8) & 0xff green = (rgb >> 8) & 0xff
red = (rgb >> 16) & 0xff red = (rgb >> 16) & 0xff
return red, green, blue return color_util.color_RGB_to_hs(red, green, blue)
@property @property
def rgb_color(self) -> tuple: def hs_color(self) -> tuple:
"""Return the color property.""" """Return the color property."""
return self._rgb return self._hs
@property
def xy_color(self) -> tuple:
"""Return the XY color value."""
return self._xy
@property @property
def _properties(self) -> dict: def _properties(self) -> dict:
@ -288,13 +266,7 @@ class YeelightLight(Light):
if temp_in_k: if temp_in_k:
self._color_temp = kelvin_to_mired(int(temp_in_k)) self._color_temp = kelvin_to_mired(int(temp_in_k))
self._rgb = self._get_rgb_from_properties() self._hs = self._get_hs_from_properties()
if self._rgb:
xyb = color_RGB_to_xy(*self._rgb)
self._xy = (xyb[0], xyb[1])
else:
self._xy = None
self._available = True self._available = True
except yeelight.BulbException as ex: except yeelight.BulbException as ex:
@ -313,7 +285,7 @@ class YeelightLight(Light):
@_cmd @_cmd
def set_rgb(self, rgb, duration) -> None: def set_rgb(self, rgb, duration) -> None:
"""Set bulb's color.""" """Set bulb's color."""
if rgb and self.supported_features & SUPPORT_RGB_COLOR: if rgb and self.supported_features & SUPPORT_COLOR:
_LOGGER.debug("Setting RGB: %s", rgb) _LOGGER.debug("Setting RGB: %s", rgb)
self._bulb.set_rgb(rgb[0], rgb[1], rgb[2], duration=duration) self._bulb.set_rgb(rgb[0], rgb[1], rgb[2], duration=duration)
@ -349,7 +321,7 @@ class YeelightLight(Light):
count = 1 count = 1
duration = transition * 2 duration = transition * 2
red, green, blue = self.rgb_color red, green, blue = color_util.color_hs_to_RGB(*self._hs)
transitions = list() transitions = list()
transitions.append( transitions.append(
@ -419,10 +391,10 @@ class YeelightLight(Light):
import yeelight import yeelight
brightness = kwargs.get(ATTR_BRIGHTNESS) brightness = kwargs.get(ATTR_BRIGHTNESS)
colortemp = kwargs.get(ATTR_COLOR_TEMP) colortemp = kwargs.get(ATTR_COLOR_TEMP)
rgb = kwargs.get(ATTR_RGB_COLOR) hs_color = kwargs.get(ATTR_HS_COLOR)
rgb = color_util.color_hs_to_RGB(*hs_color) if hs_color else None
flash = kwargs.get(ATTR_FLASH) flash = kwargs.get(ATTR_FLASH)
effect = kwargs.get(ATTR_EFFECT) effect = kwargs.get(ATTR_EFFECT)
xy_color = kwargs.get(ATTR_XY_COLOR)
duration = int(self.config[CONF_TRANSITION]) # in ms duration = int(self.config[CONF_TRANSITION]) # in ms
if ATTR_TRANSITION in kwargs: # passed kwarg overrides config if ATTR_TRANSITION in kwargs: # passed kwarg overrides config
@ -440,9 +412,6 @@ class YeelightLight(Light):
except yeelight.BulbException as ex: except yeelight.BulbException as ex:
_LOGGER.error("Unable to turn on music mode," _LOGGER.error("Unable to turn on music mode,"
"consider disabling it: %s", ex) "consider disabling it: %s", ex)
if xy_color and brightness:
rgb = color_xy_brightness_to_RGB(xy_color[0], xy_color[1],
brightness)
try: try:
# values checked for none in methods # values checked for none in methods

View File

@ -10,15 +10,16 @@ import voluptuous as vol
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.components.light import ( from homeassistant.components.light import (
Light, ATTR_RGB_COLOR, SUPPORT_RGB_COLOR, ATTR_BRIGHTNESS, Light, ATTR_HS_COLOR, SUPPORT_COLOR, ATTR_BRIGHTNESS,
SUPPORT_BRIGHTNESS, PLATFORM_SCHEMA) SUPPORT_BRIGHTNESS, PLATFORM_SCHEMA)
from homeassistant.const import CONF_HOST from homeassistant.const import CONF_HOST
import homeassistant.util.color as color_util
REQUIREMENTS = ['yeelightsunflower==0.0.8'] REQUIREMENTS = ['yeelightsunflower==0.0.8']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SUPPORT_YEELIGHT_SUNFLOWER = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR) SUPPORT_YEELIGHT_SUNFLOWER = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string vol.Required(CONF_HOST): cv.string
@ -48,7 +49,7 @@ class SunflowerBulb(Light):
self._available = light.available self._available = light.available
self._brightness = light.brightness self._brightness = light.brightness
self._is_on = light.is_on self._is_on = light.is_on
self._rgb_color = light.rgb_color self._hs_color = light.rgb_color
@property @property
def name(self): def name(self):
@ -71,9 +72,9 @@ class SunflowerBulb(Light):
return int(self._brightness / 100 * 255) return int(self._brightness / 100 * 255)
@property @property
def rgb_color(self): def hs_color(self):
"""Return the color property.""" """Return the color property."""
return self._rgb_color return self._hs_color
@property @property
def supported_features(self): def supported_features(self):
@ -86,12 +87,12 @@ class SunflowerBulb(Light):
if not kwargs: if not kwargs:
self._light.turn_on() self._light.turn_on()
else: else:
if ATTR_RGB_COLOR in kwargs and ATTR_BRIGHTNESS in kwargs: if ATTR_HS_COLOR in kwargs and ATTR_BRIGHTNESS in kwargs:
rgb = kwargs[ATTR_RGB_COLOR] rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR])
bright = int(kwargs[ATTR_BRIGHTNESS] / 255 * 100) bright = int(kwargs[ATTR_BRIGHTNESS] / 255 * 100)
self._light.set_all(rgb[0], rgb[1], rgb[2], bright) self._light.set_all(rgb[0], rgb[1], rgb[2], bright)
elif ATTR_RGB_COLOR in kwargs: elif ATTR_HS_COLOR in kwargs:
rgb = kwargs[ATTR_RGB_COLOR] rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR])
self._light.set_rgb_color(rgb[0], rgb[1], rgb[2]) self._light.set_rgb_color(rgb[0], rgb[1], rgb[2])
elif ATTR_BRIGHTNESS in kwargs: elif ATTR_BRIGHTNESS in kwargs:
bright = int(kwargs[ATTR_BRIGHTNESS] / 255 * 100) bright = int(kwargs[ATTR_BRIGHTNESS] / 255 * 100)
@ -107,4 +108,4 @@ class SunflowerBulb(Light):
self._available = self._light.available self._available = self._light.available
self._brightness = self._light.brightness self._brightness = self._light.brightness
self._is_on = self._light.is_on self._is_on = self._light.is_on
self._rgb_color = self._light.rgb_color self._hs_color = color_util.color_RGB_to_hs(*self._light.rgb_color)

View File

@ -10,15 +10,16 @@ import voluptuous as vol
from homeassistant.const import CONF_DEVICES, CONF_NAME from homeassistant.const import CONF_DEVICES, CONF_NAME
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_RGB_COLOR, ATTR_WHITE_VALUE, ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_WHITE_VALUE, SUPPORT_BRIGHTNESS,
SUPPORT_RGB_COLOR, SUPPORT_WHITE_VALUE, Light, PLATFORM_SCHEMA) SUPPORT_COLOR, SUPPORT_WHITE_VALUE, Light, PLATFORM_SCHEMA)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util
REQUIREMENTS = ['zengge==0.2'] REQUIREMENTS = ['zengge==0.2']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SUPPORT_ZENGGE_LED = (SUPPORT_RGB_COLOR | SUPPORT_WHITE_VALUE) SUPPORT_ZENGGE_LED = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR | SUPPORT_WHITE_VALUE)
DEVICE_SCHEMA = vol.Schema({ DEVICE_SCHEMA = vol.Schema({
vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_NAME): cv.string,
@ -56,7 +57,8 @@ class ZenggeLight(Light):
self.is_valid = True self.is_valid = True
self._bulb = zengge.zengge(self._address) self._bulb = zengge.zengge(self._address)
self._white = 0 self._white = 0
self._rgb = (0, 0, 0) self._brightness = 0
self._hs_color = (0, 0)
self._state = False self._state = False
if self._bulb.connect() is False: if self._bulb.connect() is False:
self.is_valid = False self.is_valid = False
@ -80,9 +82,14 @@ class ZenggeLight(Light):
return self._state return self._state
@property @property
def rgb_color(self): def brightness(self):
"""Return the brightness property."""
return self._brightness
@property
def hs_color(self):
"""Return the color property.""" """Return the color property."""
return self._rgb return self._hs_color
@property @property
def white_value(self): def white_value(self):
@ -117,21 +124,29 @@ class ZenggeLight(Light):
self._state = True self._state = True
self._bulb.on() self._bulb.on()
rgb = kwargs.get(ATTR_RGB_COLOR) hs_color = kwargs.get(ATTR_HS_COLOR)
white = kwargs.get(ATTR_WHITE_VALUE) white = kwargs.get(ATTR_WHITE_VALUE)
brightness = kwargs.get(ATTR_BRIGHTNESS)
if white is not None: if white is not None:
self._white = white self._white = white
self._rgb = (0, 0, 0) self._hs_color = (0, 0)
if rgb is not None: if hs_color is not None:
self._white = 0 self._white = 0
self._rgb = rgb self._hs_color = hs_color
if brightness is not None:
self._white = 0
self._brightness = brightness
if self._white != 0: if self._white != 0:
self.set_white(self._white) self.set_white(self._white)
else: else:
self.set_rgb(self._rgb[0], self._rgb[1], self._rgb[2]) rgb = color_util.color_hsv_to_RGB(
self._hs_color[0], self._hs_color[1],
self._brightness / 255 * 100)
self.set_rgb(*rgb)
def turn_off(self, **kwargs): def turn_off(self, **kwargs):
"""Turn the specified light off.""" """Turn the specified light off."""
@ -140,6 +155,9 @@ class ZenggeLight(Light):
def update(self): def update(self):
"""Synchronise internal state with the actual light state.""" """Synchronise internal state with the actual light state."""
self._rgb = self._bulb.get_colour() rgb = self._bulb.get_colour()
hsv = color_util.color_RGB_to_hsv(*rgb)
self._hs_color = hsv[:2]
self._brightness = hsv[2]
self._white = self._bulb.get_white() self._white = self._bulb.get_white()
self._state = self._bulb.get_on() self._state = self._bulb.get_on()

View File

@ -7,8 +7,8 @@ at https://home-assistant.io/components/light.zha/
import logging import logging
from homeassistant.components import light, zha from homeassistant.components import light, zha
from homeassistant.util.color import color_RGB_to_xy
from homeassistant.const import STATE_UNKNOWN from homeassistant.const import STATE_UNKNOWN
import homeassistant.util.color as color_util
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -57,7 +57,7 @@ class Light(zha.Entity, light.Light):
super().__init__(**kwargs) super().__init__(**kwargs)
self._supported_features = 0 self._supported_features = 0
self._color_temp = None self._color_temp = None
self._xy_color = None self._hs_color = None
self._brightness = None self._brightness = None
import zigpy.zcl.clusters as zcl_clusters import zigpy.zcl.clusters as zcl_clusters
@ -71,9 +71,8 @@ class Light(zha.Entity, light.Light):
self._supported_features |= light.SUPPORT_COLOR_TEMP self._supported_features |= light.SUPPORT_COLOR_TEMP
if color_capabilities & CAPABILITIES_COLOR_XY: if color_capabilities & CAPABILITIES_COLOR_XY:
self._supported_features |= light.SUPPORT_XY_COLOR self._supported_features |= light.SUPPORT_COLOR
self._supported_features |= light.SUPPORT_RGB_COLOR self._hs_color = (0, 0)
self._xy_color = (1.0, 1.0)
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
@ -92,17 +91,12 @@ class Light(zha.Entity, light.Light):
temperature, duration) temperature, duration)
self._color_temp = temperature self._color_temp = temperature
if light.ATTR_XY_COLOR in kwargs: if light.ATTR_HS_COLOR in kwargs:
self._xy_color = kwargs[light.ATTR_XY_COLOR] self._hs_color = kwargs[light.ATTR_HS_COLOR]
elif light.ATTR_RGB_COLOR in kwargs: xy_color = color_util.color_hs_to_xy(*self._hs_color)
xyb = color_RGB_to_xy(
*(int(val) for val in kwargs[light.ATTR_RGB_COLOR]))
self._xy_color = (xyb[0], xyb[1])
self._brightness = xyb[2]
if light.ATTR_XY_COLOR in kwargs or light.ATTR_RGB_COLOR in kwargs:
await self._endpoint.light_color.move_to_color( await self._endpoint.light_color.move_to_color(
int(self._xy_color[0] * 65535), int(xy_color[0] * 65535),
int(self._xy_color[1] * 65535), int(xy_color[1] * 65535),
duration, duration,
) )
@ -135,9 +129,9 @@ class Light(zha.Entity, light.Light):
return self._brightness return self._brightness
@property @property
def xy_color(self): def hs_color(self):
"""Return the XY color value [float, float].""" """Return the hs color value [int, int]."""
return self._xy_color return self._hs_color
@property @property
def color_temp(self): def color_temp(self):
@ -165,11 +159,12 @@ class Light(zha.Entity, light.Light):
self._color_temp = result.get('color_temperature', self._color_temp = result.get('color_temperature',
self._color_temp) self._color_temp)
if self._supported_features & light.SUPPORT_XY_COLOR: if self._supported_features & light.SUPPORT_COLOR:
result = await zha.safe_read(self._endpoint.light_color, result = await zha.safe_read(self._endpoint.light_color,
['current_x', 'current_y']) ['current_x', 'current_y'])
if 'current_x' in result and 'current_y' in result: if 'current_x' in result and 'current_y' in result:
self._xy_color = (result['current_x'], result['current_y']) xy_color = (result['current_x'], result['current_y'])
self._hs_color = color_util.color_xy_to_hs(*xy_color)
@property @property
def should_poll(self) -> bool: def should_poll(self) -> bool:

View File

@ -9,14 +9,14 @@ import logging
# Because we do not compile openzwave on CI # Because we do not compile openzwave on CI
# pylint: disable=import-error # pylint: disable=import-error
from threading import Timer from threading import Timer
from homeassistant.components.light import ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, \ from homeassistant.components.light import (
ATTR_RGB_COLOR, ATTR_TRANSITION, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, \ ATTR_WHITE_VALUE, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR,
SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, DOMAIN, Light ATTR_TRANSITION, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR,
SUPPORT_TRANSITION, SUPPORT_WHITE_VALUE, DOMAIN, Light)
from homeassistant.components import zwave from homeassistant.components import zwave
from homeassistant.components.zwave import async_setup_platform # noqa # pylint: disable=unused-import from homeassistant.components.zwave import async_setup_platform # noqa # pylint: disable=unused-import
from homeassistant.const import STATE_OFF, STATE_ON from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.util.color import color_temperature_mired_to_kelvin, \ import homeassistant.util.color as color_util
color_temperature_to_rgb, color_rgb_to_rgbw, color_rgbw_to_rgb
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -65,10 +65,11 @@ def brightness_state(value):
return 0, STATE_OFF return 0, STATE_OFF
def ct_to_rgb(temp): def ct_to_hs(temp):
"""Convert color temperature (mireds) to RGB.""" """Convert color temperature (mireds) to hs."""
colorlist = list( colorlist = list(
color_temperature_to_rgb(color_temperature_mired_to_kelvin(temp))) color_util.color_temperature_to_hs(
color_util.color_temperature_mired_to_kelvin(temp)))
return [int(val) for val in colorlist] return [int(val) for val in colorlist]
@ -209,8 +210,9 @@ class ZwaveColorLight(ZwaveDimmer):
def __init__(self, values, refresh, delay): def __init__(self, values, refresh, delay):
"""Initialize the light.""" """Initialize the light."""
self._color_channels = None self._color_channels = None
self._rgb = None self._hs = None
self._ct = None self._ct = None
self._white = None
super().__init__(values, refresh, delay) super().__init__(values, refresh, delay)
@ -218,9 +220,12 @@ class ZwaveColorLight(ZwaveDimmer):
"""Call when a new value is added to this entity.""" """Call when a new value is added to this entity."""
super().value_added() super().value_added()
self._supported_features |= SUPPORT_RGB_COLOR self._supported_features |= SUPPORT_COLOR
if self._zw098: if self._zw098:
self._supported_features |= SUPPORT_COLOR_TEMP self._supported_features |= SUPPORT_COLOR_TEMP
elif self._color_channels is not None and self._color_channels & (
COLOR_CHANNEL_WARM_WHITE | COLOR_CHANNEL_COLD_WHITE):
self._supported_features |= SUPPORT_WHITE_VALUE
def update_properties(self): def update_properties(self):
"""Update internal properties based on zwave values.""" """Update internal properties based on zwave values."""
@ -238,10 +243,11 @@ class ZwaveColorLight(ZwaveDimmer):
data = self.values.color.data data = self.values.color.data
# RGB is always present in the openzwave color data string. # RGB is always present in the openzwave color data string.
self._rgb = [ rgb = [
int(data[1:3], 16), int(data[1:3], 16),
int(data[3:5], 16), int(data[3:5], 16),
int(data[5:7], 16)] int(data[5:7], 16)]
self._hs = color_util.color_RGB_to_hs(*rgb)
# Parse remaining color channels. Openzwave appends white channels # Parse remaining color channels. Openzwave appends white channels
# that are present. # that are present.
@ -267,30 +273,35 @@ class ZwaveColorLight(ZwaveDimmer):
if self._zw098: if self._zw098:
if warm_white > 0: if warm_white > 0:
self._ct = TEMP_WARM_HASS self._ct = TEMP_WARM_HASS
self._rgb = ct_to_rgb(self._ct) self._hs = ct_to_hs(self._ct)
elif cold_white > 0: elif cold_white > 0:
self._ct = TEMP_COLD_HASS self._ct = TEMP_COLD_HASS
self._rgb = ct_to_rgb(self._ct) self._hs = ct_to_hs(self._ct)
else: else:
# RGB color is being used. Just report midpoint. # RGB color is being used. Just report midpoint.
self._ct = TEMP_MID_HASS self._ct = TEMP_MID_HASS
elif self._color_channels & COLOR_CHANNEL_WARM_WHITE: elif self._color_channels & COLOR_CHANNEL_WARM_WHITE:
self._rgb = list(color_rgbw_to_rgb(*self._rgb, w=warm_white)) self._white = warm_white
elif self._color_channels & COLOR_CHANNEL_COLD_WHITE: elif self._color_channels & COLOR_CHANNEL_COLD_WHITE:
self._rgb = list(color_rgbw_to_rgb(*self._rgb, w=cold_white)) self._white = cold_white
# If no rgb channels supported, report None. # If no rgb channels supported, report None.
if not (self._color_channels & COLOR_CHANNEL_RED or if not (self._color_channels & COLOR_CHANNEL_RED or
self._color_channels & COLOR_CHANNEL_GREEN or self._color_channels & COLOR_CHANNEL_GREEN or
self._color_channels & COLOR_CHANNEL_BLUE): self._color_channels & COLOR_CHANNEL_BLUE):
self._rgb = None self._hs = None
@property @property
def rgb_color(self): def hs_color(self):
"""Return the rgb color.""" """Return the hs color."""
return self._rgb return self._hs
@property
def white_value(self):
"""Return the white value of this light between 0..255."""
return self._white
@property @property
def color_temp(self): def color_temp(self):
@ -301,6 +312,9 @@ class ZwaveColorLight(ZwaveDimmer):
"""Turn the device on.""" """Turn the device on."""
rgbw = None rgbw = None
if ATTR_WHITE_VALUE in kwargs:
self._white = kwargs[ATTR_WHITE_VALUE]
if ATTR_COLOR_TEMP in kwargs: if ATTR_COLOR_TEMP in kwargs:
# Color temperature. With the AEOTEC ZW098 bulb, only two color # Color temperature. With the AEOTEC ZW098 bulb, only two color
# temperatures are supported. The warm and cold channel values # temperatures are supported. The warm and cold channel values
@ -313,19 +327,16 @@ class ZwaveColorLight(ZwaveDimmer):
self._ct = TEMP_COLD_HASS self._ct = TEMP_COLD_HASS
rgbw = '#00000000ff' rgbw = '#00000000ff'
elif ATTR_RGB_COLOR in kwargs: elif ATTR_HS_COLOR in kwargs:
self._rgb = kwargs[ATTR_RGB_COLOR] self._hs = kwargs[ATTR_HS_COLOR]
if (not self._zw098 and (
self._color_channels & COLOR_CHANNEL_WARM_WHITE or if ATTR_WHITE_VALUE in kwargs or ATTR_HS_COLOR in kwargs:
self._color_channels & COLOR_CHANNEL_COLD_WHITE)):
rgbw = '#' rgbw = '#'
for colorval in color_rgb_to_rgbw(*self._rgb): for colorval in color_util.color_hs_to_RGB(*self._hs):
rgbw += format(colorval, '02x') rgbw += format(colorval, '02x')
rgbw += '00' if self._white is not None:
rgbw += format(self._white, '02x') + '00'
else: else:
rgbw = '#'
for colorval in self._rgb:
rgbw += format(colorval, '02x')
rgbw += '0000' rgbw += '0000'
if rgbw and self.values.color: if rgbw and self.values.color:

View File

@ -21,7 +21,7 @@ from homeassistant.helpers.event import track_time_change
from homeassistant.helpers.sun import get_astral_event_date from homeassistant.helpers.sun import get_astral_event_date
from homeassistant.util import slugify from homeassistant.util import slugify
from homeassistant.util.color import ( from homeassistant.util.color import (
color_temperature_to_rgb, color_RGB_to_xy, color_temperature_to_rgb, color_RGB_to_xy_brightness,
color_temperature_kelvin_to_mired) color_temperature_kelvin_to_mired)
from homeassistant.util.dt import now as dt_now from homeassistant.util.dt import now as dt_now
@ -234,7 +234,7 @@ class FluxSwitch(SwitchDevice):
else: else:
temp = self._sunset_colortemp + temp_offset temp = self._sunset_colortemp + temp_offset
rgb = color_temperature_to_rgb(temp) rgb = color_temperature_to_rgb(temp)
x_val, y_val, b_val = color_RGB_to_xy(*rgb) x_val, y_val, b_val = color_RGB_to_xy_brightness(*rgb)
brightness = self._brightness if self._brightness else b_val brightness = self._brightness if self._brightness else b_val
if self._disable_brightness_adjust: if self._disable_brightness_adjust:
brightness = None brightness = None

View File

@ -173,11 +173,18 @@ def color_name_to_rgb(color_name):
return hex_value return hex_value
# pylint: disable=invalid-name, invalid-sequence-index
def color_RGB_to_xy(iR: int, iG: int, iB: int) -> Tuple[float, float]:
"""Convert from RGB color to XY color."""
return color_RGB_to_xy_brightness(iR, iG, iB)[:2]
# Taken from: # Taken from:
# http://www.developers.meethue.com/documentation/color-conversions-rgb-xy # http://www.developers.meethue.com/documentation/color-conversions-rgb-xy
# License: Code is given as is. Use at your own risk and discretion. # License: Code is given as is. Use at your own risk and discretion.
# pylint: disable=invalid-name, invalid-sequence-index # pylint: disable=invalid-name, invalid-sequence-index
def color_RGB_to_xy(iR: int, iG: int, iB: int) -> Tuple[float, float, int]: def color_RGB_to_xy_brightness(
iR: int, iG: int, iB: int) -> Tuple[float, float, int]:
"""Convert from RGB color to XY color.""" """Convert from RGB color to XY color."""
if iR + iG + iB == 0: if iR + iG + iB == 0:
return 0.0, 0.0, 0 return 0.0, 0.0, 0
@ -210,6 +217,11 @@ def color_RGB_to_xy(iR: int, iG: int, iB: int) -> Tuple[float, float, int]:
return round(x, 3), round(y, 3), brightness return round(x, 3), round(y, 3), brightness
def color_xy_to_RGB(vX: float, vY: float) -> Tuple[int, int, int]:
"""Convert from XY to a normalized RGB."""
return color_xy_brightness_to_RGB(vX, vY, 255)
# Converted to Python from Obj-C, original source from: # Converted to Python from Obj-C, original source from:
# http://www.developers.meethue.com/documentation/color-conversions-rgb-xy # http://www.developers.meethue.com/documentation/color-conversions-rgb-xy
# pylint: disable=invalid-sequence-index # pylint: disable=invalid-sequence-index
@ -307,6 +319,12 @@ def color_RGB_to_hsv(iR: int, iG: int, iB: int) -> Tuple[float, float, float]:
return round(fHSV[0]*360, 3), round(fHSV[1]*100, 3), round(fHSV[2]*100, 3) return round(fHSV[0]*360, 3), round(fHSV[1]*100, 3), round(fHSV[2]*100, 3)
# pylint: disable=invalid-sequence-index
def color_RGB_to_hs(iR: int, iG: int, iB: int) -> Tuple[float, float]:
"""Convert an rgb color to its hs representation."""
return color_RGB_to_hsv(iR, iG, iB)[:2]
# pylint: disable=invalid-sequence-index # pylint: disable=invalid-sequence-index
def color_hsv_to_RGB(iH: float, iS: float, iV: float) -> Tuple[int, int, int]: def color_hsv_to_RGB(iH: float, iS: float, iV: float) -> Tuple[int, int, int]:
"""Convert an hsv color into its rgb representation. """Convert an hsv color into its rgb representation.
@ -320,12 +338,24 @@ def color_hsv_to_RGB(iH: float, iS: float, iV: float) -> Tuple[int, int, int]:
# pylint: disable=invalid-sequence-index # pylint: disable=invalid-sequence-index
def color_xy_to_hs(vX: float, vY: float) -> Tuple[int, int]: def color_hs_to_RGB(iH: float, iS: float) -> Tuple[int, int, int]:
"""Convert an hsv color into its rgb representation."""
return color_hsv_to_RGB(iH, iS, 100)
# pylint: disable=invalid-sequence-index
def color_xy_to_hs(vX: float, vY: float) -> Tuple[float, float]:
"""Convert an xy color to its hs representation.""" """Convert an xy color to its hs representation."""
h, s, _ = color_RGB_to_hsv(*color_xy_brightness_to_RGB(vX, vY, 255)) h, s, _ = color_RGB_to_hsv(*color_xy_to_RGB(vX, vY))
return (h, s) return (h, s)
# pylint: disable=invalid-sequence-index
def color_hs_to_xy(iH: float, iS: float) -> Tuple[float, float]:
"""Convert an hs color to its xy representation."""
return color_RGB_to_xy(*color_hs_to_RGB(iH, iS))
# pylint: disable=invalid-sequence-index # pylint: disable=invalid-sequence-index
def _match_max_scale(input_colors: Tuple[int, ...], def _match_max_scale(input_colors: Tuple[int, ...],
output_colors: Tuple[int, ...]) -> Tuple[int, ...]: output_colors: Tuple[int, ...]) -> Tuple[int, ...]:
@ -374,6 +404,11 @@ def rgb_hex_to_rgb_list(hex_string):
len(hex_string) // 3)] len(hex_string) // 3)]
def color_temperature_to_hs(color_temperature_kelvin):
"""Return an hs color from a color temperature in Kelvin."""
return color_RGB_to_hs(*color_temperature_to_rgb(color_temperature_kelvin))
def color_temperature_to_rgb(color_temperature_kelvin): def color_temperature_to_rgb(color_temperature_kelvin):
""" """
Return an RGB color from a color temperature in Kelvin. Return an RGB color from a color temperature in Kelvin.

View File

@ -950,42 +950,6 @@ def test_api_set_color_rgb(hass):
assert msg['header']['name'] == 'Response' assert msg['header']['name'] == 'Response'
@asyncio.coroutine
def test_api_set_color_xy(hass):
"""Test api set color process."""
request = get_new_request(
'Alexa.ColorController', 'SetColor', 'light#test')
# add payload
request['directive']['payload']['color'] = {
'hue': '120',
'saturation': '0.612',
'brightness': '0.342',
}
# setup test devices
hass.states.async_set(
'light.test', 'off', {
'friendly_name': "Test light",
'supported_features': 64,
})
call_light = async_mock_service(hass, 'light', 'turn_on')
msg = yield from smart_home.async_handle_message(
hass, DEFAULT_CONFIG, request)
yield from hass.async_block_till_done()
assert 'event' in msg
msg = msg['event']
assert len(call_light) == 1
assert call_light[0].data['entity_id'] == 'light.test'
assert call_light[0].data['xy_color'] == (0.23, 0.585)
assert call_light[0].data['brightness'] == 18
assert msg['header']['name'] == 'Response'
@asyncio.coroutine @asyncio.coroutine
def test_api_set_color_temperature(hass): def test_api_set_color_temperature(hass):
"""Test api set color temperature process.""" """Test api set color temperature process."""

View File

@ -21,7 +21,7 @@ async def test_sync_message(hass):
light = DemoLight( light = DemoLight(
None, 'Demo Light', None, 'Demo Light',
state=False, state=False,
rgb=[237, 224, 33] hs_color=(180, 75),
) )
light.hass = hass light.hass = hass
light.entity_id = 'light.demo_light' light.entity_id = 'light.demo_light'
@ -88,7 +88,7 @@ async def test_query_message(hass):
light = DemoLight( light = DemoLight(
None, 'Demo Light', None, 'Demo Light',
state=False, state=False,
rgb=[237, 224, 33] hs_color=(180, 75),
) )
light.hass = hass light.hass = hass
light.entity_id = 'light.demo_light' light.entity_id = 'light.demo_light'
@ -97,7 +97,7 @@ async def test_query_message(hass):
light2 = DemoLight( light2 = DemoLight(
None, 'Another Light', None, 'Another Light',
state=True, state=True,
rgb=[237, 224, 33], hs_color=(180, 75),
ct=400, ct=400,
brightness=78, brightness=78,
) )
@ -137,7 +137,7 @@ async def test_query_message(hass):
'online': True, 'online': True,
'brightness': 30, 'brightness': 30,
'color': { 'color': {
'spectrumRGB': 15589409, 'spectrumRGB': 4194303,
'temperature': 2500, 'temperature': 2500,
} }
}, },
@ -197,7 +197,7 @@ async def test_execute(hass):
"online": True, "online": True,
'brightness': 20, 'brightness': 20,
'color': { 'color': {
'spectrumRGB': 15589409, 'spectrumRGB': 16773155,
'temperature': 2631, 'temperature': 2631,
}, },
} }

View File

@ -361,12 +361,10 @@ async def test_color_spectrum_light(hass):
"""Test ColorSpectrum trait support for light domain.""" """Test ColorSpectrum trait support for light domain."""
assert not trait.ColorSpectrumTrait.supported(light.DOMAIN, 0) assert not trait.ColorSpectrumTrait.supported(light.DOMAIN, 0)
assert trait.ColorSpectrumTrait.supported(light.DOMAIN, assert trait.ColorSpectrumTrait.supported(light.DOMAIN,
light.SUPPORT_RGB_COLOR) light.SUPPORT_COLOR)
assert trait.ColorSpectrumTrait.supported(light.DOMAIN,
light.SUPPORT_XY_COLOR)
trt = trait.ColorSpectrumTrait(State('light.bla', STATE_ON, { trt = trait.ColorSpectrumTrait(State('light.bla', STATE_ON, {
light.ATTR_RGB_COLOR: [255, 10, 10] light.ATTR_HS_COLOR: (0, 94),
})) }))
assert trt.sync_attributes() == { assert trt.sync_attributes() == {
@ -375,7 +373,7 @@ async def test_color_spectrum_light(hass):
assert trt.query_attributes() == { assert trt.query_attributes() == {
'color': { 'color': {
'spectrumRGB': 16714250 'spectrumRGB': 16715535
} }
} }
@ -399,7 +397,7 @@ async def test_color_spectrum_light(hass):
assert len(calls) == 1 assert len(calls) == 1
assert calls[0].data == { assert calls[0].data == {
ATTR_ENTITY_ID: 'light.bla', ATTR_ENTITY_ID: 'light.bla',
light.ATTR_RGB_COLOR: [16, 16, 255] light.ATTR_HS_COLOR: (240, 93.725),
} }

View File

@ -4,8 +4,8 @@ import unittest
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.components.homekit.type_lights import Light from homeassistant.components.homekit.type_lights import Light
from homeassistant.components.light import ( from homeassistant.components.light import (
DOMAIN, ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_RGB_COLOR, DOMAIN, ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_HS_COLOR,
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR) SUPPORT_BRIGHTNESS, SUPPORT_COLOR)
from homeassistant.const import ( from homeassistant.const import (
ATTR_DOMAIN, ATTR_ENTITY_ID, ATTR_SERVICE, ATTR_SERVICE_DATA, ATTR_DOMAIN, ATTR_ENTITY_ID, ATTR_SERVICE, ATTR_SERVICE_DATA,
ATTR_SUPPORTED_FEATURES, EVENT_CALL_SERVICE, SERVICE_TURN_ON, ATTR_SUPPORTED_FEATURES, EVENT_CALL_SERVICE, SERVICE_TURN_ON,
@ -108,16 +108,16 @@ class TestHomekitLights(unittest.TestCase):
"""Test light with rgb_color.""" """Test light with rgb_color."""
entity_id = 'light.demo' entity_id = 'light.demo'
self.hass.states.set(entity_id, STATE_ON, { self.hass.states.set(entity_id, STATE_ON, {
ATTR_SUPPORTED_FEATURES: SUPPORT_RGB_COLOR, ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR,
ATTR_RGB_COLOR: (120, 20, 255)}) ATTR_HS_COLOR: (260, 90)})
acc = Light(self.hass, entity_id, 'Light', aid=2) acc = Light(self.hass, entity_id, 'Light', aid=2)
self.assertEqual(acc.char_hue.value, 0) self.assertEqual(acc.char_hue.value, 0)
self.assertEqual(acc.char_saturation.value, 75) self.assertEqual(acc.char_saturation.value, 75)
acc.run() acc.run()
self.hass.block_till_done() self.hass.block_till_done()
self.assertEqual(acc.char_hue.value, 265.532) self.assertEqual(acc.char_hue.value, 260)
self.assertEqual(acc.char_saturation.value, 92.157) self.assertEqual(acc.char_saturation.value, 90)
# Set from HomeKit # Set from HomeKit
acc.char_hue.set_value(145) acc.char_hue.set_value(145)
@ -129,4 +129,4 @@ class TestHomekitLights(unittest.TestCase):
self.events[0].data[ATTR_SERVICE], SERVICE_TURN_ON) self.events[0].data[ATTR_SERVICE], SERVICE_TURN_ON)
self.assertEqual( self.assertEqual(
self.events[0].data[ATTR_SERVICE_DATA], { self.events[0].data[ATTR_SERVICE_DATA], {
ATTR_ENTITY_ID: entity_id, ATTR_RGB_COLOR: (63, 255, 143)}) ATTR_ENTITY_ID: entity_id, ATTR_HS_COLOR: (145, 75)})

View File

@ -33,19 +33,22 @@ class TestDemoLight(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
state = self.hass.states.get(ENTITY_LIGHT) state = self.hass.states.get(ENTITY_LIGHT)
self.assertTrue(light.is_on(self.hass, ENTITY_LIGHT)) self.assertTrue(light.is_on(self.hass, ENTITY_LIGHT))
self.assertEqual((.4, .6), state.attributes.get(light.ATTR_XY_COLOR)) self.assertEqual((0.378, 0.574), state.attributes.get(
light.ATTR_XY_COLOR))
self.assertEqual(25, state.attributes.get(light.ATTR_BRIGHTNESS)) self.assertEqual(25, state.attributes.get(light.ATTR_BRIGHTNESS))
self.assertEqual( self.assertEqual(
(76, 95, 0), state.attributes.get(light.ATTR_RGB_COLOR)) (207, 255, 0), state.attributes.get(light.ATTR_RGB_COLOR))
self.assertEqual('rainbow', state.attributes.get(light.ATTR_EFFECT)) self.assertEqual('rainbow', state.attributes.get(light.ATTR_EFFECT))
light.turn_on( light.turn_on(
self.hass, ENTITY_LIGHT, rgb_color=(251, 252, 253), self.hass, ENTITY_LIGHT, rgb_color=(251, 253, 255),
white_value=254) white_value=254)
self.hass.block_till_done() self.hass.block_till_done()
state = self.hass.states.get(ENTITY_LIGHT) state = self.hass.states.get(ENTITY_LIGHT)
self.assertEqual(254, state.attributes.get(light.ATTR_WHITE_VALUE)) self.assertEqual(254, state.attributes.get(light.ATTR_WHITE_VALUE))
self.assertEqual( self.assertEqual(
(251, 252, 253), state.attributes.get(light.ATTR_RGB_COLOR)) (250, 252, 255), state.attributes.get(light.ATTR_RGB_COLOR))
self.assertEqual(
(0.316, 0.333), state.attributes.get(light.ATTR_XY_COLOR))
light.turn_on(self.hass, ENTITY_LIGHT, color_temp=400, effect='none') light.turn_on(self.hass, ENTITY_LIGHT, color_temp=400, effect='none')
self.hass.block_till_done() self.hass.block_till_done()
state = self.hass.states.get(ENTITY_LIGHT) state = self.hass.states.get(ENTITY_LIGHT)

View File

@ -20,8 +20,7 @@ async def test_default_state(hass):
assert state.state == 'unavailable' assert state.state == 'unavailable'
assert state.attributes['supported_features'] == 0 assert state.attributes['supported_features'] == 0
assert state.attributes.get('brightness') is None assert state.attributes.get('brightness') is None
assert state.attributes.get('rgb_color') is None assert state.attributes.get('hs_color') is None
assert state.attributes.get('xy_color') is None
assert state.attributes.get('color_temp') is None assert state.attributes.get('color_temp') is None
assert state.attributes.get('white_value') is None assert state.attributes.get('white_value') is None
assert state.attributes.get('effect_list') is None assert state.attributes.get('effect_list') is None
@ -85,61 +84,32 @@ async def test_brightness(hass):
assert state.attributes['brightness'] == 100 assert state.attributes['brightness'] == 100
async def test_xy_color(hass): async def test_color(hass):
"""Test XY reporting."""
await async_setup_component(hass, 'light', {'light': {
'platform': 'group', 'entities': ['light.test1', 'light.test2']
}})
hass.states.async_set('light.test1', 'on',
{'xy_color': (1.0, 1.0), 'supported_features': 64})
await hass.async_block_till_done()
state = hass.states.get('light.light_group')
assert state.state == 'on'
assert state.attributes['supported_features'] == 64
assert state.attributes['xy_color'] == (1.0, 1.0)
hass.states.async_set('light.test2', 'on',
{'xy_color': (0.5, 0.5), 'supported_features': 64})
await hass.async_block_till_done()
state = hass.states.get('light.light_group')
assert state.state == 'on'
assert state.attributes['xy_color'] == (0.75, 0.75)
hass.states.async_set('light.test1', 'off',
{'xy_color': (1.0, 1.0), 'supported_features': 64})
await hass.async_block_till_done()
state = hass.states.get('light.light_group')
assert state.state == 'on'
assert state.attributes['xy_color'] == (0.5, 0.5)
async def test_rgb_color(hass):
"""Test RGB reporting.""" """Test RGB reporting."""
await async_setup_component(hass, 'light', {'light': { await async_setup_component(hass, 'light', {'light': {
'platform': 'group', 'entities': ['light.test1', 'light.test2'] 'platform': 'group', 'entities': ['light.test1', 'light.test2']
}}) }})
hass.states.async_set('light.test1', 'on', hass.states.async_set('light.test1', 'on',
{'rgb_color': (255, 0, 0), 'supported_features': 16}) {'hs_color': (0, 100), 'supported_features': 16})
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get('light.light_group') state = hass.states.get('light.light_group')
assert state.state == 'on' assert state.state == 'on'
assert state.attributes['supported_features'] == 16 assert state.attributes['supported_features'] == 16
assert state.attributes['rgb_color'] == (255, 0, 0) assert state.attributes['hs_color'] == (0, 100)
hass.states.async_set('light.test2', 'on', hass.states.async_set('light.test2', 'on',
{'rgb_color': (255, 255, 255), {'hs_color': (0, 50),
'supported_features': 16}) 'supported_features': 16})
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get('light.light_group') state = hass.states.get('light.light_group')
assert state.attributes['rgb_color'] == (255, 127, 127) assert state.attributes['hs_color'] == (0, 75)
hass.states.async_set('light.test1', 'off', hass.states.async_set('light.test1', 'off',
{'rgb_color': (255, 0, 0), 'supported_features': 16}) {'hs_color': (0, 0), 'supported_features': 16})
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get('light.light_group') state = hass.states.get('light.light_group')
assert state.attributes['rgb_color'] == (255, 255, 255) assert state.attributes['hs_color'] == (0, 50)
async def test_white_value(hass): async def test_white_value(hass):
@ -413,5 +383,7 @@ async def test_invalid_service_calls(hass):
} }
await grouped_light.async_turn_on(**data) await grouped_light.async_turn_on(**data)
data['entity_id'] = ['light.test1', 'light.test2'] data['entity_id'] = ['light.test1', 'light.test2']
data.pop('rgb_color')
data.pop('xy_color')
mock_call.assert_called_once_with('light', 'turn_on', data, mock_call.assert_called_once_with('light', 'turn_on', data,
blocking=True) blocking=True)

View File

@ -188,23 +188,25 @@ class TestLight(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
_, data = dev1.last_call('turn_on') _, data = dev1.last_call('turn_on')
self.assertEqual( self.assertEqual({
{light.ATTR_TRANSITION: 10, light.ATTR_TRANSITION: 10,
light.ATTR_BRIGHTNESS: 20, light.ATTR_BRIGHTNESS: 20,
light.ATTR_RGB_COLOR: (0, 0, 255)}, light.ATTR_HS_COLOR: (240, 100),
data) }, data)
_, data = dev2.last_call('turn_on') _, data = dev2.last_call('turn_on')
self.assertEqual( self.assertEqual({
{light.ATTR_RGB_COLOR: (255, 255, 255), light.ATTR_HS_COLOR: (0, 0),
light.ATTR_WHITE_VALUE: 255}, light.ATTR_WHITE_VALUE: 255,
data) }, data)
_, data = dev3.last_call('turn_on') _, data = dev3.last_call('turn_on')
self.assertEqual({light.ATTR_XY_COLOR: (.4, .6)}, data) self.assertEqual({
light.ATTR_HS_COLOR: (71.059, 100),
}, data)
# One of the light profiles # One of the light profiles
prof_name, prof_x, prof_y, prof_bri = 'relax', 0.5119, 0.4147, 144 prof_name, prof_h, prof_s, prof_bri = 'relax', 35.932, 69.412, 144
# Test light profiles # Test light profiles
light.turn_on(self.hass, dev1.entity_id, profile=prof_name) light.turn_on(self.hass, dev1.entity_id, profile=prof_name)
@ -216,16 +218,16 @@ class TestLight(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
_, data = dev1.last_call('turn_on') _, data = dev1.last_call('turn_on')
self.assertEqual( self.assertEqual({
{light.ATTR_BRIGHTNESS: prof_bri, light.ATTR_BRIGHTNESS: prof_bri,
light.ATTR_XY_COLOR: (prof_x, prof_y)}, light.ATTR_HS_COLOR: (prof_h, prof_s),
data) }, data)
_, data = dev2.last_call('turn_on') _, data = dev2.last_call('turn_on')
self.assertEqual( self.assertEqual({
{light.ATTR_BRIGHTNESS: 100, light.ATTR_BRIGHTNESS: 100,
light.ATTR_XY_COLOR: (.5119, .4147)}, light.ATTR_HS_COLOR: (prof_h, prof_s),
data) }, data)
# Test bad data # Test bad data
light.turn_on(self.hass) light.turn_on(self.hass)
@ -301,15 +303,16 @@ class TestLight(unittest.TestCase):
_, data = dev1.last_call('turn_on') _, data = dev1.last_call('turn_on')
self.assertEqual( self.assertEqual({
{light.ATTR_XY_COLOR: (.4, .6), light.ATTR_BRIGHTNESS: 100}, light.ATTR_HS_COLOR: (71.059, 100),
data) light.ATTR_BRIGHTNESS: 100
}, data)
async def test_intent_set_color(hass): async def test_intent_set_color(hass):
"""Test the set color intent.""" """Test the set color intent."""
hass.states.async_set('light.hello_2', 'off', { hass.states.async_set('light.hello_2', 'off', {
ATTR_SUPPORTED_FEATURES: light.SUPPORT_RGB_COLOR ATTR_SUPPORTED_FEATURES: light.SUPPORT_COLOR
}) })
hass.states.async_set('switch.hello', 'off') hass.states.async_set('switch.hello', 'off')
calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON) calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON)
@ -364,7 +367,7 @@ async def test_intent_set_color_and_brightness(hass):
"""Test the set color intent.""" """Test the set color intent."""
hass.states.async_set('light.hello_2', 'off', { hass.states.async_set('light.hello_2', 'off', {
ATTR_SUPPORTED_FEATURES: ( ATTR_SUPPORTED_FEATURES: (
light.SUPPORT_RGB_COLOR | light.SUPPORT_BRIGHTNESS) light.SUPPORT_COLOR | light.SUPPORT_BRIGHTNESS)
}) })
hass.states.async_set('switch.hello', 'off') hass.states.async_set('switch.hello', 'off')
calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON) calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON)

View File

@ -250,12 +250,12 @@ class TestLightMQTT(unittest.TestCase):
state = self.hass.states.get('light.test') state = self.hass.states.get('light.test')
self.assertEqual(STATE_ON, state.state) self.assertEqual(STATE_ON, state.state)
self.assertEqual([255, 255, 255], state.attributes.get('rgb_color')) self.assertEqual((255, 255, 255), state.attributes.get('rgb_color'))
self.assertEqual(255, state.attributes.get('brightness')) self.assertEqual(255, state.attributes.get('brightness'))
self.assertEqual(150, state.attributes.get('color_temp')) self.assertEqual(150, state.attributes.get('color_temp'))
self.assertEqual('none', state.attributes.get('effect')) self.assertEqual('none', state.attributes.get('effect'))
self.assertEqual(255, state.attributes.get('white_value')) self.assertEqual(255, state.attributes.get('white_value'))
self.assertEqual([1, 1], state.attributes.get('xy_color')) self.assertEqual((0.32, 0.336), state.attributes.get('xy_color'))
fire_mqtt_message(self.hass, 'test_light_rgb/status', '0') fire_mqtt_message(self.hass, 'test_light_rgb/status', '0')
self.hass.block_till_done() self.hass.block_till_done()
@ -303,7 +303,7 @@ class TestLightMQTT(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
light_state = self.hass.states.get('light.test') light_state = self.hass.states.get('light.test')
self.assertEqual([125, 125, 125], self.assertEqual((255, 255, 255),
light_state.attributes.get('rgb_color')) light_state.attributes.get('rgb_color'))
fire_mqtt_message(self.hass, 'test_light_rgb/xy/status', fire_mqtt_message(self.hass, 'test_light_rgb/xy/status',
@ -311,7 +311,7 @@ class TestLightMQTT(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
light_state = self.hass.states.get('light.test') light_state = self.hass.states.get('light.test')
self.assertEqual([0.675, 0.322], self.assertEqual((0.652, 0.343),
light_state.attributes.get('xy_color')) light_state.attributes.get('xy_color'))
def test_brightness_controlling_scale(self): def test_brightness_controlling_scale(self):
@ -458,11 +458,11 @@ class TestLightMQTT(unittest.TestCase):
state = self.hass.states.get('light.test') state = self.hass.states.get('light.test')
self.assertEqual(STATE_ON, state.state) self.assertEqual(STATE_ON, state.state)
self.assertEqual(50, state.attributes.get('brightness')) self.assertEqual(50, state.attributes.get('brightness'))
self.assertEqual([1, 2, 3], state.attributes.get('rgb_color')) self.assertEqual((0, 123, 255), state.attributes.get('rgb_color'))
self.assertEqual(300, state.attributes.get('color_temp')) self.assertEqual(300, state.attributes.get('color_temp'))
self.assertEqual('rainbow', state.attributes.get('effect')) self.assertEqual('rainbow', state.attributes.get('effect'))
self.assertEqual(75, state.attributes.get('white_value')) self.assertEqual(75, state.attributes.get('white_value'))
self.assertEqual([0.123, 0.123], state.attributes.get('xy_color')) self.assertEqual((0.14, 0.131), state.attributes.get('xy_color'))
def test_sending_mqtt_commands_and_optimistic(self): \ def test_sending_mqtt_commands_and_optimistic(self): \
# pylint: disable=invalid-name # pylint: disable=invalid-name
@ -516,18 +516,18 @@ class TestLightMQTT(unittest.TestCase):
self.mock_publish.async_publish.assert_has_calls([ self.mock_publish.async_publish.assert_has_calls([
mock.call('test_light_rgb/set', 'on', 2, False), mock.call('test_light_rgb/set', 'on', 2, False),
mock.call('test_light_rgb/rgb/set', '75,75,75', 2, False), mock.call('test_light_rgb/rgb/set', '50,50,50', 2, False),
mock.call('test_light_rgb/brightness/set', 50, 2, False), mock.call('test_light_rgb/brightness/set', 50, 2, False),
mock.call('test_light_rgb/white_value/set', 80, 2, False), mock.call('test_light_rgb/white_value/set', 80, 2, False),
mock.call('test_light_rgb/xy/set', '0.123,0.123', 2, False), mock.call('test_light_rgb/xy/set', '0.32,0.336', 2, False),
], any_order=True) ], any_order=True)
state = self.hass.states.get('light.test') state = self.hass.states.get('light.test')
self.assertEqual(STATE_ON, state.state) self.assertEqual(STATE_ON, state.state)
self.assertEqual((75, 75, 75), state.attributes['rgb_color']) self.assertEqual((255, 255, 255), state.attributes['rgb_color'])
self.assertEqual(50, state.attributes['brightness']) self.assertEqual(50, state.attributes['brightness'])
self.assertEqual(80, state.attributes['white_value']) self.assertEqual(80, state.attributes['white_value'])
self.assertEqual((0.123, 0.123), state.attributes['xy_color']) self.assertEqual((0.32, 0.336), state.attributes['xy_color'])
def test_sending_mqtt_rgb_command_with_template(self): def test_sending_mqtt_rgb_command_with_template(self):
"""Test the sending of RGB command with template.""" """Test the sending of RGB command with template."""
@ -554,12 +554,12 @@ class TestLightMQTT(unittest.TestCase):
self.mock_publish.async_publish.assert_has_calls([ self.mock_publish.async_publish.assert_has_calls([
mock.call('test_light_rgb/set', 'on', 0, False), mock.call('test_light_rgb/set', 'on', 0, False),
mock.call('test_light_rgb/rgb/set', '#ff8040', 0, False), mock.call('test_light_rgb/rgb/set', '#ff803f', 0, False),
], any_order=True) ], any_order=True)
state = self.hass.states.get('light.test') state = self.hass.states.get('light.test')
self.assertEqual(STATE_ON, state.state) self.assertEqual(STATE_ON, state.state)
self.assertEqual((255, 128, 64), state.attributes['rgb_color']) self.assertEqual((255, 128, 63), state.attributes['rgb_color'])
def test_show_brightness_if_only_command_topic(self): def test_show_brightness_if_only_command_topic(self):
"""Test the brightness if only a command topic is present.""" """Test the brightness if only a command topic is present."""
@ -679,7 +679,7 @@ class TestLightMQTT(unittest.TestCase):
state = self.hass.states.get('light.test') state = self.hass.states.get('light.test')
self.assertEqual(STATE_ON, state.state) self.assertEqual(STATE_ON, state.state)
self.assertEqual([1, 1], state.attributes.get('xy_color')) self.assertEqual((0.32, 0.336), state.attributes.get('xy_color'))
def test_on_command_first(self): def test_on_command_first(self):
"""Test on command being sent before brightness.""" """Test on command being sent before brightness."""
@ -799,7 +799,7 @@ class TestLightMQTT(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
self.mock_publish.async_publish.assert_has_calls([ self.mock_publish.async_publish.assert_has_calls([
mock.call('test_light/rgb', '75,75,75', 0, False), mock.call('test_light/rgb', '50,50,50', 0, False),
mock.call('test_light/bright', 50, 0, False) mock.call('test_light/bright', 50, 0, False)
], any_order=True) ], any_order=True)

View File

@ -180,7 +180,7 @@ class TestLightMQTTJSON(unittest.TestCase):
state = self.hass.states.get('light.test') state = self.hass.states.get('light.test')
self.assertEqual(STATE_OFF, state.state) self.assertEqual(STATE_OFF, state.state)
self.assertEqual(255, state.attributes.get(ATTR_SUPPORTED_FEATURES)) self.assertEqual(191, state.attributes.get(ATTR_SUPPORTED_FEATURES))
self.assertIsNone(state.attributes.get('rgb_color')) self.assertIsNone(state.attributes.get('rgb_color'))
self.assertIsNone(state.attributes.get('brightness')) self.assertIsNone(state.attributes.get('brightness'))
self.assertIsNone(state.attributes.get('color_temp')) self.assertIsNone(state.attributes.get('color_temp'))
@ -192,8 +192,7 @@ class TestLightMQTTJSON(unittest.TestCase):
# Turn on the light, full white # Turn on the light, full white
fire_mqtt_message(self.hass, 'test_light_rgb', fire_mqtt_message(self.hass, 'test_light_rgb',
'{"state":"ON",' '{"state":"ON",'
'"color":{"r":255,"g":255,"b":255,' '"color":{"r":255,"g":255,"b":255},'
'"x":0.123,"y":0.123},'
'"brightness":255,' '"brightness":255,'
'"color_temp":155,' '"color_temp":155,'
'"effect":"colorloop",' '"effect":"colorloop",'
@ -202,12 +201,12 @@ class TestLightMQTTJSON(unittest.TestCase):
state = self.hass.states.get('light.test') state = self.hass.states.get('light.test')
self.assertEqual(STATE_ON, state.state) self.assertEqual(STATE_ON, state.state)
self.assertEqual([255, 255, 255], state.attributes.get('rgb_color')) self.assertEqual((255, 255, 255), state.attributes.get('rgb_color'))
self.assertEqual(255, state.attributes.get('brightness')) self.assertEqual(255, state.attributes.get('brightness'))
self.assertEqual(155, state.attributes.get('color_temp')) self.assertEqual(155, state.attributes.get('color_temp'))
self.assertEqual('colorloop', state.attributes.get('effect')) self.assertEqual('colorloop', state.attributes.get('effect'))
self.assertEqual(150, state.attributes.get('white_value')) self.assertEqual(150, state.attributes.get('white_value'))
self.assertEqual([0.123, 0.123], state.attributes.get('xy_color')) self.assertEqual((0.32, 0.336), state.attributes.get('xy_color'))
# Turn the light off # Turn the light off
fire_mqtt_message(self.hass, 'test_light_rgb', '{"state":"OFF"}') fire_mqtt_message(self.hass, 'test_light_rgb', '{"state":"OFF"}')
@ -232,7 +231,7 @@ class TestLightMQTTJSON(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
light_state = self.hass.states.get('light.test') light_state = self.hass.states.get('light.test')
self.assertEqual([125, 125, 125], self.assertEqual((255, 255, 255),
light_state.attributes.get('rgb_color')) light_state.attributes.get('rgb_color'))
fire_mqtt_message(self.hass, 'test_light_rgb', fire_mqtt_message(self.hass, 'test_light_rgb',
@ -241,7 +240,7 @@ class TestLightMQTTJSON(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
light_state = self.hass.states.get('light.test') light_state = self.hass.states.get('light.test')
self.assertEqual([0.135, 0.135], self.assertEqual((0.141, 0.14),
light_state.attributes.get('xy_color')) light_state.attributes.get('xy_color'))
fire_mqtt_message(self.hass, 'test_light_rgb', fire_mqtt_message(self.hass, 'test_light_rgb',
@ -503,7 +502,7 @@ class TestLightMQTTJSON(unittest.TestCase):
state = self.hass.states.get('light.test') state = self.hass.states.get('light.test')
self.assertEqual(STATE_ON, state.state) self.assertEqual(STATE_ON, state.state)
self.assertEqual([255, 255, 255], state.attributes.get('rgb_color')) self.assertEqual((255, 255, 255), state.attributes.get('rgb_color'))
self.assertEqual(255, state.attributes.get('brightness')) self.assertEqual(255, state.attributes.get('brightness'))
self.assertEqual(255, state.attributes.get('white_value')) self.assertEqual(255, state.attributes.get('white_value'))
@ -516,7 +515,7 @@ class TestLightMQTTJSON(unittest.TestCase):
# Color should not have changed # Color should not have changed
state = self.hass.states.get('light.test') state = self.hass.states.get('light.test')
self.assertEqual(STATE_ON, state.state) self.assertEqual(STATE_ON, state.state)
self.assertEqual([255, 255, 255], state.attributes.get('rgb_color')) self.assertEqual((255, 255, 255), state.attributes.get('rgb_color'))
# Bad brightness values # Bad brightness values
fire_mqtt_message(self.hass, 'test_light_rgb', fire_mqtt_message(self.hass, 'test_light_rgb',

View File

@ -151,7 +151,7 @@ class TestLightMQTTTemplate(unittest.TestCase):
state = self.hass.states.get('light.test') state = self.hass.states.get('light.test')
self.assertEqual(STATE_ON, state.state) self.assertEqual(STATE_ON, state.state)
self.assertEqual([255, 128, 64], state.attributes.get('rgb_color')) self.assertEqual((255, 128, 63), state.attributes.get('rgb_color'))
self.assertEqual(255, state.attributes.get('brightness')) self.assertEqual(255, state.attributes.get('brightness'))
self.assertEqual(145, state.attributes.get('color_temp')) self.assertEqual(145, state.attributes.get('color_temp'))
self.assertEqual(123, state.attributes.get('white_value')) self.assertEqual(123, state.attributes.get('white_value'))
@ -185,7 +185,8 @@ class TestLightMQTTTemplate(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
light_state = self.hass.states.get('light.test') light_state = self.hass.states.get('light.test')
self.assertEqual([41, 42, 43], light_state.attributes.get('rgb_color')) self.assertEqual((243, 249, 255),
light_state.attributes.get('rgb_color'))
# change the white value # change the white value
fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,,134') fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,,134')
@ -254,7 +255,7 @@ class TestLightMQTTTemplate(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
self.mock_publish.async_publish.assert_called_once_with( self.mock_publish.async_publish.assert_called_once_with(
'test_light_rgb/set', 'on,50,,,75-75-75', 2, False) 'test_light_rgb/set', 'on,50,,,50-50-50', 2, False)
self.mock_publish.async_publish.reset_mock() self.mock_publish.async_publish.reset_mock()
# turn on the light with color temp and white val # turn on the light with color temp and white val
@ -267,7 +268,7 @@ class TestLightMQTTTemplate(unittest.TestCase):
# check the state # check the state
state = self.hass.states.get('light.test') state = self.hass.states.get('light.test')
self.assertEqual(STATE_ON, state.state) self.assertEqual(STATE_ON, state.state)
self.assertEqual((75, 75, 75), state.attributes['rgb_color']) self.assertEqual((255, 255, 255), state.attributes['rgb_color'])
self.assertEqual(50, state.attributes['brightness']) self.assertEqual(50, state.attributes['brightness'])
self.assertEqual(200, state.attributes['color_temp']) self.assertEqual(200, state.attributes['color_temp'])
self.assertEqual(139, state.attributes['white_value']) self.assertEqual(139, state.attributes['white_value'])
@ -387,7 +388,7 @@ class TestLightMQTTTemplate(unittest.TestCase):
self.assertEqual(STATE_ON, state.state) self.assertEqual(STATE_ON, state.state)
self.assertEqual(255, state.attributes.get('brightness')) self.assertEqual(255, state.attributes.get('brightness'))
self.assertEqual(215, state.attributes.get('color_temp')) self.assertEqual(215, state.attributes.get('color_temp'))
self.assertEqual([255, 255, 255], state.attributes.get('rgb_color')) self.assertEqual((255, 255, 255), state.attributes.get('rgb_color'))
self.assertEqual(222, state.attributes.get('white_value')) self.assertEqual(222, state.attributes.get('white_value'))
self.assertEqual('rainbow', state.attributes.get('effect')) self.assertEqual('rainbow', state.attributes.get('effect'))
@ -421,7 +422,7 @@ class TestLightMQTTTemplate(unittest.TestCase):
# color should not have changed # color should not have changed
state = self.hass.states.get('light.test') state = self.hass.states.get('light.test')
self.assertEqual([255, 255, 255], state.attributes.get('rgb_color')) self.assertEqual((255, 255, 255), state.attributes.get('rgb_color'))
# bad white value values # bad white value values
fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,,off,255-255-255') fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,,off,255-255-255')

View File

@ -4,9 +4,9 @@ from unittest.mock import patch, MagicMock
import homeassistant.components.zwave import homeassistant.components.zwave
from homeassistant.components.zwave import const from homeassistant.components.zwave import const
from homeassistant.components.light import ( from homeassistant.components.light import (
zwave, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_TRANSITION, zwave, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR, ATTR_TRANSITION,
SUPPORT_BRIGHTNESS, SUPPORT_TRANSITION, SUPPORT_RGB_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_TRANSITION, SUPPORT_COLOR, ATTR_WHITE_VALUE,
SUPPORT_COLOR_TEMP) SUPPORT_COLOR_TEMP, SUPPORT_WHITE_VALUE)
from tests.mock.zwave import ( from tests.mock.zwave import (
MockNode, MockValue, MockEntityValues, value_changed) MockNode, MockValue, MockEntityValues, value_changed)
@ -42,7 +42,7 @@ def test_get_device_detects_colorlight(mock_openzwave):
device = zwave.get_device(node=node, values=values, node_config={}) device = zwave.get_device(node=node, values=values, node_config={})
assert isinstance(device, zwave.ZwaveColorLight) assert isinstance(device, zwave.ZwaveColorLight)
assert device.supported_features == SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR assert device.supported_features == SUPPORT_BRIGHTNESS | SUPPORT_COLOR
def test_get_device_detects_zw098(mock_openzwave): def test_get_device_detects_zw098(mock_openzwave):
@ -54,7 +54,23 @@ def test_get_device_detects_zw098(mock_openzwave):
device = zwave.get_device(node=node, values=values, node_config={}) device = zwave.get_device(node=node, values=values, node_config={})
assert isinstance(device, zwave.ZwaveColorLight) assert isinstance(device, zwave.ZwaveColorLight)
assert device.supported_features == ( assert device.supported_features == (
SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR | SUPPORT_COLOR_TEMP) SUPPORT_BRIGHTNESS | SUPPORT_COLOR | SUPPORT_COLOR_TEMP)
def test_get_device_detects_rgbw_light(mock_openzwave):
"""Test get_device returns a color light."""
node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR])
value = MockValue(data=0, node=node)
color = MockValue(data='#0000000000', node=node)
color_channels = MockValue(data=0x1d, node=node)
values = MockLightValues(
primary=value, color=color, color_channels=color_channels)
device = zwave.get_device(node=node, values=values, node_config={})
device.value_added()
assert isinstance(device, zwave.ZwaveColorLight)
assert device.supported_features == (
SUPPORT_BRIGHTNESS | SUPPORT_COLOR | SUPPORT_WHITE_VALUE)
def test_dimmer_turn_on(mock_openzwave): def test_dimmer_turn_on(mock_openzwave):
@ -203,7 +219,7 @@ def test_dimmer_refresh_value(mock_openzwave):
assert device.brightness == 118 assert device.brightness == 118
def test_set_rgb_color(mock_openzwave): def test_set_hs_color(mock_openzwave):
"""Test setting zwave light color.""" """Test setting zwave light color."""
node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR])
value = MockValue(data=0, node=node) value = MockValue(data=0, node=node)
@ -216,12 +232,12 @@ def test_set_rgb_color(mock_openzwave):
assert color.data == '#0000000000' assert color.data == '#0000000000'
device.turn_on(**{ATTR_RGB_COLOR: (200, 150, 100)}) device.turn_on(**{ATTR_HS_COLOR: (30, 50)})
assert color.data == '#c896640000' assert color.data == '#ffbf7f0000'
def test_set_rgbw_color(mock_openzwave): def test_set_white_value(mock_openzwave):
"""Test setting zwave light color.""" """Test setting zwave light color."""
node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR])
value = MockValue(data=0, node=node) value = MockValue(data=0, node=node)
@ -234,9 +250,9 @@ def test_set_rgbw_color(mock_openzwave):
assert color.data == '#0000000000' assert color.data == '#0000000000'
device.turn_on(**{ATTR_RGB_COLOR: (200, 150, 100)}) device.turn_on(**{ATTR_WHITE_VALUE: 200})
assert color.data == '#c86400c800' assert color.data == '#ffffffc800'
def test_zw098_set_color_temp(mock_openzwave): def test_zw098_set_color_temp(mock_openzwave):
@ -273,7 +289,7 @@ def test_rgb_not_supported(mock_openzwave):
color_channels=color_channels) color_channels=color_channels)
device = zwave.get_device(node=node, values=values, node_config={}) device = zwave.get_device(node=node, values=values, node_config={})
assert device.rgb_color is None assert device.hs_color is None
def test_no_color_value(mock_openzwave): def test_no_color_value(mock_openzwave):
@ -283,7 +299,7 @@ def test_no_color_value(mock_openzwave):
values = MockLightValues(primary=value) values = MockLightValues(primary=value)
device = zwave.get_device(node=node, values=values, node_config={}) device = zwave.get_device(node=node, values=values, node_config={})
assert device.rgb_color is None assert device.hs_color is None
def test_no_color_channels_value(mock_openzwave): def test_no_color_channels_value(mock_openzwave):
@ -294,7 +310,7 @@ def test_no_color_channels_value(mock_openzwave):
values = MockLightValues(primary=value, color=color) values = MockLightValues(primary=value, color=color)
device = zwave.get_device(node=node, values=values, node_config={}) device = zwave.get_device(node=node, values=values, node_config={})
assert device.rgb_color is None assert device.hs_color is None
def test_rgb_value_changed(mock_openzwave): def test_rgb_value_changed(mock_openzwave):
@ -308,12 +324,12 @@ def test_rgb_value_changed(mock_openzwave):
color_channels=color_channels) color_channels=color_channels)
device = zwave.get_device(node=node, values=values, node_config={}) device = zwave.get_device(node=node, values=values, node_config={})
assert device.rgb_color == [0, 0, 0] assert device.hs_color == (0, 0)
color.data = '#c896640000' color.data = '#ffbf800000'
value_changed(color) value_changed(color)
assert device.rgb_color == [200, 150, 100] assert device.hs_color == (29.764, 49.804)
def test_rgbww_value_changed(mock_openzwave): def test_rgbww_value_changed(mock_openzwave):
@ -327,12 +343,14 @@ def test_rgbww_value_changed(mock_openzwave):
color_channels=color_channels) color_channels=color_channels)
device = zwave.get_device(node=node, values=values, node_config={}) device = zwave.get_device(node=node, values=values, node_config={})
assert device.rgb_color == [0, 0, 0] assert device.hs_color == (0, 0)
assert device.white_value == 0
color.data = '#c86400c800' color.data = '#c86400c800'
value_changed(color) value_changed(color)
assert device.rgb_color == [200, 150, 100] assert device.hs_color == (30, 100)
assert device.white_value == 200
def test_rgbcw_value_changed(mock_openzwave): def test_rgbcw_value_changed(mock_openzwave):
@ -346,12 +364,14 @@ def test_rgbcw_value_changed(mock_openzwave):
color_channels=color_channels) color_channels=color_channels)
device = zwave.get_device(node=node, values=values, node_config={}) device = zwave.get_device(node=node, values=values, node_config={})
assert device.rgb_color == [0, 0, 0] assert device.hs_color == (0, 0)
assert device.white_value == 0
color.data = '#c86400c800' color.data = '#c86400c800'
value_changed(color) value_changed(color)
assert device.rgb_color == [200, 150, 100] assert device.hs_color == (30, 100)
assert device.white_value == 200
def test_ct_value_changed(mock_openzwave): def test_ct_value_changed(mock_openzwave):

View File

@ -0,0 +1 @@
{"myprofile": {"id_map": {}}}

View File

@ -1,5 +1,5 @@
""" """
Provide a mock switch platform. Provide a mock light platform.
Call init before using it in your tests to ensure clean test data. Call init before using it in your tests to ensure clean test data.
""" """

View File

@ -10,26 +10,52 @@ class TestColorUtil(unittest.TestCase):
"""Test color util methods.""" """Test color util methods."""
# pylint: disable=invalid-name # pylint: disable=invalid-name
def test_color_RGB_to_xy(self): def test_color_RGB_to_xy_brightness(self):
"""Test color_RGB_to_xy.""" """Test color_RGB_to_xy_brightness."""
self.assertEqual((0, 0, 0), color_util.color_RGB_to_xy(0, 0, 0)) self.assertEqual((0, 0, 0),
color_util.color_RGB_to_xy_brightness(0, 0, 0))
self.assertEqual((0.32, 0.336, 255), self.assertEqual((0.32, 0.336, 255),
color_util.color_RGB_to_xy(255, 255, 255)) color_util.color_RGB_to_xy_brightness(255, 255, 255))
self.assertEqual((0.136, 0.04, 12), self.assertEqual((0.136, 0.04, 12),
color_util.color_RGB_to_xy(0, 0, 255)) color_util.color_RGB_to_xy_brightness(0, 0, 255))
self.assertEqual((0.172, 0.747, 170), self.assertEqual((0.172, 0.747, 170),
color_util.color_RGB_to_xy(0, 255, 0)) color_util.color_RGB_to_xy_brightness(0, 255, 0))
self.assertEqual((0.679, 0.321, 80), self.assertEqual((0.679, 0.321, 80),
color_util.color_RGB_to_xy_brightness(255, 0, 0))
self.assertEqual((0.679, 0.321, 17),
color_util.color_RGB_to_xy_brightness(128, 0, 0))
def test_color_RGB_to_xy(self):
"""Test color_RGB_to_xy."""
self.assertEqual((0, 0),
color_util.color_RGB_to_xy(0, 0, 0))
self.assertEqual((0.32, 0.336),
color_util.color_RGB_to_xy(255, 255, 255))
self.assertEqual((0.136, 0.04),
color_util.color_RGB_to_xy(0, 0, 255))
self.assertEqual((0.172, 0.747),
color_util.color_RGB_to_xy(0, 255, 0))
self.assertEqual((0.679, 0.321),
color_util.color_RGB_to_xy(255, 0, 0)) color_util.color_RGB_to_xy(255, 0, 0))
self.assertEqual((0.679, 0.321),
color_util.color_RGB_to_xy(128, 0, 0))
def test_color_xy_brightness_to_RGB(self): def test_color_xy_brightness_to_RGB(self):
"""Test color_RGB_to_xy.""" """Test color_xy_brightness_to_RGB."""
self.assertEqual((0, 0, 0), self.assertEqual((0, 0, 0),
color_util.color_xy_brightness_to_RGB(1, 1, 0)) color_util.color_xy_brightness_to_RGB(1, 1, 0))
self.assertEqual((194, 186, 169),
color_util.color_xy_brightness_to_RGB(.35, .35, 128))
self.assertEqual((255, 243, 222), self.assertEqual((255, 243, 222),
color_util.color_xy_brightness_to_RGB(.35, .35, 255)) color_util.color_xy_brightness_to_RGB(.35, .35, 255))
@ -42,6 +68,20 @@ class TestColorUtil(unittest.TestCase):
self.assertEqual((0, 63, 255), self.assertEqual((0, 63, 255),
color_util.color_xy_brightness_to_RGB(0, 0, 255)) color_util.color_xy_brightness_to_RGB(0, 0, 255))
def test_color_xy_to_RGB(self):
"""Test color_xy_to_RGB."""
self.assertEqual((255, 243, 222),
color_util.color_xy_to_RGB(.35, .35))
self.assertEqual((255, 0, 60),
color_util.color_xy_to_RGB(1, 0))
self.assertEqual((0, 255, 0),
color_util.color_xy_to_RGB(0, 1))
self.assertEqual((0, 63, 255),
color_util.color_xy_to_RGB(0, 0))
def test_color_RGB_to_hsv(self): def test_color_RGB_to_hsv(self):
"""Test color_RGB_to_hsv.""" """Test color_RGB_to_hsv."""
self.assertEqual((0, 0, 0), self.assertEqual((0, 0, 0),
@ -110,6 +150,23 @@ class TestColorUtil(unittest.TestCase):
self.assertEqual((225.176, 100), self.assertEqual((225.176, 100),
color_util.color_xy_to_hs(0, 0)) color_util.color_xy_to_hs(0, 0))
def test_color_hs_to_xy(self):
"""Test color_hs_to_xy."""
self.assertEqual((0.151, 0.343),
color_util.color_hs_to_xy(180, 100))
self.assertEqual((0.352, 0.329),
color_util.color_hs_to_xy(350, 12.5))
self.assertEqual((0.228, 0.476),
color_util.color_hs_to_xy(140, 50))
self.assertEqual((0.465, 0.33),
color_util.color_hs_to_xy(0, 40))
self.assertEqual((0.32, 0.336),
color_util.color_hs_to_xy(360, 0))
def test_rgb_hex_to_rgb_list(self): def test_rgb_hex_to_rgb_list(self):
"""Test rgb_hex_to_rgb_list.""" """Test rgb_hex_to_rgb_list."""
self.assertEqual([255, 255, 255], self.assertEqual([255, 255, 255],