Automations with dusk, dawn, night and day period

Hi Derek! So you want to understand when the day-period transitions into dusk? You’re right, it’s usually 30 minutes before night falls. However, a template (at least mine) is not forward-looking, and cannot take into consideration elements which have either not yet happened or not calculated (such as the next_rising value for instance).

How about working with a trigger in an automation, like this:

trigger:
  - platform: state
    entity_id: sensor.period_of_day
    from: 'day'
    to: 'dusk'

If you describe your use case better, we might help better as well :smiley:

Thanks for the reply @mastermarkush and thanks again for making this component with comprehensive instructions.

I’m using your component to trigger my sunset actions by triggering when the state moves away from “day”. However, I feel like that’s a little later than I’d like. I was really hoping I could find a way to subtract 30 minutes from the next_dusk time and have “day” transition into “dusk” at that time.

Thanks

This is a really good sensor thanks, do you know if it is possible to add an offset as this would be great for automation

Cheers

Rich

Hi Rich!

You can set a positive (forward pointing) offset, for example through a delay in your automation. You unfortunately cannot set backward pointing offsets with this sensor, because the ‘period of the day’ calculates dynamically and it is unknown to homeassistant as to when the value changes.

-Markus

Hi, this doesn’t work «universally». I live in the arctic region, so we wont see the sun above the horizon until 21st of january and this is current data:

next_rising: 2021-01-14T10:47:56+00:00
next_setting: 2021-01-14T10:58:25+00:00

This code will keep the sensor as «dusk» until 14th og January.

This is a sensor that works based on elevation. It’s worked out together with an employee of The Norwegian Meteorological Institute (met.no and yr.no)

sensor:
  - platform: template
    sensors:
      period_of_day:
        friendly_name: 'Period of the day'
        value_template: >-
          {% set elevation = state_attr('sun.sun', 'elevation') %}
          {% set rising = state_attr('sun.sun', 'rising') %}
          {%- if elevation <= -12 -%}
            night
          {%- elif -12 < elevation <= -6 -%}
            {{ 'dawn' if rising else 'dusk' }}
          {%- else -%}
            day
          {%- endif -%}light
        icon_template: >-
          {% set elevation = state_attr('sun.sun', 'elevation') %}
          {% set rising = state_attr('sun.sun', 'rising') %}
          {%- if elevation <= -12 -%}
            mdi:weather-night
          {%- elif -12 < elevation <= -6 -%}
            mdi:weather-sunset-{{ 'up' if rising else 'down' }}
          {% else %}
            mdi:weather-sunny
          {% endif %}

Between -12 and -6 is nautical dusk/dawn, and between -6 and 0 is «normal dusk/dawn». They consider everything between -6 and greater as «daylight», and I’m using this mostly in automation, so I’ve choosen this range (-12 to -6 as dusk/dawn). But you can tweak it for your linking. :slight_smile:

EDIT: Updated the code. Forgot to alter the icon_template.

14/12/2020: Updated the code.

7 Likes

Hello Joachim!

You demonstrate the true power of this forum: Exchange good - better - best ideas. Quite frankly, your sensor is literally “universal”, since it uses the sun’s elevation as basic criteria. Don’t know why I didn’t come up with the idea when I wrote my sensor, I believe that the sun attributes were not yet available in hass at that point of time.

Thumbs up, good work!

Cheers,
Markus

Anyone got it working for their region? I have tried to tweak the numbers, but it does not show dusklight or dawnlight. Just daylight or nightlight.

The original updated code works. For my region (japan), dawn is about 06:09 and dusk is about 16:30.

 - platform: template
   sensors:
     period_of_day:
       friendly_name: 'period of the day'
       value_template: >-
         {% if (as_timestamp(states.sun.sun.attributes.next_dusk)) - (as_timestamp(states.sun.sun.attributes.next_setting)) < 0 %}
           dusk
         {% elif (as_timestamp(states.sun.sun.attributes.next_rising)) - (as_timestamp(states.sun.sun.attributes.next_dawn)) < 0 %}
           dawn
         {% elif (states.sun.sun.attributes.elevation) < -4 %}
           night
         {% else %}
           day
         {% endif %}
       icon_template: >-
         {% if (as_timestamp(states.sun.sun.attributes.next_dusk)) - (as_timestamp(states.sun.sun.attributes.next_setting)) < 0 %}
           mdi:weather-sunset-down
         {% elif (as_timestamp(states.sun.sun.attributes.next_rising)) - (as_timestamp(states.sun.sun.attributes.next_dawn)) < 0 %}
           mdi:weather-sunset-up
         {% elif (states.sun.sun.attributes.elevation) < -4 %}
           mdi:weather-night
         {% else %}
           mdi:weather-sunny
         {% endif %}

Hi, I don’t recognize the code you’ve pasted as the version in my post. However, I found a bug in the code and have updated it.

Which version of HA are you running? From masterkarkush’s post, the elevation values is probably available in newer versions of HA.

Which version of HA are you running?
Ah, that may explains it. I am running 0.117

I don’t recognize the code you’ve pasted as the version in my post.
The code is from the OP, 3rd post from top.

Ah, you had posted as a reply to my post, so got confused. But the reason why I rewrote the code, was simply because the solution you’re using didn’t work in my region either.

Have a look at this. Automations with dusk, dawn, night and day period

There’s a bug in your logic comparison, in order to compare a range you need to chain two boolean expressions with a binary and.
The a > b < c expression valid in math isn’t normally in programming languages; therefore the ‘<= -6’ condition is never checked and ‘day’ condition is never trigged.
I guess since it’s pretty far away for you, it’d have taken you a while to notice it :smile:.

       period_of_day:
        friendly_name: 'Period of the day'
        value_template: >-
          {% set elevation = state_attr('sun.sun', 'elevation') %}
          {% set rising = state_attr('sun.sun', 'rising') %}
          {%- if elevation <= -12 -%}
            night
          {%- elif elevation > -12 and elevation <= -6 -%}
            {{ 'dawn' if rising else 'dusk' }}
          {%- else -%}
            day
          {%- endif -%}light
        icon_template: >-
          {% set elevation = state_attr('sun.sun', 'elevation') %}
          {% set rising = state_attr('sun.sun', 'rising') %}
          {%- if elevation <= -12 -%}
            mdi:weather-night
          {%- elif elevation > -12 and elevation <= -6 -%}
            mdi:weather-sunset-{{ 'up' if rising else 'down' }}
          {% else %}
            mdi:weather-sunny
          {% endif %}

Hi, this high > this < low is a valid comparison. However, you’re quoting the old code - with the bug (which had this < high < low). The code was updated 2 days ago- and yes Compound Boolean Expressions is valid.

1 Like

I really like this solution, but at least for Germany the values aren’t quite right. Dawn was between 3:53 and 4:42am tonight, so when the sensor switched to “day”, it was still pitch black outside. Where are the elevation values -12 and -6 coming from?

@ dantist
Seems like Germany and Japan share the same day periods. Can you post your codes?

Hi,

My code only respect “Nautical dusk/dawn” from -12 to -6 degree angle of the sun towards the earth.

If you want to include civil dusk/dawn too, change -6 to 0. Let me know if you also want to separate between civil and nautical, and I’ll write an updated code for you.

The meteorologists that I worked this out with said they considered the civil dusk/dawn as part of the daylight.

I mostly use this for light automation outdoor and I don’t see the need of keeping the light on until it’s fully bright. The light can be quite dim before turned on/off.

But got to admit that it’s strange that it switched when it was pitch black :flushed:

Hi Joachim, I’m using the sensor to define the brightness of indoor lighting. When you switch on the lights during daytime, they are set to 100%. During dusk/dawn to 70% and at night to 10%. I’m afraid I don’t know the difference between civil and nautical dusk/dawn, but my goal is to define the times where there’s still a little bit of daylight outside, but already/still dark enough that you need to use indoor lighting.

@mastermarkush awesome job! Thanks for sharing! :grinning:

1 Like

Works fine for me:

- platform: template
  sensors:
    period_of_day:
      friendly_name: 'Period of the day'
      value_template: >-
        {% if (as_timestamp(states.sun.sun.attributes.next_dusk)) - (as_timestamp(states.sun.sun.attributes.next_setting)) < 0 %}
          dusk
        {% elif (as_timestamp(states.sun.sun.attributes.next_rising)) - (as_timestamp(states.sun.sun.attributes.next_dawn)) < 0 %}
          dawn
        {% elif states('sun.sun') == 'above_horizon' %}
          day
        {% else %}
          night
        {% endif %}
      icon_template: >-
        {% if (as_timestamp(states.sun.sun.attributes.next_dusk)) - (as_timestamp(states.sun.sun.attributes.next_setting)) < 0 %}
          mdi:weather-sunset-down
        {% elif (as_timestamp(states.sun.sun.attributes.next_rising)) - (as_timestamp(states.sun.sun.attributes.next_dawn)) < 0 %}
          mdi:weather-sunset-up
        {% elif states('sun.sun') == 'above_horizon' %}
          mdi:weather-sunny
        {% else %}
          mdi:weather-night
        {% endif %}
1 Like

Little update on that:

    - name: Period of the day
      unique_id: period_of_day
      state: >
        {% if (as_timestamp(state_attr('sun.sun','next_dusk'))) - (as_timestamp(state_attr('sun.sun','next_setting'))) < 0 %}
          dusk
        {% elif (as_timestamp(state_attr('sun.sun','next_rising'))) - (as_timestamp(state_attr('sun.sun','next_dawn'))) < 0 %}
          dawn
        {% elif is_state('sun.sun','above_horizon') %}
          day
        {% else %}
          night
        {% endif %}
      icon: >
        {% if (as_timestamp(state_attr('sun.sun','next_dusk'))) - (as_timestamp(state_attr('sun.sun','next_setting'))) < 0 %}
          mdi:weather-sunset-down
        {% elif (as_timestamp(state_attr('sun.sun','next_rising'))) - (as_timestamp(state_attr('sun.sun','next_dawn'))) < 0 %}
          mdi:weather-sunset-up
        {% elif is_state('sun.sun','above_horizon') %}
          mdi:weather-sunny
        {% else %}
          mdi:weather-night
        {% endif %}
3 Likes