Yet Another Adaptive Lighting

Некоторое время назад всё основное освещение у меня стало умным, а значит, стало поддерживать изменение яркости и температуры. Я начал изучать разные варианты адаптивного освещения и пришёл к выводу, что все они мне чем-то не нравятся. Каждый чем-то своим.

В итоге, принял волевое решение сделать свою систему адаптивного освещения с блэкджеком и куртизанками со скриптами и автоматизациями в Home Assistant.

Зачем, вообще, нужно адаптивное освещение? Вкратце и упрощённо, чтобы днём светить более холодным светом, а вечером — более тёплым. Говорят, это полезно для человеческого организма. Но изначально я задумался об адаптивном освещении немного по другой причине.

Основное освещение у меня включается и выключается автоматически, в зависимости от состояния разных датчиков и условий. И мне захотелось настроить всё так, чтобы во время ночных походов свет включался не выжигая глаза. Будь то поход к белому фаянсовому другу или же к большому, почти всегда белому, железному. Ну а потом уже всё остальное. 🙂

Долго ли, коротко ли, наваял template-сенсор.

sensor:
  - platform: template
    sensors:
      home_light_mode:
        unique_id: home_light_mode
        friendly_name: "Home Light Mode"
        value_template: >-
          {% if is_state('input_boolean.night_mode','on') %}
            night
          {% elif now().hour >= 22 or now().hour <= 4 %}
            evening
          {% else %}
            day
          {% endif %}

Как видно из кода, он принимает три значения. И значения эти говорят сами за себя:
- day
- evening
- night

input_boolean.night_mode в штатном режиме выставляется автоматизациями, но, при желании, может быть включен или выключен вручную.

alias: Night Mode On
description: ''
trigger:
  - at: '01:30:00'
    platform: time
  - entity_id: group.home_motion
    for: '3600'
    platform: state
    to: 'off'
condition:
  - after: '22:00:00'
    before: '05:29:59'
    condition: time
  - condition: state
    entity_id: group.home_motion
    for: '3599'
    state: 'off'
  - condition: state
    entity_id: group.awesome_people
    state: home
action:
  - data: {}
    entity_id: input_boolean.night_mode
    service: input_boolean.turn_on
mode: single
alias: Night Mode Off
description: ''
trigger:
  - at: '05:30:00'
    platform: time
  - platform: state
    entity_id: group.home_motion
    for: '480'
    to: 'on'
condition: []
action:
  - data: {}
    entity_id: input_boolean.night_mode
    service: input_boolean.turn_off
mode: single

group.home_motion — группа, где есть все датчики движения. Т.е. принимает значение off, когда дома не обнаруживается движение ни одним из датчиков движения.

group.awesome_people — группа, в которую входят все замечательные люди, живущие со мной (person.*).

После сделал скрипты для каждого основного источника света по образу и подобию.

alias: Kitchen Light
sequence:
  - choose:
      - conditions:
          - condition: state
            entity_id: sensor.home_light_mode
            state: night
        sequence:
          - service: light.turn_on
            data:
              brightness: 8
              color_temp: 370
            target:
              entity_id: light.kitchen_light
      - conditions:
          - condition: state
            entity_id: sensor.home_light_mode
            state: evening
        sequence:
          - service: light.turn_on
            data:
              brightness: 255
              color_temp: 320
            target:
              entity_id: light.kitchen_light
    default:
      - service: light.turn_on
        data:
          brightness: 255
          color_temp: 200
        target:
          entity_id: light.kitchen_light
mode: single

Для разных комнат у меня настройки яркости и температуры для источников света несколько отличаются, поэтому я не стал делать универсальный скрипт, а сделал их по количеству источников света. В моём случае их десять, здесь, для простоты, привёл только один скрипт. Остальные отличаются от этого только настройками яркости, температуры и источником света.

