Root cause of the dead data path (assoc/scan/RPC fine, zero data frames): esp-hosted 1.4.x is formally incompatible with IDF 5.5 (esp-hosted-mcu#47) and the factory C6 slave firmware was ancient (couldn't even answer a version RPC). Waveshare's examples pin 1.4.* — do not follow them. Fix: - host: espressif/esp_hosted ^2.12 (+ esp_wifi_remote 1.6) - slave: 2.12.11 network_adapter.bin embedded in the app (c6_ota.c streams it to the C6 over the SDIO RPC channel at boot when the reported version is < 2.x; ~10s, no wires, idempotent) - RAM diet for hosted 2.x's footprint (MEMPOOL_PREFER_SPIRAM, reduced WIFI_RMT buffers) — without it internal SRAM famine boot-loops in xTaskCreateStaticPinnedToCore before app_main - conservative 20MHz SDIO clock for first verified data path Verified on hardware: DHCP lease (even that healed), 8/8 pings to router and tower-of-joy at 1-5ms, WebSocket to the gateway connected, device registered at /devices as desklock-p4 with fw version. Also: wifi_diag.c L1 SoftAP diagnostic mode (DESKLOCK-DIAG) with review fixes, boot ping ladder in net.c, static-IP fallback, face_status() line, docs for the whole failure taxonomy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
46 lines
2.1 KiB
Markdown
46 lines
2.1 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
Claude Code-specific notes for this project. For architecture, hard rules, and full
|
|
command reference — see [AGENTS.md](AGENTS.md), and read it before starting work.
|
|
|
|
## Quick orientation
|
|
|
|
DeskLock = firmware for a Waveshare ESP32-P4 round-display device (`firmware/`, ESP-IDF/C/LVGL)
|
|
plus a voice gateway container (`gateway/`, Python/FastAPI, port 8600) that bridges device
|
|
audio to the Tatlock butler API. The device↔gateway WebSocket protocol lives in
|
|
`docs/architecture.md` and must stay in sync with both implementations.
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
# Firmware (requires `source ~/esp-idf/export.sh` first; IDF ≥ 5.4)
|
|
cd firmware && idf.py build
|
|
idf.py -p /dev/ttyACM0 flash monitor
|
|
|
|
# Gateway
|
|
cd gateway && make setup # once
|
|
make run # dev server :8600
|
|
make test # pytest; single test: .venv/bin/pytest tests/test_health.py -k healthz
|
|
make lint typecheck
|
|
```
|
|
|
|
## Gotchas
|
|
|
|
- ESP-IDF v5.5 lives at `~/esp-idf` (`source ~/esp-idf/export.sh`). Flash via
|
|
`sg dialout -c …` (see AGENTS.md) — the login session predates dialout membership.
|
|
- **PSRAM 200 MHz requires `CONFIG_IDF_EXPERIMENTAL_FEATURES=y`** — without it the
|
|
option silently degrades to 20 MHz and the DSI display underruns into a watchdog
|
|
loop. Details in AGENTS.md.
|
|
- **Wi-Fi = esp_hosted 2.x on BOTH chips** (host manifest + C6 slave, auto-OTA'd from
|
|
`main/c6_slave.bin`). 1.x on IDF 5.5 gives working control RPC but a dead data path
|
|
(the great July 14th debugging night). Boot-loop assert on
|
|
`xTaskCreateStaticPinnedToCore` = internal-RAM famine. Details in AGENTS.md.
|
|
- Gateway speech deps are optional extras; `make setup` alone runs the app and tests
|
|
without GPU/ML packages. `make setup` uses `python3.12` (system python3 is 3.8).
|
|
- Tatlock replies open with a `<think>` block — always strip via
|
|
`tatlock.strip_reasoning()` before TTS or display.
|
|
- Low power is a prime user requirement: see "Power management" in
|
|
docs/architecture.md before touching the face/render loop.
|