How to automate lights dynamically based on time of day?

Hi all!

I’m stuck in my mind trying to automate my lights. To make it simple, I’ll focus on one light.

What I’d like to do is one light to cycle it’s brightness, colour temperature/colour based on the time of the day. For example, at 14:00 when I work from home, I would like the light to display a cool blue light at 255 brightness. Then, at 20:00, it should be a warm white on a 149 brightness, while at 22:00 it should be red (xy_color) with a brightness of 79, etc. I’ve made a list of the values I’d like per time of day.

At the moment, I’m using a 6 scenes to cycle trough this configuration. I call them using a script with a transition, and that works nice. I’m really happy with how the lights behave! I did it to help my circadian rhythm - I’m up north and in winter there is barely any sun, and in the summer it’s there all the time. I am aware of the circadian plugin, but I’m quite sure it’s not what I’m looking for.

The problem, however, is for example when I arrive home at 21:53. It will activate the latest scene; the one of 20:00, which is not fitting for that moment. The same for when my chromecast changes to ‘stop’ (disactivating the movie lights mode), and the lights turn on to their normal state, it’s usually way too bright.

Using the list from the picture, I would like to use the time to calculate the brightness, colour etc. For example, turning on the lights at 20:45 takes the times of 20:00 and 21:00 and calculates the according brightness: 123:

149+((114-149)*45/60)
oldBrightness+((newBrightness-oldBrightness)*currentMinute/60)

I tried to do this using a script, but it didn’t know how to get it to work properly, this is what I got at the moment;

ceiling_default_sate:
  alias: Ceiling Default State
  variables:
    current_hour: now().hour
    brightness: [8,8,8,8,8,8,43,79,114,149,184,220,255,255,255,255,255,255,220,184,149,114,79,43]
    color_temperature: [500,500,500,500,500,500,500,500,500,500,500,414,153,153,153,153,153,153,414,500,500,500,500,500]
    x_color: [0.689,0.689,0.689,0.689,0.689,0.689,0.689,0,0,0,0,0,0,0,0,0,0,0,0,0,0.539,0.581,0.675,0.689]
    y_color: [0.309,0.309,0.309,0.309,0.309,0.309,0.309,0,0,0,0,0,0,0,0,0,0,0,0,0,0.392,0.387,0.392,0.309]
  sequence:
  - service: light.turn_on
    data:
      entity_id: light.ceiling
      brightness: {{ brightness[current_hour] }}
      rgb_color: 179,255,251
  mode: single
  icon: mdi:ceiling-light

I think that should give a good idea of what I’m trying to do.

My question is, do you have a tip for me where to start with this project? I’ve done a lot of googling and looking around on the forum, but can’t find the right terms. Do you know of a blueprint, tutorial, documentation or anything else that can get me started with this? I can get into programming it too if that’s easier. Thanks a lot!

1 Like

Have you seen this?

1 Like

I was going to say… this is already 100% done and working perfectly with a simple integration in my home!

Out-of-the-box:

1 Like

Ooh, pretty. Does this have manual override similar to adaptive lighting? That is something that I use a LOT when I want to mess with the light levels then have them reset next time I turn on.

Don’t know about adaptive lightning, but Flux integration is represented as a switch to enable or disable Flux anytime.

Hi all! Late reply, but thanks for your help. I looked at the links but it’s not exactly what I wanted, so I decided to tinker some more myself :slight_smile:

I made scenes for every hours of the evening. During the day, the scenes are full bright daylight. I’ve made two scripts;

The first script sets the scene based on time. Lets say it’s 18:20, it will first set the scene to the one of 18:00, then turn on the scene for 19:00 with a delay of 3 second (60/20), however, after 1 second (so 33% into its transition), the same scene is triggered (19:00 again), but then with a transition time of ((60 - 20) *60) seconds. 60 is the minutes in an hour, 20 is the minutes in the current hour, times 60 for 60 seconds in a minute.

