Auto light on based on sunset AND presence

Hi,

I have been struggling for a long time with this 'simple?' logic:

If me or my wife are home ànd the sunset goes in, the outdoor light should go on until 9:30pm.
Since I want to use 3 checks, I'm using the boolean logic ultimate node.
This way I can create an OR for the presence of me and my wife. Once that is a go it is send to an AND that is waiting for the presence and the sunset.

Yet: the status of this don't seem live. Or imagine this: the sunset gives a go; but we are not home until past 10pm, then the light would go on while it shouldn't. the AND function remembers the state and don't reinitialize.

I have my code here. I tried everything, but can't seem to make it work. I have been adding checks like: is it past 9:30pm and wait untill sunset to restart the function. etc Nothing helps. It seems a much used idea, but can't make it work. Any tips?

[{"id":"ec23ac591e0ba1c1","type":"comment","z":"3ad1aee4bf3eebb2","name":"Chalet buitenlamp aan in donker","info":"","x":230,"y":1440,"wires":[]},{"id":"ce9ddade72ca7990","type":"ha-wait-until","z":"3ad1aee4bf3eebb2","name":"wait till 9:30pm","server":"7c8d4509.f039ec","version":2,"outputs":1,"entityId":"sensor.time","entityIdFilterType":"exact","property":"state","comparator":"is","value":"21:30","valueType":"str","timeout":"0","timeoutType":"num","timeoutUnits":"seconds","checkCurrentState":true,"blockInputOverrides":true,"outputProperties":[],"x":800,"y":1580,"wires":[["0c1ae773432fb8c5"]]},{"id":"0c1ae773432fb8c5","type":"api-call-service","z":"3ad1aee4bf3eebb2","name":"chalet lamp off","server":"7c8d4509.f039ec","version":5,"debugenabled":false,"domain":"switch","service":"turn_off","areaId":[],"deviceId":[],"entityId":["switch.sonoff_10015c1449_2"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1020,"y":1580,"wires":[["38f5ca4ba2feb13d"]]},{"id":"eceeabaa176d9e55","type":"debug","z":"3ad1aee4bf3eebb2","name":"debug 9","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"\"De automatische chaletlamp is terug uit\"","statusType":"msg","x":1460,"y":1580,"wires":[]},{"id":"7012b25a34cc9bb8","type":"trigger-state","z":"3ad1aee4bf3eebb2","name":"Is X home?","server":"7c8d4509.f039ec","version":2,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":"device_tracker.tomas_s22","entityidfiltertype":"exact","debugenabled":false,"constraints":[],"inputs":0,"outputs":3,"customoutputs":[{"messageType":"payload","messageValue":"true","messageValueType":"bool","comparatorPropertyType":"current_state","comparatorPropertyValue":"new_state.state","comparatorType":"is","comparatorValue":"home","comparatorValueDataType":"str"}],"outputinitially":true,"state_type":"str","enableInput":false,"x":170,"y":1500,"wires":[[],[],["2c4dc29b884b39be"]]},{"id":"85044d931132543d","type":"trigger-state","z":"3ad1aee4bf3eebb2","name":"Is Y home?","server":"7c8d4509.f039ec","version":2,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":"device_tracker.celine_gsm","entityidfiltertype":"exact","debugenabled":false,"constraints":[],"inputs":0,"outputs":3,"customoutputs":[{"messageType":"payload","messageValue":"true","messageValueType":"bool","comparatorPropertyType":"current_state","comparatorPropertyValue":"new_state.state","comparatorType":"is","comparatorValue":"home","comparatorValueDataType":"str"}],"outputinitially":true,"state_type":"str","enableInput":false,"x":160,"y":1560,"wires":[[],[],["2c4dc29b884b39be"]]},{"id":"2c4dc29b884b39be","type":"BooleanLogicUltimate","z":"3ad1aee4bf3eebb2","name":"OR","payloadPropName":"payload","filtertrue":"both","persist":false,"sInitializeWith":"false","triggertopic":"trigger","outputtriggeredby":"all","inputCount":"2","topic":"result","restrictinputevaluation":false,"delayEvaluation":0,"x":390,"y":1500,"wires":[[],["3753f074c1532296"],[]]},{"id":"3753f074c1532296","type":"BooleanLogicUltimate","z":"3ad1aee4bf3eebb2","name":"AND","payloadPropName":"payload","filtertrue":"both","persist":false,"sInitializeWith":"false","triggertopic":"trigger","outputtriggeredby":"onlyonetopic","inputCount":"3","topic":"result","restrictinputevaluation":false,"delayEvaluation":0,"x":420,"y":1660,"wires":[["839e16c0c981d692"],[],[]]},{"id":"839e16c0c981d692","type":"api-call-service","z":"3ad1aee4bf3eebb2","name":"Chalet lamp on","server":"8be923df.d66f9","version":5,"debugenabled":true,"domain":"switch","service":"turn_on","areaId":[],"deviceId":[],"entityId":["switch.sonoff_10015c1449_2"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"\"Het licht is aangegaan\"","valueType":"str"}],"queue":"none","x":560,"y":1580,"wires":[["ce9ddade72ca7990"]]},{"id":"9e1c976856de51f1","type":"server-state-changed","z":"3ad1aee4bf3eebb2","name":"Sunset?","server":"8be923df.d66f9","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sun.sun","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"below_horizon","halt_if_type":"str","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"true","valueType":"bool"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":160,"y":1640,"wires":[["3753f074c1532296"],[]]},{"id":"38f5ca4ba2feb13d","type":"ha-wait-until","z":"3ad1aee4bf3eebb2","name":"pause till sun come up","server":"7c8d4509.f039ec","version":2,"outputs":1,"entityId":"sensor.time","entityIdFilterType":"exact","property":"state","comparator":"is","value":"10:30","valueType":"str","timeout":"0","timeoutType":"num","timeoutUnits":"seconds","checkCurrentState":true,"blockInputOverrides":true,"outputProperties":[],"x":1240,"y":1580,"wires":[["eceeabaa176d9e55"]]},{"id":"5d54c61acdbbbcc5","type":"trigger-state","z":"3ad1aee4bf3eebb2","name":"After 9:30pm?","server":"8be923df.d66f9","version":2,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":"sensor.time","entityidfiltertype":"exact","debugenabled":false,"constraints":[],"inputs":0,"outputs":3,"customoutputs":[{"messageType":"payload","messageValue":"true","messageValueType":"bool","comparatorPropertyType":"current_state","comparatorPropertyValue":"new_state.state","comparatorType":"<","comparatorValue":"21:30","comparatorValueDataType":"str"}],"outputinitially":true,"state_type":"str","enableInput":false,"x":170,"y":1700,"wires":[["3753f074c1532296"],[],[]]},{"id":"7c8d4509.f039ec","type":"server","name":"Home Assistant","version":4,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m"},{"id":"8be923df.d66f9","type":"server","name":"homeassistant","version":4,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m"}]```


Ouch! I think that's a record for importing a flow full of unknown nodes!

You might find some hints in this thread but it's all Node-red and devoid of Home Assistant.

ps

I tried everything... Nothing helps.

It must be impossible then? :wink:

You can do this without external nodes other than 1 that will give you a sunset marker.

Personally, I would keep your 3 markers (or possibly 4) as separate flows.

  1. Get a function that lets you output a true payload when it is sunset and a false when sunrise. Save the output to a context variable (flow or global). Ideally, when the false is output, also change the next entry to false to reset it.
  2. Use a trigger node to output a true for 9:30pm - saved to a context variable.
  3. Have 1 or 2 flows that record whether you and/or your wife are "present". Also saved to a context variable (or two if you need to track separate).

Now you have saved all of the data you need. Next you need to trigger the test and output whether the light should be on or off. To do that, the tails of each of the above flows should also go to your test and output flow. You can use a function node to get all of the context variables, use an if statement to get the answer you need and send on a suitable message to turn on/off the light to your control.

Something to play with.

[{"id":"b92f0455d3f222df","type":"tab","label":"Auto light","disabled":false,"info":"","env":[]},{"id":"c7c74f302401ceb4","type":"cronplus","z":"b92f0455d3f222df","name":"Sunset","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output1","outputs":1,"options":[{"name":"schedule1","topic":"schedule1","payloadType":"str","payload":"night","expressionType":"solar","expression":"0 * * * * * *","location":"55.48476 9.743309","offset":"0","solarType":"selected","solarEvents":"sunset"}],"x":120,"y":100,"wires":[["2a2b261de937ad29"]]},{"id":"2170a852c2b146e6","type":"cronplus","z":"b92f0455d3f222df","name":"Sunrise","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output1","outputs":1,"options":[{"name":"schedule2","topic":"schedule2","payloadType":"str","payload":"day","expressionType":"solar","expression":"0 * * * * * *","location":"55.48476 9.743309","offset":"0","solarType":"selected","solarEvents":"sunrise"}],"x":120,"y":40,"wires":[["2a2b261de937ad29"]]},{"id":"1ea95bb32e6d2b7f","type":"inject","z":"b92f0455d3f222df","name":"On","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":610,"y":140,"wires":[["38e78186bcf323b3"]]},{"id":"4e7521444bc7b5ad","type":"inject","z":"b92f0455d3f222df","name":"Off","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":610,"y":180,"wires":[["38e78186bcf323b3"]]},{"id":"9055ea9d8c381bd6","type":"inject","z":"b92f0455d3f222df","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":110,"y":380,"wires":[["e7a8c0a8ee6634bb"]]},{"id":"ecb35ad0dcf4152f","type":"inject","z":"b92f0455d3f222df","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":110,"y":420,"wires":[["e7a8c0a8ee6634bb"]]},{"id":"843d320d71faf5e4","type":"cronplus","z":"b92f0455d3f222df","name":"@23:15","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output1","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"str","payload":"auto","expressionType":"cron","expression":"0 15 23 * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":120,"y":160,"wires":[["2a2b261de937ad29"]]},{"id":"63c6a19db3d864c0","type":"inject","z":"b92f0455d3f222df","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":110,"y":260,"wires":[["d12b40fcce0d74c8"]]},{"id":"a287f9e7d2b4ea18","type":"inject","z":"b92f0455d3f222df","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":110,"y":300,"wires":[["d12b40fcce0d74c8"]]},{"id":"d12b40fcce0d74c8","type":"function","z":"b92f0455d3f222df","name":"Home/Away","func":"let home = 'away'\nif(msg.payload === true) {\n    home = 'home'\n} else {\n}\nmsg.payload = home\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":280,"wires":[["fc5f7b76be354f1d","2a2b261de937ad29"]]},{"id":"38e78186bcf323b3","type":"debug","z":"b92f0455d3f222df","name":"debug 69","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":820,"y":100,"wires":[]},{"id":"e7a8c0a8ee6634bb","type":"function","z":"b92f0455d3f222df","name":"Pir","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":470,"y":400,"wires":[["d2fd687cc65b3ab1","2a2b261de937ad29"]]},{"id":"d2fd687cc65b3ab1","type":"debug","z":"b92f0455d3f222df","name":"debug 70","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":820,"y":400,"wires":[]},{"id":"fc5f7b76be354f1d","type":"debug","z":"b92f0455d3f222df","name":"debug 71","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":820,"y":280,"wires":[]},{"id":"2a2b261de937ad29","type":"function","z":"b92f0455d3f222df","name":"","func":"// On Start\nlet msg1 = {} // output\n\nlet night = context.get('night')\nlet auto = context.get('auto')\nlet home = context.get('home')\nlet pir = context.get('pir')\n\nlet cmdNull = 'off'\nlet cmdOn = 'on'\n\nlet invar = msg.payload\n//node.warn('invar ' + invar)\n\nswitch(invar) {\n    case 'day':\n        node.status({ fill: \"red\", shape: \"ring\", text: \"day\" })\n        night = false\n        auto = false    \n        break\n    case 'night':\n        node.status({ fill: \"green\", shape: \"ring\", text: \"night\" })\n        night = true \n        auto = false\n        break\n    case 'auto':\n        night = false\n        auto = true\n        node.status({ fill: \"green\", shape: \"ring\", text: \"auto\" })\n        \n        break  \n    case true:\n        pir = true\n        break    \n    case false:\n        pir = false\n        break\n    case 'home':\n        home = true\n        break    \n    case 'away':\n        home = false\n        break\n    default:\n        node.send(null)\n}\n\ncontext.set('night', night)\ncontext.set('auto', auto)\ncontext.set('home', home)\ncontext.set('pir', pir)\n\nlet command = false\nif(night && !auto && home) {\n    command = true\n}\nif(auto && home && pir){\n    command = true\n} \nmsg1.payload = command\nreturn msg1\n","outputs":1,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is started.\nlet night = context.get('night') || false\nlet auto = context.get('auto') || false\nlet home = context.get('home') || false\nlet pir = context.get('pir') || false\n\nnode.status({ fill: \"\" + (night === false ?'red':'green'), shape: \"ring\", text: 'ab ' + (night === false ? 'day' : 'night') })\n\n//context.set('activ', activ)\ncontext.set('night', night)\ncontext.set('auto', auto)\ncontext.set('home', home)\ncontext.set('pir', pir)\n","finalize":"","libs":[],"x":460,"y":100,"wires":[["38e78186bcf323b3"]]}]

Thank you for the replies! Very valuable. I will try your suggestions later on.
I've noticed that my export of nodes is not showing correctly. This was the structure I had.
I used the AND and OR functions of Boolean Logic Ultimate.
I'll keep you posted.

Nothing wrong with your export, my strange looking screenshot is because none of your nodes (Home Assistant & Boolean Logic) are installed in my Node-red machine.

I hope peoples' suggestions help you work it out. :grinning: