New to HA and wanted to say thanks for this blueprint, it provided a great base for the functionality I wanted.
I’ve added support to add a speaker that slowly increases the volume in combination with the light. This is tested with a Sonos speaker (IKEA Symfonisk). I’m using IKEA Trådfri bulbs so I also had to do some minor changes to how brightness is set. I’ve also added the possibility to lock the color temperature to the set value (incase you want to only increase brightness) and fixed some minor issues with the timestamps.
The issue with the timestamps came from that sensor.time_date_time_iso doesn’t include the timezone information while now() does. So when converted to timestamps, they give different times.
{{states('sensor.date_time_iso')}} = 2022-01-08T20:05:00
{{now()}} = 2022-01-08 20:05:00.004820+01:00
When converted, these should give the same time but
{{as_timestamp(states('sensor.date_time_iso'))}} = 1641672300.0
{{as_timestamp(now())}} = 1641668700.004835
This problem also applies when setting the time manually as
states(''sensor.date'') ~ '' '' ~ manual_time)
also lacks information about the timezone.
Below is my full code with the added functionality and fixes incase it’s useful for someone.
EDIT: I fell victim for the “never post anything until fully tested”. Fixed the code below.
blueprint:
name: Wake-up light and music alarm with sunrise effect and increasing volume
description: 'A wake-up light and music alarm with a brightness and color temperature sunrise effect and increasing volume.
Note: Requires date_time_iso sensor in configuration, not manually executable!'
domain: automation
input:
light_entity:
name: Wake-up light entity
description: The light to control. Turning it off during the sunrise will keep
it off. Color temperature range is auto-detected.
selector:
entity:
domain: light
speaker_entity:
name: Wake-up speaker entity
description: The speaker to control. Turning it off during the wake-up will keep
it off.
selector:
entity:
domain: media_player
music_source:
name: Sound source
description: What the speaker should play
selector:
select:
options:
- Radio Nova
- Radio SuomiPop
timestamp_sensor:
name: Alarm timestamp sensor
description: 'Sensor with timestamp of next alarm with device_class: timestamp
(set to ''none'' for manual alarm time)'
default: none
selector:
entity:
device_class: timestamp
manual_time:
name: Manual alarm time
description: Time to trigger alarm every day if timestamp sensor is not set.
Settings at or shortly after midnight will not work as expected!
default: '7:00:00'
selector:
time: {}
check_entity:
name: Additional entity to check before wake-up is triggered
description: If set, checks if entity is 'on' or 'home' before triggering. Use
e.g. a (workday) sensor, device_tracker or person entity.
default: none
selector:
entity: {}
wakeup_duration:
name: Wake-up duration
description: The wake-up will start the configured number of minutes before
the timestamp.
default: 25
selector:
number:
min: 5.0
max: 60.0
step: 5.0
unit_of_measurement: min
mode: slider
start_brightness:
name: Minimum brightness in percentage
description: The brightness to start with. Some lights ignore very low values
and may turn on with full brightness instead!
default: 1
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
end_brightness:
name: Maximum brightness in percentage
description: The brightness will be transitioned from the minimum to the configured
value.
default: 100
selector:
number:
min: 5.0
max: 100.0
step: 1.0
mode: slider
min_mired:
name: Minimum color temperature
description: 'The minimum color temperature to use. (0: lowest supported)'
default: 0
selector:
number:
min: 0.0
max: 500.0
step: 5.0
mode: slider
unit_of_measurement: mired
lock_mired:
name: Lock color temperature
description: Lock the color temperature to the selected minimum temperature
default: false
selector:
boolean:
start_volume:
name: Minimum volume
description: The volume to start with
default: 1
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
end_volume:
name: Maximum volume
description: The volume will be transitioned from the minimum to the configured
value.
default: 20
selector:
number:
min: 5.0
max: 100.0
step: 1.0
mode: slider
pre_wakeup_actions:
name: Pre-wakeup actions
description: Optional actions to run before wake-up starts.
default: []
selector:
action: {}
post_wakeup_actions:
name: Post-wakeup actions
description: Optional actions to run after wake-up ends (around the alarm time).
default: []
selector:
action: {}
variables:
light_entity: !input 'light_entity'
speaker_entity: !input 'speaker_entity'
music_source: !input 'music_source'
sensor: !input 'timestamp_sensor'
wakeup_duration: !input 'wakeup_duration'
start_brightness: !input 'start_brightness'
end_brightness: !input 'end_brightness'
range_brightness: '{{float(end_brightness) - float(start_brightness)}}'
min_mired: !input 'min_mired'
lock_mired: !input 'lock_mired'
start_mired: '{{state_attr(light_entity, ''max_mireds'')}}'
end_mired: '{{[state_attr(light_entity, ''min_mireds'') | int(0), min_mired | int(0)] | max}}'
range_mired: '{{float(start_mired) - float(end_mired)}}'
start_volume: !input 'start_volume'
end_volume: !input 'end_volume'
range_volume: '{{float(end_volume) - float(start_volume)}}'
manual_time: !input 'manual_time'
seconds: '{{float(wakeup_duration) * 60}}'
tick_time: '{{float(seconds) / float(range_brightness)}}'
check_entity: !input 'check_entity'
trigger:
- platform: time_pattern
minutes: '*'
action:
- wait_template: '{{sensor == ''none'' or as_timestamp(states(sensor), None) != None}}'
- wait_template: '{{0 < as_timestamp(states(sensor) if sensor != ''none'' else (states(''sensor.date'') ~ '' '' ~ manual_time) | as_datetime() | as_local())
- as_timestamp(now()) <= float(seconds) and states(check_entity) in [''unknown'', ''on'', ''home'']}}'
- choose: []
default: !input 'pre_wakeup_actions'
- condition: template
value_template: '{{sensor == ''none'' or as_timestamp(states(sensor), None) != None}}'
- condition: template
value_template: '{{0 < as_timestamp(states(sensor) if sensor != ''none'' else (states(''sensor.date'') ~ '' '' ~ manual_time) | as_datetime() | as_local())
- as_timestamp(now()) <= float(seconds) and states(check_entity) in [''unknown'', ''on'', ''home'']}}'
- choose:
- conditions:
- '{{state_attr(light_entity, ''min_mireds'') != None}}'
sequence:
- service: light.turn_on
data:
brightness_pct: '{{start_brightness}}'
color_temp: '{{end_mired + 1 if lock_mired else start_mired}}'
entity_id: !input 'light_entity'
default:
- service: light.turn_on
data:
brightness_pct: '{{start_brightness}}'
entity_id: !input 'light_entity'
- service: media_player.volume_set
data:
volume_level: '{{float(start_volume / 100)}}'
entity_id: !input 'speaker_entity'
- service: media_player.select_source
data:
source: !input 'music_source'
entity_id: !input 'speaker_entity'
- repeat:
while:
- '{{sensor == ''none'' or as_timestamp(states(sensor), None) != None}}'
- '{{0 < as_timestamp(states(sensor) if sensor != ''none'' else (states(''sensor.date'') ~ '' '' ~ manual_time) | as_datetime() | as_local())
- as_timestamp(now()) <= float(seconds)}}'
sequence:
- delay: '{{tick_time}}'
- choose:
- conditions:
- '{{0 < state_attr(light_entity, ''brightness'') | int(0) < float(end_brightness) / 100 * 255 | int(0)}}'
sequence:
- choose:
- conditions:
- '{{state_attr(light_entity, ''min_mireds'') != None}}'
sequence:
- service: light.turn_on
data:
brightness_pct: '{{float(end_brightness) - ([0, float(range_brightness) * (as_timestamp(states(sensor) if sensor != ''none'' else (states(''sensor.date'') ~ '' '' ~ manual_time) | as_datetime() | as_local())
- as_timestamp(now())) / seconds, float(end_brightness)]|sort)[1] | round(0)}}'
color_temp: '{{end_mired if lock_mired else
float(end_mired) + ([0, float(range_mired) * (as_timestamp(states(sensor) if sensor != ''none'' else (states(''sensor.date'') ~ '' '' ~ manual_time) | as_datetime() | as_local())
- as_timestamp(now())) / seconds, float(start_mired)]|sort)[1] | round(0)}}'
entity_id: !input 'light_entity'
default:
- service: light.turn_on
data:
brightness_pct: '{{float(end_brightness) - ([0, float(range_brightness) * (as_timestamp(states(sensor) if sensor != ''none'' else (states(''sensor.date'') ~ '' '' ~ manual_time) | as_datetime() | as_local())
- as_timestamp(now())) / seconds, float(end_brightness)]|sort)[1] | round(0)}}'
entity_id: !input 'light_entity'
- choose:
- conditions:
- '{{0 < state_attr(speaker_entity, ''volume_level'') * 100 | round(0) < float(end_volume) - ([0, float(range_volume) * (as_timestamp(states(sensor) if sensor != ''none'' else (states(''sensor.date'') ~ '' '' ~ manual_time) | as_datetime() | as_local())
- as_timestamp(now())) / seconds, float(end_volume)]|sort)[1] | round(0) <= float(end_volume)}}'
sequence:
- service: media_player.volume_set
data:
volume_level: '{{(float(end_volume) - ([0, float(range_volume) * (as_timestamp(states(sensor) if sensor != ''none'' else (states(''sensor.date'') ~ '' '' ~ manual_time) | as_datetime() | as_local())
- as_timestamp(now())) / seconds, float(end_volume)]|sort)[1]) / 100 | round(2)}}'
entity_id: !input 'speaker_entity'
- choose: []
default: !input 'post_wakeup_actions'
mode: single
max_exceeded: silent