Node-Red

Installing Node-Red as an intermediate layer between RFM interface and EmonCMS

This is the third part of my article series on how to set up an IoT base station using a Raspberry PI and EmonCMS. If you came here by chance, I suggest that you go take a look at the first article, which, besides being a natural entry point, also contains an overview of the series.

Node-red is an easy-to-use visual flow control application that is capable of reading from (and writing to) a serial port and sending information using MQTT or ReST (or socket or HTTPRequest or ..), thus making it perfect as an intermediate flow-control layer between the RFM12PI and EmonCMS.

Once having set up the Raspberry PI with the EmonBase OS, installing Node-Red is pretty straight forward, but requires a bit of console work. In this article I will describe how to install Node-Red on a Raspberry PI and connect it to RFM12PI/RFM69PI and EmonBase.

Installing Node-Red on the Raspberry PI consists of several steps, one of which obviously is installing Node.js. The remainder of this article describes all required steps.

Installing Node-Red

Assuming that the base station is used exclusively for IoT we use the home folder of the default pi user as working space.

As of writing, EmonHub is not compatible with the latest version of Node.js and must be installed in version 0.12.6.

  1. First Node.js must be installed. Do this by downloading version 0.12.6 of the Debian package for the ARM architecture and install it:
    rpi-rw
    cd ~
    wget http://node-arm.herokuapp.com/node_archive_armhf.deb
    sudo dpkg -i node_archive_armhf.deb

    Once installed the installation package can be deleted:

    rm node_archive_armhf.deb
  2. Now Node-Red can be installed by executing the following commands:
    rpi-rw
    sudo apt-get install git-core build-essential python-dev python-rpi.gpio
    sudo npm install -g --unsafe-perm node-red
    sudo npm cache clean

    The first command installs required dependencies for Python, then Node-Red is installed, which takes a lot of time, and, finally the npm cache is cleared to preserve space on the SD-card.

  3. Now Node-Red should be installed successfully and its version can be checked by executing the following command:
    /usr/local/lib/node_modules/node-red/nodes/core/hardware/nrgpio ver 0

    According to the installation guide over at Node-Red running this should return a version that is at least 0.5.8 if you are installing on an original Raspberry PI and at least 0.5.11 on a Raspberry Pi 2.

Installing required modules

To read data from the serial port of the Raspberry PI and to forward data from Node-Red to EmonCMS sub flows can be configured that handles the requirements of such tasks. Luckily, though, nodes have been created that accommodate these tasks in easily configurable nodes. These, along with some other useful nodes and components can be installed using the Node package manager:

cd /usr/local/lib/
sudo npm install -g --unsafe-perm node-red-node-emoncms node-red-node-serialport time
sudo npm cache clean

This installs node-serialport, which can read data from any serial port available on the Raspberry PI. Beware that no other process must be using the serial port when Node-Red starts, otherwise it will not be available to Node-Red. It also installs node-emoncms, which easily handles sending data to EmonCMS using its ReST API.

Finally, it installs node-time, which has no graphical presence in Node-Red, but can be used to perform operations depending on correct time zones in the function nodes in Node-Red. In order to use this node properly Node-Red must be configured to load it at start up. To do so, edit the configuration file /usr/local/lib/node-modules/node-red/settings.js and add the following lines to the list of available plugins towards the bottom of the file:

    functionGlobalContext: {
        time:require('time')
    },

Now, the time module is available through the global object context.global.time – see the documentation for its use.

Starting Node-Red automatically on boot

The basic installation of Node-Red does not include a startup script, so you will have to set one up yourself. Fortunately bigmonkeyboy has had the same need and have made a Node-Red startup script ready and up for grabs. Install it by executing the following commands at a console:

rpi-rw
sudo wget -O /tmp/download https://gist.github.com/bigmonkeyboy/9962293/download && sudo unzip -j -d /etc/init.d/ /tmp/download && sudo rm /etc/init.d/README.md && sudo chmod 755 /etc/init.d/nodered && sudo update-rc.d nodered defaults

Now Node-Red will be started automatically on boot and you can use the service command to manage it, e.g.:

sudo service nodered restart

Opening up the firewall

By default Node-Red will listen on port 1880, but this port is not accessible through the local firewall until it has been opened up. Do this by executing the following command:

sudo ufw allow 1880

Now you should be able to access Node-Red by pointing your browser to http://<RPI_IP_ADDRESS>:1880 and start making flows (although, see the conclusion for an important catch).

Disabling EmonHub

It might sound odd to disable EmonHub on a system based on it, but this is because EmonHub actually is the broker between RFM12/69PI (well, actually the serial port on the Raspberry PI) and EmonBase, which is the local data store used by EmonCMS. Thus, the EmonHub process must be disabled for the serial port to be available for Node-Red.

By default EmonHub is configured to start automatically on boot, which must be disabled by executing the following command:

sudo update-rc.d -f emonhub remove

Install Mosquitto MQTT broker

While not strictly required for running Node-Red on the Raspberry PI, if you just forward data to EmonCMS using its ReST API, it can be a good idea to install an MQTT broker to be able to receive and send MQTT messages.

Mosquitto is the preferred MQTT broker for the Raspberry PI and can be easily installed and configured using the default package manager.

On EmonHub of May 27. 2015 and later Mosquitto is already installed by default, except for the python-mosquitto package and its dependencies, so these instructions are not strictly necessary to use Mosquitto with newer releases of EmonHub.

