Add protocol command builder
This commit is contained in:
@@ -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=0x00–0x64)
|
||||||
|
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: 0–100"""
|
||||||
|
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: 0x80–0x8b (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
|
||||||
Reference in New Issue
Block a user