Handle color temp to RGBWW conversion (#61473)
Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
parent
12671b370e
commit
94ae6ac2b2
4 changed files with 140 additions and 8 deletions
|
@ -382,14 +382,22 @@ async def async_setup(hass, config): # noqa: C901
|
||||||
params[ATTR_WHITE_VALUE] = rgbw_color[3]
|
params[ATTR_WHITE_VALUE] = rgbw_color[3]
|
||||||
|
|
||||||
# If a color temperature is specified, emulate it if not supported by the light
|
# If a color temperature is specified, emulate it if not supported by the light
|
||||||
if (
|
if ATTR_COLOR_TEMP in params:
|
||||||
ATTR_COLOR_TEMP in params
|
if (
|
||||||
and COLOR_MODE_COLOR_TEMP not in legacy_supported_color_modes
|
supported_color_modes
|
||||||
):
|
and COLOR_MODE_COLOR_TEMP not in supported_color_modes
|
||||||
color_temp = params.pop(ATTR_COLOR_TEMP)
|
and COLOR_MODE_RGBWW in supported_color_modes
|
||||||
if color_supported(legacy_supported_color_modes):
|
):
|
||||||
temp_k = color_util.color_temperature_mired_to_kelvin(color_temp)
|
color_temp = params.pop(ATTR_COLOR_TEMP)
|
||||||
params[ATTR_HS_COLOR] = color_util.color_temperature_to_hs(temp_k)
|
brightness = params.get(ATTR_BRIGHTNESS, light.brightness)
|
||||||
|
params[ATTR_RGBWW_COLOR] = color_util.color_temperature_to_rgbww(
|
||||||
|
color_temp, brightness, light.min_mireds, light.max_mireds
|
||||||
|
)
|
||||||
|
elif COLOR_MODE_COLOR_TEMP not in legacy_supported_color_modes:
|
||||||
|
color_temp = params.pop(ATTR_COLOR_TEMP)
|
||||||
|
if color_supported(legacy_supported_color_modes):
|
||||||
|
temp_k = color_util.color_temperature_mired_to_kelvin(color_temp)
|
||||||
|
params[ATTR_HS_COLOR] = color_util.color_temperature_to_hs(temp_k)
|
||||||
|
|
||||||
# If a color is specified, convert to the color space supported by the light
|
# If a color is specified, convert to the color space supported by the light
|
||||||
# Backwards compatibility: Fall back to hs color if light.supported_color_modes
|
# Backwards compatibility: Fall back to hs color if light.supported_color_modes
|
||||||
|
|
|
@ -528,6 +528,16 @@ def color_temperature_to_rgb(
|
||||||
return red, green, blue
|
return red, green, blue
|
||||||
|
|
||||||
|
|
||||||
|
def color_temperature_to_rgbww(
|
||||||
|
temperature: int, brightness: int, min_mireds: int, max_mireds: int
|
||||||
|
) -> tuple[int, int, int, int, int]:
|
||||||
|
"""Convert color temperature to rgbcw."""
|
||||||
|
mired_range = max_mireds - min_mireds
|
||||||
|
warm = ((max_mireds - temperature) / mired_range) * brightness
|
||||||
|
cold = brightness - warm
|
||||||
|
return (0, 0, 0, round(cold), round(warm))
|
||||||
|
|
||||||
|
|
||||||
def _clamp(color_component: float, minimum: float = 0, maximum: float = 255) -> float:
|
def _clamp(color_component: float, minimum: float = 0, maximum: float = 255) -> float:
|
||||||
"""
|
"""
|
||||||
Clamp the given color component value between the given min and max values.
|
Clamp the given color component value between the given min and max values.
|
||||||
|
|
|
@ -1852,6 +1852,74 @@ async def test_light_service_call_color_temp_emulation(
|
||||||
assert data == {"brightness": 255, "hs_color": (27.001, 19.243)}
|
assert data == {"brightness": 255, "hs_color": (27.001, 19.243)}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_light_service_call_color_temp_conversion(
|
||||||
|
hass, enable_custom_integrations
|
||||||
|
):
|
||||||
|
"""Test color temp conversion in service calls."""
|
||||||
|
platform = getattr(hass.components, "test.light")
|
||||||
|
platform.init(empty=True)
|
||||||
|
|
||||||
|
platform.ENTITIES.append(platform.MockLight("Test_rgbww_ct", STATE_ON))
|
||||||
|
platform.ENTITIES.append(platform.MockLight("Test_rgbww", STATE_ON))
|
||||||
|
|
||||||
|
entity0 = platform.ENTITIES[0]
|
||||||
|
entity0.supported_color_modes = {
|
||||||
|
light.COLOR_MODE_COLOR_TEMP,
|
||||||
|
light.COLOR_MODE_RGBWW,
|
||||||
|
}
|
||||||
|
|
||||||
|
entity1 = platform.ENTITIES[1]
|
||||||
|
entity1.supported_color_modes = {light.COLOR_MODE_RGBWW}
|
||||||
|
|
||||||
|
assert await async_setup_component(hass, "light", {"light": {"platform": "test"}})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get(entity0.entity_id)
|
||||||
|
assert state.attributes["supported_color_modes"] == [
|
||||||
|
light.COLOR_MODE_COLOR_TEMP,
|
||||||
|
light.COLOR_MODE_RGBWW,
|
||||||
|
]
|
||||||
|
|
||||||
|
state = hass.states.get(entity1.entity_id)
|
||||||
|
assert state.attributes["supported_color_modes"] == [light.COLOR_MODE_RGBWW]
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
"light",
|
||||||
|
"turn_on",
|
||||||
|
{
|
||||||
|
"entity_id": [
|
||||||
|
entity0.entity_id,
|
||||||
|
entity1.entity_id,
|
||||||
|
],
|
||||||
|
"brightness_pct": 100,
|
||||||
|
"color_temp": 153,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
_, data = entity0.last_call("turn_on")
|
||||||
|
assert data == {"brightness": 255, "color_temp": 153}
|
||||||
|
_, data = entity1.last_call("turn_on")
|
||||||
|
assert data == {"brightness": 255, "rgbww_color": (0, 0, 0, 0, 255)}
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
"light",
|
||||||
|
"turn_on",
|
||||||
|
{
|
||||||
|
"entity_id": [
|
||||||
|
entity0.entity_id,
|
||||||
|
entity1.entity_id,
|
||||||
|
],
|
||||||
|
"brightness_pct": 50,
|
||||||
|
"color_temp": 500,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
_, data = entity0.last_call("turn_on")
|
||||||
|
assert data == {"brightness": 128, "color_temp": 500}
|
||||||
|
_, data = entity1.last_call("turn_on")
|
||||||
|
assert data == {"brightness": 128, "rgbww_color": (0, 0, 0, 128, 0)}
|
||||||
|
|
||||||
|
|
||||||
async def test_light_service_call_white_mode(hass, enable_custom_integrations):
|
async def test_light_service_call_white_mode(hass, enable_custom_integrations):
|
||||||
"""Test color_mode white in service calls."""
|
"""Test color_mode white in service calls."""
|
||||||
platform = getattr(hass.components, "test.light")
|
platform = getattr(hass.components, "test.light")
|
||||||
|
|
|
@ -401,3 +401,49 @@ def test_color_rgb_to_rgbww():
|
||||||
assert color_util.color_rgb_to_rgbww(64, 64, 64, 154, 370) == (0, 14, 25, 64, 64)
|
assert color_util.color_rgb_to_rgbww(64, 64, 64, 154, 370) == (0, 14, 25, 64, 64)
|
||||||
assert color_util.color_rgb_to_rgbww(32, 64, 16, 154, 370) == (9, 64, 0, 38, 38)
|
assert color_util.color_rgb_to_rgbww(32, 64, 16, 154, 370) == (9, 64, 0, 38, 38)
|
||||||
assert color_util.color_rgb_to_rgbww(0, 0, 0, 154, 370) == (0, 0, 0, 0, 0)
|
assert color_util.color_rgb_to_rgbww(0, 0, 0, 154, 370) == (0, 0, 0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_color_temperature_to_rgbww():
|
||||||
|
"""Test color temp to warm, cold conversion."""
|
||||||
|
assert color_util.color_temperature_to_rgbww(153, 255, 153, 500) == (
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
)
|
||||||
|
assert color_util.color_temperature_to_rgbww(153, 128, 153, 500) == (
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
128,
|
||||||
|
)
|
||||||
|
assert color_util.color_temperature_to_rgbww(500, 255, 153, 500) == (
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
assert color_util.color_temperature_to_rgbww(500, 128, 153, 500) == (
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
128,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
assert color_util.color_temperature_to_rgbww(347, 255, 153, 500) == (
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
143,
|
||||||
|
112,
|
||||||
|
)
|
||||||
|
assert color_util.color_temperature_to_rgbww(347, 128, 153, 500) == (
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
72,
|
||||||
|
56,
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue