From fb6cdb5a38463809104ac91edc55bca395ed4e15 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Wed, 11 May 2022 09:57:54 +0200 Subject: [PATCH] Optimistically set hs_color in template light (#71629) * Optimistically set hs_color in template light * Update light.py * Update test --- homeassistant/components/template/light.py | 18 ++- tests/components/template/test_light.py | 133 ++++++++++++++++++++- 2 files changed, 145 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/template/light.py b/homeassistant/components/template/light.py index 0ebdc3fb93a..1988e77d223 100644 --- a/homeassistant/components/template/light.py +++ b/homeassistant/components/template/light.py @@ -352,25 +352,37 @@ class LightTemplate(TemplateEntity, LightEntity): optimistic_set = True if self._level_template is None and ATTR_BRIGHTNESS in kwargs: - _LOGGER.info( + _LOGGER.debug( "Optimistically setting brightness to %s", kwargs[ATTR_BRIGHTNESS] ) self._brightness = kwargs[ATTR_BRIGHTNESS] optimistic_set = True if self._white_value_template is None and ATTR_WHITE_VALUE in kwargs: - _LOGGER.info( + _LOGGER.debug( "Optimistically setting white value to %s", kwargs[ATTR_WHITE_VALUE] ) self._white_value = kwargs[ATTR_WHITE_VALUE] optimistic_set = True if self._temperature_template is None and ATTR_COLOR_TEMP in kwargs: - _LOGGER.info( + _LOGGER.debug( "Optimistically setting color temperature to %s", kwargs[ATTR_COLOR_TEMP], ) self._temperature = kwargs[ATTR_COLOR_TEMP] + if self._color_template is None: + self._color = None + optimistic_set = True + + if self._color_template is None and ATTR_HS_COLOR in kwargs: + _LOGGER.debug( + "Optimistically setting color to %s", + kwargs[ATTR_HS_COLOR], + ) + self._color = kwargs[ATTR_HS_COLOR] + if self._temperature_template is None: + self._temperature = None optimistic_set = True common_params = {} diff --git a/tests/components/template/test_light.py b/tests/components/template/test_light.py index 0888511c583..924a5c25538 100644 --- a/tests/components/template/test_light.py +++ b/tests/components/template/test_light.py @@ -1183,7 +1183,7 @@ async def test_entity_picture_template(hass, start_ha): @pytest.mark.parametrize("count,domain", [(1, light.DOMAIN)]) @pytest.mark.parametrize( "supported_features,supported_color_modes, expected_color_mode", - [(SUPPORT_COLOR, [ColorMode.HS], ColorMode.UNKNOWN)], + [(SUPPORT_COLOR, [ColorMode.HS], ColorMode.HS)], ) @pytest.mark.parametrize( "config", @@ -1253,8 +1253,8 @@ async def test_color_action_no_template( state = hass.states.get("light.test_template_light") assert state.state == STATE_ON - assert state.attributes["color_mode"] == expected_color_mode # hs_color is None - assert "hs_color" not in state.attributes + assert state.attributes["color_mode"] == expected_color_mode + assert state.attributes.get("hs_color") == (40, 50) assert state.attributes["supported_color_modes"] == supported_color_modes assert state.attributes["supported_features"] == supported_features @@ -1308,6 +1308,133 @@ async def test_color_template( assert state.attributes["supported_features"] == supported_features +@pytest.mark.parametrize("count,domain", [(1, light.DOMAIN)]) +@pytest.mark.parametrize( + "supported_features,supported_color_modes", + [(SUPPORT_COLOR | SUPPORT_COLOR_TEMP, [ColorMode.COLOR_TEMP, ColorMode.HS])], +) +@pytest.mark.parametrize( + "config", + [ + { + "light": { + "platform": "template", + "lights": { + "test_template_light": { + "value_template": "{{1 == 1}}", + "turn_on": { + "service": "light.turn_on", + "entity_id": "light.test_state", + }, + "turn_off": { + "service": "light.turn_off", + "entity_id": "light.test_state", + }, + "set_color": [ + { + "service": "test.automation", + "data_template": { + "entity_id": "test.test_state", + "h": "{{h}}", + "s": "{{s}}", + }, + }, + ], + "set_temperature": { + "service": "test.automation", + "data_template": { + "entity_id": "test.test_state", + "color_temp": "{{color_temp}}", + }, + }, + } + }, + } + }, + ], +) +async def test_color_and_temperature_actions_no_template( + hass, start_ha, calls, supported_features, supported_color_modes +): + """Test setting color and color temperature with optimistic template.""" + state = hass.states.get("light.test_template_light") + assert state.attributes.get("hs_color") is None + + # Optimistically set color, light should be in hs_color mode + await hass.services.async_call( + light.DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_template_light", ATTR_HS_COLOR: (40, 50)}, + blocking=True, + ) + + assert len(calls) == 1 + assert calls[-1].data["h"] == 40 + assert calls[-1].data["s"] == 50 + + state = hass.states.get("light.test_template_light") + assert state.attributes["color_mode"] == ColorMode.HS + assert "color_temp" not in state.attributes + assert state.attributes["hs_color"] == (40, 50) + assert state.attributes["supported_color_modes"] == supported_color_modes + assert state.attributes["supported_features"] == supported_features + + # Optimistically set color temp, light should be in color temp mode + await hass.services.async_call( + light.DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_template_light", ATTR_COLOR_TEMP: 123}, + blocking=True, + ) + + assert len(calls) == 2 + assert calls[-1].data["color_temp"] == 123 + + state = hass.states.get("light.test_template_light") + assert state.attributes["color_mode"] == ColorMode.COLOR_TEMP + assert state.attributes["color_temp"] == 123 + assert "hs_color" in state.attributes # Color temp represented as hs_color + assert state.attributes["supported_color_modes"] == supported_color_modes + assert state.attributes["supported_features"] == supported_features + + # Optimistically set color, light should again be in hs_color mode + await hass.services.async_call( + light.DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_template_light", ATTR_HS_COLOR: (10, 20)}, + blocking=True, + ) + + assert len(calls) == 3 + assert calls[-1].data["h"] == 10 + assert calls[-1].data["s"] == 20 + + state = hass.states.get("light.test_template_light") + assert state.attributes["color_mode"] == ColorMode.HS + assert "color_temp" not in state.attributes + assert state.attributes["hs_color"] == (10, 20) + assert state.attributes["supported_color_modes"] == supported_color_modes + assert state.attributes["supported_features"] == supported_features + + # Optimistically set color temp, light should again be in color temp mode + await hass.services.async_call( + light.DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "light.test_template_light", ATTR_COLOR_TEMP: 234}, + blocking=True, + ) + + assert len(calls) == 4 + assert calls[-1].data["color_temp"] == 234 + + state = hass.states.get("light.test_template_light") + assert state.attributes["color_mode"] == ColorMode.COLOR_TEMP + assert state.attributes["color_temp"] == 234 + assert "hs_color" in state.attributes # Color temp represented as hs_color + assert state.attributes["supported_color_modes"] == supported_color_modes + assert state.attributes["supported_features"] == supported_features + + @pytest.mark.parametrize("count,domain", [(1, light.DOMAIN)]) @pytest.mark.parametrize( "config",