Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 5 additions & 16 deletions homeassistant/components/alexa/smart_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,7 @@ def interfaces(self):
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
if supported & light.SUPPORT_BRIGHTNESS:
yield _AlexaBrightnessController(self.entity)
if supported & light.SUPPORT_RGB_COLOR:
yield _AlexaColorController(self.entity)
if supported & light.SUPPORT_XY_COLOR:
if supported & light.SUPPORT_COLOR:
yield _AlexaColorController(self.entity)
if supported & light.SUPPORT_COLOR_TEMP:
yield _AlexaColorTemperatureController(self.entity)
Expand Down Expand Up @@ -842,25 +840,16 @@ def async_api_adjust_brightness(hass, config, request, entity):
@asyncio.coroutine
def async_api_set_color(hass, config, request, entity):
"""Process a set color request."""
supported = entity.attributes.get(ATTR_SUPPORTED_FEATURES)
rgb = color_util.color_hsb_to_RGB(
float(request[API_PAYLOAD]['color']['hue']),
float(request[API_PAYLOAD]['color']['saturation']),
float(request[API_PAYLOAD]['color']['brightness'])
)

if supported & light.SUPPORT_RGB_COLOR > 0:
yield from hass.services.async_call(entity.domain, SERVICE_TURN_ON, {
ATTR_ENTITY_ID: entity.entity_id,
light.ATTR_RGB_COLOR: rgb,
}, 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)
yield from hass.services.async_call(entity.domain, SERVICE_TURN_ON, {
ATTR_ENTITY_ID: entity.entity_id,
light.ATTR_RGB_COLOR: rgb,
}, blocking=False)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to drop request[API_PAYLOAD]['color']['brightness'] because RGB now ignores brightness.

With the available input data I would expect hs_color and brightness to be used.


return api_message(request)

Expand Down
15 changes: 7 additions & 8 deletions homeassistant/components/google_assistant/trait.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ def supported(domain, features):
if domain != light.DOMAIN:
return False

return features & (light.SUPPORT_RGB_COLOR | light.SUPPORT_XY_COLOR)
return features & light.SUPPORT_COLOR

def sync_attributes(self):
"""Return color spectrum attributes for a sync request."""
Expand All @@ -254,13 +254,11 @@ def query_attributes(self):
"""Return color spectrum query attributes."""
response = {}

# No need to handle XY color because light component will always
# convert XY to RGB if possible (which is when brightness is available)
color_rgb = self.state.attributes.get(light.ATTR_RGB_COLOR)
if color_rgb is not None:
color_hs = self.state.attributes.get(light.ATTR_HS_COLOR)
if color_hs is not None:
response['color'] = {
'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
Expand All @@ -274,11 +272,12 @@ async def execute(self, hass, command, params):
"""Execute a color spectrum command."""
# Convert integer to hex format and left pad with 0's till length 6
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, {
ATTR_ENTITY_ID: self.state.entity_id,
light.ATTR_RGB_COLOR: color
light.ATTR_HS_COLOR: color
}, blocking=True)


Expand Down
28 changes: 11 additions & 17 deletions homeassistant/components/homekit/type_lights.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
import logging

from homeassistant.components.light import (
ATTR_RGB_COLOR, ATTR_BRIGHTNESS,
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR)
ATTR_HS_COLOR, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, SUPPORT_COLOR)
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 .accessories import HomeAccessory, add_preload_service
Expand Down Expand Up @@ -40,7 +38,7 @@ def __init__(self, hass, entity_id, name, *args, **kwargs):
.attributes.get(ATTR_SUPPORTED_FEATURES)
if self._features & SUPPORT_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_SATURATION)
self._hue = None
Expand Down Expand Up @@ -102,15 +100,15 @@ def set_hue(self, value):

def set_color(self):
"""Set color if call came from HomeKit."""
# Handle RGB Color
if self._features & SUPPORT_RGB_COLOR and self._flag[CHAR_HUE] and \
# Handle Color
if self._features & SUPPORT_COLOR and self._flag[CHAR_HUE] and \
self._flag[CHAR_SATURATION]:
color = color_hsv_to_RGB(self._hue, self._saturation, 100)
_LOGGER.debug('%s: Set rgb_color to %s', self._entity_id, color)
color = (self._hue, self._saturation)
_LOGGER.debug('%s: Set hs_color to %s', self._entity_id, color)
self._flag.update({
CHAR_HUE: False, CHAR_SATURATION: False, RGB_COLOR: True})
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):
"""Update light after state change."""
Expand All @@ -134,15 +132,11 @@ def update_state(self, entity_id=None, old_state=None, new_state=None):
should_callback=False)
self._flag[CHAR_BRIGHTNESS] = False

# Handle RGB Color
# Handle Color
if CHAR_SATURATION in self.chars and CHAR_HUE in self.chars:
rgb_color = new_state.attributes.get(ATTR_RGB_COLOR)
current_color = color_hsv_to_RGB(self._hue, self._saturation, 100)\
if self._hue and self._saturation else [None] * 3
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)
hue, saturation = new_state.attributes.get(ATTR_HS_COLOR)
if not self._flag[RGB_COLOR] and (
hue != self._hue or saturation != self._saturation):
self.char_hue.set_value(hue, should_callback=False)
self.char_saturation.set_value(saturation,
should_callback=False)
Expand Down
54 changes: 33 additions & 21 deletions homeassistant/components/light/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@
SUPPORT_COLOR_TEMP = 2
SUPPORT_EFFECT = 4
SUPPORT_FLASH = 8
SUPPORT_RGB_COLOR = 16
SUPPORT_COLOR = 16
SUPPORT_TRANSITION = 32
SUPPORT_XY_COLOR = 64
SUPPORT_WHITE_VALUE = 128

