Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion blebox_uniapi/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,23 @@ def evaluate_brightness_from_rgb(iterable: Sequence[int]) -> int:
)
return int(max(iterable))

@staticmethod
def swap_ww_cw(value: list) -> list:
"""Swap WW and CW channels in RGBWW mode for API compatibility."""
if len(value) == 5:
value = list(value)
value[3], value[4] = value[4], value[3]
return value

@staticmethod
def scale_rgbww_brightness(value: list, brightness: int) -> list:
"""Scale RGBWW value preserving WW:CW ratio."""
current_max = max(value)
if current_max > 0:
return [round(x * brightness / current_max) for x in value]
else:
return [0, 0, 0, 0, brightness]

def apply_brightness(self, value: int, brightness: int) -> Any:
"""Return list of values with applied brightness."""
if not isinstance(brightness, int):
Expand All @@ -303,7 +320,11 @@ def apply_brightness(self, value: int, brightness: int) -> Any:
BleboxColorMode.RGBorW,
):
value = self.normalise_elements_of_rgb(list(value))
res = list(map(lambda x: round(x * (brightness / 255)), value))
res = list(map(lambda x: round(x * (brightness / 255)), value))
elif self.color_mode == BleboxColorMode.RGBWW:
res = self.scale_rgbww_brightness(value, brightness)
else:
res = list(map(lambda x: round(x * (brightness / 255)), value))
return res

def evaluate_off_value(self, config: dict, raw_hex: str) -> str:
Expand Down Expand Up @@ -544,6 +565,9 @@ def sensible_on_value(self) -> Any:
return self.rgb_hex_to_rgb_list(self._last_on_state[:6])
elif self.color_mode == BleboxColorMode.MONO:
return self._last_on_state
elif self.color_mode == BleboxColorMode.RGBWW:
result = self.rgb_hex_to_rgb_list(self._last_on_state)
return self.swap_ww_cw(result)
else:
return self.rgb_hex_to_rgb_list(self._last_on_state)
else:
Expand Down
30 changes: 30 additions & 0 deletions tests/test_light.py
Original file line number Diff line number Diff line change
Expand Up @@ -1337,3 +1337,33 @@ def mask(x):
light._set_last_on_value("test_alias", box, light._off_value)
box.expect_rgbw.assert_not_called()
assert light._last_on_state == light._default_on_value


def test_unit_light_swap_ww_cw():
"""Test swap_ww_cw preserves first 3 channels and swaps last 2."""
value = [100, 150, 200, 120, 80]
result = Light.swap_ww_cw(value)
assert result == [100, 150, 200, 80, 120]


def test_unit_light_swap_ww_cw_non_5_channel():
"""Test swap_ww_cw returns unchanged for non-5-channel values."""
value = [100, 150, 200]
result = Light.swap_ww_cw(value)
assert result == [100, 150, 200]


def test_unit_light_scale_rgbww_brightness_preserves_ratio():
"""Test scale_rgbww_brightness preserves WW:CW ratio within rounding tolerance."""
value = [100, 100, 100, 120, 80]
result = Light.scale_rgbww_brightness(value, 100)
expected_ratio = 120 / 80
actual_ratio = result[3] / result[4]
assert abs(actual_ratio - expected_ratio) < 0.01


def test_unit_light_scale_rgbww_brightness_zero():
"""Test scale_rgbww_brightness with zero max."""
value = [0, 0, 0, 0, 0]
result = Light.scale_rgbww_brightness(value, 200)
assert result == [0, 0, 0, 0, 200]
Loading