Creating a FIFO buffer with NodeRed to allow recent messages to be replayed.

Background

Nodered Buffer Flow}

I have a NodeRed instance running on a RaspberryPi to handle some of my home automation projects. One of the systems is an LED Matrix display that reports (among other things) the time, weather information, and information about the house. Occasionally, I notice a message just as it disappears and wish that I could play it back again. This is a method to do that.

This article assumes some familiarity with NodeRed, so I won’t go into the details of all the steps about how to set this up – just the code that I used to create the cyclical buffer.

Algorithm

    * Create a FIFO buffer for the last three messages that were published to the display * Allow recall of the messages when a button is pressed.

Coding

The flow relies on the context variable in NodeRed. This is valid since at least 0.10, and may have changed in later versions (I’m running 0.10, I think). Messages that need to be recalled are sent to the /buffer topic, and the last three are available in a cyclical fashion. If you want to send a message that’s not buffered, you can simple post to /message – this is useful to post the time or other information that’s not particularly valuable if it’s been recalled.

//There are 3 messages buffered. When a new one arrives, cycle the previous ones down the queue, and add the new one to the top.

var count = context.count || 0;

if (msg.payload == 'button'){
    //Do something to handle the button press.
    rotate();
    msg.payload = context.buffer[0];
} else {
    rotate();
    context.buffer[0]=msg.payload;
}
//node.warn(context.buffer);
return msg;

function rotate() {
    //This should rotate the buffer by one, nothing's deleted.
    var buffer = context.buffer || [0, 1,2];
    var myBuffer = buffer[0]; //Store the first value to prevent overwriting.
    for (i = 0; i < buffer.length-1; i++) //Loop through remainder, and iterate the values up one. It's -2 because the list is 0-indexed, and we want to stop one early so that the last one can be filled with the first one...
    {
      buffer[i]=buffer[i+1];    
    }
    buffer[buffer.length-1]=myBuffer;
    //node.warn(buffer);
    context.buffer = buffer; //Write the data back to the context for 'persistance'
}