# Integer that represents transition time in seconds to make change.
Expand All @@ -51,6 +50,7 @@
# Lists holding color values
ATTR_RGB_COLOR = "rgb_color"
ATTR_XY_COLOR = "xy_color"
ATTR_HS_COLOR = "hs_color"
ATTR_COLOR_TEMP = "color_temp"
ATTR_KELVIN = "kelvin"
ATTR_MIN_MIREDS = "min_mireds"
Expand Down Expand Up @@ -86,8 +86,9 @@
PROP_TO_ATTR = {
'brightness': ATTR_BRIGHTNESS,
'color_temp': ATTR_COLOR_TEMP,
'rgb_color': ATTR_RGB_COLOR,
'xy_color': ATTR_XY_COLOR,
'min_mireds': ATTR_MIN_MIREDS,
'max_mireds': ATTR_MAX_MIREDS,
'hs_color': ATTR_HS_COLOR,
'white_value': ATTR_WHITE_VALUE,
'effect_list': ATTR_EFFECT_LIST,
'effect': ATTR_EFFECT,
Expand All @@ -111,6 +112,11 @@
vol.Exclusive(ATTR_XY_COLOR, COLOR_GROUP):
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):
Expand Down Expand Up @@ -149,22 +155,23 @@ def is_on(hass, entity_id=None):

@bind_hass
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,
profile=None, flash=None, effect=None, color_name=None):
"""Turn all or specified light on."""
hass.add_job(
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)


@callback
@bind_hass
def async_turn_on(hass, entity_id=None, transition=None, brightness=None,
brightness_pct=None, rgb_color=None, xy_color=None,
color_temp=None, kelvin=None, white_value=None,
profile=None, flash=None, effect=None, color_name=None):
hs_color=None, color_temp=None, kelvin=None,
white_value=None, profile=None, flash=None, effect=None,
color_name=None):
"""Turn all or specified light on."""
data = {
key: value for key, value in [
Expand All @@ -175,6 +182,7 @@ def async_turn_on(hass, entity_id=None, transition=None, brightness=None,
(ATTR_BRIGHTNESS_PCT, brightness_pct),
(ATTR_RGB_COLOR, rgb_color),
(ATTR_XY_COLOR, xy_color),
(ATTR_HS_COLOR, hs_color),
(ATTR_COLOR_TEMP, color_temp),
(ATTR_KELVIN, kelvin),
(ATTR_WHITE_VALUE, white_value),
Expand Down Expand Up @@ -254,6 +262,14 @@ def preprocess_turn_on_alternatives(params):
if brightness_pct is not None:
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):
"""Handle set color intents."""
Expand Down Expand Up @@ -281,7 +297,7 @@ async def async_handle(self, intent_obj):

if 'color' in slots:
intent.async_test_feature(
state, SUPPORT_RGB_COLOR, 'changing colors')
state, SUPPORT_COLOR, 'changing colors')
service_data[ATTR_RGB_COLOR] = slots['color']['value']
# Use original passed in value of the color because we don't have
# human readable names for that internally.
Expand Down Expand Up @@ -428,13 +444,8 @@ def brightness(self):
return None

@property
def xy_color(self):
"""Return the XY color value [float, float]."""
return None

@property
def rgb_color(self):
"""Return the RGB color value [int, int, int]."""
def hs_color(self):
"""Return the hue and saturation color value [float, float]."""
return None

@property
Expand Down Expand Up @@ -484,11 +495,12 @@ def state_attributes(self):
if value is not None:
data[attr] = value

if ATTR_RGB_COLOR not in data and ATTR_XY_COLOR in data and \
ATTR_BRIGHTNESS in data:
data[ATTR_RGB_COLOR] = color_util.color_xy_brightness_to_RGB(
data[ATTR_XY_COLOR][0], data[ATTR_XY_COLOR][1],
data[ATTR_BRIGHTNESS])
# Expose current color also as RGB and XY
if ATTR_HS_COLOR in data:
data[ATTR_RGB_COLOR] = color_util.color_hs_to_RGB(
*data[ATTR_HS_COLOR])
data[ATTR_XY_COLOR] = color_util.color_hs_to_xy(
*data[ATTR_HS_COLOR])

return data

Expand Down
19 changes: 11 additions & 8 deletions homeassistant/components/light/abode.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@

from homeassistant.components.abode import AbodeDevice, DOMAIN as ABODE_DOMAIN
from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_RGB_COLOR,
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, Light)
ATTR_BRIGHTNESS, ATTR_HS_COLOR,
SUPPORT_BRIGHTNESS, SUPPORT_COLOR, Light)
import homeassistant.util.color as color_util


DEPENDENCIES = ['abode']
Expand Down Expand Up @@ -44,10 +45,12 @@ class AbodeLight(AbodeDevice, Light):

def turn_on(self, **kwargs):
"""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.set_color(kwargs[ATTR_RGB_COLOR])
elif ATTR_BRIGHTNESS in kwargs and self._device.is_dimmable:
self._device.set_color(color_util.color_hs_to_RGB(
*kwargs[ATTR_HS_COLOR]))

if ATTR_BRIGHTNESS in kwargs and self._device.is_dimmable:
self._device.set_level(kwargs[ATTR_BRIGHTNESS])
else:
self._device.switch_on()
Expand All @@ -68,16 +71,16 @@ def brightness(self):
return self._device.brightness

@property
def rgb_color(self):
def hs_color(self):
"""Return the color of the light."""
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
def supported_features(self):
"""Flag supported features."""
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:
return SUPPORT_BRIGHTNESS

Expand Down
Loading