Generate a time Weighted Average plus Max and Min for user defined period

Uses a Function node to calculate a moving time Weighted average plus Max and Min for a period defined by msg.filterTime (default 60 seconds) in seconds. Output sent every time an input value is sent to function node (and msg.filterTime is Not defined).

Input msg.payload needs to be a number to allow it to be included in average and max and min otherwise output msg will be same as input.

Outputs the results in msg.payload (average) msg.result.average msg.result.max msg.result.min

[{"id":"e6850585a0c8395b","type":"inject","z":"7d0cd726e27a659a","name":"Set Filter time","props":[{"p":"filterTime","v":"300","vt":"num"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","x":900,"y":100,"wires":[["41337e2a1c963412"]]},{"id":"41337e2a1c963412","type":"function","z":"7d0cd726e27a659a","name":"function 3","func":"// determines the time weighted average, max and min of all payload values passed in\n// over the specified time range passed to node by msg.filterTime in seconds\n// developed from Code posted by Colin to Node_red Forum \n//     https://discourse.nodered.org/t/nodes-suggestion-for-timed-rolling-average-and-desynchronised-sum/4933/26 by Colin\n\nif (typeof msg.filterTime == 'number') {\n    context.set('filterTime', msg.filterTime);\n    node.warn(`Filter Time set to: ${msg.filterTime} seconds`);\n    msg = null;\n} else if (typeof msg.payload == 'number') {\n    let filterTime = context.get('filterTime') || 60 // in seconds\n    const range = filterTime * 1000; // window time millisecs\n    let buffer = context.get('buffer') || [];\n    let now = new Date();\n    let lastTimestamp = context.get(\"lastTimestamp\") || now;\n    let value = Number(msg.payload);\n    // remove any samples that are too old\n    // @ts-ignore\n    while (buffer[0] && buffer[0].timestamp < now - range) {\n        // remove oldest sample from array and total\n        //node.warn(`removing oldest ${buffer[0].timestamp}`);\n        lastTimestamp = buffer[0].timestamp;\n        buffer.shift();\n    }\n    context.set('lastTimestamp', lastTimestamp);\n\n    // add the new sample to the end\n    buffer.push({\n        timestamp: now,\n        value: value\n    });\n    // @ts-ignore\n    let duration = (now - lastTimestamp); // difference between latest sample and oldest\n    // now calculate Average, max and min\n    let max = value;\n    let min = value;\n    let ave = 0;\n    for (var i in buffer) {\n        max = Math.max(max, buffer[i].value);\n        min = Math.min(min, buffer[i].value);\n        ave += buffer[i].value * (buffer[i].timestamp - lastTimestamp);\n        lastTimestamp = buffer[i].timestamp;\n    }\n    ave = ave / duration;\n\n    context.set('buffer', buffer);\n    //context.set('total', total);\n    msg.payload = ave;\n    msg.result = {\n        average: ave,\n        max: max,\n        min: min\n    };\n    node.status({ text: `${buffer.length}` });\n    //node.warn(`length: ${buffer.length}, average: ${ave}, min: ${min}, max: ${max} over ${duration/1000} seconds`);\n\n};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1060,"y":140,"wires":[["36a47a8a4813ad47","05b49c564a8dd3a1"]]}]

Flow Info

Created 8 months, 2 weeks ago
Rating: not yet rated

Owner

Actions

Rate:

Node Types

Core
  • function (x1)
  • inject (x1)

Tags

Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option