А что если источник света включился не средствами Home Assistant, а как-то по-другому? Мы отлавливаем включение источника света и проверяем, что включение произошло не по воле пользователя и не автоматизацией. Если всё так, запускаем скрипт.

alias: Light Correction
description: ''
trigger:
  - platform: state
    entity_id:
      - light.kitchen_light
      - light.bathroom_light
      - light.toilet_light
      - light.bedroom_light
   to: 'on'
condition:
  - condition: template
    value_template: >-
      {{ trigger.to_state.context.parent_id == None and
      trigger.to_state.context.user_id == None }}
action:
  - service: "script.{{trigger.to_state.object_id}}"
mode: queued
max: 10

Для корректной работы этого примера нужно для каждого источника света создать скрипт с соответствующим entity_id. Т.е. должны быть созданы скрипты со следующими entity_id:
- script.kitchen_light
- script.bathroom_light
- script.toilet_light
- script.bedroom_light

Если у вас уже были соответствующие скрипты и вам лень их изменять, как мне, можно сделать и вот так.

alias: Light Correction
description: ''
trigger:
  - platform: state
    entity_id:
      - light.kitchen_light
      - light.bathroom_light
      - light.toilet_light
      - light.bedroom_light
    to: 'on'
condition:
  - condition: template
    value_template: >-
      {{ trigger.to_state.context.parent_id == None and
      trigger.to_state.context.user_id == None }}
action:
  - service: >-
      {% if trigger.to_state.entity_id == 'light.kitchen_light' %}
        script.kitchen_bulb
      {% elif trigger.to_state.entity_id == 'light.bathroom_light' %}
        script.bathroom_superbulb
      {% elif trigger.to_state.entity_id == 'light.toilet_light' %}
        script.toilet_lightbulb
      {% elif trigger.to_state.entity_id == 'light.bedroom_light' %}
        script.bedroom_lights
      {% endif %}
mode: queued
max: 10

В идеале, конечно, можно было бы создать один скрипт со всеми возможными настройками в переменных, которому в качестве параметра передавать entity_id источника света и переменную заданных параметров света. Но мне это лень.

Ну и последнее, если меняется значение sensor.home_light_mode, нам нужно изменить параметры включенных источников света в зависимости от него.

alias: Update Lights Based On Home Light Mode
description: ''
trigger:
  - platform: state
    entity_id: sensor.home_light_mode
condition: []
action:
  - choose:
      - conditions:
          - condition: state
            entity_id: light.kitchen_light
            state: 'on'
        sequence:
          - service: script.kitchen_light
            data: {}
    default: []
  - choose:
      - conditions:
          - condition: state
            entity_id: light.bathroom_light
            state: 'on'
        sequence:
          - service: script.bathroom_light
    default: []
  - choose:
      - conditions:
          - condition: state
            entity_id: light.toilet_light
            state: 'on'
        sequence:
          - service: script.toilet_light
    default: []
  - choose:
      - conditions:
          - condition: state
            entity_id: light.bedroom_light
            state: 'on'
        sequence:
          - service: script.bedroom_light
    default: []
mode: single

Что мы получили в итоге? Все нужные нам источники света будут включаться с заданными параметрами, в зависимости от состояния сенсора sensor.home_light_mode. При желании, можно сделать не 3 состояния, а сколько душе угодно.

Если захочется, чтобы аналогичная реакция на включение источников света была и из интерфейса Home Assistant, достаточно убрать условие trigger.to_state.context.parent_id == None в автоматизации Light Correction. Ну а если надо, чтобы при любом включении источников света отрабатывала коррекция света, то и вовсе убрать все условия в этой автоматизации и включать свет не скриптами, а сервисом light.turn_on.

Традиционно, никого ни к чему не призываю, ничего не навязываю. Просто делюсь тем, как реализовал у себя. Если есть желание поделиться своими решениями или появились вопросы, заходите обсудить.

Vladimir Turekhanov ・ December 26, 2021

вернуться