Light by Time, Sun, and Brightness: Sunrise, Sunset, Offset, Lux

Module 20 · Lesson 12

Light by Time, Sun, and Brightness: Sunrise, Sunset, Offset, Lux

The sun tells you what part of the day you're in. Lux tells you whether it's actually dark in a specific spot. Presence and the home's mode tell you whether a light is needed at all. A household member's manual decision always comes first.

Lesson 11 handled motion. Here you're building light without a motion sensor: the Evening scene, a day-frame built on the sun, and a separate path for an overcast day. Don't merge everything into one careless OR. Build a stable sunset trigger first, then presence and modes, then a manual override, and lux last. Further on I'll shorten Home Assistant to HA.

Plan on about 110 to 120 minutes. Syntax: triggers / conditions / actions with action:.

This lesson's rule
The Evening automation and the overcast-day automation are two different functions. Don't merge them into one trigger without thinking through the consequences.

A real-life problem: a light at 6pm in summer and winter

A "living room at 6pm" schedule turns on too early in summer and too late in winter. Sunset with an offset helps: but if you add an "after sunset" condition to a trigger firing 20 minutes before sunset, the two contradict each other. Or: a lux-OR-sunset trigger turns on the living room during a storm at 10am. Or: a closed blind lowers the lux reading and turns on the light even though nobody's there.

A trigger, a condition, and an action are three different things

  • The trigger: sunset, or a drop in lux, starts a check.
  • The conditions: the system checks the home's mode, presence, lockouts, and the light's current state.
  • The action: only once the conditions pass does it trigger a scene or a single light.

What takes priority

  1. A household member's manual decision.
  2. An active manual override.
  3. A special mode: Movie, Guests, Cleaning, Night, or Away.
  4. Household member presence.
  5. Global permission for automation.
  6. The day's frame, set by the sun or by time.
  7. Lux, as a refinement.
  8. Triggering the scene.

hallway_motion_lockout (Lesson 11) blocks hallway motion: not the sun-based schedule or the Evening scene. When lighting_automation_enabled is off, motion, sun, lux, and schedule automations don't trigger. Manual control and deliberately triggered scenes still work. light_mode records the last deliberately chosen logical mode: not confirmation that a scene fully executed.

Sunrise, sunset, and offset

HA calculates sunrise and sunset from the location set under Settings → System → General. Check the coordinates, the time zone (Europe/Warsaw), open the sun.sun entity, and compare next_rising / next_setting against your local calendar. A wrong location after a migration produces wrong times.

How to read an offset

-00:20:00 means 20 minutes before sunset. +00:20:00 means 20 minutes after sunset. The sign refers to the solar event, not to brightness inside a room.

If the trigger is sunset with a -20-minute offset, don't add a condition requiring sunset to have already occurred without a matching after_offset: the condition will be false. A -15 to -30 minute offset is a decent start, but the length of twilight changes over the year. Solar elevation (e.g. below -4°) is often more stable seasonally: an option for exterior lighting. The trigger alone below shows just the turn-on step: build a separate turn-off (elevation above the threshold, or after sunrise), a limit on late-night hours, and a manual override too: otherwise the example looks like a complete automation while showing only half of it.

triggers:
  - trigger: numeric_state
    entity_id: sun.sun
    attribute: elevation
    below: -4
Seasonal illustration (New York, rounded) Sunset ~ Sunrise ~
June approx. 8:30pm approx. 5:25am
December approx. 4:30pm approx. 7:15am

The table shows the scale of the seasonal swing: it isn't design data. Your automation uses the location set in your own HA. This course assumes a typical location in the continental US; in far-northern or far-southern locations, basing things on elevation works better.

Solar time: the start of the evening, exterior lighting. Clock time: quiet hours, the end of decorative lighting. The home's mode: Movie, Guests, Night, Away. Sunrise doesn't have to unconditionally turn off every light: it can end night mode or shift thresholds instead. Decorative lighting doesn't have to stay lit until sunrise.

Stages 1-3: the Evening scene after sunset

The automation triggers the local scene.living_room_evening from Lesson 10: no motion-controlled hallway. Don't duplicate brightness values in the YAML. Don't trigger a full Evening scene when nobody's home. Filter by mode: only normal / evening (reject movie, guests, cleaning, night, away).

timer:
  living_room_manual_override:
    name: Living room light manual override
    duration: "00:30:00"
    restore: true

Start the timer from remotes and manual scenes (Movie, Guests, a manual turn-off): not from every light change, since the Evening scene itself also changes entities. The sunset automation only runs while timer.living_room_manual_override == idle.

