Program a smart device directly, no install needed

Kenneth Christiansen
6 min readJan 16, 2017

--

I have been excited about Web USB since when I heard about it the first time. Many of my friends ask me why I would care about a cabled standard and not just use Bluetooth. Well, technologies like Bluetooth are definitely cool and have their strengths, but so does USB.

Think about it, say in a hospital you really want to limit signals as they can affect machines and readings, and for additional security you can even lock the USB connector behind a mini door with an actual physical key, so that only the people who need access will get it.

Simple early demo using the Arduino Leonardo

So I have been playing a bit around with Web USB lately and giving feedback to the authors of the spec. First I got everything running using the official demo which makes use of an Arduino Leonardo and regular Arduino board software (Firmata). It was quite easy to use as the Web USB team already wrote the software allowing for a simple serial connection between the device and the browser. For Web USB to work, the device needs to support being a USB peripheral and it needs to have the right Web USB headers, so some software support for Web USB.

Web USB makes it real easy to talk to devices, but they need to have the right Web USB headers

Now I have a few other more modern boards which have additional features, such as Bluetooth and even JavaScript support. As I work at Intel on basically anything related to web, I am pretty excited about the Curie-based Arduino 101 [Genuino 101 in Europe] board. First of all, it supports Bluetooth and it can run the Zephyr RTOS which is a Linux Foundation Collaborative Project.

I like Zephyr a lot. It is rather low-level and powerful, but I also find its APIs quite easy to deal with, but even cooler — at least for a web fan like me — is that it can run JavaScript code using the JerryScript engine, and that there is good access to device APIs like OCF, GPIO, I2C, and sensors like the onboard gyroscope and accelerometer. All you have to do is install the ZJS runtime described here.

ZJS supports sensors like gyroscope based on the Generic Sensor API spec

A coworker of mine, Sudarsana Nagineni has been adding Web USB support to Zephyr with a bit of guidance from me (adding the right headers etc), so I set out to do a simple demo. Now, ZJS has a sample project called ashell, which is a kind of interactive mini shell with build in JS support, ie. you can actually evaluate JS code or transfer source snippets using the Intel HEX protocol.

I really find this to be a cool use case and a great way for hobbyists to play around with internet-of-things and smart devices. Plug in a device and there you go, no software install needed.

Running one of the ZJS sample demos transferred to the device using the browser (https://webusb-shell.appspot.com)

Writing the browser client / site was actually quite simple. The Arduino 101 is flashed with ashell and Web USB support pointing to the demo site. The site (client) then created a serial connection and sends code using IHEX.

Being able to plug a device and immediately use it, no install needed, is just mind blowing

Now, I didn’t find any JavaScript implementation of IHEX but instead a C one found here, but that was not a problem because it gave me a good change to play around with Emscripten and Web Assembly, which is about to ship in Chrome.

Wrote the simple strtoihex method that I needed, using the IHEX library and compiled it all to Web Assembly

Compiling to Web Assembly was quite simple, and Emscripten spits out the wasm module as well as a .js file which does the proper exporting.

$ emcc ihex/kk_ihex_write.c convert.c -s WASM=1 -o ihex.js -s EXPORTED_FUNCTIONS=”[‘_strtoihex’]”

Loading and exporting the C method via Web Assembly

As Emscripten is pretty general purpose, the .js file exports support for things that I don’t need, like Filesystem support.

Reusing existing C/C++ code and exporting it to the web is just amazing, and Web Assembly and Emscripten makes that quite easy

I played a bit around with it and could minify it further using arguments like

$ … -s NO_FILESYSTEM=1 -s EXPORTED_RUNTIME_METHODS=”[‘intArrayFromString’, ‘cwrap’]”

The configuration file here lists most of these settings which can be tweaked

The client application

To actually write JavaScript code in the browser I needed a simple client using a simple editor and potentially a terminal to access ashell directly.

Now I have been quite fond of using Visual Studio Code lately which is based on Microsoft's Monaco code editor, so I went ahead and used that.

As the terminal, I started building my own but quickly realized that that would probably not scale and instead found the nice Google HTerm which works pretty nicely.

Using HTerm to control the ashell running on the Arduino 101

The result is pretty cool. You plug in the Arduino 101 and a few seconds later a dialog pops up (if externally powered it should appear immediately. When just powered over USB the device waits some seconds at boot in order to receive DFU flash instructions).

Now from here you can either use the terminal to directly access ashell or you can choose a code sample (or modify them) and then transfer them directly to the device after which they will run.

Possible improvements

Now the demo is already quite cool, but there are still a few bugs in ashell, like console.log(…) not working all the time, and the some code size restrictions due to limited flash/memory on the device.

That is made even worse as ashell has to parse the received JS code, which take up a lot of memory on the device. Now, JerryScript supports snapshotting so the parsing could be avoided if the browser were to run JerryScript via Web Assembly :-) and that would also cut off about 30% of the transfer size.

Takeaways

So there you got it! Along with Web Bluetooth, Web NFC and similar APIs, the web is becoming more and more powerful, enabling the web to expand to other industries while bringing with it some of the major benefits, like low friction (no install) and great reach.

Smart devices (aka Internet-of-Things but not necessarily connected to the internet directly) are super cool to play with, but getting started can be quite hard for most due to having to learn a bit of electrical engineering, plus whole new software stacks, often lower-level (proprietary C and C++, or similar).

With JavaScript support, that becomes much easier and the turn around time smaller as well. This can be very important because prototyping and time to market is essential today.

I do realize that you might not want to ship a product using JS, but it is possible to re-implement the device code using lower level APIs (C in Zephyr's case) for lower memory requirements, higher performance, more battery life and decreased BOM cost, at any time.

--

--