Project: Full-Stack JavaScript on embedded SoCs

For a test equipment design and manufacturing specialist whose products are mainly used in the automobile–, space– and aeronautics industry, TenTwentyFour1024 developped a Java-Script based hardware control platform to interact with the specialised hardware.

Functionality
First trials of the Gumstix Overo, communicating with Arduino and RaspberryPi platforms over its SPI bus. First trials of the Gumstix Overo, communicating with Arduino and RaspberryPi platforms over its SPI bus.

Having previously been using a Windows-based tool that talked over serial to control their testing equipment, usage and maintenance of this software turned out to be too troublesome. Cross-platform availability being another required of the new software revision, a web-based approach was quickly deemed to be the appropriate solution and put into action. Upon agreeing on the software's requirements, TenTwentyFour1024 started working on the web-based control and measuring software, built with backbone.js and node.js.

The embedded, Linux-based System on a Chip (SoC) on the test equipment is running a node.js server communicating through websockets with the web application. Operating directly on the device's registers using the SPI interface, it adjusts frequency, and duration of a test run and concurrently reads sensor data from various sensors, reporting it back to the web-application.

Several revisions of the test equipment and software – some reading data for extended periods of time from several sensor arrays – have been developed, extended, and subsequently shipped to customers around the world. Starting with node.js 0.10.x the project has been upgraded to node.js 4.x and up using ES6 features to improve performance and code-structure.

Development

SPI timings diagram, CC by-sa 3.0 Colin M.L. Burnett SPI timings diagram (CC by-sa 3.0 Colin M.L. Burnett)
Before diving into the actual application development, a platform had to be selected and set-up, which was both small enough and could handle the requirements, the most important ones being WiFi support and being able to run a node.js server. We finally opted for the Gumstix Overo Airstorm platform, a Computer on a Module that supports the Yocto Linux platform using bitbake as a build system. Our own build environment and bitbake recipes allow us to quickly build new, fully-functional images to be flashed on to the Overo boards. The Gumstix board handles everything from talking to the motor driver to providing a WiFi access point and handling DNS requests for devices that connect to it using the web application.

TenTwentyFour1024 followed up the platform selection by writing a driver for the motor in pure JavaScript, so that data could be read and written to and from it. The driver sends and retrieves hex-encoded binary instructions directly into and form the various registers of both the motor and the sensors' analog/digital converters (ADCs). Writing a device driver in JavaScript might sound adventurous at first, and it certainly is, but using the node-spi module, we were able to come up with production and mock-drivers that allow for blazingly fast communication with all hardware controllers.

  /**
   * Instructs the device to copy a state into the AUX variable, then retrieves it.
   *
   * @param {Instruction}    copyStateIntoAUXInstruction The copy instruction.
   * @param {Array<Integer>} bytesToFetch                (Optional) Positions of the bytes to fetch.
   *                                               0 to 3, 0 = LSB, 3 = MSB.
   *                                               If unset, it will return the full register
   *                                               as a 32 bits variable. Otherwise, it will
   *                                               return the desired bytes after compacting
   *                                               them into a variable.
   *
   * @return {Void}
   */
  Device.prototype.readState = function (copyStateIntoAUXInstruction, bytesToFetch) {
      var response = [0, 0, 0, 0];
      var self     = this;
      bytesToFetch = bytesToFetch || [0, 1, 2, 3];

      this.senders.push(copyStateIntoAUXInstruction);
      this.receivers.push(null);

      var accumulateFragments = function (i, fragment) {
          response[i] = fragment[1];
      };

      var returnResponse = function (i, lastFragment) {
          accumulateFragments(i, lastFragment);
          self.setState(copyStateIntoAUXInstruction, self.assembleVariable(response));
      };

      for (var i = 0; i < bytesToFetch.length; i++) {
          this.senders.push(instructions['READ_AUX_BYTE_' + bytesToFetch[i]]);

          if (i === bytesToFetch.length - 1) {
              this.receivers.push(returnResponse.bind(null, i));
          } else {
              this.receivers.push(accumulateFragments.bind(null, i));
          }
      }
  };
  

The next step was to write a web application to allow the user to start tests and allow them to extract measurements out of those tests in the form of graphs, and CSV files that can later be either imported into spreadsheet office tools, or even re-imported and visualized using the web-application's graph renderer. The web-application combines several state-of-the-art technologies, making use of WebSockets, localStorage and the FileAPI on browsers.

The Full-Stack JavaScript on embedded SoCs project is a perfect showcase of TenTwentyFour1024's ability to leverage both its software engineering and linux systems expertise to build an impressive piece of technology based on Free and Open Source technology.

Technologies used in building this application

backbone.js

backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface. (+)

Node.js

Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. (+)

Gumstix Overo

gumstix makes small system boards based on ARM processors, such as the Overo series, running embedded Linux environments that are comparable in size to a stick of gum (hence the name). (+)

dnsmasq

Dnsmasq provides network infrastructure for small networks: DNS, DHCP, router advertisement and network boot. It is designed to be lightweight and have a small footprint, suitable for resource constrained routers and firewalls. It has also been widely used for tethering on smartphones and portable hotspots, and to support virtual networking in virtualisation frameworks. (+)

wpa_supplicant

wpa_supplicant is a WPA Supplicant for Linux, BSD, Mac OS X, and Windows with support for WPA and WPA2 (IEEE 802.11i / RSN). It is suitable for both desktop/laptop computers and embedded systems. Supplicant is the IEEE 802.1X/WPA component that is used in the client stations. (+)

systemd

systemd is a suite of system management daemons, libraries, and utilities designed as a central management and configuration platform for the Linux computer operating system. (+)

hostapd

hostapd is a user space daemon for access point and authentication servers. It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators, RADIUS client, EAP server, and RADIUS authentication server. (+)