diff --git a/README.md b/README.md index 3821f0c..7c5e7ba 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ De BLE-verbinding is beveiligd met **HMAC-SHA256 authenticatie** (application-le | Touch sensor 1 | HS-S43A Digital Capacitive Switch Module op **G8** (actief HIGH) | | Touch sensor 2 | HS-S43A Digital Capacitive Switch Module op **G6** (actief HIGH) | | Knop | Op **G41** (active low) | -| Status LED | Op **G46** (knippert 3x bij opstarten) | +| Status LED | Op **G46** (rood = geen verbinding, geel = verbinding <60s, uit = stabiel) | ### Pinout @@ -41,6 +41,21 @@ Relais - → GND > **HS-S43A touch sensor:** Digitale output (actief HIGH). Geen pullup nodig — de sensor geeft actief 0V of 3.3V. +## LED-signalering + +De LED fungeert als debug-indicator en schakelt uit na 60 seconden stabiele verbinding: + +| State | LED | Prioriteit | +|-------|-----|-----------| +| OTA in progress | Groen knipperend (100ms) | 1 (hoogst) | +| OTA completed, wacht op confirm | Geel vast | 1 | +| Geen verbinding | Rood | 2 | +| Verbinding actief (< 60s) | Geel | 3 | +| Verbinding stabiel (>= 60s) | Uit | 4 (laagst) | +| Relais-flash overlay | Groen 150ms | overlay | + +De relais-flash toont kort groen bij een verandering in relais-status, waarna de LED terugkeert naar de verbindingskleur. + ## Beveiliging De relay is beveiligd tegen ongeautoriseerde toegang via HMAC-SHA256 authenticatie op applicatieniveau. @@ -112,6 +127,7 @@ module → App: OK\n (bevestiging) |---|---| | **Replay** | Sequence counter — zelfde packet werkt niet 2x (`seq <= lastSeq` wordt geweerd) | | **Ongeautoriseerd device** | HMAC vereist geheime sleutel (32-byte random via USB provisioning) | +| **BLE spoofing (client)** | **Bekend lek (issue #10):** ESP32 client scant op naam "SylDa_Server" i.p.v. UUID — geen server-verificatie. De Android app scant wél op service UUID én verifieert device UUID na connect. | | **Commando vervalsing** | HMAC dekt command byte + sequence — wijzigen maakt handtekening ongeldig | | **Brute-force key** | 32-byte key = 2^256 mogelijkheden — onhaalbaar | | **Sniffen** | Pakketten zijn onversleuteld; geen confidentiality. Alleen commando's (aan/uit) zijn zichtbaar, niet de key. | @@ -125,7 +141,14 @@ BLE-link encryptie (bonding/Just Works) vereist complexe pairing flows die op An ## Firmware -De firmware is geschreven in C++ met behulp van PlatformIO en de Arduino-framework. BLE wordt verzorgd door de ESP32 NimBLE library, HMAC door mbedtls (ingebouwd in ESP-IDF). +De firmware is geschreven in C++ met behulp van PlatformIO en de Arduino-framework. BLE wordt verzorgd door de ESP32 NimBLE library, HMAC door mbedtls (ingebouwd in ESP-IDF). Er zijn twee PlatformIO environments: + +| Environment | Bronbestand | Rol | +|---|---|---| +| `s3lite-server` | `src/main.cpp` | Ontvangt BLE-verbindingen, bedient relais | +| `s3lite-client` | `src/client.cpp` | Verbindt als BLE-central met server, stuurt relais-commando's | + +Firmwareversies worden beheerd via `version.txt` (single source of truth). PlatformIO genereert `src/version.h` automatisch via een pre-build script. ### Logica @@ -181,7 +204,7 @@ Baudrate: **115200** (USB CDC). De firmware stuurt heartbeat-statussen elke 5 se ``` === SylDa BLE Relay === HMAC key loaded from NVS -LED blink done, starting BLE... +LED red (no connection), starting BLE... BLE: advertising started as 'SylDa_Server' (start=1, isAdv=1) Setup done. [heartbeat] R1=0 R2=0 t1=1 t2=1 btn=1 ble1=0 ble2=0 @@ -194,7 +217,7 @@ BLE: relay1 OFF (seq=2) ``` === SylDa BLE Relay === No HMAC key provisioned — connect USB and run SET_KEY -LED blink done, starting BLE... +LED red (no connection), starting BLE... BLE: advertising started as 'SylDa_Server' (start=1, isAdv=1) No HMAC key — use USB SET_KEY to provision Setup done. @@ -207,11 +230,14 @@ In deze staat accepteert de module wel BLE-verbindingen, maar elk HMAC-packet fa > **Download-mode:** Houd de reset-knop ~2 seconden ingedrukt tot de groene LED aangaat, laat dan los. Het board is nu in download-mode. ```bash -# Flash firmware (behoudt NVS/key) -pio run --target upload +# Flash server firmware (behoudt NVS/key) +pio run -e s3lite-server --target upload + +# Flash client firmware (behoudt NVS/key) +pio run -e s3lite-client --target upload # Volledig wissen (incl. NVS/key) + opnieuw flashen -pio run -t erase && pio run -t upload +pio run -t erase && pio run -e s3lite-server --target upload ``` Na het uploaden treedt er een harde reset op. Als het board in download-mode blijft, USB eruit/erin of kort op reset tikken om in run-mode te komen. @@ -226,7 +252,7 @@ De firmware kan rechtstreeks via de Android-app worden geflashed, geen computer 4. Is de firmware verouderd, dan flasht de app bootloader, partitions, en firmware 5. Na het flashen herstart de module en volgt automatisch de key exchange -De firmware binaries worden via `tools/copy_firmware.sh` naar de app assets gekopieerd. +De firmware binaries worden via `tools/copy_firmware.sh` naar de app assets gekopieerd (`assets/firmware/server/` en `assets/firmware/client/`). ## Android App @@ -238,7 +264,7 @@ De firmware binaries worden via `tools/copy_firmware.sh` naar de app assets geko - **Hold-to-activate:** Houd de knop ingedrukt voor relais aan, loslaten voor relais uit - **Twee onafhankelijke relais:** Twee knoppen, elk met eigen HMAC commando code - **Write Without Response:** Gebruikt `WRITE_TYPE_NO_RESPONSE` voor minimale latency -- **MTU negotiatie:** Vraagt MTU 256 aan na service discovery (voor 37-byte HMAC packets) +- **MTU negotiatie:** Vraagt MTU 512 aan na service discovery (voor 37-byte HMAC packets) - **HMAC authenticatie:** Elk commando wordt ondertekend met HMAC-SHA256 + sequence counter - **Key exchange geïntegreerd:** De "Firmware bijwerken" knop checkt versie, flasht indien nodig, en wisselt automatisch sleutels uit - **Thema-selector:** Instellingen → Weergave kiest Systeem, Licht of Donker @@ -315,11 +341,15 @@ adb -s :5555 install -r android/app/build/outputs/apk/debug/app-debug.apk ``` Project_SylDa/ -├── platformio.ini # PlatformIO configuratie (ESP32-S3) +├── platformio.ini # PlatformIO configuratie (ESP32-S3, server + client environments) +├── version.txt # Single source of truth voor firmwareversies ├── src/ -│ └── main.cpp # Firmware (BLE + HMAC + NVS + USB serial + touch + relais) +│ ├── main.cpp # Server firmware (BLE + HMAC + NVS + USB serial + touch + relais) +│ ├── client.cpp # Client firmware (BLE central + touch + relais commando's) +│ └── version.h # Auto-gegenereerd uit version.txt — niet handmatig bewerken ├── tools/ -│ └── copy_firmware.sh # Kopieert firmware binaries naar app assets +│ ├── copy_firmware.sh # Kopieert firmware binaries naar app assets +│ └── pio_version_pre.py # PlatformIO pre-build script (genereert version.h) ├── android/ │ ├── build.gradle # Root Gradle config │ ├── settings.gradle # Gradle settings @@ -330,16 +360,24 @@ Project_SylDa/ │ └── src/main/ │ ├── AndroidManifest.xml │ ├── assets/firmware/ -│ │ ├── bootloader.bin -│ │ ├── partitions.bin -│ │ ├── firmware.bin -│ │ └── boot_app0.bin +│ │ ├── server/ +│ │ │ ├── bootloader.bin +│ │ │ ├── partitions.bin +│ │ │ ├── firmware.bin +│ │ │ └── boot_app0.bin +│ │ └── client/ +│ │ ├── bootloader.bin +│ │ ├── partitions.bin +│ │ ├── firmware.bin +│ │ └── boot_app0.bin │ ├── java/nl/eddydevink/sylda/ │ │ ├── MainActivity.kt │ │ ├── SettingsActivity.kt │ │ ├── BleRelayManager.kt │ │ ├── BleStatus.kt │ │ ├── EspFlasher.kt +│ │ ├── OtaManager.kt +│ │ ├── SylDaVersions.kt │ │ ├── UsbSerialTransport.kt │ │ ├── UsbUtils.kt │ │ └── PrefsHelper.kt @@ -380,6 +418,7 @@ De app gebruikt `Theme.AppCompat.DayNight` in plaats van het eerder geforceerde - De firmware gebruikt geen M5Unified library — alleen Arduino core + ESP32 NimBLE + mbedtls. - `ARDUINO_USB_CDC_ON_BOOT=1` is ingeschakeld voor virtuele serial via USB. - De HMAC key wordt opgeslagen in NVS (namespace `hmac`, key `key`, partitie 0x9000-0xDFFF). Via `pio run -t erase` kan NVS gewist worden. +- Firmwareversies worden beheerd via `version.txt` — `src/version.h` wordt automatisch gegenereerd, nooit handmatig bewerken. - De app gebruikt `WRITE_TYPE_NO_RESPONSE` (Write Without Response) voor minimale latency. - De sequence counter start bij 1 (niet 0) om te voorkomen dat het eerste packet na connectie als replay wordt geweerd. - De app gebruikt raw Android USB API (`UsbDeviceConnection.bulkTransfer`) in plaats van een externe serial library.