Skip to content

Commit c3c976e

Browse files
committed
fix: fix protocol determin for new protocol
1 parent 7b78779 commit c3c976e

File tree

4 files changed

+36
-13
lines changed

4 files changed

+36
-13
lines changed

flux_led/models_db.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,8 +1334,9 @@ def protocol_for_version_num(self, version_num: int) -> str:
13341334
# not work and will never work on this device.
13351335
always_writes_white_and_colors=False,
13361336
protocols=[MinVersionProtocol(0, PROTOCOL_LEDENET_EXTENDED_CUSTOM)],
1337-
mode_to_color_mode={0x01: COLOR_MODES_RGB_CCT, 0x17: COLOR_MODES_RGB_CCT},
1338-
color_modes=COLOR_MODES_RGB_CCT,
1337+
# Device has single white LED (not separate warm/cool), so use RGB_W not RGB_CCT
1338+
mode_to_color_mode={0x01: COLOR_MODES_RGB_W, 0x17: COLOR_MODES_RGB_W},
1339+
color_modes=COLOR_MODES_RGB_W,
13391340
channel_map={},
13401341
microphone=True,
13411342
device_config=IMMUTABLE_DEVICE_CONFIG,

flux_led/protocol.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,14 +1032,35 @@ def _is_start_of_power_state_response(self, data: bytes) -> bool:
10321032
"""Check if a message is the start of a state response."""
10331033
return _message_type_from_start_of_msg(data) == MSG_POWER_STATE
10341034

1035+
def is_valid_extended_state_response(self, raw_state: bytes) -> bool:
1036+
"""Check if this is an extended state response (0xEA 0x81 format).
1037+
1038+
Some devices (like 0xB6) only respond with extended state format.
1039+
This allows probing to recognize these responses.
1040+
"""
1041+
return len(raw_state) >= 20 and raw_state[0] == 0xEA and raw_state[1] == 0x81
1042+
10351043
def is_valid_state_response(self, raw_state: bytes) -> bool:
10361044
"""Check if a state response is valid."""
1045+
# Check for extended state format (0xEA 0x81) first
1046+
if self.is_valid_extended_state_response(raw_state):
1047+
return True
1048+
# Check for standard state format (0x81)
10371049
if len(raw_state) != self.state_response_length:
10381050
return False
10391051
if raw_state[0] != 129:
10401052
return False
10411053
return self.is_checksum_correct(raw_state)
10421054

