Skip to content

Instantly share code, notes, and snippets.

@haberda
Last active July 28, 2024 23:02
Show Gist options
  • Save haberda/f17694969a6de15d75267667b7c955ac to your computer and use it in GitHub Desktop.
Save haberda/f17694969a6de15d75267667b7c955ac to your computer and use it in GitHub Desktop.
Periodic lights
blueprint:
name: Periodic lights
description: "Dim and adjust color temperature of lights progressively throughout the evening (RGB bulbs probably won't change temperature). This is indexed to the midpoint between sunset and sunrise and fit to a sin function, so the midpoint will be minimum brightness and midpoint +12hr will be maximum brightness. The midpoint can be offset by a fixed amount if lights are too dim or bright at the desired time."
domain: automation
source_url: https://gist.github.com/haberda/f17694969a6de15d75267667b7c955ac
input:
light:
name: Light(s)
description: The light(s) to control
selector:
entity:
multiple: true
domain: light
min_brightness:
name: Minimum Brightness
description: Minimum brightness of the light(s)
default: 1
selector:
number:
min: 0.0
max: 100.0
mode: slider
step: 1.0
unit_of_measurement: "%"
max_brightness:
name: Maximum Brightness
description: Maximum brightness of the light(s)
default: 100
selector:
number:
min: 0.0
max: 100.0
mode: slider
step: 1.0
unit_of_measurement: "%"
min_temperature:
name: Minimum Temperature
description: Minimum temperature of the light(s) (Kelvin)
default: 2200
selector:
number:
min: 1800
max: 6000
mode: slider
step: 100.0
unit_of_measurement: "K"
max_temperature:
name: Maximum Temperature
description: Maximum temperature of the light(s) (Kelvin)
default: 5000
selector:
number:
min: 1800
max: 6000
mode: slider
step: 100.0
unit_of_measurement: "K"
threshold_brightness:
name: Brightness change threshold
description: Threshold value, above which the lights will not be adjusted (+ or -). This is the residual value between the current brightness level and the level it would adjust to.
default: 10
selector:
number:
min: 0.0
max: 100.0
mode: slider
step: 1.0
unit_of_measurement: "%"
transition:
name: Transition
description: Transition time (s)
default: 0
selector:
number:
min: 0.0
max: 30.0
mode: slider
step: 1.0
unit_of_measurement: "s"
midnight_offset:
name: Offset middle of the night
description: Offset from middle of the night (e.g. dimmest lights). Positive for brighter evening and dimmer morning. Negative for dimmer evening and brighter morning.
default: 0
selector:
number:
min: -120.0
max: 120.0
step: 1.0
unit_of_measurement: min
mode: slider
light_on_adjust:
name: Adjust lights when they are turned on
description: "If true adjusts a light immediately when it is turned on."
default: true
selector:
boolean:
entity_off_adjust:
name: Adjust lights when disable entity is turned off
description: "If true adjusts a light immediately when the disable entity is turned off."
default: true
selector:
boolean:
disable_entity:
name: Disable entity
description: Binary sensor or input boolean that when on disables the updating of lights.
selector:
entity:
multiple: true
event_fired:
name: Event
description: The name of the event that will force an update.
default: "periodic_lights"
mode: parallel
max_exceeded: silent
variables:
light_list: !input "light"
threshold_brightness: !input "threshold_brightness"
min_brightness: !input "min_brightness"
max_brightness: !input "max_brightness"
min_temperature: !input "min_temperature"
max_temperature: !input "max_temperature"
midnight_offset: !input "midnight_offset"
light_on_adjust: !input light_on_adjust
entity_off_adjust: !input entity_off_adjust
pct: >
{% if (states('sun.sun') == 'below_horizon') %}
{% set sunset = as_timestamp(states.sun.sun.attributes.next_setting)|float - 86400 %}
{% set sunrise = as_timestamp(states.sun.sun.attributes.next_rising)|float %}
{% else %}
{% set sunset = as_timestamp(states.sun.sun.attributes.next_setting)|float %}
{% set sunrise = as_timestamp(states.sun.sun.attributes.next_rising)|float %}
{% endif %}
{% set midpoint = (sunset |float + sunrise |float) / 2 + (midnight_offset|float * 60) | float %}
{{ sin(((as_timestamp(now())|float - midpoint)/86400)*pi) |abs }}
brightness_percent: "{{ (min_brightness|int+(max_brightness|int-min_brightness|int) * pct) | int }}"
kelvin_temperature: "{{ (min_temperature|int+(max_temperature|int-min_temperature|int) * pct) | int }}"
on_lights: >
{{ expand(light_list) | selectattr('state', 'eq', 'on')
| map(attribute='entity_id') | list }}
compliant_lights: >
{{ expand(on_lights) | selectattr('attributes.brightness','ge',((brightness_percent-threshold_brightness)*2.55))
| selectattr('attributes.brightness','le',((brightness_percent+threshold_brightness)*2.55))
| map(attribute='entity_id') | list }}
# brightness_lights: >
# {{ expand(on_lights) | selectattr('attributes.color_mode','eq','brightness')
# | map(attribute='entity_id') | list }}
# color_temp_lights: >
# {{ expand(on_lights) | selectattr('attributes.color_mode','in',['color_temp','white'])
# | map(attribute='entity_id') | list }}
# color_lights: >
# {{ expand(on_lights) | selectattr('attributes.color_mode','in',['xy','rgb','rgbw','rgbww','HS'])
# | map(attribute='entity_id') | list }}
trigger:
- platform: time_pattern
minutes: "/5"
id: "time_change"
- platform: state
entity_id: !input "light"
to: "on"
id: "light_on"
- platform: state
entity_id: !input "disable_entity"
to: "off"
id: "disable_off"
- platform: event
event_type: !input event_fired
id: "event_fired"
condition:
- condition: state
entity_id: !input disable_entity
state: "off"
- condition: template
value_template: "{{ on_lights|length > 0 }}"
action:
- delay:
hours: 0
minutes: 0
seconds: 0
milliseconds: 500
- choose:
- conditions:
- or:
- condition: trigger
id: "event_fired"
- and:
- condition: trigger
id: "disable_off"
- condition: template
value_template: "{{ entity_off_adjust }}"
sequence:
- service: light.turn_on
data:
entity_id: "{{ on_lights }}"
brightness_pct: "{{ brightness_percent|int }}"
kelvin: "{{ kelvin_temperature|int }}"
transition: !input transition
- conditions:
- condition: trigger
id: "light_on"
- condition: template
value_template: "{{ light_on_adjust }}"
sequence:
- service: light.turn_on
data:
entity_id: "{{ trigger.entity_id }}"
brightness_pct: "{{ brightness_percent|int }}"
kelvin: "{{ kelvin_temperature|int }}"
default:
- condition: template
value_template: "{{ compliant_lights|length > 0 }}"
- service: light.turn_on
data:
entity_id: "{{ compliant_lights }}"
brightness_pct: "{{ brightness_percent|int }}"
kelvin: "{{ kelvin_temperature|int }}"
transition: !input transition
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment