Автоматизации: анатомия и типичные ошибки
Автоматизация в Home Assistant — это правило из трёх частей: что-то её запускает, что-то может её остановить перед выполнением, и что-то она в итоге делает. Почти все странности в поведении умного дома сводятся к тому, что одна из этих трёх частей написана небрежно.
Триггер, условие, действие
Триггер — событие, которое запускает проверку автоматизации: датчик изменил состояние, наступило время, значение пересекло порог. Триггер только инициирует проверку, он не гарантирует, что действие выполнится.
Условие — необязательная проверка, которая идёт после триггера и до действия. Если условие не выполнено, автоматизация останавливается молча, без действия и без ошибки. Условий может быть несколько, и все они должны выполниться одновременно.
Действие — то, что фактически произойдёт, если триггер сработал и все условия прошли: включить свет, отправить уведомление, вызвать сценарий.
Разделение важно, потому что одна и та же логика через триггер и через условие ведёт себя по-разному. «Включать свет, когда освещённость ниже 20 люкс» как триггер сработает один раз — в момент, когда значение пересечёт порог сверху вниз. То же самое как условие будет проверяться каждый раз, когда происходит любой другой триггер, и не сработает, пока освещённость уже не окажется ниже порога на момент проверки.
Гонка двух автоматизаций за одну лампу
Частая ошибка — две независимые автоматизации управляют одной и той же
сущностью по разным поводам: одна включает свет по движению, другая
выключает его по расписанию или по другому датчику. Если оба события
происходят почти одновременно, результат зависит от порядка выполнения,
который не гарантирован, — свет то мигает, то остаётся в неожиданном
состоянии. Правильное решение — не разносить логику по разным
автоматизациям, которые тянут в разные стороны одну сущность, а собирать
её в одном месте с явными условиями на оба случая, либо явно определять
приоритет через mode и условия внутри одной автоматизации.
Отсутствие условия на «уже включено»
Автоматизация, которая включает свет по каждому срабатыванию датчика
движения без проверки текущего состояния, на первый взгляд безобидна —
свет и так уже горит, повторное включение вроде бы ничего не меняет. На
практике это создаёт побочные эффекты: если действие не просто
light.turn_on, а сценарий, который заново применяет яркость и цвет,
человек, который сам через приложение поставил приглушённый свет для
чтения, каждые несколько секунд получает его обратно на дефолтную
яркость, потому что автоматизация переигрывает сценарий заново. Условие
state: "off" перед действием turn_on останавливает это — действие
выполняется один раз, при переходе, а не на каждый повторный триггер.
Сценарий без таймаута
Автоматизация «включить свет по движению» без парной логики выключения оставляет свет гореть бесконечно, если датчик по какой-то причине не пришлёт следующее событие — севшая батарейка, потеря пакета, устройство подвисло. Надёжнее не полагаться на то, что «выключающий» триггер обязательно придёт, а привязывать выключение к отсутствию движения в течение заданного времени — тогда даже если датчик один раз не ответит, свет всё равно погаснет по истечении таймаута при следующем удачном опросе состояния.
Пример: включение по движению с условием по освещённости
automation:
- alias: "Свет в коридоре по движению"
trigger:
- platform: state
entity_id: binary_sensor.koridor_dvizhenie
to: "on"
condition:
- condition: numeric_state
entity_id: sensor.koridor_osveshchennost
below: 20
action:
- service: light.turn_on
target:
entity_id: light.koridor
data:
brightness_pct: 40
Триггер здесь — переход датчика движения в «есть движение». Условие
отсекает срабатывание днём, когда в коридоре и так светло. Действие
включает свет на фиксированную яркость. Обратите внимание, чего здесь
нет: условия на «уже включено» — но действие безопасно повторять, потому
что brightness_pct: 40 не создаёт побочных эффектов при повторном
вызове, в отличие от сценария с произвольными настройками.
Пример: выключение с таймаутом и защитой от лишнего вызова
automation:
- alias: "Коридор: выключить свет после тишины"
trigger:
- platform: state
entity_id: binary_sensor.koridor_dvizhenie
to: "off"
for:
minutes: 5
condition:
- condition: state
entity_id: light.koridor
state: "on"
action:
- service: light.turn_off
target:
entity_id: light.koridor
mode: single
Ключевое здесь — for: minutes: 5 в триггере: событие сработает не в
момент, когда движение прекратилось, а только если состояние «нет
движения» продержалось пять минут без перерыва. Это и есть таймаут,
который защищает от «свет погас, пока человек просто на секунду
остановился». Условие state: "on" перед выключением не даёт
автоматизации лишний раз дёргать сущность, которая и так уже выключена.
mode: single не позволяет запускаться второй копии этой же
автоматизации, пока первая ещё не завершилась, — это и есть защита от
гонки, о которой шла речь выше.