Motion Sensing and Illuminance Threshold based Lights Automation that Dims and Changes Color Temperature according to Sun Elevation

I made some automations to keep my lighting tied to my circadian rhythm. It’s based on the sun’s state, an illuminance sensor in each room, and motion sensors as well.

Having a setup like this will likely reduce your energy consumption. It will also allow you to utilize cooler/warmer temperature and brightness dynamically to make use of your programmable lights and dimmer switches.

If the automation does not turn off your lights make sure you selected entities with the light target not devices. (Click the device one more time to expand to it’s related entity)

blueprint:
   name: Lights by presence with illuminance and sunrise/sunset brightness variance
   description: Turn on a light when motion is detected and sunset.
   domain: automation
   input:
     motion_entity:
       name: Motion Sensor
       selector:
         entity:
           domain: binary_sensor
           device_class: motion
           multiple: false
     illuminance_entity:
       name: Illuminance Sensor
       selector:
         entity:
           domain: sensor
           device_class: illuminance
           multiple: false
     light_target:
       name: Light
       selector:
         target:
           entity:
             domain: light
     illuminance_threshold:
         name: Illuminance Threshold
         description: The amount of allowable illuminance below which, the lights will turn on
         default: 50
         selector:
           number:
             min: 0
             max: 100
             unit_of_measurement: percent
             step: 1.0
             mode: slider
     no_motion_wait:
       name: Wait time
       description: Time to leave the light on after last motion is detected.
       default: 120
       selector:
         number:
           min: 0.0
           max: 3600.0
           unit_of_measurement: seconds
           step: 1.0
           mode: slider
     min_sun_elevation:
       name: Min Solar Elevation
       description: The lowest point the sun gets to relative to the horizon.
       default: -27
       selector:
         number:
           min: -90
           max: 90
           unit_of_measurement: degrees
           step: 1.0
           mode: slider
     max_sun_elevation:
       name: Max Solar Elevation
       description: The highest point the sun gets to relative to the horizon.
       default: 90
       selector:
         number:
           min: -90
           max: 90
           unit_of_measurement: degrees
           step: 1.0
           mode: slider
     min_brightness:
       name: Min Brightness
       description: The brightness to use when the sun is at the lowest point the sun gets to relative to the horizon.
       default: 25
       selector:
         number:
           min: 0
           max: 255
           unit_of_measurement: units
           step: 1.0
           mode: slider
     max_brightness:
       name: Max Brightness
       description: The brightness to use when the sun is at the highest point the sun gets to relative to the horizon.
       default: 255
       selector:
         number:
           min: 0
           max: 255
           unit_of_measurement: units
           step: 1.0
           mode: slider
     min_color_temp:
       name: Min Color Temperature
       description: The temperature to use when the sun is at the lowest point the sun gets to relative to the horizon.
       default: 370
       selector:
         color_temp:
           min_mireds: 153
           max_mireds: 370
     max_color_temp:
       name: Max Color Temperature
       description: The temperature to use when the sun is at the highest point the sun gets to relative to the horizon.
       default: 275
       selector:
         color_temp:
           min_mireds: 153
           max_mireds: 370
 mode: restart
 max_exceeded: silent
 variables:
   lights: !input light_target
   min_sun_elevation: !input min_sun_elevation
   max_sun_elevation: !input max_sun_elevation
   min_brightness: !input min_brightness
   max_brightness: !input max_brightness
   min_color_temp: !input min_color_temp
   max_color_temp: !input max_color_temp
 trigger:
   platform: state
   entity_id: !input motion_entity
   from: 'off'
   to: 'on'
 action:
 - condition: or
   conditions:
     - condition: numeric_state
       entity_id: !input illuminance_entity
       below: !input illuminance_threshold
     - "{{ expand(lights.entity_id) | selectattr('state', '==', 'on') | list | count > 0 }}"
 - service: light.turn_on
   target: !input light_target
   data:
     brightness: "{{ (state_attr('sun.sun', 'elevation') - min_sun_elevation) / (max_sun_elevation - min_sun_elevation) * (max_brightness - min_brightness) + min_brightness }}"
     color_temp: "{{ (state_attr('sun.sun', 'elevation') - min_sun_elevation) / (max_sun_elevation - min_sun_elevation) * (max_color_temp - min_color_temp) + min_color_temp }}"
 - wait_for_trigger:
     platform: state
     entity_id: !input motion_entity
     from: 'on'
     to: 'off'
 - delay: !input no_motion_wait
 - service: light.turn_off
   target: !input light_target

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

If you have some lights on a simple dumb on/off type switch I also made another automation:

