Para realizar actualizaciones seguras y evitar interrupciones debidas a la conexión WiFi o factores externos, podemos descargar un archivo binario desde un servidor HTTP. Este archivo binario se almacenará en el ESP32 mediante SPIFFS y luego será utilizado para realizar la actualización del firmware.
El primer paso es inicializar SPIFFS para poder trabajar con el sistema de archivos del ESP32:
#include "SPIFFS.h"
void setup_spiff(){
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
}
El siguiente código se encarga de descargar el archivo binario desde el servidor HTTP y guardarlo en el ESP32:
#include <HTTPClient.h>
#define BIN_NAME "/firmware/binario.bin" // Directorio donde se guardará el binario
#define UPDATE_URL "fmesasc.com/firmware.bin" // URL del archivo binario
void downloadFile() {
HTTPClient http;
File f = SPIFFS.open(BIN_NAME, FILE_WRITE);
if (f) {
http.begin(UPDATE_URL);
int httpCode = http.GET();
if (httpCode > 0) {
if (httpCode == HTTP_CODE_OK) {
WiFiClient* stream = http.getStreamPtr();
while (stream->available()) {
char c = stream->read();
f.print(c);
}
}
} else {
Serial.printf("[HTTP] GET... failed, error: %s
", http.errorToString(httpCode).c_str());
}
f.close();
http.end();
}
}
Este código descarga el archivo binario desde el servidor especificado por UPDATE_URL y lo guarda en SPIFFS bajo el nombre BIN_NAME.
Una vez descargado el archivo binario, podemos proceder a instalarlo en el ESP32:
void updateWithFile(){
File file = SPIFFS.open(BIN_NAME);
if(!file){
Serial.println("Failed to open file for reading");
return;
}
Serial.println("Starting update..");
size_t fileSize = file.size();
if(!Update.begin(fileSize)){
Serial.println("Cannot do the update");
return;
};
Update.writeStream(file);
if(Update.end()){
Serial.println("Successful update");
} else {
Serial.println("Error Occurred: " + String(Update.getError()));
return;
}
file.close();
Serial.println("Reset in 4 seconds...");
delay(4000);
ESP.restart();
}
Este código carga el archivo descargado y lo instala en el ESP32, reiniciando el dispositivo una vez que la actualización se haya completado correctamente.
También es posible actualizar el firmware de forma remota mediante MQTT. Podemos recibir la URL del archivo binario a través de un mensaje MQTT y luego proceder a descargarlo.
#include <WiFi.h>
#include <PubSubClient.h>
const char* mqttServer = ""; // Servidor MQTT
const int mqttPort = 1883; // Puerto MQTT
WiFiClient wifiClient;
PubSubClient client(wifiClient);
void setup_mqtt() {
client.setServer(mqttServer, mqttPort);
// Intentar conexión hasta que se establezca
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) { // Conectar sin credenciales MQTT
Serial.println("connected");
client.subscribe("/demo/update");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
client.setCallback(callback);
}
callback para manejar mensajes MQTTLa función callback se ejecutará cada vez que se reciba un mensaje en el topic al que estamos suscritos. Si el topic es /demo/update, descargaremos el archivo binario usando downloadFile().
void callback(char* topic, byte *payload, unsigned int length) {
Serial.print("data:");
Serial.write(payload, length);
Serial.println();
if(strcmp(topic, "/demo/update") == 0) {
downloadFile(); // Descargar el archivo binario cuando recibamos el mensaje MQTT
}
}
Este código permite recibir una notificación mediante MQTT para descargar el archivo de actualización cuando el mensaje sea enviado al topic /demo/update.