- 03-01-SUMMARY.md: WLED encoders, animation cmd, UDP sender, 27 passing tests - STATE.md: advanced to plan 2/3, progress 80%, decisions recorded - ROADMAP.md: phase 3 plan progress updated (1/3 complete) - REQUIREMENTS.md: marked UDP-01/02/03, ANI-03/04 complete - pyproject.toml: pytest added as dev dependency - uv.lock: updated lockfile
7.5 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | duration | completed | |||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 03-communication-protocol | 01 | protocol |
|
|
|
|
|
|
|
~4min | 2026-04-06 |
Phase 3 Plan 01: Protocol Encoders Summary
WLED-compatible UDP protocol layer implemented — DRGB/DRGBW/DNRGB frame encoders, custom 0xAC animation command packet with full roundtrip, async UDPSender transport, and SK6812/WS2801 device stubs replaced with real 16-byte packets — all tested with 27 passing tests
Performance
- Duration: ~4 min
- Started: 2026-04-06T21:38:29Z
- Completed: 2026-04-06T21:42:37Z
- Tasks: 2 (Task 1 TDD, Task 2 auto)
- Tests: 27 passing
Accomplishments
Task 1: Protocol encoders — DRGB/DRGBW/DNRGB + animation command (TDD)
RED phase: 27 failing tests committed covering all encoder behaviors including byte layout, MTU truncation, DNRGB multi-packet splitting, big-endian start index, animation roundtrip, flags byte, and defaults.
GREEN phase: Implemented lightsync/protocol/drgb.py with:
encode_drgb: 2-byte header + 3-byte-per-pixel body, truncates at 490 px (MTU)encode_drgbw: 2-byte header + 4-byte-per-pixel body, truncates at 367 px (MTU)encode_dnrgb_packets: splits at 489 px/packet with big-endian start index viastruct.pack(">BBH")
Implemented lightsync/protocol/animation_cmd.py with:
ANIMATION_IDSandANIMATION_NAMESdicts mapping 7 animation names to IDs 0-6encode_animation_cmd: 16-byte packet (0xAC marker, version, type ID, flags, speed float32, primary/secondary color, white, density)decode_animation_cmd: full inverse — roundtrips correctly for all 7 types
All 27 tests pass.
Task 2: UDP sender + device stub completion
Created lightsync/protocol/udp_sender.py:
_NullProtocolswallows OS-level send errors (UDP delivery is best-effort)UDPSenderopens single shared DatagramTransport atlocal_addr=("0.0.0.0", 0)send(payload, ip, port)is synchronous fire-and-forgetstart()/stop()async lifecycle methods for FastAPI lifespan integrationis_runningproperty reflects transport state
Updated lightsync/devices/sk6812.py and ws2801.py:
- Added
from lightsync.protocol.animation_cmd import encode_animation_cmd as _encode_cmd - Replaced
return b""stub withreturn _encode_cmd(animation, params) - SK6812:
encode_animation_cmd("solid_color", {"color":[255,0,0], "white":128})→ac0100003f000000ff00000000008000(16 bytes, starts 0xAC) - WS2801:
encode_animation_cmd("chase", {"color":[0,255,0], "speed":0.7})→ac0101003f33333300ff000000000000(16 bytes, starts 0xAC)
Task Commits
- Task 1 RED: Failing protocol tests —
ffc4ef6(test) - Task 1 GREEN: WLED encoders + animation cmd —
5e13da3(feat) - Task 2: UDP sender + device stubs —
f17e77f(feat)
Files Created/Modified
lightsync/protocol/__init__.py— empty package initlightsync/protocol/drgb.py— DRGB/DRGBW/DNRGB encoders with WLED constantslightsync/protocol/animation_cmd.py— 0xAC animation command encoder/decoderlightsync/protocol/udp_sender.py— async UDP transport wrappertests/__init__.py— test package inittests/test_protocol.py— 27 tests for protocol correctnesslightsync/devices/sk6812.py— stub replaced with real encodinglightsync/devices/ws2801.py— stub replaced with real encoding
Decisions Made
- TDD approach applied: Tests written and committed as RED before implementation, ensuring coverage is meaningful not retrofitted
- 0xAC marker: Well above WLED 0x01-0x04 range — firmware can dispatch on first byte without ambiguity
- No asyncudp library: Python stdlib asyncio DatagramTransport is sufficient and avoids an extra dependency
- pytest added as dev dep: Was missing from pyproject.toml, added via
uv add --dev pytest
Deviations from Plan
Auto-fixed Issues
1. [Rule 3 - Blocking] pytest not installed
- Found during: TDD RED phase (running tests)
- Issue:
uv run python -m pytestfailed with "No module named pytest" - Fix:
uv add --dev pytest— added to pyproject.toml [project.optional-dependencies] dev section - Files modified: pyproject.toml (by uv)
- Commit: (included in uv lockfile update before
ffc4ef6)
Verification Results
python -m pytest tests/test_protocol.py -v— 27 passed in 0.04sfrom lightsync.protocol.drgb import encode_drgb, encode_drgbw, encode_dnrgb_packets— imports OKfrom lightsync.protocol.udp_sender import UDPSender— imports OK- SK6812Device.encode_animation_cmd returns 16-byte 0xAC packet — PASS
- WS2801Device.encode_animation_cmd returns 16-byte 0xAC packet — PASS
Known Stubs
None — all planned stubs replaced with real implementations. The encode_animation_cmd stubs in SK6812Device and WS2801Device that returned b"" are now wired to the real protocol encoder.
Self-Check
Files created/modified:
- lightsync/protocol/init.py — FOUND
- lightsync/protocol/drgb.py — FOUND
- lightsync/protocol/animation_cmd.py — FOUND
- lightsync/protocol/udp_sender.py — FOUND
- tests/init.py — FOUND
- tests/test_protocol.py — FOUND
- lightsync/devices/sk6812.py — FOUND
- lightsync/devices/ws2801.py — FOUND
Commits:
Self-Check: PASSED
Phase: 03-communication-protocol Completed: 2026-04-06