blueprint:
  name: Dim lights based on sun elevation
  description: Adjust brightness of lights based on the current sun elevation. If
    force debug is enabled, you need to execute this automation manually or let Home
    Assitant restart before the change take effect.
  source_url: https://github.com/EvTheFuture/homeassistant-blueprints/blob/master/blueprints/dim_lights_based_on_sun_elevation.yaml
  domain: automation
  input:
    target_lights:
      name: Lights
      description: The lights to control the brightness of
      selector:
        target:
          entity:
            domain: light
    max_brightness:
      name: Maximum brightness percent
      description: Brightness to set as the maximum brightness
      default: 100
      selector:
        number:
          min: 2.0
          max: 100.0
          unit_of_measurement: '%'
          mode: slider
          step: 1.0
    min_brightness:
      name: Minimum brightnes percent
      description: Brightness to set as the minimum brightness
      default: 1
      selector:
        number:
          min: 1.0
          max: 99.0
          unit_of_measurement: '%'
          mode: slider
          step: 1.0
    reverse:
      name: Reverse brightness
      description: If checked, light will start dim when sun starts to set (start
        elevation value) and will be at full brightness when the elevation has reached
        the end elevation value.
      default: false
      selector:
        boolean: {}
    allowance:
      name: Change Allowance
      description: How much can the brightnes be changed without this automation stop
        updating the brightness. If set to 0% this automation will stop update the
        brightness if the brightness has been changed at all since the last triggering
        of this automation. If set to 100% this automation will keep on and update
        the brightness even if you have manually changed the brightness to any other
        value since the last trigger.
      default: 0
      selector:
        number:
          min: 0.0
          max: 100.0
          unit_of_measurement: '%'
          mode: slider
          step: 1.0
    turn_on:
      name: Turn on lights automatically
      description: Turn on lights when sun is setting.
      default: false
      selector:
        boolean: {}
    start_elevation_setting:
      name: Elevation of the sun to start dim the light when the sun is setting
      default: 0
      selector:
        number:
          min: -60.0
          max: 60.0
          unit_of_measurement: °
          mode: slider
          step: 0.5
    end_elevation_setting:
      name: Elevation of the sun when the light shall be fully dimmed when the sun
        is setting
      default: -30
      selector:
        number:
          min: -60.0
          max: 60.0
          unit_of_measurement: °
          mode: slider
          step: 0.5
    turn_off:
      name: Turn off lights automatically
      description: Turn off lights when sun has risen.
      default: false
      selector:
        boolean: {}
    start_elevation_rising:
      name: Elevation of the sun to start brighten the light when the sun is rising
      default: -8
      selector:
        number:
          min: -60.0
          max: 60.0
          unit_of_measurement: °
          mode: slider
          step: 0.5
    end_elevation_rising:
      name: Elevation of the sun when the light shall have max brightness when the
        sun is rising
      default: 6
      selector:
        number:
          min: -60.0
          max: 60.0
          unit_of_measurement: °
          mode: slider
          step: 0.5
    transition_time:
      name: Transition time in seconds between brightness values
      default: 0
      selector:
        number:
          min: 0.0
          max: 5.0
          unit_of_measurement: s
          mode: slider
          step: 0.25
    debugging:
      name: Debug logging
      description: 'WARNING: Don''t enable this unless you have activated ''logger''
        in your configuration.yaml file. Turn on debugging of this automation. In
        order for this to take effect you need to manually trigger (EXECUTE) this
        automation or let Home Assistant restart before debug will be turned on/off.'
      default: false
      selector:
        boolean: {}
variables:
  allowance_input: !input 'allowance'
  allowance_value: '{{ allowance_input|float * 2.54 }}'
  debugging: !input 'debugging'
  target_lights: !input 'target_lights'
  entity_list: "{%- if target_lights.entity_id is string -%}\n  {{ [target_lights.entity_id]\
    \ }}\n{%- else -%}\n  {{ target_lights.entity_id }}\n{%- endif -%}"
  transition_time: !input 'transition_time'
  turn_on: !input 'turn_on'
  turn_off: !input 'turn_off'
  reverse: !input 'reverse'
  start_setting: !input 'start_elevation_setting'
  start_rising: !input 'start_elevation_rising'
  end_setting: !input 'end_elevation_setting'
  end_rising: !input 'end_elevation_rising'
  max_brightness_input: !input 'max_brightness'
  max_brightness: '{{ max_brightness_input|float }}'
  min_brightness_input: !input 'min_brightness'
  min_brightness: '{{ min_brightness_input|float }}'
  trigger_is_event: '{{ trigger is defined and trigger.platform == ''event'' }}'
  skip_event: '{{ trigger_is_event and trigger.event.data.service_data|length > 1
    }}'
  affected_entities: "{%- if skip_event -%}\n  {{ [] }}\n{%- elif trigger is not defined\
    \ or trigger.platform != 'event' or trigger.event.data.service_data is not defined\
    \ or trigger.event.data.service_data.entity_id is not defined -%}\n  {{ entity_list\
    \ }}\n{%- else -%}\n  {%- if trigger.event.data.service_data.entity_id is string\
    \ -%}\n    {%- set eids = [trigger.event.data.service_data.entity_id] -%}\n  {%-\
    \ else -%}\n    {%- set eids = trigger.event.data.service_data.entity_id -%}\n\
    \  {%- endif -%}\n  {%- set data = namespace(e=[]) -%}\n  {%- for e in eids -%}\n\
    \    {%- if e in entity_list -%}\n      {%- set data.e = data.e + [e] -%}\n  \
    \  {%- endif -%}\n  {% endfor %}\n  {{ data.e }}\n{%- endif -%}"
  current_states: "{%- set data = namespace(e=[]) -%} {%- for e in entity_list -%}\n\
    \  {%- set a = {'entity_id': e, 'state': states(e), 'brightness': state_attr(e,\
    \ 'brightness')} -%}\n  {%- set data.e = data.e + [a] -%}\n{%- endfor -%} {{ data.e\
    \ }}"
  error_msg: "{%- if start_setting|float <= end_setting|float -%}\n  {{ 'Start elevation\
    \ must be greater than end evevation when the sun is setting' }}\n{%- elif start_rising|float\
    \ >= end_rising|float -%}\n  {{ 'End elevation must be greater than start evevation\
    \ when the sun is rising' }}\n{%- elif entity_list|length == 0 -%}\n  {{ 'No valid\
    \ entites specified or found' }}\n{%- endif -%}"
  has_last: "{% if trigger is defined and trigger.platform == 'state' and trigger.from_state.entity_id\
    \ == 'sun.sun' -%}\n  {{ True }}\n{% else %}\n  {{ False }}\n{% endif %}"
  rising: '{{ state_attr(''sun.sun'', ''rising'') }}'
  last_rising: '{% if has_last %}{{ trigger.from_state.attributes.rising }}{% else
    %}{{ rising }}{% endif %}'
  elevation: '{{ state_attr(''sun.sun'', ''elevation'') }}'
  last_elevation: '{% if has_last %}{{ trigger.from_state.attributes.elevation }}{%
    else %}{{ elevation }}{% endif %}'
  force_turn_on: '{{ turn_on and not rising and last_elevation != "" and last_elevation
    >= end_setting|float and elevation <= start_setting|float }}'
  force_turn_off: '{{ turn_off and rising and last_elevation != "" and last_elevation
    <= end_rising|float and elevation >= end_rising|float }}'
  max_elevation: '{% if rising %}{{end_rising|float}}{% else %}{{start_setting|float}}{%
    endif %}'
  min_elevation: '{% if rising %}{{start_rising|float}}{% else %}{{end_setting|float}}{%
    endif %}'
  last_max_elevation: '{% if last_rising %}{{end_rising|float}}{% else %}{{start_setting|float}}{%
    endif %}'
  last_min_elevation: '{% if last_rising %}{{start_rising|float}}{% else %}{{end_setting|float}}{%
    endif %}'
  elevation_range: '{{ max_elevation - min_elevation }}'
  last_elevation_range: '{{ last_max_elevation - last_min_elevation }}'
  brightness_range: '{{ max_brightness - min_brightness }}'
  delta_to_min: '{{ elevation - min_elevation }}'
  last_delta_to_min: '{{ last_elevation|float - last_min_elevation }}'
  full_percent_raw: '{% if delta_to_min / elevation_range < 0 %}0{% elif delta_to_min
    / elevation_range > 1 %}1{% else %}{{delta_to_min / elevation_range}}{% endif
    %}'
  full_percent: '{% if reverse %}{{1 - full_percent_raw}}{% else %}{{full_percent_raw}}{%
    endif %}'
  last_full_percent_raw: '{% if last_delta_to_min / elevation_range < 0 %}0{% elif
    last_delta_to_min / elevation_range > 1 %}1{% else %}{{last_delta_to_min / elevation_range}}{%
    endif %}'
  last_full_percent: '{% if reverse %}{{1 - last_full_percent_raw}}{% else %}{{last_full_percent_raw}}{%
    endif %}'
  brightness_pct: '{{ full_percent * brightness_range + min_brightness }}'
  last_brightness_pct: '{{ last_full_percent * brightness_range + min_brightness }}'
  brightness: '{{ (brightness_pct * 2.54)|int }}'
  last_brightness: '{{ (last_brightness_pct * 2.54)|int }}'
  turn_on_entities: "{%- if force_turn_on -%}\n  {%- set data = namespace(entities=[])\
    \ -%}\n  {%- for e in entity_list -%}\n    {%- if not state_attr(e, 'supported_features')|bitwise_and(1)\
    \ -%}\n      {%- set data.entities = data.entities + [e] -%}\n    {%- endif -%}\n\
    \  {%- endfor -%}\n  {{ data.entities }}\n{%- else -%}\n  {{ [] }}\n{%- endif\
    \ -%}"
  dim_entities: "{%- set data = namespace(entities=[]) -%} {%- for e in entity_list\
    \ -%}\n  {%- set current_brightness = state_attr(e, 'brightness') -%}\n  {%- set\
    \ is_on = states(e) == 'on' -%}\n  {%- set last_changed = (now() - states[e].last_changed)\
    \ -%}\n  {%- set can_dim = state_attr(e, 'supported_features')|bitwise_and(1)|bitwise_or(not\
    \ is_on) -%}\n  {#\n    Set brightness and turn on if\n      * Trigger is an event\
    \ to turn on entity and it is currently off\n    OR\n      * dimming is supported\
    \ by the entity AND light shall be turned on because the sun is setting (force_turn_on)\n\
    \    OR\n      * dimming is supported by the entity AND light is ON AND the current\
    \ brightness differ from the new brightness\n      AND\n      * current brightness\
    \ is equal to last set brightness (has not been changed by the user within the\
    \ allowance)\n  #}\n  {%- if e in affected_entities -%}\n    {%- if trigger_is_event\
    \ and (not is_on or (is_on and last_changed.seconds < 2)) -%}\n      {%- set data.entities\
    \ = data.entities + [e] -%}\n    {%- elif can_dim and force_turn_on -%}\n    \
    \  {%- set data.entities = data.entities + [e] -%}\n    {%- elif can_dim and is_on\
    \ and current_brightness != brightness and (current_brightness - last_brightness)|abs\
    \ <= allowance_value -%}\n      {%- set data.entities = data.entities + [e] -%}\n\
    \    {%- endif -%}\n  {%- endif -%}\n{%- endfor -%} {{ data.entities }}"
  turn_off_entities: "{%- if force_turn_off -%}\n  {{ entity_list }}\n{%- else -%}\n\
    \  {{ [] }}\n{%- endif -%}"
