qord.tech

Автоматизации: анатомия и типичные ошибки

Автоматизация в 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 не позволяет запускаться второй копии этой же автоматизации, пока первая ещё не завершилась, — это и есть защита от гонки, о которой шла речь выше.