Presence: create a group of people, or use match: any across several person.* entities. Don't copy group.household without actually creating it. Phone-based location isn't infallible: don't rely on it for safety; it's acceptable as a comfort signal. Just home alone can trigger the living room even when everyone's in other rooms: as you expand the system, you can add presence within the daytime zone; at the start, don't over-complicate things if the scene is gentle.

- id: living_room_evening
  alias: Living room - trigger the Evening scene
  description: >
    Triggers the Evening scene before sunset, or once automation is
    re-enabled, if evening conditions still apply.
  mode: single

  triggers:
    - trigger: sun
      event: sunset
      offset: "-00:20:00"
      id: sunset

    - trigger: state
      entity_id: input_boolean.lighting_automation_enabled
      to: "on"
      id: automation_enabled

  conditions:
    - condition: state
      entity_id: input_boolean.lighting_automation_enabled
      state: "on"

    - condition: state
      entity_id: group.household
      state: "home"

    - condition: state
      entity_id: input_select.light_mode
      state:
        - "normal"
        - "evening"

    - condition: state
      entity_id: timer.living_room_manual_override
      state: "idle"

    - condition: sun
      after: sunset
      after_offset: "-00:20:00"
      before: sunrise

    - condition: state
      entity_id: light.living_room_ceiling
      state: "off"

  actions:
    - action: scene.turn_on
      target:
        entity_id: scene.living_room_evening
      data:
        transition: 3

The sun condition with after_offset is mainly needed for the second trigger (re-enabling the helper later). With the sunset-minus-20-minutes trigger alone, it's often redundant. The light.living_room_ceiling == off condition limits risk: it doesn't cover the whole scene; the override helper is the safer backstop. Turning permission back on after sunset can immediately trigger the Evening scene, if every condition is met: that's intentional; don't mistake it for a bug.

Fallback after a restart, or a missed sunset: the sunset trigger fires at the moment of the event. If HA was down, the moment passes and the scene never starts. The second trigger (re-enabling the helper) plus an "it's evening" condition helps. At homeassistant start you can add a trigger, but wait for entities to become available: don't trigger the scene while a person's state is unknown or the light is unavailable. Night mode shouldn't get reverted back to Evening after a restart.

Don't unconditionally turn things off at 11:30pm: you might switch off Movie mode, Guests, or someone working. A better approach: a reminder, a conditional transition into Night mode, or a manual Night button.

Stage 4: a separate overcast-day automation

Sunset doesn't know about clouds. Lux shouldn't act as a random 24-hour replacement for sunset. Separate them: A = a standard evening (no lux required), B = an unusually dark day (a separate trigger, an hour window, a gentler scene).

With an AND (sunset and lux), you need both triggers, and both conditions checked again at each one: otherwise the sunset moment with lux at 55 falls through. A for: clause on lux doesn't survive an HA restart or an automation reload. Lux from a motion sensor often only updates when motion occurs. Once a lamp turns on, lux rises: use lux only for the initial turn-on, not to keep forcing the scene continuously. Add hysteresis: check lux once within the day's window, not every few minutes.

No lux data: for Evening, sunset works on its own (fail evening). For decorative lighting, you can choose not to turn it on (fail dark). Lux being unavailable shouldn't block the whole evening.

- id: living_room_cloudy_day
  alias: Living room - gentle light on a very dark day
  description: >
    Turns on gentle lighting when lux stays low for a sustained period.
    Doesn't trigger in the morning or during special modes.
  mode: single

  triggers:
    - trigger: numeric_state
      entity_id: sensor.living_room_lux
      below: 35
      for: "00:10:00"

  conditions:
    - condition: state
      entity_id: input_boolean.lighting_automation_enabled
      state: "on"

    - condition: state
      entity_id: group.household
      state: "home"

    - condition: time
      after: "12:00:00"
      before: "22:30:00"

    - condition: state
      entity_id: input_select.light_mode
      state: "normal"

    - condition: state
      entity_id: light.living_room_ceiling
      state: "off"

    - condition: state
      entity_id: timer.living_room_manual_override
      state: "idle"

  actions:
    - action: scene.turn_on
      target:
        entity_id: scene.living_room_cloudy
      data:
        transition: 3
A lux sensor tuning card
Room: ..................................................
Sensor model: ..................................................
Mounting location: ..................................................
Lux on a bright day: ..................................................
Lux on an overcast day: ..................................................
Lux with the blind closed: ..................................................
Lux after turning on the lamp: ..................................................
Automatic turn-on threshold: ..................................................
Threshold hold duration: ..................................................
Behavior on unavailable: ..................................................
Test date: ..................................................

