I was recently asked on Reddit how I setup my circadian lighting at my house. There are a couple of my posts around where I was asking for help on this, but I wanted to do the full write-up.
I tried the flux component and the custom circadian lighting component. Both worked very well, but each had something about them that didn’t fit my needs/wants.
The quick breakdown is that there are two template sensors (one for brightness and one for color_temp), a group, an input_boolean and a series of automations.
Setup as follows:
Created two template sensors in sensors.yaml
- platform: template
sensors:
cl_brightness:
friendly_name: Circadian Brightness
value_template: >
{% set state = states('sensor.time') %}
{% if '05:00' <= state < '06:00' %}
25
{% elif '06:00' <= state < '06:30' %}
85
{% elif '06:30' <= state < '07:00' %}
105
{% elif '07:00' <= state < '07:30' %}
125
{% elif '07:30' <= state < '08:00' %}
190
{% elif '08:00' <= state < '09:00' %}
210
{% elif '09:00' <= state < '16:30' %}
255
{% elif '16:30' <= state < '17:00' %}
255
{% elif '17:00' <= state < '017:30' %}
240
{% elif '17:30' <= state < '18:00' %}
235
{% elif '18:00' <= state < '18:30' %}
225
{% elif '18:30' <= state < '19:00' %}
200
{% elif '19:00' <= state < '19:30' %}
175
{% elif '19:30' <= state < '20:00' %}
125
{% elif '20:00' <= state < '20:30' %}
115
{% elif '20:30' <= state < '21:00' %}
110
{% elif '21:00' <= state < '22:00' %}
100
{% elif '22:00' <= state < '22:30' %}
85
{% elif '22:30' <= state < '23:00' %}
25
{% else %}
1
{% endif %}
cl_color_temp:
friendly_name: Circadian Color Temperature
value_template: >
{% set state = states('sensor.time') %}
{% if '05:00' <= state < '06:00' %}
500
{% elif '06:00' <= state < '06:30' %}
450
{% elif '06:30' <= state < '07:00' %}
400
{% elif '07:00' <= state < '07:30' %}
350
{% elif '07:30' <= state < '08:00' %}
350
{% elif '08:00' <= state < '09:00' %}
325
{% elif '09:00' <= state < '16:30' %}
300
{% elif '16:30' <= state < '17:00' %}
350
{% elif '17:00' <= state < '017:30' %}
360
{% elif '17:30' <= state < '18:00' %}
370
{% elif '18:00' <= state < '18:30' %}
375
{% elif '18:30' <= state < '19:00' %}
400
{% elif '19:00' <= state < '19:30' %}
425
{% elif '19:30' <= state < '20:00' %}
450
{% elif '20:00' <= state < '20:30' %}
465
{% elif '20:30' <= state < '21:00' %}
475
{% elif '21:00' <= state < '22:00' %}
500
{% elif '22:00' <= state < '22:30' %}
500
{% elif '22:30' <= state < '23:00' %}
500
{% else %}
500
{% endif %}
Circadian Brightness shows the brightness I want betwixt the specified times and Circadian Color Temperature obviously shows the color temp. The (found out that this doesn’t actually work){% else %}
value is RGB color for overnight nightlight giving the light a more reddish hue. This comes into play on the automation side as you’ll need to have two automations to accommodate this.
Thank you @123 and @Mutt for help with the template sensors and really overall help with my setup. Those folks are awesome!
in groups.yaml
circadian:
entities:
- light.lamp
- light.dining_bulb
- light.sengled_cabinet_strip
- light.desk_lamp
- light.back_hall_lights
add whichever entity here that you’d like to follow this circadian rhythm. At my house I have them all doing the same thing but you could create separate groups and template sensors by room or whatever if you want different areas to act differently (great room, kitchen, basement, etc.)
I also use an input_boolean used as a condition for these automations to run. When I change the color of the lights for a notification (doorbell rings, laundry done, etc.) this input_boolean is turned off. When it turns back on, triggers a “pre-color” scene.
input_boolean.yaml
circadian_on:
initial: 'on'
name: Circadian On
Next comes the automations. I have 3 for the actual lighting and 2 for the boolean. The first two are for a trigger when any entity turns from off to on. The first of those is for daytime (color_temp data in the service call) and the second is for overnight (rgb_color data in the service call) as mentioned earlier.These are now just one automation since the rgb_color wasn’t represented as a string value. In this automation, the transition is 5 seconds so the color/brightness will basically change right as the entity is turned on. The third second automation triggers at each of the time changes so if any of the lights are already on, the transition is 30 seconds so the shift in brightness and color isn’t jarring. You could make this longer but I find this to be plenty sufficient.
in automation.yaml
- id: circadian_on
alias: Circadian On Trigger
initial_state: true
trigger:
- platform: state
entity_id: light.lamp
from: 'off'
to: 'on'
- platform: state
entity_id: light.desk_lamp
from: 'off'
to: 'on'
- platform: state
entity_id: light.sengled_cabinet_strip
from: 'off'
to: 'on'
- platform: state
entity_id: light.dining_bulb
from: 'off'
to: 'on'
- platform: state
entity_id: light.back_hall_lights
from: 'off'
to: 'on'
condition:
- condition: state
entity_id: input_boolean.circadian_on
state: 'on'
action:
- service: light.turn_on
data_template:
entity_id: "{{ trigger.entity_id }}"
brightness: "{{ states('sensor.cl_brightness') }}"
color_temp: "{{ states('sensor.cl_color_temp') }}"
transition: '5'
######################################
##slow transition automation trigger##
######################################
- id: circadian_time_transition
alias: Circadian Time Transition
initial_state: true
trigger:
- platform: time
at: '05:00:00'
- platform: time
at: '06:00:00'
- platform: time
at: '06:30:00'
- platform: time
at: '07:00:00'
- platform: time
at: '07:30:00'
- platform: time
at: '08:00:00'
- platform: time
at: '09:00:00'
- platform: time
at: '16:30:00'
- platform: time
at: '17:00:00'
- platform: time
at: '17:30:00'
- platform: time
at: '18:00:00'
- platform: time
at: '18:30:00'
- platform: time
at: '19:00:00'
- platform: time
at: '19:30:00'
- platform: time
at: '20:00:00'
- platform: time
at: '20:30:00'
- platform: time
at: '21:00:00'
- platform: time
at: '22:00:00'
- platform: time
at: '22:30:00'
- platform: time
at: '23:00:00'
condition:
- condition: state
entity_id: input_boolean.circadian_on
state: 'on'
- condition: template
value_template: >
{% set lights = ['group.circadian'] %}
{{ expand(lights)|selectattr('state','eq','on')|list|length > 0 }}
action:
- service: light.turn_on
data_template:
entity_id: >
{% set lights = ['group.circadian'] %}
{{ expand(lights)|selectattr('state','eq','on')
|map(attribute='entity_id')|join(',') }}
brightness: "{{ states('sensor.cl_brightness') }}"
color_temp: "{{ states('sensor.cl_color_temp') }}"
transition: '30'
These last automations are for my input_boolean. When it turns off, it creates a pre-color scene and when it turns on, it triggers that scene.
- id: color_on_scene_create
alias: Color on Scene Create
trigger:
- platform: state
entity_id: input_boolean.circadian_on
from: 'on'
to: 'off'
condition: []
action:
- service: scene.create
data:
scene_id: before_color
snapshot_entities: #######could probably just use group.circadian here######
- light.desk_lamp
- light.sengled_cabinet_strip
- light.dining_bulb
- light.lamp
- light.back_hall_lights
##############################
- id: color_reset
alias: Reset Colors
trigger:
- platform: state
entity_id: input_boolean.circadian_on
from: 'off'
to: 'on'
action:
- service: scene.turn_on
data:
entity_id: scene.before_color
One thing to note is that when if you turn off the input_boolean in an automation, you may want to add a 1 second delay afterwards before you change the colors do allow the pre_color scene to be created properly. Might not matter but I’ve noticed occasionally that the pre_color scene didn’t capture everything before the colors change.
I hope this helps. Let me know if there’s any questions.