Accesso remoto microcontrollori ESP con Google Firebase

Buongiorno a tutti.
Sperimentando con i vari servizi gratuiti offerti da Google, ed in particolare con Google Firebase, mi sono imbattuto in questa libreria completissima che consente di usare questo servizio cloud con le MCU Espressif (per ora solo quelle purtroppo).

Google Firebase è una suite di servizi (Realtime Database, Firestore, Hosting, Storage etc etc) che già con il piano gratuito Spark Plan può coprire abbondantemente le esigenze Cloud più comuni di noi makers.
Ad esempio, con Realtime Database, il sevizio che sto usando in questo momento, abbiamo a disposizione un totale di 1GB per i nostri dati ed un traffico massimo di 10GB/mese.

Il Realtime Database è un servizio davvero interessante, veloce ed efficiente, ma in particolare ciò che mi interessava in questo caso è la possibilità di “sottoscrivere” lo streaming degli eventi in funzione di un “topic”, un po’ come si fa con MQTT.
In parole povere se scrivo o aggiorno un dato sul database, tutti i client connessi vengono notificati.

Da qui l’idea di utilizzarlo come infrastruttura per collegare una webpage (o una web app su dispositivi mobile) al nostro microcontrollore e devo dire che funziona davvero alla grande!
Massima flessibilità, tempi di risposta velocissimi ed il vantaggio di avere come dipendenza “esterna” un colosso come Google che difficilmente smetterà di esistere dall’oggi al domani o stravolgerà la “politica dei prezzi” e di ciò che offre gratuitamente.

Quando realizzo webpage da usare come interfaccia grafica per una MCU, io di solito uso WebSocket per avere un canale di comunicazione bidirezionale e poter aggiornare la GUI non solo quando l’utente esegue un’operazione, ma anche quando lato MCU si genera un evento e voglio notificare/aggiornare l’utente.

Usando lo stesso approccio ho fatto questo progetto di prova con la classica pagina che mostra un elenco di I/O con stato e pulsante per attivare disattivare le uscite esp-vue-gui-firebase

Il firmware per la MCU è poco più dell’esempio incluso nella libreria, modificato secondo le mie esigenze per inviare un payload con l’elenco dei pin e del relativo stato (in formato JSON) ogni volta che lo stato di uno dei gpio monitorati cambia e fare il parsing dei comandi ricevuti dalla pagina (sempre JSON, unico comando supportato writeOut).

Per sviluppare pagine web, negli ultimi tempi sto imparando ad usare il framework Vue di cui sono entusiasta, ma ovviamente lo stesso funzionamento si può ottenere anche con l’utilizzo di HTML e Javascript “plain”.

Se volete provare/migliorare rapidamente il progetto che ho realizzato, dopo aver installato Vue (e Node.js), scaricate o clonate il repository, aprite un terminale (nella cartella del progetto ovviamente) e digitate questo comando per installare in automatico tutte le dipendenze necessarie

npm install

Completata l’installazione, con il comando

npm run build

verrà generato il codice html/javascript/css nella cartella /dist

Per provare rapidamente la pagina invece, con

npm run serve

verrà avviato un webserver locale. Io uso VSCode che ha il terminale integrato per fare tutto: sia firmware ESP che progetto Vue.

I contenuti html/javascript/css che vengono generati possono essere poi caricati su un sito “statico”. Lo stesso Google ha un servizio del genere, ma io ho usato Github perché più rapido: basta solo fare l’upload dei file contenuti in /dist cosi come sono ( i file .map in realtà non sono necessari).

Ad esempio questa è la mia pagina (chiaramente se l’ESP è spento, non vedrete cambiare nulla).
https://cotestatnt.github.io. Le credenziali di test sono dummyemail@email.it - dummypassword

1 Like

