Hi !
I did the job ! It works. A Node-red flow :
If you want to import it :
[{"id":"c238030.dc3538","type":"tab","label":"Ephemeris","disabled":false,"info":""},{"id":"69221bf1.879e3c","type":"sun-position","z":"c238030.dc3538","name":"sun times","positionConfig":"72e65941.bb87e8","rules":[],"onlyOnChange":"true","topic":"","outputs":1,"start":"","startType":"none","startOffset":0,"startOffsetType":"none","startOffsetMultiplier":60000,"end":"","endType":"none","endOffset":0,"endOffsetType":"none","endOffsetMultiplier":60000,"x":760,"y":520,"wires":[["c97b6a90.fe7c88","186f6671.f94a92"]]},{"id":"2a77eab6.52a876","type":"inject","z":"c238030.dc3538","name":"manual run","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":460,"wires":[["32810ef2.57a242"]]},{"id":"c97b6a90.fe7c88","type":"debug","z":"c238030.dc3538","name":"check sun times","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.times","targetType":"msg","x":840,"y":460,"wires":[]},{"id":"b24cc59.4f52ab8","type":"change","z":"c238030.dc3538","name":"latitude / longitude","rules":[{"t":"set","p":"payload.latitude","pt":"msg","to":"haConfig.latitude","tot":"flow"},{"t":"set","p":"payload.longitude","pt":"msg","to":"haConfig.longitude","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":520,"wires":[["69221bf1.879e3c"]],"info":"Inject latitude and longitude inside flow."},{"id":"ed0f82.a677188","type":"ha-entity","z":"c238030.dc3538","name":"set Ephemeris entity","server":"1d6258f3.3a5177","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"ephemeris"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:calendar-today"},{"property":"unit_of_measurement","value":""}],"state":"ephemeris_state","stateType":"str","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":1140,"y":520,"wires":[[]]},{"id":"52a2dd0.e55e824","type":"cronplus","z":"c238030.dc3538","name":"3h30 every day","outputField":"payload","timeZone":"Europe/Paris","options":[{"topic":"3h30","payload":"","type":"str","expression":"0 30 3 * * *"}],"x":120,"y":520,"wires":[["32810ef2.57a242"]]},{"id":"186f6671.f94a92","type":"function","z":"c238030.dc3538","name":"build entity","func":"\nattributes = {};\n\nfor (let [keyCamel, value] of Object.entries(msg.payload.times)) {\n keySnake = keyCamel.split(/(?=[A-Z])/).join('_').toLowerCase();\n attributes[keySnake] = value.value;\n}\n\nmsg.payload = {attributes: attributes};\n\nreturn msg;\n","outputs":1,"noerr":0,"x":930,"y":520,"wires":[["ed0f82.a677188","7ee7694c.6e1a6"]]},{"id":"75c9be5.cf0adc","type":"cronplus","z":"c238030.dc3538","name":"cron","outputField":"payload","timeZone":"","options":[],"x":270,"y":640,"wires":[["b67bb42b.6feb78"]]},{"id":"7ee7694c.6e1a6","type":"function","z":"c238030.dc3538","name":"build crons","func":"cronList = [];\n\nfor (let [event, time] of Object.entries(msg.payload.attributes)) {\n cronList.push({\n command: \"add\",\n name: event,\n expression: time,\n payload: event,\n type: \"str\",\n limit: 1\n });\n}\n\nmsg.payload = cronList;\n\nreturn msg;","outputs":1,"noerr":0,"x":110,"y":640,"wires":[["75c9be5.cf0adc","aac694ce.61574"]]},{"id":"7953e04a.bcd15","type":"ha-fire-event","z":"c238030.dc3538","name":"fire event","server":"1d6258f3.3a5177","event":"","data":"","dataType":"json","x":1180,"y":640,"wires":[[]]},{"id":"e6a15e12.c0fce8","type":"function","z":"c238030.dc3538","name":"build event","func":"eventName = msg.payload.cron;\nsunPosition = msg.payload.sun;\n\nmsg = {};\nmsg.payload = {};\nmsg.payload.event = eventName;\nmsg.payload.data = {\n azimuth: sunPosition.azimuthDegrees,\n elevation: sunPosition.altitudeDegrees,\n elevationPercent: sunPosition.altitudePercent\n};\n\n//msg.payload.time = timeObj.value;\n//msg.payload.elevation = timeObj.elevation;\n\nreturn msg;","outputs":1,"noerr":0,"x":1010,"y":640,"wires":[["7953e04a.bcd15","bc30e145.12109"]],"info":"unifiy event name and sun data in the object asked by the fire event node"},{"id":"775926dc.7ebad8","type":"sun-position","z":"c238030.dc3538","name":"sun data","positionConfig":"72e65941.bb87e8","rules":[],"onlyOnChange":"true","topic":"","outputs":1,"start":"","startType":"none","startOffset":0,"startOffsetType":"none","startOffsetMultiplier":60000,"end":"","endType":"none","endOffset":0,"endOffsetType":"none","endOffsetMultiplier":60000,"x":700,"y":660,"wires":[["d75ba6e6.678d1"]]},{"id":"bc30e145.12109","type":"debug","z":"c238030.dc3538","name":"check event","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1110,"y":700,"wires":[]},{"id":"d75ba6e6.678d1","type":"join","z":"c238030.dc3538","name":"join","mode":"auto","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":850,"y":640,"wires":[["e6a15e12.c0fce8"]]},{"id":"b67bb42b.6feb78","type":"function","z":"c238030.dc3538","name":"clone","func":"parts = {\n id: msg.payload,\n index: -1,\n count: 2,\n type: \"object\",\n key: \"n/a\"\n};\n\nmsg.parts = parts;\nreturn msg;","outputs":1,"noerr":0,"x":410,"y":640,"wires":[["2f9cf931.62b4be","978c8959.65bf9"]]},{"id":"2f9cf931.62b4be","type":"change","z":"c238030.dc3538","name":"0:cron","rules":[{"t":"set","p":"parts.index","pt":"msg","to":"0","tot":"num"},{"t":"set","p":"parts.key","pt":"msg","to":"cron","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":620,"wires":[["d75ba6e6.678d1"]]},{"id":"978c8959.65bf9","type":"change","z":"c238030.dc3538","name":"1:sun","rules":[{"t":"set","p":"parts.index","pt":"msg","to":"1","tot":"num"},{"t":"set","p":"parts.key","pt":"msg","to":"sun","tot":"str"},{"t":"set","p":"payload.latitude","pt":"msg","to":"haConfig.latitude","tot":"flow"},{"t":"set","p":"payload.longitude","pt":"msg","to":"haConfig.longitude","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":660,"wires":[["775926dc.7ebad8"]],"info":"Prepare the part 2 of the duplicated flow.\nAnd inject latitude and longitude."},{"id":"32810ef2.57a242","type":"ha-api","z":"c238030.dc3538","name":"get HA config","server":"1d6258f3.3a5177","debugenabled":false,"protocol":"http","method":"get","path":"config","data":"","dataType":"json","location":"haConfig","locationType":"flow","responseType":"json","x":360,"y":520,"wires":[["b24cc59.4f52ab8"]]},{"id":"7bd63c22.03527c","type":"comment","z":"c238030.dc3538","name":"create parts for join","info":"to have in the same flow\n - event name from cron flow\n - sun data (position) in the 2nd flow\nthese flows are joined in one","x":470,"y":700,"wires":[]},{"id":"84752ec5.e2157","type":"comment","z":"c238030.dc3538","name":"save localization","info":"Save latitude and longitude in the flow. \nThey are fetched every day.","x":360,"y":480,"wires":[]},{"id":"aac694ce.61574","type":"debug","z":"c238030.dc3538","name":"check crons","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":170,"y":700,"wires":[]},{"id":"72e65941.bb87e8","type":"position-config","z":"","name":"Greenwich Royal Observatory","isValide":"true","longitude":"0","latitude":"0","angleType":"deg","timeZoneOffset":"99","timeZoneDST":"0","stateTimeFormat":"3","stateDateFormat":"12"},{"id":"1d6258f3.3a5177","type":"server","z":"","name":"Home Assistant","addon":true}]
It does 2 things:
- create the entity ephemeris(*) which contains all the sun events of the current day with their hour
- fire an event when it’s time, this for each event managed by the node-red plugin node-red-contrib-sun-position.
This flow use the node-red-contrib-cron-plus too.
Data are calculated at 3h30 AM to avoid daylight saving time change problems (at 3h AM).
Please, if you use it and improve it, tell me
(*) Here is an example of the ephemeris entity inside HA: