Skip to content

ActionHero + Tessel2

Sunday, 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!

bash
# Install the Tessel command package from NPM
npm install -g t2-cli

# Find and Rename your Tessel
t2 list
t2 rename TesselBot

# Connect the Tessel to your WiFi
t2 wifi -n <network-name> -p <password>

# Allow your computer to talk to the Tessel
t2 provision

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

bash
mkdir actionhero
cd actionhero
npm install actionhero
./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.

js
var ActionheroPrototype = require("actionhero").actionheroPrototype;
var actionhero = new ActionheroPrototype();
process.env.PORT = 80;
console.log("Starting up Tessel ActionHero Wrapper");
console.log(" local path: " + __dirname);
console.log(" working path: " + process.cwd());
if (process.cwd() !== __dirname) {
  console.log(" changing working path to : " + __dirname);
  process.chdir(__dirname);
}
actionhero.start(function (err, api) {
  if (err) {
    throw err;
  } else {
    api.log("~ boot shim complete ~");
  }
});

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

bash
> t2 run — full index.js

INFO Looking for your Tessel…
INFO Connected to tesselBot.
INFO Building project.
INFO Writing project to RAM on tesselBot (19278.336 kB)…
INFO Deployed.
INFO Running index.js…
Starting up Tessel ActionHero Wrapper
 local path: /tmp/remote-script
 working path: /root
 changing working path to : /tmp/remote-script
2016–04–24T18:50:54.228Z notice: *** starting actionhero ***
2016–04–24T18:50:59.036Z warning: running with fakeredis
2016–04–24T18:51:01.108Z info: actionhero member 10.0.1.40 has joined the cluster
2016–04–24T18:51:05.405Z notice: pid: 1491
2016–04–24T18:51:05.428Z notice: server ID: 10.0.1.40
2016–04–24T18:51:11.432Z notice: Starting server: `web` @ 0.0.0.0:8080
2016–04–24T18:51:22.957Z notice: environment: development
2016–04–24T18:51:23.198Z notice: *** Server Started ***
2016–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

js
process.env.PORT = 80;
process.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

bash
# To try out your project while connected to the Tessel2
**t2 run --full index.js**

# To install your project to the Tessel2 to it runs at boot
**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!

Last updated: