this post was submitted on 10 Feb 2026
1 points (100.0% liked)

Home Assistant

259 readers
2 users here now

Home Assistant is open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY...

founded 2 years ago
MODERATORS
 
This is an automated archive made by the Lemmit Bot.

The original was posted on /r/homeassistant by /u/crua9 on 2026-02-10 15:09:21+00:00.


I figure I might as well share this because I'm sure others will get some use out of this. Something to note is I use my bathroom door sensor to tell if I'm up because I don't have a motion in my room. This can be replaced with pretty much anything you want.

Anyways I based this on science and pretty much all my automations in the description I list the rules and other bits because I have bad memory at times, and if someone else works on it or I might need to mess with it down the road. I can easily see what is going on. I figure I might as well share the rules first so if you can see if you want it.

______

Rules:

  1. At 2:30 AM this grabs the next alarm that will happen on my phone. It then subtracts 60 minutes.
  2. If no time is set or out of bounds if it is a school day base on the calendar, then it will default to 6AM. If not then 8am. In bounds is 3:30 AM - 11 AM
  3. If the event is running, and I go to the bathroom. Assume I am up and end the lock/event.
  4. If the event has ran, don't run it again that day.
  5. If the event has ran, lock other events which might overwrite the lights for this room.
  6. If my protection toggle is on (my bedroom motion) then don't trigger this event. (sick or whatever and I need my rest)

The lighting events are as follows:

  1. Ignition (T+0m to T+10m): Ramps to deep Red/Brown (RGB 68, 28, 0) at 25% brightness.
  2. Dawn (T+10m to T+20m): Ramps to warm Salmon/Orange (RGB 160, 85, 68) at 51% brightness.
  3. Rise (T+20m to T+30m): Switches to Kelvin; ramps to Neutral White (4239K) at 75% brightness.
  4. Peak (T+30m to T+40m): Ramps to Cool Daylight (6500K) at 100% brightness.
  5. Soak (T+40m+): Maintains max brightness for 30 minutes (plus an optional 20m post-alarm buffer).

Scientific Basis:

  1. The Curve (Weber-Fechner Law): Uses a segmented ramp to counter the eye's logarithmic perception of brightness. By stepping intensity alongside color temperature, it creates a "perceptually linear" dawn rather than a sudden glare, mimicking the changing angle of solar elevation.
  2. Start (Melatonin Sparing via Rayleigh Scattering): Begins with long-wavelength Red/Amber (>600nm). This mimics the atmospheric scattering of early dawn. Crucially, this wavelength is invisible to Melanopsin (the protein in your eye that tracks time), allowing you to drift out of deep sleep without prematurely crushing melatonin, preventing "sleep inertia" (grogginess).
  3. End (Cortisol Awakening Response): Ramps to blue-enriched 6500K (simulating zenith daylight). This targets the ipRGC receptors (peak sensitivity ~480nm) to signal the Suprachiasmatic Nucleus. This hard-stop suppresses melatonin and triggers the natural Cortisol Awakening Response (CAR) required for alertness and circadian alignment.

_______

alias: My Bedroom Sunrise
description: >
  60-min lead: Deep Red start, Gamma ramp to 6500K, 20-min pre-alarm soak, plus
  post-alarm soak. 

  Rules: 

  1. At 2:30 AM this grabs the next alarm that will happen on my phone. It then
  subtracts 60 minutes.

  2. If no time is set or out of bounds if it is a school day base on the
  calendar, then it will default to 6AM. If not then 8am. In bounds is 3:30 AM -
  11 AM 

  3. If the event is running, and I go to the bathroom. Assume I am up and end
  the lock/event.

  4. If the event has ran, don't run it again that day. 

  5. If the event has ran, lock other events which might overwrite the lights
  for this room.

  6. If my protection toggle is on (my bedroom motion) then don't trigger this
  event. (sick or whatever and I need my rest)

  The lighting events are as follows:

  1. Ignition (T+0m to T+10m): Ramps to deep Red/Brown (RGB 68, 28, 0) at 25%
  brightness.  

  2. Dawn (T+10m to T+20m): Ramps to warm Salmon/Orange (RGB 160, 85, 68) at 51%
  brightness.  

  3. Rise (T+20m to T+30m): Switches to Kelvin; ramps to Neutral White (4239K)
  at 75% brightness.  

  4. Peak (T+30m to T+40m): Ramps to Cool Daylight (6500K) at 100% brightness.  

  5. Soak (T+40m+): Maintains max brightness for 30 minutes (plus an optional
  20m post-alarm buffer).
  6. If I haven't waked by that point or I'm not home then the lights turn off.

  Scientific Basis: 

  1. The Curve (Weber-Fechner Law): Uses a segmented ramp to counter the eye's
  logarithmic perception of brightness. By stepping intensity alongside color
  temperature, it creates a "perceptually linear" dawn rather than a sudden
  glare, mimicking the changing angle of solar elevation.

  2. Start (Melatonin Sparing via Rayleigh Scattering): Begins with
  long-wavelength Red/Amber (>600nm). This mimics the atmospheric scattering of
  early dawn. Crucially, this wavelength is invisible to Melanopsin (the protein
  in your eye that tracks time), allowing you to drift out of deep sleep without
  prematurely crushing melatonin, preventing "sleep inertia" (grogginess).

  3. End (Cortisol Awakening Response): Ramps to blue-enriched 6500K (simulating
  zenith daylight). This targets the ipRGC receptors (peak sensitivity ~480nm)
  to signal the Suprachiasmatic Nucleus. This hard-stop suppresses melatonin and
  triggers the natural Cortisol Awakening Response (CAR) required for alertness
  and circadian alignment.
triggers:
  - trigger: time
    at: "02:30:00"
    id: calculate
  - trigger: template
    id: start_sunrise
    value_template: >-
      {{ now().strftime('%H:%M') ==
      states('input_datetime.sunrise_start_time')[:5] }}
  - trigger: state
    entity_id:
      - binary_sensor.bathroom_door_sensor
    id: bathroom_trip
    to:
      - "off"
  - trigger: time
    at: "10:00:00"
    id: reset
conditions:
  - condition: state
    entity_id: input_boolean.smoke_or_co_detected
    state: "off"
  - condition: time
    after: "02:00:00"
    before: "11:00:00"
actions:
  - alias: Main logic
    choose:
      - conditions:
          - condition: trigger
            id: calculate
          - condition: state
            entity_id: input_boolean.my_bedroom_motion
            state: "off"
        sequence:
          - action: input_datetime.set_datetime
            target:
              entity_id: input_datetime.sunrise_start_time
            data:
              time: >-
                {% set alarm = states('sensor.pixel_10_pro_next_alarm') %}

                {% set t = as_datetime(alarm) %}

                {# 1. Check if alarm is valid, is set for TODAY, and is between
                5am-8am #}

                {% if alarm not in ['unavailable', 'unknown', 'none'] and t is
                not none and t.date() == now().date() and 5 <= t.hour < 8 %}
                  {% set wake = t %}
                {# 2. Fallback: School Days (6am) #}

                {% elif is_state('calendar.school_days', 'on') %}
                  {% set wake = today_at("06:00") %}
                {# 3. Fallback: Weekends (8am) #}

                {% else %}
                  {% set wake = today_at("08:00") %}
                {% endif %} 

                {# 4. Subtract 80 minutes and output #}

                {{ (wake - timedelta(minutes=60)).strftime('%H:%M:%S') }}
        alias: 2:30 AM get the alarm data
      - conditions:
          - condition: trigger
            id: start_sunrise
          - condition: state
            entity_id: input_boolean.my_bedroom_motion
            state: "off"
          - condition: state
            entity_id: input_boolean.sunrise_has_run
            state: "off"
        sequence:
          - action: input_boolean.turn_on
            target:
              entity_id:
                - input_boolean.sunrise_has_run
                - input_boolean.sunrise_active_lock
          - action: light.turn_off
            metadata: {}
            target:
              entity_id: light.my_bedroom
            data: {}
          - delay:
              hours: 0
              minutes: 0
              seconds: 2
              milliseconds: 0
          - action: light.turn_on
            target:
              entity_id: light.my_bedroom
            data:
              brightness: 65
              rgb_color:
                - 68
                - 28
                - 0
              transition: 600
          - delay: "00:10:00"
          - action: light.turn_on
            target:
              entity_id: light.my_bedroom
            data:
              brightness: 130
              rgb_color:
                - 160
                - 85
                - 68
              transition: 600
          - delay: "00:10:00"
          - action: light.turn_on
            target:
              entity_id: light.my_bedroom
            data:
              brightness: 190
              transition: 600
              color_temp_kelvin: 4239
          - delay: "00:10:00"
          - action: light.turn_on
            target:
              entity_id: light.my_bedroom
            data:
              brightness: 255
              transition: 600
              color_temp_kelvin: 6500
          - delay: "00:30:00"
          - if:
              - condition: state
                entity_id: input_boolean.sunrise_active_lock
                state: "on"
            then:
              - delay:
                  hours: 0
                  minutes: 20
                  seconds: 0
                  milliseconds: 0
              - action: light.turn_off
                target:
                  entity_id: light.my_bedroom
              - action: input_boolean.turn_off
                target:
                  ...
***
Content cut off. Read original on https://old.reddit.com/r/homeassistant/comments/1r139se/i_made_an_artificial_sunrise_that_uses_science_to/
no comments (yet)
sorted by: hot top controversial new old
there doesn't seem to be anything here