Hours of Daylight

{% set my_test_json = {“results”:{“sunrise”:“2018-07-25T05:18:21+00:00”,“sunset”:“2018-07-25T19:30:05+00:00”,“solar_noon”:“2018-07-25T12:24:13+00:00”,“day_length”:51104,“civil_twilight_begin”:“2018-07-25T04:49:21+00:00”,“civil_twilight_end”:“2018-07-25T19:59:06+00:00”,“nautical_twilight_begin”:“2018-07-25T04:13:45+00:00”,“nautical_twilight_end”:“2018-07-25T20:34:42+00:00”,“astronomical_twilight_begin”:“2018-07-25T03:35:04+00:00”,“astronomical_twilight_end”:“2018-07-25T21:13:22+00:00”},“status”:“OK”} %}

Hours Today {{ (as_timestamp(my_test_json.results.sunset) - as_timestamp(my_test_json.results.sunrise)) | timestamp_custom(’%H:%M’,false) }}

Produces:
Hours Today 14:11

The trick is to build the URL and use the timezone…

A Yes, the code does work.
But every time restarting HA, you have to wait after midnigt to get values : (

I was waiting for a couple of days to see how consistent the code is.

I do not know how HA works concerning sensor and GUI refresh.
Does the GUI only refresh when a sensor changes values on the server?
Wonder how my code refreshes the GUI since it checks the timestamp constantly?

Maybe it would be a better solution making a automation setting the sensor value at midnight? This way the sensor gets changes only once.

Is it at all possible to set sensor values wit a automation?

It would be great if you are able to make a sensor(s) and get sun data for selected dates.

How does your sensor code look like?

So I didn’t mention this before, because I thought you’d probably want to use a standard component. But I did create a custom sensor platform for estimating outdoor illuminance from weather data obtained from Weather Underground. As a side effect, it does have attributes for today’s sunrise and sunset that do not change during the day. E.g.:

{{ states.sensor.illuminance }}

gives:

<template state sensor.illuminance=10000; unit_of_measurement=lux, sunrise=2018-07-25 05:40:00, sunset=2018-07-25 20:17:00, friendly_name=Illum @ 2018-07-25T06:23:04.265828-05:00>

You have to have a WU API key, which they no longer give out for free. But if you already have one, they appear to still work. If you’re interested, let me know and I can give you more details.

No, but you can save a date and/or time to an input_datetime. I think the tricky part would be dealing with HA not running, or sun.sun not having the data for some reason, when your automation would normally run to capture the times. Other than that, it should be fairly straightforward.

LOL! I missed your post and just found the same website! :slight_smile: I’m going to play with it a bit. Should be easy to do this!

@DavidFW1960 & @Tomahawk, this appears to work:

sensor:
  - platform: rest
    resource: https://api.sunrise-sunset.org/json?lat=LAT&lng=LNG
    name: "Day Length (HMS) from https://sunrise-sunset.org/api"
    value_template: "{{ value_json.results.day_length }}"
    scan_interval:
      minutes: 15
  - platform: rest
    resource: https://api.sunrise-sunset.org/json?lat=LAT&lng=LNG&formatted=0
    name: "Day Length (sec) from https://sunrise-sunset.org/api"
    value_template: "{{ value_json.results.day_length }}"
    unit_of_measurement: sec
    scan_interval:
      minutes: 15

where, of course, you replace LAT & LNG with your latitude & longitude. (I suppose you could even use templates to get those numbers automatically from your zone.home, although I didn’t try that.) And you might want to adjust the scan_interval. The website says, “You may not use this API in a manner that exceeds reasonable request volume, constitutes excessive or abusive usage”, but it doesn’t define what that is. (And, FYI, it does require attribution, which is why I put the link in the name. Use your own discretion.)

And here is the results (for me):

@DavidFW1960, nice find!

1 Like

Any chance you can describe how to set the LAT and LNG, as constants, from the secret.yaml file?

I had a look at the sensor documentation without luck. And this is over my level of knowledge.

Well, I tried using a template, but apparently the REST Sensor’s resource parameter doesn’t accept templates. :frowning: And, I don’t know that you can use a secret as a partial value of a parameter. Of course, you could put the entire URL in your secrets file and use that for the value of resource:. That should work.

Nice… I’m going to have a play. Not sure it’s correct because of the time zone though… ‘today’ here spans 2 days in UTC and not sure it’s dealing with that correctly or not yet. But that sensor format gives me something to work off…

Also is there any reason for the ‘seconds’ sensor?

Also… I’m a moron not seeing the day_length was included there!!! Duh!

OK so I see it’s looking correct even accounting for the time zone difference as UTC sunrise is yesterday’s date and sunset UTC is today’s so when I add 10 hours they are both today and hence it is daylight hours today.

So for yesterday, today and tomorrow sensors I have:

sensor:
  - platform: rest
    resource: !secret daylength_yesterday
    name: "Day Length Yesterday (sunrise-sunset.org)"
    value_template: "{{ value_json.results.day_length }}"
    scan_interval:
      minutes: 60
  - platform: rest
    resource: !secret daylength_today
    name: "Day Length Today (sunrise-sunset.org)"
    value_template: "{{ value_json.results.day_length }}"
    scan_interval:
      minutes: 60
  - platform: rest
    resource: !secret daylength_tomorrow
    name: "Day Length Tomorrow (sunrise-sunset.org)"
    value_template: "{{ value_json.results.day_length }}"
    scan_interval:
      minutes: 60

and it’s reading the secrets file in this format: https://api.sunrise-sunset.org/json?lat=LAT&lng=LNG&date=today
(Today, Yesterday and Tomorrow)

Awesome @pnbruckner

3 Likes

Nope, just wanted to try both formats. Depending on what you need the sensor for, having it already in seconds might be slightly easier to use.

In case you’re still interested, although the REST Sensor doesn’t support templates in the resource parameter, the Command line Sensor does support templates in its command parameter. So, rather than using the REST Sensor, you could use the Command line Sensor with the curl command. So, something like this:

sensor:
  platform: command_line
  name: day_length
  command: curl "-s 'https://api.sunrise-sunset.org/json?lat={{ states.zone.home.attributes.latitude }}&lng={{ states.zone.home.attributes.longitude }}'"
  value_template: "{{ value_json.results.day_length }}"

I discovered today that this sensor does something unexpected with the command relative to templating. It first splits the command at the first space, then it only evaluates the template for everything after the space. Hence, that’s why I have the first double-quote character after the first space (i.e., double-quotes surrounding the arguments of the curl command.)

1 Like

Before deciding what to use. Trying out this without luck.
Any ideas what I am missing?

   - platform: rest
        resource: https://api.sunrise-sunset.org/json?lat=XX.xxx&lng=YY.yy
        name: "Sun Rise and Set"
        json_attributes:
          - sunrise
          - sunset
          - day_length
          - status
        value_template: "{{ value_json.results }}"
        scan_interval:
          minutes: 60

Putting all the results in the state (with value_json.results) may be temporarily interesting, but ultimately, not very useful, IMHO.

What do you mean by “without luck”?

I’m not sure the json_attributes options will work as is, or even at all. At a minimum, I would think you need to change them to results.sunrise, results.sunset, etc., but I’m not sure even that would work.

Without luck = dint work.

Looking at the document, I was hoping it would work. But Ill settle for a several Rest sensors.

Thanks for helping out!

So, I just learned something about the RESTful Sensor. Although there’s no way to make the state (i.e., what comes out of value_template) a dictionary (even if it looks like a dictionary, it’s really always a string), the same is not true for the json_attributes. So, that sheds a new light on this! :slight_smile:

One other comment about what you tried. I tried it myself - i.e., value_template: "{{ value_json.results }}" - and the reason it doesn’t work is because the output is too long. States strings are limited to 255 characters.

So, the following you might find useful:

sensor:
  - platform: rest
    resource: https://api.sunrise-sunset.org/json?lat=XX.xxx&lng=YY.yy
    name: "Sun Rise and Set"
    value_template: "{{ value_json.status }}"
    json_attributes:
      - results
  - platform: template
    sensors:
      sunrise:
        friendly_name: "Sunrise"
        value_template: "{{ states.sensor.sun_rise_and_set.attributes.results.sunrise }}"
      sunset:
        friendly_name: "Sunset"
        value_template: "{{ states.sensor.sun_rise_and_set.attributes.results.sunset}}"
      day_length:
        friendly_name: "Day Length"
        value_template: "{{ states.sensor.sun_rise_and_set.attributes.results.day_length }}"

I just tried this with my lat/lon and got:

{{ states('sensor.sun_rise_and_set') }}
{{ states('sensor.sunrise') }}
{{ states('sensor.sunset') }}
{{ states('sensor.day_length') }}
OK
5:19:08 AM
7:29:18 PM
14:10:10

EDIT: So those values were actually using the example lat/lon from the sunrise-sunset.org website. When I updated with my real lat/lon, I noticed the times are being reported in UTC, not local. Doesn’t matter for day_length, but it does for sunrise and sunset. So, although this can work, some more massaging is necessary to get the sunrise and sunset values into something actually useful.

EDIT 2: It’s probably best to add &formatted=0 to the end of the resource URL. That way the sunrise & sunset times will be full date/time strings, which can then be converted to whatever you want. Also, day_length will be in seconds, again easily convertible to whatever display format you want.

E.g.:

{{ states('sensor.sun_rise_and_set') }}
{{ states('sensor.sunrise') }}
{{ states('sensor.sunset') }}
{{ states('sensor.day_length') }}
{{ as_timestamp(states('sensor.sunrise'))|timestamp_custom('%I:%M:%S %p') }}
{{ as_timestamp(states('sensor.sunset'))|timestamp_custom('%I:%M:%S %p') }}
{{ states('sensor.day_length')|int|timestamp_custom('%H:%M:%S',false) }}

gets:

OK
2018-07-26T10:42:20+00:00
2018-07-27T01:16:23+00:00
52443
05:42:20 AM
08:16:23 PM
14:34:03
1 Like

Actually it does.

I am expecting when 10am ticks over (we are UTC+10) that all the day lengths yesterday, today and tomorrow will shift as currently, they have not shifted since yesterday at 11am when I set it all up… Maybe this is no biggie and I can just roll them forward myself if it’s before 10am but I’ll need to get tomorrow+1

If you have the lat & lon correct, even if you’re not using &formatted=0 (or if you are using &formatted=1) then for the day, the day_length value will be correct. It doesn’t matter that the sunrise and sunset are reported in (partial) UTC.

And when you use &formatted=0, everything is right for the day. Yes, the (complete, aware) datetimes will be in UTC, but they are still correct. Just reformat them into local time if you want.

I think you’re confusing how datetimes are displayed vs what they actually are. I seriously doubt that for some part of the day they will be for another day. If that were so, then the website would be useless.

FWIW, I have the following currently set up:

sensor:
  - platform: rest
    resource: !secret sun_data_url
    name: sun_data
    value_template: "{{ value_json.status }}"
    json_attributes:
      - results
    scan_interval:
      hours: 1
  - platform: template
    sensors:
      sunrise:
        friendly_name: Sunrise
        value_template: "{{ states.sensor.sun_data.attributes.results.sunrise }}"
      sunset:
        friendly_name: Sunset
        value_template: "{{ states.sensor.sun_data.attributes.results.sunset}}"
      day_length:
        friendly_name: Day Length
        value_template: "{{ states.sensor.sun_data.attributes.results.day_length }}"

where the sun_data_url secret is:

https://api.sunrise-sunset.org/json?lat=REDACTED&lng=REDACTED&formatted=0

The values being reported are all correct, and for today, even though we’ve already crossed the boundary you mentioned (which, in my case, is 7:00 PM, since my timezone is -05:00.) I even restarted HA to force an update and they are still correct.

ok so yesterday, and today up till 10am, I had:

Day Length Yesterday: 10:20:09
Today: 10:21:28
Tomorrow: 10:22:50

After 10am this ticked over today to show:
Yesterday: 10:20:09
Today: 10:22:50
Tomorrow: 10:24:12

(Note yesterday hasn’t kicked over at all yet…)