Accessing global context values in function?

Apologies for the noob question, I'm just starting off with Node Red.

I'm trying to make a flow such that If the Generator is Running then set in a time delay ....then after the delay check to see if Battery Charge - AC Consumption is less than 1000. If less, shut off generator, if not, do nothing.

I can see AC Consumption and Battery Charge but I'm not sure how to reference those in my function. I know I'll need to put some if else logic in the function, but I don't know how to reference those values. Many thanks for any help.

check if this helps.

[{"id":"e6ee54547726fd4a","type":"function","z":"972775b3ccaa2485","name":"Check Global Context","func":"if (global.get(\"condition1\") == \"Yes\") {\n    msg.payload=\"Condition 1 Met\"}\n else {msg.payload = \"Condition 1 not met\"\n }\n\n return msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":2400,"wires":[["30af994c30ebc8e1"]]},{"id":"152b53caea2a44c1","type":"inject","z":"972775b3ccaa2485","name":"Check","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":330,"y":2400,"wires":[["e6ee54547726fd4a"]]},{"id":"30af994c30ebc8e1","type":"debug","z":"972775b3ccaa2485","name":"debug 318","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":770,"y":2400,"wires":[]},{"id":"babcc51a29551240","type":"function","z":"972775b3ccaa2485","name":"Set Global context","func":"global.set(\"condition1\", msg.payload);\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":550,"y":2320,"wires":[[]]},{"id":"dc1c3d4cfb5cfe13","type":"inject","z":"972775b3ccaa2485","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Yes","payloadType":"str","x":330,"y":2320,"wires":[["babcc51a29551240"]]},{"id":"19a2576c7aef715f","type":"inject","z":"972775b3ccaa2485","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"No","payloadType":"str","x":330,"y":2360,"wires":[["babcc51a29551240"]]}]

You may find it better to collect all the information in one object. Then there would be no need for context, and when 1 item changes you have all the other information. Each item must have a unique identifier, in the example I have used msg.topic.

You can use a join node in manual mode to do this, after three items have come in any change to them will send an output that has all the info from previous readings.

Here is an example I have used inject nodes, but you can use your incoming nodes and if they have no topic field you can add them with a change node.

[{"id":"3eec1b2334fe4b33","type":"inject","z":"d1395164b4eec73e","name":"Generator state","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"genState","payload":"true","payloadType":"bool","x":240,"y":7580,"wires":[["2990d3bb5c32cf09"]]},{"id":"2990d3bb5c32cf09","type":"join","z":"d1395164b4eec73e","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","useparts":false,"accumulate":true,"timeout":"","count":"3","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":390,"y":7620,"wires":[["96fc0b979686861b"]]},{"id":"b961b9912ac41161","type":"inject","z":"d1395164b4eec73e","name":"vattery charge","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"batCharge","payload":"56","payloadType":"num","x":230,"y":7640,"wires":[["2990d3bb5c32cf09"]]},{"id":"2644fcce954af7e7","type":"inject","z":"d1395164b4eec73e","name":"AC concumption","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"acComp","payload":"700","payloadType":"num","x":240,"y":7700,"wires":[["2990d3bb5c32cf09"]]},{"id":"96fc0b979686861b","type":"debug","z":"d1395164b4eec73e","name":"debug 2579","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":7560,"wires":[]}]

Now you have all the info in one object for you function or other nodes.

You may benifit from watching the essentials videos which will give you the basics of messages and standard nodes.

1 Like

Do I copy and paste that code you supplied into the function or do I need to import it somehow?

Thank you, that seems intuitive. So I could take my generator state node and all the other nodes I need and join them together for processing and they'd be subelements in the msg for me to reference. Thank you very much, I'll try that.

I appreciate the help for these basic questions that I probably could have answered with more reading.

No sorry I should of added
How to import/export a flow

To your OG topic, you can read how to access context in a function here Writing Functions : Node-RED

1 Like

its a flow, so you need to import it Copy/Ctrl+i/Paste/Deploy.
I was just trying to show you how to set and get global context in a function node. But as @E1cid suggested, avoiding context and getting a linear flow is best option.

1 Like

So far I'm not sure how to reference the individual data components that are joined in my switch. I'll take a look at that video and look into using a change node to add a topic.

You will need to add topics with change nodes if the input nodes do not allow you to add a topic in them.

Add a debug and the you can see the joined object

There’s a great page in the docs (Working with messages : Node-RED) that will explain how to use the debug panel to find the right path/value for any data item.

Pay particular attention to the part about the buttons that appear under your mouse pointer when you over hover a debug message property in the sidebar.

BX00Cy7yHi

You can use the path to reference the data in a switch node and most other nodes. You can use multiple switch nodes in series or parallel to do your logic.

1 Like

Awesome, I will get to studying. Excited to learn this, many thanks!

That debug link you sent has opened it up. Now I'm seeing the components from the join. I had to set the join node to not do automatic, and to send to debug after 1 message changed. Now it's becoming more clear. Thank you!

It appears I do not need a change node because it is publishing topics.

I'm just not yet sure how to reference those individual topics in my switch for function.

Use the copy path button in the debug node, the path is the way to reference the value in a switch node.

I would also advise to add your own topics as the ones from the input nodes have spaces, which complicates the path for the switch node. Add topics and use underscores instead of spaces.

1 Like

This seems to be working now. When you say add my own topics (to get rid of spaces), is that done with the Change node?

Yes, unless you can add them manually in your input nodes.

1 Like

Thanks to all the help I got here (especially the join command in lieu of global context), I have been able to create a generator auto-start and auto-stop flow.

One flow I'm having a bit of issue with is meant to detect when the generator has run out of gas and isn't supplying power anymore, so that it shuts off the relay.

It seems my error was thinking the message from the join module would be updated to the latest values after the delay. This delay is so the generator can ramp up before its power is evaluated. But what is happening is the messages that are delayed are not being dynamically updated to the current values by the time they get to the function that evaluates them, so the generator keeps shutting down.

Is there a way to make the data in the join node always current value even as it travels along the flow? Or, alternatively, not have AC Consumption, Battery Charge, and MPPT power evaluated until AFTER the delay?

I think maybe you misunderstand messages and Node-red.
The join node is not continually monitoring the "state" of it's 4 inputs. It only ever does anything when a message arrives from one of the inputs. What it does then is to compare the latest inputs and (maybe) send a message on down the line.

Maybe you can replace the delay node with a trigger node? Set it to send nothing, wait 120 seconds and then send the latest msg object. You might need to be able to reset the trigger depending on the incoming message.

1 Like

Yes, I misunderstood. I will take a look at the trigger node, many thanks!

I think I've figured it out.

I just referenced the global context variable in my function and that returns the latest data (after the delay).

power = global.get("victronenergy.battery._512.Dc._0.Power");