docs(03-01): complete protocol encoders plan — SUMMARY, STATE, ROADMAP updated
- 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
This commit is contained in:
@@ -25,8 +25,8 @@
|
||||
|
||||
- [ ] **ANI-01**: Built-in animation types: chase, pulse, rainbow, strobe, color wipe, fire, solid color
|
||||
- [ ] **ANI-02**: Per-animation parameters: speed, primary color(s), secondary color(s), direction, length/density
|
||||
- [ ] **ANI-03**: RGBW-aware color handling for SK6812 (separate W channel)
|
||||
- [ ] **ANI-04**: RGB color handling for WS2801
|
||||
- [x] **ANI-03**: RGBW-aware color handling for SK6812 (separate W channel)
|
||||
- [x] **ANI-04**: RGB color handling for WS2801
|
||||
|
||||
### Timeline Editor
|
||||
|
||||
@@ -47,9 +47,9 @@
|
||||
|
||||
### UDP Communication
|
||||
|
||||
- [ ] **UDP-01**: Animation command packet: device ID, animation type, params — sent when block starts
|
||||
- [ ] **UDP-02**: Raw pixel frame packet: WLED DRGB/DNRGB/DRGBW protocol — used for AI-generated sequences
|
||||
- [ ] **UDP-03**: Multi-packet framing for frames >MTU (SK6812 300 LEDs RGBW = 1200 bytes, exceeds WiFi MTU)
|
||||
- [x] **UDP-01**: Animation command packet: device ID, animation type, params — sent when block starts
|
||||
- [x] **UDP-02**: Raw pixel frame packet: WLED DRGB/DNRGB/DRGBW protocol — used for AI-generated sequences
|
||||
- [x] **UDP-03**: Multi-packet framing for frames >MTU (SK6812 300 LEDs RGBW = 1200 bytes, exceeds WiFi MTU)
|
||||
- [ ] **UDP-04**: Software UDP receiver/simulator for testing without physical hardware
|
||||
|
||||
### Automatic Sync
|
||||
|
||||
@@ -72,7 +72,7 @@ Plans:
|
||||
**Plans**: 3 plans
|
||||
|
||||
Plans:
|
||||
- [ ] 03-01-PLAN.md — Protocol encoders (DRGB/DRGBW/DNRGB + animation command), UDP sender, device stub completion
|
||||
- [x] 03-01-PLAN.md — Protocol encoders (DRGB/DRGBW/DNRGB + animation command), UDP sender, device stub completion
|
||||
- [ ] 03-02-PLAN.md — Animation library (7 built-in types with AnimationBase ABC, registry, factory)
|
||||
- [ ] 03-03-PLAN.md — UDP simulator, FastAPI integration, end-to-end protocol validation
|
||||
|
||||
@@ -154,7 +154,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7
|
||||
|-------|----------------|--------|-----------|
|
||||
| 1. Foundation | 4/4 | Complete | 2026-04-05 |
|
||||
| 2. Audio Engine | 3/3 | Complete | 2026-04-06 |
|
||||
| 3. Communication Protocol | 0/3 | Not started | - |
|
||||
| 3. Communication Protocol | 1/3 | In Progress| |
|
||||
| 4. Timeline Editor | 0/4 | Not started | - |
|
||||
| 5. Live Show Execution | 0/3 | Not started | - |
|
||||
| 6. AI Sync | 0/3 | Not started | - |
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
gsd_state_version: 1.0
|
||||
milestone: v1.0
|
||||
milestone_name: milestone
|
||||
status: verifying
|
||||
stopped_at: "Completed 02-audio-engine/02-03-PLAN.md (architecture redesign: browser audio + librosa)"
|
||||
last_updated: "2026-04-06T15:40:50.951Z"
|
||||
status: executing
|
||||
stopped_at: Completed 03-communication-protocol/03-01-PLAN.md
|
||||
last_updated: "2026-04-06T21:43:45.010Z"
|
||||
last_activity: 2026-04-06
|
||||
progress:
|
||||
total_phases: 7
|
||||
completed_phases: 2
|
||||
total_plans: 7
|
||||
completed_plans: 7
|
||||
total_plans: 10
|
||||
completed_plans: 8
|
||||
percent: 0
|
||||
---
|
||||
|
||||
@@ -21,13 +21,13 @@ progress:
|
||||
See: .planning/PROJECT.md (updated 2026-04-05)
|
||||
|
||||
**Core value:** Load a song, build a synchronized light show, play it back live — with precise control over every effect on every device.
|
||||
**Current focus:** Phase 02 — audio-engine
|
||||
**Current focus:** Phase 03 — communication-protocol
|
||||
|
||||
## Current Position
|
||||
|
||||
Phase: 02 (audio-engine) — EXECUTING
|
||||
Plan: 3 of 3
|
||||
Status: Phase complete — ready for verification
|
||||
Phase: 03 (communication-protocol) — EXECUTING
|
||||
Plan: 2 of 3
|
||||
Status: Ready to execute
|
||||
Last activity: 2026-04-06
|
||||
|
||||
Progress: [░░░░░░░░░░] 0%
|
||||
@@ -59,6 +59,7 @@ Progress: [░░░░░░░░░░] 0%
|
||||
| Phase 02-audio-engine P02 | 8 | 2 tasks | 3 files |
|
||||
| Phase 02-audio-engine P03 | 8min | 2 tasks | 5 files |
|
||||
| Phase 02-audio-engine P03 | 4 | 9 tasks | 8 files |
|
||||
| Phase 03-communication-protocol P01 | 4min | 2 tasks | 8 files |
|
||||
|
||||
## Accumulated Context
|
||||
|
||||
@@ -88,6 +89,9 @@ Recent decisions affecting current work:
|
||||
- [Phase 02-audio-engine]: Transport state driven by WebSocket tick — no frontend polling
|
||||
- [Phase 02-audio-engine]: Browser plays audio via HTML5 audio element — eliminates python-mpv, Docker libmpv dependency, and server-side position polling
|
||||
- [Phase 02-audio-engine]: librosa.beat.beat_track for beat detection — tempo + beat grid in one call, cached in app.state.beats by filepath
|
||||
- [Phase 03-communication-protocol]: TDD approach for protocol encoders: tests committed RED before implementation, ensuring coverage is meaningful
|
||||
- [Phase 03-communication-protocol]: 0xAC animation command marker chosen well above WLED 0x01-0x04 range — no firmware collision
|
||||
- [Phase 03-communication-protocol]: UDPSender uses single shared asyncio DatagramTransport — no socket pool needed for UDP multi-device sends
|
||||
|
||||
### Pending Todos
|
||||
|
||||
@@ -101,8 +105,8 @@ None yet.
|
||||
|
||||
## Session Continuity
|
||||
|
||||
Last session: 2026-04-06T15:40:34.296Z
|
||||
Stopped at: Completed 02-audio-engine/02-03-PLAN.md (architecture redesign: browser audio + librosa)
|
||||
Last session: 2026-04-06T21:43:45.002Z
|
||||
Stopped at: Completed 03-communication-protocol/03-01-PLAN.md
|
||||
Resume file: None
|
||||
|
||||
Next action: `/gsd:plan-phase 1`
|
||||
|
||||
171
.planning/phases/03-communication-protocol/03-01-SUMMARY.md
Normal file
171
.planning/phases/03-communication-protocol/03-01-SUMMARY.md
Normal file
@@ -0,0 +1,171 @@
|
||||
---
|
||||
phase: 03-communication-protocol
|
||||
plan: 01
|
||||
subsystem: protocol
|
||||
tags: [udp, wled, protocol, animation, led, struct, asyncio, tdd]
|
||||
|
||||
# Dependency graph
|
||||
requires:
|
||||
- phase: 02-audio-engine
|
||||
provides: "FastAPI app with lifespan pattern and app.state for shared resources"
|
||||
provides:
|
||||
- "WLED-compatible DRGB/DRGBW/DNRGB UDP frame encoders"
|
||||
- "Custom 0xAC animation command packet encoder/decoder (16 bytes)"
|
||||
- "UDPSender async transport wrapper (single shared socket)"
|
||||
- "SK6812Device.encode_animation_cmd — real 16-byte packets, not empty stub"
|
||||
- "WS2801Device.encode_animation_cmd — real 16-byte packets, not empty stub"
|
||||
affects:
|
||||
- lightsync/protocol/ (new package)
|
||||
- lightsync/devices/sk6812.py
|
||||
- lightsync/devices/ws2801.py
|
||||
|
||||
# Tech tracking
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "TDD RED-GREEN: failing tests committed first, implementation committed to pass them"
|
||||
- "Single shared asyncio DatagramTransport — one socket sends to N device addresses (no socket pool)"
|
||||
- "WLED DRGB/DRGBW: 2-byte header [type, timeout] + RGB/RGBW body per pixel"
|
||||
- "WLED DNRGB: 4-byte header [type, timeout, start_hi, start_lo] + RGB chunks per packet"
|
||||
- "struct.pack('>BBH') for big-endian DNRGB start index (critical per WLED spec)"
|
||||
- "struct.pack('>BBBBf') for 0xAC animation command header + float32 speed"
|
||||
- "_NullProtocol swallows OS UDP errors — fire-and-forget is correct for LED delivery"
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- lightsync/protocol/__init__.py
|
||||
- lightsync/protocol/drgb.py
|
||||
- lightsync/protocol/animation_cmd.py
|
||||
- lightsync/protocol/udp_sender.py
|
||||
- tests/__init__.py
|
||||
- tests/test_protocol.py
|
||||
modified:
|
||||
- lightsync/devices/sk6812.py
|
||||
- lightsync/devices/ws2801.py
|
||||
|
||||
key-decisions:
|
||||
- "TDD approach: tests committed as RED before implementation — forces verification of test coverage"
|
||||
- "0xAC animation command marker chosen well above WLED 0x01-0x04 range — no firmware collision"
|
||||
- "UDPSender uses asyncio DatagramTransport over asyncudp library — no dependency needed, stdlib suffices"
|
||||
- "Device stubs delegate to encode_animation_cmd via import alias _encode_cmd — clean, no code duplication"
|
||||
- "pytest added as dev dependency via uv add --dev pytest — was missing from pyproject.toml"
|
||||
|
||||
# Metrics
|
||||
duration: ~4min
|
||||
completed: 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 via `struct.pack(">BBH")`
|
||||
|
||||
Implemented `lightsync/protocol/animation_cmd.py` with:
|
||||
- `ANIMATION_IDS` and `ANIMATION_NAMES` dicts mapping 7 animation names to IDs 0-6
|
||||
- `encode_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`:
|
||||
- `_NullProtocol` swallows OS-level send errors (UDP delivery is best-effort)
|
||||
- `UDPSender` opens single shared DatagramTransport at `local_addr=("0.0.0.0", 0)`
|
||||
- `send(payload, ip, port)` is synchronous fire-and-forget
|
||||
- `start()`/`stop()` async lifecycle methods for FastAPI lifespan integration
|
||||
- `is_running` property 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 with `return _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
|
||||
|
||||
1. **Task 1 RED: Failing protocol tests** — `ffc4ef6` (test)
|
||||
2. **Task 1 GREEN: WLED encoders + animation cmd** — `5e13da3` (feat)
|
||||
3. **Task 2: UDP sender + device stubs** — `f17e77f` (feat)
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `lightsync/protocol/__init__.py` — empty package init
|
||||
- `lightsync/protocol/drgb.py` — DRGB/DRGBW/DNRGB encoders with WLED constants
|
||||
- `lightsync/protocol/animation_cmd.py` — 0xAC animation command encoder/decoder
|
||||
- `lightsync/protocol/udp_sender.py` — async UDP transport wrapper
|
||||
- `tests/__init__.py` — test package init
|
||||
- `tests/test_protocol.py` — 27 tests for protocol correctness
|
||||
- `lightsync/devices/sk6812.py` — stub replaced with real encoding
|
||||
- `lightsync/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 pytest` failed 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.04s
|
||||
- `from lightsync.protocol.drgb import encode_drgb, encode_drgbw, encode_dnrgb_packets` — imports OK
|
||||
- `from 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:
|
||||
- ffc4ef6 — test(03-01) RED phase
|
||||
- 5e13da3 — feat(03-01) GREEN phase
|
||||
- f17e77f — feat(03-01) Task 2
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
---
|
||||
*Phase: 03-communication-protocol*
|
||||
*Completed: 2026-04-06*
|
||||
@@ -26,3 +26,8 @@ dev = [
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["lightsync"]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=9.0.2",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user