A new "watchdog" node. (Time out? Trigger?)

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.

Updated version:

Version 2.
Double message at start removed. Silly mistake on my part.

Slightly improved the nodes and the workings.

Fixed another bug that when you have Repeat set, you get an output at the same time as the other node. Now there is a delay before you receive the first repeated message.

New code:

[{"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":240,"wires":[{"id":"fa5b277c.02e8d","port":0}]},{"x":840,"y":190,"wires":[{"id":"a50330bd.11ebc8","port":0}]},{"x":840,"y":400,"wires":[{"id":"8e11acf.ab6c85","port":0}]},{"x":840,"y":140,"wires":[{"id":"4cd334b3.f53a1c","port":0}]},{"x":840,"y":470,"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","790dc2aa.838214","9866d51a.ad2e1","94449624.5472b"],["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":390,"y":340,"wires":[[]]},{"id":"9f9155b2.e30a1","type":"trigger","z":"55861e64.8bd218","name":"","op1":"","op2":"0","op1type":"nul","op2type":"str","duration":"5","extend":true,"overrideDelay":true,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":400,"y":200,"wires":[["a50330bd.11ebc8"]]},{"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":410,"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":580,"y":200,"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":580,"y":240,"wires":[["60da0d5e.e1a484"]]},{"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":620,"y":300,"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":410,"y":240,"wires":[["fa5b277c.02e8d"]]},{"id":"4563bc68.7f338c","type":"catch","z":"55861e64.8bd218","name":"","scope":null,"uncaught":false,"x":710,"y":470,"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":600,"y":160,"wires":[[]]},{"id":"25a84715.51fb78","type":"link out","z":"55861e64.8bd218","name":"Start","links":["dcf5f793.7dd0b"],"x":675,"y":220,"wires":[]},{"id":"dcf5f793.7dd0b","type":"link in","z":"55861e64.8bd218","name":"Start","links":["25a84715.51fb78"],"x":305,"y":400,"wires":[["6f0d5093.ae4e6"]]},{"id":"41c3e8ea.6e9d","type":"trigger","z":"55861e64.8bd218","name":"Repeat","op1":"1","op2":"0","op1type":"str","op2type":"str","duration":"-5","extend":false,"overrideDelay":true,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":615,"y":400,"wires":[["8e11acf.ab6c85"]],"l":false},{"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":465,"y":440,"wires":[["41c3e8ea.6e9d","4932c24d.75b71c"]],"l":false},{"id":"60da0d5e.e1a484","type":"link out","z":"55861e64.8bd218","name":"Stop","links":["9ddb508b.a11a88"],"x":675,"y":260,"wires":[]},{"id":"9ddb508b.a11a88","type":"link in","z":"55861e64.8bd218","name":"Stop","links":["60da0d5e.e1a484"],"x":415,"y":440,"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":720,"y":400,"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":410,"y":400,"wires":[["4932c24d.75b71c"]]},{"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":"9866d51a.ad2e1","type":"switch","z":"55861e64.8bd218","name":"PassThrough?","property":"PassThrough","propertyType":"flow","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":420,"y":300,"wires":[["e7e7c5df.ecd478"]]},{"id":"4932c24d.75b71c","type":"delay","z":"55861e64.8bd218","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":545,"y":400,"wires":[["41c3e8ea.6e9d"]],"l":false},{"id":"77a37d9e.9e231c","type":"comment","z":"55861e64.8bd218","name":"Repeated message output","info":"","x":700,"y":360,"wires":[]},{"id":"c24fe52c.e68bf","type":"subflow:55861e64.8bd218","z":"2b69bd59.6754f2","name":"","x":1050,"y":4230,"wires":[["e7231979.3304d"],["db5d83f2.94d628"],["2ad148ed.ac20b"],["d49ea71e.eaec58"],[]]}]

Can you describe in words what it does please?

Thanks Colin. I am not proficient at this.

What the node does/is used for:

Given:
You receive messages at an interval.

These indicate things are good. If they stop, things are bad.

This node receives messages (which need to have msg.delay to determine/set a time which is greater than the interval between messages) and on-sends the/a message. More on this shortly.

You can select if the original message is sent or a defined message.
This way you can use the original message past this node.
Or you can use the output of the node to feed into more nodes that detect and act on what is sent on from this node.

If a message isn't received and the time expires, another message is sent (on another output pin).

Another option is to have the message indicating no message received to be repeatedly sent out on another output.

There is also an output to indicate/echo the change in the delay time.

Also an output for any errors which happen in the subflow.

err - isn't that just a wire that goes past the node... not everything needs to go via the trigger node :slight_smile: .

Just configure the node not to send the first message - and extend delay before sending the latest object - if you need repeated failure messages that is just another trigger node set to repeat - and cleared when the input starts again...

[{"id":"2c6acea2.b47582","type":"inject","z":"ba6c3622.ce6758","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"dev_id\":\"70B3D57050006F77\"},{\"dev_id\":\"70A3C57050006F76\"},{\"dev_id\":\"24E1641094172783\"}]","payloadType":"json","x":130,"y":880,"wires":[["733d9591.b8b4ac","c467feb6.da903","bf363d5.9e779c"]]},{"id":"733d9591.b8b4ac","type":"trigger","z":"ba6c3622.ce6758","name":"","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"5","extend":true,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":2,"x":340,"y":920,"wires":[["bf363d5.9e779c"],["6b84b35a.280d0c"]]},{"id":"c467feb6.da903","type":"change","z":"ba6c3622.ce6758","name":"","rules":[{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":980,"wires":[["6b84b35a.280d0c"]]},{"id":"bf363d5.9e779c","type":"debug","z":"ba6c3622.ce6758","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":730,"y":880,"wires":[]},{"id":"6b84b35a.280d0c","type":"trigger","z":"ba6c3622.ce6758","name":"","op1":"","op2":"0","op1type":"pay","op2type":"str","duration":"-10","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":530,"y":980,"wires":[["bf363d5.9e779c"]]}]

Shouldn't this topic be renamed as;

"A new “watchdog” flow. (Time out? Trigger?)"

It's not a node.

Well - it is packaged as a subflow - and until we have "export subflow to node" capability it's fairly close.

1 Like

Yes, that is true, but you can't change the messages sent for either condition on the fly.
(Not that you would)

It is (was) about 8 hours of brain work trying to get that working as neatly as it is.
Though I do get that neatly is subjective.

I have a lot of instances where this is needed and rather than all the 3 nodes you show to do it, I wanted to make a sub-flow that has a bit more flexibility and so should be more useful to more people.

You are right with the "drop the first part" for the trigger node. I kind of learnt that the painful way and so was fixed in my second release.

It would seem even when I have a clear (well: as clear as I could get it) that it took me about 8 hours and I still kinda goofed.

3 nodes compared to the 15 I used.

I also spent a lot of time trying all the other similar nodes and they all lacked something in one way or another.

In hind sight I see I could use those nodes but their way of editing their config for the time waiting needs a new message which isn't that much different to how I set my node up.

Oh well.

It was an effort. I'm not sure what I learnt from it.

I guess I am also a bit distracted with trying to get MQTT working on that other post/thread and this was a need which was calling out.

Thanks.