From fc8c5f1bbd66b88b9dab9ec0ff4f75f55c0a49bc Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Fri, 14 Apr 2023 09:01:29 +0200 Subject: [PATCH] Do not allow mqtt lights to set brightness to zero (#91296) * Do not allow mqtt lights to set brightness to zero * Loglevel to debug * Typo --- .../components/mqtt/light/schema_basic.py | 4 +++ .../components/mqtt/light/schema_json.py | 17 +++++++--- .../components/mqtt/light/schema_template.py | 15 +++++++-- tests/components/mqtt/test_light.py | 13 ++++++++ tests/components/mqtt/test_light_json.py | 31 +++++++++++++++++++ tests/components/mqtt/test_light_template.py | 6 ++++ 6 files changed, 78 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/mqtt/light/schema_basic.py b/homeassistant/components/mqtt/light/schema_basic.py index 358a97ed30d..b3659a67e61 100644 --- a/homeassistant/components/mqtt/light/schema_basic.py +++ b/homeassistant/components/mqtt/light/schema_basic.py @@ -468,6 +468,10 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity): return device_value = float(payload) + if device_value == 0: + _LOGGER.debug("Ignoring zero brightness from '%s'", msg.topic) + return + percent_bright = device_value / self._config[CONF_BRIGHTNESS_SCALE] self._attr_brightness = min(round(percent_bright * 255), 255) diff --git a/homeassistant/components/mqtt/light/schema_json.py b/homeassistant/components/mqtt/light/schema_json.py index e0b20436fe6..c40dae659b7 100644 --- a/homeassistant/components/mqtt/light/schema_json.py +++ b/homeassistant/components/mqtt/light/schema_json.py @@ -378,11 +378,18 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity): if brightness_supported(self.supported_color_modes): try: - self._attr_brightness = int( - values["brightness"] # type: ignore[operator] - / float(self._config[CONF_BRIGHTNESS_SCALE]) - * 255 - ) + if brightness := values["brightness"]: + self._attr_brightness = int( + brightness # type: ignore[operator] + / float(self._config[CONF_BRIGHTNESS_SCALE]) + * 255 + ) + else: + _LOGGER.debug( + "Ignoring zero brightness value for entity %s", + self.entity_id, + ) + except KeyError: pass except (TypeError, ValueError): diff --git a/homeassistant/components/mqtt/light/schema_template.py b/homeassistant/components/mqtt/light/schema_template.py index d0eaa31548d..c2b4de289fd 100644 --- a/homeassistant/components/mqtt/light/schema_template.py +++ b/homeassistant/components/mqtt/light/schema_template.py @@ -236,11 +236,20 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity): if CONF_BRIGHTNESS_TEMPLATE in self._config: try: - self._attr_brightness = int( + if brightness := int( self._value_templates[CONF_BRIGHTNESS_TEMPLATE](msg.payload) - ) + ): + self._attr_brightness = brightness + else: + _LOGGER.debug( + "Ignoring zero brightness value for entity %s", + self.entity_id, + ) + except ValueError: - _LOGGER.warning("Invalid brightness value received") + _LOGGER.warning( + "Invalid brightness value received from %s", msg.topic + ) if CONF_COLOR_TEMP_TEMPLATE in self._config: try: diff --git a/tests/components/mqtt/test_light.py b/tests/components/mqtt/test_light.py index 0f5370b865c..22330d65c2a 100644 --- a/tests/components/mqtt/test_light.py +++ b/tests/components/mqtt/test_light.py @@ -794,6 +794,19 @@ async def test_controlling_state_via_topic_with_templates( assert state.attributes.get(light.ATTR_COLOR_MODE) == "xy" assert state.attributes.get(light.ATTR_SUPPORTED_COLOR_MODES) == color_modes + async_fire_mqtt_message(hass, "test_light_rgb/brightness/status", '{"hello": 100}') + state = hass.states.get("light.test") + assert state.attributes.get("brightness") == 100 + + async_fire_mqtt_message(hass, "test_light_rgb/brightness/status", '{"hello": 50}') + state = hass.states.get("light.test") + assert state.attributes.get("brightness") == 50 + + # test zero brightness received is ignored + async_fire_mqtt_message(hass, "test_light_rgb/brightness/status", '{"hello": 0}') + state = hass.states.get("light.test") + assert state.attributes.get("brightness") == 50 + @pytest.mark.parametrize( "hass_config", diff --git a/tests/components/mqtt/test_light_json.py b/tests/components/mqtt/test_light_json.py index 5add22af721..4bac39ed8ef 100644 --- a/tests/components/mqtt/test_light_json.py +++ b/tests/components/mqtt/test_light_json.py @@ -493,6 +493,37 @@ async def test_controlling_state_via_topic( light_state = hass.states.get("light.test") assert light_state.attributes.get("effect") == "colorloop" + async_fire_mqtt_message( + hass, + "test_light_rgb", + '{"state":"ON",' + '"color":{"r":255,"g":255,"b":255},' + '"brightness":128,' + '"color_temp":155,' + '"effect":"colorloop"}', + ) + light_state = hass.states.get("light.test") + assert light_state.state == STATE_ON + assert light_state.attributes.get("brightness") == 128 + + async_fire_mqtt_message( + hass, + "test_light_rgb", + '{"state":"OFF","brightness":0}', + ) + light_state = hass.states.get("light.test") + assert light_state.state == STATE_OFF + assert light_state.attributes.get("brightness") is None + + # test previous zero brightness received was ignored and brightness is restored + async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON"}') + light_state = hass.states.get("light.test") + assert light_state.attributes.get("brightness") == 128 + + async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON","brightness":0}') + light_state = hass.states.get("light.test") + assert light_state.attributes.get("brightness") == 128 + @pytest.mark.parametrize( "hass_config", diff --git a/tests/components/mqtt/test_light_template.py b/tests/components/mqtt/test_light_template.py index 3369a5591c9..0dffe6368e2 100644 --- a/tests/components/mqtt/test_light_template.py +++ b/tests/components/mqtt/test_light_template.py @@ -330,6 +330,12 @@ async def test_state_brightness_color_effect_temp_change_via_topic( light_state = hass.states.get("light.test") assert light_state.attributes["brightness"] == 100 + # ignore a zero brightness + async_fire_mqtt_message(hass, "test_light_rgb", "on,0") + + light_state = hass.states.get("light.test") + assert light_state.attributes["brightness"] == 100 + # change the color temp async_fire_mqtt_message(hass, "test_light_rgb", "on,,195")