[RISOLTO] Arduino MKR 1010 - aggiornamento da remoto - OTA

Buongiorno,

ho questa necessità, aggiornare più Arduino da remoto in un colpo solo. Ho trovato le librerie ArduinoOTA, che funzionano bene e mi permettono di caricare lo Sketch via ip. E fin qui tutto bene.

Però non vorrei essere io a dover caricare il nuovo Sketch ma che sia questo a controllare su un server ftp se è presente uno Sketch aggiornato ed in caso scaricarlo e aggiornarsi in autonomia.

Esiste qualche cosa o sapreste darmi delle indicazioni a riguardo? Grazie per qualsiasi aiuto

Ecco lo sketch finito e funzionante. Forse non è perfetto e perfettamente ottimizzato, non sono un programmatore, ma il suo lavoro lo fa.

L’Arduino ogni tot controlla se su un server web se esiste un file sketch più recente, se è presente lo scarica e si aggiorna in autonomia. Si riavvia ed riprende il suo lavoro normalmente.

Lo copio di seguito perchè potrebbe tornare utile ad altri e magari essere ulteriormente ottimizzato.

Librerie usate:

ArduinoOta
ArduinoHttpClient
wifiNina

/*
  This example downloads sketch update over network.
  It doesn't start the OTA upload sever of the ArduinoOTA library,
  it only uses the InternalStorage object of the library
  to store and apply the downloaded binary file.
  To create the bin file for update, use in Arduino IDE command
  "Export compiled binary".
  To try this example, you should have a web server where you put
  the binary update.
  Modify the constants below to match your configuration.
  Created for ArduinoOTA library in February 2020
  by Juraj Andrassy
*/

#include <WiFiNINA.h>
#include <ArduinoOTA.h>
#include <ArduinoHttpClient.h> // changed from HttpClient.h
#include "arduino_secrets.h"

char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;
int status = WL_IDLE_STATUS;

const short VERSION = 3;
#define Serial SerialUSB
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

void handleSketchDownload() {

  const char* SERVER = "192.168.103.179"; // must be string for HttpClient
  const unsigned short SERVER_PORT = 8080;
  const char* PATH = "/update-v%d.bin";
  const unsigned long CHECK_INTERVAL = 5000;

  static unsigned long previousMillis;

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis < CHECK_INTERVAL)
    return;
  previousMillis = currentMillis;

  // EthernetClient transport;
  WiFiClient transport;
  HttpClient client(transport, SERVER, SERVER_PORT);

  char buff[32];
  snprintf(buff, sizeof(buff), PATH, VERSION + 1);

  Serial.print("Check for update file ");
  Serial.println(buff);

  client.get(buff);

  int statusCode = client.responseStatusCode();
  Serial.print("Update status code: ");
  Serial.println(statusCode);
  if (statusCode != 200) {
    client.stop();
    return;
  }

  int length = client.contentLength();
  if (length == HttpClient::kNoContentLengthHeader) {
    client.stop();
    Serial.println("Server didn't provide Content-length header. Can't continue with update.");
    return;
  }
  Serial.print("Server returned update file of size ");
  Serial.print(length);
  Serial.println(" bytes");

  if (!InternalStorage.open(length)) {
    client.stop();
    Serial.println("There is not enough space to store the update. Can't continue with update.");
    return;
  }
  byte b;

  client.setTimeout(30000); //timeout per download
  
  while (length > 0) {
    if (!client.readBytes(&b, 1)) // reading a byte with timeout
      break;
    InternalStorage.write(b);
    length--;
  }
  InternalStorage.close();
  client.stop();

  if (length > 0) {
    Serial.print("Timeout downloading update file at ");
    Serial.print(length);
    Serial.println(" bytes. Can't continue with update.");
    return;
  }

  Serial.println("Sketch update apply and reset.");
  Serial.flush();
  InternalStorage.apply(); // this doesn't return
}

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ;
  }
  Serial.print("Sketch version ");
  Serial.println(VERSION);

  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);
    delay(10000);
  }
  Serial.print("You're connected to the network");
  printCurrentNet();
  printWifiData();
}

void loop() {
  // check for updates
  handleSketchDownload();

  // add your normal loop code below ...
}


void printWifiData() {
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  byte mac[6];
  WiFi.macAddress(mac);
  Serial.print("MAC address: ");
  Serial.println(bytesToMACAddress(mac));
}

void printCurrentNet() {
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  byte bssid[6];
  WiFi.BSSID(bssid);
  Serial.print("BSSID: ");
  Serial.println(bytesToMACAddress(bssid));

  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.println(rssi);

  byte encryption = WiFi.encryptionType();
  Serial.print("Encryption Type:");
  Serial.println(encryption, HEX);
  Serial.println();
}

String getMACAddress()  {
  byte mac[6];
  WiFi.macAddress(mac);

  return bytesToMACAddress(mac);
}

String bytesToMACAddress(byte mac[]) {
  String m = "";

  for (int i = 5; i >= 0; i--) {
    m = m + byeToHex(mac[i]);
    if (i > 0) {
      m = m + ":";
    }
  }

  return m;
}

String byeToHex(byte b) {
  if (b < 16) {
    return "0" + String(b, HEX);
  }

  return String(b, HEX);
}

Esempi usati di riferimento:

Aggiornamento diretto, con ethernet

Aggiornamento via SD, con ethernet

Grazie per aver condiviso. Karma +1

Nel sorgente sopra postato ho scordato di levare/commentare il seguente codice:

while (!Serial) { ; }

che naturalmente bloccava il riavvio in autonomia dell'Arduino.

(se dico castronate o risolvo in modo poco elegante/consono ogni suggerimento è davvero ben accetto)

molto interessante!!!!!

quale web server posso usare??