Calculate Differences
Node-RED Flow: Calculate Differences
This flow is designed to calculate the difference between consecutive numerical values along with the time elapsed between them.
Flow Overview
Inject Nodes
- Several inject nodes send predefined numerical values (0, 10, 20, 50, 100) into the flow to simulate data input.
- Each inject node triggers the flow manually when clicked.
Set Value Node (Function Node: "set val")
- Converts the incoming numerical value into an object:
{ "value": <input_value> } - Adds a timestamp (
msg.timestamp) representing the current time.
- Converts the incoming numerical value into an object:
RBE (Report-by-Exception) Node
- Ensures that only changes in the
payloadvalue are forwarded to the next stage, filtering out duplicate values.
- Ensures that only changes in the
Calculate Differences (Function Node)
- Computes the difference (
diffValue) between the current and previous values. - Computes the time difference (
diffTimestamp) between the current and previous timestamps. - Outputs an object with:
{ "diffValue": <difference>, "diffTimestamp": <time_difference>, "newValue": <current_value>, "newTimestamp": <current_timestamp>, "prevValue": <previous_value>, "prevTimestamp": <previous_timestamp> } - Stores the current value and timestamp in the node’s context for the next calculation.
- Computes the difference (
Debug Node ("Show Output")
- Displays the computed differences in the Node-RED debug pane.
Expected Output
- On each new value input, the flow calculates and outputs the difference from the previous value along with the time difference between updates.
- If it’s the first received value,
diffValueanddiffTimestampwill benull.
This flow can be useful for tracking sensor data changes, logging rate-of-change metrics, or monitoring process values over time.
[{"id":"1a0b1c8a.2d4b7b","type":"tab","label":"Calculate Differences","disabled":false,"info":""},{"id":"f9f14f0f.12cd28","type":"rbe","z":"1a0b1c8a.2d4b7b","name":"","func":"rbe","gap":"0","start":"false","inout":"out","septopics":true,"property":"payload","topi":"topic","x":430,"y":280,"wires":[["24c0b35d.46ea3a"]]},{"id":"24c0b35d.46ea3a","type":"function","z":"1a0b1c8a.2d4b7b","name":"Calculate Differences","func":"//[input]\n// msg.payload.value\n// msg.timestamp\n\nlet prevValue = context.get('prevValue');\nlet prevTimestamp = context.get('prevTimestamp');\n\nlet newValue = msg.payload.value;\nlet newTimestamp = new Date(msg.timestamp).getTime();\n\n\n\n// If we have a previous value/timestamp, calculate differences\nif (prevValue !== undefined && prevTimestamp !== undefined) {\n \n prevTimestamp = new Date(prevTimestamp).getTime();\n \n let diffValue = newValue - prevValue;\n let diffTimestamp = newTimestamp - prevTimestamp;\n \n msg.payload = {\n diffValue: diffValue,\n diffTimestamp: diffTimestamp,\n newValue: newValue,\n newTimestamp: newTimestamp,\n prevValue: prevValue,\n prevTimestamp: prevTimestamp\n };\n} else {\n // First run - no differences yet\n msg.payload = {\n diffValue: null,\n diffTimestamp: null,\n newValue: newValue,\n newTimestamp: newTimestamp,\n prevValue: null,\n prevTimestamp: null\n };\n}\n\ncontext.set(\"prevValue\",newValue);\ncontext.set(\"prevTimestamp\",newTimestamp);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":400,"wires":[["b0b3a6e9.d63c8"]]},{"id":"b0b3a6e9.d63c8","type":"debug","z":"1a0b1c8a.2d4b7b","name":"Show Output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":400,"wires":[]},{"id":"7ee6438287ad9016","type":"inject","z":"1a0b1c8a.2d4b7b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":150,"y":160,"wires":[["127d7b092805890b"]]},{"id":"127d7b092805890b","type":"function","z":"1a0b1c8a.2d4b7b","name":"set val","func":"msg.payload = {\n value: msg.payload, \n};\nmsg.timestamp = new Date();\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":200,"wires":[["f9f14f0f.12cd28","a5ab0fe5a8237ce8","90c06b57413a7042"]]},{"id":"43dc4671f3c9713a","type":"inject","z":"1a0b1c8a.2d4b7b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"20","payloadType":"num","x":150,"y":220,"wires":[["127d7b092805890b"]]},{"id":"4afdd1702bf1fba4","type":"inject","z":"1a0b1c8a.2d4b7b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"50","payloadType":"num","x":150,"y":280,"wires":[["127d7b092805890b"]]},{"id":"fa9fc23e09721b85","type":"inject","z":"1a0b1c8a.2d4b7b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"100","payloadType":"num","x":150,"y":340,"wires":[["127d7b092805890b"]]},{"id":"eb0ec244618a894a","type":"inject","z":"1a0b1c8a.2d4b7b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":150,"y":100,"wires":[["127d7b092805890b"]]},{"id":"a5ab0fe5a8237ce8","type":"debug","z":"1a0b1c8a.2d4b7b","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":690,"y":80,"wires":[]},{"id":"90c06b57413a7042","type":"debug","z":"1a0b1c8a.2d4b7b","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"timestamp","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":140,"wires":[]}]