An action once a day, every day…

Are you comfortable with javascript?

Have a look at the flow below, which seems to work OK.
The group of inject nodes to the left are just used to simulate the inputs, but in your flow they would be deleted, and the lux level (as a number) would be fed into the function node, and the two inject nodes (into the change node) would be set to trigger at 8am and the other at whatever time that you wanted them closing.

As your lux level arrives every 6 minutes, that will run the flow in the function node, which will output the appropriate command to open or close the blinds.

Remember! in this demo, if you use the two 8am/8pm inject nodes, the changes will not take place until the function node flow is run by injecting either of the simulated Lux level inject nodes (which in your flow would be run every 6 minutes).

blinds

[{"id":"a44f90a57324d4b0","type":"change","z":"8ec88bd9c36c3f6b","name":"Save timer state to context","rules":[{"t":"set","p":"blinds.timer","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":465,"y":1460,"wires":[[]]},{"id":"609b12f869abbac0","type":"function","z":"8ec88bd9c36c3f6b","name":"Calculation","func":"let lux = msg.payload\nlet savedVals = flow.get('blinds') || {timer:'closed',currentState:'closed', lux: 0}\nif (savedVals.currentState == 'closed') {\n    if (savedVals.timer == 'open' && lux > 300) {\n        node.send({payload: 'open'})\n        savedVals.currentState = 'open'\n    }\n} else if (savedVals.timer == 'close') {\n    node.send({ payload: 'close' })\n    savedVals.currentState = 'closed'\n}\nsavedVals.lux = lux\nflow.set('blinds', savedVals)\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":1530,"wires":[["ab738f4cc68e72c8"]]},{"id":"ab738f4cc68e72c8","type":"debug","z":"8ec88bd9c36c3f6b","name":"Blinds output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":635,"y":1530,"wires":[]},{"id":"0a15e85cf4762091","type":"group","z":"8ec88bd9c36c3f6b","name":"Simulated data","style":{"label":true,"label-position":"n"},"nodes":["2d06eb572c0ccf78","a8948e86490c79c6","c4d090aa24ab127b","3a86e149786d6e50"],"x":14,"y":1399,"w":272,"h":192},{"id":"2d06eb572c0ccf78","type":"inject","z":"8ec88bd9c36c3f6b","g":"0a15e85cf4762091","name":"8am timer (open blinds)","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"open","payloadType":"str","x":160,"y":1440,"wires":[["a44f90a57324d4b0"]]},{"id":"a8948e86490c79c6","type":"inject","z":"8ec88bd9c36c3f6b","g":"0a15e85cf4762091","name":"8pm timer (close blinds)","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"close","payloadType":"str","x":160,"y":1475,"wires":[["a44f90a57324d4b0"]]},{"id":"c4d090aa24ab127b","type":"inject","z":"8ec88bd9c36c3f6b","g":"0a15e85cf4762091","name":"Simulated Lux level 310","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"310","payloadType":"num","x":160,"y":1550,"wires":[["609b12f869abbac0"]]},{"id":"3a86e149786d6e50","type":"inject","z":"8ec88bd9c36c3f6b","g":"0a15e85cf4762091","name":"Simulated Lux level 280","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"280","payloadType":"num","x":160,"y":1515,"wires":[["609b12f869abbac0"]]}]

If you don't want to close the blinds at a certain time, just comment out this line in the function node, and it will then just reset things for the following morning instead;
// node.send({ payload: 'close' })

Hi,
Thank you for your two solutions that I will look at carefully and for the trouble you are taking to help me.
Give me some time to fully understand each function and then I'll tell you if it works well.
Cordially,
Patrick

1 Like

Hi,

I tried the jbudd solution with the bakman2 flow, it works fine!
Maybe there is a way to prevent the flow from being restarted after a Node Red restart, but for a rolling shutter it's not very important...
Thanks again !

Now I'm going to try Paul-Reed's solution but it's more difficult for me to understand how it works...

[{"id":"586aea4fe7dac722","type":"debug","z":"efc74f09177072ce","name":"debug 29","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":640,"y":1920,"wires":[]},{"id":"edec724ccfec800e","type":"api-call-service","z":"efc74f09177072ce","name":"","server":"f1388c55.bbcd1","version":5,"debugenabled":false,"domain":"switch","service":"turn_on","areaId":[],"deviceId":[],"entityId":["switch.0xa4c1383f33e40153"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":820,"y":2300,"wires":[["349b103154a7218f"]]},{"id":"349b103154a7218f","type":"delay","z":"efc74f09177072ce","name":"","pauseType":"delay","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":1000,"y":2300,"wires":[["5432c23bb5ad5f7b"]]},{"id":"5432c23bb5ad5f7b","type":"api-call-service","z":"efc74f09177072ce","name":"","server":"f1388c55.bbcd1","version":5,"debugenabled":false,"domain":"switch","service":"turn_off","areaId":[],"deviceId":[],"entityId":["switch.0xa4c1383f33e40153"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1180,"y":2300,"wires":[[]]},{"id":"05c469e2d94bce75","type":"inject","z":"efc74f09177072ce","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"lux","payloadType":"flow","x":170,"y":2040,"wires":[["56f1a70e0a9cc86d"]]},{"id":"c976c33f4cc95606","type":"group","z":"efc74f09177072ce","name":"lux sensor light value","style":{"label":true},"nodes":["febdd4615d21e4c1","52aee46d107eecb6","c5b42f064b7a5c83","293c094dab5da71b"],"x":94,"y":1839,"w":432,"h":162},{"id":"febdd4615d21e4c1","type":"inject","z":"efc74f09177072ce","g":"c976c33f4cc95606","name":"lux sensor = 400","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"400","payloadType":"num","x":220,"y":1880,"wires":[["293c094dab5da71b"]]},{"id":"52aee46d107eecb6","type":"inject","z":"efc74f09177072ce","g":"c976c33f4cc95606","name":"lux sensor = 300","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"300","payloadType":"num","x":220,"y":1920,"wires":[["293c094dab5da71b"]]},{"id":"c5b42f064b7a5c83","type":"inject","z":"efc74f09177072ce","g":"c976c33f4cc95606","name":"lux sensor =  200","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"200","payloadType":"num","x":220,"y":1960,"wires":[["293c094dab5da71b"]]},{"id":"293c094dab5da71b","type":"change","z":"efc74f09177072ce","g":"c976c33f4cc95606","name":"","rules":[{"t":"set","p":"lux","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":1920,"wires":[["586aea4fe7dac722"]]},{"id":"ceb66203ef1d2fc8","type":"group","z":"efc74f09177072ce","style":{"stroke":"#0722fc","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#0722fc"},"nodes":["6959d49e6c362c87","56f1a70e0a9cc86d","f8d8f523415a70d2","22f6c8ebde1b6775","25459c34a54f9b95","b01f65df14baa26a"],"x":94,"y":2079,"w":812,"h":182},{"id":"6959d49e6c362c87","type":"inject","z":"efc74f09177072ce","g":"ceb66203ef1d2fc8","name":"From 08:00 to 16:00","props":[{"p":"payload"}],"repeat":"","crontab":"*/1 8-15 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"go","payloadType":"str","x":240,"y":2180,"wires":[["56f1a70e0a9cc86d"]]},{"id":"56f1a70e0a9cc86d","type":"switch","z":"efc74f09177072ce","g":"ceb66203ef1d2fc8","name":"lux > 300 ?","property":"lux","propertyType":"flow","rules":[{"t":"gte","v":"300","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":450,"y":2180,"wires":[["f8d8f523415a70d2"]]},{"id":"f8d8f523415a70d2","type":"rbe","z":"efc74f09177072ce","g":"ceb66203ef1d2fc8","name":"Only once","func":"rbe","gap":"","start":"","inout":"out","septopics":false,"property":"payload","topi":"topic","x":620,"y":2180,"wires":[["b01f65df14baa26a","edec724ccfec800e"]]},{"id":"22f6c8ebde1b6775","type":"inject","z":"efc74f09177072ce","g":"ceb66203ef1d2fc8","name":"Reset filter at 10:02","props":[{"p":"reset","v":"","vt":"str"}],"repeat":"","crontab":"02 10 * * *","once":false,"onceDelay":0.1,"topic":"","x":400,"y":2120,"wires":[["f8d8f523415a70d2"]]},{"id":"25459c34a54f9b95","type":"inject","z":"efc74f09177072ce","g":"ceb66203ef1d2fc8","name":"Test","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"go","payloadType":"str","x":290,"y":2220,"wires":[["56f1a70e0a9cc86d"]]},{"id":"b01f65df14baa26a","type":"debug","z":"efc74f09177072ce","g":"ceb66203ef1d2fc8","name":"debug 247","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":790,"y":2140,"wires":[]},{"id":"f1388c55.bbcd1","type":"server","name":"Home Assistant RBT","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","statusSeparator":"","enableGlobalContextStore":false}]

I can't speak for the flow posted by jbudd as I haven't tried it, but my flow will survive a reboot OK if you save the context to your file system instead of memory as described here:

https://nodered.org/docs/user-guide/context

It reads maybe complicated, but it's not really...

1 Like

I'm glad you are making progress!

There are usually more than one ways to do something. the "best" one is generally the one you can understand in 2 year's time when you have to change it.
My natural tendency is to write a javascript function for everything but I'm trying to do more with the standard nodes.

One point about the flow you posted:
My version had "Reset filter at 07:59", you have "Reset filter at 10:02".
Consider what would happen if on a dull day the lux level went from 299 to 301 at 10:05 - presumably the blinds would open.
The following morning at 8:10 it goes above 300 again. Will the filter allow the message through?

No, it was just for the test!
By putting the reset 10 minutes after the start of the test, I can quickly see if the flow works before and after the reset without waiting 24 hours.

1 Like

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