Looking for feedback on flow design - measuring elapsed time with Shelly EM

Hi!
I'm building a solution that let's us verify at a glance if some heating elements have been turned on (and not malfunctioned) for a predetermined time.

ie I set the electromechanical timer for 5h and let the heating element heat. When I come back the next day I want to verify that it really heated for at least 5h. I'm using Shelly EM elements to measure the consumed power.

So the Shellies send ~0W most of the time, as each machine has it's own electrical circuit.
When I turn the timer on the heating element draws 100W and when the timer turns off the consumption goes back to ~0W.

My plan is to generate a timestamp when consumption goes over 100W, unblock the stop trigger, so it can generate a timestamp when the consumption goes under 100W. To avoid triggering too easily I have a smooth node that averages 10 latest values.

Once the cycle has completed I'll reset the time calculation manually - so also the gate and the triggers.

My flow is as follows:

It uses a few custom nodes:
node-red-node-smooth to pass on the average of last 10ish readings, to weed out random errors
node-red-contrib-shelly to communicate with the shelly (could be done directly with mqtt as well)
node-red-contrib-simple-gate to block generating stop timestamp before the start timestamp has been generated

[{"id":"821607c2e9020d15","type":"shelly-gen1","z":"452ab868.195118","hostname":"192.168.1.151","description":"A & B","pollinginterval":"10000","pollstatus":true,"getstatusoncommand":true,"devicetype":"Measure","outputs":2,"x":710,"y":860,"wires":[["25e2a970d7b8f5bf"],[]]},{"id":"25e2a970d7b8f5bf","type":"change","z":"452ab868.195118","name":"Select W","rules":[{"t":"move","p":"payload.emeters[0].power","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":720,"y":940,"wires":[["89074d5994c7a130"]]},{"id":"89074d5994c7a130","type":"rbe","z":"452ab868.195118","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":true,"property":"payload","topi":"topic","x":710,"y":1000,"wires":[["39b43ebfd131e3e1"]]},{"id":"2dacbb961efd608b","type":"trigger","z":"452ab868.195118","name":"start timestamp","op1":"","op2":"0","op1type":"date","op2type":"str","duration":"0","extend":false,"overrideDelay":false,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":1180,"y":1000,"wires":[["2d2b791756cded63","c3eda38b31f8f3fd"]]},{"id":"f468ec71a6996ebc","type":"switch","z":"452ab868.195118","name":"if >100","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"100","vt":"num"},{"t":"lt","v":"100","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":870,"y":1040,"wires":[["2dacbb961efd608b"],[]]},{"id":"39b43ebfd131e3e1","type":"smooth","z":"452ab868.195118","name":"","property":"payload","action":"mean","count":"10","round":"1","mult":"single","reduce":true,"x":720,"y":1060,"wires":[["f468ec71a6996ebc","f922cf8d6c4be0fb"]]},{"id":"fb665f00b6be17af","type":"trigger","z":"452ab868.195118","name":"stop timestamp","op1":"","op2":"0","op1type":"date","op2type":"str","duration":"0","extend":false,"overrideDelay":false,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":1180,"y":1160,"wires":[["8da96d449d6eabb4","c3eda38b31f8f3fd"]]},{"id":"2d2b791756cded63","type":"change","z":"452ab868.195118","name":"open gate after start","rules":[{"t":"set","p":"topic","pt":"msg","to":"control","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"open","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1180,"y":1080,"wires":[["2a041f0878c3ea2f"]]},{"id":"2a041f0878c3ea2f","type":"gate","z":"452ab868.195118","name":"","controlTopic":"control","defaultState":"closed","openCmd":"open","closeCmd":"close","toggleCmd":"toggle","defaultCmd":"default","statusCmd":"status","persist":true,"storeName":"memory","x":1010,"y":1160,"wires":[["fb665f00b6be17af"]]},{"id":"f922cf8d6c4be0fb","type":"switch","z":"452ab868.195118","name":"if <100","property":"payload","propertyType":"msg","rules":[{"t":"lt","v":"100","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":870,"y":1080,"wires":[["2a041f0878c3ea2f"]]},{"id":"8da96d449d6eabb4","type":"change","z":"452ab868.195118","name":"close gate","rules":[{"t":"set","p":"payload","pt":"msg","to":"close","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"control","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1170,"y":1260,"wires":[["2a041f0878c3ea2f"]]},{"id":"c3eda38b31f8f3fd","type":"function","z":"452ab868.195118","name":"elapsed time calculation","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1490,"y":1060,"wires":[[]]}]

My question is: does this look like a working solution? Would there be important bottlenecks that are glaringly obvious? Also, I have 10 measures like this to set up.

Have you considered first visualising the data, before starting to write logic to measure it? I understand that your specific application may not require this, but doing so would shine a light very quickly on things you may not had considered about the data. Not only when setting up your flows, but when you encounter some unexpected thing later, it will provide immediate insight into the data so you can adjust your logic. Also your flow gives no history, so if something failed you can't recalculate later. Setting up visualisation takes time, but it is like setting up a proper work light in the attic if you plan to do any real work up there - worth the effort in the long run.

I use a Shelly EM to monitor 2 circuits; they send data periodically over MQTT to Node-RED where I then log this data to a database called Influx and then visualise in Grafana. When I say "visualise", this means I can monitor energy in realtime, and from the same view, zoom in on historic data from any period since the beginning of logging.

When you say "weed out random errors", in my experience you don't get random errors when measuring energy usage with a Shelly EM. You may get spikes in power, but visualising this will help you determine how long / when those spikes occur so you can account for them if necessary.

If it's a simple heating (i.e. without some compressor or other additional electronics) then it's likely there may be some inrush current which causes a spike, but this won't be seen on the power reading from the Shelly if it starts and ends between readings. Note that it would be reflected in the total usage, as the Shelly has a counter.

To answer your question specifically, I highly doubt there will be bottlenecks: Node-RED will work orders of magnitude faster than anything you are measuring, but I really do suggest that visualising energy usage will be the best starting point, before attempting any logic (e.g. notifications when something doesn't happen, time measurement, etc.)

You'll find a couple of youtube videos on the subject of Shelly EM + Node-RED + Influx + Grafana.

Hope that helps

1 Like

I use email node and gates to send me messages when my sensor gets out of sync with my microcontroller its connected to.
it will monitor the sensor messages and when i stop getting them it sends me an email that it stopped working and runs a command that reboots microcontroller and then it sends me an email when the sensor is working again.
its a little different then what you need but you can look how I have the gates set up and maybe that ill help you a little.

[{"id":"d50ab6a9776ef7f6","type":"group","z":"feb81af7b09dad8f","name":"Temp Sensor Baby sitting","style":{"stroke":"#000000","fill":"#bfdbef","label":true,"color":"#000000"},"nodes":["c9a4e0d4b6c5042c","9c00ad97c966f557","4928a645f26be602","d42b47999508ef83","331b43f05fab6bd7","dd2166660e680c5a","80db6d7ce0a73136","2696ab962dbc3f47","55e1e3c5b3a45ee2","a27ddc8a076702fb","507fb0823a730f67","25a88a2078b27790","f3c5617e7e4a4ec8","7521d3575e8440d8","3d23ee7a79f6b44c","cd751f44f02830ad","1419d602fb0988da","2ec07b2bba965498","bf6c587da4d44d2f","79cfdcb0c099ff05","49c243e555497be6","4420592fe68663bb","0d4cfbea95fa05c2","29579fd684d75db0"],"x":693.4998788833618,"y":1397.1709451675415,"w":1349.4999380111694,"h":476.829083442688},{"id":"c9a4e0d4b6c5042c","type":"inject","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"cmnd/Eferm/RESTART","payload":"1","payloadType":"num","x":1292.9999694824219,"y":1643.3333559036255,"wires":[["9c00ad97c966f557"]]},{"id":"9c00ad97c966f557","type":"ui_button","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"","group":"efd7b7c424179c82","order":1,"width":0,"height":0,"passthru":true,"label":"REBOOT","tooltip":"","color":"","bgcolor":"","icon":"","payload":"1","payloadType":"str","topic":"cmnd/Eferm/RESTART","x":1503.9999694824219,"y":1516.333327293396,"wires":[["2696ab962dbc3f47"]]},{"id":"4928a645f26be602","type":"trigger","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"","op1":"East sensor working","op2":"On","op1type":"str","op2type":"str","duration":"60","extend":true,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":2,"x":991.999885559082,"y":1510.0000200271606,"wires":[["331b43f05fab6bd7","dd2166660e680c5a","cd751f44f02830ad"],["d42b47999508ef83","9c00ad97c966f557","507fb0823a730f67","4420592fe68663bb"]]},{"id":"d42b47999508ef83","type":"debug","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"badsensor","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1189.9999694824219,"y":1599.333327293396,"wires":[]},{"id":"331b43f05fab6bd7","type":"debug","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"sensor good","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1089.6542701721191,"y":1438.1709451675415,"wires":[]},{"id":"dd2166660e680c5a","type":"e-mail","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","server":"smtp.gmail.com","port":"465","secure":true,"tls":true,"name":"railhoperrors@gmail.com","dname":"","x":1323.2009811401367,"y":1489.4270515441895,"wires":[]},{"id":"80db6d7ce0a73136","type":"link in","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"","links":["7c4cbc1a995ee8c7"],"x":734.4998788833618,"y":1511.0000200271606,"wires":[["4928a645f26be602","bf6c587da4d44d2f"]]},{"id":"2696ab962dbc3f47","type":"mqtt out","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"","topic":"cmnd/Eferm/RESTART","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"31a99116.50a74e","x":1772.9999694824219,"y":1521.333327293396,"wires":[]},{"id":"55e1e3c5b3a45ee2","type":"e-mail","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","server":"smtp.gmail.com","port":"465","secure":true,"tls":true,"name":"railhoperrors@gmail.com","dname":"","x":1906.9998168945312,"y":1741.0000267028809,"wires":[]},{"id":"a27ddc8a076702fb","type":"gate","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"","controlTopic":"control","defaultState":"open","openCmd":"open","closeCmd":"close","toggleCmd":"toggle","defaultCmd":"default","statusCmd":"status","persist":false,"storeName":"default","x":1718.9998474121094,"y":1718.000075340271,"wires":[["55e1e3c5b3a45ee2","2ec07b2bba965498"]]},{"id":"507fb0823a730f67","type":"mytimeout","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"Close the Gate after a single message","outtopic":"","outsafe":"Sensor Failed","outwarning":"","outunsafe":"off","warning":"5","timer":"10","debug":false,"ndebug":false,"ignoreCase":false,"repeat":false,"again":false,"x":1234.9999694824219,"y":1812.000075340271,"wires":[["a27ddc8a076702fb","25a88a2078b27790"],["f3c5617e7e4a4ec8"]]},{"id":"25a88a2078b27790","type":"debug","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"After Timer","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1640.9998168945312,"y":1663.0000247955322,"wires":[]},{"id":"f3c5617e7e4a4ec8","type":"change","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"Close the Gate","rules":[{"t":"set","p":"payload","pt":"msg","to":"Close","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"control","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1577.9998092651367,"y":1833.0000286102295,"wires":[["a27ddc8a076702fb"]]},{"id":"7521d3575e8440d8","type":"link in","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"Fermenter (East) Gate Control In","links":["3d23ee7a79f6b44c"],"x":1589.9998168945312,"y":1769.000020980835,"wires":[["a27ddc8a076702fb"]]},{"id":"3d23ee7a79f6b44c","type":"link out","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"Fermenter (East) Out to Gate Control","mode":"link","links":["7521d3575e8440d8"],"x":1700.9998779296875,"y":1459,"wires":[]},{"id":"cd751f44f02830ad","type":"change","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"Open The Gate after a Good Temperature Read","rules":[{"t":"set","p":"payload","pt":"msg","to":"Open","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"control","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1390.9998168945312,"y":1453.0000486373901,"wires":[["3d23ee7a79f6b44c"]]},{"id":"1419d602fb0988da","type":"inject","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"Test Flow","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":832.9999618530273,"y":1471.3333921432495,"wires":[["4928a645f26be602"]]},{"id":"2ec07b2bba965498","type":"debug","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"After Gate","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1865.999984741211,"y":1697.3333597183228,"wires":[]},{"id":"bf6c587da4d44d2f","type":"debug","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":836.6666259765625,"y":1559.0000228881836,"wires":[]},{"id":"79cfdcb0c099ff05","type":"change","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1588.6667175292969,"y":1561.000075340271,"wires":[["2696ab962dbc3f47","49c243e555497be6"]]},{"id":"49c243e555497be6","type":"debug","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1781.6665954589844,"y":1570.9999532699585,"wires":[]},{"id":"4420592fe68663bb","type":"link out","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"Restart Out Link","mode":"link","links":["0d4cfbea95fa05c2"],"x":1156.6666564941406,"y":1545.9999532699585,"wires":[]},{"id":"0d4cfbea95fa05c2","type":"link in","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"restart in link","links":["4420592fe68663bb"],"x":1472.6667175292969,"y":1557.9999532699585,"wires":[["79cfdcb0c099ff05"]]},{"id":"29579fd684d75db0","type":"comment","z":"feb81af7b09dad8f","g":"d50ab6a9776ef7f6","name":"Temp Sensor Babysitting","info":"this section controls email notifications if the temperature sensor stops reporting to the esp8266\nemails should be sent to railhoperrors@gmail.com\nths section of flow should also restart the esp8266\nto refresh connection with the ds18b20 temp sensor.","x":836.6666870117188,"y":1823,"wires":[]},{"id":"efd7b7c424179c82","type":"ui_group","name":"East Fermenternew","tab":"a74ffe3d.4eb73","order":7,"disp":true,"width":24,"collapse":false},{"id":"31a99116.50a74e","type":"mqtt-broker","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"a74ffe3d.4eb73","type":"ui_tab","name":"Brewery","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
1 Like

Hi! Thank you for detailed answer.
I removed parts of the existing setup before posting, to keep it simpler. I have set up the visualisation through a chart node and a reset through reset_totals sent to shellies/shellyem-AB/emeter/0/command.

Here's my graph for the moment:

And my setup with one Shelly EM :smiley:

For the moment I don't have the historic data, I could I guess already download the .csv from the shellies. I'll look into Influx.

I think I was using the term bottleneck too nilly-willy, what I was looking for more was pitfalls :smiley:

A question: Is Aedes broker node running in Node-red good as MQTT server?

Thanks, it's always a pleasure to look into other peoples work / thinking. Also what nodes are used and for what.

I really like flow based programming, as these relaations are already complicated - to follow them in code only is not my cup of tea.

A question: is it better to use mytimeout node instead of filter node to let only one similar message through?

Here is some elapsed time code that i use for monitoring runtime of my poolpump - it basically takes in the MQTT feed from my Tasmota Sonoff POWr2 when it is running and runs up some counters for daily, weekly and monthly runtimes

[{"id":"81d443ab.f3096","type":"comment","z":"ff144260.9dd2a","name":"Dashboard Display and Control","info":"","x":1330,"y":700,"wires":[]},{"id":"bf459332.ea079","type":"comment","z":"ff144260.9dd2a","name":"Capture State of Pool Pump and increment Runtime","info":"","x":430,"y":720,"wires":[]},{"id":"aeababc4.0ff758","type":"comment","z":"ff144260.9dd2a","name":"Reset Daily and Weekly Counters","info":"","x":370,"y":960,"wires":[]},{"id":"86fc392e.9d15c8","type":"ui_text","z":"ff144260.9dd2a","group":"604cf268.cd7c4c","order":4,"width":0,"height":0,"name":"Pool Pump Status","label":"Pump On/Off Status","format":"{{msg.payload.state}}","layout":"col-center","x":1350,"y":900,"wires":[]},{"id":"7562a0ba.f4ea1","type":"debug","z":"ff144260.9dd2a","name":"stats","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":630,"y":880,"wires":[]},{"id":"b8d74a96.da7e58","type":"function","z":"ff144260.9dd2a","name":"Track Daily, Weekly and Monthly runtimes","func":"const flowVarName = \"PoolPump\";\n\nconst stats = flow.get(flowVarName) || { state: \"UNKNOWN\", onMS: 0, offMS: 0, onMSdaily: 0, offMSdaily: 0, onMSweekly: 0, offMSweekly: 0, onMSmonthly: 0, offMSmonthly: 0, lastOn: null, lastOff: null, lastUpdate: Date.now()};\nif (msg.topic == \"RESET\") {\n    stats.onMSdaily = 0;\n    stats.offMSdaily = 0;\n    stats.onMSweekly = 0;\n    stats.offMSWeekly = 0;\n    stats.onMSmonthly = 0;\n    stats.offMSmonthly = 0;\n} else if (msg.topic == \"RESET:DAILY\") {\n    stats.onMSdaily = 0;\n    stats.offMSdaily = 0;\n} else if (msg.topic == \"RESET:WEEKLY\") {\n    stats.onMSweekly = 0;\n    stats.offMSWeekly = 0;\n} else if (msg.topic == \"RESET:MONTHLY\") {\n    stats.onMSmonthly = 0;\n    stats.offMSmonthly = 0;\n} else if(msg.topic == \"TICK\") {\n    var dif = (Date.now() - stats.lastUpdate);\n    if(stats.state == \"ON\") {\n        stats.onMS += dif;\n        stats.onMSdaily += dif;\n        stats.onMSweekly += dif;\n        stats.onMSmonthly += dif;\n    } else {\n        stats.offMS += dif;\n        stats.offMSdaily += dif;\n        stats.offMSweekly += dif;\n        stats.offMSmonthly += dif;\n    }\n    stats.lastUpdate = Date.now();\n} else {\n    var state = msg.payload.POWER;\n    if (state == \"ON\" && stats.state != \"ON\") {\n        stats.lastOn = Date.now();\n        node.status({fill:\"green\",shape:\"ring\",text:\"on\"});\n    }\n    if (state == \"OFF\" && stats.state != \"OFF\") {\n        stats.lastOff = Date.now();\n        node.status({ fill: \"red\", shape: \"ring\", text: \"off\"});\n    }\n    stats.state = state;\n}\n\nflow.set(flowVarName, stats); //update stats\nmsg.payload = stats;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":700,"y":800,"wires":[["86fc392e.9d15c8","7562a0ba.f4ea1","f4d0ef05.20561","e124d5fc.6ab618","b5bac3d7.ee33a"]]},{"id":"4f319f05.b8f61","type":"inject","z":"ff144260.9dd2a","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"10","crontab":"","once":false,"onceDelay":0.1,"topic":"TICK","payload":"","payloadType":"date","x":350,"y":820,"wires":[["b8d74a96.da7e58"]]},{"id":"d8c8385e.846418","type":"ui_text","z":"ff144260.9dd2a","group":"604cf268.cd7c4c","order":6,"width":0,"height":0,"name":"Weekly Running Time","label":"Weekly Runtime","format":"{{msg.payload}}","layout":"row-spread","x":1400,"y":760,"wires":[]},{"id":"90d2ca0e.c57a68","type":"ui_text","z":"ff144260.9dd2a","group":"604cf268.cd7c4c","order":5,"width":0,"height":0,"name":"Todays Running Time","label":"Todays Runtime","format":"{{msg.payload}}","layout":"row-spread","x":1400,"y":800,"wires":[]},{"id":"a78521df.986a2","type":"inject","z":"ff144260.9dd2a","name":"Reset Weekly Run Counter for Pool Pump","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"01 00 * * 1","once":false,"onceDelay":0.1,"topic":"RESET:WEEKLY","payload":"","payloadType":"date","x":430,"y":1040,"wires":[["21811240.028c6e"]]},{"id":"f1d2118d.19f1a","type":"inject","z":"ff144260.9dd2a","name":"Reset Daily Run Counter for Pool Pump","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"01 00 * * *","once":false,"onceDelay":0.1,"topic":"RESET:DAILY","payload":"","payloadType":"date","x":420,"y":1000,"wires":[["21811240.028c6e"]]},{"id":"69c85e7f.d4c21","type":"inject","z":"ff144260.9dd2a","name":"Reset all counters","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"RESET","payload":"","payloadType":"date","x":350,"y":1080,"wires":[["21811240.028c6e"]]},{"id":"57db55a0.2ad19c","type":"link in","z":"ff144260.9dd2a","name":">> command","links":["21811240.028c6e"],"x":370,"y":860,"wires":[["b8d74a96.da7e58"]],"l":true},{"id":"21811240.028c6e","type":"link out","z":"ff144260.9dd2a","name":"command >>","links":["57db55a0.2ad19c"],"x":750,"y":1040,"wires":[],"l":true},{"id":"f4d0ef05.20561","type":"function","z":"ff144260.9dd2a","name":"","func":"var day, hours, minutes, seconds;\n    elapsedms = flow.get(\"PoolPump.onMSdaily\");\n    seconds = Math.floor(elapsedms / 1000);\n    minutes = Math.floor(seconds / 60);\n    seconds = seconds % 60;\n    hours = Math.floor(minutes / 60);\n    minutes = minutes % 60;\n    //day = Math.floor(hour / 24);\n    //hour = hour % 24;\n    hours = (hours < 10) ? \"0\" + hours : hours;\n    minutes = (minutes < 10) ? \"0\" + minutes : minutes;\n    seconds = (seconds < 10) ? \"0\" + seconds : seconds;\n\n    msg.payload = hours + \":\" + minutes;\nreturn msg;","outputs":1,"noerr":2,"initialize":"","finalize":"","libs":[],"x":1020,"y":640,"wires":[["aabbf500.2a0aa8"]]},{"id":"aabbf500.2a0aa8","type":"debug","z":"ff144260.9dd2a","name":"stats","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1190,"y":640,"wires":[]},{"id":"b5bac3d7.ee33a","type":"function","z":"ff144260.9dd2a","name":"Convert WeeklyMs to Hours:Minutes","func":"var day, hours, minutes, seconds;\n    elapsedms = flow.get(\"PoolPump.onMSweekly\");\n    seconds = Math.floor(elapsedms / 1000);\n    minutes = Math.floor(seconds / 60);\n    seconds = seconds % 60;\n    hours = Math.floor(minutes / 60);\n    minutes = minutes % 60;\n    //day = Math.floor(hour / 24);\n    //hour = hour % 24;\n    hours = (hours < 10) ? \"0\" + hours : hours;\n    minutes = (minutes < 10) ? \"0\" + minutes : minutes;\n    seconds = (seconds < 10) ? \"0\" + seconds : seconds;\n\n    msg.payload = hours + \":\" + minutes;\nreturn msg;","outputs":1,"noerr":2,"initialize":"","finalize":"","libs":[],"x":1110,"y":760,"wires":[["d8c8385e.846418"]]},{"id":"e124d5fc.6ab618","type":"function","z":"ff144260.9dd2a","name":"Convert DailyMs to Hours:Minutes","func":"var day, hours, minutes, seconds;\n    elapsedms = flow.get(\"PoolPump.onMSdaily\");\n    seconds = Math.floor(elapsedms / 1000);\n    minutes = Math.floor(seconds / 60);\n    seconds = seconds % 60;\n    hours = Math.floor(minutes / 60);\n    minutes = minutes % 60;\n    //day = Math.floor(hour / 24);\n    //hour = hour % 24;\n    hours = (hours < 10) ? \"0\" + hours : hours;\n    minutes = (minutes < 10) ? \"0\" + minutes : minutes;\n    seconds = (seconds < 10) ? \"0\" + seconds : seconds;\n\n    msg.payload = hours + \":\" + minutes;\nreturn msg;","outputs":1,"noerr":2,"initialize":"","finalize":"","libs":[],"x":1100,"y":800,"wires":[["90d2ca0e.c57a68"]]},{"id":"9747e7f3.ee00b8","type":"link in","z":"ff144260.9dd2a","name":"Link in from MQTT Page - Pool Pump - State","links":["e185c325.36e44"],"x":255,"y":760,"wires":[["b8d74a96.da7e58"]]},{"id":"604cf268.cd7c4c","type":"ui_group","name":"Pump Status","tab":"a30b3814.18c8b8","order":1,"disp":true,"width":"6","collapse":false},{"id":"a30b3814.18c8b8","type":"ui_tab","name":"Pool Information","icon":"dashboard","order":3,"disabled":false,"hidden":false}]

Craig

2 Likes

Thanks!
I haven't yet gotten to the question of calculating the runtimes, your solution will be the basis for it.

I stand on the shoulders of giants - this was passed to me from someone else in the forum a long time ago - i think @zenofmud maybe - but anyway it was one of the long timers here so happy to pay it forward.

It has worked flawlessly for me for a couple of years for a number of different things not just the pool pump.

If you look at what it does it sets up Flow context variables - so the beauty of these is that you can monitor them to see if they are increasing and then possibly use them for your daily elapsed routines you were originally looking at

Craig

1 Like