Sonntag, 4. Juni 2017

IoTSystem - Patchday!

Hallo,

über Pfingsten habe ich mich entschlossen ein schon länger geplantes Feature umzusetzen. Sicher hat der eine oder andere schonmal von "OTA-Updates" gehört. "OTA" steht hier für "Over the air", es werden also Updates drahtlos übertragen. Ein Anwendungsbeispiel ist die Aktualisierung von Android-Smartphones, welche neue Software über WLAN erhalten.

Da der Großteil meiner bisher angebundenen Geräte auf ESP8266 basiert, habe ich mit diesen Geräten begonnen. Glücklicherweise beinhaltet die ESP8266-Arduino-Bibliothek direkt eine Möglichkeit zu OTA-Updates. Die zugehörige Dokumentation beschreibt dafür drei Wege.

Weg 1 - Arduino IDE

Um OTA-Updates über die Arduino IDE verteilen zu können, muss zunächst erst einmal Python installiert sein. Der Upload erfolgt dann über einen virtuellen Serialport analog zum Upload über einen USB-Programmer. Allerdings muss jedes Gerät einzeln aktualisiert werden, daher habe ich diesen Weg für mich ausgeschlossen.

Weg 2 - Webbrowser

Die Verteilung von Updates über den Webbrowser funktioniert, indem der ESP8266 als Webserver dient, welchem man über einen POST-Request die neue Software unterschiebt. Dafür muss die installierte Software allerdings erst einen extra dafür vorhandenen Server starten, zu welchem man sich verbinden kann. Aber auch hier muss jedes Gerät einzeln aktualisiert werden.

Weg 3 - HTTP-Server

Der letzte Weg für OTA-Updates beschreibt die selbstständige Aktualisierung über einen HTTP-Server. Die installierte Software muss dafür eine Anfrage an den Server stellen, welchem sie dabei Version mitteilen kann. Der Server schickt nun abhängig davon, ob eine Software mit höherer Versionsnummer bereitsteht oder nicht die neue Software, oder lehnt die Anfrage ab. Großer Vorteil dieser Variante ist, dass dem Server nur einmal eine neue Version übergeben werden muss, welche sich dann alle Geräte selbstständig abholen können.

Eben auf Grund dieses Umstandes habe ich mich für den dritten Weg entschieden. Es mussten nun also zwei Dinge getan werden. Einmal musste der HTTP-Server geschrieben werden, welche die Updates speichert und verteilt. Entsprechend dazu musste die Software der ESPs auch dazu gebracht werden, sich die Updates abzuholen.

Zur Abfrage der Updates habe ich den bei der Dokumentation enthaltenen Beispielcode verwendet, an welchen ich lediglich IP, Port und URL angepasst habe. Um meine verschiedenen Geräte unterscheiden zu können, verwende ich einen URL-Parameter. Die integrierte Softwareversion muss natürlich für jeden Build erhöht werden. Der gezeigte Codeabschnitt ist so eingebaut, dass er nach Anfrage durch den Systemserver behandelt wird.


const unsigned long int VAR_VERSION = 14;
const String VAR_OTAUPDATENAME = "RGBSTRIP";

String UpdatePath = "/espupdate?device=" + VAR_OTAUPDATENAME;
TurnOnStatusLED();
t_httpUpdate_return ret = ESPhttpUpdate.update(ServerIP, 4713, UpdatePath, String(VAR_VERSION));
  switch(ret) {
    case HTTP_UPDATE_FAILED:
      Serial.println(F("[update] Update failed."));
      break;
    case HTTP_UPDATE_NO_UPDATES:
      Serial.println(F("[update] Update no Update."));
      break;
    case HTTP_UPDATE_OK:
      Serial.println(F("[update] Update ok.")); // may not called we reboot the ESP
      break;
  }
TurnOffStatusLED();

Dies ist auf Geräteseite auch schon alles. Passend dazu habe ich meinen bereits vorhanden Http-Server erweitert. Bisher diente dieser nur als Kommunikationsschnittstelle zum User-Interface. Nun nimmt er auch die Anfragen der Geräte entgegen. Die Anfragen enthalten das anfragende Gerät, bzw. dessen Softwaretyp, in der URL und die mitgeschickte Softwareversion als Http-Parameter namens "x-ESP-version". Zusätzlich werden diverse Http-Parameter wie verwendeter, freier und vorhandener Speicher etc. mitgeschickt. Wer will kann diese auch zur Ermittlung der entsprechend zurückzusendenden Software verwenden, für meine Anwendung reichen jedoch die genannten Parameter.
Der Server sucht nun im Dateisystem nach einem entsprechend dem Gerätetyp benannten Ordner. Darin sollte sich eine "Version.txt" befinden, welche die Version der neuen Software enthält. Durch den Vergleich der Versionsnummer aus der Datei und der Versionsnummer ergibt sich, ob ein Update vorhanden ist oder eben nicht. Als letztes lädt der Server eine "Firmware.bin", welche sich ebenfalls im Ordner befinden sollte und schickt diese an das anfragende Gerät.


Tritt während des Prozesses ein Fehler auf, ist also eine Datei nicht vorhanden, fehlt ein benötigter Parameter etc., so wird ein entsprechender Statuscode  (400-BadRequest / 404-NotFound / 500-InternalServerError) zurückgeschickt, nach welchem das anfragende Gerät weiß, wie es zu verfahren hat.

Um nun ein Update zu starten, muss mit der Android-IDE (oder mit dem Plugin für Visual Studio) die Software kompiliert werden, wodurch im Ordner des Sketches eine Binärdatei mit der Endung ".bin" entsteht. Diese muss in das richtige Verzeichnis kopiert werden. Zudem muss die Versionsnummer in der "Version.txt" erhöht werden. Darauf hin kann über das aktualisierte Nutzerinterface das Update ausgelöst werden. Dieses zeigt nun auch den Gerätetyp und die aktuelle Versionsnummer an. Unterstützt das jeweilige Gerät keine OTA-Updates, dann stehen diese Möglichkeiten entsprechend auch nicht zur Verfügung.


Keine Kommentare:

Kommentar veröffentlichen