# 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