diff --git a/homeassistant/components/alexa/smart_home.py b/homeassistant/components/alexa/smart_home.py index 0d325534266c..5e5155b3db86 100644 --- a/homeassistant/components/alexa/smart_home.py +++ b/homeassistant/components/alexa/smart_home.py @@ -438,9 +438,7 @@ class _LightCapabilities(_AlexaEntity): 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) @@ -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) return api_message(request) diff --git a/homeassistant/components/google_assistant/trait.py b/homeassistant/components/google_assistant/trait.py index c78d70e21e64..2f60f226042b 100644 --- a/homeassistant/components/google_assistant/trait.py +++ b/homeassistant/components/google_assistant/trait.py @@ -243,7 +243,7 @@ class ColorSpectrumTrait(_Trait): 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.""" @@ -254,13 +254,11 @@ class ColorSpectrumTrait(_Trait): """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 @@ -274,11 +272,12 @@ class ColorSpectrumTrait(_Trait): """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) diff --git a/homeassistant/components/homekit/type_lights.py b/homeassistant/components/homekit/type_lights.py index db7172bef173..6cd606981108 100644 --- a/homeassistant/components/homekit/type_lights.py +++ b/homeassistant/components/homekit/type_lights.py @@ -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 @@ -40,7 +38,7 @@ class Light(HomeAccessory): .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 @@ -102,15 +100,15 @@ class Light(HomeAccessory): 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.""" @@ -134,15 +132,11 @@ class Light(HomeAccessory): 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) diff --git a/homeassistant/components/light/__init__.py b/homeassistant/components/light/__init__.py index a3a962a7e343..f03521947b77 100644 --- a/homeassistant/components/light/__init__.py +++ b/homeassistant/components/light/__init__.py @@ -40,9 +40,8 @@ SUPPORT_BRIGHTNESS = 1 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. @@ -51,6 +50,7 @@ ATTR_TRANSITION = "transition" # 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" @@ -86,8 +86,9 @@ LIGHT_PROFILES_FILE = "light_profiles.csv" 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, @@ -111,6 +112,11 @@ LIGHT_TURN_ON_SCHEMA = vol.Schema({ 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): @@ -149,13 +155,13 @@ 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) @@ -163,8 +169,9 @@ def turn_on(hass, entity_id=None, transition=None, brightness=None, @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 [ @@ -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), @@ -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.""" @@ -281,7 +297,7 @@ class SetIntentHandler(intent.IntentHandler): 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. @@ -428,13 +444,8 @@ class Light(ToggleEntity): 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 @@ -484,11 +495,12 @@ class Light(ToggleEntity): 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 diff --git a/homeassistant/components/light/abode.py b/homeassistant/components/light/abode.py index d3e79b386473..bfea19fc3fac 100644 --- a/homeassistant/components/light/abode.py +++ b/homeassistant/components/light/abode.py @@ -8,8 +8,9 @@ import logging 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'] @@ -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() @@ -68,16 +71,16 @@ class AbodeLight(AbodeDevice, Light): 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 diff --git a/homeassistant/components/light/blinksticklight.py b/homeassistant/components/light/blinksticklight.py index d6a6ef465a8f..18a6b4ae266d 100644 --- a/homeassistant/components/light/blinksticklight.py +++ b/homeassistant/components/light/blinksticklight.py @@ -9,9 +9,11 @@ import logging import voluptuous as vol 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 import homeassistant.helpers.config_validation as cv +import homeassistant.util.color as color_util REQUIREMENTS = ['blinkstick==1.1.8'] @@ -21,7 +23,7 @@ CONF_SERIAL = 'serial' DEFAULT_NAME = 'Blinkstick' -SUPPORT_BLINKSTICK = SUPPORT_RGB_COLOR +SUPPORT_BLINKSTICK = SUPPORT_BRIGHTNESS | SUPPORT_COLOR PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ 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) - add_devices([BlinkStickLight(stick, name)]) + add_devices([BlinkStickLight(stick, name)], True) class BlinkStickLight(Light): @@ -50,7 +52,8 @@ class BlinkStickLight(Light): self._stick = stick self._name = name self._serial = stick.get_serial() - self._rgb_color = stick.get_color() + self._hs_color = None + self._brightness = None @property def should_poll(self): @@ -63,14 +66,19 @@ class BlinkStickLight(Light): return self._name @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.""" - return self._rgb_color + return self._hs_color @property def is_on(self): - """Check whether any of the LEDs colors are non-zero.""" - return sum(self._rgb_color) > 0 + """Return True if entity is on.""" + return self._brightness > 0 @property def supported_features(self): @@ -79,18 +87,24 @@ class BlinkStickLight(Light): def update(self): """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): """Turn the device on.""" - if ATTR_RGB_COLOR in kwargs: - self._rgb_color = kwargs[ATTR_RGB_COLOR] + if ATTR_HS_COLOR in kwargs: + self._hs_color = kwargs[ATTR_HS_COLOR] + if ATTR_BRIGHTNESS in kwargs: + self._brightness = kwargs[ATTR_BRIGHTNESS] else: - self._rgb_color = [255, 255, 255] + self._brightness = 255 - self._stick.set_color(red=self._rgb_color[0], - green=self._rgb_color[1], - blue=self._rgb_color[2]) + rgb_color = color_util.color_hsv_to_RGB( + self._hs_color[0], self._hs_color[1], self._brightness / 255 * 100) + self._stick.set_color( + red=rgb_color[0], green=rgb_color[1], blue=rgb_color[2]) def turn_off(self, **kwargs): """Turn the device off.""" diff --git a/homeassistant/components/light/blinkt.py b/homeassistant/components/light/blinkt.py index db3171cf4cf4..97edd7c54d25 100644 --- a/homeassistant/components/light/blinkt.py +++ b/homeassistant/components/light/blinkt.py @@ -10,15 +10,16 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv 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) from homeassistant.const import CONF_NAME +import homeassistant.util.color as color_util REQUIREMENTS = ['blinkt==0.1.0'] _LOGGER = logging.getLogger(__name__) -SUPPORT_BLINKT = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR) +SUPPORT_BLINKT = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR) DEFAULT_NAME = 'blinkt' @@ -55,7 +56,7 @@ class BlinktLight(Light): self._index = index self._is_on = False self._brightness = 255 - self._rgb_color = [255, 255, 255] + self._hs_color = [0, 0] @property def name(self): @@ -71,12 +72,9 @@ class BlinktLight(Light): return self._brightness @property - def rgb_color(self): - """Read back the color of the light. - - Returns [r, g, b] list with values in range of 0-255. - """ - return self._rgb_color + def hs_color(self): + """Read back the color of the light.""" + return self._hs_color @property def supported_features(self): @@ -100,16 +98,17 @@ class BlinktLight(Light): def turn_on(self, **kwargs): """Instruct the light to turn on and set correct brightness & color.""" - if ATTR_RGB_COLOR in kwargs: - self._rgb_color = kwargs[ATTR_RGB_COLOR] + if ATTR_HS_COLOR in kwargs: + self._hs_color = kwargs[ATTR_HS_COLOR] if ATTR_BRIGHTNESS in kwargs: self._brightness = kwargs[ATTR_BRIGHTNESS] percent_bright = (self._brightness / 255) + rgb_color = color_util.color_hs_to_RGB(*self._hs_color) self._blinkt.set_pixel(self._index, - self._rgb_color[0], - self._rgb_color[1], - self._rgb_color[2], + rgb_color[0], + rgb_color[1], + rgb_color[2], percent_bright) self._blinkt.show() diff --git a/homeassistant/components/light/deconz.py b/homeassistant/components/light/deconz.py index a3e544341098..020f43d99354 100644 --- a/homeassistant/components/light/deconz.py +++ b/homeassistant/components/light/deconz.py @@ -7,12 +7,12 @@ https://home-assistant.io/components/light.deconz/ from homeassistant.components.deconz import ( DOMAIN as DATA_DECONZ, DATA_DECONZ_ID) from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR, - ATTR_TRANSITION, ATTR_XY_COLOR, EFFECT_COLORLOOP, FLASH_LONG, FLASH_SHORT, - SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH, - SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, SUPPORT_XY_COLOR, Light) + ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_HS_COLOR, + ATTR_TRANSITION, EFFECT_COLORLOOP, FLASH_LONG, FLASH_SHORT, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, + SUPPORT_FLASH, SUPPORT_TRANSITION, Light) from homeassistant.core import callback -from homeassistant.util.color import color_RGB_to_xy +import homeassistant.util.color as color_util DEPENDENCIES = ['deconz'] @@ -51,8 +51,7 @@ class DeconzLight(Light): self._features |= SUPPORT_COLOR_TEMP if self._light.xy is not None: - self._features |= SUPPORT_RGB_COLOR - self._features |= SUPPORT_XY_COLOR + self._features |= SUPPORT_COLOR if self._light.effect is not None: self._features |= SUPPORT_EFFECT @@ -124,14 +123,8 @@ class DeconzLight(Light): if ATTR_COLOR_TEMP in kwargs: data['ct'] = kwargs[ATTR_COLOR_TEMP] - if ATTR_RGB_COLOR in kwargs: - xyb = color_RGB_to_xy( - *(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_HS_COLOR in kwargs: + data['xy'] = color_util.color_hs_to_xy(*kwargs[ATTR_HS_COLOR]) if ATTR_BRIGHTNESS in kwargs: data['bri'] = kwargs[ATTR_BRIGHTNESS] diff --git a/homeassistant/components/light/demo.py b/homeassistant/components/light/demo.py index acc70a57ff47..05aecd542e2a 100644 --- a/homeassistant/components/light/demo.py +++ b/homeassistant/components/light/demo.py @@ -7,14 +7,13 @@ https://home-assistant.io/components/demo/ import random from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, - ATTR_RGB_COLOR, ATTR_WHITE_VALUE, ATTR_XY_COLOR, SUPPORT_BRIGHTNESS, - SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_RGB_COLOR, SUPPORT_WHITE_VALUE, - Light) + ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_HS_COLOR, + ATTR_WHITE_VALUE, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, + SUPPORT_COLOR, SUPPORT_WHITE_VALUE, Light) LIGHT_COLORS = [ - [237, 224, 33], - [255, 63, 111], + (56, 86), + (345, 75), ] LIGHT_EFFECT_LIST = ['rainbow', 'none'] @@ -22,7 +21,7 @@ LIGHT_EFFECT_LIST = ['rainbow', 'none'] LIGHT_TEMPS = [240, 380] 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): @@ -40,17 +39,16 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): class DemoLight(Light): """Representation of a demo light.""" - def __init__(self, unique_id, name, state, available=False, rgb=None, - ct=None, brightness=180, xy_color=(.5, .5), white=200, - effect_list=None, effect=None): + def __init__(self, unique_id, name, state, available=False, hs_color=None, + ct=None, brightness=180, white=200, effect_list=None, + effect=None): """Initialize the light.""" self._unique_id = unique_id self._name = name self._state = state - self._rgb = rgb + self._hs_color = hs_color self._ct = ct or random.choice(LIGHT_TEMPS) self._brightness = brightness - self._xy_color = xy_color self._white = white self._effect_list = effect_list self._effect = effect @@ -83,14 +81,9 @@ class DemoLight(Light): return self._brightness @property - def xy_color(self) -> tuple: - """Return the XY color value [float, float].""" - return self._xy_color - - @property - def rgb_color(self) -> tuple: - """Return the RBG color value.""" - return self._rgb + def hs_color(self) -> tuple: + """Return the hs color value.""" + return self._hs_color @property def color_temp(self) -> int: @@ -126,8 +119,8 @@ class DemoLight(Light): """Turn the light on.""" self._state = True - if ATTR_RGB_COLOR in kwargs: - self._rgb = kwargs[ATTR_RGB_COLOR] + if ATTR_HS_COLOR in kwargs: + self._hs_color = kwargs[ATTR_HS_COLOR] if ATTR_COLOR_TEMP in kwargs: self._ct = kwargs[ATTR_COLOR_TEMP] @@ -135,9 +128,6 @@ class DemoLight(Light): if ATTR_BRIGHTNESS in kwargs: self._brightness = kwargs[ATTR_BRIGHTNESS] - if ATTR_XY_COLOR in kwargs: - self._xy_color = kwargs[ATTR_XY_COLOR] - if ATTR_WHITE_VALUE in kwargs: self._white = kwargs[ATTR_WHITE_VALUE] diff --git a/homeassistant/components/light/flux_led.py b/homeassistant/components/light/flux_led.py index 2a239c9ae103..ed0836f14498 100644 --- a/homeassistant/components/light/flux_led.py +++ b/homeassistant/components/light/flux_led.py @@ -12,10 +12,11 @@ import voluptuous as vol from homeassistant.const import CONF_DEVICES, CONF_NAME, CONF_PROTOCOL 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, - SUPPORT_RGB_COLOR, Light, PLATFORM_SCHEMA) + SUPPORT_COLOR, Light, PLATFORM_SCHEMA) import homeassistant.helpers.config_validation as cv +import homeassistant.util.color as color_util REQUIREMENTS = ['flux_led==0.21'] @@ -27,7 +28,7 @@ ATTR_MODE = 'mode' DOMAIN = 'flux_led' SUPPORT_FLUX_LED = (SUPPORT_BRIGHTNESS | SUPPORT_EFFECT | - SUPPORT_RGB_COLOR) + SUPPORT_COLOR) MODE_RGB = 'rgb' MODE_RGBW = 'rgbw' @@ -183,9 +184,9 @@ class FluxLight(Light): return self._bulb.brightness @property - def rgb_color(self): + def hs_color(self): """Return the color property.""" - return self._bulb.getRgb() + return color_util.color_RGB_to_hs(*self._bulb.getRgb()) @property def supported_features(self): @@ -202,7 +203,8 @@ class FluxLight(Light): if not self.is_on: 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) effect = kwargs.get(ATTR_EFFECT) diff --git a/homeassistant/components/light/group.py b/homeassistant/components/light/group.py index b4a5e9dddfb6..f9ffbb4e0bf7 100644 --- a/homeassistant/components/light/group.py +++ b/homeassistant/components/light/group.py @@ -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.typing import HomeAssistantType, ConfigType from homeassistant.components.light import ( - SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, SUPPORT_COLOR_TEMP, - SUPPORT_TRANSITION, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_XY_COLOR, - SUPPORT_WHITE_VALUE, PLATFORM_SCHEMA, ATTR_BRIGHTNESS, ATTR_XY_COLOR, - ATTR_RGB_COLOR, ATTR_WHITE_VALUE, ATTR_COLOR_TEMP, ATTR_MIN_MIREDS, - ATTR_MAX_MIREDS, ATTR_EFFECT_LIST, ATTR_EFFECT, ATTR_FLASH, - ATTR_TRANSITION) + SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_TRANSITION, + SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_WHITE_VALUE, PLATFORM_SCHEMA, + ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_WHITE_VALUE, ATTR_COLOR_TEMP, + ATTR_MIN_MIREDS, ATTR_MAX_MIREDS, ATTR_EFFECT_LIST, ATTR_EFFECT, + ATTR_FLASH, ATTR_TRANSITION) import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) @@ -37,8 +36,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ }) SUPPORT_GROUP_LIGHT = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT - | SUPPORT_FLASH | SUPPORT_RGB_COLOR | SUPPORT_TRANSITION - | SUPPORT_XY_COLOR | SUPPORT_WHITE_VALUE) + | SUPPORT_FLASH | SUPPORT_COLOR | SUPPORT_TRANSITION + | SUPPORT_WHITE_VALUE) async def async_setup_platform(hass: HomeAssistantType, config: ConfigType, @@ -58,8 +57,7 @@ class LightGroup(light.Light): self._is_on = False # type: bool self._available = False # type: bool self._brightness = None # type: Optional[int] - self._xy_color = None # type: Optional[Tuple[float, float]] - self._rgb_color = None # type: Optional[Tuple[int, int, int]] + self._hs_color = None # type: Optional[Tuple[float, float]] self._color_temp = None # type: Optional[int] self._min_mireds = 154 # type: Optional[int] self._max_mireds = 500 # type: Optional[int] @@ -108,14 +106,9 @@ class LightGroup(light.Light): return self._brightness @property - def xy_color(self) -> Optional[Tuple[float, float]]: - """Return the XY color value [float, float].""" - return self._xy_color - - @property - def rgb_color(self) -> Optional[Tuple[int, int, int]]: - """Return the RGB color value [int, int, int].""" - return self._rgb_color + def hs_color(self) -> Optional[Tuple[float, float]]: + """Return the HS color value [float, float].""" + return self._hs_color @property def color_temp(self) -> Optional[int]: @@ -164,11 +157,8 @@ class LightGroup(light.Light): if ATTR_BRIGHTNESS in kwargs: data[ATTR_BRIGHTNESS] = kwargs[ATTR_BRIGHTNESS] - if ATTR_XY_COLOR in kwargs: - data[ATTR_XY_COLOR] = kwargs[ATTR_XY_COLOR] - - if ATTR_RGB_COLOR in kwargs: - data[ATTR_RGB_COLOR] = kwargs[ATTR_RGB_COLOR] + if ATTR_HS_COLOR in kwargs: + data[ATTR_HS_COLOR] = kwargs[ATTR_HS_COLOR] if ATTR_COLOR_TEMP in kwargs: 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._xy_color = _reduce_attribute( - on_states, ATTR_XY_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._hs_color = _reduce_attribute( + on_states, ATTR_HS_COLOR, reduce=_mean_tuple) self._white_value = _reduce_attribute(on_states, ATTR_WHITE_VALUE) diff --git a/homeassistant/components/light/hive.py b/homeassistant/components/light/hive.py index e57bdf2c0462..c4ecc5a9d2c6 100644 --- a/homeassistant/components/light/hive.py +++ b/homeassistant/components/light/hive.py @@ -4,13 +4,13 @@ Support for the Hive devices. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/light.hive/ """ -import colorsys from homeassistant.components.hive import DATA_HIVE from homeassistant.components.light import (ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, - ATTR_RGB_COLOR, + ATTR_HS_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, - SUPPORT_RGB_COLOR, Light) + SUPPORT_COLOR, Light) +import homeassistant.util.color as color_util DEPENDENCIES = ['hive'] @@ -75,10 +75,11 @@ class HiveDeviceLight(Light): return self.session.light.get_color_temp(self.node_id) @property - def rgb_color(self) -> tuple: - """Return the RBG color value.""" + def hs_color(self) -> tuple: + """Return the hs color value.""" 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 def is_on(self): @@ -99,15 +100,11 @@ class HiveDeviceLight(Light): if ATTR_COLOR_TEMP in kwargs: tmp_new_color_temp = kwargs.get(ATTR_COLOR_TEMP) new_color_temp = round(1000000 / tmp_new_color_temp) - if ATTR_RGB_COLOR in kwargs: - get_new_color = kwargs.get(ATTR_RGB_COLOR) - tmp_new_color = colorsys.rgb_to_hsv(get_new_color[0], - get_new_color[1], - get_new_color[2]) - 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) + if ATTR_HS_COLOR in kwargs: + get_new_color = kwargs.get(ATTR_HS_COLOR) + hue = int(get_new_color[0]) + saturation = int(get_new_color[1]) + new_color = (hue, saturation, 100) self.session.light.turn_on(self.node_id, self.light_device_type, new_brightness, new_color_temp, @@ -132,7 +129,7 @@ class HiveDeviceLight(Light): supported_features = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP) elif self.light_device_type == "colourtuneablelight": supported_features = ( - SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR) + SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_COLOR) return supported_features diff --git a/homeassistant/components/light/hue.py b/homeassistant/components/light/hue.py index c45d9c5c44ec..b1562aaba8f3 100644 --- a/homeassistant/components/light/hue.py +++ b/homeassistant/components/light/hue.py @@ -13,12 +13,11 @@ import async_timeout import homeassistant.components.hue as hue from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR, - ATTR_TRANSITION, ATTR_XY_COLOR, EFFECT_COLORLOOP, EFFECT_RANDOM, - FLASH_LONG, FLASH_SHORT, SUPPORT_BRIGHTNESS, - SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_RGB_COLOR, - SUPPORT_TRANSITION, SUPPORT_XY_COLOR, Light) -import homeassistant.util.color as color_util + ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, + ATTR_TRANSITION, ATTR_HS_COLOR, EFFECT_COLORLOOP, EFFECT_RANDOM, + FLASH_LONG, FLASH_SHORT, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, + SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_COLOR, SUPPORT_TRANSITION, + Light) DEPENDENCIES = ['hue'] SCAN_INTERVAL = timedelta(seconds=5) @@ -28,8 +27,7 @@ _LOGGER = logging.getLogger(__name__) SUPPORT_HUE_ON_OFF = (SUPPORT_FLASH | SUPPORT_TRANSITION) SUPPORT_HUE_DIMMABLE = (SUPPORT_HUE_ON_OFF | SUPPORT_BRIGHTNESS) SUPPORT_HUE_COLOR_TEMP = (SUPPORT_HUE_DIMMABLE | SUPPORT_COLOR_TEMP) -SUPPORT_HUE_COLOR = (SUPPORT_HUE_DIMMABLE | SUPPORT_EFFECT | - SUPPORT_RGB_COLOR | SUPPORT_XY_COLOR) +SUPPORT_HUE_COLOR = (SUPPORT_HUE_DIMMABLE | SUPPORT_EFFECT | SUPPORT_COLOR) SUPPORT_HUE_EXTENDED = (SUPPORT_HUE_COLOR_TEMP | SUPPORT_HUE_COLOR) SUPPORT_HUE = { @@ -228,11 +226,17 @@ class HueLight(Light): return self.light.state.get('bri') @property - def xy_color(self): - """Return the XY color value.""" + def hs_color(self): + """Return the hs color value.""" if self.is_group: - return self.light.action.get('xy') - return self.light.state.get('xy') + return ( + 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 def color_temp(self): @@ -272,25 +276,9 @@ class HueLight(Light): if ATTR_TRANSITION in kwargs: command['transitiontime'] = int(kwargs[ATTR_TRANSITION] * 10) - if ATTR_XY_COLOR in kwargs: - if self.is_osram: - color_hue, sat = color_util.color_xy_to_hs( - *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] + if ATTR_HS_COLOR in kwargs: + command['hue'] = int(kwargs[ATTR_HS_COLOR][0] / 360 * 65535) + command['sat'] = int(kwargs[ATTR_HS_COLOR][1] / 100 * 255) elif ATTR_COLOR_TEMP in kwargs: temp = kwargs[ATTR_COLOR_TEMP] command['ct'] = max(self.min_mireds, min(temp, self.max_mireds)) diff --git a/homeassistant/components/light/hyperion.py b/homeassistant/components/light/hyperion.py index 2057192299ec..e5a4bd18115b 100644 --- a/homeassistant/components/light/hyperion.py +++ b/homeassistant/components/light/hyperion.py @@ -11,10 +11,11 @@ import socket import voluptuous as vol from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_EFFECT, SUPPORT_BRIGHTNESS, - SUPPORT_RGB_COLOR, SUPPORT_EFFECT, Light, PLATFORM_SCHEMA) + ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_EFFECT, SUPPORT_BRIGHTNESS, + SUPPORT_COLOR, SUPPORT_EFFECT, Light, PLATFORM_SCHEMA) from homeassistant.const import (CONF_HOST, CONF_PORT, CONF_NAME) import homeassistant.helpers.config_validation as cv +import homeassistant.util.color as color_util _LOGGER = logging.getLogger(__name__) @@ -40,7 +41,7 @@ DEFAULT_EFFECT_LIST = ['HDMI', 'Cinema brighten lights', 'Cinema dim lights', 'Color traces', 'UDP multicast listener', '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({ vol.Required(CONF_HOST): cv.string, @@ -107,9 +108,9 @@ class Hyperion(Light): return self._brightness @property - def rgb_color(self): - """Return last RGB color value set.""" - return self._rgb_color + def hs_color(self): + """Return last color value set.""" + return color_util.color_RGB_to_hs(*self._rgb_color) @property def is_on(self): @@ -138,8 +139,8 @@ class Hyperion(Light): def turn_on(self, **kwargs): """Turn the lights on.""" - if ATTR_RGB_COLOR in kwargs: - rgb_color = kwargs[ATTR_RGB_COLOR] + if ATTR_HS_COLOR in kwargs: + rgb_color = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR]) elif self._rgb_mem == [0, 0, 0]: rgb_color = self._default_color else: diff --git a/homeassistant/components/light/iglo.py b/homeassistant/components/light/iglo.py index c7de8d8bede7..77e3972968cd 100644 --- a/homeassistant/components/light/iglo.py +++ b/homeassistant/components/light/iglo.py @@ -10,8 +10,8 @@ import math import voluptuous as vol from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_RGB_COLOR, - SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, SUPPORT_EFFECT, + ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_HS_COLOR, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR, SUPPORT_EFFECT, PLATFORM_SCHEMA, Light) from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT import homeassistant.helpers.config_validation as cv @@ -77,9 +77,9 @@ class IGloLamp(Light): self._lamp.min_kelvin)) @property - def rgb_color(self): - """Return the RGB value.""" - return self._lamp.state()['rgb'] + def hs_color(self): + """Return the hs value.""" + return color_util.color_RGB_to_hsv(*self._lamp.state()['rgb']) @property def effect(self): @@ -95,7 +95,7 @@ class IGloLamp(Light): def supported_features(self): """Flag supported features.""" return (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | - SUPPORT_RGB_COLOR | SUPPORT_EFFECT) + SUPPORT_COLOR | SUPPORT_EFFECT) @property def is_on(self): @@ -111,8 +111,8 @@ class IGloLamp(Light): self._lamp.brightness(brightness) return - if ATTR_RGB_COLOR in kwargs: - rgb = kwargs[ATTR_RGB_COLOR] + if ATTR_HS_COLOR in kwargs: + rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR]) self._lamp.rgb(*rgb) return diff --git a/homeassistant/components/light/knx.py b/homeassistant/components/light/knx.py index 83083e34bad1..18446951735b 100644 --- a/homeassistant/components/light/knx.py +++ b/homeassistant/components/light/knx.py @@ -9,11 +9,12 @@ import voluptuous as vol from homeassistant.components.knx import ATTR_DISCOVER_DEVICES, DATA_KNX from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_RGB_COLOR, PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS, - SUPPORT_RGB_COLOR, Light) + ATTR_BRIGHTNESS, ATTR_HS_COLOR, PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS, + SUPPORT_COLOR, Light) from homeassistant.const import CONF_NAME from homeassistant.core import callback import homeassistant.helpers.config_validation as cv +import homeassistant.util.color as color_util CONF_ADDRESS = 'address' CONF_STATE_ADDRESS = 'state_address' @@ -114,15 +115,10 @@ class KNXLight(Light): None @property - def xy_color(self): - """Return the XY color value [float, float].""" - return None - - @property - def rgb_color(self): - """Return the RBG color value.""" + def hs_color(self): + """Return the HS color value.""" if self.device.supports_color: - return self.device.current_color + return color_util.color_RGB_to_hs(*self.device.current_color) return None @property @@ -157,7 +153,7 @@ class KNXLight(Light): if self.device.supports_brightness: flags |= SUPPORT_BRIGHTNESS if self.device.supports_color: - flags |= SUPPORT_RGB_COLOR + flags |= SUPPORT_COLOR return flags async def async_turn_on(self, **kwargs): @@ -165,9 +161,10 @@ class KNXLight(Light): if ATTR_BRIGHTNESS in kwargs: if self.device.supports_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: - 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: await self.device.set_on() diff --git a/homeassistant/components/light/lifx.py b/homeassistant/components/light/lifx.py index 0bb65a78c6e6..dff5ccd42acf 100644 --- a/homeassistant/components/light/lifx.py +++ b/homeassistant/components/light/lifx.py @@ -16,10 +16,10 @@ import voluptuous as vol from homeassistant import util from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_COLOR_NAME, ATTR_COLOR_TEMP, - ATTR_EFFECT, ATTR_KELVIN, ATTR_RGB_COLOR, ATTR_TRANSITION, ATTR_XY_COLOR, - DOMAIN, LIGHT_TURN_ON_SCHEMA, PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS, - SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, - SUPPORT_XY_COLOR, VALID_BRIGHTNESS, VALID_BRIGHTNESS_PCT, Light, + ATTR_EFFECT, ATTR_HS_COLOR, ATTR_KELVIN, ATTR_RGB_COLOR, ATTR_TRANSITION, + ATTR_XY_COLOR, COLOR_GROUP, DOMAIN, LIGHT_TURN_ON_SCHEMA, PLATFORM_SCHEMA, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, + SUPPORT_TRANSITION, VALID_BRIGHTNESS, VALID_BRIGHTNESS_PCT, Light, preprocess_turn_on_alternatives) from homeassistant.const import ATTR_ENTITY_ID, EVENT_HOMEASSISTANT_STOP from homeassistant.core import callback @@ -87,11 +87,22 @@ LIFX_EFFECT_SCHEMA = vol.Schema({ LIFX_EFFECT_PULSE_SCHEMA = LIFX_EFFECT_SCHEMA.extend({ ATTR_BRIGHTNESS: VALID_BRIGHTNESS, ATTR_BRIGHTNESS_PCT: VALID_BRIGHTNESS_PCT, - ATTR_COLOR_NAME: cv.string, - ATTR_RGB_COLOR: vol.All(vol.ExactSequence((cv.byte, cv.byte, cv.byte)), - vol.Coerce(tuple)), - ATTR_COLOR_TEMP: vol.All(vol.Coerce(int), vol.Range(min=1)), - ATTR_KELVIN: vol.All(vol.Coerce(int), vol.Range(min=0)), + vol.Exclusive(ATTR_COLOR_NAME, COLOR_GROUP): cv.string, + vol.Exclusive(ATTR_RGB_COLOR, COLOR_GROUP): + vol.All(vol.ExactSequence((cv.byte, cv.byte, cv.byte)), + vol.Coerce(tuple)), + 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): + vol.All(vol.Coerce(int), vol.Range(min=0)), ATTR_PERIOD: vol.All(vol.Coerce(float), vol.Range(min=0.05)), ATTR_CYCLES: vol.All(vol.Coerce(float), vol.Range(min=1)), ATTR_MODE: vol.In(PULSE_MODES), @@ -168,16 +179,8 @@ def find_hsbk(**kwargs): preprocess_turn_on_alternatives(kwargs) - if ATTR_RGB_COLOR in kwargs: - hue, saturation, brightness = \ - 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]) + if ATTR_HS_COLOR in kwargs: + hue, saturation = kwargs[ATTR_HS_COLOR] hue = int(hue / 360 * 65535) saturation = int(saturation / 100 * 65535) kelvin = 3500 @@ -585,7 +588,7 @@ class LIFXColor(LIFXLight): def supported_features(self): """Flag supported features.""" support = super().supported_features - support |= SUPPORT_RGB_COLOR | SUPPORT_XY_COLOR + support |= SUPPORT_COLOR return support @property @@ -598,15 +601,12 @@ class LIFXColor(LIFXLight): ] @property - def rgb_color(self): - """Return the RGB value.""" - hue, sat, bri, _ = self.device.color - + def hs_color(self): + """Return the hs value.""" + hue, sat, _, _ = self.device.color hue = hue / 65535 * 360 sat = sat / 65535 * 100 - bri = bri / 65535 * 100 - - return color_util.color_hsv_to_RGB(hue, sat, bri) + return (hue, sat) class LIFXStrip(LIFXColor): diff --git a/homeassistant/components/light/lifx_legacy.py b/homeassistant/components/light/lifx_legacy.py index cf3dba848a89..490eeb6ecaba 100644 --- a/homeassistant/components/light/lifx_legacy.py +++ b/homeassistant/components/light/lifx_legacy.py @@ -7,14 +7,13 @@ not yet support Windows. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/light.lifx/ """ -import colorsys import logging import voluptuous as vol from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_TRANSITION, - SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, + ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR, ATTR_TRANSITION, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR, SUPPORT_TRANSITION, Light, PLATFORM_SCHEMA) from homeassistant.helpers.event import track_time_change from homeassistant.util.color import ( @@ -37,7 +36,7 @@ TEMP_MAX_HASS = 500 TEMP_MIN = 2500 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) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -129,17 +128,6 @@ class LIFX(object): 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): """Representation of a LIFX light.""" @@ -170,11 +158,9 @@ class LIFXLight(Light): return self._ip @property - def rgb_color(self): - """Return the RGB value.""" - _LOGGER.debug( - "rgb_color: [%d %d %d]", self._rgb[0], self._rgb[1], self._rgb[2]) - return self._rgb + def hs_color(self): + """Return the hs value.""" + return (self._hue / 65535 * 360, self._sat / 65535 * 100) @property def brightness(self): @@ -209,13 +195,13 @@ class LIFXLight(Light): else: fade = 0 - if ATTR_RGB_COLOR in kwargs: - hue, saturation, brightness = \ - convert_rgb_to_hsv(kwargs[ATTR_RGB_COLOR]) + if ATTR_HS_COLOR in kwargs: + hue, saturation = kwargs[ATTR_HS_COLOR] + hue = hue / 360 * 65535 + saturation = saturation / 100 * 65535 else: hue = self._hue saturation = self._sat - brightness = self._bri if ATTR_BRIGHTNESS in kwargs: brightness = kwargs[ATTR_BRIGHTNESS] * (BYTE_MAX + 1) @@ -265,16 +251,3 @@ class LIFXLight(Light): self._sat = sat self._bri = bri 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] diff --git a/homeassistant/components/light/limitlessled.py b/homeassistant/components/light/limitlessled.py index f011792a15c5..5a6a0a349596 100644 --- a/homeassistant/components/light/limitlessled.py +++ b/homeassistant/components/light/limitlessled.py @@ -12,12 +12,13 @@ import voluptuous as vol from homeassistant.const import ( CONF_NAME, CONF_HOST, CONF_PORT, CONF_TYPE, STATE_ON) 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, 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 -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 REQUIREMENTS = ['limitlessled==1.1.0'] @@ -40,19 +41,19 @@ LED_TYPE = ['rgbw', 'rgbww', 'white', 'bridge-led', 'dimmer'] 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_TRANSITION) SUPPORT_LIMITLESSLED_DIMMER = (SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION) SUPPORT_LIMITLESSLED_RGB = (SUPPORT_BRIGHTNESS | SUPPORT_EFFECT | - SUPPORT_FLASH | SUPPORT_RGB_COLOR | + SUPPORT_FLASH | SUPPORT_COLOR | SUPPORT_TRANSITION) SUPPORT_LIMITLESSLED_RGBWW = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT | SUPPORT_FLASH | - SUPPORT_RGB_COLOR | SUPPORT_TRANSITION) + SUPPORT_COLOR | SUPPORT_TRANSITION) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_BRIDGES): vol.All(cv.ensure_list, [ @@ -239,7 +240,7 @@ class LimitlessLEDGroup(Light): return self._temperature @property - def rgb_color(self): + def hs_color(self): """Return the color property.""" return self._color @@ -282,17 +283,17 @@ class LimitlessLEDGroup(Light): self._brightness = kwargs[ATTR_BRIGHTNESS] args['brightness'] = self.limitlessled_brightness() - if ATTR_RGB_COLOR in kwargs and self._supported & SUPPORT_RGB_COLOR: - self._color = kwargs[ATTR_RGB_COLOR] + if ATTR_HS_COLOR in kwargs and self._supported & SUPPORT_COLOR: + self._color = kwargs[ATTR_HS_COLOR] # White is a special case. - if min(self._color) > 256 - RGB_BOUNDARY: + if self._color[1] < MIN_SATURATION: pipeline.white() self._color = WHITE else: args['color'] = self.limitlessled_color() if ATTR_COLOR_TEMP in kwargs: - if self._supported & SUPPORT_RGB_COLOR: + if self._supported & SUPPORT_COLOR: pipeline.white() self._color = WHITE if self._supported & SUPPORT_COLOR_TEMP: @@ -333,6 +334,6 @@ class LimitlessLEDGroup(Light): return self._brightness / 255 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 - return Color(*tuple(self._color)) + return Color(color_hs_to_RGB(*tuple(self._color))) diff --git a/homeassistant/components/light/mqtt.py b/homeassistant/components/light/mqtt.py index f97e37127b1b..a0534ba4e950 100644 --- a/homeassistant/components/light/mqtt.py +++ b/homeassistant/components/light/mqtt.py @@ -12,10 +12,9 @@ import voluptuous as vol from homeassistant.core import callback import homeassistant.components.mqtt as mqtt from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_RGB_COLOR, - ATTR_WHITE_VALUE, ATTR_XY_COLOR, Light, SUPPORT_BRIGHTNESS, - SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_RGB_COLOR, - SUPPORT_WHITE_VALUE, SUPPORT_XY_COLOR) + ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_HS_COLOR, + ATTR_WHITE_VALUE, Light, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, + SUPPORT_EFFECT, SUPPORT_COLOR, SUPPORT_WHITE_VALUE) from homeassistant.const import ( CONF_BRIGHTNESS, CONF_COLOR_TEMP, CONF_EFFECT, CONF_NAME, 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, MqttAvailability) import homeassistant.helpers.config_validation as cv +import homeassistant.util.color as color_util _LOGGER = logging.getLogger(__name__) @@ -191,14 +191,13 @@ class MqttLight(MqttAvailability, Light): self._on_command_type = on_command_type self._state = False self._brightness = None - self._rgb = None + self._hs = None self._color_temp = None self._effect = None self._white_value = None - self._xy = None self._supported_features = 0 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 |= ( topic[CONF_BRIGHTNESS_COMMAND_TOPIC] is not None and SUPPORT_BRIGHTNESS) @@ -212,7 +211,7 @@ class MqttLight(MqttAvailability, Light): topic[CONF_WHITE_VALUE_COMMAND_TOPIC] is not None and SUPPORT_WHITE_VALUE) 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 def async_added_to_hass(self): @@ -263,19 +262,18 @@ class MqttLight(MqttAvailability, Light): @callback def rgb_received(topic, payload, qos): """Handle new MQTT messages for RGB.""" - self._rgb = [int(val) for val in - templates[CONF_RGB](payload).split(',')] + rgb = [int(val) for val in + templates[CONF_RGB](payload).split(',')] + self._hs = color_util.color_RGB_to_hs(*rgb) self.async_schedule_update_ha_state() if self._topic[CONF_RGB_STATE_TOPIC] is not None: yield from mqtt.async_subscribe( self.hass, self._topic[CONF_RGB_STATE_TOPIC], rgb_received, self._qos) - self._rgb = [255, 255, 255] + self._hs = (0, 0) if self._topic[CONF_RGB_COMMAND_TOPIC] is not None: - self._rgb = [255, 255, 255] - else: - self._rgb = None + self._hs = (0, 0) @callback def color_temp_received(topic, payload, qos): @@ -330,19 +328,18 @@ class MqttLight(MqttAvailability, Light): @callback def xy_received(topic, payload, qos): """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(',')] + self._hs = color_util.color_xy_to_hs(*xy_color) self.async_schedule_update_ha_state() if self._topic[CONF_XY_STATE_TOPIC] is not None: yield from mqtt.async_subscribe( self.hass, self._topic[CONF_XY_STATE_TOPIC], xy_received, self._qos) - self._xy = [1, 1] + self._hs = (0, 0) if self._topic[CONF_XY_COMMAND_TOPIC] is not None: - self._xy = [1, 1] - else: - self._xy = None + self._hs = (0, 0) @property def brightness(self): @@ -350,9 +347,9 @@ class MqttLight(MqttAvailability, Light): return self._brightness @property - def rgb_color(self): - """Return the RGB color value.""" - return self._rgb + def hs_color(self): + """Return the hs color value.""" + return self._hs @property def color_temp(self): @@ -364,11 +361,6 @@ class MqttLight(MqttAvailability, Light): """Return the white property.""" return self._white_value - @property - def xy_color(self): - """Return the RGB color value.""" - return self._xy - @property def should_poll(self): """No polling needed for a MQTT light.""" @@ -426,24 +418,43 @@ class MqttLight(MqttAvailability, Light): kwargs[ATTR_BRIGHTNESS] = self._brightness if \ 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: + 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] if tpl: - colors = ('red', 'green', 'blue') - variables = {key: val for key, val in - zip(colors, kwargs[ATTR_RGB_COLOR])} - rgb_color_str = tpl.async_render(variables) + rgb_color_str = tpl.async_render({ + 'red': rgb[0], + 'green': rgb[1], + 'blue': rgb[2], + }) else: - rgb_color_str = '{},{},{}'.format(*kwargs[ATTR_RGB_COLOR]) + rgb_color_str = '{},{},{}'.format(*rgb) mqtt.async_publish( self.hass, self._topic[CONF_RGB_COMMAND_TOPIC], rgb_color_str, self._qos, self._retain) 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 if ATTR_BRIGHTNESS in kwargs and \ @@ -493,18 +504,6 @@ class MqttLight(MqttAvailability, Light): self._white_value = kwargs[ATTR_WHITE_VALUE] 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': mqtt.async_publish(self.hass, self._topic[CONF_COMMAND_TOPIC], self._payload['on'], self._qos, self._retain) diff --git a/homeassistant/components/light/mqtt_json.py b/homeassistant/components/light/mqtt_json.py index 19747b89ca0b..25212e45c601 100644 --- a/homeassistant/components/light/mqtt_json.py +++ b/homeassistant/components/light/mqtt_json.py @@ -13,10 +13,10 @@ from homeassistant.core import callback import homeassistant.components.mqtt as mqtt from homeassistant.components.light import ( 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, - SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_RGB_COLOR, - SUPPORT_TRANSITION, SUPPORT_WHITE_VALUE, SUPPORT_XY_COLOR) + SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_COLOR, + SUPPORT_TRANSITION, SUPPORT_WHITE_VALUE) from homeassistant.components.light.mqtt import CONF_BRIGHTNESS_SCALE from homeassistant.const import ( 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, MqttAvailability) import homeassistant.helpers.config_validation as cv +import homeassistant.util.color as color_util _LOGGER = logging.getLogger(__name__) @@ -143,31 +144,26 @@ class MqttJson(MqttAvailability, Light): else: self._effect = None - if rgb: - self._rgb = [0, 0, 0] + if rgb or xy: + self._hs = [0, 0] else: - self._rgb = None + self._hs = None if white_value: self._white_value = 255 else: self._white_value = None - if xy: - self._xy = [1, 1] - else: - self._xy = None - self._flash_times = flash_times self._brightness_scale = brightness_scale 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 |= (color_temp and SUPPORT_COLOR_TEMP) self._supported_features |= (effect and SUPPORT_EFFECT) 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 def async_added_to_hass(self): @@ -184,17 +180,26 @@ class MqttJson(MqttAvailability, Light): elif values['state'] == 'OFF': self._state = False - if self._rgb is not None: + if self._hs is not None: try: red = int(values['color']['r']) green = int(values['color']['g']) blue = int(values['color']['b']) - self._rgb = [red, green, blue] + self._hs = color_util.color_RGB_to_hs(red, green, blue) except KeyError: pass except ValueError: _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: try: @@ -230,17 +235,6 @@ class MqttJson(MqttAvailability, Light): except ValueError: _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() if self._topic[CONF_STATE_TOPIC] is not None: @@ -269,20 +263,15 @@ class MqttJson(MqttAvailability, Light): return self._effect_list @property - def rgb_color(self): - """Return the RGB color value.""" - return self._rgb + def hs_color(self): + """Return the hs color value.""" + return self._hs @property def white_value(self): """Return the white property.""" return self._white_value - @property - def xy_color(self): - """Return the XY color value.""" - return self._xy - @property def should_poll(self): """No polling needed for a MQTT light.""" @@ -318,15 +307,23 @@ class MqttJson(MqttAvailability, Light): 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'] = { - 'r': kwargs[ATTR_RGB_COLOR][0], - 'g': kwargs[ATTR_RGB_COLOR][1], - 'b': kwargs[ATTR_RGB_COLOR][2] + 'r': rgb[0], + 'g': rgb[1], + 'b': rgb[2], + 'x': xy_color[0], + 'y': xy_color[1], } if self._optimistic: - self._rgb = kwargs[ATTR_RGB_COLOR] + self._hs = kwargs[ATTR_HS_COLOR] should_update = True if ATTR_FLASH in kwargs: @@ -370,16 +367,6 @@ class MqttJson(MqttAvailability, Light): self._white_value = kwargs[ATTR_WHITE_VALUE] 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( self.hass, self._topic[CONF_COMMAND_TOPIC], json.dumps(message), self._qos, self._retain) diff --git a/homeassistant/components/light/mqtt_template.py b/homeassistant/components/light/mqtt_template.py index de0f6d934c6b..06a94cd23b4e 100644 --- a/homeassistant/components/light/mqtt_template.py +++ b/homeassistant/components/light/mqtt_template.py @@ -12,15 +12,16 @@ from homeassistant.core import callback import homeassistant.components.mqtt as mqtt from homeassistant.components.light import ( 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_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.components.mqtt import ( CONF_AVAILABILITY_TOPIC, CONF_STATE_TOPIC, CONF_COMMAND_TOPIC, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS, CONF_RETAIN, MqttAvailability) import homeassistant.helpers.config_validation as cv +import homeassistant.util.color as color_util _LOGGER = logging.getLogger(__name__) @@ -142,9 +143,9 @@ class MqttTemplate(MqttAvailability, Light): if (self._templates[CONF_RED_TEMPLATE] is not None and self._templates[CONF_GREEN_TEMPLATE] is not None and self._templates[CONF_BLUE_TEMPLATE] is not None): - self._rgb = [0, 0, 0] + self._hs = [0, 0] else: - self._rgb = None + self._hs = None self._effect = None for tpl in self._templates.values(): @@ -186,17 +187,18 @@ class MqttTemplate(MqttAvailability, Light): except ValueError: _LOGGER.warning("Invalid color temperature value received") - if self._rgb is not None: + if self._hs is not None: try: - self._rgb[0] = int( + red = int( self._templates[CONF_RED_TEMPLATE]. async_render_with_possible_json_value(payload)) - self._rgb[1] = int( + green = int( self._templates[CONF_GREEN_TEMPLATE]. async_render_with_possible_json_value(payload)) - self._rgb[2] = int( + blue = int( self._templates[CONF_BLUE_TEMPLATE]. async_render_with_possible_json_value(payload)) + self._hs = color_util.color_RGB_to_hs(red, green, blue) except ValueError: _LOGGER.warning("Invalid color value received") @@ -236,9 +238,9 @@ class MqttTemplate(MqttAvailability, Light): return self._color_temp @property - def rgb_color(self): - """Return the RGB color value [int, int, int].""" - return self._rgb + def hs_color(self): + """Return the hs color value [int, int].""" + return self._hs @property def white_value(self): @@ -300,13 +302,18 @@ class MqttTemplate(MqttAvailability, Light): if self._optimistic: self._color_temp = kwargs[ATTR_COLOR_TEMP] - if ATTR_RGB_COLOR in kwargs: - values['red'] = kwargs[ATTR_RGB_COLOR][0] - values['green'] = kwargs[ATTR_RGB_COLOR][1] - values['blue'] = kwargs[ATTR_RGB_COLOR][2] + 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) + values['red'] = rgb[0] + values['green'] = rgb[1] + values['blue'] = rgb[2] if self._optimistic: - self._rgb = kwargs[ATTR_RGB_COLOR] + self._hs = kwargs[ATTR_HS_COLOR] if ATTR_WHITE_VALUE in kwargs: values['white_value'] = int(kwargs[ATTR_WHITE_VALUE]) @@ -360,8 +367,8 @@ class MqttTemplate(MqttAvailability, Light): features = (SUPPORT_FLASH | SUPPORT_TRANSITION) if self._brightness is not None: features = features | SUPPORT_BRIGHTNESS - if self._rgb is not None: - features = features | SUPPORT_RGB_COLOR + if self._hs is not None: + features = features | SUPPORT_COLOR if self._effect_list is not None: features = features | SUPPORT_EFFECT if self._color_temp is not None: diff --git a/homeassistant/components/light/mysensors.py b/homeassistant/components/light/mysensors.py index a37553017e7e..26e20ff387d2 100644 --- a/homeassistant/components/light/mysensors.py +++ b/homeassistant/components/light/mysensors.py @@ -6,12 +6,13 @@ https://home-assistant.io/components/light.mysensors/ """ from homeassistant.components import mysensors from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_WHITE_VALUE, DOMAIN, - SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, SUPPORT_WHITE_VALUE, Light) + ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_WHITE_VALUE, DOMAIN, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_WHITE_VALUE, Light) from homeassistant.const import STATE_OFF, STATE_ON 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) @@ -35,7 +36,7 @@ class MySensorsLight(mysensors.MySensorsEntity, Light): super().__init__(*args) self._state = None self._brightness = None - self._rgb = None + self._hs = None self._white = None @property @@ -44,9 +45,9 @@ class MySensorsLight(mysensors.MySensorsEntity, Light): return self._brightness @property - def rgb_color(self): - """Return the RGB color value [int, int, int].""" - return self._rgb + def hs_color(self): + """Return the hs color value [int, int].""" + return self._hs @property def white_value(self): @@ -103,10 +104,10 @@ class MySensorsLight(mysensors.MySensorsEntity, Light): def _turn_on_rgb_and_w(self, hex_template, **kwargs): """Turn on RGB or RGBW child device.""" - rgb = self._rgb + rgb = color_util.color_hs_to_RGB(*self._hs) white = self._white 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) if new_rgb is None and new_white is None: @@ -126,7 +127,7 @@ class MySensorsLight(mysensors.MySensorsEntity, Light): if self.gateway.optimistic: # optimistically assume that light has changed state - self._rgb = rgb + self._hs = color_util.color_RGB_to_hs(*rgb) self._white = white self._values[self.value_type] = hex_color @@ -160,7 +161,7 @@ class MySensorsLight(mysensors.MySensorsEntity, Light): color_list = rgb_hex_to_rgb_list(value) if len(color_list) > 3: self._white = color_list.pop() - self._rgb = color_list + self._hs = color_util.color_RGB_to_hs(*color_list) class MySensorsLightDimmer(MySensorsLight): diff --git a/homeassistant/components/light/mystrom.py b/homeassistant/components/light/mystrom.py index 9f049dd2e8aa..d9312e6aadca 100644 --- a/homeassistant/components/light/mystrom.py +++ b/homeassistant/components/light/mystrom.py @@ -11,10 +11,9 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.components.light import ( Light, PLATFORM_SCHEMA, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, - SUPPORT_EFFECT, ATTR_EFFECT, SUPPORT_FLASH, SUPPORT_RGB_COLOR, - ATTR_RGB_COLOR) + SUPPORT_EFFECT, ATTR_EFFECT, SUPPORT_FLASH, SUPPORT_COLOR, + ATTR_HS_COLOR) 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'] @@ -24,7 +23,7 @@ DEFAULT_NAME = 'myStrom bulb' SUPPORT_MYSTROM = ( SUPPORT_BRIGHTNESS | SUPPORT_EFFECT | SUPPORT_FLASH | - SUPPORT_RGB_COLOR + SUPPORT_COLOR ) EFFECT_RAINBOW = 'rainbow' @@ -91,9 +90,9 @@ class MyStromLight(Light): return self._brightness @property - def rgb_color(self): + def hs_color(self): """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 def available(self) -> bool: @@ -117,12 +116,8 @@ class MyStromLight(Light): brightness = kwargs.get(ATTR_BRIGHTNESS, 255) effect = kwargs.get(ATTR_EFFECT) - if ATTR_RGB_COLOR in kwargs: - # New color, compute from RGB - color_h, color_s, brightness = color_RGB_to_hsv( - *kwargs[ATTR_RGB_COLOR] - ) - brightness = brightness / 100 * 255 + if ATTR_HS_COLOR in kwargs: + color_h, color_s = kwargs[ATTR_HS_COLOR] elif ATTR_BRIGHTNESS in kwargs: # Brightness update, keep color color_h, color_s = self._color_h, self._color_s diff --git a/homeassistant/components/light/osramlightify.py b/homeassistant/components/light/osramlightify.py index ff526c4783d9..2c44620cacaa 100644 --- a/homeassistant/components/light/osramlightify.py +++ b/homeassistant/components/light/osramlightify.py @@ -13,15 +13,15 @@ import voluptuous as vol from homeassistant import util from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_RGB_COLOR, - ATTR_TRANSITION, ATTR_XY_COLOR, EFFECT_RANDOM, PLATFORM_SCHEMA, - SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_RGB_COLOR, - SUPPORT_TRANSITION, SUPPORT_XY_COLOR, Light) + ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_HS_COLOR, + ATTR_TRANSITION, EFFECT_RANDOM, PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS, + SUPPORT_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_TRANSITION, + Light) from homeassistant.const import CONF_HOST import homeassistant.helpers.config_validation as cv from homeassistant.util.color import ( - color_temperature_kelvin_to_mired, color_temperature_mired_to_kelvin, - color_xy_brightness_to_RGB) + color_temperature_kelvin_to_mired, color_temperature_mired_to_kelvin) +import homeassistant.util.color as color_util 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) SUPPORT_OSRAMLIGHTIFY = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | - SUPPORT_EFFECT | SUPPORT_RGB_COLOR | - SUPPORT_TRANSITION | SUPPORT_XY_COLOR) + SUPPORT_EFFECT | SUPPORT_COLOR | + SUPPORT_TRANSITION) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, @@ -113,7 +113,7 @@ class Luminary(Light): self.update_lights = update_lights self._luminary = luminary self._brightness = None - self._rgb = [None] + self._hs = None self._name = None self._temperature = None self._state = False @@ -125,9 +125,9 @@ class Luminary(Light): return self._name @property - def rgb_color(self): - """Last RGB color value set.""" - return self._rgb + def hs_color(self): + """Last hs color value set.""" + return self._hs @property def color_temp(self): @@ -158,42 +158,24 @@ class Luminary(Light): """Turn the device on.""" if ATTR_TRANSITION in kwargs: transition = int(kwargs[ATTR_TRANSITION] * 10) - _LOGGER.debug("turn_on requested transition time for light: " - "%s is: %s", self._name, transition) else: transition = 0 - _LOGGER.debug("turn_on requested transition time for light: " - "%s is: %s", self._name, transition) if ATTR_BRIGHTNESS in kwargs: self._brightness = kwargs[ATTR_BRIGHTNESS] - _LOGGER.debug("turn_on requested brightness for light: %s is: %s ", - self._name, self._brightness) self._luminary.set_luminance( int(self._brightness / 2.55), transition) else: self._luminary.set_onoff(1) - if ATTR_RGB_COLOR in kwargs: - red, green, blue = kwargs[ATTR_RGB_COLOR] - _LOGGER.debug("turn_on requested ATTR_RGB_COLOR for light:" - " %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) + if ATTR_HS_COLOR in kwargs: + red, green, blue = \ + color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR]) self._luminary.set_rgb(red, green, blue, transition) if ATTR_COLOR_TEMP in kwargs: color_t = kwargs[ATTR_COLOR_TEMP] 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) if ATTR_EFFECT in kwargs: @@ -202,23 +184,16 @@ class Luminary(Light): self._luminary.set_rgb( random.randrange(0, 255), random.randrange(0, 255), 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() def turn_off(self, **kwargs): """Turn the device off.""" - _LOGGER.debug("Attempting to turn off light: %s", self._name) if ATTR_TRANSITION in kwargs: 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) else: transition = 0 - _LOGGER.debug("turn_off requested transition time for light:" - " %s is: %s ", self._name, transition) self._luminary.set_onoff(0) self.schedule_update_ha_state() @@ -240,7 +215,8 @@ class OsramLightifyLight(Luminary): """Update status of a light.""" super().update() 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() if o_temp == 0: self._temperature = None @@ -270,7 +246,8 @@ class OsramLightifyGroup(Luminary): self._light_ids = self._luminary.lights() light = self._bridge.lights()[self._light_ids[0]] 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() if o_temp == 0: self._temperature = None diff --git a/homeassistant/components/light/piglow.py b/homeassistant/components/light/piglow.py index 40798810c0e0..755cf9dca669 100644 --- a/homeassistant/components/light/piglow.py +++ b/homeassistant/components/light/piglow.py @@ -11,15 +11,16 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv 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) from homeassistant.const import CONF_NAME +import homeassistant.util.color as color_util REQUIREMENTS = ['piglow==1.2.4'] _LOGGER = logging.getLogger(__name__) -SUPPORT_PIGLOW = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR) +SUPPORT_PIGLOW = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR) DEFAULT_NAME = 'Piglow' @@ -50,7 +51,7 @@ class PiglowLight(Light): self._name = name self._is_on = False self._brightness = 255 - self._rgb_color = [255, 255, 255] + self._hs_color = [0, 0] @property def name(self): @@ -63,9 +64,9 @@ class PiglowLight(Light): return self._brightness @property - def rgb_color(self): + def hs_color(self): """Read back the color of the light.""" - return self._rgb_color + return self._hs_color @property def supported_features(self): @@ -93,15 +94,15 @@ class PiglowLight(Light): if ATTR_BRIGHTNESS in kwargs: self._brightness = kwargs[ATTR_BRIGHTNESS] - percent_bright = (self._brightness / 255) - if ATTR_RGB_COLOR in kwargs: - self._rgb_color = kwargs[ATTR_RGB_COLOR] - self._piglow.red(int(self._rgb_color[0] * percent_bright)) - self._piglow.green(int(self._rgb_color[1] * percent_bright)) - self._piglow.blue(int(self._rgb_color[2] * percent_bright)) - else: - self._piglow.all(self._brightness) + if ATTR_HS_COLOR in kwargs: + self._hs_color = kwargs[ATTR_HS_COLOR] + + rgb = color_util.color_hsv_to_RGB( + self._hs_color[0], self._hs_color[1], self._brightness / 255 * 100) + self._piglow.red(rgb[0]) + self._piglow.green(rgb[1]) + self._piglow.blue(rgb[2]) self._piglow.show() self._is_on = True self.schedule_update_ha_state() diff --git a/homeassistant/components/light/rpi_gpio_pwm.py b/homeassistant/components/light/rpi_gpio_pwm.py index 55b64bf8a74f..9385c4bfb804 100644 --- a/homeassistant/components/light/rpi_gpio_pwm.py +++ b/homeassistant/components/light/rpi_gpio_pwm.py @@ -10,9 +10,10 @@ import voluptuous as vol from homeassistant.const import CONF_NAME, CONF_TYPE from homeassistant.components.light import ( - Light, ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_TRANSITION, - SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, PLATFORM_SCHEMA) + Light, ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_TRANSITION, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_TRANSITION, PLATFORM_SCHEMA) import homeassistant.helpers.config_validation as cv +import homeassistant.util.color as color_util REQUIREMENTS = ['pwmled==1.2.1'] @@ -33,10 +34,10 @@ CONF_LED_TYPE_RGB = 'rgb' CONF_LED_TYPE_RGBW = '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_RGB_LED = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR | SUPPORT_TRANSITION) +SUPPORT_RGB_LED = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR | SUPPORT_TRANSITION) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_LEDS): vol.All(cv.ensure_list, [ @@ -169,7 +170,7 @@ class PwmRgbLed(PwmSimpleLed): self._color = DEFAULT_COLOR @property - def rgb_color(self): + def hs_color(self): """Return the color property.""" return self._color @@ -180,8 +181,8 @@ class PwmRgbLed(PwmSimpleLed): def turn_on(self, **kwargs): """Turn on a LED.""" - if ATTR_RGB_COLOR in kwargs: - self._color = kwargs[ATTR_RGB_COLOR] + if ATTR_HS_COLOR in kwargs: + self._color = kwargs[ATTR_HS_COLOR] if ATTR_BRIGHTNESS in kwargs: self._brightness = kwargs[ATTR_BRIGHTNESS] @@ -209,4 +210,5 @@ def _from_hass_brightness(brightness): def _from_hass_color(color): """Convert Home Assistant RGB list to Color tuple.""" from pwmled import Color - return Color(*tuple(color)) + rgb = color_util.color_hs_to_RGB(*color) + return Color(*tuple(rgb)) diff --git a/homeassistant/components/light/sensehat.py b/homeassistant/components/light/sensehat.py index 6c5467f8c6d3..6ab2592cedf9 100644 --- a/homeassistant/components/light/sensehat.py +++ b/homeassistant/components/light/sensehat.py @@ -10,15 +10,16 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv 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) from homeassistant.const import CONF_NAME +import homeassistant.util.color as color_util REQUIREMENTS = ['sense-hat==2.2.0'] _LOGGER = logging.getLogger(__name__) -SUPPORT_SENSEHAT = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR) +SUPPORT_SENSEHAT = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR) DEFAULT_NAME = 'sensehat' @@ -49,7 +50,7 @@ class SenseHatLight(Light): self._name = name self._is_on = False self._brightness = 255 - self._rgb_color = [255, 255, 255] + self._hs_color = [0, 0] @property def name(self): @@ -62,12 +63,9 @@ class SenseHatLight(Light): return self._brightness @property - def rgb_color(self): - """Read back the color of the light. - - Returns [r, g, b] list with values in range of 0-255. - """ - return self._rgb_color + def hs_color(self): + """Read back the color of the light.""" + return self._hs_color @property def supported_features(self): @@ -93,14 +91,13 @@ class SenseHatLight(Light): """Instruct the light to turn on and set correct brightness & color.""" if ATTR_BRIGHTNESS in kwargs: self._brightness = kwargs[ATTR_BRIGHTNESS] - percent_bright = (self._brightness / 255) - if ATTR_RGB_COLOR in kwargs: - self._rgb_color = kwargs[ATTR_RGB_COLOR] + if ATTR_HS_COLOR in kwargs: + self._hs_color = kwargs[ATTR_HS_COLOR] - self._sensehat.clear(int(self._rgb_color[0] * percent_bright), - int(self._rgb_color[1] * percent_bright), - int(self._rgb_color[2] * percent_bright)) + rgb = color_util.color_hsv_to_RGB( + self._hs_color[0], self._hs_color[1], self._brightness / 255 * 100) + self._sensehat.clear(*rgb) self._is_on = True self.schedule_update_ha_state() diff --git a/homeassistant/components/light/skybell.py b/homeassistant/components/light/skybell.py index 012190023fa0..d32183f14683 100644 --- a/homeassistant/components/light/skybell.py +++ b/homeassistant/components/light/skybell.py @@ -8,10 +8,11 @@ import logging 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) from homeassistant.components.skybell import ( DOMAIN as SKYBELL_DOMAIN, SkybellDevice) +import homeassistant.util.color as color_util DEPENDENCIES = ['skybell'] @@ -54,8 +55,9 @@ class SkybellLight(SkybellDevice, Light): def turn_on(self, **kwargs): """Turn on the light.""" - if ATTR_RGB_COLOR in kwargs: - self._device.led_rgb = kwargs[ATTR_RGB_COLOR] + if ATTR_HS_COLOR in kwargs: + rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR]) + self._device.led_rgb = rgb elif ATTR_BRIGHTNESS in kwargs: self._device.led_intensity = _to_skybell_level( kwargs[ATTR_BRIGHTNESS]) @@ -77,11 +79,11 @@ class SkybellLight(SkybellDevice, Light): return _to_hass_level(self._device.led_intensity) @property - def rgb_color(self): + def hs_color(self): """Return the color of the light.""" - return self._device.led_rgb + return color_util.color_RGB_to_hs(*self._device.led_rgb) @property def supported_features(self): """Flag supported features.""" - return SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR + return SUPPORT_BRIGHTNESS | SUPPORT_COLOR diff --git a/homeassistant/components/light/tikteck.py b/homeassistant/components/light/tikteck.py index c39748e44303..2079638f7f10 100644 --- a/homeassistant/components/light/tikteck.py +++ b/homeassistant/components/light/tikteck.py @@ -10,15 +10,16 @@ import voluptuous as vol from homeassistant.const import CONF_DEVICES, CONF_NAME, CONF_PASSWORD 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) import homeassistant.helpers.config_validation as cv +import homeassistant.util.color as color_util REQUIREMENTS = ['tikteck==0.4'] _LOGGER = logging.getLogger(__name__) -SUPPORT_TIKTECK_LED = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR) +SUPPORT_TIKTECK_LED = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR) DEVICE_SCHEMA = vol.Schema({ vol.Optional(CONF_NAME): cv.string, @@ -57,7 +58,7 @@ class TikteckLight(Light): self._address = device['address'] self._password = device['password'] self._brightness = 255 - self._rgb = [255, 255, 255] + self._hs = [0, 0] self._state = False self.is_valid = True self._bulb = tikteck.tikteck( @@ -88,9 +89,9 @@ class TikteckLight(Light): return self._brightness @property - def rgb_color(self): + def hs_color(self): """Return the color property.""" - return self._rgb + return self._hs @property def supported_features(self): @@ -115,16 +116,17 @@ class TikteckLight(Light): """Turn the specified light on.""" self._state = True - rgb = kwargs.get(ATTR_RGB_COLOR) + hs_color = kwargs.get(ATTR_HS_COLOR) brightness = kwargs.get(ATTR_BRIGHTNESS) - if rgb is not None: - self._rgb = rgb + if hs_color is not None: + self._hs = hs_color if brightness is not None: self._brightness = brightness - self.set_state(self._rgb[0], self._rgb[1], self._rgb[2], - self.brightness) + rgb = color_util.color_hs_to_RGB(*self._hs) + + self.set_state(rgb[0], rgb[1], rgb[2], self.brightness) self.schedule_update_ha_state() def turn_off(self, **kwargs): diff --git a/homeassistant/components/light/tplink.py b/homeassistant/components/light/tplink.py index f87d624b83aa..0bbec0102820 100644 --- a/homeassistant/components/light/tplink.py +++ b/homeassistant/components/light/tplink.py @@ -5,23 +5,20 @@ For more details about this component, please refer to the documentation at https://home-assistant.io/components/light.tplink/ """ import logging -import colorsys import time import voluptuous as vol from homeassistant.const import (CONF_HOST, CONF_NAME) from homeassistant.components.light import ( - Light, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_KELVIN, ATTR_RGB_COLOR, - SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, PLATFORM_SCHEMA) + Light, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_KELVIN, ATTR_HS_COLOR, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR, PLATFORM_SCHEMA) import homeassistant.helpers.config_validation as cv from homeassistant.util.color import \ color_temperature_mired_to_kelvin as mired_to_kelvin from homeassistant.util.color import ( color_temperature_kelvin_to_mired as kelvin_to_mired) -from typing import Tuple - REQUIREMENTS = ['pyHS100==0.3.0'] _LOGGER = logging.getLogger(__name__) @@ -56,22 +53,6 @@ def brightness_from_percentage(percent): 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): """Representation of a TPLink Smart Bulb.""" @@ -83,7 +64,7 @@ class TPLinkSmartBulb(Light): self._available = True self._color_temp = None self._brightness = None - self._rgb = None + self._hs = None self._supported_features = 0 self._emeter_params = {} @@ -114,9 +95,10 @@ class TPLinkSmartBulb(Light): if ATTR_BRIGHTNESS in kwargs: brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness or 255) self.smartbulb.brightness = brightness_to_percentage(brightness) - if ATTR_RGB_COLOR in kwargs: - rgb = kwargs.get(ATTR_RGB_COLOR) - self.smartbulb.hsv = rgb_to_hsv(rgb) + if ATTR_HS_COLOR in kwargs: + hue, sat = kwargs.get(ATTR_HS_COLOR) + hsv = (hue, sat, 100) + self.smartbulb.hsv = hsv def turn_off(self, **kwargs): """Turn the light off.""" @@ -133,9 +115,9 @@ class TPLinkSmartBulb(Light): return self._brightness @property - def rgb_color(self): - """Return the color in RGB.""" - return self._rgb + def hs_color(self): + """Return the color.""" + return self._hs @property def is_on(self): @@ -168,8 +150,9 @@ class TPLinkSmartBulb(Light): self._color_temp = kelvin_to_mired( self.smartbulb.color_temp) - if self._supported_features & SUPPORT_RGB_COLOR: - self._rgb = hsv_to_rgb(self.smartbulb.hsv) + if self._supported_features & SUPPORT_COLOR: + hue, sat, _ = self.smartbulb.hsv + self._hs = (hue, sat) if self.smartbulb.has_emeter: self._emeter_params[ATTR_CURRENT_POWER_W] = '{:.1f}'.format( @@ -203,4 +186,4 @@ class TPLinkSmartBulb(Light): if self.smartbulb.is_variable_color_temp: self._supported_features += SUPPORT_COLOR_TEMP if self.smartbulb.is_color: - self._supported_features += SUPPORT_RGB_COLOR + self._supported_features += SUPPORT_COLOR diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index bb2fa44c15cd..1851579a1720 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -10,9 +10,9 @@ import logging from homeassistant.core import callback from homeassistant.const import ATTR_BATTERY_LEVEL 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_RGB_COLOR, Light) + SUPPORT_COLOR, Light) from homeassistant.components.light import \ PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA from homeassistant.components.tradfri import KEY_GATEWAY, KEY_TRADFRI_GROUPS, \ @@ -157,7 +157,7 @@ class TradfriLight(Light): self._light_control = None self._light_data = None self._name = None - self._rgb_color = None + self._hs_color = None self._features = SUPPORTED_FEATURES self._temp_supported = False self._available = True @@ -237,9 +237,9 @@ class TradfriLight(Light): ) @property - def rgb_color(self): - """RGB color of the light.""" - return self._rgb_color + def hs_color(self): + """HS color of the light.""" + return self._hs_color @asyncio.coroutine def async_turn_off(self, **kwargs): @@ -252,12 +252,12 @@ class TradfriLight(Light): Instruct the light to turn on. 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( - self._light.light_control.set_rgb_color( - *kwargs[ATTR_RGB_COLOR])) + self._light.light_control.set_rgb_color(*rgb)) elif ATTR_COLOR_TEMP in kwargs 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_data = light.light_control.lights[0] self._name = light.name - self._rgb_color = None + self._hs_color = None self._features = SUPPORTED_FEATURES if self._light.device_info.manufacturer == IKEA: if self._light_control.can_set_kelvin: self._features |= SUPPORT_COLOR_TEMP if self._light_control.can_set_color: - self._features |= SUPPORT_RGB_COLOR + self._features |= SUPPORT_COLOR else: 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 \ in ALLOWED_TEMPERATURES @@ -328,7 +328,8 @@ class TradfriLight(Light): def _observe_update(self, tradfri_device): """Receive new state data for this light.""" 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._hs_color = color_util.color_RGB_to_hs(*rgb) self.async_schedule_update_ha_state() diff --git a/homeassistant/components/light/vera.py b/homeassistant/components/light/vera.py index 102ca8148829..6b12e69341d2 100644 --- a/homeassistant/components/light/vera.py +++ b/homeassistant/components/light/vera.py @@ -7,10 +7,11 @@ https://home-assistant.io/components/light.vera/ import logging from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ENTITY_ID_FORMAT, - SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, Light) + ATTR_BRIGHTNESS, ATTR_HS_COLOR, ENTITY_ID_FORMAT, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR, Light) from homeassistant.components.vera import ( VERA_CONTROLLER, VERA_DEVICES, VeraDevice) +import homeassistant.util.color as color_util _LOGGER = logging.getLogger(__name__) @@ -42,7 +43,7 @@ class VeraLight(VeraDevice, Light): return self._brightness @property - def rgb_color(self): + def hs_color(self): """Return the color of the light.""" return self._color @@ -50,13 +51,14 @@ class VeraLight(VeraDevice, Light): def supported_features(self): """Flag supported features.""" if self._color: - return SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR + return SUPPORT_BRIGHTNESS | SUPPORT_COLOR return SUPPORT_BRIGHTNESS def turn_on(self, **kwargs): """Turn the light on.""" - if ATTR_RGB_COLOR in kwargs and self._color: - self.vera_device.set_color(kwargs[ATTR_RGB_COLOR]) + if ATTR_HS_COLOR in kwargs and self._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: self.vera_device.set_brightness(kwargs[ATTR_BRIGHTNESS]) else: @@ -83,4 +85,5 @@ class VeraLight(VeraDevice, Light): # If it is dimmable, both functions exist. In case color # is not supported, it will return None 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 diff --git a/homeassistant/components/light/wemo.py b/homeassistant/components/light/wemo.py index 540c718b04d7..d05751052355 100644 --- a/homeassistant/components/light/wemo.py +++ b/homeassistant/components/light/wemo.py @@ -9,12 +9,11 @@ import logging from datetime import timedelta import homeassistant.util as util -import homeassistant.util.color as color_util from homeassistant.components.light import ( - Light, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_TRANSITION, - ATTR_XY_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, - SUPPORT_TRANSITION, SUPPORT_XY_COLOR) + Light, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR, ATTR_TRANSITION, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR, SUPPORT_TRANSITION) from homeassistant.loader import get_component +import homeassistant.util.color as color_util DEPENDENCIES = ['wemo'] @@ -23,8 +22,8 @@ MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(milliseconds=100) _LOGGER = logging.getLogger(__name__) -SUPPORT_WEMO = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR | - SUPPORT_TRANSITION | SUPPORT_XY_COLOR) +SUPPORT_WEMO = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_COLOR | + SUPPORT_TRANSITION) def setup_platform(hass, config, add_devices, discovery_info=None): @@ -89,9 +88,10 @@ class WemoLight(Light): return self.device.state.get('level', 255) @property - def xy_color(self): - """Return the XY color values of this light.""" - return self.device.state.get('color_xy') + def hs_color(self): + """Return the hs color values of this light.""" + xy_color = self.device.state.get('color_xy') + return color_util.color_xy_to_hs(*xy_color) if xy_color else None @property def color_temp(self): @@ -112,17 +112,11 @@ class WemoLight(Light): """Turn the light on.""" transitiontime = int(kwargs.get(ATTR_TRANSITION, 0)) - if ATTR_XY_COLOR in kwargs: - 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 + hs_color = kwargs.get(ATTR_HS_COLOR) - if xycolor is not None: - self.device.set_color(xycolor, transition=transitiontime) + if hs_color is not None: + xy_color = color_util.color_hs_to_xy(*hs_color) + self.device.set_color(xy_color, transition=transitiontime) if ATTR_COLOR_TEMP in kwargs: colortemp = kwargs[ATTR_COLOR_TEMP] diff --git a/homeassistant/components/light/wink.py b/homeassistant/components/light/wink.py index e329fa04837d..fd957f8f11d2 100644 --- a/homeassistant/components/light/wink.py +++ b/homeassistant/components/light/wink.py @@ -8,8 +8,8 @@ import asyncio import colorsys from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, - SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, Light) + ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR, SUPPORT_BRIGHTNESS, + SUPPORT_COLOR_TEMP, SUPPORT_COLOR, Light) from homeassistant.components.wink import DOMAIN, WinkDevice from homeassistant.util import color as color_util from homeassistant.util.color import \ @@ -17,7 +17,7 @@ from homeassistant.util.color import \ 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): @@ -72,11 +72,11 @@ class WinkLight(WinkDevice, Light): return r_value, g_value, b_value @property - def xy_color(self): - """Define current bulb color in CIE 1931 (XY) color space.""" + def hs_color(self): + """Define current bulb color.""" if not self.wink.supports_xy_color(): return None - return self.wink.color_xy() + return color_util.color_xy_to_hs(*self.wink.color_xy()) @property def color_temp(self): @@ -94,21 +94,17 @@ class WinkLight(WinkDevice, Light): def turn_on(self, **kwargs): """Turn the switch on.""" 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) - state_kwargs = { - } + state_kwargs = {} - if rgb_color: + if hs_color: if self.wink.supports_xy_color(): - xyb = color_util.color_RGB_to_xy(*rgb_color) - state_kwargs['color_xy'] = xyb[0], xyb[1] - state_kwargs['brightness'] = xyb[2] + xy_color = color_util.color_hs_to_xy(*hs_color) + state_kwargs['color_xy'] = xy_color if self.wink.supports_hue_saturation(): - hsv = colorsys.rgb_to_hsv( - rgb_color[0], rgb_color[1], rgb_color[2]) - state_kwargs['color_hue_saturation'] = hsv[0], hsv[1] + state_kwargs['color_hue_saturation'] = hs_color if color_temp_mired: state_kwargs['color_kelvin'] = mired_to_kelvin(color_temp_mired) diff --git a/homeassistant/components/light/xiaomi_aqara.py b/homeassistant/components/light/xiaomi_aqara.py index efe37d3d5775..125e791829fa 100644 --- a/homeassistant/components/light/xiaomi_aqara.py +++ b/homeassistant/components/light/xiaomi_aqara.py @@ -4,9 +4,10 @@ import struct import binascii from homeassistant.components.xiaomi_aqara import (PY_XIAOMI_GATEWAY, XiaomiDevice) -from homeassistant.components.light import (ATTR_BRIGHTNESS, ATTR_RGB_COLOR, +from homeassistant.components.light import (ATTR_BRIGHTNESS, ATTR_HS_COLOR, SUPPORT_BRIGHTNESS, - SUPPORT_RGB_COLOR, Light) + SUPPORT_COLOR, Light) +import homeassistant.util.color as color_util _LOGGER = logging.getLogger(__name__) @@ -29,7 +30,7 @@ class XiaomiGatewayLight(XiaomiDevice, Light): def __init__(self, device, name, xiaomi_hub): """Initialize the XiaomiGatewayLight.""" self._data_key = 'rgb' - self._rgb = (255, 255, 255) + self._hs = (0, 0) self._brightness = 180 XiaomiDevice.__init__(self, device, name, xiaomi_hub) @@ -64,7 +65,7 @@ class XiaomiGatewayLight(XiaomiDevice, Light): rgb = rgba[1:] self._brightness = int(255 * brightness / 100) - self._rgb = rgb + self._hs = color_util.color_RGB_to_hs(*rgb) self._state = True return True @@ -74,24 +75,25 @@ class XiaomiGatewayLight(XiaomiDevice, Light): return self._brightness @property - def rgb_color(self): - """Return the RBG color value.""" - return self._rgb + def hs_color(self): + """Return the hs color value.""" + return self._hs @property def supported_features(self): """Return the supported features.""" - return SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR + return SUPPORT_BRIGHTNESS | SUPPORT_COLOR def turn_on(self, **kwargs): """Turn the light on.""" - if ATTR_RGB_COLOR in kwargs: - self._rgb = kwargs[ATTR_RGB_COLOR] + if ATTR_HS_COLOR in kwargs: + self._hs = kwargs[ATTR_HS_COLOR] if ATTR_BRIGHTNESS in kwargs: 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 = int(rgbhex, 16) diff --git a/homeassistant/components/light/yeelight.py b/homeassistant/components/light/yeelight.py index ca10d246ce8a..585db950efc5 100644 --- a/homeassistant/components/light/yeelight.py +++ b/homeassistant/components/light/yeelight.py @@ -5,26 +5,20 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/light.yeelight/ """ import logging -import colorsys -from typing import Tuple import voluptuous as vol from homeassistant.util.color import ( color_temperature_mired_to_kelvin as mired_to_kelvin, - color_temperature_kelvin_to_mired as kelvin_to_mired, - color_temperature_to_rgb, - color_RGB_to_xy, - color_xy_brightness_to_RGB) + color_temperature_kelvin_to_mired as kelvin_to_mired) from homeassistant.const import CONF_DEVICES, CONF_NAME from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_TRANSITION, ATTR_COLOR_TEMP, - ATTR_FLASH, ATTR_XY_COLOR, FLASH_SHORT, FLASH_LONG, ATTR_EFFECT, - SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, SUPPORT_XY_COLOR, - SUPPORT_TRANSITION, - SUPPORT_COLOR_TEMP, SUPPORT_FLASH, SUPPORT_EFFECT, - Light, PLATFORM_SCHEMA) + ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_TRANSITION, ATTR_COLOR_TEMP, + ATTR_FLASH, FLASH_SHORT, FLASH_LONG, ATTR_EFFECT, SUPPORT_BRIGHTNESS, + SUPPORT_COLOR, SUPPORT_TRANSITION, SUPPORT_COLOR_TEMP, SUPPORT_FLASH, + SUPPORT_EFFECT, Light, PLATFORM_SCHEMA) import homeassistant.helpers.config_validation as cv +import homeassistant.util.color as color_util REQUIREMENTS = ['yeelight==0.4.0'] @@ -53,8 +47,7 @@ SUPPORT_YEELIGHT = (SUPPORT_BRIGHTNESS | SUPPORT_FLASH) SUPPORT_YEELIGHT_RGB = (SUPPORT_YEELIGHT | - SUPPORT_RGB_COLOR | - SUPPORT_XY_COLOR | + SUPPORT_COLOR | SUPPORT_EFFECT | SUPPORT_COLOR_TEMP) @@ -98,14 +91,6 @@ YEELIGHT_EFFECT_LIST = [ 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): """Define a wrapper to catch exceptions from the bulb.""" def _wrap(self, *args, **kwargs): @@ -157,8 +142,7 @@ class YeelightLight(Light): self._brightness = None self._color_temp = None self._is_on = None - self._rgb = None - self._xy = None + self._hs = None @property def available(self) -> bool: @@ -209,38 +193,32 @@ class YeelightLight(Light): return kelvin_to_mired(YEELIGHT_RGB_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) color_mode = self._properties.get('color_mode', None) if not rgb or not color_mode: - return rgb + return None color_mode = int(color_mode) if color_mode == 2: # color temperature 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 hue = int(self._properties.get('hue')) sat = int(self._properties.get('sat')) - val = int(self._properties.get('bright')) - return hsv_to_rgb((hue, sat, val)) + return (hue / 360 * 65536, sat / 100 * 255) rgb = int(rgb) blue = rgb & 0xff green = (rgb >> 8) & 0xff red = (rgb >> 16) & 0xff - return red, green, blue + return color_util.color_RGB_to_hs(red, green, blue) @property - def rgb_color(self) -> tuple: + def hs_color(self) -> tuple: """Return the color property.""" - return self._rgb - - @property - def xy_color(self) -> tuple: - """Return the XY color value.""" - return self._xy + return self._hs @property def _properties(self) -> dict: @@ -288,13 +266,7 @@ class YeelightLight(Light): if temp_in_k: self._color_temp = kelvin_to_mired(int(temp_in_k)) - self._rgb = self._get_rgb_from_properties() - - if self._rgb: - xyb = color_RGB_to_xy(*self._rgb) - self._xy = (xyb[0], xyb[1]) - else: - self._xy = None + self._hs = self._get_hs_from_properties() self._available = True except yeelight.BulbException as ex: @@ -313,7 +285,7 @@ class YeelightLight(Light): @_cmd def set_rgb(self, rgb, duration) -> None: """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) self._bulb.set_rgb(rgb[0], rgb[1], rgb[2], duration=duration) @@ -349,7 +321,7 @@ class YeelightLight(Light): count = 1 duration = transition * 2 - red, green, blue = self.rgb_color + red, green, blue = color_util.color_hs_to_RGB(*self._hs) transitions = list() transitions.append( @@ -419,10 +391,10 @@ class YeelightLight(Light): import yeelight brightness = kwargs.get(ATTR_BRIGHTNESS) 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) effect = kwargs.get(ATTR_EFFECT) - xy_color = kwargs.get(ATTR_XY_COLOR) duration = int(self.config[CONF_TRANSITION]) # in ms if ATTR_TRANSITION in kwargs: # passed kwarg overrides config @@ -440,9 +412,6 @@ class YeelightLight(Light): except yeelight.BulbException as ex: _LOGGER.error("Unable to turn on music mode," "consider disabling it: %s", ex) - if xy_color and brightness: - rgb = color_xy_brightness_to_RGB(xy_color[0], xy_color[1], - brightness) try: # values checked for none in methods diff --git a/homeassistant/components/light/yeelightsunflower.py b/homeassistant/components/light/yeelightsunflower.py index 5f48e3a0a71a..88f86063c131 100644 --- a/homeassistant/components/light/yeelightsunflower.py +++ b/homeassistant/components/light/yeelightsunflower.py @@ -10,15 +10,16 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv 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) from homeassistant.const import CONF_HOST +import homeassistant.util.color as color_util REQUIREMENTS = ['yeelightsunflower==0.0.8'] _LOGGER = logging.getLogger(__name__) -SUPPORT_YEELIGHT_SUNFLOWER = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR) +SUPPORT_YEELIGHT_SUNFLOWER = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string @@ -48,7 +49,7 @@ class SunflowerBulb(Light): self._available = light.available self._brightness = light.brightness self._is_on = light.is_on - self._rgb_color = light.rgb_color + self._hs_color = light.rgb_color @property def name(self): @@ -71,9 +72,9 @@ class SunflowerBulb(Light): return int(self._brightness / 100 * 255) @property - def rgb_color(self): + def hs_color(self): """Return the color property.""" - return self._rgb_color + return self._hs_color @property def supported_features(self): @@ -86,12 +87,12 @@ class SunflowerBulb(Light): if not kwargs: self._light.turn_on() else: - if ATTR_RGB_COLOR in kwargs and ATTR_BRIGHTNESS in kwargs: - rgb = kwargs[ATTR_RGB_COLOR] + if ATTR_HS_COLOR in kwargs and ATTR_BRIGHTNESS in kwargs: + rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR]) bright = int(kwargs[ATTR_BRIGHTNESS] / 255 * 100) self._light.set_all(rgb[0], rgb[1], rgb[2], bright) - elif ATTR_RGB_COLOR in kwargs: - rgb = kwargs[ATTR_RGB_COLOR] + elif ATTR_HS_COLOR in kwargs: + rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR]) self._light.set_rgb_color(rgb[0], rgb[1], rgb[2]) elif ATTR_BRIGHTNESS in kwargs: bright = int(kwargs[ATTR_BRIGHTNESS] / 255 * 100) @@ -107,4 +108,4 @@ class SunflowerBulb(Light): self._available = self._light.available self._brightness = self._light.brightness 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) diff --git a/homeassistant/components/light/zengge.py b/homeassistant/components/light/zengge.py index 7071c8c43bb0..3c77f2d8449c 100644 --- a/homeassistant/components/light/zengge.py +++ b/homeassistant/components/light/zengge.py @@ -10,15 +10,16 @@ import voluptuous as vol from homeassistant.const import CONF_DEVICES, CONF_NAME from homeassistant.components.light import ( - ATTR_RGB_COLOR, ATTR_WHITE_VALUE, - SUPPORT_RGB_COLOR, SUPPORT_WHITE_VALUE, Light, PLATFORM_SCHEMA) + ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_WHITE_VALUE, SUPPORT_BRIGHTNESS, + SUPPORT_COLOR, SUPPORT_WHITE_VALUE, Light, PLATFORM_SCHEMA) import homeassistant.helpers.config_validation as cv +import homeassistant.util.color as color_util REQUIREMENTS = ['zengge==0.2'] _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({ vol.Optional(CONF_NAME): cv.string, @@ -56,7 +57,8 @@ class ZenggeLight(Light): self.is_valid = True self._bulb = zengge.zengge(self._address) self._white = 0 - self._rgb = (0, 0, 0) + self._brightness = 0 + self._hs_color = (0, 0) self._state = False if self._bulb.connect() is False: self.is_valid = False @@ -80,9 +82,14 @@ class ZenggeLight(Light): return self._state @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 self._rgb + return self._hs_color @property def white_value(self): @@ -117,21 +124,29 @@ class ZenggeLight(Light): self._state = True self._bulb.on() - rgb = kwargs.get(ATTR_RGB_COLOR) + hs_color = kwargs.get(ATTR_HS_COLOR) white = kwargs.get(ATTR_WHITE_VALUE) + brightness = kwargs.get(ATTR_BRIGHTNESS) if white is not None: 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._rgb = rgb + self._hs_color = hs_color + + if brightness is not None: + self._white = 0 + self._brightness = brightness if self._white != 0: self.set_white(self._white) 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): """Turn the specified light off.""" @@ -140,6 +155,9 @@ class ZenggeLight(Light): def update(self): """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._state = self._bulb.get_on() diff --git a/homeassistant/components/light/zha.py b/homeassistant/components/light/zha.py index 7958fcabf137..68c5bcc2a299 100644 --- a/homeassistant/components/light/zha.py +++ b/homeassistant/components/light/zha.py @@ -7,8 +7,8 @@ at https://home-assistant.io/components/light.zha/ import logging from homeassistant.components import light, zha -from homeassistant.util.color import color_RGB_to_xy from homeassistant.const import STATE_UNKNOWN +import homeassistant.util.color as color_util _LOGGER = logging.getLogger(__name__) @@ -57,7 +57,7 @@ class Light(zha.Entity, light.Light): super().__init__(**kwargs) self._supported_features = 0 self._color_temp = None - self._xy_color = None + self._hs_color = None self._brightness = None import zigpy.zcl.clusters as zcl_clusters @@ -71,9 +71,8 @@ class Light(zha.Entity, light.Light): self._supported_features |= light.SUPPORT_COLOR_TEMP if color_capabilities & CAPABILITIES_COLOR_XY: - self._supported_features |= light.SUPPORT_XY_COLOR - self._supported_features |= light.SUPPORT_RGB_COLOR - self._xy_color = (1.0, 1.0) + self._supported_features |= light.SUPPORT_COLOR + self._hs_color = (0, 0) @property def is_on(self) -> bool: @@ -92,17 +91,12 @@ class Light(zha.Entity, light.Light): temperature, duration) self._color_temp = temperature - if light.ATTR_XY_COLOR in kwargs: - self._xy_color = kwargs[light.ATTR_XY_COLOR] - elif light.ATTR_RGB_COLOR in kwargs: - 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: + if light.ATTR_HS_COLOR in kwargs: + self._hs_color = kwargs[light.ATTR_HS_COLOR] + xy_color = color_util.color_hs_to_xy(*self._hs_color) await self._endpoint.light_color.move_to_color( - int(self._xy_color[0] * 65535), - int(self._xy_color[1] * 65535), + int(xy_color[0] * 65535), + int(xy_color[1] * 65535), duration, ) @@ -135,9 +129,9 @@ class Light(zha.Entity, light.Light): return self._brightness @property - def xy_color(self): - """Return the XY color value [float, float].""" - return self._xy_color + def hs_color(self): + """Return the hs color value [int, int].""" + return self._hs_color @property def color_temp(self): @@ -165,11 +159,12 @@ class Light(zha.Entity, light.Light): self._color_temp = result.get('color_temperature', 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, ['current_x', 'current_y']) 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 def should_poll(self) -> bool: diff --git a/homeassistant/components/light/zwave.py b/homeassistant/components/light/zwave.py index 64c6530dd2b1..286ce73f1ed0 100644 --- a/homeassistant/components/light/zwave.py +++ b/homeassistant/components/light/zwave.py @@ -9,14 +9,14 @@ import logging # Because we do not compile openzwave on CI # pylint: disable=import-error from threading import Timer -from homeassistant.components.light import ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, \ - ATTR_RGB_COLOR, ATTR_TRANSITION, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, \ - SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, DOMAIN, Light +from homeassistant.components.light import ( + ATTR_WHITE_VALUE, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR, + ATTR_TRANSITION, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR, + SUPPORT_TRANSITION, SUPPORT_WHITE_VALUE, DOMAIN, Light) from homeassistant.components import zwave from homeassistant.components.zwave import async_setup_platform # noqa # pylint: disable=unused-import from homeassistant.const import STATE_OFF, STATE_ON -from homeassistant.util.color import color_temperature_mired_to_kelvin, \ - color_temperature_to_rgb, color_rgb_to_rgbw, color_rgbw_to_rgb +import homeassistant.util.color as color_util _LOGGER = logging.getLogger(__name__) @@ -65,10 +65,11 @@ def brightness_state(value): return 0, STATE_OFF -def ct_to_rgb(temp): - """Convert color temperature (mireds) to RGB.""" +def ct_to_hs(temp): + """Convert color temperature (mireds) to hs.""" 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] @@ -209,8 +210,9 @@ class ZwaveColorLight(ZwaveDimmer): def __init__(self, values, refresh, delay): """Initialize the light.""" self._color_channels = None - self._rgb = None + self._hs = None self._ct = None + self._white = None super().__init__(values, refresh, delay) @@ -218,9 +220,12 @@ class ZwaveColorLight(ZwaveDimmer): """Call when a new value is added to this entity.""" super().value_added() - self._supported_features |= SUPPORT_RGB_COLOR + self._supported_features |= SUPPORT_COLOR if self._zw098: 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): """Update internal properties based on zwave values.""" @@ -238,10 +243,11 @@ class ZwaveColorLight(ZwaveDimmer): data = self.values.color.data # RGB is always present in the openzwave color data string. - self._rgb = [ + rgb = [ int(data[1:3], 16), int(data[3:5], 16), int(data[5:7], 16)] + self._hs = color_util.color_RGB_to_hs(*rgb) # Parse remaining color channels. Openzwave appends white channels # that are present. @@ -267,30 +273,35 @@ class ZwaveColorLight(ZwaveDimmer): if self._zw098: if warm_white > 0: self._ct = TEMP_WARM_HASS - self._rgb = ct_to_rgb(self._ct) + self._hs = ct_to_hs(self._ct) elif cold_white > 0: self._ct = TEMP_COLD_HASS - self._rgb = ct_to_rgb(self._ct) + self._hs = ct_to_hs(self._ct) else: # RGB color is being used. Just report midpoint. self._ct = TEMP_MID_HASS 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: - self._rgb = list(color_rgbw_to_rgb(*self._rgb, w=cold_white)) + self._white = cold_white # If no rgb channels supported, report None. if not (self._color_channels & COLOR_CHANNEL_RED or self._color_channels & COLOR_CHANNEL_GREEN or self._color_channels & COLOR_CHANNEL_BLUE): - self._rgb = None + self._hs = None @property - def rgb_color(self): - """Return the rgb color.""" - return self._rgb + def hs_color(self): + """Return the hs color.""" + return self._hs + + @property + def white_value(self): + """Return the white value of this light between 0..255.""" + return self._white @property def color_temp(self): @@ -301,6 +312,9 @@ class ZwaveColorLight(ZwaveDimmer): """Turn the device on.""" rgbw = None + if ATTR_WHITE_VALUE in kwargs: + self._white = kwargs[ATTR_WHITE_VALUE] + if ATTR_COLOR_TEMP in kwargs: # Color temperature. With the AEOTEC ZW098 bulb, only two color # temperatures are supported. The warm and cold channel values @@ -313,19 +327,16 @@ class ZwaveColorLight(ZwaveDimmer): self._ct = TEMP_COLD_HASS rgbw = '#00000000ff' - elif ATTR_RGB_COLOR in kwargs: - self._rgb = kwargs[ATTR_RGB_COLOR] - if (not self._zw098 and ( - self._color_channels & COLOR_CHANNEL_WARM_WHITE or - self._color_channels & COLOR_CHANNEL_COLD_WHITE)): - rgbw = '#' - for colorval in color_rgb_to_rgbw(*self._rgb): - rgbw += format(colorval, '02x') - rgbw += '00' + elif ATTR_HS_COLOR in kwargs: + self._hs = kwargs[ATTR_HS_COLOR] + + if ATTR_WHITE_VALUE in kwargs or ATTR_HS_COLOR in kwargs: + rgbw = '#' + for colorval in color_util.color_hs_to_RGB(*self._hs): + rgbw += format(colorval, '02x') + if self._white is not None: + rgbw += format(self._white, '02x') + '00' else: - rgbw = '#' - for colorval in self._rgb: - rgbw += format(colorval, '02x') rgbw += '0000' if rgbw and self.values.color: diff --git a/homeassistant/components/switch/flux.py b/homeassistant/components/switch/flux.py index acc0c3ac4230..e0bfdeee030f 100644 --- a/homeassistant/components/switch/flux.py +++ b/homeassistant/components/switch/flux.py @@ -21,7 +21,7 @@ from homeassistant.helpers.event import track_time_change from homeassistant.helpers.sun import get_astral_event_date from homeassistant.util import slugify 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) from homeassistant.util.dt import now as dt_now @@ -234,7 +234,7 @@ class FluxSwitch(SwitchDevice): else: temp = self._sunset_colortemp + temp_offset 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 if self._disable_brightness_adjust: brightness = None diff --git a/homeassistant/util/color.py b/homeassistant/util/color.py index 70863a0ab903..c2e4ac737e83 100644 --- a/homeassistant/util/color.py +++ b/homeassistant/util/color.py @@ -173,11 +173,18 @@ def color_name_to_rgb(color_name): 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: # http://www.developers.meethue.com/documentation/color-conversions-rgb-xy # License: Code is given as is. Use at your own risk and discretion. # 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.""" if iR + iG + iB == 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 +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: # http://www.developers.meethue.com/documentation/color-conversions-rgb-xy # 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) +# 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 def color_hsv_to_RGB(iH: float, iS: float, iV: float) -> Tuple[int, int, int]: """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 -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.""" - 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) +# 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 def _match_max_scale(input_colors: Tuple[int, ...], output_colors: Tuple[int, ...]) -> Tuple[int, ...]: @@ -374,6 +404,11 @@ def rgb_hex_to_rgb_list(hex_string): 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): """ Return an RGB color from a color temperature in Kelvin. diff --git a/tests/components/alexa/test_smart_home.py b/tests/components/alexa/test_smart_home.py index a5375ba26622..8199652d09e5 100644 --- a/tests/components/alexa/test_smart_home.py +++ b/tests/components/alexa/test_smart_home.py @@ -950,42 +950,6 @@ def test_api_set_color_rgb(hass): 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 def test_api_set_color_temperature(hass): """Test api set color temperature process.""" diff --git a/tests/components/google_assistant/test_smart_home.py b/tests/components/google_assistant/test_smart_home.py index 24d74afa6da7..6523c22fee12 100644 --- a/tests/components/google_assistant/test_smart_home.py +++ b/tests/components/google_assistant/test_smart_home.py @@ -21,7 +21,7 @@ async def test_sync_message(hass): light = DemoLight( None, 'Demo Light', state=False, - rgb=[237, 224, 33] + hs_color=(180, 75), ) light.hass = hass light.entity_id = 'light.demo_light' @@ -88,7 +88,7 @@ async def test_query_message(hass): light = DemoLight( None, 'Demo Light', state=False, - rgb=[237, 224, 33] + hs_color=(180, 75), ) light.hass = hass light.entity_id = 'light.demo_light' @@ -97,7 +97,7 @@ async def test_query_message(hass): light2 = DemoLight( None, 'Another Light', state=True, - rgb=[237, 224, 33], + hs_color=(180, 75), ct=400, brightness=78, ) @@ -137,7 +137,7 @@ async def test_query_message(hass): 'online': True, 'brightness': 30, 'color': { - 'spectrumRGB': 15589409, + 'spectrumRGB': 4194303, 'temperature': 2500, } }, @@ -197,7 +197,7 @@ async def test_execute(hass): "online": True, 'brightness': 20, 'color': { - 'spectrumRGB': 15589409, + 'spectrumRGB': 16773155, 'temperature': 2631, }, } diff --git a/tests/components/google_assistant/test_trait.py b/tests/components/google_assistant/test_trait.py index 4ffb273662e1..e6336e052460 100644 --- a/tests/components/google_assistant/test_trait.py +++ b/tests/components/google_assistant/test_trait.py @@ -361,12 +361,10 @@ async def test_color_spectrum_light(hass): """Test ColorSpectrum trait support for light domain.""" assert not trait.ColorSpectrumTrait.supported(light.DOMAIN, 0) assert trait.ColorSpectrumTrait.supported(light.DOMAIN, - light.SUPPORT_RGB_COLOR) - assert trait.ColorSpectrumTrait.supported(light.DOMAIN, - light.SUPPORT_XY_COLOR) + light.SUPPORT_COLOR) 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() == { @@ -375,7 +373,7 @@ async def test_color_spectrum_light(hass): assert trt.query_attributes() == { 'color': { - 'spectrumRGB': 16714250 + 'spectrumRGB': 16715535 } } @@ -399,7 +397,7 @@ async def test_color_spectrum_light(hass): assert len(calls) == 1 assert calls[0].data == { ATTR_ENTITY_ID: 'light.bla', - light.ATTR_RGB_COLOR: [16, 16, 255] + light.ATTR_HS_COLOR: (240, 93.725), } diff --git a/tests/components/homekit/test_type_lights.py b/tests/components/homekit/test_type_lights.py index 83456f459cd7..b4d4d5a59456 100644 --- a/tests/components/homekit/test_type_lights.py +++ b/tests/components/homekit/test_type_lights.py @@ -4,8 +4,8 @@ import unittest from homeassistant.core import callback from homeassistant.components.homekit.type_lights import Light from homeassistant.components.light import ( - DOMAIN, ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_RGB_COLOR, - SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR) + DOMAIN, ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_HS_COLOR, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR) from homeassistant.const import ( ATTR_DOMAIN, ATTR_ENTITY_ID, ATTR_SERVICE, ATTR_SERVICE_DATA, ATTR_SUPPORTED_FEATURES, EVENT_CALL_SERVICE, SERVICE_TURN_ON, @@ -108,16 +108,16 @@ class TestHomekitLights(unittest.TestCase): """Test light with rgb_color.""" entity_id = 'light.demo' self.hass.states.set(entity_id, STATE_ON, { - ATTR_SUPPORTED_FEATURES: SUPPORT_RGB_COLOR, - ATTR_RGB_COLOR: (120, 20, 255)}) + ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR, + ATTR_HS_COLOR: (260, 90)}) acc = Light(self.hass, entity_id, 'Light', aid=2) self.assertEqual(acc.char_hue.value, 0) self.assertEqual(acc.char_saturation.value, 75) acc.run() self.hass.block_till_done() - self.assertEqual(acc.char_hue.value, 265.532) - self.assertEqual(acc.char_saturation.value, 92.157) + self.assertEqual(acc.char_hue.value, 260) + self.assertEqual(acc.char_saturation.value, 90) # Set from HomeKit acc.char_hue.set_value(145) @@ -129,4 +129,4 @@ class TestHomekitLights(unittest.TestCase): self.events[0].data[ATTR_SERVICE], SERVICE_TURN_ON) self.assertEqual( 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)}) diff --git a/tests/components/light/test_demo.py b/tests/components/light/test_demo.py index 8a7d648e6f28..ff984aff221c 100644 --- a/tests/components/light/test_demo.py +++ b/tests/components/light/test_demo.py @@ -33,19 +33,22 @@ class TestDemoLight(unittest.TestCase): self.hass.block_till_done() state = self.hass.states.get(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( - (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)) light.turn_on( - self.hass, ENTITY_LIGHT, rgb_color=(251, 252, 253), + self.hass, ENTITY_LIGHT, rgb_color=(251, 253, 255), white_value=254) self.hass.block_till_done() state = self.hass.states.get(ENTITY_LIGHT) self.assertEqual(254, state.attributes.get(light.ATTR_WHITE_VALUE)) 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') self.hass.block_till_done() state = self.hass.states.get(ENTITY_LIGHT) diff --git a/tests/components/light/test_group.py b/tests/components/light/test_group.py index 3c94fa2af3e9..26b949720d94 100644 --- a/tests/components/light/test_group.py +++ b/tests/components/light/test_group.py @@ -20,8 +20,7 @@ async def test_default_state(hass): assert state.state == 'unavailable' assert state.attributes['supported_features'] == 0 assert state.attributes.get('brightness') is None - assert state.attributes.get('rgb_color') is None - assert state.attributes.get('xy_color') is None + assert state.attributes.get('hs_color') is None assert state.attributes.get('color_temp') is None assert state.attributes.get('white_value') is None assert state.attributes.get('effect_list') is None @@ -85,61 +84,32 @@ async def test_brightness(hass): assert state.attributes['brightness'] == 100 -async def test_xy_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): +async def test_color(hass): """Test RGB reporting.""" await async_setup_component(hass, 'light', {'light': { 'platform': 'group', 'entities': ['light.test1', 'light.test2'] }}) 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() state = hass.states.get('light.light_group') assert state.state == 'on' 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', - {'rgb_color': (255, 255, 255), + {'hs_color': (0, 50), 'supported_features': 16}) await hass.async_block_till_done() 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', - {'rgb_color': (255, 0, 0), 'supported_features': 16}) + {'hs_color': (0, 0), 'supported_features': 16}) await hass.async_block_till_done() 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): @@ -413,5 +383,7 @@ async def test_invalid_service_calls(hass): } await grouped_light.async_turn_on(**data) 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, blocking=True) diff --git a/tests/components/light/test_init.py b/tests/components/light/test_init.py index d35321b44793..4e8fad261bd3 100644 --- a/tests/components/light/test_init.py +++ b/tests/components/light/test_init.py @@ -188,23 +188,25 @@ class TestLight(unittest.TestCase): self.hass.block_till_done() _, data = dev1.last_call('turn_on') - self.assertEqual( - {light.ATTR_TRANSITION: 10, - light.ATTR_BRIGHTNESS: 20, - light.ATTR_RGB_COLOR: (0, 0, 255)}, - data) + self.assertEqual({ + light.ATTR_TRANSITION: 10, + light.ATTR_BRIGHTNESS: 20, + light.ATTR_HS_COLOR: (240, 100), + }, data) _, data = dev2.last_call('turn_on') - self.assertEqual( - {light.ATTR_RGB_COLOR: (255, 255, 255), - light.ATTR_WHITE_VALUE: 255}, - data) + self.assertEqual({ + light.ATTR_HS_COLOR: (0, 0), + light.ATTR_WHITE_VALUE: 255, + }, data) _, 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 - 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 light.turn_on(self.hass, dev1.entity_id, profile=prof_name) @@ -216,16 +218,16 @@ class TestLight(unittest.TestCase): self.hass.block_till_done() _, data = dev1.last_call('turn_on') - self.assertEqual( - {light.ATTR_BRIGHTNESS: prof_bri, - light.ATTR_XY_COLOR: (prof_x, prof_y)}, - data) + self.assertEqual({ + light.ATTR_BRIGHTNESS: prof_bri, + light.ATTR_HS_COLOR: (prof_h, prof_s), + }, data) _, data = dev2.last_call('turn_on') - self.assertEqual( - {light.ATTR_BRIGHTNESS: 100, - light.ATTR_XY_COLOR: (.5119, .4147)}, - data) + self.assertEqual({ + light.ATTR_BRIGHTNESS: 100, + light.ATTR_HS_COLOR: (prof_h, prof_s), + }, data) # Test bad data light.turn_on(self.hass) @@ -301,15 +303,16 @@ class TestLight(unittest.TestCase): _, data = dev1.last_call('turn_on') - self.assertEqual( - {light.ATTR_XY_COLOR: (.4, .6), light.ATTR_BRIGHTNESS: 100}, - data) + self.assertEqual({ + light.ATTR_HS_COLOR: (71.059, 100), + light.ATTR_BRIGHTNESS: 100 + }, data) async def test_intent_set_color(hass): """Test the set color intent.""" 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') 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.""" hass.states.async_set('light.hello_2', 'off', { ATTR_SUPPORTED_FEATURES: ( - light.SUPPORT_RGB_COLOR | light.SUPPORT_BRIGHTNESS) + light.SUPPORT_COLOR | light.SUPPORT_BRIGHTNESS) }) hass.states.async_set('switch.hello', 'off') calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON) diff --git a/tests/components/light/test_mqtt.py b/tests/components/light/test_mqtt.py index 6c56564df69f..71fe77ef6bea 100644 --- a/tests/components/light/test_mqtt.py +++ b/tests/components/light/test_mqtt.py @@ -250,12 +250,12 @@ class TestLightMQTT(unittest.TestCase): state = self.hass.states.get('light.test') 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(150, state.attributes.get('color_temp')) self.assertEqual('none', state.attributes.get('effect')) 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') self.hass.block_till_done() @@ -303,7 +303,7 @@ class TestLightMQTT(unittest.TestCase): self.hass.block_till_done() light_state = self.hass.states.get('light.test') - self.assertEqual([125, 125, 125], + self.assertEqual((255, 255, 255), light_state.attributes.get('rgb_color')) fire_mqtt_message(self.hass, 'test_light_rgb/xy/status', @@ -311,7 +311,7 @@ class TestLightMQTT(unittest.TestCase): self.hass.block_till_done() 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')) def test_brightness_controlling_scale(self): @@ -458,11 +458,11 @@ class TestLightMQTT(unittest.TestCase): state = self.hass.states.get('light.test') self.assertEqual(STATE_ON, state.state) 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('rainbow', state.attributes.get('effect')) 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): \ # pylint: disable=invalid-name @@ -516,18 +516,18 @@ class TestLightMQTT(unittest.TestCase): self.mock_publish.async_publish.assert_has_calls([ 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/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) state = self.hass.states.get('light.test') 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(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): """Test the sending of RGB command with template.""" @@ -554,12 +554,12 @@ class TestLightMQTT(unittest.TestCase): self.mock_publish.async_publish.assert_has_calls([ 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) state = self.hass.states.get('light.test') 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): """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') 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): """Test on command being sent before brightness.""" @@ -799,7 +799,7 @@ class TestLightMQTT(unittest.TestCase): self.hass.block_till_done() 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) ], any_order=True) diff --git a/tests/components/light/test_mqtt_json.py b/tests/components/light/test_mqtt_json.py index ba306a81a34e..cfeffc93108f 100644 --- a/tests/components/light/test_mqtt_json.py +++ b/tests/components/light/test_mqtt_json.py @@ -180,7 +180,7 @@ class TestLightMQTTJSON(unittest.TestCase): state = self.hass.states.get('light.test') 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('brightness')) self.assertIsNone(state.attributes.get('color_temp')) @@ -192,8 +192,7 @@ class TestLightMQTTJSON(unittest.TestCase): # Turn on the light, full white fire_mqtt_message(self.hass, 'test_light_rgb', '{"state":"ON",' - '"color":{"r":255,"g":255,"b":255,' - '"x":0.123,"y":0.123},' + '"color":{"r":255,"g":255,"b":255},' '"brightness":255,' '"color_temp":155,' '"effect":"colorloop",' @@ -202,12 +201,12 @@ class TestLightMQTTJSON(unittest.TestCase): state = self.hass.states.get('light.test') 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(155, state.attributes.get('color_temp')) self.assertEqual('colorloop', state.attributes.get('effect')) 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 fire_mqtt_message(self.hass, 'test_light_rgb', '{"state":"OFF"}') @@ -232,7 +231,7 @@ class TestLightMQTTJSON(unittest.TestCase): self.hass.block_till_done() light_state = self.hass.states.get('light.test') - self.assertEqual([125, 125, 125], + self.assertEqual((255, 255, 255), light_state.attributes.get('rgb_color')) fire_mqtt_message(self.hass, 'test_light_rgb', @@ -241,7 +240,7 @@ class TestLightMQTTJSON(unittest.TestCase): self.hass.block_till_done() 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')) fire_mqtt_message(self.hass, 'test_light_rgb', @@ -503,7 +502,7 @@ class TestLightMQTTJSON(unittest.TestCase): state = self.hass.states.get('light.test') 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('white_value')) @@ -516,7 +515,7 @@ class TestLightMQTTJSON(unittest.TestCase): # Color should not have changed state = self.hass.states.get('light.test') 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 fire_mqtt_message(self.hass, 'test_light_rgb', diff --git a/tests/components/light/test_mqtt_template.py b/tests/components/light/test_mqtt_template.py index 5a01aa15fa2b..90d68dd10d20 100644 --- a/tests/components/light/test_mqtt_template.py +++ b/tests/components/light/test_mqtt_template.py @@ -151,7 +151,7 @@ class TestLightMQTTTemplate(unittest.TestCase): state = self.hass.states.get('light.test') 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(145, state.attributes.get('color_temp')) self.assertEqual(123, state.attributes.get('white_value')) @@ -185,7 +185,8 @@ class TestLightMQTTTemplate(unittest.TestCase): self.hass.block_till_done() 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 fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,,134') @@ -254,7 +255,7 @@ class TestLightMQTTTemplate(unittest.TestCase): self.hass.block_till_done() 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() # turn on the light with color temp and white val @@ -267,7 +268,7 @@ class TestLightMQTTTemplate(unittest.TestCase): # check the state state = self.hass.states.get('light.test') 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(200, state.attributes['color_temp']) self.assertEqual(139, state.attributes['white_value']) @@ -387,7 +388,7 @@ class TestLightMQTTTemplate(unittest.TestCase): self.assertEqual(STATE_ON, state.state) self.assertEqual(255, state.attributes.get('brightness')) 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('rainbow', state.attributes.get('effect')) @@ -421,7 +422,7 @@ class TestLightMQTTTemplate(unittest.TestCase): # color should not have changed 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 fire_mqtt_message(self.hass, 'test_light_rgb', 'on,,,off,255-255-255') diff --git a/tests/components/light/test_zwave.py b/tests/components/light/test_zwave.py index b925b74a7f05..4966b1613602 100644 --- a/tests/components/light/test_zwave.py +++ b/tests/components/light/test_zwave.py @@ -4,9 +4,9 @@ from unittest.mock import patch, MagicMock import homeassistant.components.zwave from homeassistant.components.zwave import const from homeassistant.components.light import ( - zwave, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_TRANSITION, - SUPPORT_BRIGHTNESS, SUPPORT_TRANSITION, SUPPORT_RGB_COLOR, - SUPPORT_COLOR_TEMP) + zwave, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR, ATTR_TRANSITION, + SUPPORT_BRIGHTNESS, SUPPORT_TRANSITION, SUPPORT_COLOR, ATTR_WHITE_VALUE, + SUPPORT_COLOR_TEMP, SUPPORT_WHITE_VALUE) from tests.mock.zwave import ( 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={}) 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): @@ -54,7 +54,23 @@ def test_get_device_detects_zw098(mock_openzwave): device = zwave.get_device(node=node, values=values, node_config={}) assert isinstance(device, zwave.ZwaveColorLight) 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): @@ -203,7 +219,7 @@ def test_dimmer_refresh_value(mock_openzwave): assert device.brightness == 118 -def test_set_rgb_color(mock_openzwave): +def test_set_hs_color(mock_openzwave): """Test setting zwave light color.""" node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) value = MockValue(data=0, node=node) @@ -216,12 +232,12 @@ def test_set_rgb_color(mock_openzwave): 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.""" node = MockNode(command_classes=[const.COMMAND_CLASS_SWITCH_COLOR]) value = MockValue(data=0, node=node) @@ -234,9 +250,9 @@ def test_set_rgbw_color(mock_openzwave): 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): @@ -273,7 +289,7 @@ def test_rgb_not_supported(mock_openzwave): color_channels=color_channels) 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): @@ -283,7 +299,7 @@ def test_no_color_value(mock_openzwave): values = MockLightValues(primary=value) 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): @@ -294,7 +310,7 @@ def test_no_color_channels_value(mock_openzwave): values = MockLightValues(primary=value, color=color) 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): @@ -308,12 +324,12 @@ def test_rgb_value_changed(mock_openzwave): color_channels=color_channels) 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) - assert device.rgb_color == [200, 150, 100] + assert device.hs_color == (29.764, 49.804) def test_rgbww_value_changed(mock_openzwave): @@ -327,12 +343,14 @@ def test_rgbww_value_changed(mock_openzwave): color_channels=color_channels) 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' 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): @@ -346,12 +364,14 @@ def test_rgbcw_value_changed(mock_openzwave): color_channels=color_channels) 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' 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): diff --git a/tests/testing_config/.remember_the_milk.conf b/tests/testing_config/.remember_the_milk.conf new file mode 100644 index 000000000000..272ac0903bda --- /dev/null +++ b/tests/testing_config/.remember_the_milk.conf @@ -0,0 +1 @@ +{"myprofile": {"id_map": {}}} \ No newline at end of file diff --git a/tests/testing_config/custom_components/light/test.py b/tests/testing_config/custom_components/light/test.py index fafe88eecbeb..71625dfdf933 100644 --- a/tests/testing_config/custom_components/light/test.py +++ b/tests/testing_config/custom_components/light/test.py @@ -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. """ diff --git a/tests/util/test_color.py b/tests/util/test_color.py index 86d303c23b7d..b64cf0acf80d 100644 --- a/tests/util/test_color.py +++ b/tests/util/test_color.py @@ -10,26 +10,52 @@ class TestColorUtil(unittest.TestCase): """Test color util methods.""" # pylint: disable=invalid-name - def test_color_RGB_to_xy(self): - """Test color_RGB_to_xy.""" - self.assertEqual((0, 0, 0), color_util.color_RGB_to_xy(0, 0, 0)) + def test_color_RGB_to_xy_brightness(self): + """Test color_RGB_to_xy_brightness.""" + self.assertEqual((0, 0, 0), + color_util.color_RGB_to_xy_brightness(0, 0, 0)) 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), - 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), - 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), + 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)) + self.assertEqual((0.679, 0.321), + color_util.color_RGB_to_xy(128, 0, 0)) + def test_color_xy_brightness_to_RGB(self): - """Test color_RGB_to_xy.""" + """Test color_xy_brightness_to_RGB.""" self.assertEqual((0, 0, 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), color_util.color_xy_brightness_to_RGB(.35, .35, 255)) @@ -42,6 +68,20 @@ class TestColorUtil(unittest.TestCase): self.assertEqual((0, 63, 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): """Test color_RGB_to_hsv.""" self.assertEqual((0, 0, 0), @@ -110,6 +150,23 @@ class TestColorUtil(unittest.TestCase): self.assertEqual((225.176, 100), 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): """Test rgb_hex_to_rgb_list.""" self.assertEqual([255, 255, 255],