No description
  • C 96.2%
  • C++ 2.9%
  • CMake 0.6%
  • Shell 0.3%
Find a file
Peter de15aa8e48 docs: clarify project purpose, first use and verification
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>
2026-10-13 21:07:15 +02:00
components HomeWatch: HomeKit remote + "Major Tom" voice assistant on the AMOLED-1.75 2026-10-10 18:00:31 +02:00
docs HomeWatch: HomeKit remote + "Major Tom" voice assistant on the AMOLED-1.75 2026-10-10 18:00:31 +02:00
main websearch ok 2026-10-11 13:54:34 +02:00
models docs: clarify project purpose, first use and verification 2026-10-13 21:07:15 +02:00
tools HomeWatch: HomeKit remote + "Major Tom" voice assistant on the AMOLED-1.75 2026-10-10 18:00:31 +02:00
.clang-format HomeWatch: HomeKit remote + "Major Tom" voice assistant on the AMOLED-1.75 2026-10-10 18:00:31 +02:00
.gitignore HomeWatch: HomeKit remote + "Major Tom" voice assistant on the AMOLED-1.75 2026-10-10 18:00:31 +02:00
CMakeLists.txt HomeWatch: HomeKit remote + "Major Tom" voice assistant on the AMOLED-1.75 2026-10-10 18:00:31 +02:00
flash.sh HomeWatch: HomeKit remote + "Major Tom" voice assistant on the AMOLED-1.75 2026-10-10 18:00:31 +02:00
partitions.csv HomeWatch: HomeKit remote + "Major Tom" voice assistant on the AMOLED-1.75 2026-10-10 18:00:31 +02:00
README.md docs: clarify project purpose, first use and verification 2026-10-13 21:07:15 +02:00
sdkconfig.defaults HomeWatch: HomeKit remote + "Major Tom" voice assistant on the AMOLED-1.75 2026-10-10 18:00:31 +02:00

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

  1. 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).
  2. 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.
  3. Buttons: in the Home app, open HomeWatch → Button N and bind single, double and long press.
  4. 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.
  5. Voice (optional): set up the separate Demokrit voice server on a Mac. Check that repository's source-completeness status first. Copy its homewatch.toml.example to homewatch.toml and describe the button bindings. Set this firmware's CONFIG_VOICE_SERVER_URL to the server's LAN address via idf.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 pyatv instead 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.