Passing Variables to subflows

I am still fairly new to Node-Red and progressing slowly, although today I built my first sub flow so that I can reuse this functionality. I have gone through several documents and videos about sub flows but still do not quite understand how to do what I need done. I am using NR V 1.04.

Brief Explanation of sub flow:
Reads a payload (payload = true followed by payload = false) and determines the start / end time of the payload pulse and its duration – i.e. time on. The payload result (JSON) is stored in a context variable and also sent out in the msg payload. (Please refer to the attached flow).

[{"id":"34e707bd.f201b8","type":"subflow","name":"Calc TS/Dur","info":"","category":"","in":[{"x":220,"y":140,"wires":[{"id":"d3d60357.3d77d"},{"id":"6021b437.eebcdc"}]}],"out":[{"x":1060,"y":160,"wires":[{"id":"4c112160.9d261","port":0}]}],"env":[{"name":"TS_Data","type":"str","value":""},{"name":"TopicName","type":"str","value":""}],"color":"#DDAA99","status":{"x":1060,"y":280,"wires":[{"id":"67db6300.1da7ac","port":0}]}},{"id":"d49cbb34.913418","type":"debug","z":"34e707bd.f201b8","d":true,"name":"TS_Data Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1120,"y":220,"wires":[]},{"id":"4c112160.9d261","type":"function","z":"34e707bd.f201b8","name":"Calc TS Data","func":"// Calculates the time data for when msg.payload is true. This\n// function calculates the duration of the pulse while true due to the\n// upstream rising / falling trigger nodes which set the topic.\n\nvar TS_Data = env.get(\"TS_Data\");  \n// Want the TopicName to be the RngTmr\n// TopicName = ${TS_Data} or TopicName = $TS_Data  does not work\nvar TopicName = env.get(\"TopicName\");  // This works\nvar ts;\n\n// Get TS_Data \nif(global.get(TopicName) === undefined){\n    TS_Data = {\n        \"Topic\": TopicName,\n        \"R_ms\": 0,\n        \"F_ms\": 0,\n        \"StartTime\": 0,\n        \"EndTime\": 0,\n        \"Dur\": 0,\n        \"Valid\": false\n    }\n } else {\n     TS_Data = global.get(TopicName);\n }\n\n// Process R_Trig timestamp and set to invalid\nif (msg.topic === \"R_Trig\") {\n    \n    TS_Data.R_ms = msg.payload;\n    // R_Trig Received\n    // Get new timestamp\n    ts = new Date(msg.payload);\n    TS_Data.StartTime = new Date(ts.getTime() - ts.getTimezoneOffset() * 60000).toISOString().replace('T', ' ').substr(0, 19);\n    \n    // Clear falling data\n    TS_Data.F_ms = \"\";\n    TS_Data.EndTime = \"\";\n    TS_Data.Dur = 0;\n    TS_Data.Valid = \"In Progress\";\n    global.set(TopicName, TS_Data);\n    node.status({fill:\"yellow\",shape:\"ring\",text:\"Waiting for F_Trig\"});\n    msg.topic = TopicName;  \n    msg.payload = TS_Data;\n    return msg;\n}\n\n// Process F_Trig timestamp and check validity\nif (msg.topic === \"F_Trig\") {\n    TS_Data.F_ms = msg.payload;\n    \n    if (TS_Data.R_ms === 0) {\n        // R_Trig NOT Received before F_Trig\n        TS_Data.R_ms = 0;\n        TS_Data.F_ms = 0;\n        TS_Data.StartTime = \"\";\n        TS_Data.EndTime = \"\";\n        TS_Data.Dur =0;\n        TS_Data.Valid = false;\n        global.set(TopicName, TS_Data);\n        node.status({fill:\"red\",shape:\"dot\",text:\"R_Trig NOT Received\"});\n        return null;\n        \n    } else if ((TS_Data.F_ms > TS_Data.R_ms) && (TS_Data.R_ms > 0)) {\n        // F_Trig Received after R_Trig (good)\n        // Get new timestamp\n        ts = new Date(msg.payload);\n        TS_Data.EndTime = new Date(ts.getTime() - ts.getTimezoneOffset() * 60000).toISOString().replace('T', ' ').substr(0, 19);\n        \n        TS_Data.Dur = Number(((TS_Data.F_ms - TS_Data.R_ms) / 60000).toFixed(2));\n        TS_Data.Valid = true;\n        global.set(TopicName, TS_Data);\n        node.status({fill:\"green\",shape:\"dot\",text:\"Done \"});\n        msg.topic = TopicName;  \n        msg.payload = TS_Data;\n        return msg;\n        \n    } else {\n        // Error - Clear all data\n        TS_Data.R_ms = 0;\n        TS_Data.F_ms = 0;\n        TS_Data.StartTime = \"\";\n        TS_Data.EndTime = \"\";\n        TS_Data.Dur =0;\n        TS_Data.Valid = false;\n        global.set(TopicName, TS_Data);\n        node.status({fill:\"red\",shape:\"ring\",text:\"Error\"});\n        return null;\n    }\n    \n}\n\n//node.status({});   // to clear the status\n\n","outputs":1,"noerr":0,"x":910,"y":220,"wires":[["d49cbb34.913418"]]},{"id":"63f9cb01.fa0fd4","type":"inject","z":"34e707bd.f201b8","d":true,"name":"On","topic":"","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":200,"wires":[["d3d60357.3d77d","6021b437.eebcdc"]]},{"id":"187f2db9.72a2d2","type":"inject","z":"34e707bd.f201b8","d":true,"name":"Off","topic":"","payload":"false","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":260,"wires":[["6021b437.eebcdc","d3d60357.3d77d"]]},{"id":"6021b437.eebcdc","type":"trigger","z":"34e707bd.f201b8","op1":"false","op2":"0","op1type":"bool","op2type":"str","duration":"0","extend":false,"units":"ms","reset":"true","bytopic":"all","name":"F_Trig","x":530,"y":260,"wires":[["e8b30cb6.a1112"]]},{"id":"d3d60357.3d77d","type":"trigger","z":"34e707bd.f201b8","op1":"true","op2":"0","op1type":"bool","op2type":"str","duration":"0","extend":false,"units":"ms","reset":"false","bytopic":"all","name":"R_Trig","x":530,"y":200,"wires":[["9811ad47.516ca"]]},{"id":"e8b30cb6.a1112","type":"change","z":"34e707bd.f201b8","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"F_Trig","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":260,"wires":[["4c112160.9d261"]]},{"id":"9811ad47.516ca","type":"change","z":"34e707bd.f201b8","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"R_Trig","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":200,"wires":[["4c112160.9d261"]]},{"id":"67db6300.1da7ac","type":"status","z":"34e707bd.f201b8","name":"","scope":null,"x":900,"y":280,"wires":[[]]},{"id":"5e9749cb.6a8178","type":"tab","label":"Flow 7","disabled":false,"info":""},{"id":"680bc089.1e416","type":"debug","z":"5e9749cb.6a8178","name":"L_Rng_Data Debug3","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1320,"y":640,"wires":[]},{"id":"f785d5ab.5a5618","type":"function","z":"5e9749cb.6a8178","name":"Calc TS Data","func":"// Calculates the time data for when msg.payload is true. This\n// function calculates the duration of the pulse while true due to the\n// upstream rising / falling trigger nodes which set the topic.\n\nvar TS_Data = env.get(\"TS_Data\");  \nvar TopicName = \"TS_Data\"\nvar ts;\n\n// Get TS_Data \nif(global.get(\"TS_Data\") === undefined){\n    TS_Data = {\n        \"Topic\": TopicName,\n        \"R_ms\": 0,\n        \"F_ms\": 0,\n        \"StartTime\": 0,\n        \"EndTime\": 0,\n        \"Dur\": 0,\n        \"Valid\": false\n    }\n } else {\n     TS_Data = global.get(TopicName);\n }\n\n// Process R_Trig timestamp and set to invalid\nif (msg.topic === \"R_Trig\") {\n    \n    TS_Data.R_ms = msg.payload;\n    // R_Trig Received\n    // Get new timestamp\n    ts = new Date(msg.payload);\n    TS_Data.StartTime = new Date(ts.getTime() - ts.getTimezoneOffset() * 60000).toISOString().replace('T', ' ').substr(0, 19);\n    \n    // Clear falling data\n    TS_Data.F_ms = \"\";\n    TS_Data.EndTime = \"\";\n    TS_Data.Dur = 0;\n    TS_Data.Valid = \"In Progress\";\n    global.set(TopicName, TS_Data);\n    node.status({fill:\"yellow\",shape:\"ring\",text:\"Waiting for F_Trig\"});\n    msg.topic = TopicName;  \n    msg.payload = TS_Data;\n    return msg;\n}\n\n// Process F_Trig timestamp and check validity\nif (msg.topic === \"F_Trig\") {\n    TS_Data.F_ms = msg.payload;\n    \n    if (TS_Data.R_ms === 0) {\n        // R_Trig NOT Received before F_Trig\n        TS_Data.R_ms = 0;\n        TS_Data.F_ms = 0;\n        TS_Data.StartTime = \"\";\n        TS_Data.EndTime = \"\";\n        TS_Data.Dur =0;\n        TS_Data.Valid = false;\n        global.set(TopicName, TS_Data);\n        node.status({fill:\"red\",shape:\"dot\",text:\"R_Trig NOT Received\"});\n        return null;\n        \n    } else if ((TS_Data.F_ms > TS_Data.R_ms) && (TS_Data.R_ms > 0)) {\n        // F_Trig Received after R_Trig (good)\n        // Get new timestamp\n        ts = new Date(msg.payload);\n        TS_Data.EndTime = new Date(ts.getTime() - ts.getTimezoneOffset() * 60000).toISOString().replace('T', ' ').substr(0, 19);\n        \n        TS_Data.Dur = Number(((TS_Data.F_ms - TS_Data.R_ms) / 60000).toFixed(2));\n        TS_Data.Valid = true;\n        global.set(TopicName, TS_Data);\n        node.status({fill:\"green\",shape:\"dot\",text:\"Done \"});\n        msg.topic = TopicName;  \n        msg.payload = TS_Data;\n        return msg;\n        \n    } else {\n        // Error - Clear all data\n        TS_Data.R_ms = 0;\n        TS_Data.F_ms = 0;\n        TS_Data.StartTime = \"\";\n        TS_Data.EndTime = \"\";\n        TS_Data.Dur =0;\n        TS_Data.Valid = false;\n        global.set(TopicName, TS_Data);\n        node.status({fill:\"red\",shape:\"ring\",text:\"Error\"});\n        return null;\n    }\n    \n}\n\n//node.status({});   // to clear the status\n\n","outputs":1,"noerr":0,"x":950,"y":640,"wires":[["680bc089.1e416"]]},{"id":"2ee80916.f0fec6","type":"inject","z":"5e9749cb.6a8178","name":"L_Rng_On","topic":"","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":300,"y":620,"wires":[["aa124d56.07732","857d865c.c028d8"]]},{"id":"85b709f2.597f38","type":"inject","z":"5e9749cb.6a8178","name":"L_Rng_Off","topic":"","payload":"false","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":300,"y":680,"wires":[["857d865c.c028d8","aa124d56.07732"]]},{"id":"857d865c.c028d8","type":"trigger","z":"5e9749cb.6a8178","op1":"false","op2":"0","op1type":"bool","op2type":"str","duration":"0","extend":false,"units":"ms","reset":"true","bytopic":"all","name":"F_Trig","x":570,"y":680,"wires":[["e71c2191.00dde"]]},{"id":"aa124d56.07732","type":"trigger","z":"5e9749cb.6a8178","op1":"true","op2":"0","op1type":"bool","op2type":"str","duration":"0","extend":false,"units":"ms","reset":"false","bytopic":"all","name":"R_Trig","x":570,"y":620,"wires":[["c3762f1d.2d549"]]},{"id":"e71c2191.00dde","type":"change","z":"5e9749cb.6a8178","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"F_Trig","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":740,"y":680,"wires":[["f785d5ab.5a5618"]]},{"id":"c3762f1d.2d549","type":"change","z":"5e9749cb.6a8178","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"R_Trig","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":740,"y":620,"wires":[["f785d5ab.5a5618"]]},{"id":"9068c5fb.8fc208","type":"inject","z":"5e9749cb.6a8178","name":"On1","topic":"","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":290,"y":380,"wires":[["7a6956e2.af8698"]]},{"id":"56c72afe.7d5a74","type":"inject","z":"5e9749cb.6a8178","name":"Off1","topic":"","payload":"false","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":290,"y":420,"wires":[["7a6956e2.af8698"]]},{"id":"fe043789.0d0268","type":"debug","z":"5e9749cb.6a8178","name":"L_Rng_Data Debug1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":740,"y":400,"wires":[]},{"id":"7a6956e2.af8698","type":"subflow:34e707bd.f201b8","z":"5e9749cb.6a8178","name":"","env":[{"name":"TS_Data","value":"RngTmr","type":"str"},{"name":"TopicName","value":"RngTmr","type":"str"},{"name":"Topic_Name","value":"RngTmr","type":"str"}],"x":510,"y":400,"wires":[["fe043789.0d0268"]]},{"id":"1e07083c.555eb8","type":"comment","z":"5e9749cb.6a8178","name":"-----------------------------------  Main Flow -----------------------------------------------","info":"","x":760,"y":580,"wires":[]},{"id":"9d6ebed8.39933","type":"comment","z":"5e9749cb.6a8178","name":"Sub Flow","info":"","x":520,"y":360,"wires":[]}]

Anomaly:
I noticed a slight difference in how the status information is displayed beside the function in a flow versus when a sub flow is used. When I click twice on an inject node, the status message disappears, and it shouldn’t. It works correctly using the same function node in a flow.

Questions:

  • Why does the status information disappear in the sub flow when I click twice on the inject node but works correctly in a regular flow? (I am using the same code in both function nodes.)
  • Also, is it possible to have a context node, flow, or global variable associated to each sub flow - TS_Data JSON object? Right now, it seems like ONLY the GLOBAL context works?
  • I am currently passing two env variables to my sub flow: TS_Data and TopicName. TopicName is actually the name of the variable, ie “TS_Data”. Originally I thought I could do this by setting TopicName = ${TS_Data} or TopicName = $TS_Data, but neither way seems to work. Is there a way of doing this so that the env variable TopicName is not required?

Thanks for taking the time to look at this!

Good news! I managed to solve the the first question by changing the internal status node from "All" to the specific node that I want to monitor. I think one of the other nodes (R_Trig or F_Trig) were sending an empty "text" when they were triggered and over riding the status.

Did some more testing on the other two . . . but no progress.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.