Read sunset offset at a given time?

HI, thanks!

Yes, what I am trying to accomplish is this:
lets say sun sets at 1800 hours. My light_level sensors switches in at 18.45 and turns on the lights. Id like to template that positive offset of 45 minutes from the sunset automatically.

I can do the same with the sun angle on each moment of the day:

value_template: >
  {{ '%+.1f'|format(state_attr('sun.sun','elevation')) }}

Hope to be able to do something like that for the offset.
example automation to do that:

    data_template:
      message: >
        {{as_timestamp(now()) | timestamp_custom("%X") }}: Parking is set and safely lit 
         while Solar angle is {{states('sensor.solar_angle')}} and Offset is {{template_offset}}

so id just like to find out what the offset is, rather than set it, as you do in your template with + n_seconds

Ok, I guess I misunderstood what you said here and in the other thread (for my CC.) I thought you were looking to trigger an automation at some dynamically calculated offset from sunset.

If you just want to figure out how long it has been since the last sunset (at some time determined by some other mechanism), then yes, there is no current attribute I’m aware of that would tell you when the previous sunset was (especially after midnight.) My CC could be fairly easily extended to add a prev_sunset attribute I suppose. Although as others have suggested, you could have an automation that runs, say at midnight, that saves the value of the next sunset (i.e., “today’s”, from either the standard sun component or my CC) into an input_datetime, and then use that. Actually, since these attributes are really strings (which are compatible with the as_timestamp function), it would probably be easier to save to an input_text.

EDIT: Actually, if you triggered the automation at sunset, and had it save the current time (i.e., now()), that should give you the time of the previous sunset until the next sunset happens (when the time is updated again.)

do i understand correctly that your component has an attribute sunset that is valid for the whole day? wouldn’t that than allow for something like offset = sunset - now() ? (never mind the correct syntax , this is only the idea)

the sunset would never go past midnight, so id always stay within the 24 hours of one day

i think that would be easiest, might I throw in a feature request for that :wink: no need for extra input_texts or automations if it were available like that!

this would be what I need, call it last_sunset, and then use that to calculate the offset when the light_sensor kicks in with the now() of that moment: offset = now() - last_sunset.

think that’s what I posted above already…

No, that would not work between midnight and sunset, because at midnight it gets updated to the new day’s sunset. From sunset to midnight it is effectively the date/time of the previous sunset. But after midnight (and until sunset) it is the date/time of the next sunset, just like next_rising. The difference between these two attributes is that next_rising updates at sunset, whereas sunset updates at midnight. next_rising always tells you when the next sunset will be, whereas sunset always tells you when today’s sunset will be or was. What you’re looking for is an attribute that also updates at sunset and always tells you when the previous sunset was (which is effectively the date/time of when next_rising is updated, which is why capturing the current time at sunset would give you the same thing.)

Easiest for you, not for me. :wink: So far you’re the only one that I’m aware of that is looking for such a feature. If I had infinite time on my hands I’d consider doing this, but I don’t, and I have a few other things I’m trying to do right now that I think more people will benefit from, so they’re taking priority.

It really comes down to what time period during a given day do you want to be able to calculate the time since the last sunset. If you just need that to work between sunset and midnight, then you can do this with my current CC using the sunset attribute. But if you want the calculations to be valid between midnight and sunset as well, then I’d suggest what I did before: use a simple automation that triggers at sunset and captures the current time in an input_text.

yes, that was what I am looking for, and hoping to be able to use your component for. would this work:

{{(as_timestamp(now()) - as_timestamp(state_attr('sun.sun','sunset')))| timestamp_custom('%H:%M:%S', 0) }}

would lead to:

##############################################################################################################
# using @pnbruckner cc sun.py
# https://github.com/pnbruckner/homeassistant-config/blob/master/custom_components/sun.py
##############################################################################################################

      sunset_offset:
        friendly_name: Sunset offset
        value_template: >
          {{(as_timestamp(now()) - 
             as_timestamp(state_attr('sun.sun','sunset')))| timestamp_custom('%H:%M:%S', 0) }}

and

automation:

  - alias: 'Notify outside daylight'
    id: 'Notify outside daylight'
#    initial_state: on
    trigger:
      platform: state
      entity_id: binary_sensor.outside_daylight_sensor
#      to: 'off'
    condition: 
      condition: template
      value_template: >
        {{is_state('input_boolean.notify_system', 'on')}}
    action:
      service: notify.notify
      data_template:
        message: >
          {{as_timestamp(now()) | timestamp_custom("%X") }}: 
          Daylight {{states('binary_sensor.outside_daylight_sensor') }}: Outside lights are powered 
          {{'on, ' if is_state('binary_sensor.outside_daylight_sensor', 'off') else 'off, '}}
          Solar angle is {{states('sensor.solar_angle')}} and Offset is {{states('sensor.sunset_offset')}}.

Mostly, but you’ve fallen into the “don’t count on now() to update a template sensor” trap again. :wink: In this particular case (unless you want to use sensor.sunset_offset elsewhere) you’re probably better off just moving the calculation into the automation action.

Also, the second parameter of timestamp_custom is supposed to be a boolean, so it should be false, not 0. (BTW, the preferred boolean values in jinja are lower case false & true, not the Python spelling of capitalized False and True, although either works.)

a yes, sorry…
should it be like this then:

      sunset_offset:
        friendly_name: Sunset offset
        entity_id: sensor.time, sun.sun
        value_template: >
          {{(as_timestamp(now()) - 
             as_timestamp(state_attr('sun.sun','sunset')))| timestamp_custom('%H:%M:%S', false) }}

not sure how id put all that in the act part of the automation…

Yep, that should do it.

