Ein Blog

Gesammelte Notizen

Run EspruinoHub as a systemd service

20 April, 2017 | puck.js

This is a guide how to run the EspruinoHub as a service controled by systemd on an rasperrypi using raspbian.

You need espruino hub for connecting a Puck.js bluetooth device to a mqtt broker like mosqito.


First get the EspruinoHub software at https://github.com/espruino/EspruinoHub.

Install it according the guide.

Start the EspruinoHub using the


to check if the installation worked.


Then create a service user called 'EspruinoHub' using the command 

sudo useradd -r EspruinoHub

Move the directory /home/pi/EspruinoHub to /opt by

sudo mv /home/pi/EspruinoHub /opt

I do this because I do not want to have the service files in the pi home directory.

Now change the the owner of the directory '/opt/EspruinoHub' to the service user created. By

sudo chown -R EspruinoHub /opt/EsprionoHub

Then create the file startService.sh that hast this content:

cd `dirname $0`

/usr/bin/node index.js

Now create the service configuration insprired by the how you find at https://nodesource.com/blog/running-your-node-js-app-with-systemd-part-1/

go to '/etc/systemd/system', open a text editor, for example nano and create the file 'espruinoHub.service'. Using

sudo nano espruinoHub.service


Description=EspruinoHub service

ExecStart=/bin/sh /opt/EspruinoHub/startService.sh

after the file has bee saved run

sudo systemctl enable espruinoHub.service

and then start the service with

sudo systemctl start espruinoHub.service


There seems to be a problem with the status output that prevents the service to run. Fix this I changed the file lib/status.js so that it looks like this:

function dumpStatus() {
   var inRange = require("./discovery.js").inRange;
   // clear screen
   var status = '\033c';
   // ...
   status += logHistory.join("\n")+"\n\n";

   status += (new Date()).toString()+"\n\n";
   // sort by most recent
   var arr = [];
   for (var id in inRange)
   //arr.sort(function(a,b) { return a.rssi - b.rssi; });
   arr.sort(function(a,b) { return a.id.localeCompare(b.id); });
   // output
   var amt = 3;
   /*var maxAmt = process.stdout.getWindowSize()[1];
   for (var i in arr) {
     var p = arr[i];
     if (++amt > maxAmt) { console.log("..."); return; }
     status += p.id+" - "+p.name+" (RSSI "+p.rssi+")\n";
     for (var j in p.data) {
       if (++amt > maxAmt) { console.log("..."); return; }
       var n = attributes.getReadableAttributeName(j);
       var v = p.data[j].payload;
       status += "  "+n+" => "+JSON.stringify(attributes.decodeAttribute(n,v))+"\n";

// -----------------------------------------

exports.init = function() {
  //console._log = console.log;
  /** Replace existing console.log with something that'll let us
  report status alongside evrything else */
  /*console.log = function() {
    //var args = Array.from(arguments);
    var args = Array.prototype.slice.call(arguments);
    if (logHistory.length>10)
      logHistory = logHistory.slice(-5);

The lines 22, 35 to 47, 53 and 56 to 63 are commented out