Skip to content

Instantly share code, notes, and snippets.

@sbyx
Last active December 17, 2024 16:36
Show Gist options
  • Save sbyx/96c43b13b90ae1c35b872313ba1d2d2d to your computer and use it in GitHub Desktop.
Save sbyx/96c43b13b90ae1c35b872313ba1d2d2d to your computer and use it in GitHub Desktop.
Home Assistant Blueprint: Wake-up light alarm with sunrise effect
blueprint:
name: Wake-up light alarm with sunrise effect
description: 'A wake-up light alarm with a brightness and color temperature sunrise
effect. 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
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 sunrise 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: {}
sunrise_duration:
name: Sunrise duration
description: The sunrise 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
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: 255.0
step: 1.0
mode: slider
end_brightness:
name: Maximum brightness
description: The brightness will be transitioned from the minimum to the configured
value.
default: 254
selector:
number:
min: 5.0
max: 255.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
pre_sunrise_actions:
name: Pre-sunrise actions
description: Optional actions to run before sunrise starts.
default: []
selector:
action: {}
post_sunrise_actions:
name: Post-sunrise actions
description: Optional actions to run after sunrise ends (around the alarm time).
default: []
selector:
action: {}
source_url: https://gist.github.com/sbyx/96c43b13b90ae1c35b872313ba1d2d2d
variables:
light_entity: !input 'light_entity'
sensor: !input 'timestamp_sensor'
sunrise_duration: !input 'sunrise_duration'
start_brightness: !input 'start_brightness'
end_brightness: !input 'end_brightness'
range_brightness: '{{float(end_brightness)-float(start_brightness)}}'
manual_time: !input 'manual_time'
seconds: '{{float(sunrise_duration) * 60}}'
min_mired: !input 'min_mired'
start_mired: '{{state_attr(light_entity, ''max_mireds'')}}'
end_mired: '{{[state_attr(light_entity, ''min_mireds'')|int(0), min_mired|int(0)]|max}}'
tick_time: '{{float(seconds) / float(range_brightness)}}'
check_entity: !input 'check_entity'
trigger:
- platform: time_pattern
minutes: '*'
condition: []
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_timestamp(states(''sensor.date_time_iso'')) <= float(seconds)
and states(check_entity) in [''unknown'', ''on'', ''home'']}}'
- choose: []
default: !input 'pre_sunrise_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_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: '{{start_brightness}}'
color_temp: '{{start_mired}}'
entity_id: !input 'light_entity'
default:
- service: light.turn_on
data:
brightness: '{{start_brightness}}'
entity_id: !input 'light_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_timestamp(now()) <= float(seconds)}}'
sequence:
- delay: '{{tick_time}}'
- choose:
- conditions:
- '{{0 < state_attr(light_entity, ''brightness'') | int(0) < end_brightness |
int}}'
- '{{sensor == ''none'' or as_timestamp(states(sensor), None) != None}}'
- '{{0 < as_timestamp(states(sensor) if sensor != ''none'' else states(''sensor.date'')
~ '' '' ~ manual_time) - as_timestamp(now()) <= float(seconds)}}'
sequence:
- choose:
- conditions:
- '{{state_attr(light_entity, ''min_mireds'') != None}}'
sequence:
- service: light.turn_on
data:
brightness: '{{(float(end_brightness) - (float(range_brightness) *
(as_timestamp(states(sensor) if sensor != ''none'' else states(''sensor.date'')
~ '' '' ~ manual_time) - as_timestamp(now())) / float(seconds)))
| int(0)}}'
color_temp: '{{(float(end_mired) + (float(start_mired) - float(end_mired))
* ((as_timestamp(states(sensor) if sensor != ''none'' else states(''sensor.date'')
~ '' '' ~ manual_time) - as_timestamp(now())) / float(seconds)))
| int(0)}}'
entity_id: !input 'light_entity'
default:
- service: light.turn_on
data:
brightness: '{{(float(end_brightness) - (float(range_brightness) * (as_timestamp(states(sensor)
if sensor != ''none'' else states(''sensor.date'') ~ '' '' ~ manual_time)
- as_timestamp(now())) / float(seconds))) | int(0)}}'
entity_id: !input 'light_entity'
- choose: []
default: !input 'post_sunrise_actions'
mode: single
max_exceeded: silent
@hwinkel
Copy link

hwinkel commented Oct 4, 2023

in regards to use RGB Lights with Red, Orange, Warmwhite, White Sequence, it seems another Project has done this calculation already:

https://community.home-assistant.io/t/sunrise-simulator-wake-up-gently-to-light/493778

@rednas201
Copy link

The reason could be that that I updated my home assistant recently, but currently this blueprint doesn't work anymore for me.
It keeps waiting at the second wait sequence.
image

When I debug the lines of code and simplify it a bit, I see it has to do with the timezone
image

In the screenshot, I set the next alarm at 23.20 and the current time is 23:06. With a sunrise time of 20 minutes, the value should be true already.
When I subtract the next alarm time and current time, I end up with a negative number. This is due to the fact that the next alarm time is not converted to my timezone (+2) when it is converted to a timestamp.
With my limited programming knowledge I tried everything to make the conversion right, but I didn't manage yet.
Oddly enough that this has worked in the past....
Anyone any idea on how to solve this?

@MoritzTockner
Copy link

The reason could be that that I updated my home assistant recently, but currently this blueprint doesn't work anymore for me. It keeps waiting at the second wait sequence. image

When I debug the lines of code and simplify it a bit, I see it has to do with the timezone image

In the screenshot, I set the next alarm at 23.20 and the current time is 23:06. With a sunrise time of 20 minutes, the value should be true already. When I subtract the next alarm time and current time, I end up with a negative number. This is due to the fact that the next alarm time is not converted to my timezone (+2) when it is converted to a timestamp. With my limited programming knowledge I tried everything to make the conversion right, but I didn't manage yet. Oddly enough that this has worked in the past.... Anyone any idea on how to solve this?

Same problem for me.

@fuxifex
Copy link

fuxifex commented Jan 20, 2024

Same for me .. stopped working since the last HA update :(

In 'template' condition: ValueError: Template error: as_timestamp got invalid input 'unknown' when rendering template '{{0 < as_timestamp(states(sensor) if sensor != 'none' else states('sensor.date') ~ ' ' ~ manual_time) - as_timestamp(states('sensor.date_time_iso')) <= float(seconds) and states(check_entity) in ['unknown', 'on', 'home']}}' but no default was specified

Has anyone managed to repair it themselves?

@ChristophHandschuh
Copy link

ChristophHandschuh commented Jan 20, 2024

FIXED the error!
Heres the fixed Blueprint. Works only with sensor. Manual timesetting is not supported.

Change this part of the code:

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_timestamp(now()) <= float(seconds)
    and states(check_entity) in [''unknown'', ''on'', ''home'']}}'
  • choose: []

basically changes as_timestamp(states('sensor.date_time_iso') to: as_timestamp(now())

@triplepoint
Copy link

triplepoint commented Jan 21, 2024

I don't understand why this blueprint uses this idiom of states("sensor.date") ~ " " ~ manual_time to construct a string for "today at the manual_time time".

today_at(manual_time) returns an equivalent value, except that it has the timezone offset attached. But since this blueprint is always using these strings as parameters for as_timestamp(), these are all equivalent:

{{ as_timestamp(states("sensor.date") ~ " " ~ "07:01:00") }}
{{ as_timestamp(now().date() ~ " " ~ "07:01:00") }}
{{ as_timestamp(today_at("07:01:00")) }}
1705762860.0
1705762860.0
1705762860.0

I'm testing a variant that doesn't need sensor.date and sensor.date_time_iso, have a look at https://gist.github.com/triplepoint/1b9006ddec208a07fc0100a2a30110eb

@rednas201
Copy link

@triplepoint Works for me! I owe you a big thanks!! My setup is working again.

@Delvint
Copy link

Delvint commented Aug 8, 2024

The reason why this querqy manual time computation is needed is the mqtt automation over Sleep As Android.

The manual time stamp format seems deprected or whatever. That is the reason why some mentioned defaulting to 0 would solve the problem. But it does not really solve it. I could by adding a markup for the time string to begin:
{{ states(''sensor.date'') ~ '' '' ~ manual_time }}
{{ states(''sensor.date'') ~ ''T'' ~ manual_time }}

The two time stamp computation produce different outputs.
{{ as_timestamp(states('sensor.date_time_iso')) }} # 1723102440.0
{{ as_timestamp(now()) }} # 1723098900.217016
I dont know why both are used. But I replaced every occurence of now() with states('sensor.date_time_iso') and it worked.

Have a look at: https://gist.github.com/Delvint/a4203ab90ec3000c590acb7bf16f6d86

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment