Add kiosk wall-panel control view

Full-screen /kiosk route, separate from the staff SPA: dedicated long-lived
kiosk login (own password, hashed, mints its own hnf_session cookie locally
via CENTRAL_AUTH_SECRET -- no central auth changes needed), scrollable grid
of small mode/setpoint blocks per live-controllable device (shelly_trv,
mhi_mqtt, daikin), tap-to-edit modal reusing the existing per-type control
panels, and a type-aware bulk multiselect (separate TRV/AC sections, only
applied to matching selected devices, TRV commands staggered).

- backend/src/routes/kiosk.js: public POST /api/kiosk/login
- backend/src/routes/settings.js: admin set/check kiosk password (bcrypt)
- backend/src/routes/config.js: exclude/protect kiosk_password_hash
- frontend/src/pages/Kiosk.tsx + components/Kiosk*: the kiosk UI
- reuses GET /api/status for the combined device list -- no new status
  endpoint needed since the kiosk token now also carries the 'view' cap

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-08-25 20:44:50 +00:00
parent f0b4ac3c41
commit 2db7d5f4d0
16 changed files with 757 additions and 14 deletions

View file

@ -26,6 +26,13 @@ export const DEVICE_TYPE_LABELS: Record<DeviceType, string> = {
// value only, ready for its driver (currently just 'midea').
export const IMPLEMENTED_DEVICE_TYPES: DeviceType[] = ['shelly_trv', 'mhi_mqtt', 'home_assistant', 'daikin']
// Device types the kiosk wall-panel actually shows/controls — deliberately
// narrower than IMPLEMENTED_DEVICE_TYPES (excludes home_assistant, which has no
// kiosk-friendly control shape yet). See project_hvac_kiosk memory's "v1 device
// scope" decision — widen this if/when mitsubishi_cn105/midea_mqtt/hitachi_ir land.
export const KIOSK_DEVICE_TYPES: DeviceType[] = ['shelly_trv', 'mhi_mqtt', 'daikin']
export const KIOSK_AC_DEVICE_TYPES: DeviceType[] = ['mhi_mqtt', 'daikin']
// TRV temps/offsets and aircon template fields are all nullable on a zone — NULL means
// "inherit the matching field from hvac_defaults" (see HvacDefaults below); a non-null
// value is that room's explicit override. Set via ZoneDetailModal's per-field toggles.