The first step is to add the Mosquitto repository to the package manager:

cd ~
wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
sudo apt-key add mosquitto-repo.gpg.key
rm mosquitto-repo.gpg.key 
cd /etc/apt/sources.list.d/
sudo curl -O http://repo.mosquitto.org/debian/mosquitto-wheezy.list
sudo apt-get update

Next step is to install Mosquitto using the package manager:

sudo apt-get install mosquitto mosquitto-clients python-mosquitto

Mosquitto uses a configuration file which – rather unfortunately – is not part of the default installation. Thus we need to provide the entire configuration file. Copy the content of the basic configuration file, provided by @mqttand, to /etc/mosquitto/mosquitto.conf and set the following properties in it:

pid_file /var/run/mosquitto.pid
user pi
autosave_interval 1800
autosave_on_changes true

The above changes to the configuration file saves the .pid file to writable space, tells Mosquitto to run as the pi user and auto saves every hour and whenever there is a change.

To test the Mosquitto installation, run the following command in one terminal

mosquitto_sub -h localhost -v -t test

and the following in another terminal:

mosquitto_pub -h localhost -t test -m 'hello world'

Going back to the first terminal, it should now print:

test hello world

Configuring the serialport node

To configure the serialport node to read messages from the RFM12PI or RFM96PI set its properties to the following values:

Serial port
/dev/ttyAMA0
Baud rate
9600
Data bits
7
Parity
None
Stop bits
1
Split input on the character
\r
Deliver
ASCII string
Add split character to output message
True

Import below into Node-Red’s to get a preconfigured serial node:

[{"id":"f852c411.07ad38", "type":"serial-port", "serialport":"/dev/ttyAMA0", "serialbaud":"9600", "databits":"7", "parity":"none", "stopbits":"1", "newline":"\\r", "bin":"false", "out":"char", "addchar":true}, {"id":"1ff50be3.e00af4", "type":"serial in", "name":"RFM12PI", "serial":"f852c411.07ad38", "x":97, "y":80, "z":"2c395a29.d3c6a6", "wires":[["1ae56e8f.e51a91", "38cc98ce.c73368"]]}]

Parsing data from the serial port

Once the seiralport node has been configured, Node-Red can receive data from the serial port, or rather the RFM12/69PI. This data comes in pairs of bytes and is not readily usable for any subsequent flow, although it can somewhat easily be transformed into something usable represented in JSON. This can be done by flowing the output of the serialport node to a function node, which runs the following code:

msg.payload = msg.payload.trim();
 
var tokens = msg.payload.split(" ", 66);
var outString;
var outTopic;
var msg2 = null;
var nodeId = tokens.shift();
 
if (!isNaN(nodeId))
{
    nodeId = nodeId & 0x1F;
    var raw = tokens;
    var buf = new Buffer(raw);
    outString = {
        nodeId: nodeId,
        values: {}
    };
 
    var i = 0;
    var cnt = 1;
    for (; i <= (tokens.length - 2); i += 2)
    {
        outString.values[cnt] = buf.readInt16LE(i);
        cnt++;
    }
 
    msg2 = {payload:outString};
}
 
return msg2;

Import below into Node-Red to get a preconfigured function node:

[{"id":"38cc98ce.c73368", "type":"function", "name":"Parse raw RFM12", "func":"msg.payload = msg.payload.trim();\n\nvar tokens = msg.payload.split(\" \", 66);\nvar outString;\nvar outTopic;\nvar msg2 = null;\nvar nodeId = tokens.shift();\n\nif (!isNaN(nodeId))\n{\n    nodeId = nodeId & 0x1F;\n    var raw = tokens;\n    var buf = new Buffer(raw);\n    outString = {\n        nodeId: nodeId,\n        values: {}\n    };\n\n    var i = 0;\n    var cnt = 1;\n    for (; i <= (tokens.length - 2); i += 2)\n    {\n        outString.values[cnt] = buf.readInt16LE(i);\n        cnt++;\n    }\n    \n    msg2 = {payload:outString};\n}\n\nreturn msg2;\n", "outputs":1, "noerr":0, "x":288.5, "y":136.5, "z":"2c395a29.d3c6a6", "wires":[["495109d4.b6aef8"]]}]

This results in an output consisting of a JSON object containing the node ID and the received data. The data part is basically a JSON representation of a dictionary with a one-based index as key and the received serial value as value, in the order read from the serial port.

Conclusion

Now you have a basic installation of Node-Red on your Raspberry PI and can easily manage complex flows that acts on the serial data received by the RPI using the graphical flow editor.

Unfortunately, there is a downside of running Node-Red on a low-write Linux distribution, such as EmonHub: You have to write-enable the file system to deploy your flows. E.g. if you go to your local Node-Red (http://<RPI_ADDRESS>:1880), make a flow and try to publish it, you will get a message telling you that the file system is read only.

Fortunately Node-Red is running through a separate interface (a web browser), so  nothing is lost and you can readily go to a terminal on the Raspberry PI and make the file system temporarily writable by issuing the, now well known, command

rpi-rw

Remember to write protect the file system again after editing, otherwise log files will probably eat away your free space and wear the SD-card:

rpi-ro

 

4 comments on “Installing Node-Red as an intermediate layer between RFM interface and EmonCMSAdd yours →

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: