- C 96.2%
- C++ 2.9%
- CMake 0.6%
- Shell 0.3%
Explain prerequisites, supported entry points, expected results and known limits based on the repository source. Preserve historical and upstream documentation where applicable. Co-authored-by: Codex Signed-off-by: Peter <peter@psxl.org> |
||
|---|---|---|
| components | ||
| docs | ||
| main | ||
| models | ||
| tools | ||
| .clang-format | ||
| .gitignore | ||
| CMakeLists.txt | ||
| flash.sh | ||
| partitions.csv | ||
| README.md | ||
| sdkconfig.defaults | ||
HomeWatch
A HomeKit remote on the wrist, with a "Major Tom" voice assistant. Waveshare ESP32-S3-Touch-AMOLED-1.75 (466×466 CO5300 AMOLED, CST9217 touch, ES7210 dual mic, AXP2101 PMU), native ESP-IDF 5.5 + esp-homekit-sdk.
No AirPlay, no loud speaker: the watch listens and shows; your local voice
server (develop/speachtotext) thinks.
"Major Tom, Licht im Wohnzimmer an"
ES7210 ─► microWakeWord ─► voice_assist ──POST /v1/voice?device=homewatch&reply=json──► speachtotext (Mac)
Whisper → LM Studio
watch ◄── {"transcript", "reply", "action": {"tile": 1, "press": "single"}} ◄─────────────┘
├─ answer on the AMOLED
└─ HomeKit "Button 1, single press" ─► Home hub ─► whatever you bound in the Home app
tap a tile ──────────────────────────► same HomeKit event
How it controls Apple Home
An ESP32 can't be a HomeKit controller for devices that are already in your
home, because they're paired to Apple's controllers. It can be an accessory,
though. HomeWatch shows up in the Home app as one accessory with
8 Stateless Programmable Switches (CONFIG_HW_TILE_COUNT) plus a battery.
In the Home app, each button gets an action per press type (single, double,
long), so you have 24 actions that can be any scene or accessory. The home hub
(HomePod or Apple TV) runs them. No Mac or entitlement is needed for this part.
What it can't do (yet): show device state ("is the lamp on?"). See the roadmap.
Build & flash
You need the exact Waveshare ESP32-S3-Touch-AMOLED-1.75 board, a USB data
cable, Git, an ESP-IDF 5.5 environment and the ESP HomeKit SDK including its
submodules. Follow the ESP-IDF 5.5 setup
for your host before these Bash commands. The first build downloads managed
components listed in main/idf_component.yml.
git clone https://git.peterscharmueller.com/tompeak/homewatch.git
git clone --recursive https://github.com/espressif/esp-homekit-sdk.git
export HOMEKIT_PATH="$(pwd)/esp-homekit-sdk"
cd homewatch
# Activate your installed ESP-IDF environment first.
idf.py --version
idf.py set-target esp32s3
idf.py build
HOMEKIT_PATH must be an absolute path containing components/homekit and
examples/common. Set it explicitly: the CMake fallback is the original
developer's absolute macOS path, not a portable ~/esp default.
The SDK commit is not pinned here; a successful build on your selected SDK
revision still needs a device check.
Build success: build/homewatch.bin is created. Identify your board's serial
port, then run idf.py -p YOUR_SERIAL_PORT flash monitor, replacing
YOUR_SERIAL_PORT with its actual port name. Ctrl+] exits the monitor.
Flashing replaces the board's application. Device success: the clock/setup
screen appears, then complete the Wi-Fi and HomeKit steps below.
If CMake cannot find HAP components, check HOMEKIT_PATH and SDK submodules.
If the board is not detected, check the data cable/port and its BOOT/RESET
procedure. The existing flash.sh wrapper assumes the original macOS
ESP-IDF/virtualenv layout and /dev/cu.usbmodem*; use the direct IDF commands
above on a new host. Its --ota mode is for an already running, reachable watch.
tools/gen_fonts.sh is optional regeneration and needs Node; generated font
sources are already included.
First setup
- WiFi: first boot starts BLE provisioning. Use the ESP BLE Provisioning app. The QR / PoP is printed on the serial console (same flow as blinds/curtain).
- HomeKit: in the Home app, add an accessory → scan docs/homekit-pairing-qr.svg, or enter 246-80-135. Until it's paired, the clock face shows the code.
- Buttons: in the Home app, open HomeWatch → Button N and bind single, double and long press.
- Check a button: bind one harmless test action in Apple Home, then tap its tile on the watch. Success is that the bound action runs through your home hub. Clock display or successful pairing alone does not test the action.
- Voice (optional): set up the separate
Demokrit voice server
on a Mac. Check that repository's source-completeness status first. Copy its
homewatch.toml.exampletohomewatch.tomland describe the button bindings. Set this firmware'sCONFIG_VOICE_SERVER_URLto the server's LAN address viaidf.py menuconfig; the checked-in default is the original Mac's mDNS name. The server constrains replies to the configured actions. The firmware forces JSON replies and displays the answer.
BOOT button: hold 3 s and release = forget WiFi; hold 10 s = factory reset (WiFi + pairings).
Using it
- Clock page shows the time, date, battery and status (WiFi / HomeKit / mic). Swipe left for tiles.
- Tiles page has 8 round buttons around a talk button. Tap = single, double-tap = double, hold = long.
- Voice: say "Major Tom" or tap the centre button. Red = listening, blue = thinking, then the answer (a green title means a button was pressed). Tap to dismiss.
- The screen switches off after 15 s (
CONFIG_HW_SCREEN_OFF_MS). The touch that wakes it never presses a button.
Admin API (port 8080; HomeKit owns 80)
POST /api/ota/update |
raw build/homewatch.bin → flash + reboot |
GET /api/system/info |
version, heap, battery, pairing, wake-word stats, last turn |
POST /api/system/restart |
|
POST /api/voice/begin |
start a voice turn (as the wake word does) |
POST /api/tile?n=3&press=double |
fire a HomeKit button event (as a tap does) |
ws://<ip>:8080/ws/logs |
live log stream |
Where the parts came from
| here | from |
|---|---|
components/mic_es7210, components/microfrontend, components/board_utils |
watch/firmware (ES7210 gained a 16 kHz clock row) |
main/wake_word*.{c,cc,h}, models/major_tom.* |
watch/firmware (playback coupling removed) |
main/audio_input.c |
watch/firmware, now owns I2S at 16 kHz: no resampler, no AEC |
main/voice_assist.c |
watch/firmware: JSON-only replies, action parsing, tile fetch |
main/display.c |
watch/firmware/components/display/display_co5300.c |
main/homekit.c |
watch/blinds/main/app_main.c (HAP boilerplate) |
main/pmu_axp2101.c |
AirPlay board file + binarywatch-amoled-1.75 charger setup |
Roadmap
- State readback: a Mac-side HomeKit bridge (Mac Catalyst app with the HomeKit framework, REST on localhost → speachtotext) so tiles can show on/off and the model can read sensors. Needs the HomeKit entitlement.
- Spoken replies on an AirPlay speaker: the server already does TTS. It
could stream the reply to a chosen AirPlay receiver (a HomePod, or a tPlay)
with
pyatvinstead of sending it to the watch. The watch stays silent and the room speaker answers. That has to happen on the server: an ESP32 can't act as an AirPlay 2 sender to HomePods. - Bluetooth audio: not possible on this chip. The ESP32-S3 has BLE only: no Classic Bluetooth (A2DP) and no LE Audio, so no BT headphones.
- Battery: always-on wake word costs about 40–60 mA. A listen-mode toggle (always / screen on / tap only) and wrist-raise via the QMI8658 are next.