From 2eb5a5b9fb626382e4202880b1b76034d63a1b61 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 14 Jan 2022 00:17:51 -1000 Subject: [PATCH 1/7] Fix flux_led not being able to turn on with older devices - If the brightness was externally adjusted to 0, the device would not be able to turn back on if the device did not support auto on --- homeassistant/components/flux_led/light.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/flux_led/light.py b/homeassistant/components/flux_led/light.py index e63b8250de82b3..60befa19c83cbc 100644 --- a/homeassistant/components/flux_led/light.py +++ b/homeassistant/components/flux_led/light.py @@ -249,6 +249,10 @@ def effect(self) -> str | None: async def _async_turn_on(self, **kwargs: Any) -> None: """Turn the specified or all lights on.""" if self._device.requires_turn_on or not kwargs: + if not self.brightness: + await self._device.async_set_brightness( + self._async_brightness(**kwargs) + ) if not self.is_on: await self._device.async_turn_on() if not kwargs: @@ -281,13 +285,11 @@ def _async_brightness(self, **kwargs: Any) -> int: """Determine brightness from kwargs or current value.""" if (brightness := kwargs.get(ATTR_BRIGHTNESS)) is None: brightness = self.brightness - if not brightness: - # If the brightness was previously 0, the light - # will not turn on unless brightness is at least 1 - # If the device was on and brightness was not - # set, it means it was masked by an effect - brightness = 255 if self.is_on else 1 - return brightness + # If the brightness was previously 0, the light + # will not turn on unless brightness is at least 1 + # If the device was on and brightness was not + # set, it means it was masked by an effect + return min(1, brightness) async def _async_set_mode(self, **kwargs: Any) -> None: """Set an effect or color mode.""" From 7169229ad165af68eb3552efba56b57ca7d9d844 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 14 Jan 2022 00:23:15 -1000 Subject: [PATCH 2/7] fix cover --- homeassistant/components/flux_led/light.py | 4 +--- tests/components/flux_led/test_light.py | 16 ++++++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/flux_led/light.py b/homeassistant/components/flux_led/light.py index 60befa19c83cbc..7525134b8da3b1 100644 --- a/homeassistant/components/flux_led/light.py +++ b/homeassistant/components/flux_led/light.py @@ -287,9 +287,7 @@ def _async_brightness(self, **kwargs: Any) -> int: brightness = self.brightness # If the brightness was previously 0, the light # will not turn on unless brightness is at least 1 - # If the device was on and brightness was not - # set, it means it was masked by an effect - return min(1, brightness) + return max(1, brightness) async def _async_set_mode(self, **kwargs: Any) -> None: """Set an effect or color mode.""" diff --git a/tests/components/flux_led/test_light.py b/tests/components/flux_led/test_light.py index e3a136afb0b11b..625cbf384a8589 100644 --- a/tests/components/flux_led/test_light.py +++ b/tests/components/flux_led/test_light.py @@ -254,9 +254,12 @@ async def test_rgb_light(hass: HomeAssistant) -> None: blocking=True, ) # If the bulb is on and we are using existing brightness - # and brightness was 0 it means we could not read it because - # an effect is in progress so we use 255 - bulb.async_set_levels.assert_called_with(10, 10, 30, brightness=255) + # and brightness was 0 older devices will not be able to turn on + # so we need to make sure its at least 1 and that we + # call it before the turn on command since the device + # does not support auto on + bulb.async_set_brightness.assert_called_with(1) + bulb.async_set_levels.assert_called_with(10, 10, 30, brightness=1) bulb.async_set_levels.reset_mock() bulb.brightness = 128 @@ -364,10 +367,11 @@ async def test_rgb_light_auto_on(hass: HomeAssistant) -> None: blocking=True, ) # If the bulb is on and we are using existing brightness - # and brightness was 0 it means we could not read it because - # an effect is in progress so we use 255 + # and brightness was 0 we need to set it to at least 1 + # or the device may not turn on bulb.async_turn_on.assert_not_called() - bulb.async_set_levels.assert_called_with(10, 10, 30, brightness=255) + bulb.async_set_brightness.assert_not_called() + bulb.async_set_levels.assert_called_with(10, 10, 30, brightness=1) bulb.async_set_levels.reset_mock() bulb.brightness = 128 From 6dc1c69be08256d6c9f4fdb1f68ece2ce34bdd29 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 14 Jan 2022 00:25:36 -1000 Subject: [PATCH 3/7] fix cover --- homeassistant/components/flux_led/light.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/homeassistant/components/flux_led/light.py b/homeassistant/components/flux_led/light.py index 7525134b8da3b1..44c2acd9fc34f2 100644 --- a/homeassistant/components/flux_led/light.py +++ b/homeassistant/components/flux_led/light.py @@ -287,6 +287,10 @@ def _async_brightness(self, **kwargs: Any) -> int: brightness = self.brightness # If the brightness was previously 0, the light # will not turn on unless brightness is at least 1 + # + # We previously had a problem with the brightness + # sometimes reporting as 0 when an effect was in progress, + # however this has since been resolved in the upstream library return max(1, brightness) async def _async_set_mode(self, **kwargs: Any) -> None: From 9e9ec004bd7bee0b61d8953c3b78b50eae8e169e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 14 Jan 2022 07:37:17 -1000 Subject: [PATCH 4/7] adjust --- homeassistant/components/flux_led/light.py | 12 ++++++------ homeassistant/components/flux_led/util.py | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/flux_led/light.py b/homeassistant/components/flux_led/light.py index 44c2acd9fc34f2..6f50ecd083ef54 100644 --- a/homeassistant/components/flux_led/light.py +++ b/homeassistant/components/flux_led/light.py @@ -55,6 +55,8 @@ _effect_brightness, _flux_color_mode_to_hass, _hass_color_modes, + _min_rgbw_brightness, + _min_rgbwc_brightness, _str_to_multi_color_effect, ) @@ -249,10 +251,6 @@ def effect(self) -> str | None: async def _async_turn_on(self, **kwargs: Any) -> None: """Turn the specified or all lights on.""" if self._device.requires_turn_on or not kwargs: - if not self.brightness: - await self._device.async_set_brightness( - self._async_brightness(**kwargs) - ) if not self.is_on: await self._device.async_turn_on() if not kwargs: @@ -321,13 +319,15 @@ async def _async_set_mode(self, **kwargs: Any) -> None: if rgbw := kwargs.get(ATTR_RGBW_COLOR): if ATTR_BRIGHTNESS in kwargs: rgbw = rgbw_brightness(rgbw, brightness) - await self._device.async_set_levels(*rgbw) + await self._device.async_set_levels(*_min_rgbw_brightness(rgbw)) return # Handle switch to RGBWW Color Mode if rgbcw := kwargs.get(ATTR_RGBWW_COLOR): if ATTR_BRIGHTNESS in kwargs: rgbcw = rgbcw_brightness(kwargs[ATTR_RGBWW_COLOR], brightness) - await self._device.async_set_levels(*rgbcw_to_rgbwc(rgbcw)) + await self._device.async_set_levels( + *_min_rgbwc_brightness(rgbcw_to_rgbwc(rgbcw)) + ) return if (white := kwargs.get(ATTR_WHITE)) is not None: await self._device.async_set_levels(w=white) diff --git a/homeassistant/components/flux_led/util.py b/homeassistant/components/flux_led/util.py index 18be67bf6b4991..503907146c44c4 100644 --- a/homeassistant/components/flux_led/util.py +++ b/homeassistant/components/flux_led/util.py @@ -52,3 +52,19 @@ def _str_to_multi_color_effect(effect_str: str) -> MultiColorEffects: return effect # unreachable due to schema validation assert False # pragma: no cover + + +def _min_rgbw_brightness(rgbw: tuple[int, int, int, int]) -> tuple[int, int, int, int]: + """Ensure the RGBW value will not turn off the device from a turn on command.""" + if all(byte == 0 for byte in rgbw): + return (1, 1, 1, 0) + return rgbw + + +def _min_rgbwc_brightness( + rgbwc: tuple[int, int, int, int, int] +) -> tuple[int, int, int, int, int]: + """Ensure the RGBWC value will not turn off the device from a turn on command.""" + if all(byte == 0 for byte in rgbwc): + return (1, 1, 1, 0, 0) + return rgbwc From 612925e89b6075697f284140fc557101624a70bc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 14 Jan 2022 08:15:11 -1000 Subject: [PATCH 5/7] more fixes --- homeassistant/components/flux_led/light.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/flux_led/light.py b/homeassistant/components/flux_led/light.py index 6f50ecd083ef54..ddef4bfacc122c 100644 --- a/homeassistant/components/flux_led/light.py +++ b/homeassistant/components/flux_led/light.py @@ -319,15 +319,18 @@ async def _async_set_mode(self, **kwargs: Any) -> None: if rgbw := kwargs.get(ATTR_RGBW_COLOR): if ATTR_BRIGHTNESS in kwargs: rgbw = rgbw_brightness(rgbw, brightness) - await self._device.async_set_levels(*_min_rgbw_brightness(rgbw)) + if not self._device.requires_turn_on: + rgbw = _min_rgbw_brightness(rgbw) + _LOGGER.warning("RGBW: %s", rgbw) + await self._device.async_set_levels(*rgbw) return # Handle switch to RGBWW Color Mode if rgbcw := kwargs.get(ATTR_RGBWW_COLOR): if ATTR_BRIGHTNESS in kwargs: rgbcw = rgbcw_brightness(kwargs[ATTR_RGBWW_COLOR], brightness) - await self._device.async_set_levels( - *_min_rgbwc_brightness(rgbcw_to_rgbwc(rgbcw)) - ) + if not self._device.requires_turn_on: + rgbcw = _min_rgbwc_brightness(rgbcw_to_rgbwc(rgbcw)) + await self._device.async_set_levels(*rgbcw) return if (white := kwargs.get(ATTR_WHITE)) is not None: await self._device.async_set_levels(w=white) From 3d877b063c680b68b61874fc626422044f85c629 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 14 Jan 2022 08:23:23 -1000 Subject: [PATCH 6/7] coverage --- tests/components/flux_led/test_light.py | 251 +++++++++++++++++++++++- 1 file changed, 248 insertions(+), 3 deletions(-) diff --git a/tests/components/flux_led/test_light.py b/tests/components/flux_led/test_light.py index 625cbf384a8589..c77cfa956c0710 100644 --- a/tests/components/flux_led/test_light.py +++ b/tests/components/flux_led/test_light.py @@ -48,6 +48,9 @@ ATTR_RGBWW_COLOR, ATTR_SUPPORTED_COLOR_MODES, ATTR_WHITE, + COLOR_MODE_RGB, + COLOR_MODE_RGBW, + COLOR_MODE_RGBWW, DOMAIN as LIGHT_DOMAIN, ) from homeassistant.const import ( @@ -258,7 +261,6 @@ async def test_rgb_light(hass: HomeAssistant) -> None: # so we need to make sure its at least 1 and that we # call it before the turn on command since the device # does not support auto on - bulb.async_set_brightness.assert_called_with(1) bulb.async_set_levels.assert_called_with(10, 10, 30, brightness=1) bulb.async_set_levels.reset_mock() @@ -314,9 +316,9 @@ async def test_rgb_light_auto_on(hass: HomeAssistant) -> None: assert state.state == STATE_ON attributes = state.attributes assert attributes[ATTR_BRIGHTNESS] == 128 - assert attributes[ATTR_COLOR_MODE] == "rgb" + assert attributes[ATTR_COLOR_MODE] == COLOR_MODE_RGB assert attributes[ATTR_EFFECT_LIST] == bulb.effect_list - assert attributes[ATTR_SUPPORTED_COLOR_MODES] == ["rgb"] + assert attributes[ATTR_SUPPORTED_COLOR_MODES] == [COLOR_MODE_RGB] assert attributes[ATTR_HS_COLOR] == (0, 100) await hass.services.async_call( @@ -341,6 +343,19 @@ async def test_rgb_light_auto_on(hass: HomeAssistant) -> None: bulb.async_set_levels.reset_mock() bulb.async_turn_on.reset_mock() + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_RGB_COLOR: (0, 0, 0)}, + blocking=True, + ) + # If the bulb is off and we are using existing brightness + # it has to be at least 1 or the bulb won't turn on + bulb.async_turn_on.assert_not_called() + bulb.async_set_levels.assert_called_with(1, 1, 1, brightness=1) + bulb.async_set_levels.reset_mock() + bulb.async_turn_on.reset_mock() + # Should still be called with no kwargs await hass.services.async_call( LIGHT_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True @@ -406,6 +421,236 @@ async def test_rgb_light_auto_on(hass: HomeAssistant) -> None: bulb.async_set_effect.reset_mock() +async def test_rgbw_light_auto_on(hass: HomeAssistant) -> None: + """Test an rgbw light that does not need the turn on command sent.""" + config_entry = MockConfigEntry( + domain=DOMAIN, + data={CONF_HOST: IP_ADDRESS, CONF_NAME: DEFAULT_ENTRY_TITLE}, + unique_id=MAC_ADDRESS, + ) + config_entry.add_to_hass(hass) + bulb = _mocked_bulb() + bulb.requires_turn_on = False + bulb.raw_state = bulb.raw_state._replace(model_num=0x33) # RGB only model + bulb.color_modes = {FLUX_COLOR_MODE_RGBW} + bulb.color_mode = FLUX_COLOR_MODE_RGBW + with _patch_discovery(), _patch_wifibulb(device=bulb): + await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) + await hass.async_block_till_done() + + entity_id = "light.bulb_rgbcw_ddeeff" + + state = hass.states.get(entity_id) + assert state.state == STATE_ON + attributes = state.attributes + assert attributes[ATTR_BRIGHTNESS] == 128 + assert attributes[ATTR_COLOR_MODE] == COLOR_MODE_RGBW + assert attributes[ATTR_EFFECT_LIST] == bulb.effect_list + assert attributes[ATTR_SUPPORTED_COLOR_MODES] == [COLOR_MODE_RGBW] + assert attributes[ATTR_HS_COLOR] == (0.0, 83.529) + + await hass.services.async_call( + LIGHT_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True + ) + bulb.async_turn_off.assert_called_once() + + await async_mock_device_turn_off(hass, bulb) + assert hass.states.get(entity_id).state == STATE_OFF + + bulb.brightness = 0 + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_RGBW_COLOR: (10, 10, 30, 0)}, + blocking=True, + ) + # If the bulb is off and we are using existing brightness + # it has to be at least 1 or the bulb won't turn on + bulb.async_turn_on.assert_not_called() + bulb.async_set_levels.assert_called_with(10, 10, 30, 0) + bulb.async_set_levels.reset_mock() + bulb.async_turn_on.reset_mock() + + # Should still be called with no kwargs + await hass.services.async_call( + LIGHT_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True + ) + bulb.async_turn_on.assert_called_once() + await async_mock_device_turn_on(hass, bulb) + assert hass.states.get(entity_id).state == STATE_ON + bulb.async_turn_on.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100}, + blocking=True, + ) + bulb.async_turn_on.assert_not_called() + bulb.async_set_brightness.assert_called_with(100) + bulb.async_set_brightness.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_RGBW_COLOR: (0, 0, 0, 0)}, + blocking=True, + ) + # If the bulb is on and we are using existing brightness + # and brightness was 0 we need to set it to at least 1 + # or the device may not turn on + bulb.async_turn_on.assert_not_called() + bulb.async_set_brightness.assert_not_called() + bulb.async_set_levels.assert_called_with(1, 1, 1, 0) + bulb.async_set_levels.reset_mock() + + bulb.brightness = 128 + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_HS_COLOR: (10, 30)}, + blocking=True, + ) + bulb.async_turn_on.assert_not_called() + bulb.async_set_levels.assert_called_with(110, 19, 0, 255) + bulb.async_set_levels.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "random"}, + blocking=True, + ) + bulb.async_turn_on.assert_not_called() + bulb.async_set_effect.assert_called_once() + bulb.async_set_effect.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "purple_fade"}, + blocking=True, + ) + bulb.async_turn_on.assert_not_called() + bulb.async_set_effect.assert_called_with("purple_fade", 50, 50) + bulb.async_set_effect.reset_mock() + + +async def test_rgbww_light_auto_on(hass: HomeAssistant) -> None: + """Test an rgbww light that does not need the turn on command sent.""" + config_entry = MockConfigEntry( + domain=DOMAIN, + data={CONF_HOST: IP_ADDRESS, CONF_NAME: DEFAULT_ENTRY_TITLE}, + unique_id=MAC_ADDRESS, + ) + config_entry.add_to_hass(hass) + bulb = _mocked_bulb() + bulb.requires_turn_on = False + bulb.raw_state = bulb.raw_state._replace(model_num=0x33) # RGB only model + bulb.color_modes = {FLUX_COLOR_MODE_RGBWW} + bulb.color_mode = FLUX_COLOR_MODE_RGBWW + with _patch_discovery(), _patch_wifibulb(device=bulb): + await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) + await hass.async_block_till_done() + + entity_id = "light.bulb_rgbcw_ddeeff" + + state = hass.states.get(entity_id) + assert state.state == STATE_ON + attributes = state.attributes + assert attributes[ATTR_BRIGHTNESS] == 128 + assert attributes[ATTR_COLOR_MODE] == COLOR_MODE_RGBWW + assert attributes[ATTR_EFFECT_LIST] == bulb.effect_list + assert attributes[ATTR_SUPPORTED_COLOR_MODES] == [COLOR_MODE_RGBWW] + assert attributes[ATTR_HS_COLOR] == (3.237, 94.51) + + await hass.services.async_call( + LIGHT_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True + ) + bulb.async_turn_off.assert_called_once() + + await async_mock_device_turn_off(hass, bulb) + assert hass.states.get(entity_id).state == STATE_OFF + + bulb.brightness = 0 + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_RGBWW_COLOR: (10, 10, 30, 0, 0)}, + blocking=True, + ) + # If the bulb is off and we are using existing brightness + # it has to be at least 1 or the bulb won't turn on + bulb.async_turn_on.assert_not_called() + bulb.async_set_levels.assert_called_with(10, 10, 30, 0, 0) + bulb.async_set_levels.reset_mock() + bulb.async_turn_on.reset_mock() + + # Should still be called with no kwargs + await hass.services.async_call( + LIGHT_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True + ) + bulb.async_turn_on.assert_called_once() + await async_mock_device_turn_on(hass, bulb) + assert hass.states.get(entity_id).state == STATE_ON + bulb.async_turn_on.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 100}, + blocking=True, + ) + bulb.async_turn_on.assert_not_called() + bulb.async_set_brightness.assert_called_with(100) + bulb.async_set_brightness.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_RGBWW_COLOR: (0, 0, 0, 0, 0)}, + blocking=True, + ) + # If the bulb is on and we are using existing brightness + # and brightness was 0 we need to set it to at least 1 + # or the device may not turn on + bulb.async_turn_on.assert_not_called() + bulb.async_set_brightness.assert_not_called() + bulb.async_set_levels.assert_called_with(1, 1, 1, 0, 0) + bulb.async_set_levels.reset_mock() + + bulb.brightness = 128 + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_HS_COLOR: (10, 30)}, + blocking=True, + ) + bulb.async_turn_on.assert_not_called() + bulb.async_set_levels.assert_called_with(14, 0, 30, 255, 255) + bulb.async_set_levels.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "random"}, + blocking=True, + ) + bulb.async_turn_on.assert_not_called() + bulb.async_set_effect.assert_called_once() + bulb.async_set_effect.reset_mock() + + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_EFFECT: "purple_fade"}, + blocking=True, + ) + bulb.async_turn_on.assert_not_called() + bulb.async_set_effect.assert_called_with("purple_fade", 50, 50) + bulb.async_set_effect.reset_mock() + + async def test_rgb_cct_light(hass: HomeAssistant) -> None: """Test an rgb cct light.""" config_entry = MockConfigEntry( From 8631b5146eae9b2e13b32f362c953d8fa7f69182 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 14 Jan 2022 08:26:25 -1000 Subject: [PATCH 7/7] fix --- homeassistant/components/flux_led/light.py | 9 ++++++--- homeassistant/components/flux_led/util.py | 7 +++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/flux_led/light.py b/homeassistant/components/flux_led/light.py index ddef4bfacc122c..4326715a8f40c0 100644 --- a/homeassistant/components/flux_led/light.py +++ b/homeassistant/components/flux_led/light.py @@ -55,6 +55,7 @@ _effect_brightness, _flux_color_mode_to_hass, _hass_color_modes, + _min_rgb_brightness, _min_rgbw_brightness, _min_rgbwc_brightness, _str_to_multi_color_effect, @@ -312,6 +313,8 @@ async def _async_set_mode(self, **kwargs: Any) -> None: return # Handle switch to RGB Color Mode if rgb := kwargs.get(ATTR_RGB_COLOR): + if not self._device.requires_turn_on: + rgb = _min_rgb_brightness(rgb) red, green, blue = rgb await self._device.async_set_levels(red, green, blue, brightness=brightness) return @@ -321,16 +324,16 @@ async def _async_set_mode(self, **kwargs: Any) -> None: rgbw = rgbw_brightness(rgbw, brightness) if not self._device.requires_turn_on: rgbw = _min_rgbw_brightness(rgbw) - _LOGGER.warning("RGBW: %s", rgbw) await self._device.async_set_levels(*rgbw) return # Handle switch to RGBWW Color Mode if rgbcw := kwargs.get(ATTR_RGBWW_COLOR): if ATTR_BRIGHTNESS in kwargs: rgbcw = rgbcw_brightness(kwargs[ATTR_RGBWW_COLOR], brightness) + rgbwc = rgbcw_to_rgbwc(rgbcw) if not self._device.requires_turn_on: - rgbcw = _min_rgbwc_brightness(rgbcw_to_rgbwc(rgbcw)) - await self._device.async_set_levels(*rgbcw) + rgbwc = _min_rgbwc_brightness(rgbwc) + await self._device.async_set_levels(*rgbwc) return if (white := kwargs.get(ATTR_WHITE)) is not None: await self._device.async_set_levels(w=white) diff --git a/homeassistant/components/flux_led/util.py b/homeassistant/components/flux_led/util.py index 503907146c44c4..da51727fbef39e 100644 --- a/homeassistant/components/flux_led/util.py +++ b/homeassistant/components/flux_led/util.py @@ -54,6 +54,13 @@ def _str_to_multi_color_effect(effect_str: str) -> MultiColorEffects: assert False # pragma: no cover +def _min_rgb_brightness(rgb: tuple[int, int, int]) -> tuple[int, int, int]: + """Ensure the RGB value will not turn off the device from a turn on command.""" + if all(byte == 0 for byte in rgb): + return (1, 1, 1) + return rgb + + def _min_rgbw_brightness(rgbw: tuple[int, int, int, int]) -> tuple[int, int, int, int]: """Ensure the RGBW value will not turn off the device from a turn on command.""" if all(byte == 0 for byte in rgbw):