Compare two values to generate a difference value

I've two incoming temp sensor values, let's call them hi and lo, they come from different devices so don't arrive at the same time.
How can I subtract the 'lo' value from the 'hi' value to create a new value called 'diff'?

I have attempted to do this in a function node, but I'm not very good with the syntax, also the input sensors don't output at the same time. Should I bestoring the sensors in a global (I can do that) but then how do I carry out the calculation? It's output can be stored as a global too for use in other flows.

See this article in the cookbook for an example of how to join messages into one object.

EDIT - sorry, i see you store them in global (that is a viable alternative to join node)

Hi Steve, the problem is they don't come in at the same time. I can store the latest value in a global, but how do I carry out the calculation? Could do with some help with the Function node syntax... It's my kryptonite...

You can use the join node...


[{"id":"8ccddb9a.a55f38","type":"inject","z":"30e2e9e0.eeaab6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"hi","payload":"100","payloadType":"num","x":1330,"y":880,"wires":[["47b769c5.cb0e28"]]},{"id":"47b769c5.cb0e28","type":"join","z":"30e2e9e0.eeaab6","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":1490,"y":900,"wires":[["0e7a60dec064d06d"]]},{"id":"f9afb265.b11b7","type":"debug","z":"30e2e9e0.eeaab6","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1770,"y":900,"wires":[]},{"id":"2d269127.4f04ce","type":"inject","z":"30e2e9e0.eeaab6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"lo","payload":"15","payloadType":"num","x":1330,"y":920,"wires":[["47b769c5.cb0e28"]]},{"id":"0e7a60dec064d06d","type":"function","z":"30e2e9e0.eeaab6","name":"","func":"msg.topic = \"diff\"\nmsg.payload = msg.payload.hi - msg.payload.lo;\nreturn msg;","outputs":1,"noerr":1,"initialize":"","finalize":"","libs":[],"x":1620,"y":900,"wires":[["f9afb265.b11b7"]]}]

or you can use a function to grab the globals and do the math

[{"id":"f9afb265.b11b7","type":"debug","z":"30e2e9e0.eeaab6","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1750,"y":900,"wires":[]},{"id":"0e7a60dec064d06d","type":"function","z":"30e2e9e0.eeaab6","name":"","func":"msg.topic = \"diff\"\n\nvar hi = global.get(\"hi\");\nvar lo = global.get(\"lo\");\n\nmsg.payload = hi - lo;\n\nreturn msg;","outputs":1,"noerr":1,"initialize":"","finalize":"","libs":[],"x":1580,"y":900,"wires":[["f9afb265.b11b7"]]},{"id":"95b54c27bb57d871","type":"inject","z":"30e2e9e0.eeaab6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"hi","payload":"100","payloadType":"num","x":1430,"y":800,"wires":[["6c1a1eeb3b1427fb"]]},{"id":"431f7653eae82780","type":"inject","z":"30e2e9e0.eeaab6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"lo","payload":"15","payloadType":"num","x":1430,"y":840,"wires":[["b8928fa8aec87fab"]]},{"id":"6c1a1eeb3b1427fb","type":"change","z":"30e2e9e0.eeaab6","name":"","rules":[{"t":"set","p":"hi","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1590,"y":800,"wires":[[]]},{"id":"b8928fa8aec87fab","type":"change","z":"30e2e9e0.eeaab6","name":"","rules":[{"t":"set","p":"lo","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1590,"y":840,"wires":[[]]},{"id":"fb2b743f2ccbdfe6","type":"inject","z":"30e2e9e0.eeaab6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":1430,"y":900,"wires":[["0e7a60dec064d06d"]]}]

You could even use a JSONata expression in a change node.

1 Like

Got it. Thanks for the syntax.
I'll post my solution (Once I've tidied it up a bit...)

How do I change this line to allow one decimal place 0.0? It's current a whole number but I could do with one place right.
global.set("fridge_diff", Math.round(parseFloat(diff)) );

Math.round( parseFloat(diff) * 10 ) / 10

1 Like

Magic, although I have no idea why that works....

Is there a better way to trigger a flow based on a Global variable than using an inject node?

Behind the scenes:
parseFloat(diff) -> "3.278942" will be 3.278942

If the diff is type of string (which contains numbers) it will be converted to number type. Math operations can't be made with strings.
If you are sure that the type of diff is number always, this can freely be omitted.

Then multiply by ten
parseFloat(diff) * 10 -> 3.278942 will be 32.78942

Then round that result
Math.round(32.78942) -> 33

And then divide it by ten
33 / 10 -> 3.3

And no more magic :slight_smile:

1 Like

Yes, run it at the point the variable changes.

1 Like

Did just try that but the trigger passes the global variable into the following flow which the upper function does not pass outwards... Wish I was better with these function nodes.... I suspect I could get rid of many of the supporting nodes wrapping their functions up into a single node...

then put return msg at the end of the function.

TBH, you probably dont even need to use an global context (it is almost always the last place I go when looking for a solution)

Use a join node for the temp long and temp short (set join to key/value, 2 parts) then in the set diff function do your maths & set msg.payload = diff, then return that msg & connect the function to where the inject goes. No need for any globals.

If you do need the values further down in your flow, store them in the msg e.g. msg.temp = temp then later on you can easily access the other values from the msg - no need for setting and getting global context.

Ooh, I think that's a few steps beyond my non-programmer level of competence, although I'll have a go at the first part to remove the inject node.
I like NodeRed because I can get stiff done quickly without having to battle through endless syntax errors that have historically kept me away from code level of computing. NR is slowly easing my 50yo knackered brain into coding... lol

1 Like