Project_SylDa/docs/superpowers/specs/2026-07-29-device-uuid-pairing-design.md

2.3 KiB

Device UUID Pairing — Design

Datum: 2026-07-29 Status: goedgekeurd

Doel

Voorkomen dat twee ESP-telefoon paren in dezelfde ruimte met elkaars ESP verbinden. Elk ESP-telefoon paar deelt een unieke UUID die tijdens key exchange wordt uitgewisseld.

Flow

Verse ESP (geen UUID, geen HMAC key)

  1. ESP boot, genereert random UUID (16 bytes via esp_random()), slaat op in NVS
  2. ESP start BLE advertising als "SylDa_Server" (UUID nog onbekend bij app)
  3. App opent Settings → Key Exchange
  4. App stuurt KEY? over USB CDC, ESP antwoordt NO_KEY
  5. App genereert random 32-byte HMAC key + 16-byte UUID
  6. App stuurt SET_KEY:<64 hex> → ESP slaat op → OK
  7. App stuurt SET_ID:<32 hex> → ESP slaat op → OK
  8. App slaat beide op in EncryptedSharedPreferences
  9. App keert terug naar main, start scan

Bestaand paar (beide hebben UUID + HMAC key)

  1. App stuurt KEY?, ESP antwoordt DEVICE_ID:<32 hex>\nHMAC_KEY:<64 hex>
  2. App slaat beide op
  3. Klaar

BLE connectie

  1. App scant op BLE service UUID 4fafc201-... (niet op naam)
  2. Bij elke gevonden device: connect, discover services
  3. Lees UUID characteristic (READ-only)
  4. UUID match → zet relay knoppen actief
  5. UUID mismatch → disconnect, voeg address toe aan triedAddresses, herstart scan
  6. Relay commands blijven HMAC-beveiligd zoals voorheen

Componenten

Firmware (src/main.cpp)

Item Details
NVS key "uuid" 16 bytes, namespace "hmac"
UUID generatie esp_random() per byte, alleen bij eerste boot
BLE naam "SylDa_Server"
UUID characteristic Nieuwe READ-only characteristic, los UUID
KEY? response DEVICE_ID:32HEX\nHMAC_KEY:64HEX of NO_KEY
SET_ID:32HEX Nieuw commando, slaat UUID in NVS

Android — PrefsHelper

  • PREF_UUID = "device_uuid" (EncryptedSharedPreferences)

Android — SettingsActivity

  • readKeyFromEsp(): parse DEVICE_ID: lijn
  • KeyResult.Success krijgt deviceUuid veld
  • Bij NO_KEY: app genereert UUID + stuurt SET_KEY en SET_ID

Android — MainActivity

  • loadState(): laadt UUID
  • startScan(): ScanFilter op service UUID
  • onScanResult: connect bij elke match (naam genegeerd)
  • gattCallback.onMtuChanged: lees UUID characteristic, verify
  • UUID mismatch: disconnect, triedAddresses.add(address), herstart scan