Pausing timer in mytimeout

#1

Situation:
Pool pump is only to run while sufficient power from solar panels.
Pool pump needs only to run x hours per day.

mytimeout seems to be a solution to the second part, but I can't determine how to pause the countdown timer.

For example; sufficient power from solar panels triggers the pool pump on and starts the mytimeout.
Cloud comes over, insufficient power triggers the pool pump off.
If I use stop, off or 0 input to the mytimeout the time remaining is lost.

Suggestions?

#2

I have found two things that might help you

  1. https://www.youtube.com/watch?v=mUSxM6KTN9s

Shows how to track accumulated/elapsed time quite easily

Also

  1. Our very own Steve Rickus helping someone out on the old forums
    https://groups.google.com/forum/#!topic/node-red/YjEldxFUU_o

Craig

#3

It's a similar use case we discussed here:

#4

Thanks for you suggestions.

I now have it basically working. Poorly coded and still looking for bugs.

The key I found was to use "stop", and not "off". Then feed back the last value of countdown timer back into the mytimeout using the JSON code.

Using this type of method I am able to inject/add the daily required pump time to the previous day. This is particularly useful if the day or days before were over cast, then the pump will run long on the following day(s).

[{"id":"c182c0c.cdb5a4","type":"tab","label":"Pump Timer","disabled":false,"info":""},{"id":"e9b94257.58865","type":"mytimeout","z":"c182c0c.cdb5a4","name":"Count Down Timer","outtopic":"TimerCountDown","outsafe":"on","outwarning":"Warning","outunsafe":"off","warning":"5","timer":"10800","debug":false,"ndebug":false,"ignoreCase":true,"repeat":false,"again":false,"x":550,"y":180,"wires":[["d2444abc.57f1b8"],["963ceca.f2ca51"]]},{"id":"d2444abc.57f1b8","type":"debug","z":"c182c0c.cdb5a4","name":"On/Off","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":770,"y":160,"wires":[]},{"id":"963ceca.f2ca51","type":"switch","z":"c182c0c.cdb5a4","name":"Filter","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":750,"y":220,"wires":[["b6cf2b14.dcc918"]]},{"id":"760ae9da.fff238","type":"function","z":"c182c0c.cdb5a4","name":"Create JSON","func":"var timeout = flow.get(\"TimeRemainPool\",msg.payload);\n\nvar value = msg.payload; //value will equal pool pump status\n\n            if  (value === true){\n            msg.payload = {\"payload\": \"on\", timeout, \"warning\": 30}; \n            return [msg];\n            }\n            \n            else {\n            msg.payload = \"stop\"; \n            return [msg];\n                }\n","outputs":1,"noerr":0,"x":330,"y":180,"wires":[["e9b94257.58865"]]},{"id":"8b8f80a5.f2879","type":"debug","z":"c182c0c.cdb5a4","name":"TimeRemainPool","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1170,"y":260,"wires":[]},{"id":"b6cf2b14.dcc918","type":"function","z":"c182c0c.cdb5a4","name":"Create flow TimeRemainPool","func":"flow.set(\"TimeRemainPool\",msg.payload);\nmsg.payload = ((msg.payload)/60).toFixed(2);\nreturn msg;\n","outputs":1,"noerr":0,"x":900,"y":280,"wires":[["8b8f80a5.f2879","a5df946b.3477c8"]]},{"id":"a5df946b.3477c8","type":"ui_text","z":"c182c0c.cdb5a4","group":"fad07ad1.a0beb8","order":0,"width":0,"height":0,"name":"Pool Time Remaining","label":"Pool Time Remaining:","format":"{{msg.payload}}","layout":"row-left","x":1180,"y":320,"wires":[]},{"id":"4c61adff.8827c4","type":"function","z":"c182c0c.cdb5a4","name":"Get PoolPump Status","func":"var value = global.get(\"PoolPumpStatus\",msg.payload);\nmsg = { payload:value };\nreturn msg;","outputs":1,"noerr":0,"x":200,"y":120,"wires":[["3265b32.337834c","80d36119.11cbf"]]},{"id":"3265b32.337834c","type":"rbe","z":"c182c0c.cdb5a4","name":"Change Only","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":430,"y":120,"wires":[["760ae9da.fff238"]]},{"id":"b8a16315.3875d","type":"inject","z":"c182c0c.cdb5a4","name":"Trigger","topic":"","payload":"","payloadType":"str","repeat":"10","crontab":"","once":true,"onceDelay":"1","x":100,"y":40,"wires":[["4c61adff.8827c4"]]},{"id":"80d36119.11cbf","type":"debug","z":"c182c0c.cdb5a4","name":"Pool Pump Status","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":460,"y":60,"wires":[]},{"id":"454e5daf.54af64","type":"inject","z":"c182c0c.cdb5a4","name":"Daily Pump Time Required","topic":"","payload":"10800","payloadType":"num","repeat":"","crontab":"01 00 * * *","once":false,"onceDelay":0.1,"x":300,"y":360,"wires":[["396af68c.11318a"]]},{"id":"396af68c.11318a","type":"function","z":"c182c0c.cdb5a4","name":"Update day's target","func":"PumpTimeRequired = msg.payload; //value will equal pool pump status\nvar TimeRemainPoolYest = flow.get(\"TimeRemainPool\",msg.payload);\nvar TimeRemainPoolStart = 0;\nTimeRemainPoolStart = TimeRemainPoolYest + PumpTimeRequired;\nflow.set(\"TimeRemainPoolStart\",TimeRemainPoolStart);\nmsg.payload = TimeRemainPoolYest + PumpTimeRequired;\n\nreturn msg;","outputs":1,"noerr":0,"x":590,"y":360,"wires":[["b6cf2b14.dcc918"]]},{"id":"fad07ad1.a0beb8","type":"ui_group","z":"","name":"POOL CONTROLLER V1.1","tab":"aa7a6127.8d57f","order":1,"disp":true,"width":"6","collapse":false},{"id":"aa7a6127.8d57f","type":"ui_tab","z":"","name":"Pool Settings","icon":"dashboard","order":1}]
#5

Take a look at: how to share code or flow json

#6

Thanks. Fixed.

#7

If you actually put the back ticks on seperate lines (i.e. above and below the text you are adding) then it puts the code into a flat 1 liner box (for our flows anyway)

Craig

#8

Third time lucky.

[{"id":"c182c0c.cdb5a4","type":"tab","label":"Pump Timer","disabled":false,"info":""},{"id":"e9b94257.58865","type":"mytimeout","z":"c182c0c.cdb5a4","name":"Count Down Timer","outtopic":"TimerCountDown","outsafe":"on","outwarning":"Warning","outunsafe":"off","warning":"5","timer":"10800","debug":false,"ndebug":false,"ignoreCase":true,"repeat":false,"again":false,"x":550,"y":180,"wires":[["d2444abc.57f1b8"],["963ceca.f2ca51"]]},{"id":"d2444abc.57f1b8","type":"debug","z":"c182c0c.cdb5a4","name":"On/Off","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":770,"y":160,"wires":[]},{"id":"963ceca.f2ca51","type":"switch","z":"c182c0c.cdb5a4","name":"Filter","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":750,"y":220,"wires":[["b6cf2b14.dcc918"]]},{"id":"760ae9da.fff238","type":"function","z":"c182c0c.cdb5a4","name":"Create JSON","func":"var timeout = flow.get(\"TimeRemainPool\",msg.payload);\n\nvar value = msg.payload; //value will equal pool pump status\n\n            if  (value === true){\n            msg.payload = {\"payload\": \"on\", timeout, \"warning\": 30}; \n            return [msg];\n            }\n            \n            else {\n            msg.payload = \"stop\"; \n            return [msg];\n                }\n","outputs":1,"noerr":0,"x":330,"y":180,"wires":[["e9b94257.58865"]]},{"id":"8b8f80a5.f2879","type":"debug","z":"c182c0c.cdb5a4","name":"TimeRemainPool","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1170,"y":260,"wires":[]},{"id":"b6cf2b14.dcc918","type":"function","z":"c182c0c.cdb5a4","name":"Create flow TimeRemainPool","func":"flow.set(\"TimeRemainPool\",msg.payload);\nmsg.payload = ((msg.payload)/60).toFixed(2);\nreturn msg;\n","outputs":1,"noerr":0,"x":900,"y":280,"wires":[["8b8f80a5.f2879","a5df946b.3477c8"]]},{"id":"a5df946b.3477c8","type":"ui_text","z":"c182c0c.cdb5a4","group":"fad07ad1.a0beb8","order":0,"width":0,"height":0,"name":"Pool Time Remaining","label":"Pool Time Remaining:","format":"{{msg.payload}}","layout":"row-left","x":1180,"y":320,"wires":[]},{"id":"4c61adff.8827c4","type":"function","z":"c182c0c.cdb5a4","name":"Get PoolPump Status","func":"var value = global.get(\"PoolPumpStatus\",msg.payload);\nmsg = { payload:value };\nreturn msg;","outputs":1,"noerr":0,"x":200,"y":120,"wires":[["3265b32.337834c","80d36119.11cbf"]]},{"id":"3265b32.337834c","type":"rbe","z":"c182c0c.cdb5a4","name":"Change Only","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":430,"y":120,"wires":[["760ae9da.fff238"]]},{"id":"b8a16315.3875d","type":"inject","z":"c182c0c.cdb5a4","name":"Trigger","topic":"","payload":"","payloadType":"str","repeat":"10","crontab":"","once":true,"onceDelay":"1","x":100,"y":40,"wires":[["4c61adff.8827c4"]]},{"id":"80d36119.11cbf","type":"debug","z":"c182c0c.cdb5a4","name":"Pool Pump Status","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":460,"y":60,"wires":[]},{"id":"454e5daf.54af64","type":"inject","z":"c182c0c.cdb5a4","name":"Daily Pump Time Required","topic":"","payload":"10800","payloadType":"num","repeat":"","crontab":"01 00 * * *","once":false,"onceDelay":0.1,"x":300,"y":360,"wires":[["396af68c.11318a"]]},{"id":"396af68c.11318a","type":"function","z":"c182c0c.cdb5a4","name":"Update day's target","func":"PumpTimeRequired = msg.payload; //value will equal pool pump status\nvar TimeRemainPoolYest = flow.get(\"TimeRemainPool\",msg.payload);\nvar TimeRemainPoolStart = 0;\nTimeRemainPoolStart = TimeRemainPoolYest + PumpTimeRequired;\nflow.set(\"TimeRemainPoolStart\",TimeRemainPoolStart);\nmsg.payload = TimeRemainPoolYest + PumpTimeRequired;\n\nreturn msg;","outputs":1,"noerr":0,"x":590,"y":360,"wires":[["b6cf2b14.dcc918"]]},{"id":"fad07ad1.a0beb8","type":"ui_group","z":"","name":"POOL CONTROLLER V1.1","tab":"aa7a6127.8d57f","order":1,"disp":true,"width":"6","collapse":false},{"id":"aa7a6127.8d57f","type":"ui_tab","z":"","name":"Pool Settings","icon":"dashboard","order":1}]
#9

In your first function node you have:

var value = global.get("PoolPumpStatus",msg.payload);
msg = { payload:value };
return msg;

The first line says you are getting PoolPumpStatus but I don't see you set it anywhere in the flow...

#10

PoolPumpStatus comes from another flow I am running. It comes from a TP-Link HS100 smart switch and is a boolean (true/false).

At the moment I am using the node-red-contrib-hs100, however there is now a better option in node-red-contrib-tplink-iot. The main improvement is in the handling of power events. With the node-red-contrib-hs100 I seem to need to continuously pole the switch to find out its condition.

I didn't want to include all the other code at the moment as I think it would be too confusing. I still haven't finished the code around the mytimeout. At the moment it is just producing some outputs and not switching the pool pump off when the timer runs out.

#11

Do you mean another flow in the same tab or another flow in a different tab?
If it is a flow on another tab, it will come back as "undefined"

So in your settings.js you have defined

	default: {
          module: "msg.payload"
	},

???

#12

The command is "global.get("PoolPumpStatus",msg.payload)", which as far as I know should take a value from any active tab. In this case it does.

#13

the reason I was bringing it up is the 'get' should just be coded global.get("PoolPumpStatus") unless you are being crafty.

in v0.19.0 with persistent context, the second option in the get - i.e. global.get(value1, value2) - is the 'key' name of the value to be retrieved. In your usage global.get("PoolPumpStatus",msg.payload), the content of msg.payload should be the link to the storage type of "PoolPumpStatus" where the value will be gotten from.

Also, the first time you use the get, an warning will come up indicating that the store location is unknown. The warning will only show up once to avoid flooding the log.

So I suggest that unless you aren't being clever and using msg.payload to name the storage location, you change your
var value = global.get("PoolPumpStatus",msg.payload);
to
var value = global.get("PoolPumpStatus");

1 Like
#14

Thanks for this.

No I don't know enough to be clever. I clearly just picked up a bad bit of coding and continued to use it.