ActionHero + Tessel2

actionhero javascript node.js 
Sun Apr 24 2016


I just received my Tessel 2 in the mail.


For those of you who don’t know, the Tessel is a small, low-power computer which is capable of running node.js natively. This little micro-computer has all the bells and whistles of a first-class IoT device, including wifi, pins, uART support, etc…. BUT IT SPEAKS A HIGH-LEVEL LANGUAGE I ACTUALLY WANT TO USE! Needless to say, I’m pretty excited. After spending a fair amount of time getting node.js to run on a Phidget board, the Tessel seems like the next iteration in an IoT device that might actually be accessible.

After going though the tutorials and getting the LED lights on the board to blink I wanted to move on to getting ActionHero running on the board so I could have background tasks and web-sockets. There were a few changes required to get this running:

Getting Started

First Connect to your Tessel2 and set it up!

1# Install the Tessel command package from NPM 2npm install -g t2-cli 3 4# Find and Rename your Tessel 5t2 list 6t2 rename TesselBot 7 8# Connect the Tessel to your WiFi 9t2 wifi -n <network-name> -p <password> 10 11# Allow your computer to talk to the Tessel 12t2 provision

Create a new ActionHero project just like you would for any use case

1mkdir actionhero 2cd actionhero 3npm install actionhero 4./node_modules/.bin/actionhero generate

Working Directory

The first issue I encountered was around how the Tessel2 execution path. Actionhero makes a lot of assumptions about how you start the process, so it can load up your local config files and actions, overriding what is in the core project.

When the Tessel runs your code, it runs it from /root but your code resides in /tmp/remote-script. To solve this, we can create a simple wrapper script for your project. Create an index.js at the root of your project, and require ActionHero directly. Then, we can check if the __dirname of this file is different than process.cwd(), and if it is, we can change it. From there, we can then boot the ActionHero server.

1var ActionheroPrototype = require("actionhero").actionheroPrototype; 2var actionhero = new ActionheroPrototype(); 3process.env.PORT = 80; 4console.log("Starting up Tessel ActionHero Wrapper"); 5console.log(" local path: " + __dirname); 6console.log(" working path: " + process.cwd()); 7if (process.cwd() !== __dirname) { 8 console.log(" changing working path to : " + __dirname); 9 process.chdir(__dirname); 10} 11actionhero.start(function (err, api) { 12 if (err) { 13 throw err; 14 } else { 15 api.log("~ boot shim complete ~"); 16 } 17});

When this runs, you can see the change in the output:

1> t2 run — full index.js 2 3INFO Looking for your Tessel… 4INFO Connected to tesselBot. 5INFO Building project. 6INFO Writing project to RAM on tesselBot (19278.336 kB)7INFO Deployed. 8INFO Running index.js… 9Starting up Tessel ActionHero Wrapper 10 local path: /tmp/remote-script 11 working path: /root 12 changing working path to : /tmp/remote-script 132016–04–24T18:50:54.228Z — notice: *** starting actionhero *** 142016–04–24T18:50:59.036Z — warning: running with fakeredis 152016–04–24T18:51:01.108Z — info: actionhero member 10.0.1.40 has joined the cluster 162016–04–24T18:51:05.405Z — notice: pid: 1491 172016–04–24T18:51:05.428Z — notice: server ID: 10.0.1.40 182016–04–24T18:51:11.432Z — notice: Starting server: `web` @ 0.0.0.0:8080 192016–04–24T18:51:22.957Z — notice: environment: development 202016–04–24T18:51:23.198Z — notice: *** Server Started *** 212016–04–24T18:51:23.203Z — info: ~ boot shim complete ~

A nice thing about this boot file is that you actually set some tessel-specific overrides here, that won’t effect your local development when you run the normal npm start. For example, I want the web server, when running on the Tessel, to run on port 80 and set the NODE_ENV. To to that I added the like

1process.env.PORT = 80; 2process.env.NODE_ENV = "production";

… which has the effect of overriding the default in the config, just like if I would have launched the server with that ENV flag.

Web-Sockets

I’ve noticed that pretty much all the websocket servers add significant boot time to the process, adding around ~10 minutes. The app does boot, but it’s painfully slow. I actually think this has to do with the magnification of the JS file onto disk, and not the server itself.

I don’t need web-sockets for my project, so I disable the server… this makes things much faster.

Run it

1# To try out your project while connected to the Tessel2 2**t2 run --full index.js** 3 4# To install your project to the Tessel2 to it runs at boot 5**t2 push --full index.js**

You can reach your Tessel in a browser via <tessel_name>.local

Observations

  • While running ActionHero on a Tessel2 is far slower than on a *real* computer, booting up in under a minute is a real impressive feat for such a tiny board. That’s quick enough to consider using it in the field.
  • File I/O is slow. If you are planning on serving/saving assets to/from disk, expect a fairly slow response time. I’m going to guess that this is one of the major contributors to a slow boot time.
  • Because file I/O is so slow, be sure you disable development mode (possibly by setting the NODE_ENV as pointed out above). It constantly polls the file system…. and you can’t really edit files on the Tessel itself anyway

What’s Next?

I’ve already got my Tessel2 tweeting a photo every minute (thanks ActionHero tasks and a very simple to A/V API)… what can you come up with?

I previously noted that the Tessel could not support binary modules like `ws`, but it can!

Hi, I'm Evan

I write about Technology, Software, and Startups. I use my Product Management, Software Engineering, and Leadership skills to build teams that create world-class digital products.

Get in touch