ESP8266: Aggiornamenti OTA
Che senso avrebbe un sistema con WiFi se poi, per riprogrammarlo, fosse sempre necessario portarlo offline, attaccargli una seriale, programmarlo e poi rimontare il tutto? Oltretutto la seriale è lenta... Soprattutto se si vuole avere uno SPIFFS bello "cicciottello"...
Ovviamente non sono il primo a pensarlo, ed infatti è stata creata la classe ArduinoOTA proprio per gestire gli aggiornamenti "sul campo".
Purtroppo, talvolta non "si annuncia" all'IDE di Arduino, o risulta con indirizzo 0.0.0.0 .
Questo succede perché la classe viene inizializzata prima che la connessione sia stabilita (o prima che venga ricevuto l'indirizzo dal DHCP).
// Esempio sbagliato #include <ArduinoOTA.h> #include <ESP8266WiFi.h> const char* ssid = "YourSSID"; const char* password = "A_very_secure_password_for_Your_net"; const char* host = "nodename"; void setup() { WiFi.persistent(false); // Avoid wear-out WiFi.mode(WIFI_STA); WiFi.hostname(host); WiFi.begin(ssid, password); ArduinoOTA.setHostname(host); // ArduinoOTA.setPasswordHash("MD5sum"); // MD5sum := echo -n password | md5sum - ArduinoOTA.begin(); } void loop() { ArduinoOTA.handle(); }
Il problema si risolve con una modifica piuttosto limitata:
// Esempio corretto #include <ArduinoOTA.h> #include <ESP8266WiFi.h> const char* ssid = "YourSSID"; const char* password = "A_very_secure_password_for_Your_net"; const char* host = "nodename"; void setup() { WiFi.persistent(false); // Avoid wear-out WiFi.mode(WIFI_STA); WiFi.hostname(host); WiFi.begin(ssid, password); ArduinoOTA.setHostname(host); // ArduinoOTA.setPasswordHash("MD5sum"); // MD5sum := echo -n password | md5sum - } void loop() { static bool otaStarted=false; if(otaStarted) { // Handle updates ArduinoOTA.handle(); } else { if(WiFi.status() == WL_CONNECTED) { /* setup the OTA server once we're connected and have obtained an IP */ ArduinoOTA.begin(); otaStarted=true; } } }
In pratica si ritarda l'attivazione degli update OTA al momento della connessione -- d'altronde, se non si è connessi è inutile attivarli, no?
E, finalmente, sarà possibile riprogrammare "sul campo" i nodi già installati senza bisogno di smontarli (a meno di non sbagliarsi ed inviare un aggiornamento senza supporto OTA!).
Per completezza, oltre alla modalità "push" (con l'attivazione del server sul nodo) è possibile anche la modalità "pull", col nodo che interroga un server esterno per verificare se sono disponibili aggiornamenti. La prima è ovviamente più adatta a nodi sempre attivi, la seconda a nodi che magari rimangono in sleep per lunghi periodi, o per i quali si vuole un maggior controllo sul momento dell'aggiornamento -- magari con l'attivazione di un tasto fisico.
Purtroppo entrambe le modalità supportano solo l'invio "cleartext" del nuovo firmware, con tutte le problematiche che questo comporta. Usando l'hash di una password (purché robusta) si complica un po' la vita all'attaccante, che altrimenti, con la passwod in chiaro potrebbe intercettare il firmware ed inviare un nuovo aggiornamento. Comunque è disponibile la classe Updater, più a basso livello ma che permette una gestione più custom del nuovo firmware.
In ogni caso deve sempre esserci abbastanza spazio per il nuovo firmware tra quello attuale e l'inizio di SPIFFS!. Quindi, se avete un Wemos D1mini Pro con flash da 16M ma usate uno SPIFFS di 15M, avete praticamente le stesse restrizioni che avreste su un ESP01 con 1M di flash senza SPIFFS. Comunque, finora non mi sono neanche avvicinato a sketch di 500k... Al più ~300K, con la maggior parte usata dalle librerie "di sistema".
Commenti
modalità PULL
Ciao
Sei l'unico che ne ha parlato : puoi fare un esempio di modalità "PULL" ?
cioè : ho un file .bin su un server esterno e tramite AuduinoOTA lo vorrei scaricare
magari se ci fosse la possibilità di vedere il progress
grazie
È nella documentazione ufficiale
In pratica, quando il nodo decide che è il momento di aggiornarsi (p.e. perché l'utente ha premuto un tasto di conferma), contatta un server web inviandogli un po' di informazioni e, se il server risponde con un bin, prova a fare l'aggiornamento.
La sezione chiave della documentazione è https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#advanced-updater .
Nota: è possibile aggiornare via OTA sia il codice che il filesystem, ma bisogna fare attenzione al "partizionamento". Se si vuole OTA per il filesystem, e si ha un ESP con 4M di flash, si può usare solo 1M per il fs (e poco meno di 1M per il codice).
Molto utile anche la possibilità di firmare digitalmente gli aggiornamenti (che però, purtroppo, rimangono non criptati: quindi meglio non inserire in chiaro le credenziali della rete WiFi )
PS: dimenticavo, non è (facilmente) possibile vedere l'avanzamento. Peccato: la onProgress() non viene chiamata se non per gli aggiornamenti push da IDE.