Evolution of an automation. Turn a light on/off at sunset/sunrise

A brief tutorial demonstrating how to create a single automation to control a light that is able to handle missed events (i.e. Home Assistant is off when the primary trigger(s) occur).

Implemented as two automations:

Turn on a light just before sunset
- alias: 'Scheduled Exterior On'
  trigger:
  - platform: numeric_state
    entity_id: sun.sun
    attribute: elevation
    below: 1.8
  action:
  - service: light.turn_on
    target:
      entity_id: light.exterior
Turn off a light just before sunrise
- alias: 'Scheduled Exterior Off'
  trigger:
  - platform: numeric_state
    entity_id: sun.sun
    attribute: elevation
    above: -3.1
  action:
  - service: light.turn_off
    target:
      entity_id: light.exterior

Consolidated into a single automation:

Turn light on/off just before sunset/sunrise
- alias: 'Scheduled Exterior'
  trigger:
  - platform: numeric_state
    entity_id: sun.sun
    attribute: elevation
    below: 1.8
  - platform: numeric_state
    entity_id: sun.sun
    attribute: elevation
    above: -3.1
  action:
  - service: "light.turn_{{ 'on' if trigger.below is defined and trigger.below != None else 'off' }}"
    target:
      entity_id: light.exterior

Same automation but implemented with choose:

Single automation using 'choose'
- alias: 'Scheduled Exterior'
  mode: single
  trigger:
  - platform: numeric_state
    entity_id: sun.sun
    attribute: elevation
    below: 1.8
  - platform: numeric_state
    entity_id: sun.sun
    attribute: elevation
    above: -3.1
  action:
  - variables:
      e: "{{ state_attr('sun.sun', 'elevation') | float }}"
  - choose:
    - conditions: "{{ e <= 1.8 }}"
      sequence:
      - service: light.turn_on
        target:
          entity_id: light.exterior
    - conditions: "{{ e >= -3.1 }}"
      sequence:
      - service: light.turn_off
        target:
          entity_id: light.exterior

Avoid needlessly turning the light on (or off) if it’s already on (or off).

Smarter version
- alias: 'Scheduled Evening Exterior'
  trigger:
  - platform: numeric_state
    entity_id: sun.sun
    attribute: elevation
    below: 1.8
  - platform: numeric_state
    entity_id: sun.sun
    attribute: elevation
    above: -3.1
  action:
  - variables:
      e: "{{ state_attr('sun.sun', 'elevation') | float }}"
  - choose:
    - conditions:
      - "{{ e <= 1.8 }}"
      - "{{ is_state('light.exterior', 'off') }}"
      sequence:
      - service: light.turn_on
        target:
          entity_id: light.exterior
    - conditions:
      - "{{ e >= -3.1 }}"
      - "{{ is_state('light.exterior', 'on') }}"
      sequence:
      - service: light.turn_off
        target:
          entity_id: light.exterior

Make it handle missed events; evaluate the sun’s elevation, and the light’s state, on startup.

Smartest version
- alias: 'Scheduled Exterior'
  trigger:
  - platform: numeric_state
    entity_id: sun.sun
    attribute: elevation
    below: 1.8
  - platform: numeric_state
    entity_id: sun.sun
    attribute: elevation
    above: -3.1
  - platform: homeassistant
    event: start
  action:
  - variables:
      e: "{{ state_attr('sun.sun', 'elevation') | float }}"
  - choose:
    - conditions:
      - "{{ e <= 1.8 }}"
      - "{{ is_state('light.exterior', 'off') }}"
      sequence:
      - service: light.turn_on
        target:
          entity_id: light.exterior
    - conditions:
      - "{{ e >= -3.1 }}"
      - "{{ is_state('light.exterior', 'on') }}"
      sequence:
      - service: light.turn_off
        target:
          entity_id: light.exterior
33 Likes

I have some of my lights set to on/dim unless there is some motion. My current automation just does a brightness pct 100 to get it to maximum brightness. When no longer motion I do a brightness pct back to 40%.

But what if the light is already at 100% or 40%?

Could we expand on the masterclass code above to include brightness pct? I’d like to improve my automations to not fire off an action when it is not needed for changing the % brightness. Could the line above

- "{{ is_state('light.exterior', 'on') }}"

be expanded to allow for (in english) “Is the brightness already 40%/100%”

Thank you!!

No because brightness_pct is not an attribute, it’s an option for the light.turn_on service.

What you can use is a light entity’s brightness attribute. It only exists when a light is on. The value of brightness ranges from 0 to 255 so 40% corresponds to 255 x 0.4 = 102.

This checks for brightness exceeding 40%.

- "{{ is_state('light.exterior', 'on') and state_attr('light.exterior', 'brightness') >= 102 }}"

If you want it to confirm brightness is exactly 40% or 100% (corresponding to 102 or 255) then you can do this:

- "{{ is_state('light.exterior', 'on') and state_attr('light.exterior', 'brightness') in [102, 255] }}"
1 Like

This should definitely be in the FAQ…

2 Likes

Hello,

Thanks a lot for this automaiton.
I would like to modify the second condition and turn off the light not at elevation above -3.1, but at a specific time. Say 1AM.
There is probably a variable to add and conditions to change, but I can’t get my head around it…
Thanks in advance for your help.

More examples are needed. Can somebody post one with time platform as trigger?

I tried copying-pasting the code and get the error when trying to save it Message malformed: extra keys not allowed @ data['0'] I’m not sure what I’m doing wrong when trying to import this code.

Nor are we with that little information. Which code did you copy, and where did you put it? Taras’ code doesn’t even have data in it.

Copying code from 3½-year old posts isn’t always the best idea.

My bad for the limited info.

I’m trying to implement the code that is the “smartest version” inf the first post:

I would want an automation to run in case it got missed; for example HA restarts and it so happens that it was sunset, thus the automation wasn’t triggered.

I tried also re-building the code but can’t seem to get it to work. If there is any direction you point me.

Add an HA start event as a trigger and have a condition to check for sunset.