Toggling lights in multi-level house

Hello,

This is my first contribution to Home Assistant. I wrote the following script to automate toggling lights in a multi-level house. The intent of the script is following:

  • When I move my ass from eg. upstairs to downstairs, I want to switch all lights in upstairs off and switch certain default lights in downstairs on, and vice versa
  • This is matter of opinion, but I personally don’t like keeping hard-coded device id lists in scripts
  • As there is no built-in support for house levels in Home Assistant, there should be some means for defining the house level where devices are located
  • AFAIK you cannot add custom data to devices, but “default lights” should be marked somehow

The intent above can be achieved by eg. prefixing device id’s with floor name and eg. by adding “default” suffix to device id’s, for example: light.upstairs_some_light_default. Some other notation should work as well. The following script can then be used to toggle lights:

alias: Toggle Lights
mode: restart
variables:
  where: upstairs
  to_state: "off"
  light_filter: >-
    {{ 'light\.' + where + '.*' if to_state == 'off' else 'light\.' + where +
    '.*default' }}
  dimmer_filter: >-
    {{ 'number\.' + where + '.*' if to_state == 'off' else 'number\.' + where +
    '.*default' }}
  from_state: "{{ 'on' if to_state == 'off' else 'off' }}"
  dimmer_operand: "{{ 'eq' if to_state == 'on' else 'ne' }}"
  dimmer_state: "{{ 0 if to_state == 'off' else 100 }}"
  service_to_call: "{{ 'light.turn_on' if to_state == 'on' else 'light.turn_off' }}"
  light_entities: |-
    {{ states | selectattr('entity_id', 'match', light_filter) |
     selectattr('state', 'eq', from_state) | map(attribute='entity_id') |
    join(',') }}
  dimmer_entities: >-
    {{ states | selectattr('entity_id', 'match', dimmer_filter) |
    selectattr('state', dimmer_operand, "0") | map(attribute='entity_id') |
    join(',') }}
sequence:
  - service: logbook.log
    data_template:
      name: Script
      message: >-
        Service: {{ service_to_call }} From {{ from_state }} to {{ to_state }}
        where {{ light_filter }} and {{ dimmer_filter }}
  - service: logbook.log
    data_template:
      name: Script
      message: "Lights: {{ light_entities }} Dimmers: {{ dimmer_entities }}"
  - if:
      - condition: template
        value_template: "{{ light_entities != '' }}"
    then:
      - service: "{{ service_to_call }}"
        data:
          entity_id: "{{ light_entities }}"
  - if:
      - condition: template
        value_template: "{{ dimmer_entities != '' }}"
    then:
      - service: number.set_value
        target:
          entity_id: "{{ dimmer_entities }}"
        data:
          value: "{{ dimmer_state }}"

The script can then be called easily, eg.

alias: Move to Upstairs
sequence:
  - service: script.toggle_lights
    data:
      where: "upstairs"
      to_state: "on"
  - service: script.toggle_lights
    data:
      where: "downstairs"
      to_state: "off"
mode: restart

Seems to work as I intended. All feedback is appreciated.

2 Likes