From 64a7be66b1859ed2c96ba3ecd8f3fb5ebf9d1566 Mon Sep 17 00:00:00 2001 From: Anders Melchiorsen Date: Sun, 30 Apr 2017 00:04:20 +0200 Subject: [PATCH] Remove global limit on white light temperature (#7206) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove global limit on white light temperature Here are the supported temperatures of some popular bulbs: Philips Hue: 2000K-6500K (the current 500-154 mired range) LIFX Color 1000: 2500K-9000K IKEA TRÅDFRI: 2200K, 2700K, 4000K Obviously, Home Assistant cannot enforce a global limit and work properly with all of these bulbs. So just remove the limit and leave it up to each platform to work it out. This commit updates the existing users and adds a clamp to Hue (where the limit appears to have originated). It does not attempt to update other platforms that might need extra handling of the larger range that is now possible. * Add min_mireds/max_mireds state attributes to lights * Support min_mireds/max_mireds with LIFX lights --- homeassistant/components/light/__init__.py | 20 ++++++++++-- homeassistant/components/light/hue.py | 3 +- .../components/light/lifx/__init__.py | 31 ++++++++++++++++++- homeassistant/components/light/services.yaml | 2 +- homeassistant/components/light/zwave.py | 13 ++++---- homeassistant/components/switch/flux.py | 3 +- homeassistant/util/color.py | 3 -- tests/components/light/test_demo.py | 2 ++ 8 files changed, 60 insertions(+), 17 deletions(-) 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):