Automating the correct lighting in your house is a complex challenge because it depends on many factors. In many cases just measuring the illuminance and then (automatically) adjusting light settings seems not a sufficient solution or isn’t accurate. Your mood, direct sunlight, covers, weather condition can be all criteria to adjust to a specific condition.
This script will save all current light settings per area or light group into a new scene with just one service call. This scene is then loaded into Home Assistant and you may later create an automation that activate this scene after you moved it into standard scene file(s).
Because the environment conditions may be important to create your new automation, a selected set of sensors is saved into the comments of the scene yaml code.
This script is similar to takes a little different approach then this project Scene_generator.py of sunnythaper by saving it per area or lightgroup. This script also only focusses on lights (or light groups), althought it save some sensors for reference.
Scene file
To save the scenes, the Home Assistant file notification (File - Home Assistant) is used. Create a file notifier:
notify:
- platform: file
name: scene_notify_snapshot
filename: /config/scenes/snapshot.yaml
timestamp: false
This saves the new scenes into the snapfile. Make sure this file exists and is not empty, else it will write a header, that will fail the scenes to load.
Include the scene file into your configuration.yaml (and keep using the scenes.yaml for UI modifications):
scene default: !include scenes.yaml
scene saved: !include scenes/snapshot.yaml
Script
To save the scenes, the Home Assistant file notification (File - Home Assistant) is used. Create a file notifier:
script:
area_scene_snapshot:
alias: area_scene_snapshot
fields:
area:
description: Area
example: Living room
group:
description: Group of lights to add to dialog
example: light.living_room
description:
description: description to save with
example: "at evening when curtains close"
variables:
entities: |
{%- set scene_entities = [] -%}
{%- if group is not defined or group is none -%}
{{ area_entities(area) | select('match','^light\.') | list }}
{%- else -%}
{{ state_attr(group, 'entity_id') | list }}
{%- endif -%}
mytime: |-
{{ states('sensor.date_time_iso') | regex_replace(find='[^\\dT]', replace='') | replace('T','_') }}
desc: |-
{{ iif(description is not defined or description is none,states('input_text.scene_snapshot_desc'),description) }}
snap: |-
snap_{{ (iif(group is not defined or group is none, area, group) ) | regex_replace(find='[^\\w]', replace='_') | lower }}_{{ mytime }}_{{ desc | regex_replace(find='[^\\w]', replace='_') | lower }}
sequence:
- choose:
- conditions: "{{ entities | length == 0 }}"
sequence:
- service: script.debug
data_template:
source: script.area_scene_snapshot
title: Invalid group or area
message: |
Group {{ group }} or area {{ area }} has no entities
default:
- service: notify.scene_notify_snapshot
data_template:
message: |
- id: {{ snap }}
name: {{ snap }}
# description: {{ desc }}
# saved: {{ states('sensor.time_date') }} ({{ states('sensor.time_of_day') }})
# illuminance:
{% for item in states.sensor | selectattr('attributes.device_class', 'eq', 'illuminance') | list -%}
# {{ item.entity_id }}: {{ states(item.entity_id) }}
{% endfor -%}
# covers:
{% for item in states.cover -%}
# {{ item.entity_id }}: {{ state_attr(item.entity_id,'current_position') }} # {{ states(item.entity_id) }}
{% endfor -%}
# condition:
# sun: "{{ states('sun.sun') }}"
# elevation: {{ state_attr('sun.sun', 'elevation') }} degrees
# rain: {{ states('sensor.my_rainmeter_rain') }} mm
# weather: "{{ states('sensor.buienradar_condition') }}"
entities:
{%- set scene_entities = [] -%}
{%- for l in entities %}
{{ l }}:
state: "{{ states(l) }}"
{%- if not is_state(l,'off') -%}
{%- for attr in states[l].attributes -%}
{%- if not attr in ['friendly_name', 'effect_list', 'update', 'update_available', 'linkquality', 'supported_features', 'icon', 'min_mireds', 'max_mireds', 'supported_color_modes'] %}
{{ attr }}: {{ " " }}
{%- if states[l].attributes[attr] is string or states[l].attributes[attr] is number -%}
{{ states[l].attributes[attr] }}
{%- elif states[l].attributes[attr] is mapping -%}
{%- for value in states[l].attributes[attr] %}
{{ value }}: {{ states[l].attributes[attr][value] }}
{%- endfor -%}
{%- elif states[l].attributes[attr] is iterable -%}
{%- for value in states[l].attributes[attr] %}
- {{ value }}
{%- endfor -%}
{% endif %}
{%- endif %}
{%- endfor %}
{%- endif %}
{%- endfor %}
- service: scene.reload
- service: script.debug
data_template:
source: script.area_scene_snapshot
title: Group or area saved
message: |
{% if group is defined and group is not none %}
Group {{ group }} saved to {{ snap }}
{% else %}
Area {{ area }} saved to {{ snap }}
{% endif %}
Calling the script
type: entities
entities:
- type: button
name: Snapshot by Area (Living room)
tap_action:
action: call-service
service: script.area_scene_snapshot
service_data:
area: Living room
description: Saved by area
- type: divider
- type: button
name: Snapshot by Area (light.living_room)
tap_action:
action: call-service
service: script.area_scene_snapshot
service_data:
group: light.living_room
description: Saved by group
Note: To use the area parameter, all lights should be assigned to an area in Home Assistant.
To use the light group you might have something like this defined in your configuration yaml:
light:
- platform: group
name: ling_room
entities:
- light.living_room_couch
- light.living_room_tv
- light.living_room_table
- light.living_room_candle
- platform: switch
name: living_room_candle
entity_id: switch.living_room_candle_plug
Some Lovelace helpers
Inputs
input_text:
scene_snapshot_desc:
name: scene_snapshot_desc
input_select:
area:
name: area
options:
- empty
light_group:
name: light_group
options:
- empty
Initialize above inputs
automation:
- id: areas_initialize
alias: areas_initialize
trigger:
- platform: homeassistant
event: start
action:
- service: input_select.set_options
data:
entity_id: input_select.area
options: |
{% set ns = namespace(areas=[]) %}
{% for elm in states.light if not area_name(elm.entity_id) in ns.areas%}
{% if area_name(elm.entity_id) is not none %}
{% set ns.areas = ns.areas + [area_name(elm.entity_id)] %}
{% endif %}
{%- endfor %}
{{ ns.areas }}
- service: input_select.set_options
data:
entity_id: input_select.light_group
options: "{{ states.light | selectattr('attributes.entity_id','defined') | map(attribute='entity_id') | list }}"
Helper scripts
script:
area_snapshot_for_area:
alias: area_snapshot_for_area
sequence:
- service: script.area_scene_snapshot
data_template:
area: "{{ states('input_select.area') }}"
description: "{{ states('input_text.scene_snapshot_desc') }}"
area_snapshot_for_group:
alias: area_snapshot_for_group
sequence:
- service: script.area_scene_snapshot
data_template:
group: "{{ states('input_select.light_group') }}"
description: "{{ states('input_text.scene_snapshot_desc') }}"
Create snapshots
type: entities
entities:
- type: button
name: Reload scenes
tap_action:
action: call-service
service: scene.reload
- entity: input_text.scene_snapshot_desc
- type: divider
- entity: input_select.area
- type: button
name: Snapshot Area
tap_action:
action: call-service
service: script.area_snapshot_for_area
- type: divider
- entity: input_select.light_group
- type: button
name: Snapshot Group
tap_action:
action: call-service
service: script.area_snapshot_for_group
Show snapped scenes
type: custom:auto-entities
card:
type: entities
filter:
include:
- domain: scene
entity_id: scene.snap_*
exclude: []