# How to Only respond to 2nd message (within time window)

**URL:** <https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320>\
**Category:** General\
**Created:** [31 December 2020 12:17 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320 "2020-12-31T12:17:20Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![rekcodocker](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rekcodocker/32/31833_2.png) [@rekcodocker](https://discourse.nodered.org/u/rekcodocker)\
**Post date:** [31 December 2020 12:17 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/1 "2020-12-31T12:17:21Z")

</div>

It looks like 'node-red-contrib-join-wait' could do this but I do not need to join messages from different paths; and I want to be sure there is no simpler way.

I have a motion sensor and I do not want a light to trigger on the first motion-message; only when it receives a second motion message within a couple of minutes.  
I want it a little less 'triggerhappy'.

I was trying out some combos with delay and the powerful 'trigger' nodes, but it does not quite do what I want. I need this:

- if a message arrives, delay it and start a timer;
- if a second message arrives within the timer window, forward it immediately;
- if the timer expires, the node resets
- if a reset arrives, the node reset.

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [31 December 2020 13:10 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/2 "2020-12-31T13:10:42Z")

</div>

Try something like this, to reset set flow.time to 0

```auto
[{"id":"dc4124a4.3d357","type":"inject","z":"8d22ae29.7df6d","name":"","props":[{"p":"payload"},{"p":"delay","v":"3000","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":140,"y":2180,"wires":[["6577879e.0f24"]]},{"id":"6577879e.0f24","type":"switch","z":"8d22ae29.7df6d","name":"","property":"time","propertyType":"flow","rules":[{"t":"jsonata_exp","v":"$millis() - $flowContext(\"time\") < delay","vt":"jsonata"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":270,"y":2180,"wires":[["c62865e.8bb9798"],["9a405fcf.440928"]]},{"id":"9a405fcf.440928","type":"change","z":"8d22ae29.7df6d","name":"","rules":[{"t":"set","p":"time","pt":"flow","to":"$millis()","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":2220,"wires":[[]]},{"id":"c62865e.8bb9798","type":"change","z":"8d22ae29.7df6d","name":"","rules":[{"t":"set","p":"time","pt":"flow","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":2140,"wires":[["dcd8ea98.f4e16"]]},{"id":"dcd8ea98.f4e16","type":"debug","z":"8d22ae29.7df6d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":570,"y":2080,"wires":[]}]

```

---

<div class="post-metadata">

**Author:** ![rekcodocker](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rekcodocker/32/31833_2.png) [@rekcodocker](https://discourse.nodered.org/u/rekcodocker)\
**Post date:** [1 January 2021 00:34 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/3 "2021-01-01T00:34:55Z")

</div>

Wow! that's a good trick!  
I ended up coding it, after all. Javascript can do exactly what I want.

This outputs the 1st message to the 1st output and the second and all following messages to a second output.  
Wait for 10 seconds and it resets - and will block the first message again.  
It also resets on a 'reset' message.  
It's a kind of debounce but instead of dropping the 2nd message, it drops the 1st.  
It called 'I insist' because you need to trigger it twice to get through.

````auto
[{"id":"5077248c.5ead5c","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"11cda614.9dc72a","type":"inject","z":"5077248c.5ead5c","name":"","props":[{"p":"payload.occupancy","v":"false","vt":"bool"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":120,"y":200,"wires":[["aea06469.6ec938"]]},{"id":"251c14fa.54998c","type":"debug","z":"5077248c.5ead5c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":640,"y":220,"wires":[]},{"id":"8a0485e2.5fa118","type":"inject","z":"5077248c.5ead5c","name":"true","props":[{"p":"payload.occupancy","v":"true","vt":"bool"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":280,"wires":[["aea06469.6ec938"]]},{"id":"e11b04c4.e8dd08","type":"inject","z":"5077248c.5ead5c","name":"reset","props":[{"p":"reset","v":"true","vt":"bool"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":140,"wires":[["aea06469.6ec938"]]},{"id":"aea06469.6ec938","type":"function","z":"5077248c.5ead5c","name":"I Insist","func":"// input:\n// messages. \n// Send only 2nd and following message within a given timeframe.\n// reset after 'msg reset'\n// reset if time window expires\n\n// implementation: node keeps track of a state. It can be in either one of \n// two modes: holding or Passthrough.\n// Holding mode: when it receives a message it does not send, but goes to Passthrough mode.\n// Passthrough mode:\n// Every message received will be sent on.\n// After N minutes after the last message, the node will leave Passthrough mode and fall back to Holding mode.\n// every message resets the timer, so it takes N mins without messages to fall back to Holding mode\n\nconst BLOCK=1;\nconst PASSTHROUGH=2;\n\nvar now = Date.now();\nvar startTimer=context.get('starttimer')||now;\nvar mode=context.get('mode')||BLOCK; \n\nnewMsg=[null,null];\n// case: Message has arrived.\n// handle reset message: Go to mode BLOCK\nif (msg.hasOwnProperty('reset') && msg.reset!=false)\n{\n mode=BLOCK;\n node.status({fill:\"blue\",shape:\"ring\",text:\"reset. now blocking.\"});\n newMsg=[null,null];\n}\nelse // regular message, either block or forward it. \n{\n // check timer for expiration, since we do not have a callback when it expires. First time we check is on this message-event.\n if (mode==PASSTHROUGH && (now-startTimer) > 10*1000)\n {\n // timer expired. kill message and go to mode BLOCK\n mode=BLOCK;\n }\n \n if (mode==BLOCK)\n {\n // discard message. change mode. set timer.\n mode=PASSTHROUGH;\n startTimer=now;\n node.status({fill:\"yellow\",shape:\"ring\",text:\"blocked 1 msg\"});\n newMsg=[msg,null];\n }\n else\n {\n // mode is passthrough. \n // reset timer\n startTimer=now;\n node.status({fill:\"green\",shape:\"ring\",text:\"forwarded 1 or more msg\"});\n newMsg=[null,msg];\n }\n} \n\ncontext.set('mode', mode);\ncontext.set('starttimer', startTimer);\nreturn(newMsg);","outputs":2,"noerr":0,"initialize":"","finalize":"","x":370,"y":220,"wires":[["251c14fa.54998c"],["251c14fa.54998c"]],"outputLabels":["First message ","Next messages"]}]```
````

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [1 January 2021 00:39 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/4 "2021-01-01T00:39:24Z")

</div>

Do you need the time to be variable?

If not, what would be wrong with this try:

```auto
[{"id":"d8da1b21.0a152","type":"inject","z":"703c61ac.837e1","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1900,"y":670,"wires":[["45dd677b.59b1a8"]]},{"id":"45dd677b.59b1a8","type":"trigger","z":"703c61ac.837e1","name":"","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"250","extend":false,"overrideDelay":false,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":2100,"y":670,"wires":[["867ba56d.f744a"]]},{"id":"867ba56d.f744a","type":"debug","z":"703c61ac.837e1","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":2310,"y":670,"wires":[]}]

```

---

<div class="post-metadata">

**Author:** ![wb666greene](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/wb666greene/32/6534_2.png) [@wb666greene](https://discourse.nodered.org/u/wb666greene)\
**Post date:** [3 January 2021 16:25 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/5 "2021-01-03T16:25:47Z")

</div>

Thanks, something like this has been on my TODO list for too long a time. This gets me most of the way there.

For my AI person detection security system the first detection image is often not the best because the person's head can be cut off when first walking into the camera field of view, since there will be more images a fraction of a second later, the later images are generally "better" to push as MMS text or Email notifications.

This gets me most of the way there, if only one message comes in during the interval I'll send it after the delay, but with multiple messages in the interval, the second or third is generally better.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [3 January 2021 17:50 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/6 "2021-01-03T17:50:03Z")

</div>

for something like video though won't the standard trigger node work ? set it to send latest msg.payload as the second message - so the first detection triggers it (don't send anything)- then x frames/seconds later it sends the latest it has (rather than the original)?

---

<div class="post-metadata">

**Author:** ![wb666greene](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/wb666greene/32/6534_2.png) [@wb666greene](https://discourse.nodered.org/u/wb666greene)\
**Post date:** [4 January 2021 15:18 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/7 "2021-01-04T15:18:01Z")

</div>

I haven't fully investigated the trigger node, but it seems to lack the behavior of sending the original message (image) if a second doesn't come within the interval.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [4 January 2021 15:39 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/8 "2021-01-04T15:39:46Z")

</div>

if set to send latest - then yes of course if nothing else arrives it will send the original as that was still the latest to arrive...

---

<div class="post-metadata">

**Author:** ![greengolfer](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/greengolfer/32/28276_2.png) [@greengolfer](https://discourse.nodered.org/u/greengolfer)\
**Post date:** [4 January 2021 15:41 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/9 "2021-01-04T15:41:52Z")

</div>

The node-red-contrib-queue-gate is doing (I think) what you are looking for.  
From [https://github.com/drmibell/node-red-contrib-queue-gate:](https://github.com/drmibell/node-red-contrib-queue-gate:)

### Save Most Recent Message (since version 1.1.0)

This flow, as noted above, saves the most recent message in the queue and releases it when a `trigger` , `flush` , or `open` command is received. (Note that if the `open` command is used, the gate will remain open until a `queue` or `default` command is received to restore the original mode of operation.) The `q-gate` is configured with `Default State = queueing` , `Maximum Queue Length = 1` , and `Keep Newest Messages = true` .

So, if further messages are received, they can replace the old ones and if nothing arrives within the time frame you can flush the queue and you will get what is the most recent message available.

---

<div class="post-metadata">

**Author:** ![wb666greene](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/wb666greene/32/6534_2.png) [@wb666greene](https://discourse.nodered.org/u/wb666greene)\
**Post date:** [4 January 2021 23:56 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/10 "2021-01-04T23:56:00Z")

</div>

Thanks, lots of new ideas to try. But I'm more comfortable inside function nodes at the moment.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [5 March 2021 23:56 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/11 "2021-03-05T23:56:08Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [27 April 2025 06:27 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/12 "2025-04-27T06:27:00Z")

</div>



---

<div class="post-metadata">

**Author:** ![DiverRich](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/diverrich/32/64523_2.png) [@DiverRich](https://discourse.nodered.org/u/DiverRich)\
**Post date:** [27 April 2025 06:53 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/13 "2025-04-27T06:53:15Z")

</div>

@E1cid

I'm using your clever flow to monitor several window and door contact sensors. If they switch to a new state for longer than 30 seconds, then Alexa announces that the specific door or window sensor is open or closed. I was using a couple of trigger nodes and reset nodes (see below) and that worked great, except it would ultimately always make an announcement of some sort.

 ![Screenshot 2025-04-26 at 11.51.21 PM](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/3/d35096e202fa94713b98aeeb5cb802d737544cd9.png)

```auto
[{"id":"c3ff746c4dd5d8a3","type":"group","z":"b5a44a6b8fa524cc","style":{"stroke":"#2b2b2b","stroke-opacity":"1","fill":"#181818","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#cccccc"},"nodes":["3a2d7a1c82fdcead","6bc937df4c81a157","fe8e5cd980ce8d89","4b50fa847e306f12","36ca26d642338046","9930e99214c0ce15","02d661c3d89456ef","ec8563aa69a61bbd","eb16e8047bf1330f"],"x":734,"y":3799,"w":892,"h":222},{"id":"3a2d7a1c82fdcead","type":"trigger","z":"b5a44a6b8fa524cc","g":"c3ff746c4dd5d8a3","name":"30 seconds","op1":"","op2":"","op1type":"nul","op2type":"pay","duration":"30","extend":true,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":1235,"y":3840,"wires":[["02d661c3d89456ef"]],"icon":"node-red-contrib-bigtimer/timer.png","l":false},{"id":"6bc937df4c81a157","type":"switch","z":"b5a44a6b8fa524cc","g":"c3ff746c4dd5d8a3","name":"Open/Closed","property":"payload.value","propertyType":"msg","rules":[{"t":"eq","v":"open","vt":"str"},{"t":"eq","v":"closed","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":990,"y":3900,"wires":[["3a2d7a1c82fdcead","4b50fa847e306f12"],["36ca26d642338046","fe8e5cd980ce8d89"]]},{"id":"fe8e5cd980ce8d89","type":"change","z":"b5a44a6b8fa524cc","g":"c3ff746c4dd5d8a3","name":"RESET","rules":[{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1235,"y":3880,"wires":[["3a2d7a1c82fdcead"]],"icon":"font-awesome/fa-refresh","l":false},{"id":"4b50fa847e306f12","type":"change","z":"b5a44a6b8fa524cc","g":"c3ff746c4dd5d8a3","name":"RESET","rules":[{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1235,"y":3940,"wires":[["36ca26d642338046"]],"icon":"font-awesome/fa-refresh","l":false},{"id":"36ca26d642338046","type":"trigger","z":"b5a44a6b8fa524cc","g":"c3ff746c4dd5d8a3","name":"30 seconds","op1":"","op2":"","op1type":"nul","op2type":"pay","duration":"30","extend":true,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":1235,"y":3980,"wires":[["02d661c3d89456ef"]],"icon":"node-red-contrib-bigtimer/timer.png","l":false},{"id":"9930e99214c0ce15","type":"debug","z":"b5a44a6b8fa524cc","g":"c3ff746c4dd5d8a3","name":"","active":false,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":1530,"y":3940,"wires":[]},{"id":"02d661c3d89456ef","type":"junction","z":"b5a44a6b8fa524cc","g":"c3ff746c4dd5d8a3","x":1400,"y":3900,"wires":[["9930e99214c0ce15","eb16e8047bf1330f"]]},{"id":"ec8563aa69a61bbd","type":"no-op","z":"b5a44a6b8fa524cc","g":"c3ff746c4dd5d8a3","name":"Input","x":810,"y":3900,"wires":[["6bc937df4c81a157"]]},{"id":"eb16e8047bf1330f","type":"no-op","z":"b5a44a6b8fa524cc","g":"c3ff746c4dd5d8a3","name":"Output","x":1540,"y":3860,"wires":[[]]}]

```

With your solution I can suppress the voice response completely if, for example, I open and close the door quickly \<30 seconds. I put it all in a sub flow (attached below) that works perfectly for my application, so thank you for that!

 ![Screenshot 2025-04-26 at 11.49.15 PM](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/4/14ee33d03e183278885289339a4a7d828b888ed4.png)

```auto
[{"id":"fcf98f412ee79100","type":"subflow","name":"flow.time","info":"","category":"","in":[{"x":160,"y":380,"wires":[{"id":"15f35af014d11b59"}]}],"out":[{"x":1260,"y":380,"wires":[{"id":"79dfadac8f91a73e","port":0}]}],"env":[],"meta":{},"color":"#C0DEED","icon":"node-red-contrib-sun-position/clock-timer-black.svg","status":{"x":500,"y":200,"wires":[{"id":"9f9bf40dd470511a","port":0}]}},{"id":"79dfadac8f91a73e","type":"junction","z":"fcf98f412ee79100","x":1180,"y":380,"wires":[[]]},{"id":"4e75361f0a901ccc","type":"junction","z":"fcf98f412ee79100","x":560,"y":440,"wires":[["fbd7f895fc7d1649","1a34d71f5baa7435"]]},{"id":"6eae251ab423fbd6","type":"junction","z":"fcf98f412ee79100","x":560,"y":320,"wires":[["fbd7f895fc7d1649","5403d70877f4991b"]]},{"id":"843d83cf9799160b","type":"junction","z":"fcf98f412ee79100","x":1000,"y":380,"wires":[["051a4af02423a941"]]},{"id":"5403d70877f4991b","type":"junction","z":"fcf98f412ee79100","x":920,"y":320,"wires":[["843d83cf9799160b"]]},{"id":"1a34d71f5baa7435","type":"junction","z":"fcf98f412ee79100","x":920,"y":440,"wires":[["843d83cf9799160b"]]},{"id":"15f35af014d11b59","type":"switch","z":"fcf98f412ee79100","name":"Open/Closed","property":"payload.value","propertyType":"msg","rules":[{"t":"eq","v":"open","vt":"str"},{"t":"eq","v":"closed","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":320,"y":380,"wires":[["6eae251ab423fbd6"],["4e75361f0a901ccc"]]},{"id":"fbd7f895fc7d1649","type":"switch","z":"fcf98f412ee79100","name":"","property":"time","propertyType":"flow","rules":[{"t":"jsonata_exp","v":"$millis() - $flowContext(\"time\") < 30000","vt":"jsonata"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":635,"y":380,"wires":[["aae3bc4e29be85e9"],["64787c1de8b159bf"]],"l":false},{"id":"64787c1de8b159bf","type":"change","z":"fcf98f412ee79100","name":"","rules":[{"t":"set","p":"time","pt":"flow","to":"$millis()","tot":"jsonata"},{"t":"set","p":"topic","pt":"msg","to":"topic","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":400,"wires":[[]]},{"id":"aae3bc4e29be85e9","type":"change","z":"fcf98f412ee79100","name":"","rules":[{"t":"set","p":"time","pt":"flow","to":"0","tot":"num"},{"t":"set","p":"topic","pt":"msg","to":"topic","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":360,"wires":[["2b2e6fdcc5ce87e3"]]},{"id":"9f9bf40dd470511a","type":"status","z":"fcf98f412ee79100","name":"","scope":["051a4af02423a941"],"x":220,"y":200,"wires":[[]]},{"id":"051a4af02423a941","type":"trigger","z":"fcf98f412ee79100","name":"31 seconds","op1":"","op2":"","op1type":"nul","op2type":"pay","duration":"31","extend":true,"overrideDelay":false,"units":"s","reset":"","bytopic":"topic","topic":"topic","outputs":1,"x":1095,"y":380,"wires":[["79dfadac8f91a73e"]],"icon":"node-red-contrib-bigtimer/timer.png","l":false},{"id":"2b2e6fdcc5ce87e3","type":"change","z":"fcf98f412ee79100","name":"RESET","rules":[{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":905,"y":380,"wires":[["843d83cf9799160b"]],"icon":"font-awesome/fa-refresh","l":false}]

```

Now, me being the curious sort that I am and you being the clever sort that you are, made me wonder if there is an easy way to make this work based on topic. Basically, instead of putting the subflow node after every sensor node, I'm wondering if there is a way to just wire all of the sensor nodes to one subflow node and have it keep track based on topic. (Currently, if I were to do that and, for example, open all of my windows, it would just skip every other window.)

In my brain, it seems like it should be doable, but I'd likely make it much more complex than it's worth.

Cheers,

Rich

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [27 April 2025 06:57 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/14 "2025-04-27T06:57:54Z")

</div>

Here is an example of setting up the response based on msg.topic.

```auto
[{"id":"dc4124a4.3d357","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"delay","v":"3000","vt":"num"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"one","payload":"one","payloadType":"str","x":510,"y":4920,"wires":[["6577879e.0f24"]]},{"id":"6577879e.0f24","type":"switch","z":"d1395164b4eec73e","name":"","property":"time","propertyType":"flow","rules":[{"t":"jsonata_exp","v":"$millis() - $flowContext(\"time.\" & $$.topic) < delay","vt":"jsonata"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":640,"y":4920,"wires":[["c62865e.8bb9798"],["9a405fcf.440928"]]},{"id":"3f81275caaca1f95","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"delay","v":"3000","vt":"num"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"two","payload":"two","payloadType":"str","x":510,"y":4960,"wires":[["6577879e.0f24"]]},{"id":"c62865e.8bb9798","type":"change","z":"d1395164b4eec73e","name":"","rules":[{"t":"set","p":"time[msg.topic]","pt":"flow","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":820,"y":4880,"wires":[["dcd8ea98.f4e16"]]},{"id":"9a405fcf.440928","type":"change","z":"d1395164b4eec73e","name":"","rules":[{"t":"set","p":"time[msg.topic]","pt":"flow","to":"$millis()","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":820,"y":4960,"wires":[[]]},{"id":"dcd8ea98.f4e16","type":"debug","z":"d1395164b4eec73e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":940,"y":4820,"wires":[]}]

```

If you regularly change topics delete the flow context time var, this is so the context var does not become bloated with old topics.

---

<div class="post-metadata">

**Author:** ![DiverRich](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/diverrich/32/64523_2.png) [@DiverRich](https://discourse.nodered.org/u/DiverRich)\
**Post date:** [27 April 2025 08:39 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/15 "2025-04-27T08:39:16Z")

</div>

Very cool thanks for taking the time to satisfy my curiosity. Just a note for anyone who tries this, it works perfectly as long as the topic has no spaces in it. The spaces will generate an error:

 ![Screenshot 2025-04-27 at 1.06.16 AM](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/c/cc64a773c2bf3b1b93c0f7a2a682818b840eb6a3.png)

In my case, I'm using Hubitat. What's happening is when you create a Hubitat node it autofills the node name with the device name from Hubitat. Then the topic is created from the node name. So, if the device name has spaces and you don't change the node name, then the resulting topic will throw the error.

In this example, changing the node name to something like "Sliding\_Glass\_Door" will eliminate the error. Of course for me, on account of Murphy's Law and all, changing the node name breaks other stuff down stream. Notwithstanding, this is a pretty slick method.

 ![Screenshot 2025-04-27 at 1.19.09 AM](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/7/37b8f7cf02a195204f8dd66351032510942cc476.png)

---

<div class="post-metadata">

**Author:** ![Sean-McG](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sean-mcg/32/54677_2.png) [@Sean-McG](https://discourse.nodered.org/u/Sean-McG)\
**Post date:** [27 April 2025 17:37 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/16 "2025-04-27T17:37:28Z")

</div>

This is easily fixed by changing topic before and after like this -

```auto
[{"id":"8e3067222da0dbc6","type":"inject","z":"87795ba7e17af83e","name":"","props":[{"p":"payload"},{"p":"delay","v":"3000","vt":"num"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"one with space","payload":"one","payloadType":"str","x":490,"y":640,"wires":[["sanitize_topic"]]},{"id":"e91212fd46c2d697","type":"inject","z":"87795ba7e17af83e","name":"","props":[{"p":"payload"},{"p":"delay","v":"3000","vt":"num"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"two two","payload":"two","payloadType":"str","x":510,"y":700,"wires":[["sanitize_topic"]]},{"id":"sanitize_topic","type":"function","z":"87795ba7e17af83e","name":"Sanitize Topic","func":"msg.originalTopic = msg.topic;\nmsg.topic = msg.topic.replace(/\\s+/g, '_');\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":720,"y":680,"wires":[["a32de1ae7af3d667"]]},{"id":"a32de1ae7af3d667","type":"switch","z":"87795ba7e17af83e","name":"","property":"time","propertyType":"flow","rules":[{"t":"jsonata_exp","v":"$millis() - $flowContext(\"time.\" & $$.topic) < delay","vt":"jsonata"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":890,"y":680,"wires":[["0a179c051d1a1729"],["38d224d7d48cb14e"]]},{"id":"0a179c051d1a1729","type":"change","z":"87795ba7e17af83e","name":"","rules":[{"t":"set","p":"time[msg.topic]","pt":"flow","to":"0","tot":"num"},{"t":"set","p":"topic","pt":"msg","to":"originalTopic","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1120,"y":660,"wires":[["c1044222bebb6cbe"]]},{"id":"38d224d7d48cb14e","type":"change","z":"87795ba7e17af83e","name":"","rules":[{"t":"set","p":"time[msg.topic]","pt":"flow","to":"$millis()","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1150,"y":740,"wires":[[]]},{"id":"c1044222bebb6cbe","type":"debug","z":"87795ba7e17af83e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1350,"y":620,"wires":[]}]

```

---

<div class="post-metadata">

**Author:** ![DiverRich](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/diverrich/32/64523_2.png) [@DiverRich](https://discourse.nodered.org/u/DiverRich)\
**Post date:** [28 April 2025 01:19 UTC](https://discourse.nodered.org/t/how-to-only-respond-to-2nd-message-within-time-window/38320/17 "2025-04-28T01:19:45Z")

</div>

It sure does. Thanks!
