Home Assistant и Zigbee-датчики: чтобы дом сам говорил, когда что-то не так

Всё началось с того, что у меня зимой в кладовке с трубами однажды чуть не прихватило воду — отопление барахлило, а я узнал об этом, только когда полез за консервами. Подумал: дом должен сам мне сообщать о таких вещах, а не я бегать с термометром. Так на сервере поселился Home Assistant.

Home Assistant — это опенсорсный центр умного дома. Никаких облаков производителя, всё крутится локально, данные не утекают неизвестно куда, и работает даже если интернет отвалился.

Запуск в Docker и Zigbee-донгл

Я не стал плодить кучу облачных гаджетов от разных вендоров, а пошёл по пути Zigbee — это единый радиопротокол, к которому цепляется куча дешёвых датчиков от любых производителей. В сервер воткнут USB-донгл Sonoff ZBDongle-E (на чипе EFR32MG21), а разговаривает с ним Zigbee2MQTT.

Связка такая: датчики → Zigbee2MQTT → MQTT-брокер (Mosquitto) → Home Assistant. Поднимаю всё одним compose в /app/homeassistant/:

services:
  homeassistant:
    image: ghcr.io/home-assistant/home-assistant:stable
    container_name: homeassistant
    network_mode: host
    volumes:
      - /app/homeassistant/config:/config
      - /etc/localtime:/etc/localtime:ro
    restart: unless-stopped

  zigbee2mqtt:
    image: koenkk/zigbee2mqtt:latest
    container_name: zigbee2mqtt
    volumes:
      - /app/zigbee2mqtt/data:/app/data
    devices:
      - /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_xxxx-if00:/dev/ttyACM0
    restart: unless-stopped

Важный момент: устройство пробрасываю не как /dev/ttyACM0, а через стабильный путь /dev/serial/by-id/.... Иначе после перезагрузки донгл может переименоваться в ttyACM1, и Zigbee2MQTT его не найдёт. Точный путь смотрим командой ls -l /dev/serial/by-id/.

Датчики

По дому развесил недорогие Aqara: температура/влажность в комнатах, датчик протечки под мойкой и за стиралкой, пара датчиков открытия на дверях. Цепляются они через MQTT-интеграцию, после сопряжения сами появляются в Home Assistant как сущности вида sensor.temperatura_kladovka или binary_sensor.protechka_mojka. Батарейки живут больше года, так что обслуживание нулевое.

Автоматизации

Вот ради чего всё затевалось. Две простые автоматизации закрыли мою главную боль. Первая — если в кладовке холодает ниже 8 градусов, прилетает уведомление на телефон:

- alias: "Кладовка остывает"
  trigger:
    - platform: numeric_state
      entity_id: sensor.temperatura_kladovka
      below: 8
      for:
        minutes: 10
  action:
    - service: notify.mobile_app_telefon
      data:
        title: "Холодает в кладовке"
        message: "Температура {{ states('sensor.temperatura_kladovka') }}°C — проверь отопление"

for: minutes: 10 тут не просто так — без него датчик может дёрнуться от сквозняка и завалить телефон ложными тревогами. А вот протечка — наоборот, реагируем мгновенно:

- alias: "Протечка под мойкой"
  trigger:
    - platform: state
      entity_id: binary_sensor.protechka_mojka
      to: "on"
  action:
    - service: notify.mobile_app_telefon
      data:
        title: "⚠️ ПРОТЕЧКА"
        message: "Сработал датчик под мойкой!"
        data:
          priority: high

Итог

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