How to get the sunset time in a function node?

I need the sunset time in a function node.

I have tried this code:

const haCtx = global.get("homeassistant");
const configCtx = haCtx.homeAssistant;
var sunset = new Date(configCtx.states["sun.sun"].attributes.next_setting);

This works good…but when the sunset has arrives, then the attribute next_setting has the sunset of the next day.

What I need is always the sunset value of the current day even if we are after that moment.

Ofcourse I can strip the day and month of the sunset date/time and construct a new date/time with always the day/month of today (the sunset value will be some minutes earlier or later).

But is there no simple solution to get always the sunset time of today no matter on which time of the day you check this value?

Multiple options here -

  1. Store the value in NodeRed or in an input helper, just after midnight and refer to that rather than the sun entity directly.
  2. Use the events node to listen for changes to the state of sun.sun and when the attribute changes from what is currently stored, use the old_state properties to get the next_setting attribute - so that you can store the value somewhere, either in NodeRed or Home Assistant.
  3. Use the many many sun events node for NodeRed, including the one that comes installed as part of the AddOn is you are running Home Assistant OS or a Supervised install.

I would store the value in a flow variable every morning using an inject, current state node and change node.
After that it’s easily accessible everywhere in that flow.

also there is a node SunEvents, which provides times of all sun events for current day on every call

It’s already stored in global sun.sun, depending on your file structure you should be able to access it with.

var sunrise = global.get('homeassistant.homeAssistant.states["sun.sun"].attributes.next_rising');

image

This is not what he wants

1 Like

I use an addon in HA that provides that info.
I get this on one of my sunrise sensors:

yesterday: ‘2021-12-08T08:24:56.866110+01:00’
today: ‘2021-12-09T08:26:13.813373+01:00’
tomorrow: ‘2021-12-10T08:27:27.558786+01:00’
friendly_name: Copenhagen Sunrise
icon: mdi:weather-sunset-up
device_class: timestamp

2 Likes

I thought i was losing my mind. I knew I had a sensor with sunrise/sunset times.

Okay I have created this flow which check every x seconds the sunset time.

save_sunset

[{"id":"a7987329d4afde76","type":"tab","label":"Save sunset","disabled":false,"info":"","env":[]},{"id":"2fbb3755fab7965a","type":"inject","z":"a7987329d4afde76","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"5","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":150,"y":120,"wires":[["28726be2112e8118"]]},{"id":"11cb8da493787d68","type":"function","z":"a7987329d4afde76","name":"Save sunset","func":"var sunset = new Date(msg.data.attributes.next_setting);\nsunsetDay = sunset.getDate();\nsunsetMonth = sunset.getMonth();\nsunsetFullYear = sunset.getFullYear();\n\nvar today = new Date(Date.now());\ntodayDay = today.getDate();\ntodayMonth = today.getMonth();\ntodayFullYear = today.getFullYear();\n\nif (todayDay != sunsetDay)\n{\n    sunset.setDate(todayDay);\n    sunset.setMonth(todayMonth);\n    sunset.setFullYear(todayFullYear);\n}\n\nglobal.set(\"sunset\", sunset);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":120,"wires":[[]]},{"id":"41e8b3e78091955f","type":"comment","z":"a7987329d4afde76","name":"Save sunset","info":"","x":150,"y":80,"wires":[]},{"id":"28726be2112e8118","type":"api-current-state","z":"a7987329d4afde76","name":"Sun.sun","server":"63f26c18.71f4f4","version":2,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sun.sun","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":340,"y":120,"wires":[["11cb8da493787d68"]]},{"id":"48962da532cb9558","type":"inject","z":"a7987329d4afde76","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":140,"y":280,"wires":[["aa614b479393ceaa"]]},{"id":"aa614b479393ceaa","type":"function","z":"a7987329d4afde76","name":"Get sunset","func":"var sunset = global.get(\"sunset\");\nmsg.sunset = sunset;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":280,"wires":[["8209f172eaad0efa"]]},{"id":"8209f172eaad0efa","type":"debug","z":"a7987329d4afde76","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":550,"y":280,"wires":[]},{"id":"283a073d3639c302","type":"comment","z":"a7987329d4afde76","name":"Get sunset","info":"","x":130,"y":240,"wires":[]},{"id":"63f26c18.71f4f4","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30}]

Checking it once at midnight is ofcourse better, but what If there is some malfunction about that time then you don’t have correct sunset?

Only the date and time is used. The rest i calculations, so as long as your clock is update-to-date, then there should be no issues.

Note! Raspi’s do have a real time clock, so a NTP request needs to occur, which might take up to a few minutes at boot. Therefore set the recuring trigger to a delay on the first run

Check the value before you save it.

If the value is not correct send a message as output and loop back to a delay of a few seconds then in to the current state node.
That way it will loop until you get a “correct” value and you only need to inject at midnight.

As I read your json (haven’t imported it) it seems you inject every five seconds, this means that a few seconds past sunset it will save next days sunset in your flow variable. What you didn’t want?

Maybee I think to complex but it is important that “today sunset” is always correct because it executes some devices like covers.

My point is: imagine that for whatever reason Node-RED has not executed the midnight check of the sunset (system is off, Node-RED isn’t running, you are updating Node-RED at that time, etc…) then the “today sunset” is wrong for 24 hours.

(By the way I don’t understand why home assistant is not providing some current_… fields of the Sun.)

But I have also found this topic.

The advantage is that you have it available in Home Assistant and Node-RED.

sensor:

  - platform: time_date
    display_options:
      - 'date_time_iso'

  - platform: template
    sensors:
      sun_sunset:
        device_class: timestamp
        friendly_name: 'Today Sunset'
        entity_id:
          - sun.sun
          - sensor.date_time_iso
        value_template: >
          {% set day = (as_timestamp(states('sensor.date_time_iso'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% set sday = (as_timestamp(states('sensor.sun_sunset'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% if day != sday %}
            {% set time = (as_timestamp(state_attr('sun.sun','next_setting'))
               | timestamp_custom("%H:%M:%S", true) ) | string %}
            {{ (strptime(day+' '+time,'%Y-%m-%d %H:%M:%S') | timestamp_local) }}
          {% else %}
            {{ as_timestamp(states('sensor.sun_sunset')) | timestamp_local }}
          {% endif %}

I don’t know what the frequency update interval is of this kind of construction? Is it updated every time sun.sun is changed and every second (so the entity_id’s)?

The only thing is that it is not UTC time so I have to convert that.