127 lines
7.3 KiB
Markdown
127 lines
7.3 KiB
Markdown
# Sway door panel
|
|
|
|
Phase 18 of `docs/project-plan.md`. Builds a Debian 12 live ISO for a wall panel by
|
|
the door/wardrobe: weather and what to wear on the way out, who's home, groceries
|
|
running low, and — the household's actual registration point — "register me as
|
|
`<name>`" by voice.
|
|
|
|
**Structurally this is `../kitchen-display/`'s twin**, not a new shape: one Sway
|
|
workspace, one Chromium kiosk window, a thin agent that only ever switches which
|
|
page is showing. The differences are what it shows by default (`identity`'s
|
|
`dashboard.html` instead of `pantry-vision`'s scan/inventory/recipes) and that its
|
|
microphone is expected to actually be used, not an edge-case opt-in.
|
|
|
|
**The actual logic does not live in this directory** — `../../identity/` owns
|
|
person/presence data and the registration flow; `../../pantry-vision/` owns the
|
|
"running low" data. This host is deliberately thin: Sway, one kiosk window, and
|
|
`door-panel-agent`, which only controls *which screen is showing* — the same split
|
|
every other kiosk host in this project already uses.
|
|
|
|
| | |
|
|
|---|---|
|
|
| Compositor | Sway, one workspace, one Chromium kiosk window |
|
|
| Autologin | greetd, straight into `/usr/local/bin/kiosk-session` |
|
|
| Touch input | Native Wayland `wl_touch`, same assumption as `../touch-panel/`/`../kitchen-display/` |
|
|
| Default screen | `identity`'s `dashboard.html` — weather + clothing suggestion, who's home, groceries running low |
|
|
| Registration | `identity`'s `register.html` — voice ("register me as `<name>`") or the touchscreen form |
|
|
| Voice | wyoming-satellite + openWakeWord — opt-in like every other host's mic, but **this device's actual purpose**, so the build script defaults it to on |
|
|
| Remote control (HA/LLM) | `door-panel-agent` — **Show home / Show registration** buttons only |
|
|
| Remote control (human) | SSH only — no wayvnc, same scope decision as `../touch-panel/` |
|
|
|
|
## Hardware
|
|
|
|
**No specific unit has been chosen.** What's assumed: a touchscreen (native
|
|
`wl_touch`, same caveat as every other touch host in this project) mounted by the
|
|
door or wardrobe, with a microphone and speaker for voice registration/Assist
|
|
playback. Unlike `../kitchen-display/`, **no camera is strictly required** — the
|
|
photo captured during registration (`identity`'s profile-picture feature) is a nice-
|
|
to-have audit artifact, not load-bearing, since identity resolution here is BLE/IRK-
|
|
based, not camera-based. See `docs/project-plan.md` §1.16 for the (unverified,
|
|
non-specific) hardware line item.
|
|
|
|
## Before you build
|
|
|
|
Deploy `identity`/`identity-web` first (`ENABLE_IDENTITY` in
|
|
`tools/setup-container-host.sh`) — this image builds and boots
|
|
fine without it, but the dashboard will show connection errors until it exists.
|
|
`pantry-vision` is optional (only "Running low" needs it). Then edit the
|
|
`# CONFIGURATION` block at the top of
|
|
[`tools/build-door-panel-iso.sh`](../../tools/build-door-panel-iso.sh):
|
|
|
|
| Variable | What to put in it |
|
|
|---|---|
|
|
| `MQTT_BROKER_HOST` | LAN IP of the container host running Mosquitto |
|
|
| `IDENTITY_WEB_URL` / `IDENTITY_URL` / `IDENTITY_TOKEN` | `identity`'s static-serving and API URLs; token must match `identity/identity.env`'s own |
|
|
| `PANTRY_VISION_URL` / `PANTRY_VISION_TOKEN` | Optional — only "Running low" needs these; must match `pantry-vision/pantry-vision.env`'s own token |
|
|
| `ENABLE_VOICE_SATELLITE` | Defaults to `true` here (unlike every other host's identical flag) — this device's whole point is voice registration, but it still needs a real mic on the specific unit before flashing it |
|
|
| `KIOSK_USERNAME` / `IMAGE_HOSTNAME` / `DOOR_PANEL_NAME` | Per-device identity |
|
|
| `SSH_AUTHORIZED_KEY` | Optional — password auth is disabled and there is no wayvnc |
|
|
|
|
## Build
|
|
|
|
```sh
|
|
sudo -E tools/build-door-panel-iso.sh
|
|
```
|
|
|
|
Same directory-split convention as every other host: `configs/` and `agent/` are
|
|
human-edited and git-tracked; `live-build/config/includes.chroot/` is generated,
|
|
gitignored, never hand-edited.
|
|
|
|
## Why one workspace, two kiosk destinations, not three
|
|
|
|
`../touch-panel/` juggles three real apps (Spotify, Home Assistant, a browser) and
|
|
needs a persistent touch dock to switch between them. This device only ever shows
|
|
one of two pages — the everyday dashboard, or the registration form — and switches
|
|
between them rarely (on an MQTT command or a voice trigger), so a dock would be
|
|
overhead with nothing to navigate day-to-day. `configs/sway/home-kiosk` and
|
|
`configs/sway/identity-kiosk` are separate scripts on separate Chromium profiles,
|
|
same shape as `../kitchen-display/`'s `pantry-kiosk`/`identity-kiosk` pair — see that
|
|
host's README for why both scripts kill *any* Chromium instance before launching
|
|
(this device also has only one workspace).
|
|
|
|
## Home Assistant entities
|
|
|
|
`door-panel-agent` publishes two buttons on connect: **Show home**, **Show
|
|
registration** — each kills and relaunches the kiosk Chromium window at the
|
|
corresponding page. That's the entire MQTT surface. Reading presence/weather/
|
|
groceries, or registering a person, is a **separate** path — Home Assistant/the LLM
|
|
calling `identity`'s or `pantry-vision`'s own published APIs directly, not through
|
|
this agent. Voice registration in particular never touches this agent at all — see
|
|
`../../identity/README.md`'s worked HA intent-script example.
|
|
|
|
### Security boundary
|
|
|
|
Same shape and reasoning as every other host's agent in this project:
|
|
`door_panel_agent/mqtt_discovery.py` is the entire inbound MQTT control surface of
|
|
this machine — LLM tool call → HA service call → MQTT → this agent, no HTTP
|
|
listener, no websocket, no exposed Sway IPC socket, no VNC. `identity` and
|
|
`pantry-vision` are **separate, deliberately published** services with their own
|
|
bearer-token boundaries — see their own READMEs' "A real network listener, unlike
|
|
admin-canvas" sections for why that trust model is different on purpose.
|
|
|
|
## Manual verification still outstanding
|
|
|
|
None of this has been run on hardware. In rough order — on top of everything already
|
|
flagged as unverified in `../../identity/README.md` (`TRUSTED_ENTITY_PREFIXES`
|
|
above all):
|
|
|
|
1. The ISO builds at all.
|
|
2. greetd lands in Sway with no login prompt.
|
|
3. Touch input as native `wl_touch` — same open item as every other touch host.
|
|
4. `door-panel-agent` connects to Mosquitto and the device appears in HA.
|
|
5. Register via the touchscreen form (`Show registration`) first, before trying
|
|
voice — this exercises the whole identity path without needing HA's intent-script
|
|
wiring set up. See `identity/README.md`'s worked example for that next step.
|
|
6. Voice registration end-to-end: wake word → "register me as `<name>`" → a spoken
|
|
confirmation. This is the number of moving pieces (wyoming-satellite, HA's Assist
|
|
pipeline, the custom sentence/intent script, `identity`'s `/register`) that has
|
|
the most to go wrong and the least individual testing so far.
|
|
7. The dashboard's clothing suggestion (`identity/frontend/dashboard.js`'s
|
|
`clothingSuggestion()`) is a plain lookup table, untuned against real weather
|
|
payloads or real household clothing preferences — reasonable starting thresholds,
|
|
not measured.
|
|
8. Switching between `home-kiosk` and `identity-kiosk` actually replaces the window
|
|
rather than leaving two Chromium instances up — same untested assumption as
|
|
`../kitchen-display/`'s identical pair.
|
|
9. Idle-blank timeout (20 minutes, `configs/sway/config`) and touch-resume — untested.
|