Node-RED: Lecture 6 – Example 6.3 Using context to generate rolling averages

A special module called context, used to store data between function invocations, is available to function nodes. This can be useful when the function needs to retain state to do its processing. For example, in a typical Industrial IoT scenario, it may be necessary to compute the average value of a sensor’s data readings over a period of time. Listing 6.4 computes a rolling average of the values received over the last 5 seconds, adding the ‘average’ field to the payload when more than 5 seconds have elapsed between received messages.

Listing 6.4 Rolling average function using context

  1. var currentTime = new Date().getTime();
  2. if (!context.lastTime) {
  3.     context.lastTime = currentTime;
  4.     context.sum = msg.payload.value;
  5.     context.count = 1;
  6. }
  7. if (currentTime-context.lastTime > 5000) {
  8.     // calculate average for previous messages
  9.     msg.payload.average = context.sum/context.count;
  10.     // start tracking average again
  11.     context.sum = msg.payload.value;
  12.     context.count = 1;
  13.     context.lastTime = currentTime;
  14. } else {
  15.     context.sum += msg.payload.value;
  16.     context.count +=1;
  17. }
  18. return msg;

Looking at listing 6.4, you first get the current time (line 1).  If there is no lastTime stored in context, you then save the currentTime, reset the sum and count context variables (lines 3-7).

If the currentTime is 5 seconds (5000 milliseconds)  greater than the last time (line 9), you calculate the average of the last values received and include that with the message payload (lines 11-13).  You then reset the sum, count and set lastTime to the currentTime to begin counting and summing up again.

If 5 seconds haven’t elapsed since the last message was received, the counts and sums need to be updated (lines 16-19). You then output the message which includes the latest value and the average if it was calculated for the interval (line 20).

To test this, let’s write another function node, that you’ll call ramp and that also uses context to generate values from 0 to 9 in sequence, as shown in Listing 6.5.

Listing 6.5 Test function to generate sequence of values using context

  1. if (!context.value) {
  2.   context.value = 0;
  3. }
  4. msg.payload = {
  5.   value:context.value
  6. }
  7. context.value +=1;
  8. if (context.value > 9) {
  9.   context.value = 0;
  10. }
  11. return msg;

Let’s configure an inject node to send data every second, as shown in Figure 6.10.

Figure 6.10 Inject node configured to inject a blank payload every second.

Then wire these up as shown in Figure 6.11.

Figure 6.11 Test flow for rolling average function.

The output should look like the one in Figure 6.12.

Figure 6.12 Debug console output showing rolling average.

BACK to main Lecture 6

PREVIOUS example           NEXT Example

Author: Rodger Lea

Currently CEO of Internet of Things startup, Sense Tecnic, Dr. Lea has over 25 years experience spanning academic, large corporations and startups. For the last 10 years, he has started or helped start 4 new companies while managing an active research program (University of British Columbia, Canada and Lancaster University, UK) into distributed and ubiquitous computing, the IoT and Smart Cities.