Precision of event when sun elevation equals a given number

Hi !

Probably a noob question but I didn’t find the answer. :yum:
I want to do something when the elevation is -12°. I have this piece of automation.yaml :

  alias: Crépuscule nautique
  trigger:
  - below: '-12'
    entity_id: sun.sun
    for: 0:05:00
    platform: numeric_state
    value_template: '{{ state_attr(''sun.sun'', ''elevation'') | float }}'
  condition:
  - condition: template
    value_template: '{{ state_attr(''sun.sun'', ''rising'') == false }}'
  action:
  - data:
      message: crépuscule nautique, élévation = {{ state_attr('sun.sun', 'elevation')
        }}
      title: soleil
    service: persistent_notification.create

Last evening it produced this message :

crépuscule nautique, élévation = -24.38

The day before the elevation was about -18.
How can I trigger the action when elevation is exactly -12 of close value ?

I notice too that the time for the sun phases are wrong, error of several minutes. My location is fine. I compared with SunCalc. I you know why …

The way it is currently written the sun has to be below -12 for 5 minutes before it will trigger. If you delete:

    for: 0:05:00

It should trigger pretty much spot on -12.1.

I was confused by your title for a while. I equated N to “north” not “number”.

Thank you !
You’re right, I changed the title.
I tried your proposal and it works. :+1: I added the “for” because the event triggers again if I restart HA. I haven’t the solution…

Add an uptime (minutes) sensor:

Add a condition that home assistant has to be started for more than 0 minutes (i.e. 1 minute or more).

That should stop the false triggering.

Just don’t restart home assistant when the sun elevation is around -11 degrees. You’ll probably miss the trigger.

1 Like

Nice idea ! Thank you again :laughing:

@Piscenois I used to use the uptime sensor method that @tom_l mentions. However, I can’t tell you how many times I would be working on HA and restarting during the time when my lighting automations should be triggering. :joy: Then all the lights wouldn’t come on. Drove me crazy! So I came up with a different way to handle my lighting automations that is working well.

This first automation defines an event called lights_on_event, which is triggered when the sun goes below the set elevation (5 degrees), and also on HA start. The condition is used so the light state will be set properly after a HA restart. This also means if I want to change the elevation to a different number, I only have to do it in this one automation.

alias: Set lights on event
trigger:
  - platform: homeassistant
    event: start
  - platform: numeric_state
    entity_id: sun.sun
    value_template: "{{ state_attr('sun.sun', 'elevation') }}"
    below: 5
condition:
  - condition: numeric_state
    entity_id: sun.sun
    value_template: "{{ state_attr('sun.sun', 'elevation') }}"
    below: 5
action:
  - event: lights_on_event

Then I trigger all my lighting automations using the lights_on_event. This example turns the lamp on when the lights_on_event fires, with the conditions such that the light is not already on, and the time is in a predetermined interval. This way a HA restart outside the time interval doesn’t turn the lights on (for example, after a 3AM power outage!)

alias: Bedroom light on
trigger:
  - platform: event
    event_type: lights_on_event
condition:
  - condition: state
    entity_id: light.bedroom
    state: 'off'
  - condition: time
    after: '15:00:00'
    before: '22:30:00'
action:
  - service: light.turn_on
    entity_id: light.bedroom
    data:
      brightness: 129

Hope this might be helpful to someone :slightly_smiling_face:

1 Like

Thank you Anwen.
I put this in the configuration.yaml :

sensor:
  - platform: uptime
    name: Time Online
    unit_of_measurement: minutes

but I can’t see the sensor. :sweat_smile:

triggered at -13.1 :sneezing_face:

You have to add the condition to the automation as well.

  alias: Crépuscule nautique
  trigger:
  - below: '-12'
    entity_id: sun.sun
    for: 0:05:00
    platform: numeric_state
    value_template: '{{ state_attr(''sun.sun'', ''elevation'') | float }}'
  condition:
  - condition: template
    value_template: '{{ state_attr(''sun.sun'', ''rising'') == false }}'
  - condition: numeric_state
    entity_id: sensor.uptime_minutes # or whatever it is called, check the dev tools states menu
    above: 0
  action:
  - data:
      message: crépuscule nautique, élévation = {{ state_attr('sun.sun', 'elevation')
        }}
      title: soleil
    service: persistent_notification.create

Newbie mistake: I had several sensor sections in configuration.yaml:-1:
I found why the elevation is not as precise as I want, in the source code:

_PHASE_UPDATES = {
    PHASE_NIGHT: timedelta(minutes=4 * 5),
    PHASE_ASTRONOMICAL_TWILIGHT: timedelta(minutes=4 * 2),
    PHASE_NAUTICAL_TWILIGHT: timedelta(minutes=4 * 2),
    PHASE_TWILIGHT: timedelta(minutes=4),
    PHASE_SMALL_DAY: timedelta(minutes=2),
    PHASE_DAY: timedelta(minutes=4),
}

My automation occurs during the nautical twilight phase, the sun position is updated every 8 minutes. Time to move about 1 degree. I have to deal with that or to create a sensor which update at noon and calculates all the next day events time.

Hi !

I did the job ! :laughing: 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 :kissing_closed_eyes:

(*) Here is an example of the ephemeris entity inside HA: