Starting a sub-flow within the start tab of a function node

would it be possible to start a sub-flow within the start tab of a function node in order to run a few task before all other routines?

You can send messages from within the On Start tab of function nodes, but it might get tricky in case the function node is initialized before the subflow.

Since the On Start sections of function nodes are always triggered upon initialization, before the flow starts, why not just set an inject node (with an appropriate delay) to call the subflow automatically upon start?

I know what the on-start tab does fore one specific node. My problem is, that I want to start some initialisation functions before all the other flows start running.

Run it from an Inject node that fires on startup. That assumes that everything in there is synchronous of course.

thanks for your response.

I actually want to start a few initialisation routines, which I could put into a sub flow, before all the other flows start to run.

You may have a chicken & egg situation here. You can ensure the on-start of a specific node is triggered before anything else (it has to be the 1st node that was created on the 1st, i.e. leftmost, tab), but then all the other nodes may not be initialized yet.
Easiest is to set a dedicated inject node which starts after, say, 0.1 seconds to run your initialization, and another, set to start after 1 second or so to start the actual flows. if you have nodes which receive unsolicited messages, e.g. web-in, MQTT etc. you will need to block them until your flow is ready to handle.

I just run my Initialisation blocks before I run the rest of the flow. They are all on a tab labelled ‘Power Up’ which then links out to start the rest of the flows.

Not sure if that would help you?

Kind of advanced but maybe you could use the Admin API methods. You could for instance have just the first tab enabled as the startup tab for the rest. All other tabs could be disabled by default. In the startup tab you put your subflow, execute it and then when completed you can, via the Admin API, enable all the other tabs

I have done this myself in one of my setups, it works fine to enable/disable tabs. Would be working fine if all the other tabs (that are disabled at start) are rather stable, i.e. you do not edit them too frequently

good idea. I will look into it.

Thanks!

Here is a sample flow demonstrating the use of the Admin API

In the first tab, you have various functionality available like disable/enable tabs and request complete data of a tab

I also added a subflow to demonstrate how the finished execution of it could trigger the enabling of the other tab(s)

My example has only one tab that gets enabled but this could of course be extended, you get the idea

[{"id":"9b4520c0b6e9d0a0","type":"subflow","name":"Subflow 1","info":"","in":[{"x":150,"y":180,"wires":[{"id":"8a8197ac37de98f9"}]}],"out":[{"x":520,"y":180,"wires":[{"id":"8a8197ac37de98f9","port":0}]}]},{"id":"8a8197ac37de98f9","type":"change","z":"9b4520c0b6e9d0a0","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"Hello, subflow finished","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":180,"wires":[[]]},{"id":"2b79b37dc68a9b85","type":"tab","label":"Startup w subflow","disabled":false,"info":"","env":[]},{"id":"9d20f267b6b81016","type":"http request","z":"2b79b37dc68a9b85","name":"","method":"use","ret":"txt","paytoqs":"query","url":"","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"headers":[],"x":770,"y":80,"wires":[[]]},{"id":"25d2c8370302be1b","type":"comment","z":"2b79b37dc68a9b85","name":"disable/enable an existing flow tab","info":"","x":230,"y":40,"wires":[]},{"id":"e0fcf107b7eaee28","type":"change","z":"2b79b37dc68a9b85","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"\"http://localhost:1880/flow/\" & payload.id","tot":"jsonata"},{"t":"set","p":"method","pt":"msg","to":"PUT","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":80,"wires":[["9d20f267b6b81016"]]},{"id":"072051fd0cd67c3a","type":"change","z":"2b79b37dc68a9b85","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"\"http://localhost:1880/flow/\" & payload","tot":"jsonata"},{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":460,"wires":[["e6e937b802519eac"]]},{"id":"e6e937b802519eac","type":"http request","z":"2b79b37dc68a9b85","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"headers":[],"x":550,"y":460,"wires":[["74bf8a3ca3117ec1"]]},{"id":"160e0a761954cf2e","type":"comment","z":"2b79b37dc68a9b85","name":"Request to retrieve a flow tab data","info":"","x":230,"y":420,"wires":[]},{"id":"e8a0e84c4f89aaf5","type":"inject","z":"2b79b37dc68a9b85","name":"get","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0c42aac0c59ac964","payloadType":"str","x":140,"y":460,"wires":[["072051fd0cd67c3a"]]},{"id":"74bf8a3ca3117ec1","type":"debug","z":"2b79b37dc68a9b85","name":"debug 382","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":770,"y":460,"wires":[]},{"id":"85c67242031875ba","type":"change","z":"2b79b37dc68a9b85","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"id\":\"0c42aac0c59ac964\",\"label\":\"Others\",\"disabled\":false,\"info\":\"\",\"env\":[],\"nodes\":[{\"id\":\"8c22614fdd3f15e8\",\"type\":\"inject\",\"z\":\"0c42aac0c59ac964\",\"name\":\"\",\"props\":[{\"p\":\"payload\"},{\"p\":\"topic\",\"vt\":\"str\"}],\"repeat\":\"\",\"crontab\":\"\",\"once\":false,\"onceDelay\":0.1,\"topic\":\"\",\"payload\":\"\",\"payloadType\":\"date\",\"x\":170,\"y\":90,\"wires\":[[\"524842e1afedf072\"]]},{\"id\":\"524842e1afedf072\",\"type\":\"debug\",\"z\":\"0c42aac0c59ac964\",\"name\":\"debug 6\",\"active\":true,\"tosidebar\":true,\"console\":false,\"tostatus\":false,\"complete\":\"false\",\"statusVal\":\"\",\"statusType\":\"auto\",\"x\":380,\"y\":90,\"wires\":[]}]}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":140,"wires":[["e0fcf107b7eaee28"]]},{"id":"17825aad8d05ea94","type":"change","z":"2b79b37dc68a9b85","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"id\":\"0c42aac0c59ac964\",\"label\":\"Others\",\"disabled\":true,\"info\":\"\",\"env\":[],\"nodes\":[{\"id\":\"8c22614fdd3f15e8\",\"type\":\"inject\",\"z\":\"0c42aac0c59ac964\",\"name\":\"\",\"props\":[{\"p\":\"payload\"},{\"p\":\"topic\",\"vt\":\"str\"}],\"repeat\":\"\",\"crontab\":\"\",\"once\":false,\"onceDelay\":0.1,\"topic\":\"\",\"payload\":\"\",\"payloadType\":\"date\",\"x\":170,\"y\":90,\"wires\":[[\"524842e1afedf072\"]]},{\"id\":\"524842e1afedf072\",\"type\":\"debug\",\"z\":\"0c42aac0c59ac964\",\"name\":\"debug 6\",\"active\":true,\"tosidebar\":true,\"console\":false,\"tostatus\":false,\"complete\":\"false\",\"statusVal\":\"\",\"statusType\":\"auto\",\"x\":380,\"y\":90,\"wires\":[]}]}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":80,"wires":[["e0fcf107b7eaee28"]]},{"id":"a1a096ec2ee32b04","type":"link in","z":"2b79b37dc68a9b85","name":"sonoff_disable_in","links":["033ef756d6e9c765"],"x":105,"y":80,"wires":[["17825aad8d05ea94"]]},{"id":"aef7d5f5b0d70383","type":"link in","z":"2b79b37dc68a9b85","name":"sonoff_enable_in","links":["0ac7a3f2bea08e33","3fba5d011236565d"],"x":105,"y":140,"wires":[["85c67242031875ba"]]},{"id":"3c65d9a5cae5c35f","type":"inject","z":"2b79b37dc68a9b85","name":"disable","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"10","topic":"","payload":"true","payloadType":"bool","x":140,"y":270,"wires":[["033ef756d6e9c765"]]},{"id":"033ef756d6e9c765","type":"link out","z":"2b79b37dc68a9b85","name":"link out 3","mode":"link","links":["a1a096ec2ee32b04"],"x":245,"y":270,"wires":[]},{"id":"2c6af0e0f22c55a2","type":"comment","z":"2b79b37dc68a9b85","name":"Request to disable/enable an existing flow tab","info":"","x":260,"y":230,"wires":[]},{"id":"31e8b949ef9a1ddb","type":"inject","z":"2b79b37dc68a9b85","name":"enable","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"10","topic":"","payload":"true","payloadType":"bool","x":140,"y":320,"wires":[["0ac7a3f2bea08e33"]]},{"id":"0ac7a3f2bea08e33","type":"link out","z":"2b79b37dc68a9b85","name":"link out 2","mode":"link","links":["aef7d5f5b0d70383"],"x":245,"y":320,"wires":[]},{"id":"0f1ca98020d7c20c","type":"inject","z":"2b79b37dc68a9b85","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":140,"y":610,"wires":[["80c35919f747d571"]]},{"id":"8a9378bd1b74b87e","type":"comment","z":"2b79b37dc68a9b85","name":"Init and run subflow","info":"","x":180,"y":570,"wires":[]},{"id":"3fba5d011236565d","type":"link out","z":"2b79b37dc68a9b85","name":"link out 4","mode":"link","links":["aef7d5f5b0d70383"],"x":465,"y":610,"wires":[]},{"id":"80c35919f747d571","type":"subflow:9b4520c0b6e9d0a0","z":"2b79b37dc68a9b85","name":"","x":330,"y":610,"wires":[["3fba5d011236565d","db0e1ce2db018c6a"]]},{"id":"db0e1ce2db018c6a","type":"debug","z":"2b79b37dc68a9b85","name":"debug 7","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":510,"y":680,"wires":[]},{"id":"0c42aac0c59ac964","type":"tab","label":"Others","disabled":true,"info":"","env":[]},{"id":"8c22614fdd3f15e8","type":"inject","z":"0c42aac0c59ac964","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":170,"y":90,"wires":[["524842e1afedf072"]]},{"id":"524842e1afedf072","type":"debug","z":"0c42aac0c59ac964","name":"debug 6","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":380,"y":90,"wires":[]}]

Is there a way to do this without getting a warning notification that the flow file has changed?

Also, it seems that for updating the tab, you need to provide its full definition, including the full definitions of its contents (nodes, groups etc.), else it will come up empty.

So the way to do this dynamically with the admin API (without setting explicit IDs which can change) is:

  • fetch the full flow file (GET, /flows), parse it to an object
  • search for the required tab(s) by name (type=="tab" and label==tab name)
  • update the "disabled" property of these tabs

now either:

  • replace the whole flow file with the updated one (PUT, /flows)

or

  • for each tab object, append all its internal nodes (by tab Id), then update the tab (PUT /flow/xyz)

I dont know, I don’t think so. But it is harmless, just refresh your browser and you will see the new status of the tabs (I run my flow as a server so I never look at the editor in normal case)

Correct.

Yeah, I would do it per tab. Here is a more developed flow that gets the actual tab data including nodes etc and changes the “disabled” property in the object. I would make one for each tab and then you can edit the tab as you like. Only thing you need to provide is the tab id. Next time it will use the tab as it is currently defined

[{"id":"17e9ef34522d108a","type":"change","z":"2b79b37dc68a9b85","name":"","rules":[{"t":"set","p":"payload.disabled","pt":"msg","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":880,"y":840,"wires":[["6addaa13ca47ce9a"]]},{"id":"6addaa13ca47ce9a","type":"debug","z":"2b79b37dc68a9b85","name":"debug 6","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1100,"y":840,"wires":[]},{"id":"bdefde40d5fe1e15","type":"change","z":"2b79b37dc68a9b85","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"\"http://localhost:1880/flow/\" & payload","tot":"jsonata"},{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":300,"y":840,"wires":[["359d6c29d121f0a9"]]},{"id":"359d6c29d121f0a9","type":"http request","z":"2b79b37dc68a9b85","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"headers":[],"x":500,"y":840,"wires":[["c1e9287176d25d42"]]},{"id":"47e30e42b3bf1a38","type":"inject","z":"2b79b37dc68a9b85","name":"get","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"b079a9ae7a1efb64","payloadType":"str","x":130,"y":840,"wires":[["bdefde40d5fe1e15"]]},{"id":"c1e9287176d25d42","type":"json","z":"2b79b37dc68a9b85","name":"","property":"payload","action":"","pretty":false,"x":670,"y":840,"wires":[["17e9ef34522d108a"]]}]

Just curious, what is the exact problem you are trying to solve this way? What is your use-case?