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? Smile

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".

0
Il tuo voto: Nessuna
Realizzato con Drupal, un sistema open source per la gestione dei contenuti