From 61a754d1fb99c5267203a5df3aaa332e946617a1 Mon Sep 17 00:00:00 2001 From: jbouwh Date: Fri, 8 Dec 2023 10:17:47 +0000 Subject: [PATCH 1/3] Fix mqtt state updates using deprecated color handling --- .../components/mqtt/light/schema_json.py | 3 + tests/components/mqtt/test_light_json.py | 87 +++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/homeassistant/components/mqtt/light/schema_json.py b/homeassistant/components/mqtt/light/schema_json.py index 8702069eab76..36f92247a1ae 100644 --- a/homeassistant/components/mqtt/light/schema_json.py +++ b/homeassistant/components/mqtt/light/schema_json.py @@ -398,6 +398,9 @@ def state_received(msg: ReceiveMessage) -> None: self._attr_color_temp = None else: self._attr_color_temp = int(values["color_temp"]) # type: ignore[arg-type] + # Allow deprecated color mode to switch back to color_temp + if "color" not in values: + self._attr_hs_color = None except KeyError: pass except ValueError: diff --git a/tests/components/mqtt/test_light_json.py b/tests/components/mqtt/test_light_json.py index 82b0b3467f4c..c5c24c3ae799 100644 --- a/tests/components/mqtt/test_light_json.py +++ b/tests/components/mqtt/test_light_json.py @@ -725,6 +725,93 @@ async def test_controlling_state_via_topic2( ) +@pytest.mark.parametrize( + "hass_config", + [ + { + mqtt.DOMAIN: { + light.DOMAIN: { + "schema": "json", + "name": "test", + "command_topic": "test_light_rgb/set", + "state_topic": "test_light_rgb/set", + "rgb": True, + "color_temp": True, + "brightness": True, + } + } + } + ], +) +async def test_controlling_the_state_with_legacy_color_handling( + hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator +) -> None: + """Test state updates for lights with a legacy color handling.""" + supported_color_modes = ["color_temp", "hs"] + await mqtt_mock_entry() + + state = hass.states.get("light.test") + assert state.state == STATE_UNKNOWN + expected_features = light.SUPPORT_FLASH | light.SUPPORT_TRANSITION + assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == expected_features + assert state.attributes.get("brightness") is None + assert state.attributes.get("color_mode") is None + assert state.attributes.get("color_temp") is None + assert state.attributes.get("effect") is None + assert state.attributes.get("hs_color") is None + assert state.attributes.get("rgb_color") is None + assert state.attributes.get("rgbw_color") is None + assert state.attributes.get("rgbww_color") is None + assert state.attributes.get("supported_color_modes") == supported_color_modes + assert state.attributes.get("xy_color") is None + assert not state.attributes.get(ATTR_ASSUMED_STATE) + + for _ in range(0, 2): + # Returned state after the light was turned on + # Receiving legacy color mode: rgb. + async_fire_mqtt_message( + hass, + "test_light_rgb/set", + '{ "state": "ON", "brightness": 255, "level": 100, "hue": 16,' + '"saturation": 100, "color": { "r": 255, "g": 67, "b": 0 }, ' + '"bulb_mode": "color", "color_mode": "rgb" }', + ) + + state = hass.states.get("light.test") + assert state.state == STATE_ON + assert state.attributes.get("brightness") == 255 + assert state.attributes.get("color_mode") == "hs" + assert state.attributes.get("color_temp") is None + assert state.attributes.get("effect") is None + assert state.attributes.get("hs_color") == (15.765, 100.0) + assert state.attributes.get("rgb_color") == (255, 67, 0) + assert state.attributes.get("rgbw_color") is None + assert state.attributes.get("rgbww_color") is None + assert state.attributes.get("xy_color") == (0.674, 0.322) + + # Returned state after the lights color mode was changed + # Receiving legacy color mode: color_temp + async_fire_mqtt_message( + hass, + "test_light_rgb/set", + '{ "state": "ON", "brightness": 255, "level": 100, ' + '"kelvin": 92, "color_temp": 353, "bulb_mode": "white", ' + '"color_mode": "color_temp" }', + ) + + state = hass.states.get("light.test") + assert state.state == STATE_ON + assert state.attributes.get("brightness") == 255 + assert state.attributes.get("color_mode") == "color_temp" + assert state.attributes.get("color_temp") == 353 + assert state.attributes.get("effect") is None + assert state.attributes.get("hs_color") == (28.125, 61.661) + assert state.attributes.get("rgb_color") == (255, 171, 97) + assert state.attributes.get("rgbw_color") is None + assert state.attributes.get("rgbww_color") is None + assert state.attributes.get("xy_color") == (0.513, 0.386) + + @pytest.mark.parametrize( "hass_config", [ From f03f546f47ae965bcc4d261fbdab95d03aabbd0c Mon Sep 17 00:00:00 2001 From: jbouwh Date: Fri, 8 Dec 2023 10:29:27 +0000 Subject: [PATCH 2/3] Keep fix out of try block --- homeassistant/components/mqtt/light/schema_json.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/mqtt/light/schema_json.py b/homeassistant/components/mqtt/light/schema_json.py index 36f92247a1ae..3c6a9e4740ea 100644 --- a/homeassistant/components/mqtt/light/schema_json.py +++ b/homeassistant/components/mqtt/light/schema_json.py @@ -398,9 +398,6 @@ def state_received(msg: ReceiveMessage) -> None: self._attr_color_temp = None else: self._attr_color_temp = int(values["color_temp"]) # type: ignore[arg-type] - # Allow deprecated color mode to switch back to color_temp - if "color" not in values: - self._attr_hs_color = None except KeyError: pass except ValueError: @@ -409,6 +406,9 @@ def state_received(msg: ReceiveMessage) -> None: values["color_temp"], self.entity_id, ) + # Allow deprecated color mode to switch back to color_temp + if "color" not in values: + self._attr_hs_color = None if self.supported_features and LightEntityFeature.EFFECT: with suppress(KeyError): From 78a8d73e32f79d3602cbbafc6c2039de8d4b3df7 Mon Sep 17 00:00:00 2001 From: jbouwh Date: Fri, 8 Dec 2023 10:31:55 +0000 Subject: [PATCH 3/3] Improve docst --- homeassistant/components/mqtt/light/schema_json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/mqtt/light/schema_json.py b/homeassistant/components/mqtt/light/schema_json.py index 3c6a9e4740ea..3479f1611d83 100644 --- a/homeassistant/components/mqtt/light/schema_json.py +++ b/homeassistant/components/mqtt/light/schema_json.py @@ -406,7 +406,7 @@ def state_received(msg: ReceiveMessage) -> None: values["color_temp"], self.entity_id, ) - # Allow deprecated color mode to switch back to color_temp + # Allow to switch back to color_temp if "color" not in values: self._attr_hs_color = None