0
votes

In my current project, we are trying to develop a simple application "Notify me when my room temperature goes beyond the certain limit". The flow diagram of this application as follow: enter image description here

Here, temperature sensor is producing temperature data periodically and the sensed data is send to the CalculateAvgTemp component. The CalculateAvgTemp component waits for 5 samples and then pass the calculated value to the DisplayTempController. The code of CalculateAvgTemp component, written in node.js is as follows.

var mqtt=require('mqtt');
var client=mqtt.connect('mqtt://test.mosquitto.org:1883');
var NUM_SAMPLE_FOR_AVG=5;
var numSample=0;
var tempCelcius=0;
var currentAvg=0;
client.subscribe('sensorMeasurement');
client.on('message',function(topic,payload){

sensorMeasurement=JSON.parse(payload);
console.log(sensorMeasurement);

if(numSample <= NUM_SAMPLE_FOR_AVG){
     numSample = numSample + 1;

    if(sensorMeasurement.unitofMeasurement=='F'){
        tempCelcius=((sensorMeasurement.tempValue-32)*(5/9));       
    }
    else{
        tempCelcius=sensorMeasurement.tempValue;

    }       

    currentAvg=parseFloat(currentAvg)+parseFloat(tempCelcius);

    if(numSample==NUM_SAMPLE_FOR_AVG){
        //console.log(currentAvg);
        currentAvg=currentAvg/NUM_SAMPLE_FOR_AVG;
        var avgTemp={"avgTemp":parseFloat(currentAvg),"unitofMeasurement":sensorMeasurement.unitofMeasurement};
        client.publish('roomAvgTemp',JSON.stringify(avgTemp));
         numSample =0;
         currentAvg=0;
    }
}       

});

We are trying to implement the calculateAvgTemp component in Node-RED. Node-RED provide function node that allows developers to write custom function. Now, the real problem starts here --- Node-RED custom function does not implement the calculateAvgTemp functionality correctly. It does not wait for 5 temperature values and fires whenever the temperature arrives. My question is that - Is this Node-RED limitation OR should we implement the calcuateAvgTemp functionality differently in Node-RED, if yes then - how can we implement the functionality in Node-RED? The code of CalculateAvgTempwritten in Node-RED is as follows:

context.temps = context.temps || [];
sensorMeasurement=JSON.parse(msg.payload);
var tempValue=parseFloat(sensorMeasurement.tempValue);
context.temps.push(tempValue);
if (context.temps.length > 4) {
if (context.temps.length == 6) {
//throw last value away
context.temps.shift();
}
var avg=0;
for (var i=0; i<=context.temps.length; i++) {
avg += context.temps[i];
}
avg = avg/5;
msg.payload = parseFloat(avg);
return msg;
} else {
return null;
}
2

2 Answers

2
votes

A function node does not need to pass anything on, if it doesn't return (or returns null) then the flow will stop at that point.

You can also store state in a function node using the context variable. This means you could store the last 5 values passed in and only return something once you have all 5 to compute the average.

Something like:

context.temps = context.temps || [];
context.temps.push(msg.payload);
if (context.temps.length > 4) {
  if (context.temps.length == 6) {
    //throw last value away
    context.temps.shift();
  }
  var avg=0;
  for (var i=0; i<context.temps.length; i++) {
    avg += context.temps[i];
  }
  avg = avg/5;
  msg.payload = avg;
  return msg;
} else {
  return null;
}
0
votes

@hardillb---- Many Many Thank for pointer. Following is the solution

context.temps = context.temps || [];
data=JSON.parse(msg.payload);
context.temps.push(data.tempValue);
 var NO_OF_SAMPLE=5;
if (context.temps.length > 4) {
 var avg=0.0;
 for (var i=0; i<NO_OF_SAMPLE; i++) {
 avg =parseFloat(avg)+parseFloat(context.temps[i]);
  }
  avg =avg/NO_OF_SAMPLE;
  msg.payload = avg;
  context.temps=[];
  return msg;
  } else {
   return null;
  }