Live smoke test showed /v1/chat/completions replies open with the Steward's <think> block (Open WebUI convention) — without stripping, the device would speak the internal monologue aloud. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DeskLock
A living-room visual/audio endpoint for Tatlock, the homelab butler. DeskLock gives Tatlock a face and a voice on a Waveshare round touch display: you talk to it, it listens, thinks, and answers — the first line of contact with the butler backend running on tower-of-joy.
Hardware
Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C
| Component | Details |
|---|---|
| SoC | ESP32-P4NRW32 — dual-core RISC-V @ 400 MHz + LP core |
| Memory | 32 MB PSRAM (in-package), 32 MB NOR flash |
| Display | 3.4" round IPS, 800×800, MIPI-DSI 2-lane, capacitive touch |
| Radio | ESP32-C6-MINI-1 (Wi-Fi 6 + BLE 5) over SDIO via ESP-Hosted |
| Audio in | Dual onboard microphones + ES7210 echo-cancellation ADC |
| Audio out | ES8311 codec, PH2.0 2-pin speaker connector (8Ω 2W recommended) |
| Flashing | USB-C (hold BOOT during reset for download mode) |
The device is currently connected over USB-C directly to tower-of-joy, so build/flash happens on this server.
Architecture
┌──────────────────────┐ WebSocket: PCM audio + JSON events
│ DeskLock device │◄───────────────────────────────────┐
│ (ESP32-P4) │ │
│ • LVGL face │ ┌──────────────────────────────┴───────────┐
│ • touch / wake word │ │ DeskLock Gateway (container, :8600) │
│ • mic capture + AEC │ │ thin orchestrator — no ML dependencies │
│ • TTS playback │ └───────┬──────────────────┬───────────────┘
└──────────────────────┘ │ │ OpenAI-format HTTP
│ ▼
HTTP (LAN) │ ┌─────────────────────────────┐
▼ │ Speaches (container, GPU) │
┌────────────────────┐ │ • STT: faster-whisper │
│ Tatlock (butler) │ │ • TTS: Kokoro / Piper │
│ tatlock.schweitz. │ │ also usable by Open WebUI, │
│ internal :8000 │ │ Home Assistant, … │
└────────────────────┘ └─────────────────────────────┘
Tatlock stays a text-only brain. The gateway orchestrates speech-to-text, chat, and text-to-speech; the Speaches container owns the actual STT/TTS models on the GPU, shared homelab-wide. The device firmware stays thin: audio transport, wake word, and face rendering only. Everything runs on the LAN — no cloud in the voice path.
See docs/architecture.md for the full design.
Repository layout
firmware/— ESP-IDF (C, LVGL 9) application for the ESP32-P4gateway/— Python FastAPI voice gateway, deployed as a container on tower-of-joysim/face/— browser simulator of the face (design source of truth; serve withpython3 -m http.serverand openindex.html, or use?state=…&nochrome=1for screenshots)docs/— architecture and design notes
Roadmap
- Bring-up — ESP-IDF toolchain, build/flash, BSP display + Wi-Fi working
- Face — LVGL face with idle/listening/thinking/speaking states, clock while idle
- Voice (touch-to-talk) — tap to talk → gateway → Tatlock → spoken reply
- Wake word — esp-sr WakeNet on-device, echo cancellation, barge-in
- Polish — Tatlock-initiated notifications, presence, OTA updates