From fdadacd158a817154adb68cd9098b3d2accf709b Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 27 Apr 2021 20:07:55 +0200 Subject: [PATCH] Improve color conversion for RGBW lights (#49764) --- homeassistant/components/light/__init__.py | 15 ++++++--- tests/components/light/test_init.py | 36 ++++++++++++++++++++++ tests/components/mqtt/test_light_json.py | 6 ++-- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/light/__init__.py b/homeassistant/components/light/__init__.py index dba75b805ad..0328da7c1bc 100644 --- a/homeassistant/components/light/__init__.py +++ b/homeassistant/components/light/__init__.py @@ -71,7 +71,7 @@ VALID_COLOR_MODES = { COLOR_MODE_RGBWW, } COLOR_MODES_BRIGHTNESS = VALID_COLOR_MODES - {COLOR_MODE_ONOFF} -COLOR_MODES_COLOR = {COLOR_MODE_HS, COLOR_MODE_RGB, COLOR_MODE_XY} +COLOR_MODES_COLOR = {COLOR_MODE_HS, COLOR_MODE_RGB, COLOR_MODE_RGBW, COLOR_MODE_XY} def valid_supported_color_modes(color_modes): @@ -318,7 +318,8 @@ async def async_setup(hass, config): # noqa: C901 if COLOR_MODE_RGB in supported_color_modes: params[ATTR_RGB_COLOR] = color_util.color_hs_to_RGB(*hs_color) elif COLOR_MODE_RGBW in supported_color_modes: - params[ATTR_RGBW_COLOR] = (*color_util.color_hs_to_RGB(*hs_color), 0) + rgb_color = color_util.color_hs_to_RGB(*hs_color) + params[ATTR_RGBW_COLOR] = color_util.color_rgb_to_rgbw(*rgb_color) elif COLOR_MODE_RGBWW in supported_color_modes: params[ATTR_RGBWW_COLOR] = ( *color_util.color_hs_to_RGB(*hs_color), @@ -685,6 +686,13 @@ class LightEntity(ToggleEntity): data[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color) data[ATTR_RGB_COLOR] = tuple(int(x) for x in rgb_color[0:3]) data[ATTR_XY_COLOR] = color_util.color_RGB_to_xy(*rgb_color) + elif color_mode == COLOR_MODE_RGBW and self._light_internal_rgbw_color: + rgbw_color = self._light_internal_rgbw_color + rgb_color = color_util.color_rgbw_to_rgb(*rgbw_color) + data[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color) + data[ATTR_RGB_COLOR] = tuple(int(x) for x in rgb_color[0:3]) + data[ATTR_RGBW_COLOR] = tuple(int(x) for x in rgbw_color[0:4]) + data[ATTR_XY_COLOR] = color_util.color_RGB_to_xy(*rgb_color) return data @final @@ -722,9 +730,6 @@ class LightEntity(ToggleEntity): if color_mode in COLOR_MODES_COLOR: data.update(self._light_internal_convert_color(color_mode)) - if color_mode == COLOR_MODE_RGBW: - data[ATTR_RGBW_COLOR] = self._light_internal_rgbw_color - if color_mode == COLOR_MODE_RGBWW: data[ATTR_RGBWW_COLOR] = self.rgbww_color diff --git a/tests/components/light/test_init.py b/tests/components/light/test_init.py index f0cca89892c..e52192c62ee 100644 --- a/tests/components/light/test_init.py +++ b/tests/components/light/test_init.py @@ -1195,7 +1195,10 @@ async def test_light_state_rgbw(hass): "friendly_name": "Test_rgbw", "supported_color_modes": [light.COLOR_MODE_RGBW], "supported_features": 0, + "hs_color": (240.0, 25.0), + "rgb_color": (3, 3, 4), "rgbw_color": (1, 2, 3, 4), + "xy_color": (0.301, 0.295), } @@ -1298,6 +1301,39 @@ async def test_light_service_call_color_conversion(hass): _, data = entity6.last_call("turn_on") assert data == {"brightness": 255, "rgbww_color": (0, 0, 255, 0, 0)} + await hass.services.async_call( + "light", + "turn_on", + { + "entity_id": [ + entity0.entity_id, + entity1.entity_id, + entity2.entity_id, + entity3.entity_id, + entity4.entity_id, + entity5.entity_id, + entity6.entity_id, + ], + "brightness_pct": 100, + "hs_color": (240, 0), + }, + blocking=True, + ) + _, data = entity0.last_call("turn_on") + assert data == {"brightness": 255, "hs_color": (240.0, 0.0)} + _, data = entity1.last_call("turn_on") + assert data == {"brightness": 255, "rgb_color": (255, 255, 255)} + _, data = entity2.last_call("turn_on") + assert data == {"brightness": 255, "xy_color": (0.323, 0.329)} + _, data = entity3.last_call("turn_on") + assert data == {"brightness": 255, "hs_color": (240.0, 0.0)} + _, data = entity4.last_call("turn_on") + assert data == {"brightness": 255, "hs_color": (240.0, 0.0)} + _, data = entity5.last_call("turn_on") + assert data == {"brightness": 255, "rgbw_color": (0, 0, 0, 255)} + _, data = entity6.last_call("turn_on") + assert data == {"brightness": 255, "rgbww_color": (255, 255, 255, 0, 0)} + await hass.services.async_call( "light", "turn_on", diff --git a/tests/components/mqtt/test_light_json.py b/tests/components/mqtt/test_light_json.py index 77e5936c7b4..432c17cda25 100644 --- a/tests/components/mqtt/test_light_json.py +++ b/tests/components/mqtt/test_light_json.py @@ -870,11 +870,11 @@ async def test_sending_mqtt_commands_and_optimistic2(hass, mqtt_mock): assert state.attributes["brightness"] == 75 assert state.attributes["color_mode"] == "rgbw" assert state.attributes["rgbw_color"] == (255, 128, 0, 123) - assert "hs_color" not in state.attributes - assert "rgb_color" not in state.attributes + assert state.attributes["hs_color"] == (30.0, 67.451) + assert state.attributes["rgb_color"] == (255, 169, 83) assert "rgbww_color" not in state.attributes assert "white_value" not in state.attributes - assert "xy_color" not in state.attributes + assert state.attributes["xy_color"] == (0.526, 0.393) mqtt_mock.async_publish.assert_called_once_with( "test_light_rgb/set", JsonValidator(