I have a few automations where I need to know whether it’s day, evening or night. Home Assistant have sensor for the sun, so it knows the times for sunrise and sunset. Evening can easily be calculated using sunset and the time when you want to change from evening to night.
I want my “period of day” sensor to be a bit more sophisticated. I want to measure daylight to take into consideration cloudy, misty or rainy days. Automations like turning on garden lights will run earlier when it’s getting darker, even though the sun has not yet set. Same thing in the morning: Automations running at sunrise will start slightly later on “dark” days.
To facilitate the use in automations, I have defined the “device_class” as “enum”, and entered the various states the sensor can have as attributes.
I’m changing the icon according to the lux value to make it a bit fancier.
In order to do this we of course need a light-sensor. I have one on my Weatherflow station, and have defined the tipping point between day and evening/night) to be between 80 to 100 lux. In order to avoid shifting between day/night by fluctuations around the tipping value, I have a “Hysteresis Buffer” in my YAML code. To avoid getting fluctuations during Home Assistant re-start I’m also using the light sensor to decide availability of the “period of day” sensor. Below is the YAML code I use to create a Template sensor.
- sensor:
- name: "Period of Day"
unique_id: period_of_day_unique_id
device_class: enum
attributes:
options: "{{ ['Day', 'Evening', 'Night'] }}"
availability: "{{ states('sensor.st_00018093_illuminance') not in ['unknown', 'unavailable', 'none'] }}"
icon: >
{% set sun = states('sun.sun') %}
{% set lux = states('sensor.st_00018093_illuminance') | float(-1) %}
{% set hour = now().hour %}
{% if hour >= 23 or (hour < 12 and (sun == 'below_horizon' or lux < 100)) %}
mdi:weather-night
{% elif sun == 'above_horizon' and lux > 100 %}
mdi:white-balance-sunny
{% else %}
mdi:moon-waning-crescent
{% endif %}
state: >
{% set sun = states('sun.sun') %}
{% set lux = states('sensor.st_00018093_illuminance') | float(-1) %}
{% set hour = now().hour %}
{% set current = this.state if this.state in ['Day', 'Evening', 'Night'] else none %}
{# 1. Strict Night: 23:00 until it's actually bright in the morning #}
{% if hour >= 23 or (hour < 12 and (sun == 'below_horizon' or lux < 100)) %}
Night
{% else %}
{# 2. Sun is up and it's bright enough #}
{% if sun == 'above_horizon' %}
{% if lux > 100 %}
Day
{% elif lux < 80 and lux != -1 %}
Evening
{% else %}
{# Hysteresis Buffer - keeps current state if between 80-100 #}
{% if current is not none %}
{{ current }}
{% else %}
{{ 'Day' if lux > 80 else 'Evening' }}
{% endif %}
{% endif %}
{% else %}
{# 3. Sun is down, but before 23:00 #}
Evening
{% endif %}
{% endif %}




