mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 23:57:06 +00:00
Migrate hue lights to use Kelvin (#132835)
This commit is contained in:
parent
6f3a230524
commit
416a4c02b4
@ -12,7 +12,7 @@ import aiohue
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_COLOR_TEMP,
|
||||
ATTR_COLOR_TEMP_KELVIN,
|
||||
ATTR_EFFECT,
|
||||
ATTR_FLASH,
|
||||
ATTR_HS_COLOR,
|
||||
@ -35,7 +35,7 @@ from homeassistant.helpers.update_coordinator import (
|
||||
DataUpdateCoordinator,
|
||||
UpdateFailed,
|
||||
)
|
||||
from homeassistant.util import color
|
||||
from homeassistant.util import color as color_util
|
||||
|
||||
from ..bridge import HueBridge
|
||||
from ..const import (
|
||||
@ -362,7 +362,7 @@ class HueLight(CoordinatorEntity, LightEntity):
|
||||
"bulb in the Philips Hue App."
|
||||
)
|
||||
LOGGER.warning(err, self.name)
|
||||
if self.gamut and not color.check_valid_gamut(self.gamut):
|
||||
if self.gamut and not color_util.check_valid_gamut(self.gamut):
|
||||
err = "Color gamut of %s: %s, not valid, setting gamut to None."
|
||||
LOGGER.debug(err, self.name, str(self.gamut))
|
||||
self.gamut_typ = GAMUT_TYPE_UNAVAILABLE
|
||||
@ -427,49 +427,50 @@ class HueLight(CoordinatorEntity, LightEntity):
|
||||
source = self.light.action if self.is_group else self.light.state
|
||||
|
||||
if mode in ("xy", "hs") and "xy" in source:
|
||||
return color.color_xy_to_hs(*source["xy"], self.gamut)
|
||||
return color_util.color_xy_to_hs(*source["xy"], self.gamut)
|
||||
|
||||
return None
|
||||
|
||||
@property
|
||||
def color_temp(self):
|
||||
"""Return the CT color value."""
|
||||
def color_temp_kelvin(self) -> int | None:
|
||||
"""Return the color temperature value in Kelvin."""
|
||||
# Don't return color temperature unless in color temperature mode
|
||||
if self._color_mode != "ct":
|
||||
return None
|
||||
|
||||
if self.is_group:
|
||||
return self.light.action.get("ct")
|
||||
return self.light.state.get("ct")
|
||||
ct = (
|
||||
self.light.action.get("ct") if self.is_group else self.light.state.get("ct")
|
||||
)
|
||||
return color_util.color_temperature_mired_to_kelvin(ct) if ct else None
|
||||
|
||||
@property
|
||||
def min_mireds(self):
|
||||
"""Return the coldest color_temp that this light supports."""
|
||||
def max_color_temp_kelvin(self) -> int:
|
||||
"""Return the coldest color_temp_kelvin that this light supports."""
|
||||
if self.is_group:
|
||||
return super().min_mireds
|
||||
return super().max_color_temp_kelvin
|
||||
|
||||
min_mireds = self.light.controlcapabilities.get("ct", {}).get("min")
|
||||
|
||||
# We filter out '0' too, which can be incorrectly reported by 3rd party buls
|
||||
if not min_mireds:
|
||||
return super().min_mireds
|
||||
return super().max_color_temp_kelvin
|
||||
|
||||
return min_mireds
|
||||
return color_util.color_temperature_mired_to_kelvin(min_mireds)
|
||||
|
||||
@property
|
||||
def max_mireds(self):
|
||||
"""Return the warmest color_temp that this light supports."""
|
||||
def min_color_temp_kelvin(self) -> int:
|
||||
"""Return the warmest color_temp_kelvin that this light supports."""
|
||||
if self.is_group:
|
||||
return super().max_mireds
|
||||
return super().min_color_temp_kelvin
|
||||
if self.is_livarno:
|
||||
return 500
|
||||
|
||||
max_mireds = self.light.controlcapabilities.get("ct", {}).get("max")
|
||||
|
||||
if not max_mireds:
|
||||
return super().max_mireds
|
||||
return super().min_color_temp_kelvin
|
||||
|
||||
return max_mireds
|
||||
return color_util.color_temperature_mired_to_kelvin(max_mireds)
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
@ -541,11 +542,14 @@ class HueLight(CoordinatorEntity, LightEntity):
|
||||
# Philips hue bulb models respond differently to hue/sat
|
||||
# requests, so we convert to XY first to ensure a consistent
|
||||
# color.
|
||||
xy_color = color.color_hs_to_xy(*kwargs[ATTR_HS_COLOR], self.gamut)
|
||||
xy_color = color_util.color_hs_to_xy(*kwargs[ATTR_HS_COLOR], self.gamut)
|
||||
command["xy"] = xy_color
|
||||
elif ATTR_COLOR_TEMP in kwargs:
|
||||
temp = kwargs[ATTR_COLOR_TEMP]
|
||||
command["ct"] = max(self.min_mireds, min(temp, self.max_mireds))
|
||||
elif ATTR_COLOR_TEMP_KELVIN in kwargs:
|
||||
temp_k = max(
|
||||
self.min_color_temp_kelvin,
|
||||
min(self.max_color_temp_kelvin, kwargs[ATTR_COLOR_TEMP_KELVIN]),
|
||||
)
|
||||
command["ct"] = color_util.color_temperature_kelvin_to_mired(temp_k)
|
||||
|
||||
if ATTR_BRIGHTNESS in kwargs:
|
||||
command["bri"] = hass_to_hue_brightness(kwargs[ATTR_BRIGHTNESS])
|
||||
|
@ -12,7 +12,7 @@ from aiohue.v2.models.feature import DynamicStatus
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_COLOR_TEMP,
|
||||
ATTR_COLOR_TEMP_KELVIN,
|
||||
ATTR_FLASH,
|
||||
ATTR_TRANSITION,
|
||||
ATTR_XY_COLOR,
|
||||
@ -27,6 +27,7 @@ from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
import homeassistant.helpers.entity_registry as er
|
||||
from homeassistant.util import color as color_util
|
||||
|
||||
from ..bridge import HueBridge
|
||||
from ..const import DOMAIN
|
||||
@ -157,7 +158,7 @@ class GroupedHueLight(HueBaseEntity, LightEntity):
|
||||
"""Turn the grouped_light on."""
|
||||
transition = normalize_hue_transition(kwargs.get(ATTR_TRANSITION))
|
||||
xy_color = kwargs.get(ATTR_XY_COLOR)
|
||||
color_temp = normalize_hue_colortemp(kwargs.get(ATTR_COLOR_TEMP))
|
||||
color_temp = normalize_hue_colortemp(kwargs.get(ATTR_COLOR_TEMP_KELVIN))
|
||||
brightness = normalize_hue_brightness(kwargs.get(ATTR_BRIGHTNESS))
|
||||
flash = kwargs.get(ATTR_FLASH)
|
||||
|
||||
@ -235,9 +236,21 @@ class GroupedHueLight(HueBaseEntity, LightEntity):
|
||||
if color_temp := light.color_temperature:
|
||||
lights_with_color_temp_support += 1
|
||||
# we assume mired values from the first capable light
|
||||
self._attr_color_temp = color_temp.mirek
|
||||
self._attr_max_mireds = color_temp.mirek_schema.mirek_maximum
|
||||
self._attr_min_mireds = color_temp.mirek_schema.mirek_minimum
|
||||
self._attr_color_temp_kelvin = (
|
||||
color_util.color_temperature_mired_to_kelvin(color_temp.mirek)
|
||||
if color_temp.mirek
|
||||
else None
|
||||
)
|
||||
self._attr_min_color_temp_kelvin = (
|
||||
color_util.color_temperature_mired_to_kelvin(
|
||||
color_temp.mirek_schema.mirek_maximum
|
||||
)
|
||||
)
|
||||
self._attr_max_color_temp_kelvin = (
|
||||
color_util.color_temperature_mired_to_kelvin(
|
||||
color_temp.mirek_schema.mirek_minimum
|
||||
)
|
||||
)
|
||||
if color_temp.mirek is not None and color_temp.mirek_valid:
|
||||
lights_in_colortemp_mode += 1
|
||||
if color := light.color:
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.util import color as color_util
|
||||
|
||||
|
||||
def normalize_hue_brightness(brightness: float | None) -> float | None:
|
||||
"""Return calculated brightness values."""
|
||||
@ -21,10 +23,11 @@ def normalize_hue_transition(transition: float | None) -> float | None:
|
||||
return transition
|
||||
|
||||
|
||||
def normalize_hue_colortemp(colortemp: int | None) -> int | None:
|
||||
def normalize_hue_colortemp(colortemp_k: int | None) -> int | None:
|
||||
"""Return color temperature within Hue's ranges."""
|
||||
if colortemp is not None:
|
||||
# Hue only accepts a range between 153..500
|
||||
colortemp = min(colortemp, 500)
|
||||
colortemp = max(colortemp, 153)
|
||||
return colortemp
|
||||
if colortemp_k is None:
|
||||
return None
|
||||
colortemp = color_util.color_temperature_kelvin_to_mired(colortemp_k)
|
||||
# Hue only accepts a range between 153..500
|
||||
colortemp = min(colortemp, 500)
|
||||
return max(colortemp, 153)
|
||||
|
@ -13,7 +13,7 @@ from aiohue.v2.models.light import Light
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_COLOR_TEMP,
|
||||
ATTR_COLOR_TEMP_KELVIN,
|
||||
ATTR_EFFECT,
|
||||
ATTR_FLASH,
|
||||
ATTR_TRANSITION,
|
||||
@ -28,6 +28,7 @@ from homeassistant.components.light import (
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.util import color as color_util
|
||||
|
||||
from ..bridge import HueBridge
|
||||
from ..const import DOMAIN
|
||||
@ -39,9 +40,9 @@ from .helpers import (
|
||||
)
|
||||
|
||||
EFFECT_NONE = "None"
|
||||
FALLBACK_MIN_MIREDS = 153 # 6500 K
|
||||
FALLBACK_MAX_MIREDS = 500 # 2000 K
|
||||
FALLBACK_MIREDS = 173 # halfway
|
||||
FALLBACK_MIN_KELVIN = 6500
|
||||
FALLBACK_MAX_KELVIN = 2000
|
||||
FALLBACK_KELVIN = 5800 # halfway
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
@ -164,28 +165,32 @@ class HueLight(HueBaseEntity, LightEntity):
|
||||
return None
|
||||
|
||||
@property
|
||||
def color_temp(self) -> int:
|
||||
"""Return the color temperature."""
|
||||
def color_temp_kelvin(self) -> int | None:
|
||||
"""Return the color temperature value in Kelvin."""
|
||||
if color_temp := self.resource.color_temperature:
|
||||
return color_temp.mirek
|
||||
return color_util.color_temperature_mired_to_kelvin(color_temp.mirek)
|
||||
# return a fallback value to prevent issues with mired->kelvin conversions
|
||||
return FALLBACK_MIREDS
|
||||
return FALLBACK_KELVIN
|
||||
|
||||
@property
|
||||
def min_mireds(self) -> int:
|
||||
"""Return the coldest color_temp that this light supports."""
|
||||
def max_color_temp_kelvin(self) -> int:
|
||||
"""Return the coldest color_temp_kelvin that this light supports."""
|
||||
if color_temp := self.resource.color_temperature:
|
||||
return color_temp.mirek_schema.mirek_minimum
|
||||
return color_util.color_temperature_mired_to_kelvin(
|
||||
color_temp.mirek_schema.mirek_minimum
|
||||
)
|
||||
# return a fallback value to prevent issues with mired->kelvin conversions
|
||||
return FALLBACK_MIN_MIREDS
|
||||
return FALLBACK_MAX_KELVIN
|
||||
|
||||
@property
|
||||
def max_mireds(self) -> int:
|
||||
"""Return the warmest color_temp that this light supports."""
|
||||
def min_color_temp_kelvin(self) -> int:
|
||||
"""Return the warmest color_temp_kelvin that this light supports."""
|
||||
if color_temp := self.resource.color_temperature:
|
||||
return color_temp.mirek_schema.mirek_maximum
|
||||
return color_util.color_temperature_mired_to_kelvin(
|
||||
color_temp.mirek_schema.mirek_maximum
|
||||
)
|
||||
# return a fallback value to prevent issues with mired->kelvin conversions
|
||||
return FALLBACK_MAX_MIREDS
|
||||
return FALLBACK_MIN_KELVIN
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict[str, str] | None:
|
||||
@ -210,7 +215,7 @@ class HueLight(HueBaseEntity, LightEntity):
|
||||
"""Turn the device on."""
|
||||
transition = normalize_hue_transition(kwargs.get(ATTR_TRANSITION))
|
||||
xy_color = kwargs.get(ATTR_XY_COLOR)
|
||||
color_temp = normalize_hue_colortemp(kwargs.get(ATTR_COLOR_TEMP))
|
||||
color_temp = normalize_hue_colortemp(kwargs.get(ATTR_COLOR_TEMP_KELVIN))
|
||||
brightness = normalize_hue_brightness(kwargs.get(ATTR_BRIGHTNESS))
|
||||
if self._last_brightness and brightness is None:
|
||||
# The Hue bridge sets the brightness to 1% when turning on a bulb
|
||||
|
Loading…
x
Reference in New Issue
Block a user