Two bugs causing immediate crash on first flash:
1. `Ws2801Spi2MhzMethod` typedef was wrong (had "Neo" prefix that doesn't exist
in NeoPixelBus 2.8.x), causing compile error
2. `animTickTask` called `xQueueReceive(commandQueue, ...)` before UDP server
initializes the queue — NULL pointer triggers configASSERT → panic → ~3s
reboot loop. Added NULL guard so animation ticks safely until WiFi connects.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- sounddevice InputStream at 44100Hz/512-sample blocks (~11.6ms latency)
- aubio.tempo beat detection with call_soon_threadsafe bridge (D-05)
- Thread-safe beat_count and bpm properties via threading.Lock (D-04)
- Double-trigger suppression with 200ms hold period
- ImportError wrapped in RuntimeError with clear message
- BeatDetector exported from led_sync.audio package
- Add 02-03-SUMMARY.md documenting AudioPlayer implementation
- Update STATE.md: advance to plan 3 of 6, 60% progress
- Update ROADMAP.md: phase 02 in progress (2/6 summaries)
- Mark AUD-01 and AUD-02 requirements complete in REQUIREMENTS.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ESP32Transport.send_command() injects v:1, fire-and-forget, silent drop if not ready
- 512-byte payload limit enforced with warning log
- datagram_received() parses STATUS ok → connected=True, stores last_status
- on_status callback support for status update notifications
- connection_lost() sets connected=False, clears transport ref
- create_esp32_transport() async factory sends initial STATUS ping (D-12)
- All protocol behaviors match docs/protocol.md exactly (D-10, D-11, D-12, D-14)
- Add pytest-asyncio to dev deps + asyncio_mode=auto for test suite
- Tests for send_command() v:1 injection, field preservation
- Tests for stop/brightness commands, pre-connection silent drop
- Tests for 512-byte payload limit enforcement
- Tests for STATUS ok response → connected=True + last_status
- Tests for malformed JSON silent handling, on_status callback
- Tests for send_status_ping, connection_lost, create_esp32_transport factory
- Tests for led_sync.transport package re-exports
- 01-04-SUMMARY.md: integration plan summary with hardware acceptance test instructions
- STATE.md: advanced to plan 4 of 4, progress 100%, session updated
- ROADMAP.md: Phase 01 marked Complete (4/4 plans with summaries)
- SUMMARY documents ANIM_REGISTRY name strings for Pi-side use
- W auto-derive formula documented for Phase 2 reference
- FW-03 (8 animations) and FW-04 (configurable params) requirements marked complete
- STATE updated: plan 4/4, progress 75%, decisions added
- chase.cpp: moving window of ledCount/10 pixels, speed scales position advance per tick
- pulse.cpp: sine wave brightness oscillation on solid palette color
- rainbow.cpp: HSV rainbow via HsbColor, hue offset advances with tick, no palette (generates own)
- strobe.cpp: period = 20/speed ticks, on/off alternation, high speed = rapid flash
- color_wash.cpp: linear blend between palette colors, hold_ticks = 50/speed
- breathe.cpp: sine envelope, 5% min brightness (never fully off, D-11), slower tempo than pulse
- sparkle.cpp: dim base + random bright pixels via esp_random() hardware RNG
- gradient_sweep.cpp: 2-color gradient sweeps across strip, offset advances with tick
- All 8 handle isRGBW branch, use params.speed/intensity/colors[], call applyBrightnessW/R
- RawPacket struct carries raw bytes, IP, port from AsyncUDP callback
- xQueueSendFromISR in callback (ISR-safe) — zero JSON parsing in callback
- parseTask runs in separate FreeRTOS task, drains rawQueue, parses JSON
- STATUS command handled immediately in parseTask with UDP response to sender
- commandQueue declared extern for animation engine (Plan 03) to consume
- main.cpp: include wifi_server.h, call startUdpServer() after WIFI_PS_NONE
- LedCommand, AnimParams, Zone, CmdType structs with all fields per D-05/D-06
- parseCommand(): validates v:1 version, routes schrank/wand/all zones, parses cmd/animation
- RGBW colors array parsed from params.colors; defaults to single [255,255,255,255]
- buildStatusResponse(): serializes current state to JSON for STATUS cmd reply
- Errors logged to Serial, no UDP response on bad commands (per D-07)
- Task 4 hardware checkpoint approved: zero flicker during 30s UDP burst test
- WIFI_PS_NONE confirmed working on ESP32-C3 SuperMini
- GPIO3/6/7 pin assignments validated on physical hardware
- Updated SUMMARY.md with hardware test result and plan completion
- STATE.md advanced to plan 3, progress bar updated to 25%
- main.cpp: setup() initializes strips, shows green (connecting) then white (connected)
- esp_wifi_set_ps(WIFI_PS_NONE) called immediately after WiFi connects for RMT coexistence
- loop() toggles LED colors every 5s to confirm strip responsiveness
- Coexistence test procedure documented as comment block in main.cpp
- firmware/.gitignore excludes .pio/ and credentials.h
- platformio.ini with -DESP32_ARDUINO_NO_RGB_BUILTIN, NeoPixelBus ^2.8.0, ArduinoJson ^7.4.0
- config.h defines all pin, LED count, brightness, timing, and FreeRTOS constants