Add protocol command builder

This commit is contained in:
2026-07-01 19:54:06 +10:00
parent 9fd5fae12b
commit 592351e07f
+94
View File
@@ -0,0 +1,94 @@
"""
protocol.py - Command builder for common cheap BLE LED controller protocols.
These controllers all speak one of a handful of similar protocols.
We'll confirm which format the KAIYU uses after sniffing/probing.
Supported protocol families:
- 0x7E family (most common, used by ELK-BLEDOM, LEDBLE, etc.)
- 0x56 family (older MagicLight / JACKYLED style)
"""
class Protocol7E:
"""
The 0x7E protocol family.
Packet format: 7e 00 <CMD> <P1> <P2> <P3> <P4> <LED> ef
CMD 0x04 = power on/off
CMD 0x05 = set colour (P1=mode, P2=R, P3=G, P4=B)
CMD 0x01 = set brightness (P1=0x000x64)
CMD 0x03 = set effect/speed
"""
# Colour mode byte for CMD 0x05
MODE_STATIC = 0x03
MODE_EFFECT = 0x02
# LED channel — 0xFF = all channels
LED_ALL = 0xFF
@staticmethod
def set_color(r: int, g: int, b: int) -> bytes:
r, g, b = _clamp(r), _clamp(g), _clamp(b)
return bytes([0x7e, 0x00, 0x05, Protocol7E.MODE_STATIC, r, g, b, 0x00, 0xef])
@staticmethod
def set_brightness(level: int) -> bytes:
"""level: 0100"""
level = max(0, min(100, level))
return bytes([0x7e, 0x00, 0x01, level, 0x00, 0x00, 0x00, Protocol7E.LED_ALL, 0xef])
@staticmethod
def turn_on() -> bytes:
return bytes([0x7e, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, Protocol7E.LED_ALL, 0xef])
@staticmethod
def turn_off() -> bytes:
return bytes([0x7e, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef])
@staticmethod
def set_effect(effect_id: int, speed: int = 0x03) -> bytes:
"""
effect_id: 0x800x8b (varies by controller)
speed: 0x01 (fast) 0x0a (slow)
"""
return bytes([0x7e, 0x00, 0x03, effect_id, speed, 0x00, 0x00, Protocol7E.LED_ALL, 0xef])
class Protocol56:
"""
The 0x56 protocol family (older MagicLight style).
RGB command : 56 RR GG BB 00 f0 aa
White cmd : 56 00 00 00 WW 0f aa
Power on : cc 23 33
Power off : cc 24 33
"""
@staticmethod
def set_color(r: int, g: int, b: int) -> bytes:
r, g, b = _clamp(r), _clamp(g), _clamp(b)
return bytes([0x56, r, g, b, 0x00, 0xf0, 0xaa])
@staticmethod
def set_white(level: int) -> bytes:
level = _clamp(level)
return bytes([0x56, 0x00, 0x00, 0x00, level, 0x0f, 0xaa])
@staticmethod
def turn_on() -> bytes:
return bytes([0xcc, 0x23, 0x33])
@staticmethod
def turn_off() -> bytes:
return bytes([0xcc, 0x24, 0x33])
def _clamp(v: int) -> int:
return max(0, min(255, v))
# ── Convenience ───────────────────────────────────────────────────────────────
# Default to 7E family — update after confirming with scanner
ActiveProtocol = Protocol7E