# Ideas for elapsed time counter please

**URL:** <https://discourse.nodered.org/t/ideas-for-elapsed-time-counter-please/35352>\
**Category:** General\
**Created:** [5 November 2020 03:43 UTC](https://discourse.nodered.org/t/ideas-for-elapsed-time-counter-please/35352 "2020-11-05T03:43:32Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![JGKK](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jgkk/32/18515_2.png) [@JGKK](https://discourse.nodered.org/u/JGKK)\
**Post date:** [5 November 2020 08:34 UTC](https://discourse.nodered.org/t/ideas-for-elapsed-time-counter-please/35352/2 "2020-11-05T08:34:24Z")

</div>

Hello,  
Maybe this could be useful for you. It’s not a custom node but nearly 😉  
This is a subflow I build:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/4/64a0c5aa9fdba95378b8aa30d1368f6e3eb3c1d5.jpeg)

```auto
[{"id":"60288551.9399d4","type":"subflow","name":"elapsedTime","info":"","category":"","in":[{"x":60,"y":60,"wires":[{"id":"2cdff5f2.09a772"}]}],"out":[{"x":620,"y":60,"wires":[{"id":"287cb861.3f1bc","port":0}]}],"env":[{"name":"targetTime","type":"num","value":"0","ui":{"icon":"font-awesome/fa-history","label":{"en-US":"Target Time"},"type":"input","opts":{"types":["num"]}}}],"color":"#DDAA99","status":{"x":620,"y":140,"wires":[{"id":"4ff652da.75a3bc","port":0}]}},{"id":"d1cc3968.edcc9","type":"inject","z":"60288551.9399d4","name":"","props":[{"p":"payload"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"tick","payloadType":"str","x":110,"y":140,"wires":[["2cdff5f2.09a772"]]},{"id":"2cdff5f2.09a772","type":"function","z":"60288551.9399d4","name":"Timer","func":"const targetTime = env.get(\"targetTime\");\nlet elapsedTime = flow.get(\"elapsedTime\") || 0;\nconst runningNow = flow.get(\"runningNow\") || false;\nswitch (msg.payload) {\n case \"start\":\n if (!runningNow && elapsedTime !== targetTime) {\n flow.set(\"runningNow\", true);\n msg.payload = \"start\";\n msg.targetTime = targetTime;\n msg.elapsedTime = elapsedTime;\n msg.topic = \"output\";\n } else {\n msg.payload = false;\n }\n break;\n case \"stop\":\n if (runningNow && elapsedTime !== targetTime) {\n flow.set(\"runningNow\", false);\n node.send({payload:\"stop\",topic:\"output\",targetTime:targetTime,elapsedTime:elapsedTime});\n msg.payload = \"stopped at \" + elapsedTime + \"s elapsed of \" + targetTime + \"s target\";\n } else {\n msg.payload = false;\n }\n break;\n case \"reset\":\n if (elapsedTime !== 0) { flow.set(\"elapsedTime\", 0) }\n msg.payload = \"elapsed time reset, now 0s of \" + targetTime + \"s target elapsed\";\n break;\n case \"tick\":\n if (runningNow && elapsedTime + 1 < targetTime) {\n elapsedTime += 1;\n flow.set(\"elapsedTime\", elapsedTime);\n msg.payload = \"elapsed time: \" + elapsedTime + \"s of \" + targetTime + \"s target\";\n } else if (runningNow && elapsedTime + 1 >= targetTime) {\n flow.set(\"elapsedTime\", elapsedTime + 1);\n flow.set(\"runningNow\", false);\n node.send({payload:\"stop\",topic:\"output\",targetTime:targetTime,elapsedTime:elapsedTime + 1});\n msg.payload = targetTime + \"s target reached\";\n } else {\n msg.payload = false;\n }\n break;\n}\nif (!msg.payload) { return null; }\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":250,"y":60,"wires":[["4ff652da.75a3bc","287cb861.3f1bc"]]},{"id":"4ff652da.75a3bc","type":"function","z":"60288551.9399d4","name":"status format","func":"let status = {};\nstatus.text = msg.payload;\nif(flow.get(\"runningNow\")){\n status.fill = \"green\";\n status.shape = \"dot\";\n} else {\n status.fill = \"yellow\";\n status.shape = \"ring\";\n}\nmsg.payload = status;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":470,"y":140,"wires":[[]]},{"id":"287cb861.3f1bc","type":"function","z":"60288551.9399d4","name":"OutputFormat","func":"if (msg.topic === \"output\") {\n if (msg.elapsedTime !== msg.targetTime) {\n msg.targetReached = false;\n } else {\n msg.targetReached = true;\n }\n return msg;\n} else {\n return null;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","x":480,"y":60,"wires":[[]]},{"id":"66de909d.3817d8","type":"subflow:60288551.9399d4","z":"235a0def.b0da5a","name":"","env":[{"name":"targetTime","value":"12","type":"num"}],"x":510,"y":720,"wires":[["5584e6cb.4a2878"]]},{"id":"12f62a63.78df76","type":"inject","z":"235a0def.b0da5a","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"start","payloadType":"str","x":290,"y":720,"wires":[["66de909d.3817d8"]]},{"id":"224caa7b.0e5e0e","type":"inject","z":"235a0def.b0da5a","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"stop","payloadType":"str","x":290,"y":780,"wires":[["66de909d.3817d8"]]},{"id":"78fc7f60.6fe248","type":"inject","z":"235a0def.b0da5a","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"reset","payloadType":"str","x":290,"y":840,"wires":[["66de909d.3817d8"]]},{"id":"5584e6cb.4a2878","type":"debug","z":"235a0def.b0da5a","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":730,"y":720,"wires":[]}]

```

You can configure your target time in the subflow menu.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/4/54f065bf86a16bd747dca4aef3bf3d4822dc6560.jpeg)  
If you send **start** as a `msg.payload` It will start the timer running and send a `msg.payload` of **start** from the subflow which will than run until it reaches the configured target time upon which the subflow will send a `msg.payload` of **stop** and stop the timer.  
You can also stop/pause it at any point with a `msg.payload` of **stop** which will stop/pause the timer and also send a `msg.payload` of **stop** from the subflow.  
Each **start** or **stop** payload send from the subflow also includes a handful of other useful `msg` properties:  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/2/12cd0184759bae2b4e1f4d2e6692dc2ff85ce702.jpeg)  
every `msg` object has a `msg.targetTime` property which shows the the value of the set target time. in addition there is a `msg.ellapsedTime` property which is the time that the timer has already run towards the configure target. Lastly there is also a Boolean value in `msg.targetReached` which is **false** as long as the elapsed time is below the target time and becomes **true** in the final `msg` send by the subflow when the target time is reached.

Finally to **reset** the the elapsed time simply simply send a `msg.payload` of **reset** to the subflow which will reset the elapsed time to 0.

The subflow is based on an inject node that sends a _tick_ every second within the subflow. When a **start** message is received a flow var within the subflow gets set to true. As long as this runningNow var is true the subflow adds to the elapsed time based on its internal tick. As soon as a **stop** is send or the target is reached the runningNow var becomes false again and counting stops. The subflow also shows the progress in its status below the node.  
Here are its internals:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/9/29245f67fac4b12763e3c6cbf4a0f1233e1bff54.jpeg)  
If you would want to change the subflow to minute accuracy you would only have to change the tick inject to inject every minute. This would probably be more appropriate for your usecase.

Maybe you can salvage the basic principle of this subflow for your pool pump.

Johannes

---

_[View the full topic](https://discourse.nodered.org/t/ideas-for-elapsed-time-counter-please/35352)._
