Un altro problema che dobbiamo risolvere è dove archiviare tutti i dati di cui abbiamo bisogno.
Come puoi vedere dallo schema, per vari motivi che vi spiegherò, utilizzo due tipi di storage.
SPIFFS
Come descritto a fondo nell’articolo “WeMos D1 mini (esp8266): SPIFFS FileSystem integrato” il WeMos D1 mini (come gli altri esp8266) ha una flash interna che può essere utilizzata per memorizzare i dati, ma se leggi l’articolo scopri che ha alcune limitazioni e che non è adatto per il data logging.
Ecco il codice che si occupa di restituire lo stream dei contenuti statici come pagine HTML o codice js:
bool handleFileRead(String path){ // send the right file to the client (if it exists)
DEBUG_PRINT(F("handleFileRead: "));
DEBUG_PRINTLN(path);
if(path.endsWith("/")) path += F("index.html"); // If a folder is requested, send the index file
String contentType = getContentType(path); // Get the MIME type
String pathWithGz = path + F(".gz");
if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){ // If the file exists, either as a compressed archive, or normal
if(SPIFFS.exists(pathWithGz)) // If there's a compressed version available
path += F(".gz"); // Use the compressed version
fs::File file = SPIFFS.open(path, "r"); // Open the file
size_t sent = httpServer.streamFile(file, contentType); // Send it to the client
file.close(); // Close the file again
DEBUG_PRINTLN(String(F("\tSent file: ")) + path + String(F(" of size ")) + sent);
return true;
}
DEBUG_PRINTLN(String(F("\tFile Not Found: ")) + path);
return false; // If the file doesn't exist, return false
}
Ma questo “filesystem” può essere molto utile per memorizzare le nostre pagine Web che sono essenzialmente solo in lettura, l’unica eccezione è l’indirizzo IP da esporre.
Perché usare un server FTP per caricare i dati su SPIFFS?
Aggiungo un server FTP per gestire i dati in SPIFFS perché mi piacerebbe modificare quei dati per testare nuove funzionalità o grafici in maniera facile e veloce.
Puoi disabilitarlo commentando questa riga:
// Uncomment to enable server ftp.
#define SERVER_FTP
C’è una libreria esterna molto semplice ed utile puoi fare riferimento al mio articolo “Server FTP su esp8266 ed esp32“.
L’idea è che le pagine web normalmente cambino poche volte, il fs SPIFFS è perfetto per lo scopo, ma ricorda che non supporta le directory, nel mio caso evito questo piccolo problema con la creazione di un singolo pacchetto con JS (React/Redux) e qualche altro elemento e quindi abbiamo una webapp con una struttura molto semplice.
Ho già preparato degli articoli dove spiegherò un semplice sistema per servire dinamicamente questa webapp e gestire la compressione gzip.
Scheda SD
Abbiamo quindi risolto il problema di dove mettere la nostra WebApp, ma il vero “problema” è dove memorizzare tutti i dati di logging.
La soluzione è semplice e consolidata, una scheda SD, esistono vari tipi di scheda SD e in particolare ci sono alcune SD per uso industriale (di solito non sono micro SD) che garantiscono la durata nel tempo, ma una buona microsd può essere sufficiente se pianifichi di fare almeno un backup all’anno.
Ecco la porzione di codice che fa lo stream dei dati su una response in formato JSON:
void streamFileOnRest(String filename){
if (SD.exists(filename)){
myFileSDCart = SD.open(filename);
if (myFileSDCart){
if (myFileSDCart.available()){
DEBUG_PRINT(F("Stream file..."));
DEBUG_PRINT(filename);
httpRestServer.streamFile(myFileSDCart, F("application/json"));
DEBUG_PRINTLN(F("...done."));
}else{
DEBUG_PRINTLN(F("Data not available!"));
httpRestServer.send(204, F("text/html"), F("Data not available!"));
}
myFileSDCart.close();
}else{
DEBUG_PRINT(filename);
DEBUG_PRINTLN(F(" not found!"));
httpRestServer.send(204, F("text/html"), F("No content found!"));
}
}else{
DEBUG_PRINT(filename);
DEBUG_PRINTLN(F(" not found!"));
httpRestServer.send(204, F("text/html"), F("File not exist!"));
}
}
Ho scritto anche un articolo “Come usare la scheda SD con esp8266 e Arduino” per spiegare meglio come funziona la scheda SD e come collegarla al dispositivo.
Formato dei dati di logging
Tutti i dati sono memorizzati in formato JSON, questa può sembrare una soluzione meravigliosa quando si tratta di chiamate REST e registrazione dei dati, ma “non è tutto oro ciò che luccica”.
Pros
- I dati sono strutturati, puoi organizzarli in liste “oggetti” e altro;
- È semplice da gestire;
- E i dati sono pronti per il formato dati standard delle chiamate REST.
Cons
- C’è un grosso problema: per generare un JSON strutturato il file deve essere caricato in memoria, e quando usiamo un esp8266 la memoria può essere di 40Kb a disposizione dell’utente (questo significa 40.000 / 8 = 5000 caratteri) e quando fai altro oltre a creare un file JSON questa dimensione può essere ridotta di molto.
La soluzione alternativa è usare un formato CSV o altro, ma è complesso generare dati strutturati e aggiornarli, inoltre con il file CSV aggiungi dati senza ricaricare tutto il file.
Puoi trovare maggiori informazioni e qualche esempio nel mio articolo “Gestire file JSON con Arduino, esp32 ed esp8266“
Grazie
- Centralina Web per inverter ABB (ex Power One) Aurora (WIM): intro al progetto
- Centralina Web per inverter ABB Aurora (WIM): connessione Arduino all’RS-485
- Centralina Web per inverter ABB Aurora (WIM): dispositivi di archiviazione
- Centralina Web per inverter ABB Aurora (WIM): debug e notifica
- Centralina Web per inverter ABB Aurora (WIM): impostare l’ora e UPS
- Centralina Web per inverter ABB Aurora (WIM): configurazione WIFI e server REST
- Centralina Web per inverter ABB Aurora (WIM): WebSocket e Web Server
- Centralina Web per inverter ABB Aurora (WIM): cablaggio e PCB
- Centralina Web per inverter ABB Aurora (WIM): caricare il programma ed il front end
- Centralina Web per inverter ABB Aurora (WIM): scatola stampata in 3D e completamento
- Centralina Web per inverter ABB Aurora (WIM): riparare l’errore E013
GitHub repository con tutto il codice FE (transpilato) e BE