Introduzione
Durante lo sviluppo dei miei progetti, mi capita spesso di dover progettare una interfaccia utente (GUI) che dialoga via seriale con i dispositivi che realizzo.
In passato ho scelto di realizzare tali interfacce in C# utilizzando il Framework .Net, framework che consente uno sviluppo molto rapido, grandi possibilità di personalizzazione (come l’uso di font custom nella GUI di RTCSetup) e la capacità di accedere ai vari elementi del sistema operativo, quali la systray (vedi la GUI di Type4Me).
Mi sono però chiesto come poter realizzare una interfaccia cross-platform, in modo che possa essere utilizzata anche da utenti Linux e Mac. La prima possibilità è utilizzare un linguaggio di sviluppo che abbia un compilatore/interprete per ogni sistema operativo, come Java (volendo esiste anche il progetto Mono per il Framework .Net) o Phyton. Sviluppare GUI con tali linguaggi richiede però l’utilizzo di framework dedicati, spesso di terze parti. Java inoltre ha solo definito le specifiche relative alle API di comunicazione seriale (javax.comm); è quindi necessario adottare una libreria esterna (la più famosa è RxTx) che le implementi.
Oggi voglio invece presentarvi una alternativa che non richiede librerie esterne e che consente lo sviluppo di applicazioni cross-platform con le medesime tecniche di creazione di un sito web: le Chrome Apps.
Chrome App
Una Chrome App è essenzialmente una applicazione, sviluppata utilizzando le tecnologie web (HTML5, CSS, Javascript) che viene eseguita dal motore del browser Chrome.
I vantaggi rispetto ad un sito web sono:
[checklist]
- maggiore integrazione con il desktop (no barra degli indirizzi…)
- raggruppamento in un Launcher dedicato (vedi screenshot sotto)
- possibilità di interfacciarsi con l’hardware (ad esempio le porte seriali)
[/checklist]
Struttura di una Chrome App
Una Chrome App è formata da 3 elementi:
- il file manifest, che contiene i metadati della applicazione (nome, versione, descrizione…)
- lo script di background che si occupa di creare l’interfaccia della app
- l’interfaccia, composta da pagine HTML, librerie javascript, fogli di stile (CSS)…
Ho preparato una app di esempio che “simula” il Serial Monitor dell’IDE di Arduino. La app è disponibile sul chrome web store e il suo codice sorgente nel mio repository Github.
Vediamo gli elementi nel dettaglio.
Il manifest.json contiene i metadati. Molto importante è la dichiarazione che andremo ad utilizzare la libreria serial e il nome del nostro script di background:
Lo script di background non fa altro che creare una finestra di 600 x 500 pixels non ridimensionabile e di aprire all’interno di tale finestra la pagina window.html:
L’applicazione principale è quindi composta da 3 files:
- window.html, pagina HTML di base
- main.js, funzioni javascript
- main.css, foglio di stile per i vari elementi grafici
Ho inoltre utilizzato la libreria jQuery e il suo plugin jQuery.simplemodal per visualizzare i vari popup.
Accedere alle porte seriali
Per accedere via javascript alle porte seriali del PC, Chrome mette a disposizione le API chrome.serial.
Iniziamo a elencare le porte seriali disponibili sul PC e ad aggiungerle ad una combobox in modo che l’utente possa selezionare quella desiderata:
chrome.serial.getDevices(function(ports) { for (var i = 0; i < ports.length; i++) { var portName = ports[i].path; var newOption = '' + portName + ''; var newOption = '<option value="' + portName + '">' + portName + '</option>'; $("#serial_ports_combobox").append(newOption); } }); |
Il collegamento alla porta seriale scelta avviene chiamando il metodo connect:
chrome.serial.connect(selectedPort, connectionOptions, onConnect); |
A tale metodo va passato un array (connectionOptions) contenente le impostazioni della porta:
var connectionOptions = { "bitrate": 9600, "dataBits": "eight", "parityBit": "no", "stopBits": "one", "receiveTimeout": 500, "sendTimeout": 500 }; |
Una volta collegati, è possibile inviare dati con il metodo send:
chrome.serial.send(connectionId, convertStringToArrayBuffer(textToSend), function(sendInfo) { if(sendInfo.error) $.modal('<div id="title">Unable to send data: ' + sendInfo.error + '</div>') }); |
In caso di errore viene valorizzato sendInfo.error ed è quindi possibile gestirlo (nell’esempio sopra viene visualizzato un popup di errore).
Chi programma in javascript sa che una caratteristica fondamentale di tale linguaggio è l’essere asincrono. La ricezione di dati dalla seriale segue proprio questo paradigma. Per prima cosa è necessario aggiungere un listener (una nostra funzione) all’evento onReceive:
chrome.serial.onReceive.addListener(onReceive); |
La funzione onReceive() sarà quindi chiamata ogni volta che un nuovo dato è ricevuto sulla porta seriale:
function onReceive(info) { if (info.connectionId == connectionId && info.data) { var str = convertArrayBufferToString(info.data); $("#receive_textarea").append(str); $("#receive_textarea").scrollTop($("#receive_textarea")[0].scrollHeight); } } |
La funzione verifica se effettivamente sono stati ricevuti dati e in caso affermativo converte l’oggetto ArrayBuffer in una stringa e la aggiunge alla textArea.
Test
E’ possibile provare una Chrome App semplicemente attivando la Developer mode nelle impostazioni di Chrome e successivamente cliccando su Load unpacked extension…
Selezionando la cartella che contiene l’app in fase di sviluppo, questa viene caricata da Chrome ed è possibile eseguirla.
Per quanto riguarda la distribuzione delle applicazioni, è possibile crearne un pacchetto installabile con la funzione Pack extension… o – in alternativa – esse possono essere caricate sul chrome web store previa iscrizione al programma Chrome Developer.
Conclusioni
In questo tutorial vi ho mostrato come si possa, grazie alle Chrome Apps, realizzare facilmente applicazioni cross-platform. In tal modo possiamo dotare i nostri progetti elettronici di una comoda interfaccia utente fruibile da chi utilizza Windows, Linux o MacOS (e in maniera sperimentale anche su Android e iOS).
Qual è la vostra scelta quando si tratta di realizzare GUI per i vostri progetti? Ditemelo nei commenti!
“Creating a Chrome App was for example the choice of the developing team of Cleanflight, one of the most famous firmware for multicopter’s flight control boards.”
It is somewhat disrespectful to attribute this decision to anyone working on Cleanflight considering Cleanflight was a hostile fork of Baseflight and its GUI where the author who did all of the work on building the Chrome App (who also did work on other Chrome apps with USB backends).
The choice to use Chrome was made long before Cleanflight was created, and the person who actually made the decision to use Chrome was unhappy about the Cleanflight team copying his work.
Hi Dustin! Thanks for your comment, I really wasn’t aware of this “cleanflight-vs-baseflight” war. I did a small research on google and found a lot of different versions and point of views about the story. Let’s keep it simple: if Cleanflight / Baseflight and also Multiwii (the “father”) has a Chrome App GUI, the technology works pretty well and it’s worth a try!
Will this work on a Rapsberry Pi?
Hi Mat, yes Chrome Apps do work under Raspbian
Hey Luca do you have a github with the complete source code provided? Im trying to build the same thing and am having trouble linking the html elements to the corresponding js parts.
Hi, of course the source is on Github (as explained in the article…)
Thanks for sharing this – this tutorial was really helpful to get me started with tweaking Chrome Apps
Ho provato la webapp con un convertitore seriale RS232-USB Prolific in Chrome sia in Mac che in Win7 e funziona correttamente. Se apro in Chrome (sia Mac che Win) la pagina window.html non rileva alcuna porta seriale e il menu a tendina rimano non popolato e non funzionante. Come mai?
Giuseppe è normale, Chrome ha un diverso livello di sicurezza se esegui una “app” o se carichi a mano la pagina html… in questo secondo caso non sono disponibili le API per accedere alle porte seriali
Ho provato l’app e l’ho trovata molto utile per interfacciare il mio inverter fotovoltaico.
Ho però necessità di fare delle modifiche per includere il CRC nei dati che trasmetto e poi vorrei potermi inviare le risposte su thingspeak oltre che scriverle sulla text-area.
Ho scaricato il tuo package, ho fatto alcune modifiche, e ho eseguito la Load unpacked extension, ma una volta fatto non riesco a trovare il modo di eseguirla per effettuare dei test.
Scusa ma sono nuovo delle chrome application e, inoltre, ho letto che da giugno 2022 non sono più supportate, ma spero che in qualche modo si possa manutenerle.
Altrimenti ci sarebbe il modo di migrarle?
Grazie
Ulteriori approfondimenti sulla questione Chrome applications.
Beh, purtroppo è proprio vero. Non sono più supportate e addirittura da gennaio 2023 non sarà più possibile lanciarle, figuriamoci se sarà possibile modificarle………
Sono sostituite da una nuova piattaforma di sviluppo.
Le Progressive Web Application – PWA (https://support.google.com/chrome/thread/174381169?visit_id=638003704918400057-862713327&p=chrome_app_deprecation&rd=1)
Occorre quindi procedere a migrare le Chrome application verso le PWA.
Grazie comunque.
grazie per l’approfondimento!