diff --git a/homeassistant/components/light/__init__.py b/homeassistant/components/light/__init__.py index 25dcf9e78da..853fe4d9fb1 100644 --- a/homeassistant/components/light/__init__.py +++ b/homeassistant/components/light/__init__.py @@ -50,6 +50,8 @@ ATTR_TRANSITION = "transition" ATTR_RGB_COLOR = "rgb_color" ATTR_XY_COLOR = "xy_color" ATTR_COLOR_TEMP = "color_temp" +ATTR_MIN_MIREDS = "min_mireds" +ATTR_MAX_MIREDS = "max_mireds" ATTR_COLOR_NAME = "color_name" ATTR_WHITE_VALUE = "white_value" @@ -78,6 +80,8 @@ LIGHT_PROFILES_FILE = "light_profiles.csv" PROP_TO_ATTR = { 'brightness': ATTR_BRIGHTNESS, 'color_temp': ATTR_COLOR_TEMP, + 'min_mireds': ATTR_MIN_MIREDS, + 'max_mireds': ATTR_MAX_MIREDS, 'rgb_color': ATTR_RGB_COLOR, 'xy_color': ATTR_XY_COLOR, 'white_value': ATTR_WHITE_VALUE, @@ -99,9 +103,7 @@ LIGHT_TURN_ON_SCHEMA = vol.Schema({ vol.Coerce(tuple)), ATTR_XY_COLOR: vol.All(vol.ExactSequence((cv.small_float, cv.small_float)), vol.Coerce(tuple)), - ATTR_COLOR_TEMP: vol.All(vol.Coerce(int), - vol.Range(min=color_util.HASS_COLOR_MIN, - max=color_util.HASS_COLOR_MAX)), + ATTR_COLOR_TEMP: vol.All(vol.Coerce(int), vol.Range(min=1)), ATTR_WHITE_VALUE: vol.All(vol.Coerce(int), vol.Range(min=0, max=255)), ATTR_FLASH: vol.In([FLASH_SHORT, FLASH_LONG]), ATTR_EFFECT: cv.string, @@ -337,6 +339,18 @@ class Light(ToggleEntity): """Return the CT color value in mireds.""" return None + @property + def min_mireds(self): + """Return the coldest color_temp that this light supports.""" + # Default to the Philips Hue value that HA has always assumed + return 154 + + @property + def max_mireds(self): + """Return the warmest color_temp that this light supports.""" + # Default to the Philips Hue value that HA has always assumed + return 500 + @property def white_value(self): """Return the white value of this light between 0..255.""" diff --git a/homeassistant/components/light/hue.py b/homeassistant/components/light/hue.py index c15acdd2b44..77981ea6e68 100644 --- a/homeassistant/components/light/hue.py +++ b/homeassistant/components/light/hue.py @@ -403,7 +403,8 @@ class HueLight(Light): command['bri'] = kwargs[ATTR_BRIGHTNESS] if ATTR_COLOR_TEMP in kwargs: - command['ct'] = kwargs[ATTR_COLOR_TEMP] + temp = kwargs[ATTR_COLOR_TEMP] + command['ct'] = max(self.min_mireds, min(temp, self.max_mireds)) flash = kwargs.get(ATTR_FLASH) diff --git a/homeassistant/components/light/lifx/__init__.py b/homeassistant/components/light/lifx/__init__.py index 33ed80bed06..9a44938308e 100644 --- a/homeassistant/components/light/lifx/__init__.py +++ b/homeassistant/components/light/lifx/__init__.py @@ -8,6 +8,7 @@ import colorsys import logging import asyncio import sys +import math from functools import partial from datetime import timedelta import async_timeout @@ -96,7 +97,12 @@ class LIFXManager(object): self.hass.async_add_job(entity.async_update_ha_state()) else: _LOGGER.debug("%s register NEW", device.ip_addr) - device.get_color(self.ready) + device.get_version(self.got_version) + + @callback + def got_version(self, device, msg): + """Request current color setting once we have the product version.""" + device.get_color(self.ready) @callback def ready(self, device, msg): @@ -166,6 +172,7 @@ class LIFXLight(Light): def __init__(self, device): """Initialize the light.""" self.device = device + self.product = device.product self.blocker = None self.effect_data = None self.postponed_update = None @@ -213,6 +220,28 @@ class LIFXLight(Light): _LOGGER.debug("color_temp: %d", temperature) return temperature + @property + def min_mireds(self): + """Return the coldest color_temp that this light supports.""" + # The 3 LIFX "White" products supported a limited temperature range + # https://lan.developer.lifx.com/docs/lifx-products + if self.product in [10, 11, 18]: + kelvin = 6500 + else: + kelvin = 9000 + return math.floor(color_temperature_kelvin_to_mired(kelvin)) + + @property + def max_mireds(self): + """Return the warmest color_temp that this light supports.""" + # The 3 LIFX "White" products supported a limited temperature range + # https://lan.developer.lifx.com/docs/lifx-products + if self.product in [10, 11, 18]: + kelvin = 2700 + else: + kelvin = 2500 + return math.ceil(color_temperature_kelvin_to_mired(kelvin)) + @property def is_on(self): """Return true if device is on.""" diff --git a/homeassistant/components/light/services.yaml b/homeassistant/components/light/services.yaml index 8931a46bb73..495ef9c8b39 100644 --- a/homeassistant/components/light/services.yaml +++ b/homeassistant/components/light/services.yaml @@ -25,7 +25,7 @@ turn_on: example: '[0.52, 0.43]' color_temp: - description: Color temperature for the light in mireds (154-500) + description: Color temperature for the light in mireds example: '250' white_value: diff --git a/homeassistant/components/light/zwave.py b/homeassistant/components/light/zwave.py index ce85276cae9..0b43878d025 100644 --- a/homeassistant/components/light/zwave.py +++ b/homeassistant/components/light/zwave.py @@ -15,9 +15,8 @@ from homeassistant.components.light import ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, \ 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 HASS_COLOR_MAX, HASS_COLOR_MIN, \ - color_temperature_mired_to_kelvin, color_temperature_to_rgb, \ - color_rgb_to_rgbw, color_rgbw_to_rgb +from homeassistant.util.color import color_temperature_mired_to_kelvin, \ + color_temperature_to_rgb, color_rgb_to_rgbw, color_rgbw_to_rgb _LOGGER = logging.getLogger(__name__) @@ -39,9 +38,11 @@ DEVICE_MAPPINGS = { # Generate midpoint color temperatures for bulbs that have limited # support for white light colors -TEMP_MID_HASS = (HASS_COLOR_MAX - HASS_COLOR_MIN) / 2 + HASS_COLOR_MIN -TEMP_WARM_HASS = (HASS_COLOR_MAX - HASS_COLOR_MIN) / 3 * 2 + HASS_COLOR_MIN -TEMP_COLD_HASS = (HASS_COLOR_MAX - HASS_COLOR_MIN) / 3 + HASS_COLOR_MIN +TEMP_COLOR_MAX = 500 # mireds (inverted) +TEMP_COLOR_MIN = 154 +TEMP_MID_HASS = (TEMP_COLOR_MAX - TEMP_COLOR_MIN) / 2 + TEMP_COLOR_MIN +TEMP_WARM_HASS = (TEMP_COLOR_MAX - TEMP_COLOR_MIN) / 3 * 2 + TEMP_COLOR_MIN +TEMP_COLD_HASS = (TEMP_COLOR_MAX - TEMP_COLOR_MIN) / 3 + TEMP_COLOR_MIN def get_device(node, values, node_config, **kwargs): diff --git a/homeassistant/components/switch/flux.py b/homeassistant/components/switch/flux.py index 354e3b409db..0c58fb2a182 100644 --- a/homeassistant/components/switch/flux.py +++ b/homeassistant/components/switch/flux.py @@ -17,7 +17,7 @@ from homeassistant.const import CONF_NAME, CONF_PLATFORM from homeassistant.helpers.event import track_time_change from homeassistant.util.color import ( color_temperature_to_rgb, color_RGB_to_xy, - color_temperature_kelvin_to_mired, HASS_COLOR_MIN, HASS_COLOR_MAX) + color_temperature_kelvin_to_mired) from homeassistant.util.dt import now as dt_now import homeassistant.helpers.config_validation as cv @@ -208,7 +208,6 @@ class FluxSwitch(SwitchDevice): else: # Convert to mired and clamp to allowed values mired = color_temperature_kelvin_to_mired(temp) - mired = max(HASS_COLOR_MIN, min(mired, HASS_COLOR_MAX)) set_lights_temp(self.hass, self._lights, mired, brightness) _LOGGER.info("Lights updated to mired:%s brightness:%s, %s%%" " of %s cycle complete at %s", mired, brightness, diff --git a/homeassistant/util/color.py b/homeassistant/util/color.py index a925ea337fb..396b8a63601 100644 --- a/homeassistant/util/color.py +++ b/homeassistant/util/color.py @@ -7,9 +7,6 @@ from typing import Tuple _LOGGER = logging.getLogger(__name__) -HASS_COLOR_MAX = 500 # mireds (inverted) -HASS_COLOR_MIN = 154 - # Official CSS3 colors from w3.org: # https://www.w3.org/TR/2010/PR-css3-color-20101028/#html4 # names do not have spaces in them so that we can compare against diff --git a/tests/components/light/test_demo.py b/tests/components/light/test_demo.py index f51b5a45b20..9e318ea9192 100644 --- a/tests/components/light/test_demo.py +++ b/tests/components/light/test_demo.py @@ -53,6 +53,8 @@ class TestDemoLight(unittest.TestCase): self.hass.block_till_done() state = self.hass.states.get(ENTITY_LIGHT) self.assertEqual(400, state.attributes.get(light.ATTR_COLOR_TEMP)) + self.assertEqual(154, state.attributes.get(light.ATTR_MIN_MIREDS)) + self.assertEqual(500, state.attributes.get(light.ATTR_MAX_MIREDS)) self.assertEqual('none', state.attributes.get(light.ATTR_EFFECT)) def test_turn_off(self):