Ciao cotestatnt, ti ringrazio perchè ho trovato molto interessante quanto da te esposto. Non ho ancora avuto tempo di approfondire ma mi sono riproposto di farlo quanto prima. Anch'io, da quando li ho scoperti, trovo che i WebSocket siano di una comodità unica. Ho provato a curiosare nel DOM della tua pagina ed ho visto in più punti una notevole quantità di dati la cui funziona non conosco. Gradirei se potessi spiegarmi la loro origine ed utilità. Riporto di seguito un print screen di quanto visto.

Ciao @Diego67... Pensavo che l'argomento non fosse di interesse :grinning_face_with_smiling_eyes:
Se intendi quello evidenziato con il printscreen, si tratta di immagini vettoriali in formato svg.
Le ho incluse direttamente nel sorgente html per fare in modo di generare una pagina completa senza dipendenze esterne.

Questa pagina infatti nasce originariamente per essere memorizzata direttamente in flash usando uno script js che genera un file "webpage.h" contenente un array di byte da importare nello sketch.
L'array memorizza "in formato C" i byte della pagina completa e zippata (ho mutuato lo stesso approccio usato con alcune delle più utilizzate librerie per il wifi manager (su github dovrebbe esserci anche questa versione, non ricordo se aggiornata).

Visto che la pagina era già pronta, è rimasto lo stesso approccio anche qui, ma in effetti non era necessario (ho modificato solo il codice per collegarsi con Google Firebase al posto del server locale che gira sull'ESP).

Il resto è tutto generato da Vue con i suoi meccanismi interni di creazione dei DOM.

Penso che molte volte più che non interessare non venga capito quanto esposto o venga ritenuto troppo diverso da quello a cui di solito si è abituati. Anche a me è capitato di perdere mesi per portare a termine un progetto, di descriverlo in modo particolareggiato pensando che potesse interessare a molti e poi avere pochissimi riscontri. ( vedi per esempio: Scheda I/O con sw per controllo luci e configurabile via Web - #3 by Diego67 ) . Come detto, più che ritenere che sia inutile, mi consolo pensando che non sia stato compreso completamente quanto esposto.

Tornando a quanto da te fatto, il sistema che usi per convertire un'immagine in un array di byte quali vantaggi possiede rispetto al convertire l'immagine in code64 per poi inserirla nel codice html come stringa? Io, per ora, con l'ESP non ho mai utilizzato immagini e quindi ti chiedo i pro e i contro dei 2 sistemi.

No, mi sono spiegato male.
L'array non rappresenta solo le immagini, ma tutta la pagina completa e compressa in formato gzip.
Le immagini in effetti potrei anche codificarle base64, ma con gli svg secondo me non conviene. Se apri un'immagine svg con un editor di testo, vedrai che è tutto in chiaro, codificarle aggiungerebbe byte in più (tipicamente codificare del testo base64 richiede una capacità maggiore di 1,3/1,5 volte la lunghezza del testo da codificare).

In pratica il file "webpage.h" generato dallo script contiene questo:

const uint32_t WEBPAGE_HTML_SIZE = 51854;
const char WEBPAGE_HTML[] PROGMEM = { 8,196,64,12,237,125,138,137,218,108,152...... }

Nello sketch poi aggiungo l'handler per la relativa richiesta HTTP:

void setup() {
  ...
  server.on("/yourwebpage", handleWebPage);
  ...
}

void handleWebPage() {
  server.sendHeader("Content-Encoding", "gzip");
  server.send_P(200, "text/html", WEBPAGE_HTML, WEBPAGE_HTML_SIZE);
}

La ragione principale che mi fa propendere per questo metodo, è che sviluppo tutta la parte di interfaccia grafica in modo distinto dal firmware del microcontrollore e con gli strumenti che preferisco (come detto mi piace molto il framework Vue).
Andando poi a zippare, riduco lo spazio occupato in flash e velocizzo di molto il caricamento delle pagine.
Ad esempio la pagina dell'esempio (quello originale, non la versione con Google Firebase) occupa poco più di 50Kb di memoria flash. HTML, Javascript e CSS tutto compreso senza caricare risorse esterne perché volevo che funzionasse anche senza Internet.
In realtà lo zoccolo duro (circa 40Kb) è il runtime di Vue, quindi potrei aggiungere molte altre funzionalità senza incrementare di molto la dimensione.

Ciao cotestatnt, ora ho capito meglio come operi. Ho provato a leggere anche la tua pagina : GitHub - cotestatnt/vue-mcu-gui: Create a GUI for you ESP MCU. Ammiro la tua capacità di destreggiarti e far convivere più "tecnologie". Io sinceramente, rispetto a te, possiedo un bagaglio conoscitivo molto più limitato anche se il desiderio di progredire è sempre presente. Fino a non molto tempo fa ho sviluppato applicazioni esclusivamente in ambiente Microsoft ( Visual Studio + .Net ) sia per le pagine Web che Windows. Stanco però di utilizzare framework comodissimi ma "pesanti" e dal funzionamento a volte poco chiaro ho cercato, dove possibile, di utilizzare lato Web solamente l'essenziale e cioè HTML ( poco ) parecchio codice Javascript puro + Ajax e CSS. Ancora più motivato in questa ricerca dell'essenziale è stato il voler iniziare a sviluppare pagine Web per ESP. Più ci lavoro più apprezzo la potenza di JavaScript e questo mi ha portato progressivamente a ridurre il codice HTML e a creare sempre più da JS. Sempre al fine di ridurre lo spazio e di creare app funzionati anche senza Internet ho evitato di utilizzare anche JQuery . Logicamente anch'io creo le pagine all'esterno dell'IDE di Arduino. Utilizzo per questo l'IDE di Visual Studio e poi faccio il debug tramite Chrome+F12. Una volta testata la pagina non la "Zippo" ma la compatto togliendogli quanto non necessario (Spazi, CR+LF, Commenti, ecc.. ) e la inserisco nello sketch di Arduino (ESP) come stringa in chiaro. Anch'io per il dialogo tra Pagina ed MCU utilizzo i WebSoket. In questo modo, fino ad ora, sono riuscito a contenere la dimensioni delle pagine, anche mediamente complesse, a pochi KByte. (<10). Questo procedimento mi permette di realizzare applicazioni senza troppe pretese sia a pagina singola che a pagina multipla col minimo di occupazione. Sicuramente nel caso di pagina singola l'utilizzo di un framework come Vue permette di creare app più stabili, belle e potenti ma richiede uno sforzo iniziale per l'apprendimento. Come da te detto l'utilizzo di Vue ( offline ) anche per la pagina più elementare comparta comunque un'occupazione minima di circa 40KB. Da quanto ho capito, se fosse necessario creare una app multi pagina ( sempre offline ) questi 40KB di occupazione si dovrebbero moltiplicare per il numero di pagine. Alla fine, come sempre, non penso che esista un sistema migliore in tutto ma esiste il sistema migliore per quanto serve fare e questo ognuno deve saperlo valutare. Spero comunque, come detto in precedenza, di trovare il tempo per approfondire Vue+Google Firebase. ( tutto sarebbe più facile se ci fosse un fine/stimolo )
Ti saluto cordialmente e ti auguro buono studio.

Ciao @Diego67... mi era sfuggito il tuo post.

No, il runtime una volta "in memoria" rimane buono per tutte le pagine, cosi come il framework di stile scelto (Bulma, Bootstrap etc etc ).

In questo momento ad esempio, sto sviluppando con un collega un progetto multipagina un po' più articolato che non ha a che fare con il mondo embedded sempre con Vue (una web GUI per un sistema di visione) .
Di conseguenza, non mi sono proprio posto il problema dello spazio occupato, ma alla fine tutto il codice, compreso il pacchetto Bootstrap completo, ha una dimensione totale è di circa 100kb che sarebbe andata benissimo anche per un ESP considerato che di solito montano una flash almeno da 4Mb.

Chiaramente con l'approccio minimalista come il tuo si ottiene l'occupazione minima possibile al costo di uno sviluppo un po' più laborioso e (forse) una minore scalabilità.
Alla fine si tratta di trovare un compromesso tra "comodità" e "prestazioni" come per ogni cosa.