BLE OTA Firmware Updates — Design
Doel
Firmware-updates via Bluetooth LE vanaf de Android app, zonder USB-kabel. Doelgroep: lichamelijk gehandicapten — zelfstandigheid zonder fysieke kabels.
Huidige situatie
- Firmware: ~523KB (534.793 bytes, 16% van 3.2MB beschikbaar)
- BLE: NimBLE-Arduino, service "SylDa_Server" actief
- Partitietabel: al OTA-capable —
ota_0 (0x10000, 3264K), ota_1 (0x340000, 3264K), otadata (0xe000, 8K)
- Android app: flasht nu via USB CDC (EspFlasher)
Architectuur
ESP32-S3 kant (src/main.cpp)
- Nieuwe BLE characteristic
VERSION_UUID = "beb5483e-36e1-4688-b7f5-ea07361f26db" — READ, exposeert firmwareversie als string
- Nieuwe BLE characteristic
OTA_UUID = "beb5483e-36e1-4688-b7f5-ea07361f26da" — WRITE + NOTIFY
- Bestaande relay service blijft volledig intact, aparte characteristic in dezelfde service
- OTA-modus flag: tijdens OTA worden relay-commando's genegeerd, relais vallen UIT
- Gebruikt ESP-IDF
esp_ota_* API:
esp_ota_get_next_update_partition() — vindt target partitie
esp_ota_begin() — initialiseert schrijfactie
esp_ota_write() — schrijft chunk naar flash
esp_ota_end() — valideert image, markeert als bootable
esp_ota_set_boot_partition() — zet target als actieve bootpartitie
esp_restart() — herstart naar nieuwe firmware
Android kant
- Nieuwe
OtaManager.kt — leest firmware, hasht, chunkt, verstuurt
- OTA-knop in
SettingsActivity.kt met progress UI
- Bij BLE connect: leest firmwareversie van ESP via
VERSION_UUID characteristic, vergelijkt met versie in app. Toont toast bij beschikbare update.
- Firmware bron:
assets/firmware.bin (of bestandskiezer voor handmatige update)
- SHA-256 hash berekening voor eindverificatie
- Bundled firmwareversie (uit
assets/) vergeleken met ESP-versie bij connect
Versie-check bij BLE connect
Bij elke BLE-verbinding leest de Android app de VERSION_UUID READ characteristic van de ESP. De ESP retourneert de stringwaarde van FIRMWARE_VERSION. De app vergelijkt met de versie van de gebundelde firmware.bin in assets. Als de ESP een lagere versie heeft toont de app een toast: "Firmware-update beschikbaar" — de gebruiker kan dan in SettingsActivity de OTA starten.
| VERSION_UUID |
"beb5483e-36e1-4688-b7f5-ea07361f26db" |
| Properties |
READ |
| Waarde |
String, bijv. "1" |
BLE OTA Protocol
OTA Characteristic UUID: beb5483e-36e1-4688-b7f5-ea07361f26da
Properties: WRITE, NOTIFY
MTU: 512 bytes (negotiated)
Chunk nuttige data: 488 bytes (512 - 24 header overhead)
Write commando's (App → ESP)
| Byte(s) |
Commando |
0x10 + 4 bytes size (LE) |
OTA_START — firmware grootte in bytes |
| 4 bytes seq (LE) + data[...] |
OTA_DATA — chunk met sequentienummer |
| 32 bytes SHA-256 |
OTA_END — hash van volledige firmware |
Notificatie commando's (ESP → App)
| Byte(s) |
Betekenis |
0x00 + 4 bytes seq (LE) |
ACK — chunk ontvangen en geschreven |
0x01 + 4 bytes seq (LE) |
NAK — chunk opnieuw versturen |
0x10 |
OTA_COMPLETE — succes, reboot volgt |
0x11 + 1 byte error |
OTA_ERROR |
Flow
- App stuurt
OTA_START met firmware-grootte
- ESP roept
esp_ota_begin() aan, zet OTA-modus, relais UIT
- App stuurt chunks sequentieel (seq 0, 1, 2, ...)
- ESP schrijft elke chunk met
esp_ota_write(), stuurt ACK terug
- Bij timeout of corruptie: ESP stuurt NAK met seq-nummer, app herhaalt chunk
- App stuurt
OTA_END met SHA-256
- ESP:
esp_ota_end(), esp_ota_set_boot_partition(), stuurt OTA_COMPLETE
- ESP:
esp_restart()
LED-signalering
| Patroon |
Betekenis |
| Snel knipperen (100ms) |
OTA bezig |
| Continu aan |
OTA voltooid, reboot imminent |
| Langzaam knipperen (500ms) |
OTA fout |
Beveiliging
- Firmware wordt NIET per chunk met HMAC geauthenticeerd (snelheid)
- SHA-256 hash van volledige firmware meegezonden in OTA_END
esp_ota_end() verifieert image header checksum automatisch
- Alleen een BLE-verbonden device kan OTA starten (BLE link-level encryptie via pairing)
- Bestaande HMAC-key voor relay-commando's blijft ongewijzigd
Foutafhandeling
| Scenario |
Afhandeling |
| Verbinding verbroken tijdens OTA |
Huidige firmware blijft actief, ota_1 ongeldig |
| Corrupte chunk |
ESP stuurt NAK, app herhaalt chunk |
| SHA-256 mismatch in OTA_END |
esp_ota_end() faalt, huidige firmware blijft |
| ESP crash tijdens OTA |
Bootloader boot ota_0, otadata wijst er nog naar |
| Nieuwe firmware boot niet (8x bootloop) |
ESP-IDF rollback: schakelt terug naar ota_0 |
Edge cases
- OTA opnieuw starten:
ota_1 wordt overschreven, geen clean-up nodig
- Versie-check: Bij BLE connect leest de app de firmwareversie van de ESP (
VERSION_UUID characteristic). Bij mismatch met gebundelde firmware toont app een toast "Firmware-update beschikbaar" en activeert de OTA-knop.
- Tijdens actieve relais: relais vallen UIT bij start OTA (rust-toestand)
Transfertijd schatting
523KB bij ~30 KB/s effectieve BLE throughput ≈ 17 seconden. Bij slechtere verbinding ~45-60 seconden. Acceptabel.
Bestanden
| Bestand |
Wijziging |
src/main.cpp |
VERSION characteristic, OTA characteristic, esp_ota_* logica, OTA-modus flag, LED-signalering |
platformio.ini |
Geen wijziging (partitietabel al OTA-ready) |
android/.../OtaManager.kt |
Nieuw: firmware lezen, hashen, chunken, BLE verzenden |
android/.../SettingsActivity.kt |
OTA-knop + progress UI |