12 Dec 2016

Connecting a serial device to the web

Categories: Nodejs, JavaScript

At Label305 we have several projects that require us to connect some piece of hardware to either a mobile device or a computer. Since our focus is on developing appealing interfaces to control these devices, we have done quite a bit of research on how to do this efficiently.

One of our latest projects had us connecting a device over a serial port to the web, so that people could record and share activities. To get this up and running we researched different techniques using technologies we had experience with. So let me share some of those with you.

Note: This article was also published by Joris at Medium

Approach 1: Chrome App (note: these are deprecated!)

Chrome apps provide you with a wrapper exposing some API’s which are normally not available for web applications.

In this case we are focusing on the serial API, which has functions such as getDevices and connect (as you would expect). The trick, however, is to attach it to a webpage without having to pack your entire interface. You can do this by including your page inside of a webview and stretching it to fill up your app.

Now you’re able to send messages to your webview using postMessage on which you can listen from your web application with window.addEventlistener('message', callback)

Approach 2: WebUSB

This technology would be awesome to use for your connections. Check out the WebUSB RFC as well as the Arduino example code. It allows you to connect a device directly through API’s available from Chrome. It will show you a pop-up asking to gain access to a certain device, after you do so you will get a callback in the form of a promise with the device you can connect with. To play around with these, you have to switch some flags in Chrome after which you can get it to work.

Unfortunately it is a still a bit too early to get this up and running for serial devices (on Linux that is at least). Your serial drivers will probably get first call on claiming the interface, after which your browser won’t have any options to claim it. But even if you get the connection up and running you, at the time of writing, have to write your own serial driver.

Beside this, note that your existing device has to be registered with a, currently non-existent, public repository of allowed hosts. If you are developing a new device you can include a protocol that explicitly broadcasts allowed hosts. Read more about this in the security section of the RFC.

Approach 3: Companion app

This requires your end-user to install a little app guiding them through the connection process, after which it can expose the connection through, for example, a socket.

Since we are experienced web-developers, an app using web technologies is preferable for us to maintain it in the future. So we opted for an Electron app, which allows us to use the node-serial library. Now you expose a socket on a port chosen by you on localhost using, for example, Socket.IO. Since sockets are not as tied down by CORS rules in your browser, you can listen to check if the companion application is running and implement your own protocol talking to this app.

Note that you have to think about what you will expose; also from a security standpoint. We chose to use a custom protocol which allowed us to send bytes directly to the connected device, but the companion app would verify that indeed we are talking to the device for which the application was designed.

They say hardware is hard, but also connecting with them won’t be a walk in the park either. It is useful to read up on protocols and strategies before making choices on a technology for you.

Written by: Joris Blaak