1055+
def extended_state_to_state(self, raw_state: bytes) -> bytes:
1056+
"""Convert an extended state response to a standard state response.
1057+
1058+
This is overridden by ProtocolLEDENET25Byte with the actual conversion logic.
1059+
Default implementation returns raw_state unchanged for protocols that don't
1060+
use extended state.
1061+
"""
1062+
return raw_state
1063+
10431064
def construct_state_change(self, turn_on: int) -> bytearray:
10441065
"""
10451066
The bytes to send for a state change request.

tests/test_aio.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from flux_led.aioscanner import AIOBulbScanner, LEDENETDiscovery
2424
from flux_led.const import (
2525
COLOR_MODE_CCT,
26+
COLOR_MODE_DIM,
2627
COLOR_MODE_RGB,
2728
COLOR_MODE_RGBW,
2829
COLOR_MODE_RGBWW,
@@ -4358,7 +4359,7 @@ def _updated_callback(*args, **kwargs):
43584359
assert light.version_num == 1
43594360
assert light.protocol == PROTOCOL_LEDENET_EXTENDED_CUSTOM
43604361
assert "Surplife" in light.model
4361-
assert light.color_modes == {COLOR_MODE_RGB, COLOR_MODE_CCT}
4362+
assert light.color_modes == {COLOR_MODE_RGB, COLOR_MODE_DIM}
43624363
assert light.supports_extended_custom_effects is True
43634364
assert light.microphone is True
43644365

@@ -4466,7 +4467,7 @@ def test_extended_custom_effect_option_enum_values():
44664467

44674468
def test_construct_extended_custom_effect_single_color():
44684469
"""Test constructing an extended custom effect with single color."""
4469-
proto = ProtocolLEDENET25Byte()
4470+
proto = ProtocolLEDENETExtendedCustom()
44704471

44714472
# Single red color, pattern Wave, default settings
44724473
result = proto.construct_extended_custom_effect(
@@ -4491,7 +4492,7 @@ def test_construct_extended_custom_effect_single_color():
44914492

44924493
def test_construct_extended_custom_effect_multiple_colors():
44934494
"""Test constructing an extended custom effect with multiple colors."""
4494-
proto = ProtocolLEDENET25Byte()
4495+
proto = ProtocolLEDENETExtendedCustom()
44954496

44964497
# Three colors: red, green, blue
44974498
colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]
@@ -4510,7 +4511,7 @@ def test_construct_extended_custom_effect_multiple_colors():
45104511

45114512
def test_construct_extended_custom_effect_color_order():
45124513
"""Test that colors are stored in input order."""
4513-
proto = ProtocolLEDENET25Byte()
4514+
proto = ProtocolLEDENETExtendedCustom()
45144515

45154516
# Two distinct colors
45164517
colors = [(255, 0, 0), (0, 0, 255)] # Red, Blue
@@ -4535,7 +4536,7 @@ def test_construct_extended_custom_effect_color_order():
45354536

45364537
def test_construct_extended_custom_effect_hsv_conversion():
45374538
"""Test RGB to HSV conversion accuracy."""
4538-
proto = ProtocolLEDENET25Byte()
4539+
proto = ProtocolLEDENETExtendedCustom()
45394540

45404541
# Test with a known color: pure green
45414542
colors = [(0, 255, 0)]
@@ -4553,7 +4554,7 @@ def test_construct_extended_custom_effect_hsv_conversion():
45534554

45544555
def test_construct_extended_custom_effect_speed_clamping():
45554556
"""Test that speed is clamped to 0-100."""
4556-
proto = ProtocolLEDENET25Byte()
4557+
proto = ProtocolLEDENETExtendedCustom()
45574558

45584559
# Speed > 100 should be clamped
45594560
result = proto.construct_extended_custom_effect(
@@ -4574,7 +4575,7 @@ def test_construct_extended_custom_effect_speed_clamping():
45744575

45754576
def test_construct_extended_custom_effect_density_clamping():
45764577
"""Test that density is clamped to 0-100."""
4577-
proto = ProtocolLEDENET25Byte()
4578+
proto = ProtocolLEDENETExtendedCustom()
45784579

45794580
# Density > 100 should be clamped
45804581
result = proto.construct_extended_custom_effect(
@@ -4587,7 +4588,7 @@ def test_construct_extended_custom_effect_density_clamping():
45874588

45884589
def test_construct_extended_custom_effect_max_colors():
45894590
"""Test constructing an effect with maximum 8 colors."""
4590-
proto = ProtocolLEDENET25Byte()
4591+
proto = ProtocolLEDENETExtendedCustom()
45914592

45924593
# 8 colors (maximum)
45934594
colors = [
@@ -4613,7 +4614,7 @@ def test_construct_extended_custom_effect_max_colors():
46134614

46144615
def test_construct_extended_custom_effect_with_enums():
46154616
"""Test using enum values for parameters."""
4616-
proto = ProtocolLEDENET25Byte()
4617+
proto = ProtocolLEDENETExtendedCustom()
46174618

46184619
result = proto.construct_extended_custom_effect(
46194620
pattern_id=ExtendedCustomEffectPattern.WAVE,
@@ -4629,7 +4630,7 @@ def test_construct_extended_custom_effect_with_enums():
46294630

46304631
def test_construct_extended_custom_effect_with_variant_2():
46314632
"""Test using VARIANT_2 option (e.g., breathe mode for rainbow patterns)."""
4632-
proto = ProtocolLEDENET25Byte()
4633+
proto = ProtocolLEDENETExtendedCustom()
46334634

46344635
# Rainbow colors with VARIANT_2 option
46354636
colors = [

tests/test_sync.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,7 @@ def read_data(expected):
14481448
mock_read.side_effect = read_data
14491449
light = flux_led.WifiLedBulb("192.168.1.164")
14501450

1451-
assert light.color_modes == {COLOR_MODE_RGB, COLOR_MODE_CCT}
1451+
assert light.color_modes == {COLOR_MODE_RGB, COLOR_MODE_DIM}
14521452
self.assertEqual(light.protocol, PROTOCOL_LEDENET_EXTENDED_CUSTOM)
14531453
self.assertEqual(light.model_num, 0xB6)
14541454
self.assertEqual(light.version_num, 1)

0 commit comments

Comments
 (0)