blueprint:
   name: Switches by presence with illuminance
   description: Turn on a light when motion is detected and brightness inside is below an illuminance threshold.
   domain: automation
   input:
     motion_entity:
       name: Motion Sensor
       selector:
         entity:
           domain: binary_sensor
           device_class: motion
           multiple: false
     illuminance_entity:
       name: Illuminance Sensor
       selector:
         entity:
           domain: sensor
           device_class: illuminance
           multiple: false
     light_target:
       name: Switch
       selector:
         target:
           entity:
             domain: switch
     illuminance_threshold:
       name: Illuminance threshold
       description: The percentage of illuminance below which, the lights will turn on.
       default: 50
       selector:
         number:
           min: 0.0
           max: 100.0
           unit_of_measurement: percent
           step: 1.0
           mode: slider
     no_motion_wait:
       name: Wait time
       description: Time to leave the light on after last motion is detected.
       default: 120
       selector:
         number:
           min: 0.0
           max: 3600.0
           unit_of_measurement: seconds
           step: 1.0
           mode: slider
 mode: restart
 max_exceeded: silent
variables:
   lights: !input light_target
 trigger:
   platform: state
   entity_id: !input motion_entity
   from: 'off'
   to: 'on'
 action:
 - condition: or
   conditions:
     - condition: numeric_state
       entity_id: !input illuminance_entity
       below: !input illuminance_threshold
     - "{{ expand(lights.entity_id) | selectattr('state', '==', 'on') | list | count > 0 }}" 
 - service: switch.turn_on
   target: !input light_target
 - wait_for_trigger:
     platform: state
     entity_id: !input motion_entity
     from: 'on'
     to: 'off'
 - delay: !input no_motion_wait
 - service: switch.turn_off
   target: !input light_target

The switch only blueprint is here:

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

I couldn’t post both at once.

It currently has a bug where the lights come on at night and illuminance goes to 100% then the lights don’t turn off. Anyone who finds this useful and knows how to add a condition to check that the light_target has any light currently on so that the script will still get through the conditions in that case, please let me know.

It seems I need to follow this strategy here:

I will update the gists, and there should be no requirement to update automations.xml if you’ve already applied automation from this blueprint.

I updated the blueprint to the latest working version which utilizes a second condition with “OR” logic to address whether the lights are already on. This will allow the time to reset with motion, but reach the turn-off service call at the end after the timeout is expired.

Update your blueprints as needed. It will work when you drill down your locations or devices so that only entities are selected when you choose which lights to use the automation for.

This didn’t seem to work by night if sun elevation goes below the min setting… I don’t mind a perfect setting of the elevation, more important is it continues to obey to the min brightness setting, so with this change it seems to work. My lights also show the temp going up to 500 so enlarging it to 500 looks better.

--- blueprints/automation/arosboro/presence-lights.yaml.orig
+++ blueprints/automation/arosboro/presence-lights.yaml
@@ -101,20 +101,20 @@
       name: Min Color Temperature
       description: The temperature to use when the sun is at the lowest point the
         sun gets to relative to the horizon.
-      default: 370
+      default: 500
       selector:
         color_temp:
           min_mireds: 153
-          max_mireds: 370
+          max_mireds: 500
     max_color_temp:
       name: Max Color Temperature
       description: The temperature to use when the sun is at the highest point the
         sun gets to relative to the horizon.
-      default: 275
+      default: 200
       selector:
         color_temp:
           min_mireds: 153
-          max_mireds: 370
+          max_mireds: 500
   source_url: https://gist.github.com/arosboro/8e4a05f08ef31f7fae095ba1175973e4
 mode: restart
 max_exceeded: silent
@@ -142,12 +142,14 @@
 - service: light.turn_on
   target: !input light_target
   data:
-    brightness: '{{ (state_attr(''sun.sun'', ''elevation'') - min_sun_elevation) /
+    brightness: '{{ min(max_brightness, max(min_brightness,
+      (state_attr(''sun.sun'', ''elevation'') - min_sun_elevation) /
       (max_sun_elevation - min_sun_elevation) * (max_brightness - min_brightness)
-      + min_brightness }}'
-    color_temp: '{{ (state_attr(''sun.sun'', ''elevation'') - min_sun_elevation) /
+      + min_brightness)) }}'
+    color_temp: '{{ min(min_color_temp, max(max_color_temp,
+      (state_attr(''sun.sun'', ''elevation'') - min_sun_elevation) /
       (max_sun_elevation - min_sun_elevation) * (max_color_temp - min_color_temp)
-      + min_color_temp }}'
+      + min_color_temp)) }}'
 - wait_for_trigger:
     platform: state
     entity_id: !input motion_entity