- Migrates tactility-firmware and tactility-bluetooth from ~/.hermes/skills/ into .claude/skills/ for repo co-location - Adds AGENTS.md with local workstation context, board table, board-direct build rule, Hermes PYTHONPATH pitfall, common Tactility pitfalls, and in-repo skill index Refs: personal Gitea mirror
3.0 KiB
WebServer + DevelopmentService Collision Debugging
Session: 2026-07-11 — Dashboard server started but MCP tools 404, dev service blocked.
Symptoms
- Dashboard (port 80) loads, but POST /api/mcp returns 404 even with mcpEnabled=true
- Development service (6666 /info) not reachable
- MCP screen not appearing on RLCD board (Waveshare 4.2" monochrome ST7305)
Root Causes Found
1. httpd ctrl_port collision
HttpServer::startInternal() used HTTPD_DEFAULT_CONFIG() → ctrl_port 32768 fixed for all instances.
When WebServer (80) + DevServer (6666) start near-simultaneously (service manager dispatches), second bind fails → httpd_start returns error → httpServer stays null → handlers never registered.
Fix: unique ctrl_port per server: 32768 + (port % 1000) → 80→32848, 6666→33434.
Src: Tactility/Source/network/HttpServer.cpp
2. max URI handlers too low
ESP-IDF default CONFIG_HTTPD_MAX_URI_HANDLERS=8.
WebServer registers 7 handlers: /, /filebrowser, /fs/* GET, /fs/* POST, /admin/*, /api/* GET, /api/* POST, /api/* PUT, /* = 7, plus 2 internal slots → config.max_uri_handlers = 9.
If Kconfig max 8 < 9, httpd_start fails or later httpd_register_uri_handler fails → "no slots left".
Fix: Buildscripts/sdkconfig/default.properties → CONFIG_HTTPD_MAX_URI_HANDLERS=20.
3. DisplayIdle early return killed MCP on RLCD
D3919344 added:
if (!supportsBacklightDuty()) return true;
in onStart() — disables timer + settings load for ST7305 (no backlight fn). startMcpScreensaver() depends on settings + timer for update/auto-off.
Fix: always load settings + start timer; only skip auto-backlight logic via existing if (supportsBacklightDuty()) guard in tick().
Files: Tactility/Source/service/displayidle/DisplayIdle.cpp:235-250, 303-353
4. Video stream task overflow
Stack 4096 + SPIRAM allocs + LVGL lock + socket loops → stack overflow → heap corruption blocking other tasks.
Also tight loop vTaskDelay(5) even idle.
Fix: 8192 + idle delay 50ms, busy 5ms.
Verification Commands
source ~/esp/esp-idf/export.sh
cd firmware
python device.py waveshare-esp32-s3-rlcd --dev
idf.py build
idf.py -p /dev/cu.usbmodem101 flash monitor
# Monitor logs:
# - Started on port 80 (ctrl_port 32848)
# - Started on port 6666 (ctrl_port 33434)
# - Mono TCP Video stream server started on port 8081
# - Color TCP Video stream server started on port 8083
# - Monochrome/RLCD detected: idle timer will run but auto-backlight off disabled
curl http://<ip>/api/sysinfo # public
curl -X POST http://<ip>/api/mcp -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
curl http://<ip>:6666/info
Related Incidents
- Upstream #547 merged 2026-07-04 changed settings load to check isFile first — more correct but didn't cause this.
- Board mis-ID: user has both ES3C28P color (240x320) and Waveshare RLCD mono (400x300). Wrong sdkconfig → wrong display driver → blank screen misattributed to MCP bug. Always verify
grep CONFIG_TT_DEVICE_ID sdkconfig.