DSM Node - Operating Time - Scope of variables

Hey Guys,

I am using @cflurin DSM nodes and have implemented a pool pump run time in the system.

Seems to do just what i want for a daily pump run timer - which i then display on a dashboard and then reset the runtime at midnight each night.

I wish to implement a 2nd counter on the same page that will count weekly runtime for the same pump (and be reset each Sunday night at Midnight).

Does anyone know if you can have two counters on the same page - he seems to make heavy reference of the sm. prefixes everywhere - so i would assume that two would probably collide ?

If this was the case could just go through a rename one to use (say) smdaily and the other smweekly for all references ?

I have not seen him on the forums for quite a while so hope someone else has done some more indepth playing with the nodes - in this case the Operating time example.

regards
Craig

You haven't given us much to go on to help answer your question, but if you mean that you want to add another DSM node to the flow then there should be no interaction between them unless the flow incudes the use of global or flow context.

Thansk Colin,

Thats exactly what i want to do - have two Operating time DSM nodes in the same flow. One of which will accumulate daily runtime and the other of which will collect weekly runtimes

Will test it out and report back

thanks for replying

Craig

Check in the DSM and associated nodes whether you are using global or flow context, if using global then you will have problems, if flow then put the second one on a different tab.

Colin,

Here is what i am trying to do

I have a Tasmota POWr2 that controls the power to my pool pump.

The Tasmota firmware has been setup to talk to my MQTT Broker and to broadcast its stats every minute (Teleperiod 60)

Essentially i grab the incoming data and look for either ON or OFF that the Tasmota transmits - i then want to keep a running counter of the on time for the day and a 2nd counter for the week

I know there are lots of ways to do this - but i thought using the DSM nodes would give me some more practise with them.

So i have taken his operating time example here

And used that.

I am attemtping to keep two counters - a daily and a weekly.

The only change i have made to his node is to change the interval from 1 (second) to 60 (minute) as i did not need the display updated that often

Ultimately i will need to store these values across restarts and to then see the DSM node with that as well - but that is further down the track.

The main problem i have now is

  1. If i reset the Daily node (which i do at midnight as an example) as soon as it sees the next off (every minute) it then seeds the node with a huge negative value and starts the timer again - rather than just ignoring it until the next start is received.

  2. As an extension of that if it Stop the node in the middle of the day (low solar output) it continues to count everytime it sees a stop arrive - rather than ignoring them until restarted

Any ideas on this ?/ I have tried to message @cflurin but it appears he has not been active for quite a while.

You can see the behaviour i have described just using his example nodes rather than my flow - but i also post my flow here for completenes

regards

Craig

[{"id":"e459f4e.76f2508","type":"mqtt in","z":"bc5cdb17.6d6b48","name":"MQTT from Pool Pump","topic":"tele/Tasmota_Pool_Pump_Controller/STATE","qos":"2","datatype":"auto","broker":"8c5be0a1.64904","x":160,"y":240,"wires":[["256cc97b.87a5e6"]]},{"id":"967f9355.0ad1c","type":"debug","z":"bc5cdb17.6d6b48","name":"test","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":810,"y":160,"wires":[]},{"id":"256cc97b.87a5e6","type":"json","z":"bc5cdb17.6d6b48","name":"Turn into an object","property":"payload","action":"","pretty":false,"x":150,"y":300,"wires":[["6328b52c.3006ec","1b492848.1d6328"]]},{"id":"d38d90c1.69994","type":"switch","z":"bc5cdb17.6d6b48","name":"Test on message payload and switch","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"OFF","vt":"str"},{"t":"eq","v":"ON","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":870,"y":240,"wires":[["12bc9881.faabb7","b6bde247.29e28"],["12bc9881.faabb7","e54e64c1.508308"]]},{"id":"6328b52c.3006ec","type":"change","z":"bc5cdb17.6d6b48","name":"Move the Power State to Message Payload","rules":[{"t":"move","p":"payload.POWER","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":280,"wires":[["d38d90c1.69994","967f9355.0ad1c"]]},{"id":"74e2c789.1a9188","type":"comment","z":"bc5cdb17.6d6b48","name":"Capture State of Pool Pump and increment Runtime","info":"","x":250,"y":180,"wires":[]},{"id":"5fd41a90.dcf374","type":"inject","z":"bc5cdb17.6d6b48","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","payload":"","payloadType":"date","x":200,"y":580,"wires":[["c299f7f9.b4a088"]]},{"id":"bdc3372e.2e3c38","type":"inject","z":"bc5cdb17.6d6b48","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","payload":"","payloadType":"date","x":210,"y":620,"wires":[["bd7409ad.071848"]]},{"id":"c40cc04c.732ce","type":"comment","z":"bc5cdb17.6d6b48","name":"Reset Daily and Weekly Counters","info":"","x":170,"y":540,"wires":[]},{"id":"12bc9881.faabb7","type":"ui_text","z":"bc5cdb17.6d6b48","group":"dea21ffd.1483","order":0,"width":0,"height":0,"name":"Pool Pump Status","label":"Pump On/Off Status","format":"{{msg.payload}}","layout":"col-center","x":1290,"y":280,"wires":[]},{"id":"1b492848.1d6328","type":"debug","z":"bc5cdb17.6d6b48","name":"Object Output","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":140,"y":360,"wires":[]},{"id":"e54e64c1.508308","type":"change","z":"bc5cdb17.6d6b48","name":"Start the Timer","rules":[{"t":"set","p":"payload","pt":"msg","to":"","tot":"date"},{"t":"set","p":"topic","pt":"msg","to":"on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":780,"y":320,"wires":[["c299f7f9.b4a088","bd7409ad.071848"]]},{"id":"c299f7f9.b4a088","type":"dsm","z":"bc5cdb17.6d6b48","name":"Daily operating time","sm_config":"{\n    \"currentState\": \"stopped\",\n    \"states\": {\n        \"stopped\": {\n            \"on\": \"started\"\n        },\n        \"started\": {\n            \"inc\": \"counting\",\n            \"off\": \"stopped\"\n        },\n        \"counting\": {\n            \"inc\": \"counting\",\n            \"off\": \"stopped\"\n        }\n    },\n    \"data\": {\n        \"prev_time\": null,\n        \"time\": 0,\n        \"seconds\": 0,\n        \"interval\": 60,\n        \"interval_output\": true,\n        \"hms_format\": true\n    },\n    \"methods\": {\n        \"init\": [\n            \"sm.calc_time = function() {\",\n            \"   var now = Date.now();\",\n            \"   sm.data.time += now - sm.data.prev_time;\",\n            \"   sm.data.prev_time = now;\",\n            \"   sm.data.seconds = Math.round(sm.data.time / 1000);\",\n            \"};\",\n            \"sm.sec2hhmmss = function(sec) {\",\n                \"var t = {};\",\n                \"t.h = pad(Math.floor(sec / 3600));\",\n                \"sec %= 3600;\",\n                \"t.m = pad(Math.floor(sec / 60));\",\n                \"t.s = pad(sec % 60);\",\n                \"return t.h+':'+t.m+':'+t.s;\",\n            \"};\"\n        ],\n        \"on\": [\n            \"if (sm.currentState === 'started') {\",\n            \"   sm.data.prev_time = Date.now();\",\n            \"   resume('inc', msg);\",\n            \"}\",\n            \"output = false;\"\n        ],\n        \"inc\": [\n            \"timeout.interval = setTimeout(function() {\",\n            \"   sm.calc_time();\",\n            \"   msg.data = sm.data;\",\n            \"   if (sm.data.interval_output) {\",\n            \"       msg.payload = sm.data.hms_format ? sm.sec2hhmmss(sm.data.seconds): sm.data.seconds;\",\n            \"       node.send(msg);\",\n            \"   }\",\n            \"   resume('inc', msg);\",\n            \"}, sm.data.interval*1000);\",\n            \"output = false;\"\n        ],\n        \"off\": [\n            \"clearTimeout(timeout.interval);\",\n            \"sm.calc_time();\",\n            \"msg.payload = sm.data.hms_format ? sm.sec2hhmmss(sm.data.seconds): sm.data.seconds;\"\n        ],\n        \"reset\": [\n            \"sm.data.time = 0;\",\n            \"sm.data.seconds = 0;\"\n        ],\n        \"status\": {\n            \"fill\": {\n                \"get\": \"sm.currentState === 'counting' ? 'green' : 'grey';\"\n            },\n            \"shape\": \"dot\",\n            \"text\": {\n                \"get\": \"'time ' + (sm.data.hms_format ? sm.sec2hhmmss(sm.data.seconds): sm.data.seconds);\"\n            }\n        }\n    }\n}\n","x":900,"y":380,"wires":[["57540f79.5d4c4"]]},{"id":"57540f79.5d4c4","type":"ui_text","z":"bc5cdb17.6d6b48","group":"dea21ffd.1483","order":0,"width":0,"height":0,"name":"Todays Running Time","label":"Todays Runtime","format":"{{msg.payload}}","layout":"row-spread","x":900,"y":440,"wires":[]},{"id":"b6bde247.29e28","type":"change","z":"bc5cdb17.6d6b48","name":"Stop the TImer","rules":[{"t":"set","p":"topic","pt":"msg","to":"off","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":1000,"y":320,"wires":[["c299f7f9.b4a088","bd7409ad.071848","b80234e8.5138b8"]]},{"id":"ddab9878.a65f98","type":"inject","z":"bc5cdb17.6d6b48","name":"reset","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"reset","payload":"","payloadType":"date","x":630,"y":380,"wires":[["c299f7f9.b4a088"]]},{"id":"bd7409ad.071848","type":"dsm","z":"bc5cdb17.6d6b48","name":"Weekly operating time","sm_config":"{\n    \"currentState\": \"stopped\",\n    \"states\": {\n        \"stopped\": {\n            \"on\": \"started\"\n        },\n        \"started\": {\n            \"inc\": \"counting\",\n            \"off\": \"stopped\"\n        },\n        \"counting\": {\n            \"inc\": \"counting\",\n            \"off\": \"stopped\"\n        }\n    },\n    \"data\": {\n        \"prev_time\": null,\n        \"time\": 0,\n        \"seconds\": 0,\n        \"interval\": 60,\n        \"interval_output\": true,\n        \"hms_format\": true\n    },\n    \"methods\": {\n        \"init\": [\n            \"sm.calc_time = function() {\",\n            \"   var now = Date.now();\",\n            \"   sm.data.time += now - sm.data.prev_time;\",\n            \"   sm.data.prev_time = now;\",\n            \"   sm.data.seconds = Math.round(sm.data.time / 1000);\",\n            \"};\",\n            \"sm.sec2hhmmss = function(sec) {\",\n                \"var t = {};\",\n                \"t.h = pad(Math.floor(sec / 3600));\",\n                \"sec %= 3600;\",\n                \"t.m = pad(Math.floor(sec / 60));\",\n                \"t.s = pad(sec % 60);\",\n                \"return t.h+':'+t.m+':'+t.s;\",\n            \"};\"\n        ],\n        \"on\": [\n            \"if (sm.currentState === 'started') {\",\n            \"   sm.data.prev_time = Date.now();\",\n            \"   resume('inc', msg);\",\n            \"}\",\n            \"output = false;\"\n        ],\n        \"inc\": [\n            \"timeout.interval = setTimeout(function() {\",\n            \"   sm.calc_time();\",\n            \"   msg.data = sm.data;\",\n            \"   if (sm.data.interval_output) {\",\n            \"       msg.payload = sm.data.hms_format ? sm.sec2hhmmss(sm.data.seconds): sm.data.seconds;\",\n            \"       node.send(msg);\",\n            \"   }\",\n            \"   resume('inc', msg);\",\n            \"}, sm.data.interval*1000);\",\n            \"output = false;\"\n        ],\n        \"off\": [\n            \"clearTimeout(timeout.interval);\",\n            \"sm.calc_time();\",\n            \"msg.payload = sm.data.hms_format ? sm.sec2hhmmss(sm.data.seconds): sm.data.seconds;\"\n        ],\n        \"reset\": [\n            \"sm.data.time = 0;\",\n            \"sm.data.seconds = 0;\"\n        ],\n        \"status\": {\n            \"fill\": {\n                \"get\": \"sm.currentState === 'counting' ? 'green' : 'grey';\"\n            },\n            \"shape\": \"dot\",\n            \"text\": {\n                \"get\": \"'time ' + (sm.data.hms_format ? sm.sec2hhmmss(sm.data.seconds): sm.data.seconds);\"\n            }\n        }\n    }\n}\n","x":1170,"y":380,"wires":[["7172c623.e95c98"]]},{"id":"7172c623.e95c98","type":"ui_text","z":"bc5cdb17.6d6b48","group":"dea21ffd.1483","order":0,"width":0,"height":0,"name":"Weekly Running Time","label":"Weekly Runtime","format":"{{msg.payload}}","layout":"row-spread","x":1160,"y":440,"wires":[]},{"id":"b80234e8.5138b8","type":"debug","z":"bc5cdb17.6d6b48","name":"Output of Off","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1250,"y":320,"wires":[]},{"id":"8c5be0a1.64904","type":"mqtt-broker","z":"","name":"MQTT-On-Dev","broker":"172.16.100.36","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"dea21ffd.1483","type":"ui_group","z":"","name":"Pump Status","tab":"dd590918.d334c8","order":1,"disp":true,"width":"6","collapse":false},{"id":"dd590918.d334c8","type":"ui_tab","z":"","name":"Pool Control","icon":"dashboard","disabled":false,"hidden":false}]

Hi Craig, I am not certain what you gain from the DSM node here - perhaps it suits the way your brain works?

I prefer the function node where you can write straight code (instead of JSON strings in an array)

I had a tinker and this is what I came up with - it might be of some use. I got it to work how I imagined you want it but if its of no use, then feel free to pass.

The flow (ignore the red triangle - its my node-red issue)

The output (node runtime is in MS so you would need to format that with angular format specifiers or do it in the function)
image

The demo flow...

[{"id":"e459f4e.76f2508","type":"mqtt in","z":"64ce1d00.d049e4","name":"MQTT from Pool Pump","topic":"tele/Tasmota_Pool_Pump_Controller/STATE","qos":"2","datatype":"json","broker":"dc811dae.05f5","x":1180,"y":520,"wires":[["cfd161a.81b13a"]]},{"id":"74e2c789.1a9188","type":"comment","z":"64ce1d00.d049e4","name":"Capture State of Pool Pump and increment Runtime","info":"","x":1270,"y":480,"wires":[]},{"id":"c40cc04c.732ce","type":"comment","z":"64ce1d00.d049e4","name":"Reset Daily and Weekly Counters","info":"","x":1210,"y":720,"wires":[]},{"id":"12bc9881.faabb7","type":"ui_text","z":"64ce1d00.d049e4","group":"dea21ffd.1483","order":0,"width":0,"height":0,"name":"Pool Pump Status","label":"Pump On/Off Status","format":"{{msg.payload.state}}","layout":"col-center","x":1670,"y":600,"wires":[]},{"id":"1b492848.1d6328","type":"debug","z":"64ce1d00.d049e4","name":"stats","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1470,"y":640,"wires":[]},{"id":"c3bd3e87.55a09","type":"inject","z":"64ce1d00.d049e4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"tele/Tasmota_Pool_Pump_Controller/STATE","payload":"{\"POWER\":\"OFF\"}","payloadType":"json","x":1190,"y":360,"wires":[["ea834c0d.8dd75"]]},{"id":"cf154280.073bc","type":"inject","z":"64ce1d00.d049e4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"tele/Tasmota_Pool_Pump_Controller/STATE","payload":"{\"POWER\":\"ON\"}","payloadType":"json","x":1180,"y":400,"wires":[["ea834c0d.8dd75"]]},{"id":"ea834c0d.8dd75","type":"mqtt out","z":"64ce1d00.d049e4","name":"","topic":"","qos":"","retain":"","broker":"dc811dae.05f5","x":1370,"y":380,"wires":[]},{"id":"cfd161a.81b13a","type":"function","z":"64ce1d00.d049e4","name":"","func":"const flowVarName = \"PUMP1\";\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":9,"initialize":"","finalize":"","x":1440,"y":560,"wires":[["12bc9881.faabb7","76e65a61.eed654","6c580dd6.a3a6a4","1b492848.1d6328"]]},{"id":"1fa69700.cf71b9","type":"inject","z":"64ce1d00.d049e4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"5","crontab":"","once":false,"onceDelay":0.1,"topic":"TICK","payload":"","payloadType":"date","x":1190,"y":580,"wires":[["cfd161a.81b13a"]]},{"id":"76e65a61.eed654","type":"ui_text","z":"64ce1d00.d049e4","group":"dea21ffd.1483","order":0,"width":0,"height":0,"name":"Weekly Running Time","label":"Weekly Runtime","format":"{{msg.payload.onMSweekly}}","layout":"row-spread","x":1680,"y":520,"wires":[]},{"id":"6c580dd6.a3a6a4","type":"ui_text","z":"64ce1d00.d049e4","group":"dea21ffd.1483","order":0,"width":0,"height":0,"name":"Todays Running Time","label":"Todays Runtime","format":"{{msg.payload.onMSdaily}}","layout":"row-spread","x":1680,"y":560,"wires":[]},{"id":"1ca42f86.0c5a9","type":"inject","z":"64ce1d00.d049e4","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":1270,"y":800,"wires":[["855cc8a0.7da218"]]},{"id":"bd627791.ff1768","type":"inject","z":"64ce1d00.d049e4","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":1260,"y":760,"wires":[["855cc8a0.7da218"]]},{"id":"c478d10a.56243","type":"inject","z":"64ce1d00.d049e4","name":"Reset all counters","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"RESET","payload":"","payloadType":"date","x":1190,"y":840,"wires":[["855cc8a0.7da218"]]},{"id":"3a57a028.8eee3","type":"link in","z":"64ce1d00.d049e4","name":">> command","links":["855cc8a0.7da218"],"x":1210,"y":620,"wires":[["cfd161a.81b13a"]],"l":true},{"id":"855cc8a0.7da218","type":"link out","z":"64ce1d00.d049e4","name":"command >>","links":["3a57a028.8eee3"],"x":1590,"y":800,"wires":[],"l":true},{"id":"a6926e7.2c6c59","type":"comment","z":"64ce1d00.d049e4","name":"Simulate Pool Pump POWER signal","info":"","x":1220,"y":320,"wires":[]},{"id":"dc811dae.05f5","type":"mqtt-broker","name":"","broker":"broker.emqx.io","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"50","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"dea21ffd.1483","type":"ui_group","name":"Pump Status","tab":"dd590918.d334c8","order":1,"disp":true,"width":"6","collapse":false},{"id":"dd590918.d334c8","type":"ui_tab","name":"Pool Control","icon":"dashboard","disabled":false,"hidden":false}]

Yep i do not think i gain anything from them here but was hoping to wrap my head around them for more complex things later - it is definitely overkill for what i want to do - i was hoping to have worked through it with @cflurin - but he seems to be not visiting the forum as often now.

I will revert to what you have provided (thanks) and fit that in to get me up and running

thanks for the time on this one

I have the moment node installed so should be able to reformat the time as appropriate - will report back

Craig

Hey Steve,

That works brilliantly thanks very much for the effort.

The only thing i am now stuck with is the conversion from ms into HH:MM:SS - i thought it would be easy with the moment node but apparently not so !

I have found plenty of functions people have written - but you would think there would be a node to do it !

Working on it now

Have a great XMAS

regards

Craig

It should be, what is the problem you are having?

I could not work out how to pass a millisecond reading (not a timestamp) to the Moment node and then get it to return HH:MM as the elapsed runtime.

I worked out all the output stuff in moment - but it does not appear to be able to just accept a random number in that represents millis.

In the end i just put together a function that does it and that appears to work fine.

Craig

This seems to be working ok for me

[{"id":"99530b26.a08688","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"trigger","payloadType":"str","x":90,"y":1960,"wires":[["848ae3a7.81a65"]]},{"id":"1c6cd462.0ba72c","type":"moment","z":"bdd7be38.d3b55","name":"","topic":"","input":"","inputType":"msg","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"HH:mm","locale":"UTC","output":"","outputType":"msg","outTz":"ETC/UTC","x":320,"y":2000,"wires":[["f549469b.c0156"]]},{"id":"f549469b.c0156","type":"debug","z":"bdd7be38.d3b55","name":"RESULT","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":280,"y":2060,"wires":[]},{"id":"84b8b1f.adbc95","type":"debug","z":"bdd7be38.d3b55","name":"MILLISECONDS","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":300,"y":1940,"wires":[]},{"id":"848ae3a7.81a65","type":"function","z":"bdd7be38.d3b55","name":"","func":"msg.payload = 12*60*60000 + 34 * 60000\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":120,"y":2000,"wires":[["1c6cd462.0ba72c","84b8b1f.adbc95"]]}]

You are right (as usual) - i think i might have been too smart and set my timezone in there so it was messing around with conversions etc

I have dropped that into my flow now and between you and Steve you have wrapped this one up nicely for me

If anyone else is interested here is the final flow

[{"id":"a69fd08b.efa3","type":"ui_gauge","z":"60a263ee.ee4bdc","name":"Pump Power","group":"dea21ffd.1483","order":1,"width":0,"height":0,"gtype":"gage","title":"Power Usage","label":"Watts","format":"{{payload.ENERGY.Power}}","min":0,"max":"1400","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":550,"y":140,"wires":[]},{"id":"e9df9fe.e019e6","type":"comment","z":"60a263ee.ee4bdc","name":"Dashboard Display and Control","info":"","x":1110,"y":360,"wires":[]},{"id":"19b9a7f7.e65608","type":"mqtt in","z":"60a263ee.ee4bdc","name":"MQTT from Pool Pump","topic":"tele/Tasmota_Pool_Pump_Controller/SENSOR","qos":"2","datatype":"json","broker":"8c5be0a1.64904","x":160,"y":160,"wires":[["a69fd08b.efa3","3ccadfa2.bb703","e1c847f0.c502b8"]]},{"id":"3ccadfa2.bb703","type":"ui_text","z":"60a263ee.ee4bdc","group":"dea21ffd.1483","order":2,"width":0,"height":0,"name":"Yesterdays Power","label":"Yesterdays Power (kw/h)","format":"{{payload.ENERGY.Yesterday}}","layout":"row-spread","x":570,"y":180,"wires":[]},{"id":"e1c847f0.c502b8","type":"ui_text","z":"60a263ee.ee4bdc","group":"dea21ffd.1483","order":3,"width":0,"height":0,"name":"Todays Power","label":"Todays Power (kw/h)","format":"{{payload.ENERGY.Today}}","layout":"row-spread","x":560,"y":220,"wires":[]},{"id":"48e71e58.cfc8d","type":"comment","z":"60a263ee.ee4bdc","name":"Capture Power Info from Pool Pump and Display on Dashboard","info":"","x":250,"y":100,"wires":[]},{"id":"c7950028.45edf","type":"mqtt in","z":"60a263ee.ee4bdc","name":"MQTT from Pool Pump","topic":"tele/Tasmota_Pool_Pump_Controller/STATE","qos":"2","datatype":"json","broker":"8c5be0a1.64904","x":120,"y":420,"wires":[["a13e673f.61e6a8"]]},{"id":"f7946aea.daf7e8","type":"comment","z":"60a263ee.ee4bdc","name":"Capture State of Pool Pump and increment Runtime","info":"","x":210,"y":380,"wires":[]},{"id":"8db82a55.77ef98","type":"comment","z":"60a263ee.ee4bdc","name":"Reset Daily and Weekly Counters","info":"","x":150,"y":620,"wires":[]},{"id":"ae9f0fa9.b8453","type":"ui_text","z":"60a263ee.ee4bdc","group":"dea21ffd.1483","order":4,"width":0,"height":0,"name":"Pool Pump Status","label":"Pump On/Off Status","format":"{{msg.payload.state}}","layout":"col-center","x":1130,"y":560,"wires":[]},{"id":"9020e566.7f8158","type":"debug","z":"60a263ee.ee4bdc","name":"stats","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":410,"y":540,"wires":[]},{"id":"a13e673f.61e6a8","type":"function","z":"60a263ee.ee4bdc","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":"","x":480,"y":460,"wires":[["ae9f0fa9.b8453","9020e566.7f8158","152f0ebd.19c3b1","50032fdb.a879a"]]},{"id":"28c16a34.972026","type":"inject","z":"60a263ee.ee4bdc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"10","crontab":"","once":false,"onceDelay":0.1,"topic":"TICK","payload":"","payloadType":"date","x":130,"y":480,"wires":[["a13e673f.61e6a8"]]},{"id":"d04878b3.9e1a18","type":"ui_text","z":"60a263ee.ee4bdc","group":"dea21ffd.1483","order":6,"width":0,"height":0,"name":"Weekly Running Time","label":"Weekly Runtime","format":"{{msg.payload}}","layout":"row-spread","x":1120,"y":420,"wires":[]},{"id":"c6e29c7d.11027","type":"ui_text","z":"60a263ee.ee4bdc","group":"dea21ffd.1483","order":5,"width":0,"height":0,"name":"Todays Running Time","label":"Todays Runtime","format":"{{msg.payload}}","layout":"row-spread","x":1120,"y":460,"wires":[]},{"id":"8970d540.2b0448","type":"inject","z":"60a263ee.ee4bdc","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":210,"y":700,"wires":[["b13fa073.59be4"]]},{"id":"45439616.5eadd8","type":"inject","z":"60a263ee.ee4bdc","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":200,"y":660,"wires":[["b13fa073.59be4"]]},{"id":"72091d7d.026794","type":"inject","z":"60a263ee.ee4bdc","name":"Reset all counters","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"RESET","payload":"","payloadType":"date","x":130,"y":740,"wires":[["b13fa073.59be4"]]},{"id":"fab3879b.f77b08","type":"link in","z":"60a263ee.ee4bdc","name":">> command","links":["b13fa073.59be4"],"x":150,"y":520,"wires":[["a13e673f.61e6a8"]],"l":true},{"id":"b13fa073.59be4","type":"link out","z":"60a263ee.ee4bdc","name":"command >>","links":["fab3879b.f77b08"],"x":530,"y":700,"wires":[],"l":true},{"id":"152f0ebd.19c3b1","type":"moment","z":"60a263ee.ee4bdc","name":"","topic":"","input":"payload.onMSweekly","inputType":"msg","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"HH:mm","locale":"UTC","output":"","outputType":"msg","outTz":"ETC/UTC","x":840,"y":420,"wires":[["d04878b3.9e1a18"]]},{"id":"50032fdb.a879a","type":"moment","z":"60a263ee.ee4bdc","name":"","topic":"","input":"payload.onMSdaily","inputType":"msg","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"HH:mm","locale":"UTC","output":"","outputType":"msg","outTz":"ETC/UTC","x":840,"y":460,"wires":[["c6e29c7d.11027"]]},{"id":"dea21ffd.1483","type":"ui_group","z":"","name":"Pump Status","tab":"dd590918.d334c8","order":1,"disp":true,"width":"6","collapse":false},{"id":"8c5be0a1.64904","type":"mqtt-broker","z":"","name":"MQTT-On-Dev","broker":"172.16.100.36","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"dd590918.d334c8","type":"ui_tab","z":"","name":"Pool Control","icon":"dashboard","disabled":false,"hidden":false}]

Thanks for all the help guys

Craig

Having said that, having thought about it, unless you are using the moment node for other things then actually I would personally probably use a function node. The moment node is, I believe, heavy on resources. There is another problem that it will wrap at 24 hours (or maybe 12), whereas if you just use the modulus method to get the hours and minutes then it won't.

Aah right - i just deleted my function node that i had written - oh well no biggie !!

Going on holidays tomorrow - so will leave as is with the moment node and revisit later.

I run my NR on a Virtual machine and do use the moment node for a number of other things so memory footprint is not an issue

Thanks for the heads up though

Craig

Colin,

You were right - it wrapped at 24 hours for the weekly counter.

Otherwise has been running perfectly for the week that i was away.

I will remove the Moment nodes now and rewrite the function node to create the counters.

Thanks for all the help on this one - you too @Steve-Mcl

Craig

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