Introduction
During the development of my electronic projects, I sometimes need to develop a graphical user interface (GUI) that talks using serial communication with the devices I create.
In the past, I usually chose to develop those interfaces in C# and using the .Net Framework; framework which allows a rapid development, offers great ways to customize the interface (for example the ability to use custom fonts as in the GUI for RTCSetup) and makes easy to access all the different graphical elements of the operating system, like the systray (cfr the GUI for Type4Me).
I asked myself how I could create a really cross-platform interface, that is an interface that can run also on Linux and Mac. You may consider to use a programming language that has a compiler/interpreter for almost all the operating systems, like Java (a solution for the .Net Framework could be the Mono project) or Phyton. Developing a GUI with those languages however requires the use of dedicated frameworks, sometimes made by third party developers. In addition, Sun/Oracle only defined the specification of the Java’s serial communication APIs (javax.comm); you therefore need to adopt an external library (the most famous one is RxTx) that implements those APIs .
Today I’m going to describe you a way to develop cross-platform applications with the same techniques you use to develop web sites and without requiring external libraries: the Chrome Apps.
Chrome App
A Chrome App is basically an application, developed using the common web technologies (HTML5, CSS, Javascript), executed by the engine behind the Chrome browser.
The main advantages compared to a standard web site are:
[checklist]
- seamless desktop integration (no address bar…)
- grouped in a dedicated Launcher (see screenshot below)
- ability to interface with hardware devices (for example the serial ports)
[/checklist]
Anatomy of a Chrome App
A Chrome App is made by 3 main elements:
- the manifest file, which contains the application’s metadata (name, version, description…)
- the background script, which creates the event page responsible for managing the app life cycle
- the main interface, made by HTML pages, javascript scripts, cascade stylesheets (CSS)…
I prepared a demo app that “emulates” the Serial Monitor included in the Arduino IDE. The app is available on the chrome web store and it’s source code is hosted on my Github’s repository.
Let’s see its code in details.
The manifest.json file contains the metadata. Very important is to declare that we want to access the serial ports and to specify the name of the background script:
The background scripts creates a not resizable window (600 x 500 pixels) to display the window.html page:
The main application is then made by 3 files:
- window.html, the base HTML page
- main.js, the file which contains all the javascript functions
- main.css, the file with the styles for the different graphical elements
I also used the jQuery library and its plugin jQuery.simplemodal to display the different message dialogs.
Serial ports access
To be able to interact via javascript to the serial ports of your PC, Chrome offers the chrome.serial APIs.
First, let’s list the available ports and add them to a combobox so that the user may choose the one he wants to connect to:
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); } }); |
To connect to a chosen serial port, use the connect method:
chrome.serial.connect(selectedPort, connectionOptions, onConnect); |
You need to pass an array (connectionOptions) with all the port settings:
var connectionOptions = { "bitrate": 9600, "dataBits": "eight", "parityBit": "no", "stopBits": "one", "receiveTimeout": 500, "sendTimeout": 500 }; |
Once connected, you can send data to the port using the send method:
chrome.serial.send(connectionId, convertStringToArrayBuffer(textToSend), function(sendInfo) { if(sendInfo.error) $.modal('<div id="title">Unable to send data: ' + sendInfo.error + '</div>') }); |
In case of error, the sendInfo.error is not null and, in the example above, an error message is displayed.
A main characteristic of the javascript language is to be asynchronous; this is indeed the paradigm for receiving data from the serial port. First, you must add a listener (a custom function) to the onReceive event:
chrome.serial.onReceive.addListener(onReceive); |
The onReceive() function will be called each time a new data is available on the serial port:
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); } } |
The function first checks if a valid data was received on the expected serial connection; if so converts the ArrayBuffer object to string and adds it to the textArea.
Test
You can test a Chrome App simply enabling the Developer mode in the Chrome browser settings and then clicking on Load unpacked extension…
If you choose the folder that contains the app, this is loaded in Chrome and you can run it.
If you want to distribute your application, you can create an installable package with the Pack extension… button or – alternatively – you can upload it on the chrome web store after having subscribed (for a small fee) the Chrome Developer program.
Conclusion
In this tutorial I described how you can, using the Chrome Apps, easily develop real cross-platform applications. In this way, you can add a rich user interface to your electronic projects and it will run on Windows, Linux or MacOS (and with an experimental library also on Android and MacOS).
What’s your choice when you need to develop a GUI for your projects? Let me know in the comments!
“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!