blueprint: name: Wake-up Sunrise (Kelvin, smooth & smart) - Fixed description: > Moderner Wecker mit Sonnenaufgangseffekt. Korrigierte Version mit sequenzieller Variablen-Berechnung. domain: automation input: light_entity: name: Ziel-Licht selector: entity: domain: light timestamp_sensor: name: Zeitstempel-Entität (optional) default: none selector: entity: device_class: timestamp manual_time: name: Manuelle Weckzeit default: "07:00:00" selector: time: {} sunrise_duration_min: name: Dauer des Sonnenaufgangs (Minuten) default: 25 selector: number: min: 5 max: 120 step: 5 unit_of_measurement: min mode: slider start_brightness_pct: name: Starthelligkeit (%) default: 3 selector: number: min: 1 max: 100 step: 1 mode: slider end_brightness_pct: name: Endhelligkeit (%) default: 100 selector: number: min: 5 max: 100 step: 1 mode: slider start_kelvin: name: Start-Kelvin (warm) default: 2200 selector: number: min: 1500 max: 9000 step: 50 unit_of_measurement: K mode: slider end_kelvin: name: End-Kelvin (kühler / tageslicht) default: 6500 selector: number: min: 1500 max: 9000 step: 50 unit_of_measurement: K mode: slider enable_color_ramp: name: Farbverlauf (RGB) statt Kelvin default: false selector: boolean: {} start_color_rgb: name: Startfarbe (RGB) default: { r: 255, g: 120, b: 20 } selector: color_rgb: {} end_color_rgb: name: Endfarbe (RGB) default: { r: 255, g: 255, b: 255 } selector: color_rgb: {} ramp_steps: name: Schrittanzahl (Glätte) default: 60 selector: number: min: 10 max: 240 step: 10 check_entity: name: Check-Entität default: none selector: entity: {} require_workday: name: Nur an Arbeitstagen default: false selector: boolean: {} workday_sensor: name: Workday-Sensor default: binary_sensor.workday selector: entity: domain: binary_sensor respect_quiet_hours: name: Ruhezeiten beachten default: false selector: boolean: {} quiet_start: name: Ruhezeit Beginn default: "22:00:00" selector: time: {} quiet_end: name: Ruhezeit Ende default: "06:00:00" selector: time: {} off_cancels: name: Ausschalten bricht ab default: true selector: boolean: {} pre_actions: name: Vor-Aktionen default: [] selector: action: {} post_actions: name: Nach-Aktionen default: [] selector: action: {} # Globale Variablen (nur statische Zuweisungen aus Inputs) variables: le: !input light_entity sensor_ts: !input timestamp_sensor manual_time: !input manual_time duration_min: !input sunrise_duration_min start_pct: !input start_brightness_pct end_pct: !input end_brightness_pct steps: !input ramp_steps enable_rgb: !input enable_color_ramp off_cancels: !input off_cancels check_entity: !input check_entity require_workday: !input require_workday workday_sensor: !input workday_sensor respect_quiet: !input respect_quiet_hours quiet_start: !input quiet_start quiet_end: !input quiet_end startK_in: !input start_kelvin endK_in: !input end_kelvin rgb_start: !input start_color_rgb rgb_end: !input end_color_rgb trigger: - platform: time_pattern minutes: "*" action: # Ebene 1: Basis-Berechnungen und Geräte-Attribute holen - variables: seconds: "{{ (duration_min | float(25)) * 60 }}" range_pct: "{{ (end_pct | float) - (start_pct | float) }}" minK_native: "{{ state_attr(le, 'min_color_temp_kelvin') }}" maxK_native: "{{ state_attr(le, 'max_color_temp_kelvin') }}" minM: "{{ state_attr(le, 'min_mireds') }}" maxM: "{{ state_attr(le, 'max_mireds') }}" sr: "{{ rgb_start[0] | int }}" sg: "{{ rgb_start[1] | int }}" sb: "{{ rgb_start[2] | int }}" er: "{{ rgb_end[0] | int }}" eg: "{{ rgb_end[1] | int }}" eb: "{{ rgb_end[2] | int }}" supported_modes: "{{ state_attr(le, 'supported_color_modes') | default([]) }}" # Ebene 2: Berechnungen, die auf Ebene 1 basieren (z.B. device_k_min) - variables: device_k_min: >- {% if minK_native is number %}{{ minK_native | int }} {% elif maxM is number %}{{ (1000000 / (maxM | float)) | int }} {% else %}2000{% endif %} device_k_max: >- {% if maxK_native is number %}{{ maxK_native | int }} {% elif minM is number %}{{ (1000000 / (minM | float)) | int }} {% else %}6500{% endif %} tick: >- {% set t = (seconds | float) / (steps | float) %} {{ [ t, 1 ] | max | int }} can_rgb: >- {{ 'hs' in supported_modes or 'rgb' in supported_modes or 'rgbw' in supported_modes or 'rgbww' in supported_modes or 'xy' in supported_modes }} can_ct: >- {{ 'color_temp' in supported_modes or minM is number or minK_native is number or maxM is number or maxK_native is number }} # Ebene 3: Finale Kelvin-Werte und Bedingungen - variables: startK_clamped: >- {% set s1 = [startK_in | int, device_k_min] | max %} {{ [s1, device_k_max] | min }} endK_clamped: >- {% set e1 = [endK_in | int, device_k_min] | max %} {{ [e1, device_k_max] | min }} cond_check_entity_ok: >- {{ check_entity == 'none' or states(check_entity) in ['on','home','unknown'] }} cond_workday_ok: >- {{ (not require_workday) or (is_state(workday_sensor, 'on')) }} cond_quiet_ok: >- {% if not respect_quiet %}true {% else %} {% set nowt = now().time() %} {% set qs = strptime(quiet_start, '%H:%M:%S').time() %} {% set qe = strptime(quiet_end, '%H:%M:%S').time() %} {% if qs <= qe %}{{ not (nowt >= qs and nowt < qe) }} {% else %}{{ not (nowt >= qs or nowt < qe) }}{% endif %} {% endif %} # Ebene 4: Finalisierung der Kelvin-Werte - variables: start_kelvin_final: "{{ [startK_clamped, endK_clamped] | min }}" end_kelvin_final: "{{ [startK_clamped, endK_clamped] | max }}" # --- Ablauf --- - wait_template: >- {{ sensor_ts == 'none' or as_timestamp(states(sensor_ts), None) != None }} - wait_template: >- {% set alarm_ts = as_timestamp(sensor_ts != 'none' and states(sensor_ts) or (states('sensor.date') ~ ' ' ~ manual_time)) %} {% set now_ts = as_timestamp(now()) %} {{ 0 < (alarm_ts - now_ts) <= (seconds | float) and cond_check_entity_ok and cond_workday_ok and cond_quiet_ok }} - choose: [] default: !input pre_actions - condition: template value_template: "{{ cond_check_entity_ok and cond_workday_ok and cond_quiet_ok }}" - choose: - conditions: "{{ enable_rgb and can_rgb }}" sequence: - service: light.turn_on target: entity_id: !input light_entity data: brightness_pct: "{{ start_pct | int }}" rgb_color: ["{{ sr }}","{{ sg }}","{{ sb }}"] transition: 1 - conditions: "{{ can_ct }}" sequence: - service: light.turn_on target: entity_id: !input light_entity data: brightness_pct: "{{ start_pct | int }}" color_temp_kelvin: "{{ start_kelvin_final | int }}" transition: 1 default: - service: light.turn_on target: entity_id: !input light_entity data: brightness_pct: "{{ start_pct | int }}" transition: 1 - repeat: while: - >- {% set alarm_ts = as_timestamp(sensor_ts != 'none' and states(sensor_ts) or (states('sensor.date') ~ ' ' ~ manual_time)) %} {{ 0 < (alarm_ts - as_timestamp(now())) <= (seconds | float) }} - "{{ not (off_cancels and is_state(le, 'off')) }}" sequence: - delay: seconds: "{{ tick | int }}" - variables: alarm_ts: >- {{ as_timestamp(sensor_ts != 'none' and states(sensor_ts) or (states('sensor.date') ~ ' ' ~ manual_time)) }} remain: "{{ (alarm_ts - as_timestamp(now())) | float }}" frac: "{{ (remain / (seconds | float)) | float }}" bri_now: "{{ ((end_pct | float) - ((range_pct | float) * frac)) | round(0) | int }}" r_now: "{{ (sr + (er - sr) * (1 - frac)) | round(0) | int }}" g_now: "{{ (sg + (eg - sg) * (1 - frac)) | round(0) | int }}" b_now: "{{ (sb + (eb - sb) * (1 - frac)) | round(0) | int }}" kelv_now: "{{ ((end_kelvin_final | float) - ((end_kelvin_final | float - start_kelvin_final | float) * frac)) | round(0) | int }}" - choose: - conditions: "{{ enable_rgb and can_rgb }}" sequence: - service: light.turn_on target: entity_id: !input light_entity data: brightness_pct: "{{ [bri_now, 1] | max }}" rgb_color: ["{{ r_now }}","{{ g_now }}","{{ b_now }}"] transition: "{{ [ (tick | int) - 1, 0 ] | max }}" - conditions: "{{ can_ct }}" sequence: - service: light.turn_on target: entity_id: !input light_entity data: brightness_pct: "{{ [bri_now, 1] | max }}" color_temp_kelvin: "{{ kelv_now }}" transition: "{{ [ (tick | int) - 1, 0 ] | max }}" default: - service: light.turn_on target: entity_id: !input light_entity data: brightness_pct: "{{ [bri_now, 1] | max }}" transition: "{{ [ (tick | int) - 1, 0 ] | max }}" - choose: - conditions: "{{ enable_rgb and can_rgb }}" sequence: - service: light.turn_on target: entity_id: !input light_entity data: brightness_pct: "{{ end_pct | int }}" rgb_color: ["{{ er }}","{{ eg }}","{{ eb }}"] transition: 1 - conditions: "{{ can_ct }}" sequence: - service: light.turn_on target: entity_id: !input light_entity data: brightness_pct: "{{ end_pct | int }}" color_temp_kelvin: "{{ end_kelvin_final | int }}" transition: 1 default: - service: light.turn_on target: entity_id: !input light_entity data: brightness_pct: "{{ end_pct | int }}" transition: 1 - choose: [] default: !input post_actions mode: single max_exceeded: silent