set_current_scene:
  alias: Set the current scene
  sequence:
  - service: scene.turn_on
    data:
      entity_id: >
        {% if ((states.sensor.time.state > '00:00') and (states.sensor.time.state < '07:00')) %}
          scene.00_00
        {% elif ((states.sensor.time.state > '07:00') and (states.sensor.time.state < '11:00')) %}
          scene.18_00
        {% elif ((states.sensor.time.state > '11:00') and (states.sensor.time.state < '17:00')) %}
          scene.11_00
        {% elif ((states.sensor.time.state > '17:00') and (states.sensor.time.state < '18:00')) %}
          scene.17_00
        {% elif ((states.sensor.time.state > '18:00') and (states.sensor.time.state < '19:00')) %}
          scene.18_00
        {% elif ((states.sensor.time.state > '19:00') and (states.sensor.time.state < '20:00')) %}
          scene.19_00
        {% elif ((states.sensor.time.state > '20:00') and (states.sensor.time.state < '21:00')) %}
          scene.20_00
        {% elif ((states.sensor.time.state > '21:00') and (states.sensor.time.state < '22:00')) %}
          scene.21_00
        {% elif ((states.sensor.time.state > '22:00') and (states.sensor.time.state < '23:00')) %}
          scene.22_00
        {% elif ((states.sensor.time.state > '23:00') and (states.sensor.time.state < '00:00')) %}
          scene.23_00
        {% else %}
          scene.18_00
        {% endif %}
      transition: 1
  - delay: '1'
  - service: scene.turn_on
    data:
      entity_id: >
        {% if ((states.sensor.time.state > '00:00') and (states.sensor.time.state < '06:00')) %}
          scene.00_00
        {% elif ((states.sensor.time.state > '06:00') and (states.sensor.time.state < '10:00')) %}
          scene.18_00
        {% elif ((states.sensor.time.state > '10:00') and (states.sensor.time.state < '16:00')) %}
          scene.11_00
        {% elif ((states.sensor.time.state > '16:00') and (states.sensor.time.state < '17:00')) %}
          scene.17_00
        {% elif ((states.sensor.time.state > '17:00') and (states.sensor.time.state < '18:00')) %}
          scene.18_00
        {% elif ((states.sensor.time.state > '18:00') and (states.sensor.time.state < '19:00')) %}
          scene.19_00
        {% elif ((states.sensor.time.state > '19:00') and (states.sensor.time.state < '20:00')) %}
          scene.20_00
        {% elif ((states.sensor.time.state > '20:00') and (states.sensor.time.state < '21:00')) %}
          scene.21_00
        {% elif ((states.sensor.time.state > '21:00') and (states.sensor.time.state < '22:00')) %}
          scene.22_00
        {% elif ((states.sensor.time.state > '22:00') and (states.sensor.time.state < '23:00')) %}
          scene.23_00
        {% elif ((states.sensor.time.state > '23:00') and (states.sensor.time.state < '00:00')) %}
          scene.00_00
        {% else %}
          scene.18_00
        {% endif %}
      transition: >
        {{ 60 / now().minute }}
  - delay: '1'
  - service: scene.turn_on
    data:
      entity_id: >
        {% if ((states.sensor.time.state > '00:00') and (states.sensor.time.state < '06:00')) %}
          scene.00_00
        {% elif ((states.sensor.time.state > '06:00') and (states.sensor.time.state < '10:00')) %}
          scene.18_00
        {% elif ((states.sensor.time.state > '10:00') and (states.sensor.time.state < '16:00')) %}
          scene.11_00
        {% elif ((states.sensor.time.state > '16:00') and (states.sensor.time.state < '17:00')) %}
          scene.17_00
        {% elif ((states.sensor.time.state > '17:00') and (states.sensor.time.state < '18:00')) %}
          scene.18_00
        {% elif ((states.sensor.time.state > '18:00') and (states.sensor.time.state < '19:00')) %}
          scene.19_00
        {% elif ((states.sensor.time.state > '19:00') and (states.sensor.time.state < '20:00')) %}
          scene.20_00
        {% elif ((states.sensor.time.state > '20:00') and (states.sensor.time.state < '21:00')) %}
          scene.21_00
        {% elif ((states.sensor.time.state > '21:00') and (states.sensor.time.state < '22:00')) %}
          scene.22_00
        {% elif ((states.sensor.time.state > '22:00') and (states.sensor.time.state < '23:00')) %}
          scene.23_00
        {% elif ((states.sensor.time.state > '23:00') and (states.sensor.time.state < '00:00')) %}
          scene.00_00
        {% else %}
          scene.18_00
        {% endif %}
      transition: >
        {% if now().minute > 0 %}
          {{ (60 - now().minute) * 60}}
        {% else %}
          {{ 60 * 60 }}
        {% endif %}

The second script is called every hour if the lights are on, to transition them to the next hour, over the course of 60*60 = 3600 seconds.

set_transition_next_scene:
  alias: Loop through the scene
  sequence:
  - service: scene.turn_on
    data:
      entity_id: >
        {% if ((states.sensor.time.state > '00:00') and (states.sensor.time.state < '06:00')) %}
          scene.00_00
        {% elif ((states.sensor.time.state > '06:00') and (states.sensor.time.state < '10:00')) %}
          scene.18_00
        {% elif ((states.sensor.time.state > '10:00') and (states.sensor.time.state < '16:00')) %}
          scene.11_00
        {% elif ((states.sensor.time.state > '16:00') and (states.sensor.time.state < '17:00')) %}
          scene.17_00
        {% elif ((states.sensor.time.state > '17:00') and (states.sensor.time.state < '18:00')) %}
          scene.18_00
        {% elif ((states.sensor.time.state > '18:00') and (states.sensor.time.state < '19:00')) %}
          scene.19_00
        {% elif ((states.sensor.time.state > '19:00') and (states.sensor.time.state < '20:00')) %}
          scene.20_00
        {% elif ((states.sensor.time.state > '20:00') and (states.sensor.time.state < '21:00')) %}
          scene.21_00
        {% elif ((states.sensor.time.state > '21:00') and (states.sensor.time.state < '22:00')) %}
          scene.22_00
        {% elif ((states.sensor.time.state > '22:00') and (states.sensor.time.state < '23:00')) %}
          scene.23_00
        {% elif ((states.sensor.time.state > '23:00') and (states.sensor.time.state < '00:00')) %}
          scene.00_00
        {% else %}
          scene.18_00
        {% endif %}
      transition: >
        {% if now().minute > 0 %}
          {{ (60 - now().minute) * 60 }}
        {% else %}
          {{ 60 * 60 }}
        {% endif %}

I’ve just finished it, it seems to work! Although I didn’t do a full day with it yet, it seems that especially the first script works great.

Again, thanks for the help!! :smiley:

if you are not against NodeRed you can check my project. It makes possible to create own curves of light changes during a day. You may make curves related to sun phases or hours or mix it to your liking

One thing I think you may have overlooked, is that during the time the sun is setting, and it’s starting to get dark, I want the lights brighter. Then as it gets even darker, then I want the lights softer. So the brightness curve should be very low (or no) light during the bright daylight hours, then as it starts to get dark, lights would turn on, and have increasing brightness up until that dusky time, where the lights should again soften as it gets darker.