OTA-Update-System

Technische Dokumentation zur Over-the-Air-Update-Architektur von RADR

Dieses Dokument beschreibt das Over-the-Air-(OTA-)Update-System des Research And Desire Wireless Remote (RADR), einschließlich der Update-Kette, des Ablaufs der Zustandsmaschine und der zu aktualisierenden Komponenten.

Überblick

RADR verwendet ein zweiteiliges OTA-Update-System:

KomponenteBeschreibungBinärdatei
FirmwareESP32-Anwendungsbinärdateifirmware.bin
DateisystemLittleFS-Partition mit Geräteregistrierung und Protokollspezifikationenlittlefs.bin

Das Dateisystem-Update ist besonders wichtig für die Geräteunterstützung – es enthält die Buttplug.io-Registrierung, die Bluetooth-Dienst-UUIDs den Gerätekonfigurationen zuordnet. Dies ermöglicht das Hinzufügen von Unterstützung für neue Geräte, ohne dass Firmware-Änderungen erforderlich sind.

OTA-Update-Architektur

Update-Server

Updates werden von Supabase Storage bereitgestellt. Die Server-URL ist in platformio.ini definiert:

UPDATE_SERVER_URL="https://acjajruwevyyatztbkdf.supabase.co/storage/v1/object/public/radr-firmware"

Binärdatei-URLs folgen diesem Muster:

  • Firmware: {UPDATE_SERVER_URL}/master/firmware.bin
  • Dateisystem: {UPDATE_SERVER_URL}/master/littlefs.bin

Ablauf der Zustandsmaschine

Aktualisierungen werden von der RADR-Zustandsmaschine verwaltet. Der Update-Ablauf wird über das Menü Settings ausgelöst.

Zustandsübergänge

VonNachBedingung
settings_menuupdateDer Benutzer wählt "Update Device" + WiFi verbunden
settings_menuupdate.wifiDer Benutzer wählt "Update Device" + WiFi nicht verbunden
update.wifiupdateWiFi-Verbindung hergestellt
updateupdate.filesystemDer hasFilesystemUpdate-Guard gibt true zurück
updateupdate.softwareDer hasSoftwareUpdate-Guard gibt true zurück (kein Dateisystem-Update)
updateupdate.doneKeine Updates verfügbar
update.filesystemupdate.softwareDateisystem-Update abgeschlossen + Software-Update verfügbar
update.filesystemrestartDateisystem-Update abgeschlossen, kein Software-Update
update.softwarerestartSoftware-Update abgeschlossen (immer Neustart)
update.donerestartDer Benutzer bestätigt

Was wird aktualisiert?

Firmware-Update

Das Firmware-Update ersetzt die ESP32-Anwendungsbinärdatei. Dazu gehören:

  • Kernanwendungslogik
  • UI- und Anzeigecode
  • Bluetooth-Stack und Gerätekommunikation
  • Zustandsmaschine und Navigation
  • Eingabeverarbeitung (Encoder, Tasten, Bumper)

Implementierung: updateSoftwareTask() in src/tasks/update.cpp

void updateSoftwareTask(void *pvParameters) {
    // Uses ESP32 HTTPUpdate library
    httpUpdate.setRebootOnUpdate(true);  // Auto-reboot on success

    String url = String(UPDATE_SERVER_URL) + "/master/firmware.bin";
    httpUpdate.update(client, url);
}

Das Firmware-Update führt bei Erfolg automatisch einen Neustart des Geräts durch.

Dateisystem-Update

Das Dateisystem-Update ersetzt die LittleFS-Partition, die Folgendes enthält:

DateiZweck
/registry.jsonOrdnet BLE-Dienst-UUIDs Protokollspezifikationsdateien zu
/protocols/*.jsonButtplug.io v4-Gerätekonfigurationsdateien

Implementierung: updateFilesystemTask() in src/tasks/update.cpp

void updateFilesystemTask(void *pvParameters) {
    LittleFS.end();  // Unmount before update

    httpUpdate.setRebootOnUpdate(false);  // Don't reboot yet

    String url = String(UPDATE_SERVER_URL) + "/master/littlefs.bin";
    httpUpdate.updateSpiffs(client, url);

    LittleFS.begin();  // Remount after update
}

Das Dateisystem-Update löst keinen automatischen Neustart aus. Dadurch können sowohl das Dateisystem als auch die Firmware vor dem Neustart nacheinander aktualisiert werden.

Registry-Update-Kette

Wenn das Dateisystem aktualisiert wird, wird die Geräteregistrierung von Buttplug.io aktualisiert:

Die Registrierung wird beim Gerätestart durch initRegistry() in src/devices/registry.cpp geladen:

  1. Fest codierte Geräte werden zuerst registriert (z. B. OSSM)
  2. /registry.json wird von LittleFS gelesen
  3. Jede Dienst-UUID ist einem ButtplugIODeviceFactory zugeordnet
  4. Protokollspezifikationen werden bei Bedarf geladen, wenn Geräte erkannt werden

Verfügbarkeit von Updates

Die Verfügbarkeit von Updates wird durch Guard-Funktionen in src/state/guards.hpp bestimmt:

bool hasFilesystemUpdate(const State &state, const Event &event) {
    return isFilesystemUpdateAvailable;
}

bool hasSoftwareUpdate(const State &state, const Event &event) {
    return isSoftwareUpdateAvailable;
}

Diese Flags werden folgendermaßen gesetzt:

FlagGesetzt, wenn
isSoftwareUpdateAvailableFORCE_UPDATE-Kompilierungsflag oder der Server zeigt ein Update an
isFilesystemUpdateAvailableFORCE_UPDATE-Kompilierungsflag oder der Server zeigt ein Update an

Die aktuelle Implementierung verfügt über ein TODO für die automatische Update-Überprüfung. Derzeit werden Aktualisierungen manuell ausgelöst und die Verfügbarkeit muss über Kompilierungsflags oder externe Mechanismen festgelegt werden.

Wichtige Quelldateien

DateiZweck
src/tasks/update.cppImplementierungen der Update-Tasks (updateSoftwareTask, updateFilesystemTask)
src/tasks/update.hDeklarationen der Update-Tasks und Verfügbarkeitsflags
src/state/machine.hZustandsmaschinendefinition mit Aktualisierungszuständen
src/state/guards.hppGuard-Funktionen für die Verfügbarkeit von Updates
src/devices/registry.cppRegistrierungsinitialisierung aus LittleFS
data/registry.jsonZuordnungen von Dienst-UUIDs zu Protokollspezifikationen
data/protocols/*.jsonButtplug.io-v4-Gerätespezifikationen

Entwicklungshinweise

Aktualisierungen erzwingen

Verwenden Sie für Entwicklung und Tests das Kompilierungsflag FORCE_UPDATE:

build_flags =
    -D FORCE_UPDATE

Dadurch werden sowohl isSoftwareUpdateAvailable als auch isFilesystemUpdateAvailable auf true gesetzt.

Lokale Dateisystem-Updates

Wenn Sie lokal entwickeln, verwenden Sie die Funktion „Upload Filesystem“ von PlatformIO:

pio run --target uploadfs

Dadurch wird der Inhalt des Verzeichnisses data/ auf die LittleFS-Partition hochgeladen.

"Upload Filesystem" löscht die vorhandene LittleFS-Partition vor dem Schreiben. Alle Laufzeitänderungen gehen verloren.

Verwandte Dokumentation

Auf dieser Seite