Node-Red – Digispark RGB Node

Following on from last weekends post about adding a pause node to Node-Red this weekend I’ve been trying to create a node to support my Digispark RGB USB LED.

The RGB shield for the Digispark came with a sketch and a some python code to send colours to the device using the HID protocol. I had a bit of a poke round and I found node-hid and thought things where going to be easy.

Unfortunately just trying to duplicate the python code in nodejs didn’t seam to work no matter what I tried.

After a bit more digging I found this blog post by Dougal Campbell who looked to have been pursuing a similar idea a little earlier in the year. I couldn’t see any follow up post on his blog but a quick comment later and I had pointers to what he’d managed to get working. I was hoping to leave the default sketch on the digiSpark but it needed a little change to the USB library to make things work properly, you can find the changes here.

88-digiRGB.js


// Require main module
var RED = require("../../red/red");
var HID = require('node-hid');
var device;
var node;

// The main node definition - most things happen in here
function DigiRGBNode(n) {
    // Create a RED node
    RED.nodes.createNode(this,n);
    node=this;
    //look up the matching devices
    var devices = HID.devices(0x16c0,0x05df);
    for (var i=0; i< devices.length; i++) {
      if (devices[i].product == 'DigiUSB') {
        path = devices[i].path;
        node.log("found: " + path);
        try {
          device = new HID.HID(devices[i].path);
          //only work with the first one found
          break;
        } catch (e) {
          node.log(e)
        }
      }  
   }
   
   if (device) {   
      this.on("input", function(msg) {
        if (msg != null) {
          var args = msg.payload.split(',');
          if (args.length == 3) {
            device.sendFeatureReport([115,parseInt(args[0]),parseInt(args[1]),parseInt(args[2])]);
          }
        }
      });
   } else {
      node.warn("no digispark RGB found");
   }
   
}

// Register the node by name. This must be called before overriding any of the
// Node functions.
RED.nodes.registerType("digiRGB",DigiRGBNode);


DigiRGBNode.prototype.close = function() {
    // Called when the node is shutdown - eg on redeploy.
    // Allows ports to be closed, connections dropped etc.
    // eg: this.client.disconnect();
    device.close();
}

If you want to have a play unzip 78-digiRGB.zip in the node-red directory to unpack the whole node into the nodes/hardware directory. I have now saved this a Github GIST which you can check out directly into /node-red/nodes/hardware directory as follows:

[user@node node-red]$ git clone https://gist.github.com/6573158.git

You will also need to run npm import node-hid in the node-red directory to add the dependency.

(Remember you will need to modify the DigiUSB.cpp and the usbconfig.h in the DigisparkUSB example as mentioned in the link above).

This is unlikely to make it into core Node-RED as the hardware is a little specialist, but if Nick and Dave decide to host a collection of hardware nodes it may end up in there.

Node-Red – Pause Node

Two guys from my team (Nick O’Leary and Dave Conway-Jones) at IBM released a very cool tool for wiring up IoT last week called Node-Red.

Node-Red lets you wire together a selection of inputs, things like MQTT messages, Twitter feeds, serial port and a whole lot more, perform transforms on them with Javascript functions before outputting them to a similar collection of options.

I’ve been playing with it to replace a couple things that used to be standalone scripts, but one of the things that was missing was the way to delay an action happening until a certain time after a message has arrived. For example if I want to set my Blink(1) clone to green when somebody mentions me in the tweet I may want to reset it to off 20 seconds later

To help with this I have written a new node called pause that delays passing on a given message by a configurable amount of time. Nodes are made up of 2 files and are placed in the node-red/nodes directory. As well as all the built in nodes there is a example node (99-sample) which you can use to

Each node is made up of 2 parts, the first is javascript file which controls how the node should behave and a html file which contains the descriptive text,

99-pause.js

...
// Simple node to introduce a pause into a flow

//Require main module
var RED = require("../red/red");

function PauseNode(n) {
   RED.nodes.createNode(this,n);
   
   this.timeout = n.timeout * 1000;
   
   this.on("input", function(msg) {
       var node= this;
       setTimeout(function(){node.send(msg);}, node.timeout);
   });
}

RED.nodes.registerType("pause",PauseNode);

You can see in the code above I’ve attached a small function to the ‘input’ event for the pause node, all it does setup a callback after the timeout expires to send the passed in message object to the next node in the flow.

99-pause.html

...
<!-- First, the content of the edit dialog is defined.                       -->
<script type="text/x-red" data-template-name="pause">
  <div class="form-row">
     <label for="node-input-topic"><i class="icon-tasks"></i> Pause</label>
    <input type="text" id="node-input-timeout" placeholder="Time">
  </div>
    
  <div class="form-row">
    <label for="node-input-name"><i class="icon-tag"></i> Name</label>
    <input type="text" id="node-input-name" placeholder="Name">
  </div>
</script>

<!-- Next, some simple help text is provided for the node.                   -->
<script type="text/x-red" data-help-name="pause">
    <p>Introduces a pause into a flow</p>
    <p>Default pause is 5 seconds but can be configured</p>
</script>

<!-- Finally, the node type is registered along with all of its properties   -->
<script type="text/javascript">
    RED.nodes.registerType('pause',{
        category: 'function',      // the palette category
        color:"#E6E0F8",
        defaults: {             // defines the editable properties of the node
            name: {value:""},   //  along with default values.
            timeout: {value:"5", required:true, validate:RED.validators.number()}
        },
        inputs:1,                // set the number of inputs - only 0 or 1
        outputs:1,               // set the number of outputs - 0 to n
        icon: "arrow-in.png",    // set the icon (held in public/icons)
        label: function() {      // sets the default label contents
            return this.name||this.topic||"pause";
        },
        labelStyle: function() { // sets the class to apply to the label
            return this.name?"node_label_italic":"";
        }
    });
</script>

The HTML sets up configuration dialog for the node, the help text, the nodes look and behaviour and the default values for any properties the node has.

The configuration dialog for the pause node looks like this:

I’ve checked this new node into my fork of the Node-Red project here, but I’ll be submitting a pull request to get it included in the main project as soon as I get a chance to have a chat with Nick and Dave.

EDIT:
This is now a core node called delay and is also capable of rate limiting messages