Skip to content

Instantly share code, notes, and snippets.

@dceejay
Last active January 26, 2021 14:32
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save dceejay/fb47301b759222e05f84 to your computer and use it in GitHub Desktop.
Save dceejay/fb47301b759222e05f84 to your computer and use it in GitHub Desktop.
Node-RED and Freeboard

How to use the Freeboard dashboard with Node-RED

Freeboard is a great looking html/javascript dashboard from Bug Labs Inc. Normally hosted online at freeboard.io, the client is available on Github under a MIT license. It makes for a great configurable dashboard for use with Node-RED.

Preparation

First you need to configure Node-RED to serve static web pages. This means moving the default editor pages away from the default root /. To do this edit the settings.js file. Find and edit the following properties within the file to suit yourself.

 httpStatic: '/home/{your_user}/web/',

 httpRoot: '/admin',

When you next start Node-RED this will mean that

 http://localhost:1880/    will serve pages from within the web directory
 http://localhost:1880/admin/  will serve the Node-RED flow editor

The following example assumes you have configured Node-RED in this way.

Getting Started

Git clone the freeboard client into the new web directory

cd web
git clone https://github.com/Freeboard/freeboard.git
cd freeboard

Download the wsDataSourcePlugin.js file from this gist into the freeboard/examples directory. This adds a new WebSocket datasource which we will use later...

Now edit a few of the files...

index.html

change line 
    "examples/plugin_example.js",
to be
    "examples/wsDataSourcePlugin.js",

js/freeboard/freeboard.js

at line 2181
    if(freeboardLocation != "")
        {
            $.ajax({

insert two lines to make it
    if(freeboardLocation != "")
        {
            theFreeboardModel.allow_edit(allowEdit); // respect the allowEdit flag
            theFreeboardModel.setEditing(false); // but always start with editor shut.
            $.ajax({

css/styles.css

find and tweak (line 1909) to increase the height (much more useable)
    ul.value-dropdown
    {
        height     : 200px;

You should now be able to start Node-RED and browse to http://localhost:1880/freeboard

Using Freeboard

Note : Currently this MUST be done using the Chrome browser... (there is an outstanding issue on the project to fix saving with Firefox)

First let's add a simple flow to Node-RED... cut and import this in the usual fashion. Don't forget to Deploy.

[{"id":"dc100c03.23eff","type":"websocket-listener","path":"/ws/count","wholemsg":"true"},{"id":"e035ff3b.1fca","type":"inject","name":"","topic":"counter","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"x":190,"y":900,"z":"c6a2f49a.395d08","wires":[["a7262d4c.58d9d"]]},{"id":"a7262d4c.58d9d","type":"function","name":"Count up/down","func":"context.count = context.count || 0;\nif (context.count <= 0) context.dir = 1;\nif (context.count >= 100) context.dir = -1;\ncontext.count += context.dir;\nmsg.payload = context.count;\nreturn msg;","outputs":1,"x":330,"y":900,"z":"c6a2f49a.395d08","wires":[["f8c8713e.07379","c7c66426.383998"]]},{"id":"f8c8713e.07379","type":"websocket out","name":"","server":"dc100c03.23eff","x":507,"y":900,"z":"c6a2f49a.395d08","wires":[]}]

This will provide a simple websocket output of a counter that counts up to 100 and back down again. Now switch back to the Freeboard dashboard editor page.

Adding a data feed

Within the Freeboard editor pane - click on Datasources - [ADD]

Select type - Web Socket - then enter a name you wish to call it (eg Counter) - then enter a uri, in this example:

ws://localhost:1880/admin/ws/count

and hit [SAVE]. Note that if you configured Node-RED differently you may need to change this path to suit your setup.

Adding a widget

Now you can +ADD PANE, and hit the + on the new pane that appears. Select type - TEXT - to start with.

Give it a title, then hit the +Datasource button. You should now see a dropdown containing Counter. Select Counter and you now see a further selection of topic, and payload. Select payload. The value box should now look like

datasources["Counter"].payload

Obviously this can be extended to point to any sub-property of whatever object you pass in... but for now just hit [SAVE]

You should now have a widget with a number counting as per the Node-RED flow output. Now go wild and try some of the other widgets...

Saving your Dashboard

Key tip - DO NOT refresh your browser page until you have saved your dashboard...

As this is supposed to be a hosted offering and we are just serving it statically you need to manually save the dashboard... and as previously noted - this currently ONLY works with the Chrome browser.

Click the SAVE FREEBOARD button - this will save a file dashboard.json in your default downloads location.

Restarting with your saved Dashboard

Copy / Move the dashboard.json file from wherever it got saved to the web/freeboard directory.

You can now browse directly to

http://localhost:1880/freeboard/index.html?load=dashboard.json

to open your dashboard directly.

// ## A Web Socket Datasource Plugin for the Freeboard Dashboard
(function() {
var wsDatasource = function(settings, updateCallback) {
var server = window.location.hostname;
var wsUri, ws;
var self = this;
var currentSettings = settings;
function wsStart(wsUri) {
ws = new WebSocket(wsUri);
ws.onopen = function(evt) {
console.log("ws : connected");
};
ws.onclose = function(evt) {
console.log("ws : disconnected");
setTimeout(function(){wsStart(wsUri)}, 3000); // try to reconnect every 3 secs...
}
ws.onmessage = function (evt) {
try {
var da = JSON.parse(evt.data);
updateCallback(da);
} catch (e) {
console.log("ws : bad parse",evt.data);
}
}
ws.onerror = function(evt) {
console.log("ws : error",evt);
}
}
this.updateNow = function() {
console.log("Update now");
}
this.onDispose = function() {
console.log("Disposed");
}
this.onSettingsChanged = function(newSettings) {
if (ws) ws.close();
currentSettings = newSettings;
wsUri = currentSettings.ws_uri;
wsStart(wsUri);
}
self.onSettingsChanged(settings);
};
freeboard.loadDatasourcePlugin({
type_name : "web_socket",
display_name: "Web Socket",
settings : [
{
name : "ws_uri",
display_name: "WS URI",
description : "Example: ws://server:port/path",
type : "text"
}
],
newInstance : function(settings, newInstanceCallback, updateCallback)
{
newInstanceCallback(new wsDatasource(settings, updateCallback));
}
});
}());
@philippe-gregoire
Copy link

Could it be conceivable that a NodeRED node would contribute to the UI side by generating (part of) dashboard.json?
Ideally, one would drop such a node from the palette, wire some data feed into it, select the type of dashboard widget from the node props, and this would automagically be served from the flow?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment