This is a sub-flow more than a node, but I don't think there is much difference.
Standard nodes used.
Idea:
The trigger
node is so close to what I want, but lacks a couple of things.
One being that it doesn't on-send the incoming messages.
It would seem it is only good to detect a failure of messages arriving.
There are other nodes out there but they also have their own set of quirks.
Like adjusting/setting the delay time.
Though this could be worked around with little extra effort than what my nodes needs with setting up.... I thought I would try this.
Known bug/s:
You will get undefined
for the first message if you pass through the message. As it is a one off it isn't crucial in the scheme of things. Subsequent messages work.
Other things:
If you have the Repeat
option set and you want to stop it:
Inject a command to turn off the Repeat
and then send a non-command message.
That will then reset the sending of the Failed
message.
This has a slight drawback in that you get another sequence of the start/stop messges.
But I feel in reality this will/would/should not be needed.
But if you are working on/with the node and it is spitting out the repeat Failed
message and you want to stop it: That is how you do it.
Node:
[{"id":"55861e64.8bd218","type":"subflow","name":"Watchdog","info":"Open and read the README node.\n","category":"","in":[{"x":90,"y":250,"wires":[{"id":"4ecfcb6a.96244c"}]}],"out":[{"x":840,"y":230,"wires":[{"id":"fa5b277c.02e8d","port":0}]},{"x":840,"y":170,"wires":[{"id":"a50330bd.11ebc8","port":0}]},{"x":840,"y":340,"wires":[{"id":"8e11acf.ab6c85","port":0}]},{"x":840,"y":120,"wires":[{"id":"4cd334b3.f53a1c","port":0}]},{"x":840,"y":410,"wires":[{"id":"4563bc68.7f338c","port":0}]}],"env":[],"color":"#DD5500","outputLabels":["Start message","End message","Repeat Fail Message","Show `delay` value","Errors"],"icon":"node-red/timer.svg"},{"id":"4ecfcb6a.96244c","type":"switch","z":"55861e64.8bd218","name":"topic","property":"topic","propertyType":"msg","rules":[{"t":"neq","v":"SETUP","vt":"str"},{"t":"eq","v":"SETUP","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":200,"y":250,"wires":[["9f9155b2.e30a1","84cd97ae.18e13","790dc2aa.838214"],["6be4227f.552854"]]},{"id":"6be4227f.552854","type":"change","z":"55861e64.8bd218","name":"Setup","rules":[{"t":"move","p":"StartMsg","pt":"msg","to":"StartMsg","tot":"flow"},{"t":"move","p":"EndMsg","pt":"msg","to":"EndMsg","tot":"flow"},{"t":"move","p":"PassThrough","pt":"msg","to":"PassThrough","tot":"flow"},{"t":"move","p":"Repeat","pt":"msg","to":"Repeat","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":290,"wires":[[]]},{"id":"9f9155b2.e30a1","type":"trigger","z":"55861e64.8bd218","name":"","op1":"1","op2":"0","op1type":"str","op2type":"str","duration":"250","extend":true,"overrideDelay":true,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":360,"y":200,"wires":[["1c803396.704324"]]},{"id":"84cd97ae.18e13","type":"switch","z":"55861e64.8bd218","name":"normal message","property":"topic","propertyType":"msg","rules":[{"t":"neq","v":"SETUP","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":360,"y":250,"wires":[["3e2f57f4.c6f38","94449624.5472b"]]},{"id":"1c803396.704324","type":"switch","z":"55861e64.8bd218","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"eq","v":"1","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":520,"y":200,"wires":[["a50330bd.11ebc8"],["fa5b277c.02e8d"]]},{"id":"790dc2aa.838214","type":"switch","z":"55861e64.8bd218","name":"New delay?","property":"delay","propertyType":"msg","rules":[{"t":"nempty"}],"checkall":"true","repair":false,"outputs":1,"x":350,"y":160,"wires":[["4cd334b3.f53a1c"]]},{"id":"a50330bd.11ebc8","type":"function","z":"55861e64.8bd218","name":"BAD","func":"let j = flow.get(\"EndMsg\");\nif (j == undefined)\n{\n j = \"End message\";\n}\nmsg.payload = j;\n\nlet delay = flow.get(\"DELAY\") || 0;\nif (delay > 0)\n{\n msg.delay = delay;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":710,"y":170,"wires":[["25a84715.51fb78"]]},{"id":"fa5b277c.02e8d","type":"function","z":"55861e64.8bd218","name":"GOOD","func":"let j = flow.get(\"StartMsg\");\nif (j == undefined)\n{\n j = \"Start message\";\n}\nmsg.payload = j;\nif (flow.get(\"PassThrough\") == true)\n{\n msg.payload = flow.get(\"SavedMessage\");\n}\n\nlet delay = flow.get(\"DELAY\") || 0;\nif (delay > 0)\n{\n msg.delay = delay;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":710,"y":230,"wires":[["60da0d5e.e1a484"]]},{"id":"3e2f57f4.c6f38","type":"switch","z":"55861e64.8bd218","name":"PassThrough?","property":"PassThrough","propertyType":"flow","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":550,"y":290,"wires":[["e7e7c5df.ecd478"]]},{"id":"e7e7c5df.ecd478","type":"change","z":"55861e64.8bd218","name":"","rules":[{"t":"move","p":"payload","pt":"msg","to":"SavedMessage","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":290,"wires":[[]]},{"id":"94449624.5472b","type":"delay","z":"55861e64.8bd218","name":"Slight delay","pauseType":"delay","timeout":"500","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":540,"y":250,"wires":[["fa5b277c.02e8d"]]},{"id":"4563bc68.7f338c","type":"catch","z":"55861e64.8bd218","name":"","scope":null,"uncaught":false,"x":710,"y":410,"wires":[[]]},{"id":"4cd334b3.f53a1c","type":"change","z":"55861e64.8bd218","name":"Store delay","rules":[{"t":"set","p":"payload","pt":"msg","to":"DELAY","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":540,"y":160,"wires":[[]]},{"id":"25a84715.51fb78","type":"link out","z":"55861e64.8bd218","name":"Start","links":["dcf5f793.7dd0b"],"x":785,"y":190,"wires":[]},{"id":"dcf5f793.7dd0b","type":"link in","z":"55861e64.8bd218","name":"Start","links":["25a84715.51fb78"],"x":235,"y":340,"wires":[["6f0d5093.ae4e6"]]},{"id":"41c3e8ea.6e9d","type":"trigger","z":"55861e64.8bd218","name":"Repeat","op1":"1","op2":"0","op1type":"str","op2type":"str","duration":"-250","extend":false,"overrideDelay":true,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":530,"y":340,"wires":[["8e11acf.ab6c85"]]},{"id":"eea41a37.1b739","type":"change","z":"55861e64.8bd218","name":"Stop","rules":[{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":415,"y":380,"wires":[["41c3e8ea.6e9d"]],"l":false},{"id":"60da0d5e.e1a484","type":"link out","z":"55861e64.8bd218","name":"Stop","links":["9ddb508b.a11a88"],"x":795,"y":260,"wires":[]},{"id":"9ddb508b.a11a88","type":"link in","z":"55861e64.8bd218","name":"Stop","links":["60da0d5e.e1a484"],"x":365,"y":380,"wires":[["eea41a37.1b739"]]},{"id":"8e11acf.ab6c85","type":"function","z":"55861e64.8bd218","name":"BAD","func":"let j = flow.get(\"EndMsg\");\nif (j == undefined)\n{\n j = \"End message\";\n}\nmsg.payload = j;\n\nlet delay = flow.get(\"DELAY\") || 0;\nif (delay > 0)\n{\n msg.delay = delay;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":710,"y":340,"wires":[[]]},{"id":"6f0d5093.ae4e6","type":"function","z":"55861e64.8bd218","name":"Repeat set?","func":"let x = flow.get(\"Repeat\") || 0;\nif (x == 0)\n{\n return;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":350,"y":340,"wires":[["41c3e8ea.6e9d"]]},{"id":"36e3093d.bf0d9e","type":"comment","z":"55861e64.8bd218","name":"Read me *","info":"This node is not *designed* to be constantly re-configured.\nThe message to set things up is expected to be a **ONE OFF** message sent at the start.\nThe delay is dynamic and can be changed with any normal message.\n\nThe `delay` time is set in the normal message as `msg.delay` and is honoured for all subsequent messages and for the repeat time.\n\nTo configure this you send a message with the topic of `SETUP`\n\nOptions are:\n`msg.StartMsg` - Message sent if things are good\n`msg.EndMsg` - Message sent if no messages are received in the time period\n`msg.PassThrough` - (Boolean)\nIf `true` the message arriving is used rather than the `StartMsg`.\nIf `false` when an input is received the `StartMsg` is sent.\n`msg.Repeat` - (Numbers)\nIf `1` the `EndMsg` will be sent out repeatedly if no messages are received in the time period\nIf `0` nothing is done\n\n\nOutputs:\n1 - The message when things are good. (Messages received within the `delay` time.)\n2 - The message that is sent if no messages are received in the `delay` time.\n3 - If configured earlier to set the Repeat option, this output sends out the `EndMsg` at intervals set by `msg.delay`\n4 - Echos the `msg.delay` value. Just so you can check.\n5 - Any errors.","x":190,"y":60,"wires":[]},{"id":"c24fe52c.e68bf","type":"subflow:55861e64.8bd218","z":"2b69bd59.6754f2","name":"","x":770,"y":4230,"wires":[["e7231979.3304d"],["db5d83f2.94d628"],["2ad148ed.ac20b"],[],[]]}]
Example flow:
[{"id":"55861e64.8bd218","type":"subflow","name":"Watchdog","info":"Open and read the README node.\n","category":"","in":[{"x":90,"y":250,"wires":[{"id":"4ecfcb6a.96244c"}]}],"out":[{"x":840,"y":230,"wires":[{"id":"fa5b277c.02e8d","port":0}]},{"x":840,"y":170,"wires":[{"id":"a50330bd.11ebc8","port":0}]},{"x":840,"y":340,"wires":[{"id":"8e11acf.ab6c85","port":0}]},{"x":840,"y":120,"wires":[{"id":"4cd334b3.f53a1c","port":0}]},{"x":840,"y":410,"wires":[{"id":"4563bc68.7f338c","port":0}]}],"env":[],"color":"#DD5500","outputLabels":["Start message","End message","Repeat Fail Message","Show `delay` value","Errors"],"icon":"node-red/timer.svg"},{"id":"4ecfcb6a.96244c","type":"switch","z":"55861e64.8bd218","name":"topic","property":"topic","propertyType":"msg","rules":[{"t":"neq","v":"SETUP","vt":"str"},{"t":"eq","v":"SETUP","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":200,"y":250,"wires":[["9f9155b2.e30a1","84cd97ae.18e13","790dc2aa.838214"],["6be4227f.552854"]]},{"id":"6be4227f.552854","type":"change","z":"55861e64.8bd218","name":"Setup","rules":[{"t":"move","p":"StartMsg","pt":"msg","to":"StartMsg","tot":"flow"},{"t":"move","p":"EndMsg","pt":"msg","to":"EndMsg","tot":"flow"},{"t":"move","p":"PassThrough","pt":"msg","to":"PassThrough","tot":"flow"},{"t":"move","p":"Repeat","pt":"msg","to":"Repeat","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":290,"wires":[[]]},{"id":"9f9155b2.e30a1","type":"trigger","z":"55861e64.8bd218","name":"","op1":"1","op2":"0","op1type":"str","op2type":"str","duration":"250","extend":true,"overrideDelay":true,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":360,"y":200,"wires":[["1c803396.704324"]]},{"id":"84cd97ae.18e13","type":"switch","z":"55861e64.8bd218","name":"normal message","property":"topic","propertyType":"msg","rules":[{"t":"neq","v":"SETUP","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":360,"y":250,"wires":[["3e2f57f4.c6f38","94449624.5472b"]]},{"id":"1c803396.704324","type":"switch","z":"55861e64.8bd218","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"eq","v":"1","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":520,"y":200,"wires":[["a50330bd.11ebc8"],["fa5b277c.02e8d"]]},{"id":"790dc2aa.838214","type":"switch","z":"55861e64.8bd218","name":"New delay?","property":"delay","propertyType":"msg","rules":[{"t":"nempty"}],"checkall":"true","repair":false,"outputs":1,"x":350,"y":160,"wires":[["4cd334b3.f53a1c"]]},{"id":"a50330bd.11ebc8","type":"function","z":"55861e64.8bd218","name":"BAD","func":"let j = flow.get(\"EndMsg\");\nif (j == undefined)\n{\n j = \"End message\";\n}\nmsg.payload = j;\n\nlet delay = flow.get(\"DELAY\") || 0;\nif (delay > 0)\n{\n msg.delay = delay;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":710,"y":170,"wires":[["25a84715.51fb78"]]},{"id":"fa5b277c.02e8d","type":"function","z":"55861e64.8bd218","name":"GOOD","func":"let j = flow.get(\"StartMsg\");\nif (j == undefined)\n{\n j = \"Start message\";\n}\nmsg.payload = j;\nif (flow.get(\"PassThrough\") == true)\n{\n msg.payload = flow.get(\"SavedMessage\");\n}\n\nlet delay = flow.get(\"DELAY\") || 0;\nif (delay > 0)\n{\n msg.delay = delay;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":710,"y":230,"wires":[["60da0d5e.e1a484"]]},{"id":"3e2f57f4.c6f38","type":"switch","z":"55861e64.8bd218","name":"PassThrough?","property":"PassThrough","propertyType":"flow","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":550,"y":290,"wires":[["e7e7c5df.ecd478"]]},{"id":"e7e7c5df.ecd478","type":"change","z":"55861e64.8bd218","name":"","rules":[{"t":"move","p":"payload","pt":"msg","to":"SavedMessage","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":290,"wires":[[]]},{"id":"94449624.5472b","type":"delay","z":"55861e64.8bd218","name":"Slight delay","pauseType":"delay","timeout":"500","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":540,"y":250,"wires":[["fa5b277c.02e8d"]]},{"id":"4563bc68.7f338c","type":"catch","z":"55861e64.8bd218","name":"","scope":null,"uncaught":false,"x":710,"y":410,"wires":[[]]},{"id":"4cd334b3.f53a1c","type":"change","z":"55861e64.8bd218","name":"Store delay","rules":[{"t":"set","p":"payload","pt":"msg","to":"DELAY","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":540,"y":160,"wires":[[]]},{"id":"25a84715.51fb78","type":"link out","z":"55861e64.8bd218","name":"Start","links":["dcf5f793.7dd0b"],"x":785,"y":190,"wires":[]},{"id":"dcf5f793.7dd0b","type":"link in","z":"55861e64.8bd218","name":"Start","links":["25a84715.51fb78"],"x":235,"y":340,"wires":[["6f0d5093.ae4e6"]]},{"id":"41c3e8ea.6e9d","type":"trigger","z":"55861e64.8bd218","name":"Repeat","op1":"1","op2":"0","op1type":"str","op2type":"str","duration":"-250","extend":false,"overrideDelay":true,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":530,"y":340,"wires":[["8e11acf.ab6c85"]]},{"id":"eea41a37.1b739","type":"change","z":"55861e64.8bd218","name":"Stop","rules":[{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":415,"y":380,"wires":[["41c3e8ea.6e9d"]],"l":false},{"id":"60da0d5e.e1a484","type":"link out","z":"55861e64.8bd218","name":"Stop","links":["9ddb508b.a11a88"],"x":795,"y":260,"wires":[]},{"id":"9ddb508b.a11a88","type":"link in","z":"55861e64.8bd218","name":"Stop","links":["60da0d5e.e1a484"],"x":365,"y":380,"wires":[["eea41a37.1b739"]]},{"id":"8e11acf.ab6c85","type":"function","z":"55861e64.8bd218","name":"BAD","func":"let j = flow.get(\"EndMsg\");\nif (j == undefined)\n{\n j = \"End message\";\n}\nmsg.payload = j;\n\nlet delay = flow.get(\"DELAY\") || 0;\nif (delay > 0)\n{\n msg.delay = delay;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":710,"y":340,"wires":[[]]},{"id":"6f0d5093.ae4e6","type":"function","z":"55861e64.8bd218","name":"Repeat set?","func":"let x = flow.get(\"Repeat\") || 0;\nif (x == 0)\n{\n return;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":350,"y":340,"wires":[["41c3e8ea.6e9d"]]},{"id":"36e3093d.bf0d9e","type":"comment","z":"55861e64.8bd218","name":"Read me *","info":"This node is not *designed* to be constantly re-configured.\nThe message to set things up is expected to be a **ONE OFF** message sent at the start.\nThe delay is dynamic and can be changed with any normal message.\n\nThe `delay` time is set in the normal message as `msg.delay` and is honoured for all subsequent messages and for the repeat time.\n\nTo configure this you send a message with the topic of `SETUP`\n\nOptions are:\n`msg.StartMsg` - Message sent if things are good\n`msg.EndMsg` - Message sent if no messages are received in the time period\n`msg.PassThrough` - (Boolean)\nIf `true` the message arriving is used rather than the `StartMsg`.\nIf `false` when an input is received the `StartMsg` is sent.\n`msg.Repeat` - (Numbers)\nIf `1` the `EndMsg` will be sent out repeatedly if no messages are received in the time period\nIf `0` nothing is done\n\n\nOutputs:\n1 - The message when things are good. (Messages received within the `delay` time.)\n2 - The message that is sent if no messages are received in the `delay` time.\n3 - If configured earlier to set the Repeat option, this output sends out the `EndMsg` at intervals set by `msg.delay`\n4 - Echos the `msg.delay` value. Just so you can check.\n5 - Any errors.","x":190,"y":60,"wires":[]},{"id":"c24fe52c.e68bf","type":"subflow:55861e64.8bd218","z":"2b69bd59.6754f2","name":"","x":1050,"y":4230,"wires":[["e7231979.3304d"],["db5d83f2.94d628"],["2ad148ed.ac20b"],[],[]]},{"id":"27b6e965.24ec9e","type":"inject","z":"2b69bd59.6754f2","name":"Edit `delay` to adjust value of delay/timeout","props":[{"p":"payload"},{"p":"delay","v":"5000","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":770,"y":4230,"wires":[["c24fe52c.e68bf"]]},{"id":"e7231979.3304d","type":"debug","z":"2b69bd59.6754f2","name":"Good","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1250,"y":4180,"wires":[]},{"id":"db5d83f2.94d628","type":"debug","z":"2b69bd59.6754f2","name":"Bad","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1250,"y":4220,"wires":[]},{"id":"2ad148ed.ac20b","type":"debug","z":"2b69bd59.6754f2","name":"Repeat","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1260,"y":4260,"wires":[]},{"id":"a1936f44.be8be","type":"inject","z":"2b69bd59.6754f2","name":"Repeat if timeout","props":[{"p":"topic","vt":"str"},{"p":"Repeat","v":"1","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"SETUP","x":820,"y":4290,"wires":[["c24fe52c.e68bf"]]},{"id":"bb8d342.baf42c8","type":"inject","z":"2b69bd59.6754f2","name":"Do not repeat if timeout","props":[{"p":"topic","vt":"str"},{"p":"Repeat","v":"0","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"SETUP","x":800,"y":4330,"wires":[["c24fe52c.e68bf"]]},{"id":"967212e3.d4b6d","type":"inject","z":"2b69bd59.6754f2","name":"Start and End messages","props":[{"p":"topic","vt":"str"},{"p":"StartMsg","v":"All things are good","vt":"str"},{"p":"EndMsg","v":"Things have got worse","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"SETUP","payloadType":"str","x":790,"y":4380,"wires":[["c24fe52c.e68bf"]]},{"id":"af2dfd27.b0956","type":"inject","z":"2b69bd59.6754f2","name":"Use default message for OK","props":[{"p":"topic","vt":"str"},{"p":"PassThrough","v":"false","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"SETUP","x":780,"y":4450,"wires":[["c24fe52c.e68bf"]]},{"id":"707769a6.0a746","type":"inject","z":"2b69bd59.6754f2","name":"Passthrough message if OK","props":[{"p":"topic","vt":"str"},{"p":"PassThrough","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"SETUP","x":780,"y":4490,"wires":[["c24fe52c.e68bf"]]},{"id":"269ab468.841ae4","type":"comment","z":"2b69bd59.6754f2","name":"Any combination of these.","info":"","x":520,"y":4380,"wires":[]}]
P.S.
Yes, it would be nicer if the Repeat
could be controlled with true
and false
inputs rather than 0
and 1
.
Originally I tried that but for reasons unknown to me, I couldn't get it to work in the sub-flow.
But it would work if I had it out of the subflow.
The double message/undefined
could be because the slight delay
isn't long enough.
and the context isn't set by that stage.