Sub-flows - help with their settings and getting information from them

Normally with function nodes, you can do a node-warn("message") and you see the message under the node.

Alas that isn't possible with sub-flows.
Well, it kind of it - I believe.
With the status button ticked.

But then I seem to be running into problems with multiple occurrences of said sub-flow and the messages.

What I've done to control which sub-flow's message I see is to put a bit of login in the flow so I send a message {payload:'ON',topic:'DEBUG'} (where it can be ON or OFF.

That is a gate (well: gate) before the output to the status output.

Here's the problem:
I have (say) 8 of these nodes of the sub-flow. Each has its own debug input nodes.
I turn on the debug for node 3 and I see node 7's debug information.

Keh? :frowning: :roll_eyes:

Without seeing the actual flow, it's hard to suggest where it may be going wrong.

Yeah, I know.

Couple of problems:
1 - it has foreign nodes in it.
2 - it (just the subflow) is way too big to post.

I shall try to create a few smaller ones which have the same problem.
But I am sure Mr Murphy will step in and stop that happening.

Ok, I may have found the problem, but would like confirmation, because I have a habit of not getting it right.

1 - See debug injection nodes for sub-flow (#8).
2 - See message from other sub-flow (#7)

1 - Output from Sub-flow #6

1 - Output from sub-flow #5

1 - Output from Sub-flow #4

1 - Looking inside sub-flow
2 - node name (temp).
Code: node.warn(msg.payload)

1 - (Sill in sub-flow)
2 - catch-all connected to link node.
3 - (top one) going to a gate node then to a debug node3.
4 - (bottom one) going to the output called status from sub-flow

1 - gate default to closed.
So it shouldn't let messages through.
But I think I am not getting how to get messages from a sub-flow
I maybe need the gate between the catch-all and the status output node.

Please confirm.

I notice that in the debug you are displaying the messages from 'all nodes'. you might want to change it to curent flow

Yes, thanks @zenofmud, but then I have to go through setting all that up to check for certain things.

Then when I want to look back at the bigger picture........ I have to re-set which debug nodes to use. Then when I need to look at those specific ones I need to set it again.

That seems too complicated.

I get that work needs to be done, but I am trying to keep it simple.

Sorry.

Well you did ask!!

@Trying_to_learn, can't you distill the issue into a more concise flow?

1 Like

I am kind of stuck between a rock and hard place.

I fully appreciate it is good to refine it down to a specific case - which makes it easier on which to work.

But (yeah, there's usually one of those) I have no idea what I am doing - kind of.

I am trying to get things done with the limited knowledge I have and not having a perfect vision of how it is all supposed to work.

Well, I kind of do, but getting it from there to a complete picture and then to application is a whole other thing.

I (maybe) need a better understanding of how sub-flow output works.

Yes, I'm doing the same!
...but I've found that by trying to isolate the issue by simplifying the flow, sometimes helps me by highlighting the problem, and certainly helps other members help me.

So I can see you have a Function node doing a node.warn() inside the Subflow.
Within that subflow you also have a Catch node that is wired via a gate node to a status output.

Are you expecting the catch node to handle the node.warn() message and prevent it appearing in the debug sidebar? If so, then that is not how it works. node.warn() writes a piece of text to the log - it does not send a message object.

The catch node handles errors - errors that are logged using node.error("an error", msg) - where, more specifically, the msg object you pass as the second argument to node.error is emitted from the catch node.

@knolleary

Ok, this is the latest take on what I am doing in the sub-flow.

The idea is a catch-all node. That goes to a switch node which gets a flow.DEBUG value.
If that is ON it passes the message.

[{"id":"80aeb895.49c29","type":"fan","z":"b1f30721.c3bde","x":4780,"y":1030,"wires":[[]]},{"id":"a00dc65a.1e50e8","type":"link in","z":"b1f30721.c3bde","name":"STATUS","links":["7cfe56fa.348198"],"x":4490,"y":1030,"wires":[["cc116178.c41e88"]],"l":true},{"id":"7cfe56fa.348198","type":"link out","z":"b1f30721.c3bde","name":"STATUS","links":["a00dc65a.1e50e8","b8e0924d.47d518","7e130ce.4d71cf4"],"x":4280,"y":1030,"wires":[],"l":true},{"id":"2ef78083.83a29","type":"catch","z":"b1f30721.c3bde","name":"","scope":null,"uncaught":false,"x":4070,"y":1030,"wires":[["7cfe56fa.348198"]]},{"id":"cc116178.c41e88","type":"switch","z":"b1f30721.c3bde","name":"DEBUG","property":"DEBUG","propertyType":"flow","rules":[{"t":"eq","v":"ON","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":4630,"y":1030,"wires":[["80aeb895.49c29"]]}]

Is that/this a better way of controlling what is seen?

The bigger idea is that I set a flow.DEBUG to ON/OFF and if it is ON it passes the message.

That then spits all the node.warn( ) messages out the status of the sub-flow.
But I am not sure I am fully getting that part.

(ITMT, I have discovered a great work around for my seeming dependence of the GATE node.)

You cannot control the node.warn messages. They do not travel through the flow like normal messages - they are written straight to the log and sent to the Debug sidebar.

The Catch node only catches node.error() calls that have both a log message and a message object passed to it.

Ah! Ok. So the catch-all only does errors.

Fair enough. That explains a lot.

So, what am I missing about in the sub-flow the node.warn( ) and the status node output of the sub-flow?

Are the node-warn( ) messages confined to the sub-flow and exit via the status node output?

No. For the third time: node.warn() writes a log entry directly to node-red log and Debug sidebar. It is not a 'message' in the sense of the things passing along the wires in your flow. It is a piece of text written to the log.

The status output of the subflow has absolutely nothing to do with node.warn or the log or the Debug sidebar.

Let's step through what the status output is about.

First, lets consider a simple Function node in a normal flow - nothing to do with subflows. In that Function you can use the line node.status("Hello") and in the editor you will see the text Hello appear below the node:

image

This text is the Node Status. As you know, many nodes update their status to reflect some sort of internal state.

You can then add a Status node into the flow and it will get triggered whenever the Function node updates its status.

The message the Status node sends has the msg.status property set to an object containing the status text. It also includes msg.status.source which identifies which node set this status.

image

Now, if we put that single Function node into a Subflow and trigger it, lets see what we get:

We still get a message from the Status node, and it identifies its source as being a Function node, but the id is the internally generated id for the instance of the Function inside the subflow. There is nothing there to help us know it has come from the internals of the subflow. Also note the subflow instance node does not show any status text beneath it.

This is where the Status output of the subflow comes into play.

Lets change the Function inside the subflow to the following:

Rather than call node.status it now passes the message it a second output which is wired to the subflow's status output.

Now, when we trigger the subflow as before we get:

This time, notice the Subflow node shows the status text below it. Also note the source of the status message is identified as being the subflow instance.


I hope this shows the purpose of the status output of a subflow. It lets you create a subflow that updates its status property just as any node can.

3 Likes

Ok, I sincerely apologise for the mix up.

I got status and catch-all mixed up.

My bad.

However, did you really look at the flow I posted? (No offence)

My take (though now modified. Though it shouldn't really change anything) is that in a sub-flow the flow.BLAH is local to that sub-flow.
If that is wrong, well: all bets are off.

So I send a message into the sub-flow: {payload:'ON',topic:'DEBUG'}
That goes into a change node which flow.set(DEBUG), msg.payload

The function nodes with their node.warn( ) - which I now realise should be node-status( ) are preceded by a switch node.

It looks at flow.DEBUG
If it == ON then it passes on the message into the function node - with the node.warn( )
So: (Big if) if flow.DEBUG == 'OFF' the message won't pass through.
If it doesn't pass through, the function node won't get the message and so won't warn.

I'll modify it all now to node.status( )

Thanks. But could you confirm (even if not the accepted way) would that system work?
(Stopping messages with flow.DEBUG isolating the function node.)

Only enough to identify the misunderstanding you had with node.warn and then spent 10 minutes writing a long post to clarify it for you.

flow.DEBUG will be local to the subflow and using that to make a decision as to where messages should flow is a very sensible way of doing things.

Is your goal to update the Status text under the Subflow node or to make things appear in the Debug sidebar? Changing everything to node.status() may not be what you really want to do. Note how in my post I didn't use node.status() in the final example inside the subflow?

Well the main idea is (because I can't use debug nodes in a sub-flow) to have node.warn( ) all over the place in the sub-flow that are controlled by flow.DEBUG.

I know I am putting the cart before the horse in how I am doing this, but as I need several iterations of the code to see if works, I am having difficulty having it all on the same page, repeated n times.

So in the sub-flow I have (now) a switch node that checks flow.DEBUG == 'ON' and if true, pass on the message.
Then the payload is passed to a function node which: node.warn(msg.payload)

So if I inject a DEBUG: ON message all the switch nodes will allow the messages to get to the side bar and I can see what is what in the sub-flow.

When done, I inject a DEBUG: OFF and turn off all the debug nodes in the sub-flow.

Where I think I was getting confused was I wasn't consistent in how I did it. (I have suffered enough so I won't elaborate on that)

What you have told me helps me.

I do appreciate you taking the time, and would prefer I didn't need to ask. But I am not that smart - yet. (Probably never will be)

Thanks. I'll go over the code and fix up any stuff ups I have so it is consistent and also add some node.status( ) things too to help with slower changing messages/states.

Again: Thanks.
To you and all that replied.

If this is about controlling what appears in the Debug sidebar then do not use node.status() because as I explained at length, node.status() has nothing to do with messages appearing in the Debug sidebar.

If this is all about controlling what appears in the Debug sidebar from inside the subflow, then your function node can do:

if (flow.get("DEBUG") == 'ON') {
   node.warn("Hi there");
}

There is no need to do much more than that.

Yes, thanks.

I need (well.....) to use node.status( ) because the status of the sub-flow will change from time to time.
That would be nice to see/know below the node.
So that will be used correctly (I hope) so when a message comes in to change the status of the sub flow, it will print the correct information below said node.

Oh, on what you said, yes, I also agree.
Though I would use the msg.payload so I can see what is being seen in the flow to track down why things aren't working.

Though I also admit that I am using a switch node and a function node to display the node.warn( ) part.

I guess if I am using a function node then the extra if( ) would be better. It is I have just been bitten by understanding a better use of the switch node.

(I may actually do what you said. Thanks.)

Please read through my long explanation of node.status() again. In particular, again, note how I don't use node.status() in the final example of actually updating the subflow status.

If you want to update the status of a Subflow, you need to pass a message to the subflow's status output. You don't use node.status() to do that.