Adaptive Lighting
I want to have several of my lights adapt to the outside brightness. For Home Assistant Bas Nijholt created the fantastic Adaptive Lighting custom component. However there is one downside, this integration doesn't support brightness based on external sensors. Although there is apparently a workaround. That's why I choose to roll my own using an automation.
Prerequisites
- An illuminance entity, I use a max average over an hour for a smoother experience
- The Sun integration (for color temperature)
- Knowledge of your:
- Minimum and maximum illuminance
- Minimum and maximum light brightness
- Minimum and maximum color temperature (optional)
Automation
Note
This automation can be pretty resource intensive. Because of the loop and the constant light.turn_on
service calls. Normally it shouldn't be a problem. Mostly because of the built-in delays. But you should monitor your resource usage when first trying this out.
- id: office_adaptive_lighting
alias: Office - adaptive lighting
mode: restart
variables:
# Which illuminance entity to use
illuminance_entity: 'sensor.light_sensors_illuminance_max_average_1_hour'
# Whether or not to continue adjust the brightness
continuous_adjustment: true
# Minimal outside illuminance (in lux)
minimal_illuminance: 5
# Maximal outside illuminance (in lux)
maximal_illuminance: 4000
# Minimal light brightness, will be mapped to minimal illuminance
minimal_brightness: 10
# Maximal light brightness, will be mapped to maximal illuminance
maximal_brightness: 128
# Whether color temperature adjustment is also enabled
color_temp_adjustment: true
# Minimal color temp (higher value = warmer)
minimal_color_temp: 350
# Maximal color temp (lower value = cooler)
maximal_color_temp: 250
trigger:
# Trigger when our light turns on
- platform: state
entity_id: light.office
from: 'off'
to: 'on'
# Trigger on Home Assistant (re)start
- platform: homeassistant
event: start
condition:
# Always check if the light is on before continuing.
- condition: state
entity_id: light.office
state: 'on'
action:
# Repeat for continuously adjustment
repeat:
sequence:
- service: light.turn_on
target:
entity_id: light.office
data:
# The brightness is mapped from the input values to the output values
brightness: >-
{% set illuminance = states(illuminance_entity) | int(0) %}
{% set input_start = minimal_illuminance | int(0) %}
{% set input_end = maximal_illuminance | int(0) %}
{% set output_start = minimal_brightness | int(0) %}
{% set output_end = maximal_brightness | int(0) %}
{{ [[(illuminance - input_start) / (input_end - input_start) * (output_end - output_start) + output_start, output_end] | min, output_start] | max }}
# Add a transition for a smoother experience (optional)
transition: "{{ (iif(repeat.first, 1, 5) | int(0)) }}"
- delay:
seconds: "{{ (iif(repeat.first, 1, 5) | int(0)) }}"
- service: light.turn_on
target:
entity_id: light.office
data:
# Inspired from: https://community.home-assistant.io/t/template-entity-to-guess-the-outside-colour-temperature/402510
color_temp: >-
{% if (color_temp_adjustment | default(false)) %}
{{ [ [ (1000000/(4791.67 - 3290.66/(1 + 0.222 * [ [ 0, state_attr('sun.sun', 'elevation') ] | max, 90 ] | min**0.81)))|int, (maximal_color_temp|int(0)) ] | max, (minimal_color_temp|int(0)) ] | min }}
{% else %}
{{ state_attr('light.office', color_temp) }}
{% endif %}
# Add a transition for a smoother experience (optional)
transition: "{{ (iif(repeat.first, 1, 3) | int(0)) }}"
- wait_for_trigger:
# Wait for a illuminance change
- platform: state
entity_id: sensor.light_sensors_illuminance_max_average_1_hour
# Wait for the light to turn off
- platform: state
entity_id: light.office
to: 'off'
timeout:
minutes: 15
continue_on_timeout: true
# Add a delay to lower resource usage
- delay:
minutes: 1
until:
or:
# Continue until continuous_adjustment = off
- condition: template
value_template: "{{ (continuous_adjustment | default(false)) == false }}"
# Continue until it is below our minimal illuminance (too dark)
- condition: template
value_template: "{{ (states(illuminance_entity) | int(0)) <= (minimal_illuminance | int(0)) }}"
# Continue until the light is off
- condition: state
entity_id: light.office
state: 'off'
# Continue until the light is unavailable
- condition: state
entity_id: light.office
state: 'unavailable'
for:
minutes: 1