OTA implementeren voor client ESP #3

Open
opened 2026-08-01 03:13:53 +02:00 by eddy · 3 comments
Owner

Doel

Client ESP (SylDa_Client) moet OTA updates kunnen ontvangen via BLE, net als de server dat via de OTA characteristic doet.

Huidige situatie

  • Server (main.cpp): OTA characteristic op UUID beb5...f26da, esp_ota_begin/write/end flow werkt (behalve chunk-0 bug, zie #1)
  • Client (client.cpp): geen OTA characteristic, moet na provisioning als BLE peripheral fungeren
  • Android: OtaManager ondersteunt OTA via BLE, path is al device-mode-aware

Aanpak

  • Client firmware: OTA characteristic toevoegen (zelfde flow als server)
  • Client firmware: OTA mode starten via command of dedicated characteristic
  • Android: OTA initiëren op verbonden client (settings scherm)
  • Client firmware binary in assets (firmware/client/firmware.bin) al aanwezig

Gerelateerde bestanden

  • src/client.cpp: BLE peripheral setup, OTA characteristic
  • android/.../OtaManager.kt: werkt nu via BleRelayManager (zou ook met client moeten werken)
  • android/.../SettingsActivity.kt: OTA trigger

Afhankelijkheden

  • Issue #1 (OTA server fix) eerst oplossen voor de BLE OTA flow stabiel is
## Doel Client ESP (SylDa_Client) moet OTA updates kunnen ontvangen via BLE, net als de server dat via de OTA characteristic doet. ## Huidige situatie - Server (`main.cpp`): OTA characteristic op UUID `beb5...f26da`, `esp_ota_begin/write/end` flow werkt (behalve chunk-0 bug, zie #1) - Client (`client.cpp`): geen OTA characteristic, moet na provisioning als BLE peripheral fungeren - Android: `OtaManager` ondersteunt OTA via BLE, path is al device-mode-aware ## Aanpak - Client firmware: OTA characteristic toevoegen (zelfde flow als server) - Client firmware: OTA mode starten via command of dedicated characteristic - Android: OTA initiëren op verbonden client (settings scherm) - Client firmware binary in assets (`firmware/client/firmware.bin`) al aanwezig ## Gerelateerde bestanden - `src/client.cpp`: BLE peripheral setup, OTA characteristic - `android/.../OtaManager.kt`: werkt nu via `BleRelayManager` (zou ook met client moeten werken) - `android/.../SettingsActivity.kt`: OTA trigger ## Afhankelijkheden - Issue #1 (OTA server fix) eerst oplossen voor de BLE OTA flow stabiel is
eddy added reference main 2026-08-01 03:25:59 +02:00
Author
Owner

Implementatie status — OTA voor client ESP

Client OTA is volledig geïmplementeerd (firmware v20/client v8):

Client firmware (src/client.cpp)

  • OTA characteristic op beb5483e-36e1-4688-b7f5-ea07361f26da — zelfde protocol als server (START chunk, data chunks met seq+ACK/NAK, SHA256 verify, 0xFF confirm)
  • CLIENT_OTA_AVAILABLE characteristic — client zet deze op 1 om aan de server te melden dat OTA klaarstaat
  • OTA peripheral mode: client schakelt van BLE central naar peripheral, start advertising als SylDa_Client_OTA
  • Auto-update check: leest CLIENT_OTA_TARGET characteristic van de server, als die hoger is dan eigen versie → OTA mode
  • 0xFF race-condition fix zit erin (deferred confirm net als bij server, zie #1 fix)

Server (src/main.cpp)

  • CLIENT_OTA_TARGET characteristic (beb5483e-36e1-4688-b7f5-ea07361f26dd) — Android schrijft hier de target firmwareversie, server geeft deze door aan verbonden client
  • Rapporteert client OTA availability bij versie-rapportage

Android

  • ClientOtaConnector.kt — BLE GATT client connector voor OTA, implementeert OtaTransport interface
  • BleRelayManager.ktwriteClientOtaTarget(version) schrijft target versie naar server
  • SettingsActivity.ktstartClientOtaUpdate() flow:
    1. Schrijft target versie naar server via writeClientOtaTarget()
    2. Wacht tot client verschijnt als SylDa_Client_OTA peripheral
    3. Connect + OTA flash via ClientOtaConnector + OtaManager
  • OtaManager.kt — transport-agnostisch, werkt met zowel server (BleRelayManager) als client (ClientOtaConnector)

Flow

Android → server (writeClientOtaTarget v21)
  → server BLE → client (CLIENT_OTA_TARGET notify v21)
    → client: check v21 > eigen v8 → OTA peripheral mode
      → client advertise "SylDa_Client_OTA"
        → Android: scan, connect als ClientOtaConnector
          → OtaManager: START → chunks → SHA256 → 0xFF → reboot

Resterend (optioneel): Android zou het scan+OTA gedeelte kunnen automatiseren ipv handmatig in Settings. Voor nu is de implementatie compleet en functioneel.

## Implementatie status — OTA voor client ESP Client OTA is volledig geïmplementeerd (firmware v20/client v8): ### Client firmware (`src/client.cpp`) - **OTA characteristic** op `beb5483e-36e1-4688-b7f5-ea07361f26da` — zelfde protocol als server (START chunk, data chunks met seq+ACK/NAK, SHA256 verify, 0xFF confirm) - **CLIENT_OTA_AVAILABLE characteristic** — client zet deze op `1` om aan de server te melden dat OTA klaarstaat - **OTA peripheral mode**: client schakelt van BLE central naar peripheral, start advertising als `SylDa_Client_OTA` - **Auto-update check**: leest `CLIENT_OTA_TARGET` characteristic van de server, als die hoger is dan eigen versie → OTA mode - 0xFF race-condition fix zit erin (deferred confirm net als bij server, zie #1 fix) ### Server (`src/main.cpp`) - **CLIENT_OTA_TARGET characteristic** (`beb5483e-36e1-4688-b7f5-ea07361f26dd`) — Android schrijft hier de target firmwareversie, server geeft deze door aan verbonden client - Rapporteert client OTA availability bij versie-rapportage ### Android - **`ClientOtaConnector.kt`** — BLE GATT client connector voor OTA, implementeert `OtaTransport` interface - **`BleRelayManager.kt`** — `writeClientOtaTarget(version)` schrijft target versie naar server - **`SettingsActivity.kt`** — `startClientOtaUpdate()` flow: 1. Schrijft target versie naar server via `writeClientOtaTarget()` 2. Wacht tot client verschijnt als `SylDa_Client_OTA` peripheral 3. Connect + OTA flash via `ClientOtaConnector` + `OtaManager` - **`OtaManager.kt`** — transport-agnostisch, werkt met zowel server (BleRelayManager) als client (ClientOtaConnector) ### Flow ``` Android → server (writeClientOtaTarget v21) → server BLE → client (CLIENT_OTA_TARGET notify v21) → client: check v21 > eigen v8 → OTA peripheral mode → client advertise "SylDa_Client_OTA" → Android: scan, connect als ClientOtaConnector → OtaManager: START → chunks → SHA256 → 0xFF → reboot ``` Resterend (optioneel): Android zou het scan+OTA gedeelte kunnen automatiseren ipv handmatig in Settings. Voor nu is de implementatie compleet en functioneel.
Author
Owner

Vervolg: Client OTA status zichtbaar maken in app

Probleem

Zodra de client disconnect om OTA peripheral te worden (SylDa_Client_OTA), heeft de app geen zicht meer op de client. De gebruiker weet niet wanneer hij in Settings de OTA kan starten.

Oplossing

Een nieuw CLIENT_OTA_STATUS characteristic op de server (beb5...26df):

  • Client schrijft 0x01 vlak vóór disconnect naar OTA peripheral
  • Server persisteert status in NVS (overleeft reboots)
  • Android pollt elke 30s (zelfde interval als client) en leest de status
  • Bij 0x01: toast + navigeer naar Settings met client+BLE vooringesteld
  • Bij 0x00 (client up-to-date): poll stopt

writeClientOtaTarget gebeurt nu bij elke BLE connect in onFirmwareVersion (niet pas in Settings). Idempotent, dus veilig.

Een clientOtaTriggered in-memory flag voorkomt dubbele toasts/navigatie bij herhaalde polls.

Flow

Android connect → writeClientOtaTarget(9) → poll elke 30s
Client ziet CLIENT_OTA_AVAILABLE=0x01 → schrijft 0x01 naar CLIENT_OTA_STATUS → disconnect → SylDa_Client_OTA
Server: status 0x01 in NVS + characteristic
Android poll: ziet 0x01 → toast + Settings auto-launch client OTA
OTA succes → client reconnect v9 → server ziet versie up-to-date → status 0x00 → poll stopt

Server OTA onderbreking

Client OTA status staat in NVS → overleeft server reboot. Bij herconnect schrijft Android target opnieuw (idempotent), poll herstart, vindt 0x01 → OTA gaat door.

Te wijzigen bestanden

  • src/main.cpp — new characteristic + NVS persistence
  • src/client.cpp — write status before OTA peripheral + fix !connected bug in transitie
  • android/.../BleRelayManager.kt — read CLIENT_OTA_STATUS + callback
  • android/.../BleStatus.ktonClientOtaStatus callback
  • android/.../MainActivity.kt — poller, writeClientOtaTarget op connect, triggered flag
  • android/.../SettingsActivity.kt — Intent extra startClientOta pre-select

Implementatieplan: docs/superpowers/plans/2026-08-04-client-ota-status-poll.md

## Vervolg: Client OTA status zichtbaar maken in app ### Probleem Zodra de client disconnect om OTA peripheral te worden (`SylDa_Client_OTA`), heeft de app geen zicht meer op de client. De gebruiker weet niet wanneer hij in Settings de OTA kan starten. ### Oplossing Een nieuw `CLIENT_OTA_STATUS` characteristic op de server (`beb5...26df`): - Client schrijft `0x01` vlak vóór disconnect naar OTA peripheral - Server persisteert status in NVS (overleeft reboots) - Android pollt elke 30s (zelfde interval als client) en leest de status - Bij `0x01`: toast + navigeer naar Settings met client+BLE vooringesteld - Bij `0x00` (client up-to-date): poll stopt `writeClientOtaTarget` gebeurt nu bij **elke** BLE connect in `onFirmwareVersion` (niet pas in Settings). Idempotent, dus veilig. Een `clientOtaTriggered` in-memory flag voorkomt dubbele toasts/navigatie bij herhaalde polls. ### Flow ``` Android connect → writeClientOtaTarget(9) → poll elke 30s Client ziet CLIENT_OTA_AVAILABLE=0x01 → schrijft 0x01 naar CLIENT_OTA_STATUS → disconnect → SylDa_Client_OTA Server: status 0x01 in NVS + characteristic Android poll: ziet 0x01 → toast + Settings auto-launch client OTA OTA succes → client reconnect v9 → server ziet versie up-to-date → status 0x00 → poll stopt ``` ### Server OTA onderbreking Client OTA status staat in NVS → overleeft server reboot. Bij herconnect schrijft Android target opnieuw (idempotent), poll herstart, vindt `0x01` → OTA gaat door. ### Te wijzigen bestanden - `src/main.cpp` — new characteristic + NVS persistence - `src/client.cpp` — write status before OTA peripheral + fix `!connected` bug in transitie - `android/.../BleRelayManager.kt` — read `CLIENT_OTA_STATUS` + callback - `android/.../BleStatus.kt` — `onClientOtaStatus` callback - `android/.../MainActivity.kt` — poller, `writeClientOtaTarget` op connect, triggered flag - `android/.../SettingsActivity.kt` — Intent extra `startClientOta` pre-select Implementatieplan: `docs/superpowers/plans/2026-08-04-client-ota-status-poll.md`
Author
Owner

Implementatieplan: Client BLE OTA via Server Broker

Na brainstorm-sessie is het volgende ontwerp vastgelegd:

Architectuur

  • Server fungeert als broker/registry met twee nieuwe AES-encrypted characteristics:
    • CLIENT_REGISTRY (Read/Notify): Client meldt UUID + versie aan Server
    • CLIENT_CONTROL (Write/Notify): Notificaties voor update-beschikbaarheid
  • Client rapporteert bij verbinding zijn versie aan de Server
  • Android App detecteert update-behoefte via Server, stuurt trigger
  • Client start tijdelijke BLE Server (Dual-Role) om firmware te ontvangen

Flow

  1. Client boot → verbindt met Server → schrijft UUID + versie naar CLIENT_REGISTRY
  2. App verbindt met Server → leest registry → ziet dat Client v5 heeft, App heeft v6
  3. App stuurt UPDATE_AVAILABLE (0x10) naar CLIENT_CONTROL (Target UUID)
  4. Server stuurt Notify naar Client
  5. Client start NimBLEServer als SylDa_Client_OTA_[UUID] + schrijft READY (0x20) terug
  6. App verbindt direct met Client → voert OTA uit (zelfde protocol als Server OTA)
  7. Client herboot → rapporteert nieuwe versie aan Server

Specificatie

Zie docs/superpowers/specs/2026-08-04-client-ble-ota-spec.md voor exacte byte-structuren en state-machines.

Implementatieplan

Zie docs/superpowers/plans/2026-08-04-client-ble-ota.md voor gedetailleerde taken.

Taken

  1. Server: Broker characteristics + registry logic
  2. Client: Versie-rapportage + update-notificaties + Dual-Role OTA service
  3. Android: Broker integratie + Client OTA trigger + directe OTA naar Client
  4. Verificatie: Volledige cyclus testen

Branch: feature/client-ble-ota

## Implementatieplan: Client BLE OTA via Server Broker Na brainstorm-sessie is het volgende ontwerp vastgelegd: ### Architectuur - **Server** fungeert als broker/registry met twee nieuwe AES-encrypted characteristics: - `CLIENT_REGISTRY` (Read/Notify): Client meldt UUID + versie aan Server - `CLIENT_CONTROL` (Write/Notify): Notificaties voor update-beschikbaarheid - **Client** rapporteert bij verbinding zijn versie aan de Server - **Android App** detecteert update-behoefte via Server, stuurt trigger - **Client** start tijdelijke BLE Server (Dual-Role) om firmware te ontvangen ### Flow 1. Client boot → verbindt met Server → schrijft UUID + versie naar `CLIENT_REGISTRY` 2. App verbindt met Server → leest registry → ziet dat Client v5 heeft, App heeft v6 3. App stuurt `UPDATE_AVAILABLE` (0x10) naar `CLIENT_CONTROL` (Target UUID) 4. Server stuurt Notify naar Client 5. Client start `NimBLEServer` als `SylDa_Client_OTA_[UUID]` + schrijft `READY` (0x20) terug 6. App verbindt direct met Client → voert OTA uit (zelfde protocol als Server OTA) 7. Client herboot → rapporteert nieuwe versie aan Server ### Specificatie Zie `docs/superpowers/specs/2026-08-04-client-ble-ota-spec.md` voor exacte byte-structuren en state-machines. ### Implementatieplan Zie `docs/superpowers/plans/2026-08-04-client-ble-ota.md` voor gedetailleerde taken. ### Taken 1. Server: Broker characteristics + registry logic 2. Client: Versie-rapportage + update-notificaties + Dual-Role OTA service 3. Android: Broker integratie + Client OTA trigger + directe OTA naar Client 4. Verificatie: Volledige cyclus testen **Branch:** `feature/client-ble-ota`
Sign in to join this conversation.
No description provided.