Stage 5: blinds and their effect on lux

A blind's position can explain low lux, but it doesn't replace an actual measurement. A value of 50% is often just an estimate of travel time, and for Venetian blinds it doesn't describe the slat angle at all. Treat it as a supporting signal, not an absolute condition. Watch the attribute: check it's actually a number: a missing attribute defaulting to 0 looks exactly like a closed blind.

In Lesson 13, a blind can shade the living room from heat. If Lesson 12's logic reacts to every drop in lux: the blind closes → the light turns on. Possible strategies: don't turn it on during Away mode; a gentle light only when someone's present; task lighting instead of the ceiling; or a separate living_room_shaded scene.

Arriving home: without overriding Movie mode

The Arriving scene from Lesson 10: don't trigger the living room just because a phone entered a 200-meter zone. Better: the mudroom door or motion, plus low lux or Night mode. Add a condition: the house was previously empty (light_mode = away, or this is the first person returning). Geofencing can prime the system: an entryway light once the door opens. Don't restore global automation with the Arriving scene without a separate decision.

- id: entryway_light_after_dark
  alias: Entryway - light after dark
  mode: single
  description: Optional, separate from the living room Evening scene.

  triggers:
    - trigger: numeric_state
      entity_id: sun.sun
      attribute: elevation
      below: -4

  conditions:
    - condition: state
      entity_id: input_boolean.lighting_automation_enabled
      state: "on"

  actions:
    - action: light.turn_on
      target:
        entity_id: light.entryway
      data:
        brightness_pct: 40

Tests

☐ Movie mode active before sunset: the Evening scene doesn't override it.
☐ A manual turn-off 5 minutes before sunset: it doesn't turn back on (the override is idle).
☐ Guests mode: lux doesn't change the scene.
☐ The helper is off during sunset: nothing starts; once re-enabled, the fallback re-checks conditions.
☐ An HA restart right at sunset, and again 30 minutes later.
☐ Reload the automation before and after a scheduled sunset.
☐ Traces: which trigger fired, which condition stopped execution, whether the scene actually started.
☐ Lux history: update frequency, the lamp's own effect on the reading, availability after a restart.

A -20-minute offset combined with an "after sunset" condition that lacks a matching after_offset.

One OR: sunset or low lux, checked around the clock.

hallway_motion_lockout used as a condition on the Evening scene.

An unconditional shutoff at 11:30pm overriding Movie mode or Guests.

A phone arriving home overrides a partner's Movie mode.

Hands-on exercise

☐ Check Home Assistant's location and time zone.
☐ Open the sun.sun entity and record the next sunrise and sunset.
☐ Build a simple Evening-scene automation on sunset with an offset first.
☐ Add a condition that at least one household member is home.
☐ Add a condition for an acceptable light mode.
☐ Add the living room's manual override and test Movie, Guests, and a manual turn-off.
☐ Test what happens when global automation is off during sunset.
☐ Test an HA restart at the scheduled moment of sunset.
☐ Only after several days of observation, add the separate low-lux automation.
☐ Check the lux sensor's update frequency and how your own lamp affects the reading.
☐ Define behavior for lux unknown and unavailable.
☐ Treat a blind's position as a supporting signal, not the only condition.
☐ Don't add an unconditional shutoff at 11:30pm.
☐ Record your results on the lux tuning card.

Key takeaways

  • The sun sets the day's frame, but it doesn't know about clouds, blinds, or household presence.
  • A negative offset triggers automation before sunset, and a positive one after sunset.
  • Don't combine a before-sunset trigger with a condition that requires sunset without a matching offset.
  • Lux should be a separate refinement layer, not a careless substitute for time.
  • The Evening automation and the overcast-day automation should stay separate.
  • Low lux shouldn't trigger the living room when nobody's home, or when Movie, Guests, Night, or Away mode applies.
  • Manual control and a special mode take priority over sunset and lux.
  • hallway_motion_lockout isn't a lockout on sun-based schedules.
  • Lux from a motion sensor can update rarely, and can be lit up by its own lamp.
  • A for: clause on lux doesn't preserve its countdown across a restart or an automation reload.
  • A closed blind can explain low lux, but its percentage position may only be an estimate.
  • A sunset trigger can get missed while HA is down; you need a deliberate fallback.
  • A fixed-hour shutoff can't override Movie, Guests, or a manual decision.
  • You roll out sunset first, then presence and modes, then a manual override, and lux last.

In Lesson 13 you'll combine blinds with temperature and the sun. Before moving on, the Evening scene should work with presence and modes: without fighting Movie mode.

Finished this lesson?