IoT framework: Using NodeRed.

In my previous post we’ve installed and configured a MQTT broker and a web based dashboard to see our data in realtime.The real time MQTT data is viewed through the MQTT protocol over websockets from our browser using the freeboard dashboard. This configuration means that in reality our browser is now a MQTT client.

But I also talked about installing Nodered, but ended up not referring it again on the post in how to use it and why the reason that it belongs to this IoT framework. Well, mainly because the post was already too long, but another reason is that Nodered is not directly related with presenting data but consume it, processing it, store it and communicating with other systems/platforms. Nodered might be the central point to orchestrate our devices, systems and platforms. Also Nodered can provide native websocket protocol, if we can named it that, and not MQTT over websockets (that needs an enabled broker with MQTT over WS), allowing us to bridge MQTT over native websockets if we do not have a native MQTT websocket enabled broker.

Expanding dashboard to consume websockets:

Before getting into Nodered, let’s expand our dashboard to consume native websockets. This is needed because on the previous post we configured it to consume MQTT over websockets, and now we need native websockets protocol. We are installing our IoT server on a directory named IoTServer on our home directory.

cd ~/IoTServer
git clone

We need to copy now the two support files from these freeboard plugins to the plugins directory:

cd ~/IoTServer/freeboard/plugins
cp ~/IoTServer/plugins/datasources/plugin_node.js .
cp ~/IoTServer/plugins/datasources/plugin_json_ws.js .

Now we need to change the index.html file to enable the two new plugins like this:

// *** Load more plugins here ***

And that’s it. We can now consume/display native websocket data on the freeboard dashboard using the ws:// URI.

Before we do anything with this, namely configure a dashboard widget to consume data from a Nodered websocket, we will just set up this little project, to make some sense from this:

We receive the current temperature value from a device over MQTT. From time to time, the device publishes the current temperature onto the MQTT /temperature topic.
We will use Nodered to receive the published data, and to store it onto a MySQL table. At that time Nodered will compute the mean value for all the received temperatures and publish that on a websocket. Simple, right?

For testing purposes I’m using Mosquitto 1.4 with websockets enabled, and I’m publishing data, on the same machine where the broker is running with the command: mosquitto_pub -t /temperature -m 20

So the code for Node-red is the following (to see it, just launch the Node-red web interface, and select Import from Clipboard, and paste the bellow code):

[{"id":"db4020c1.3b133","type":"websocket-listener","path":"/ws/data/meantemp","wholemsg":"false"},{"id":"39c70e78.3a446a","type":"mqtt-broker","broker":"localhost","port":"1883","clientid":"NodeRed"},{"id":"2319ac20.bdda04","type":"MySQLdatabase","host":"","port":"3306","db":"nodered","tz":""},{"id":"5c60ad12.fd3c54","type":"mysql","mydb":"2319ac20.bdda04","name":"Query BD","x":524,"y":447,"z":"78c46bf9.04906c","wires":[["24e2e587.55d6b2"]]},{"id":"a7132398.e6dd38","type":"inject","name":"","topic":"select * from DataTable","payload":"","payloadType":"string","repeat":"","crontab":"","once":false,"x":284,"y":447,"z":"78c46bf9.04906c","wires":[["5c60ad12.fd3c54"]]},{"id":"24e2e587.55d6b2","type":"debug","name":"","active":true,"console":"false","complete":"false","x":759,"y":447,"z":"78c46bf9.04906c","wires":[]},{"id":"5e11fbbf.b94c04","type":"mqtt in","name":"Receive MQTT Temperature","topic":"/temperature","broker":"39c70e78.3a446a","x":226,"y":271,"z":"78c46bf9.04906c","wires":[["38bbe4cd.bc04e4","e91f382a.016928"]]},{"id":"9817c3a7.d2627","type":"mysql","mydb":"2319ac20.bdda04","name":"Store Temperature","x":757,"y":274,"z":"78c46bf9.04906c","wires":[[]]},{"id":"38bbe4cd.bc04e4","type":"function","name":"Build MySql Query","func":"var sdata = new Date().toISOString();\nvar query = \"Insert into DataTable values ( '\" + sdata + \"','temp',\" + msg.payload + \");\"\nmsg.topic = query;\nmsg.payload = {};\nreturn msg;","outputs":1,"x":508,"y":272,"z":"78c46bf9.04906c","wires":[["9817c3a7.d2627"]]},{"id":"e91f382a.016928","type":"function","name":"Calc Mean Temp","func":"var query = \"SELECT avg(t1.value) as median_val FROM (SELECT @rownum:=@rownum+1 as `row_number`, d.value FROM DataTable d, (SELECT @rownum:=0) r WHERE 1 ORDER BY d.value ) as t1, ( SELECT count(*) as total_rows FROM DataTable d WHERE 1 ) as t2 WHERE 1 AND t1.row_number in ( floor((total_rows+1)/2), floor((total_rows+2)/2) ); \";\nmsg.topic = query;\nreturn msg;","outputs":1,"x":499,"y":117,"z":"78c46bf9.04906c","wires":[["5438e8f2.12939"]]},{"id":"5438e8f2.12939","type":"mysql","mydb":"2319ac20.bdda04","name":"Get and Calc mean temp","x":757,"y":116,"z":"78c46bf9.04906c","wires":[["a3ca0282.6a518"]]},{"id":"21e6d8fe.7ab568","type":"websocket out","name":"WebSocket: Mean Temp","server":"db4020c1.3b133","client":"","x":1209,"y":116,"z":"78c46bf9.04906c","wires":[]},{"id":"a3ca0282.6a518","type":"function","name":"Extract mean","func":"var meanval = msg.payload[0];\nmsg.payload = meanval.median_val;\nreturn msg;","outputs":1,"x":987,"y":116,"z":"78c46bf9.04906c","wires":[["21e6d8fe.7ab568"]]}]

