Maths expression in switch node (jsonata?)

Hello. I am trying to model out a potential application in Node-RED whereby I gradually reduce the speed of a pump that is filling a tank, so that the flowrate gradually decreases as the tank fills up. Think of slowing down the flow of water from the pump when filling up a fishtank as it starts to reach the maximum level, so as to avoid overfilling.

In my mockup, I assumed a 750 liter tank and a pump that flows at 10 liters/min. The pump runs at full flow rate up to the point where the tank is filled to 250 liters. I set up a switch node to decrease the pump flow rate as the tank is filled more and more. I have the fill_level set as a flow.context, which is used by the switch node.

The attached flow works fine, but the switch node uses static ranges for the tank fill_level (e.g. <250, 251-400, 401-550, etc.). I would like to do the same general switch node, but using percentages, i.e. if tank is 50% full, then send to output 2; if tank is 75% full, then send to output 3; etc. But I do not see any obvious options in the switch node settings for how this can be done. Any hints or suggestions are appreciated. I have a feeling that a JSONata expression can achieve this.

[{"id":"a185545da272dacb","type":"inject","z":"3b9f706f88df3650","name":"Pump Flowrate","props":[{"p":"payload"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":130,"y":480,"wires":[["633040094a5811be"]]},{"id":"c2867097a9f33e74","type":"debug","z":"3b9f706f88df3650","name":"10% reduction","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":740,"y":420,"wires":[]},{"id":"633040094a5811be","type":"switch","z":"3b9f706f88df3650","name":"","property":"fill_level","propertyType":"flow","rules":[{"t":"lt","v":"250","vt":"num"},{"t":"btwn","v":"251","vt":"num","v2":"400","v2t":"num"},{"t":"btwn","v":"401","vt":"num","v2":"550","v2t":"num"},{"t":"btwn","v":"551","vt":"num","v2":"700","v2t":"num"},{"t":"btwn","v":"701","vt":"num","v2":"750","v2t":"num"}],"checkall":"true","repair":false,"outputs":5,"x":290,"y":480,"wires":[["25002a565c6e77aa"],["b6869bbc3ddda501"],["f61c6ec48a30d565"],["f91fa1bdba4d3ffa"],["df563ce77daef57a"]]},{"id":"5794b071a373e98a","type":"inject","z":"3b9f706f88df3650","name":"750","props":[{"p":"topic","v":"750","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":80,"wires":[["2766485d95329272"]]},{"id":"47e6ccd0f3908757","type":"inject","z":"3b9f706f88df3650","name":"725","props":[{"p":"topic","v":"725","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":120,"wires":[["2766485d95329272"]]},{"id":"3f3001e270419cec","type":"inject","z":"3b9f706f88df3650","name":"600","props":[{"p":"topic","v":"600","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":160,"wires":[["2766485d95329272"]]},{"id":"f947756b414de641","type":"inject","z":"3b9f706f88df3650","name":"550","props":[{"p":"topic","v":"550","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":200,"wires":[["2766485d95329272"]]},{"id":"43e4e03aaf23d1f5","type":"inject","z":"3b9f706f88df3650","name":"400","props":[{"p":"topic","v":"400","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":240,"wires":[["2766485d95329272"]]},{"id":"74088ce02a700617","type":"inject","z":"3b9f706f88df3650","name":"350","props":[{"p":"topic","v":"350","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":280,"wires":[["2766485d95329272"]]},{"id":"78bc2de2535e563e","type":"inject","z":"3b9f706f88df3650","name":"240","props":[{"p":"topic","v":"240","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":320,"wires":[["2766485d95329272"]]},{"id":"2766485d95329272","type":"change","z":"3b9f706f88df3650","name":"Fill Level","rules":[{"t":"set","p":"fill_level","pt":"flow","to":"topic","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":220,"wires":[[]]},{"id":"b6869bbc3ddda501","type":"function","z":"3b9f706f88df3650","name":"Reduce flowrate by 10%","func":"msg.payload = msg.payload*.90\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":420,"wires":[["c2867097a9f33e74"]]},{"id":"25002a565c6e77aa","type":"debug","z":"3b9f706f88df3650","name":"No reduction in flow","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":470,"y":380,"wires":[]},{"id":"f61c6ec48a30d565","type":"function","z":"3b9f706f88df3650","name":"Reduce flowrate by 30%","func":"msg.payload = msg.payload*.70\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":460,"wires":[["97abd5489ba572d1"]]},{"id":"97abd5489ba572d1","type":"debug","z":"3b9f706f88df3650","name":"30% reduction","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":740,"y":460,"wires":[]},{"id":"f91fa1bdba4d3ffa","type":"function","z":"3b9f706f88df3650","name":"Reduce flowrate by 40%","func":"msg.payload = msg.payload*.60\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":500,"wires":[["5f6357ba7383ef7f"]]},{"id":"5f6357ba7383ef7f","type":"debug","z":"3b9f706f88df3650","name":"40% reduction","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":740,"y":500,"wires":[]},{"id":"df563ce77daef57a","type":"function","z":"3b9f706f88df3650","name":"Reduce flowrate by 50%","func":"msg.payload = msg.payload*.50\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":540,"wires":[["296939d31ae973a3"]]},{"id":"296939d31ae973a3","type":"debug","z":"3b9f706f88df3650","name":"50% reduction","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":740,"y":540,"wires":[]}]

I'm sure that someone with a bigger brain than mine will be able to come up with some clever JSONata to do this. But for myself, I'd generally use a function node since you can work through the problem and build up the answer more easily.

This should work you need to feed in the tank volume, i have hard coded at 750.

[{"id":"a185545da272dacb","type":"inject","z":"bf9e1e33.030598","name":"Pump Flowrate","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":1110,"y":1960,"wires":[["633040094a5811be"]]},{"id":"633040094a5811be","type":"switch","z":"bf9e1e33.030598","name":"","property":"$flowContext(\"fill_level\") / (750/100)","propertyType":"jsonata","rules":[{"t":"gt","v":"50","vt":"num"},{"t":"gt","v":"40","vt":"str"},{"t":"gt","v":"30","vt":"str"},{"t":"gt","v":"10","vt":"str"},{"t":"else"}],"checkall":"false","repair":false,"outputs":5,"x":1280,"y":1960,"wires":[["df563ce77daef57a"],["f91fa1bdba4d3ffa"],["f61c6ec48a30d565"],["b6869bbc3ddda501"],["25002a565c6e77aa"]]},{"id":"df563ce77daef57a","type":"function","z":"bf9e1e33.030598","name":"Reduce flowrate by 50%","func":"msg.payload = msg.payload*.50\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1500,"y":2020,"wires":[["296939d31ae973a3"]]},{"id":"f91fa1bdba4d3ffa","type":"function","z":"bf9e1e33.030598","name":"Reduce flowrate by 40%","func":"msg.payload = msg.payload*.60\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1500,"y":1980,"wires":[["5f6357ba7383ef7f"]]},{"id":"f61c6ec48a30d565","type":"function","z":"bf9e1e33.030598","name":"Reduce flowrate by 30%","func":"msg.payload = msg.payload*.70\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1500,"y":1940,"wires":[["97abd5489ba572d1"]]},{"id":"b6869bbc3ddda501","type":"function","z":"bf9e1e33.030598","name":"Reduce flowrate by 10%","func":"msg.payload = msg.payload*.90\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1500,"y":1900,"wires":[["c2867097a9f33e74"]]},{"id":"25002a565c6e77aa","type":"debug","z":"bf9e1e33.030598","name":"No reduction in flow","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1460,"y":1860,"wires":[]},{"id":"296939d31ae973a3","type":"debug","z":"bf9e1e33.030598","name":"50% reduction","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1730,"y":2020,"wires":[]},{"id":"5f6357ba7383ef7f","type":"debug","z":"bf9e1e33.030598","name":"40% reduction","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1730,"y":1980,"wires":[]},{"id":"97abd5489ba572d1","type":"debug","z":"bf9e1e33.030598","name":"30% reduction","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1730,"y":1940,"wires":[]},{"id":"c2867097a9f33e74","type":"debug","z":"bf9e1e33.030598","name":"10% reduction","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1730,"y":1900,"wires":[]}]

You could probably do this in a change node and output the flow rate also, without the need to save a flow var, do the calc on change of fill level input.

Thanks to both of you. I had thought of (and might still attempt to write) a function node, but there is something about the Switch node that I find easier to use (even though a function node with multiple outputs looks the same from afar). The JSONata expression that @E1cid wrote will work fine and I can modify accordingly to not use hard-coded values in the future.

Trying to apply this same logic to a weight-based program and had just one follow-up re: JSONata expressions that specify flowContext. Here is what my context variables look like:

image

In the Switch node JSONata expression, how would one specify scale_weight as the property? Using $flowContext("scale_weight") does not appear to be working. Does one need to include the word "data" in there?

image

Yes, That would be "data.scale_weight"

Thank you! That worked perfectly.