Seasonally varying twilight offset

I would like to switch our blinds with a twilight sensor depending on the season.
On the longest day of the year (June 21), the automation should be triggered at 21Lx. At the winter solstice (around 21.12.) at 1Lx.

I’ve got:

  • sensor.illuminance (measured in Lux)
  • input_number.summer_twilight (set to 21Lx)
  • input_number.winter_twilight (set to 1Lx)

what I need:
A template for a sensor or at least a trigger template for my roller shutter automation.

Since the daylight duration does not change linearly in the course of the year but follows a curve (minimum change during the solstice, maximum during the equinox), I would like to base the calculated twilight offset on it.

I lack the right approach to create a template for this purpose.
Calculating around with timedelta might be enough here, but I’m almost sure that my Local Longitude is also significant.

Do you have a tip for me on how to get this idea to work?

There are probably more elegant solutions, but you might use an input_number which is incremented daily from an automation & use that number as an additive or subtractive for your control calculation.

Could you just use the sun integration’s above horizon or azimuth.

Then you’re tracking the sun in the sky and it won’t care about time, removes most of the calculations and should be close enough to be within a couple lux. Unless inclement weather etc.

Thanks @Gnat54 ,
that would be the linear approach, which is more pragmatic.
Add or subtract 1/180 of the difference between 21 lx and 1 lx every day.

I think the following template should work for the lux value…

{%- set day = now().timetuple().tm_yday %}
{%- set lux_winter = 1 %}
{%- set lux_summer = 21 %}
{%- set lux_delta = lux_summer - lux_winter %}
{%- set summer = 172 %}
{%- set winter = 355 %}

{%- if day < summer %}
  {%- set day = 2 * summer - day %}
{%- elif day > winter %}
  {%- set day = 2 * winter - day %}
{%- endif%}

{%- set s_days_away = (day - summer) %}
{{ (lux_winter + (lux_delta * (1 - s_days_away / 183))) | round(1) }}

Since the value shouldn’t change throughout the day you could use a trigger-based sensor to save on unecessarily rendering the template every minute.

As trigger-based sensor
template:
  - trigger:
      - platform: time
        at: "00:00:00"
      - platform: homeassistant
        event: restart
    state: >
      {%- set day = now().timetuple().tm_yday %}
      {%- set lux_winter = 1 %}
      {%- set lux_summer = 21 %}
      {%- set lux_delta = lux_summer - lux_winter %}
      {%- set summer = 172 %}
      {%- set winter = 355 %}
      {%- if day < summer %}
        {%- set day = 2 * summer - day %}
      {%- elif day > winter %}
        {%- set day = 2 * winter - day %}
      {%- endif%}
      {%- set s_days_away = (day - summer) %}
      {{ (lux_winter + (lux_delta * (1 - s_days_away / 183))) | round(1) }}

EDIT: Corrected Copy/Paste error :man_facepalming:

2 Likes

Thanks @NathanCu,
I’ve used the sun integration at first. Depending on the cloud coverage, I closed at sunset or at civil dusk.
This had a bad ‘wife acceptance factor’ and I replaced it with an outdoor lux sensor.
In summer, we reach the 21 Lx at about 21:30. Thats fine.
In winter, we reach the 21 Lx at 16:00 - way to early.
I know several ways to bypass this (e.g. using the “season” integration provided by HA). But that’s neither smooth nor elegant.

Thanks @Didgeridrew,
this looks promising. These are the functions that I imagined but could never have formulated myself.
I will test it later today.

@Didgeridrew

After playing around with the day of year I experienced strange calculations in winter.
If “day” is set to 355 (winter solstice), the result is 21 instead of 1.
:thinking:

Sorry, about that… I was playing around with too many things and reusing variables :man_facepalming:
I’ve corrected the template above.

Thanks a lot @Didgeridrew,
now it works flawlessly. :clap:

Would you mind to re-add “now().timetuple().tm_yday” to your code above for later visitors of this thread?

1 Like

Thanks for adding the trigger based sensor.
What is the benefit of the trigger base in comparison to a template sensor?
Is it just load reduction by only calculating once a day or at reboot?

Yep. The now() function that’s used to define the day variable will cause a state-based template sensor to be rendered every minute, which is excessive for this application.

1 Like