cool, thanks ! btw you state the sensor is using UTC, while I am in CET…which is kind of an issue when calculating the offset :wink: Or is this recalculated in the backend?

The as_timestamp function takes into account the timezone for timezone aware times (i.e., timezone aware Python datetimes, or string representations of time that contain the timezone offset at the end), and assumes local for naive times (i.e., naive Python datetimes or string representations of time that do not contain the timezone offset at the end.)

Bottom line … as_timestamp('sun.sun', 'sunset') will produce the correct Unix Epoch timestamp.

If you’d like to see this for yourself, enter the following into the Template editor:

{{ now()|string }}
{{ utcnow()|string }}
{{ as_timestamp(now()|string) }}
{{ as_timestamp(utcnow()|string) }}

updatet and checked accordingly.

should have been this btw;

  sunset_offset:
    friendly_name: Sunset offset
    entity_id: sensor.time, sun.sun
    value_template: >
      - {{(as_timestamp(state_attr('sun.sun','sunset')) - 
         as_timestamp(now()))| timestamp_custom('%H:%M:%S', false) }}

55

cool.

about the (now) trap, why isn’t this template hindered by that:

  time_template:
    friendly_name: 'Time'
    value_template: >
      {{ as_timestamp(now()) | timestamp_custom("%H:%M %d/%m", true) }}

That’s because template sensors that don’t use the manual entity specification (i.e., the entity_id config parameter) and don’t contain any entities in the template that can be automatically extracted will update on every state change in the system. And since you have sensor.time defined, which causes a state change every minute, this particular template sensor will consequently be updated every minute. But

There is a fairly recent change that I happened to notice that will change that behavior. See PR #17276 and PR #17319. This will cause this type of template to only update once at startup, and more importantly not for every state change in the system.

Interestingly, there is also another change coming that will add a service to manually force an entity to update – see PR #17278.

So, bottom line, it works now, but won’t work soon.

a yes, I’ve seen these PR too.
thanks for listing them here so meaningful. Guess some will need the entity_id in the value_template, like these discussed here. Other might benefit from the manual updating.
As said in the PR comments, some suffer from serious timing issues, and indeed these are very frequent in my logs, so I expect a great benefit.

please let me get back on the template for the offset:

apparently the offset doesn’t work as I hoped after all, since the above template now (after todays sunset) shows the time to the next sunset, while I would have hoped it to show the time passed after todays sunset.

{{(as_timestamp(now()) -
as_timestamp(state_attr(‘sun.sun’,‘sunset’)))| timestamp_custom(’%H:%M:%S’, false) }} does show that, but is wrong when evaluated at a moment before todays sunset.
Guess I need them both:

when now() is before sunset use:

  • {{(as_timestamp(state_attr(‘sun.sun’,‘sunset’)) -
    as_timestamp(now()))| timestamp_custom(’%H:%M:%S’, false) }}
    when now() is after sunset use:
    {{(as_timestamp(now()) -
    as_timestamp(state_attr(‘sun.sun’,‘sunset’)))| timestamp_custom(’%H:%M:%S’, false) }}

would this be the correct way to write that:

{% if as_timestamp(now()) < as_timestamp(state_attr('sun.sun','sunset')) %}
   - {{(as_timestamp(state_attr('sun.sun','sunset')) - 
        as_timestamp(now()))| timestamp_custom('%H:%M:%S', false) }}
{% else%} 
   {{(as_timestamp(now()) - 
      as_timestamp(state_attr('sun.sun','sunset')))| timestamp_custom('%H:%M:%S', false) }}
{%endif%}

well that was sooner than expected…:wink: see the second Time sensor. Updated to 0.81.0b2 today… which is a huge step forward, and much more responsive. breaking change though.

57

Now you’ve got me confused again. I asked if you just needed the template to work between sunset and midnight and you said yes:

But now it looks like you want it to work all during the day. And I’m also confused as to what you want it to show.

I’ll take a stab and guess you want it to show the relative time to today’s sunset, such that before sunset it shows a positive time (i.e., how long it is before sunset), and after sunset it shows a negative time (i.e., how long it’s been since today’s sunset.) Is that it?

If so, how about this:

{% set nw = as_timestamp(now()) %}
{% set ss = as_timestamp(state_attr('sun.sun', 'sunset')) %}
{{ '- ' if nw > ss }}{{ (nw - ss)|abs|timestamp_custom('%H:%M:%S', false) }}

almost: before sunset it should give a negative time (sunset minus time) and after sunset a positive (sunset plus time)

my current template does that, but yours seems so much more sofisticated…:wink:

and yes, I might have been confusing… what I meant was the template should work per 24 day, and not per period between sunsets…

No problem.

Easy enough, just change > to < in the first if statement:

{% set nw = as_timestamp(now()) %}
{% set ss = as_timestamp(state_attr('sun.sun', 'sunset')) %}
{{ '- ' if nw < ss }}{{ (nw - ss)|abs|timestamp_custom('%H:%M:%S', false) }}
1 Like

thank you very much, very nice indeed. One for the manuals!

all of a sudden my windchill template is horribly off, could this have to do with that change too? I would have thought these entities are enough in the template itself?

  jagti_windchill:
    value_template: >
      {% set temp = states('sensor.rsd_temperature')%}
      {% set wind = states('sensor.rsd_wind_speed')%}
      {{(13.12 +0.6215*float(temp) -
         11.37*(float(wind)*3.6)**0.16 +
         0.3965*float(temp)*(float(wind)*3.6)**0.16) | round(2) }}
    unit_of_measurement: '°C'
    device_class: temperature
    friendly_name: Jag/Ti Wchill

I would think so, too. It should definitely be finding those entities and watching for their state changes.

It could be that those entities are somehow working differently themselves. See this topic for something similar.