trigger:
- platform: state
  entity_id: sun.sun
  attribute: elevation
- platform: event
  event_type: call_service
  event_data:
    domain: light
    service: turn_on
- platform: homeassistant
  event: start
mode: queued
action:
- choose:
  - conditions:
    - condition: template
      value_template: '{{ debugging and trigger is not defined }}'
    sequence:
    - service: logger.set_level
      data:
        homeassistant.components.blueprint.dim_lights_based_on_sun_elevation: DEBUG
  - conditions:
    - condition: template
      value_template: '{{ debugging and trigger.platform == ''homeassistant'' and
        trigger.event == ''start'' }}'
    sequence:
    - service: logger.set_level
      data:
        homeassistant.components.blueprint.dim_lights_based_on_sun_elevation: DEBUG
  default:
  - choose:
    - conditions:
      - condition: template
        value_template: '{{ error_msg|length }}'
      sequence:
      - service: system_log.write
        data:
          level: error
          logger: homeassistant.components.blueprint.dim_lights_based_on_sun_elevation
          message: '{{ error_msg }}'
    default:
    - choose:
      - conditions:
        - condition: template
          value_template: '{{ debugging }}'
        sequence:
        - service: system_log.write
          data:
            level: debug
            logger: homeassistant.components.blueprint.dim_lights_based_on_sun_elevation
            message: " DEBUG:\n skip_event: {{ skip_event }}\n allowance_value: {{\
              \ allowance_value }}\n affected_entities: {{ affected_entities }}\n\n\
              \ elevation: {{ elevation }} ({% if rising %}{{ start_rising ~ ', '\
              \ ~ end_rising }}{% else %}{{ start_setting ~ ', ' ~ end_setting }}{%\
              \ endif %})\n {% if last_elevation != \"\" -%}last elevation: {{ last_elevation\
              \ }}\n{% endif %} new brightness: {{ brightness }}\n {% if last_elevation\
              \ != \"\" -%}last brightness: {{ last_brightness }}\n{% endif %} \n\
              \ current_states: {{ current_states }}\n \n force_turn_on: {{ force_turn_on\
              \ }}\n force_turn_off: {{ force_turn_off }}\n \n entities: {{ entity_list\
              \ }}\n \n turn_on_entities: {{ turn_on_entities }}\n \n dim_entities:\
              \ {{ dim_entities }}\n \n turn_off_entities: {{ turn_off_entities }}\n\
              \ \n {% if trigger is defined %}Triggered by: {{ trigger.platform }}\n\
              {% endif %} {% if trigger is defined and trigger.platform == 'state'\
              \ and trigger.from_state.entity_id == 'sun.sun' -%} from: (elevation:\
              \ {{ trigger.from_state.attributes.elevation }}, azimuth: {{ trigger.from_state.attributes.azimuth\
              \ }})\n to:   (elevation: {{ trigger.to_state.attributes.elevation }},\
              \ azimuth: {{ trigger.to_state.attributes.azimuth }})\n {% endif %}\
              \ {% if trigger is defined and trigger.platform == 'event' -%} entity_id:\
              \ {{ trigger.event.data.service_data.entity_id }}\n service_data_length:\
              \ {{ trigger.event.data.service_data|length }}\n complete event data:\
              \ {{ trigger.event.data }}\n {% endif %} "
      default: []
    - choose:
      - conditions:
        - condition: template
          value_template: '{{ not skip_event and turn_off_entities|length > 0 }}'
        sequence:
        - service: light.turn_off
          data:
            entity_id: '{{ turn_off_entities }}'
      - conditions:
        - condition: template
          value_template: '{{ not skip_event and turn_on_entities|length > 0 }}'
        sequence:
        - service: light.turn_on
          data:
            entity_id: '{{ turn_on_entities }}'
      - conditions:
        - condition: template
          value_template: '{{ not skip_event and dim_entities|length > 0 }}'
        sequence:
        - service: light.turn_on
          data:
            entity_id: '{{ dim_entities }}'
            brightness: '{{ brightness }}'
            transition: '{{ transition_time }}'
      default: []
