How do I calculate diff between two consecutive payloads

#1

I'm trying to calculate the difference between to two consecutive payloads. I'm using SNMP node to query a router interface and return data bytes received. I want to subtract value payload n from payload n+1 to obtain throughput figure per second.

I've looked at context and function nodes but not not sure where to start.

Any suggestions would be appreciated.

Thanks

Chris

0 Likes

#2

Look at the storing data part of https://nodered.org/docs/writing-functions

1 Like

#3

I use a delay node, then store the output in a flow variable

Then the undelayed message go into a function which subtracts the flow variable from the current and divide with the delay time to get the rate.

0 Likes

#4

Perhaps this pre-built node could help you ?

0 Likes

#5

Thanks for your responses. To be clear, I want to subtract content of payload n from payload n+1, not find the time gap between the two.

As suggested, I'm going to run two snmp nodes and fire the second one with a short delay. Store both to context and run function node to subtract one from the other.

0 Likes

#6
[{"id":"a014e37e.af038","type":"debug","z":"e8e5ccfb.8b54e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":630,"y":80,"wires":[]},{"id":"e62bf4.e47cc41","type":"inject","z":"e8e5ccfb.8b54e","name":"","topic":"","payload":"2","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":60,"wires":[["6b749ee9.5af15"]]},{"id":"4424359f.3033ec","type":"inject","z":"e8e5ccfb.8b54e","name":"","topic":"","payload":"1","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":120,"wires":[["6b749ee9.5af15"]]},{"id":"6b749ee9.5af15","type":"join","z":"e8e5ccfb.8b54e","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":330,"y":80,"wires":[["53168641.5a4cb8"]]},{"id":"53168641.5a4cb8","type":"change","z":"e8e5ccfb.8b54e","name":"","rules":[{"t":"set","p":"result","pt":"msg","to":"payload[0]-payload[1]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":80,"wires":[["a014e37e.af038"]]}]
1 Like

#7

Here are a couple other contrib nodes that may do some of this for you...


0 Likes

#8

Thanks Leifnel.

Used this technique and have it working fine now.

Chris

0 Likes

#9

What about the following:
First SNMP node, then a change node that stores the payload in an other property of the message, then the second SNMP node with the second request, then a function node that does the subtraction. This way you have no delays, no storage, no race conditions, no parallel execution.
That would be a more flow based programming style

1 Like

#10

Here is another way with joining:

[{"id":"9e03a15e.eb805","type":"function","z":"c421dfeb.3e752","name":"AJV10","func":"var countmsg = 2;          //how many items to join?\n\nvar nodublicates = false;   //only join if payload unequal existing payload\nvar limit;                 //only join if payloads are on both sides of the limit\nvar hysteresis;      //hysteresis \nvar clearaftersend = false;//clear queue after sending\nvar sendinstantly = false;\nvar reverse = false;         //reverse output array\nvar priomode = false;\nvar storagemode = false;     \nvar topicmatch = false;\n//------------ different topic mode ------------------\nvar diftopics = false;      //true: join only different topics; false: join only same topics\nvar alphasort = false;\n\nvar inmsg = msg;\nvar msgs = context.get(\"aggmsgs\")||{};\nvar topicmsgs = msgs[inmsg.topic]||[];\n\n\nif (inmsg.topic === \"\")\n    return null;\nif (typeof inmsg.reset != \"undefined\") {\n    msgs = {};\n    topicmsgs = [];\n    lastval = undefined;\n    context.set(\"aggmsgs\",msgs);\n    context.set(\"lastval\",lastval);\n    return null;\n}\nif (typeof inmsg.resettopic != \"undefined\") {\n    topicmsgs = [];\n    lastval = undefined;\n}\nif (typeof hysteresis !== 'undefined' && typeof lastval !== 'undefined') {\n    if (Math.abs(inmsg.payload - lastval) <= hysteresis) {\n        return null;\n    }\n}\nif (typeof lastval !== 'undefined') {\n    if (nodublicates && lastval == inmsg.payload)\n        return null;\n    if (typeof limit !== 'undefined' && countmsg == 2) {\n        if (!((lastval <= limit && inmsg.payload >= limit) || (lastval >= limit && inmsg.payload <= limit)))   \n            return null;\n    }\n} \n\nif (topicmatch) {\n    if (typeof inmsg.payload.jointopic != \"undefined\") {\n        if (topicmsgs.length === 0) {\n            topicmsgs.push(inmsg);\n            msgs[inmsg.topic] = topicmsgs;\n            context.set(\"aggmsgs\",msgs);\n            return null;   \n        }\n        else {\n            topicmsgs[0] = inmsg;\n        }\n    }\n    else {  //only accept topics specified by jointopics\n        for (var tmsgs in msgs) {\n            if (msgs.hasOwnProperty(tmsgs)) {   \n                var bfound = false;\n                var btopicfound = false;\n                var ar = msgs[tmsgs];\n                for (var i = 0; i < ar.length; i++) {    //search and replace\n                    if (i === 0) {\n                        if (ar[i].payload.jointopic == inmsg.topic)\n                            btopicfound = true;\n                    } else {\n                        if (ar[i].topic == inmsg.topic) {\n                            ar[i] = inmsg;\n                            bfound = true;\n                        }\n                    }\n                }\n                if (!bfound && btopicfound)        //add new\n                    msgs[tmsgs].push(inmsg);\n            }\n        }\n    }\n}\n\nvar outmsg = { \"topic\": inmsg.topic , \"payload\": \"\"};\nvar lastval = context.get(\"lastval\");\nvar inprio = typeof inmsg.priority != \"undefined\" ? inmsg.priority: countmsg-1 ;     //default prio is 1\n\nif (diftopics) {\n    if (topicmsgs.length > 0) {     //msg with same topic -> replace old msg\n        topicmsgs.shift();\n    }\n    topicmsgs.push(inmsg);\n    msgs[inmsg.topic] = topicmsgs;    \n    if (Object.keys(msgs).length > countmsg) {\n        for (var tmsgs in msgs) {\n            if (msgs.hasOwnProperty(tmsgs)) {   \n                delete msgs[tmsgs];\n                break;\n            }\n        }\n    }\n    context.set(\"aggmsgs\",msgs);\n    context.set(\"lastval\",inmsg.payload);\n    if (Object.keys(msgs).length == countmsg || sendinstantly) {\n        var aout = [];\n        outmsg.topic = \"\";\n        \n        for (var tmsgs in msgs) {\n            if (msgs.hasOwnProperty(tmsgs)) \n                aout.push(msgs[tmsgs][0]);\n        }\n        if (clearaftersend) {\n            context.set(\"aggmsgs\",undefined);\n            context.set(\"lastval\",undefined);\n        }\n        if (alphasort) \n            aout.sort(function(a,b) {return (a.topic > b.topic) ? 1 : ((a.topic > b.topic) ? -1 : 0);});\n\n        if (reverse) \n            aout.reverse();\n\n        for (var i =0; i<aout.length;i++) {outmsg.topic += aout[i].topic + \"_\"; }\n        outmsg.topic = outmsg.topic.substr(0,String(outmsg.topic).length-1);\n        outmsg.payload = aout;\n\n        return outmsg;\n    } else\n        return null;\n} else {\n    if (topicmsgs.length == countmsg && !storagemode && !topicmatch){\n        topicmsgs.shift();\n    }\n    if (storagemode) {\n        topicmsgs[inprio] = inmsg;\n    } \n    if (!topicmatch) {\n        topicmsgs.push(inmsg);\n        msgs[inmsg.topic] = topicmsgs;\n    }\n\n    context.set(\"aggmsgs\",msgs);\n    context.set(\"lastval\",inmsg.payload);\n    \n    if (storagemode) {                          //check send msg\n        if (inprio < topicmsgs.length - 1)      //only send on trigger msg => no priority\n            return null;\n        for (var i = 0; i < topicmsgs.length; i++) { //only send if storage is full\n            if (topicmsgs[i] === undefined)\n                return null;\n        }    \n    }\n\n    if (topicmatch) {\n        for (var tmsgs in msgs) {\n            if (msgs.hasOwnProperty(tmsgs)) {   \n                var ar = msgs[tmsgs];\n                if (ar.length == countmsg) {\n                    for (var i = 0; i < ar.length; i++) {\n                        if (ar[i].topic == inmsg.topic) {\n                            outmsg.payload = ar;\n                            outmsg.topic = ar[0].topic;\n                            node.send(RED.util.cloneMessage(outmsg));\n                        }\n                    }\n                }\n            }\n        }\n    } else {\n        if (topicmsgs.length == countmsg || sendinstantly) {\n            outmsg.payload = topicmsgs;\n            if (topicmatch) {\n                outmsg.topic = topicmsgs[0].topicori;\n                outmsg.payload[0].topic = outmsg.topic;\n            }\n            \n            if (clearaftersend) {\n                msgs[inmsg.topic] = undefined;\n                context.set(\"aggmsgs\",msgs);\n                context.set(\"lastval\",undefined);\n            }\n            if (reverse) {\n                var revArr = outmsg.payload.map(a => Object.assign({}, a));\n                revArr.reverse();\n                outmsg.payload = revArr;\n            }\n            return outmsg;\n        }\n        else\n            return null;\n    }\n}\n","outputs":1,"noerr":0,"x":580,"y":2223,"wires":[["7dbd79.3f6b3288"]]},{"id":"7e87f6e1.e8b438","type":"inject","z":"c421dfeb.3e752","name":"","topic":"lala","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":419,"y":2170,"wires":[["9e03a15e.eb805"]]},{"id":"afd70e5b.5f155","type":"debug","z":"c421dfeb.3e752","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":965,"y":2271,"wires":[]},{"id":"7dbd79.3f6b3288","type":"change","z":"c421dfeb.3e752","name":"","rules":[{"t":"set","p":"dif","pt":"msg","to":"payload[1].payload - payload[0].payload","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":744,"y":2247,"wires":[["afd70e5b.5f155"]]}]
0 Likes

#11

Hi,
I want "2" be all time the first payload and 1 the second to get a positif value (If 1 is befor 2 the result is -1 and If 1 wans sent two times we obtain 0). So I want to fix the range of payload. have you an idea?
Thank you for your help.

0 Likes

#12

Are the two values coming from different places?

0 Likes