For watching the mean temperature value that is published on the websocket we will use the new freeboard plugins installed previously:

1st – Add a data source:

Goto your freeboard dashboard, select Add on the Datasources, and select the JSON Websocket Push Datasource. Give it a name, and then the URL.

VERY IMPORTANT: because this is a websocket URL the websocket has the ws:// prefix and NOT http://.

In our case the url for node red is: ws://node-red:1880/ws/data/meantemp

2nd – Add a widget: And now we can add a widget based on the above data source.

That’s it. We can consume now data from websockets from Node-red and MQTT websockets from Mosquitto/Mosca MQTT broker.

14 thoughts on “IoT framework: Using NodeRed.

    1. Forget it, I think this one is working:
      `date` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
      `temp` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
      `value` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL

      I must have a problem in the websockets part.

      1. Hi:

        I’m using this structure:

        mysql> desc DataTable;
        | Field | Type | Null | Key | Default | Extra |
        | logdate | datetime | YES | | NULL | |
        | field | varchar(64) | YES | | NULL | |
        | value | bigint(20) | YES | | NULL | |
        3 rows in set (0.24 sec)

        A bit different than yours.

  1. Thanks for the reply. I’ve been testing it deployment, some problems arise when it comes to the Websockets node. I have websockets running, since I tested your previous post ( and works.

    What’s exactly the purpose of the ‘WebSocket: Mean Temp’? I don’t quite understand how it gets connected to the Freeboard.

    Any hint will be much appreciated 🙂

    1. Hi. If I want to get a plain and simple value that is posted on a MQTT topic, I just can use the MQTT over websockets and talk directly to the MQTT broker.
      The Mean Temp is a calculated value that needs some logic to be executed. So it’s not MQTT. In this case I used the example to just show how a MQTT topic update triggers a Nodered calculation, involving writing to a database and publishing into a plain websocket that changes a widget.
      In reality it could be anything the calculated value, I’ve just choose to calculate the medium temperature of all record temperatures inserted into the database.

      1. Sure, I got that point.

        The part which is obscure to me is the configuration of the websocket node (the one most to the right in the node-red deployment). I’m having troubles to correctly receive that plain value in the freeboard side.

  2. On the nodered side, the websocket node, the simplest configuration, just like is used in this post flow, defines the base url for the websocket.
    So if the base url is something like /ws/data/meantemp, then on the freeboard side the correct url to be used on the Websocket datasource should be: ws://nodered_address:port/ws/data/meantemp
    There isn’t much else to configure. One thing that I notice, is that you might have to delete the datasource and create it again correctly if need to change something.

    1. I’ve add an additional “websocket input node” wired to a “debug node” in order to test the deployment, and it works.

      [{“id”:”decd0b05.2132f8″,”type”:”websocket-client”,”path”:”ws://my.own.ip:1880/ws/data/meantemp”,”wholemsg”:”false”},{“id”:”48a14304.b75ebc”,”type”:”debug”,”name”:””,”active”:true,”console”:”false”,”complete”:”false”,”x”:542.5,”y”:177,”z”:”f14b804a.0eb48″,”wires”:[]},{“id”:”7d900502.826ffc”,”type”:”websocket in”,”name”:””,”server”:””,”client”:”decd0b05.2132f8″,”x”:195.5,”y”:177,”z”:”f14b804a.0eb48″,”wires”:[[“48a14304.b75ebc”]]}]

      However, Freeboard is not receiving anything. Do you know how could I debug that? Some logs to review?

      1. Are you running freeboard and nodered in the same machine?
        Is nodered listening in the loopback address or do configured it to listen in a network address?

  3. Hello, I’m running both on the same machine. Finally I got it working, it was just a matter of establishing the correct URLs and in addition to make what you mentioned before:

    That solve it.

    Thanks for your patient but also for sharing this post with the community

    1. […] what you mentioned before:
      ** is that you might have to delete the datasource and create it again correctly if need to change something. **

    2. Glad it worked! 🙂

      I’ve hit some issues with freeboard, and one of them was that to change something on the datasource it is better to delete it and re-create it again.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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