↩️ Назад

Категории

Самописный умный дом - как делать правильно по мнению гермес-агента

30.09.2026 | из категории: IOT умный дом

Что можно улучшить в самописном проекте умного дома на зигби
Разбор проекта · IoT

Самописный умный дом: честный разбор живого проекта и как делать правильно

Raspberry Pi, zigbee2mqtt, Mosquitto, PHP-движок правил и MariaDB. Что здесь сделано хорошо, где болит и стоит ли переделывать конвейер так, чтобы движок слушал брокер напрямую, а не ходил в базу.

30 сентября 2026состояние на 29.09.2026≈12 минут чтения

1. Что это за система, если по фактам

Это не «умный дом на Home Assistant», а собственная реализация: человек написал её сам, от датчика до веб-панели. Масштаб уже не игрушечный — полтора десятка Zigbee-устройств, около 140 «живых» топиков, семь постоянно работающих служб, несколько скриптов по расписанию, своя база истории и панель управления с редактором правил.

СлойРеализация
ЖелезоRaspberry Pi 5 (NVMe, ~117 ГБ), Zigbee-координатор в USB
Радио → MQTTzigbee2mqtt (systemd)
Брокерmosquitto: оба порта слушают только 127.0.0.1 — 1883 с паролем (учётки mazzick, iot), 1884 анонимно для внутренних скриптов малины. Наружу не торчит
Запись данныхPython-логгер mqtt_to_mysql.py (systemd mqtt-to-mysql): последнее значение на топик + история
БазаMariaDB, БД iot_db: sensor_data (последнее значение, UNIQUE по топику), sensor_history, sensor_info, automations, automation_log
Движок правилPHP-демон mqtt_listener.php (systemd iot-automation), правит таблицу automations, редактор — admin/logic.php
ПанельPHP + nginx, доступ закрыт по IP (localhost, VPN-подсеть, рабочее место)
АномалииОтдельная служба сбора статистики (медиана/MAD, «пропажа данных», «просадка»), ИИ-модуль выключен сознательно
Автоматика по расписаниюКормушка, push-уведомления, письма, проверка батареек — cron-скрипты
Что здесь хорошо и что редко встретишь в самоделках. Есть разделение на службы с systemd и автоперезапуском; есть история отдельно от «последних значений»; есть журнал срабатываний с отдельным флагом «команда не потребовалась, устройство уже в нужном состоянии»; есть внешний healthcheck и сторож, который раз в час проверяет систему и молчит, пока всё в порядке; есть справочник порогов батареек в одном месте, а не в трёх. Это уже уровень «промышленной дисциплины», а не «скрипт в crontab».

2. Как она работает сегодня

┌──────────────┐ радио ┌──────────────┐ MQTT ┌────────────────────┐ │ Zigbee- │ ────────► │ zigbee2mqtt │ ────────► │ Mosquitto │ │ устройства │ │ (мост) │ │ zigbee2mqtt/<dev> │ └──────────────┘ └──────────────┘ └─────────┬──────────┘ │ ┌───────────────────────────────────┴──────────────┐ │ │ ▼ ▼ ┌────────────────────┐ ┌─────────────────────────┐ │ mqtt_to_mysql.py │── пишет ──► MariaDB │ mqtt_listener.php │ │ (логгер, systemd) │ iot_db │ (движок правил, PHP) │ └────────────────────┘ ▲ │ └───────────┬─────────────┘ │ │ │ раз в секунду: SELECT значения, │ publish команды правила из automations │ обратно в MQTT │ ▼ ▼ └──────────── устройство выполняет
Ключевое: данные сначала падают в базу, и только потом движок правил читает их оттуда.

То есть у каждого сообщения от датчика путь такой: брокер → Python-логгер → таблица «последнее значение» → (через секунду) PHP-движок прочитал → сравнил с порогом → отправил команду в брокер. Латентность — до секунды, потому что движок опрашивает базу циклом, а не получает данные событием.

Дополнительно рядом живёт вторая, независимая автоматика: cron-скрипты PHP.

3. Диагноз: где болит (10 пунктов)

Ниже — не «список страшного», а конкретные вещи, которые я бы менял, с указанием, почему это вообще проблема.

№Что не такПочему это больно
1Состояние живёт в трёх местах. Retained-значение в брокере, строка в sensor_data, и «последнее виденное» в памяти движка.Они расходятся. Отсюда вопросы «панель показывает одно, а реле щёлкнуло по-другому».
2Движок опрашивает базу циклом раз в секунду.Реакция до 1 с вместо миллисекунд; лишние сотни SELECT в секунду; и в теории «гонка» — значение обновилось между двумя чтениями.
3Запись в базу на каждое сообщение. Даже те, которые никому не нужны.Нагрузка на флешку/диск и на MariaDB пропорциональна болтливости датчиков, а не полезности данных. История отдельно, а «последнее значение» — по сути горячий кэш, которому база не нужна.
4Пороги в правилах — без гистерезиса. Отдельные правила «включить ниже 23» и «выключить выше 25» борются друг с другом.Классика: реле щёлкает, потому что состояние не является «машиной состояний», а вычисляется заново из мгновенного значения. (мой косяк, не указал условия состояния реле, хотя возможность есть)
5Состояние управления теряется при перезапуске службы. Отложенные действия («выключить через 60 с») и ожидание подтверждения живут в памяти процесса.Перезапуск движка — и обещанное действие просто не произойдёт. Никто об этом не узнает.
6Две параллельные системы автоматизации: движок правил и cron.Разбор инцидента начинается с расследования «кто это сделал», а не с ответа «почему». (тут все просто, логика движка проверка раз в сек, а кормушка включается на 3 секунды. просто в кроне надежнее)
7Хранение секретов исторически было в коде (пароли БД и MQTT прямо в PHP), плюс креды администратора БД использовались там, где нужны MQTT-креды.Это уже исправлено (секреты вынесены в /etc/iot/, учётка приложения урезана до SELECT/INSERT/UPDATE/DELETE), но остаётся риск возврата: любой новый скрипт легко напишет пароль «по старинке».
8Правила — это данные в таблице, с неиспользуемыми колонками. Часть полей движок просто не читает.Пользователь видит настройки, которые ничего не делают. Это хуже, чем их отсутствие.
9Датчики, пишущие «по событию», выглядят для системы как исчезнувшие.Нужен явный признак «нет данных N часов» — иначе 90 % заряда показывается как свежее значение месячной давности.
10История растёт без ретенции. Таблица чистится «до 10 000 строк на топик» при каждой вставке.Работает, но это тяжёлый способ: удаление по одной вставке, без партиционирования и без явной политики «месяц/год».
Отдельно про безопасность железа. Управление водой и нагревом через Zigbee-реле — это нормально для быта, но не как единственная защита. Если нагреватель аквариума управляется только по Wi-Fi/Zigbee, потеря связи = либо холодная рыба, либо перегрев. Правильный минимум: аппаратный термостат/предохранительный клапан как последний барьер, а софт — как удобство и экономия. (ну тут скорее у меня как раз в виде предохранителя, т.к. на самом обогревателя отсечка настраивается на максимальную температуру)

4. Главный вопрос: слушать брокер напрямую или через базу?

Вопрос поставлен верно, и ответ короткий: движок должен слушать брокер напрямую, а база должна перестать быть «транспортом» между брокером и движком. Но уточню, потому что здесь легко перепутать три разные роли базы:

  1. Транспорт/шина событий — за это должна отвечать MQTT. База тут лишнее звено.
  2. Долговременная история и аналитика — за это отвечает база, и она нужна.
  3. Настройка (правила, справочники, порогов) — тоже база, и это удобно: правила редактируются из панели.

Проблема текущей схемы в том, что первая роль тоже отдана базе. Уберём это — и всё встанет на место. (вот это и был главный вопрос гермес-агенту, надо настроиться и переделать все)

4.1. Что конкретно меняется

СейчасПравильно
Как движок узнаёт о событиираз в секунду SELECT из sensor_dataподписка zigbee2mqtt/#, событие приходит само
Где хранится «последнее значение»строка в таблицев памяти движка (+ retained в брокере как восстановимый снимок)
Латентность реакциидо 1 секунды (+ время записи в базу)единицы миллисекунд
Нагрузка на базуINSERT на каждое сообщение + SELECT-цикл каждую секундупакетная запись: только нужные топики и только когда изменилось; «последние значения» сбрасываются в базу раз в N минут
Что если база тормозит/лежитдвижок слепнет вместе с базойдвижок продолжает работать, история догоняет потом
Реакция на «молчание» устройстванужно заметить, что строка в базе стараяестественно: просто нет событий, а движок ведёт таймер последнего касания

4.2. Что это даёт на практике

4.3. А это не менее надёжно? Честно про минусы

Надёжность не в «через базу» или «через брокер», а в том, что происходит при перезапуске и при потере связи. Прямая подписка добавляет три вопроса, и у каждого есть ответ:

ВопросОтвет
Упал движок — память пуста, состояние потеряноRestart=always в systemd + запись состояния на диск после каждого изменения (маленький JSON) + retained-сообщения в брокере как источник «последнего известного». При старте движок публикует .../get и перечитывает актуальные значения — через 2 секунды он снова знает всё.
Упал брокерДвижок переподключается (клиентская библиотека это умеет), события копятся в Zigbee-мосте. Здесь важнее другое: правила должны уметь «мягко деградировать» — если данных нет дольше N минут, включается безопасное состояние (кран закрыт, нагреватель в покое), а не «оставить как было».
Данные устарели (датчик молчит), а движок этого не видитЯвный guard: у каждого значения в памяти — время последнего обновления; правило срабатывает только на свежих данных, иначе это отдельное событие «нет связи», которое стоит показывать и в панели, и в уведомлениях.

Ещё один аргумент, который часто упускают: у текущей схемы проблема с перезапуском уже есть (пункт 5 диагноза) — отложенные действия и подтверждения теряются при рестарте. То есть «через базу» не даёт надёжности, которую якобы теряет прямая подписка. Переход на события позволяет эту дыру закрыть системно, а не затыкать страховочными правилами.

4.4. Вердикт

Движок правил → одна долгоживущая служба, которая подписана на zigbee2mqtt/# и держит состояние в памяти. База → только история и настройки, запись пакетами. Правило «включить/выключить» вычисляется на событии, а не по таймеру. Это и быстрее, и, если сделать аккуратно, надёжнее, чем сейчас.

Миграцию при этом можно сделать без «большого взрыва»: сначала поднять рядом новый движок, который только слушает и пишет в отдельный лог (что бы он сделал на каждом событии), неделю сравнить его решения с текущим, а потом переключить исполнение. Так делают и в больших системах.

Скелет такого движка (Python, asyncio + aiomqtt)

import asyncio, json, time, aiomqtt

STALE = 900            # данных нет 15 минут — считаем датчик пропавшим

class Engine:
    def __init__(self, client):
        self.c = client
        self.vals = {}      # топик -> (значение, время)
        self.modes = {}     # состояние автоматов: 'fish_heater' -> 'idle'/'heating'

    async def run(self):
        await self.c.subscribe("zigbee2mqtt/#")
        async for msg in self.c.messages:
            t = str(msg.topic)
            if t.endswith("/set"):        # эхо собственных команд не считаем данными
                continue
            try: data = json.loads(msg.payload)
            except ValueError: continue
            now = time.time()
            for k, v in (data.items() if isinstance(data, dict) else [(t, data)]):
                self.vals[f"{t}/{k}"] = (v, now)
                await self.on_value(f"{t}/{k}", v)

    async def on_value(self, topic, value):
        # пример: термостат как машина состояний, а не два правила с порогами
        if topic == "zigbee2mqtt/fish_reley_temp/temperature":
            t = float(value)
            mode = self.modes.get("fish_heater", "idle")
            if mode == "idle" and t < 23.0:
                await self.act("fish_power/set", {"state_l3": "ON"})
                self.modes["fish_heater"] = "heating"
            elif mode == "heating" and t > 25.0:
                await self.act("fish_power/set", {"state_l3": "OFF"})
                self.modes["fish_heater"] = "idle"

    def fresh(self, topic):
        v = self.vals.get(topic)
        return v is not None and time.time() - v[1] < STALE

    async def act(self, action_topic, payload):
        await self.c.publish(f"zigbee2mqtt/{action_topic}", json.dumps(payload), retain=False)

Обратите внимание на три вещи: команды публикуются только на смене состояния (никакого «долбления» каждую секунду), у каждого значения есть время, и «молчание датчика» становится обычным проверяемым условием. Плюс тот же процесс может писать историю пачками — тогда отдельный логгер вообще не нужен.

5. Как делать правильно: 12 принципов

  1. Один владелец состояния. Не три места, а одно: движок. Всё остальное — производные (retained в брокере для восстановления, БД для истории).
  2. Конвейер, а не «всё в одном». Вход (протокол), логика (правила), выход (актуаторы), история (запись), интерфейс (панель) — разные роли. Сегодня это частично выполнено, доводить до конца.
  3. Событийная реакция вместо опроса. Опрос — только там, где нет событий (например, раз в 10 минут проверить, что службы живы).
  4. Команды идемпотентны. «Включить то, что уже включено» не должно порождать новое событие и уведомление. Флаг «пропущено, состояние уже целевое» — хорошая идея, которую надо оставить и в новой схеме.
  5. Каждая команда — с подтверждением. Опубликовали → ждём, что устройство сообщило новое состояние (в MQTT это приходит в тот же топик). Не пришло за N секунд — тревога, а не тишина.
  6. Безопасное состояние по умолчанию. Связь потеряна → кран закрыт, нагреватель выключен, ничего не «остаётся как было». Fail-safe должен быть заложен в правила, а не в надежду.
  7. Гистерезис и машины состояний вместо парных правил. Подробно ниже, но правило простое: «включить ниже X, выключить выше Y» — это один автомат с двумя порогами, а не два независимых правила.
  8. Не привязываться к именам устройств. Правила должны ссылаться на роль («датчик влажности грядки»), а не на строку gorshok_smallone. Имя Zigbee-устройства меняется — правило ломается. Отображение «роль → топик» должно лежать в одном справочнике.
  9. Секреты только в одном месте и с узкими правами. Отдельные учётки: «читатель» для панели, «движок» для чтения данных и записи команд, приложение — без прав менять схему БД. MQTT-ACL по топикам.
  10. Ретенция как настройка, а не как побочный эффект. «Хранить 30 дней, агрегаты — год», реализовано партиционированием или отдельной таблицей агрегатов. Удаление десяти тысяч строк при каждой вставке — это не политика хранения.
  11. Наблюдаемость по умолчанию. Здоровье, задержка реакции, число срабатываний, ошибки — и обязательное «тишина датчика» как отдельное состояние.
  12. Всё под git. Конфиги, правила в виде файла (снимок таблицы автоматизаций), скрипты, юниты. Дамп базы — отдельно, по расписанию. Историю изменения правил хочется видеть: «кто и когда поменял порог».

6. Почему «два правила на один порог» воюют: гистерезис и машина состояний

Это самая частая логическая ошибка в самодельных домах, и в разбираемом проекте она была: правило «включить нагрев при температуре ниже 23» и правило «выключить при выше 25» — на первый взгляд правильная пара. Проблема в том, что реле физически одно, а решений о нём принимают два независимых потребителя, которые ничего не знают друг о друге. Стоит добавить третий (например, cron с усреднением за 15 минут) — и начинается «реле щёлкает не по правилам, а по моменту запуска скрипта».

Правильно — один автомат с состоянием:

состояние: idle | heating

idle       + температура < 23.0 (устойчиво 30 с)  → ON  → heating
heating    + температура > 25.0                   → OFF → idle
heating    + данных нет > 15 минут                → OFF → idle  (fail-safe)
любое      + ручная команда из панели             → принудительное состояние + тайм-аут

Отсюда сразу видны вещи, которых в паре правил не выразить: выдержка (устойчиво 30 секунд), поведение при пропаже данных, приоритет ручного управления. Всё это — состояние, а не условие, и хранить его надо вместе с решением, а не выводить заново из мгновенного значения.

Проверка на практике. Хороший тест для такого автомата — не «сработало ли правило», а график: сколько раз за сутки щёлкнуло реле и какова длительность каждого включения. Если реле включалось 40 раз по 20 секунд — это не автоматика, это дребезг.

7. Секреты, доступы и ACL

Исторически это была самая слабая часть, и её уже вылечили: секреты вынесены из кода в отдельные файлы с правами 640 root:www-data и 640 root:mazzick, у приложения урезаны права в БД, крон-скрипты перестали ходить в MQTT под учёткой администратора базы. Это стоит зафиксировать как правило и не разъехаться обратно.

Что добавить:

# /etc/mosquitto/acl
user iot_engine            # движок: читает всё, командует устройствами
topic read  zigbee2mqtt/#
topic write zigbee2mqtt/+/set

user iot_panel             # панель: только чтение + ручные команды
topic read  zigbee2mqtt/#
topic write zigbee2mqtt/+/set

user iot_logger            # логгер: только чтение
topic read  zigbee2mqtt/#

pattern write zigbee2mqtt/bridge/request/#   # служебные запросы — кому разрешено

8. Бэкапы и восстановление

Сейчас есть два скрипта, собирающие архив: дамп всех БД, конфиги zigbee2mqtt, mosquitto, nginx, systemd, cron. Это правильный набор. Чего не хватает:

  1. Проверки восстановления. Бэкап без теста восстановления — это не бэкап, а надежда. Раз в квартал: развернуть на виртуалке, поднять, проверить, что панель отвечает и правила на месте.
  2. Ротации. Сейчас в домашней папке лежат архивы по 190–700 МБ за разные месяцы и рядом выгрузки сайтов с хостинга — суммарно больше гигабайта, который к дому отношения не имеет. Нужна политика: последние 7 дневных, 4 недельных, 12 месячных, всё остальное удаляется автоматически.
  3. Ключ Zigbee-координатора. Восстановление сети Zigbee — это в первую очередь сохранённый coordinator_backup.json из zigbee2mqtt. Без него вся сеть спаривается заново.
  4. Снимок правил. Таблица automations — это тоже код. Хочется видеть её в git в виде файла (TSV/JSON), с диффом при каждом изменении из панели. Полчаса работы — и вопросы «кто поменял порог» закрываются навсегда.
  5. Внешнее хранилище. Бэкап на той же малине спасает от ошибки, но не от смерти диска. Копия на NAS/в облако.

9. Наблюдаемость: чтобы дом сам сказал, что сломался

Здесь в проекте больше, чем в 90 % самоделок: внешняя проверка здоровья, ежечасный сторож с письмом и защитой от повторов, отдельная служба статистики аномалий. Что я бы добавил именно как «правильное»:

МетрикаЗачемПорог тревоги (пример)
Задержка «событие → команда»Главная метрика качества автоматики> 2 с — разобраться
Доля команд без подтвержденияМолчащие устройства и битый Zigbee> 5 % за час
Длительность непрерывного включения релеЗалипание, заливание грядки, перегрев> 10 мин для крана, > 60 мин для нагрева
Возраст последнего значения по устройствуРазличать «молчит по делу» и «сломалось»> суток для событийных датчиков — показать как «нет связи»
Число срабатываний правила за суткиДребезг и логические петли> 100 — почти всегда ошибка правила

И отдельный момент, который обычно упускают: молчание системы не должно быть единственным доказательством здоровья. Сторож, который пишет письмо только при проблеме, хорош, но раз в неделю нужен «отчёт о жизни»: сколько устройств на связи, сколько срабатываний, среднее время реакции, размер базы. Иначе поломка уведомлений выглядит как «всё хорошо».

10. Если бы строил с нуля: три варианта стека

Честно: бо́льшую часть этого дома можно не писать самому. Но у самописного есть реальная ценность — понимание каждого узла и полный контроль. Поэтому варианты, а не один «правильный ответ».

Вариант A. Готовое ядро + своя логика (рекомендую большинству)

zigbee2mqtt + Mosquitto + Home Assistant (или Node-RED) + MariaDB/InfluxDB для истории. Всё, что сегодня делают вручную PHP-движок, панель и часть cron, уже есть: редактор автоматизаций, история, уведомления, мобильное приложение, интеграции. Самописное остаётся ровно там, где оно даёт пользу — специфические сценарии (аквариум, полив) и свои отчёты. Развёртывание в Docker Compose, бэкап — том плюс дамп БД.

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

Вариант B. Остаться самописным, но сделать правильно

Тот же стек, что есть, с заменой «база как шина» на «брокер как шина»: один Python-движок на событиях (asyncio + paho/aiomqtt), правила в YAML с версионированием, FastAPI для панели вместо PHP, SQLite или MariaDB только для истории, Docker Compose, git, pytest для логики правил, симулятор MQTT для тестов.

Плюсы: полный контроль, лёгкость на Raspberry Pi, тестируемость, отсутствие зависимости от больших фреймворков. Минусы: всё это надо поддерживать самому, и мобильное приложение придётся делать самому (или обойтись Telegram-ботом, что для дома обычно достаточно).

Вариант C. Гибрид (часто лучший на практике)

Ядро — готовое (Home Assistant / Node-RED), а критичные контуры — свои, с тестами: термостат аквариума, защита от заливания, отчёты. Zigbee остаётся в zigbee2mqtt (он и так лучший в своём деле), брокер один, история одна. Так снимается 80 % рутины и остаётся контроль над тем, что действительно важно.

11. План улучшений и чек-лист

Приоритеты

ПриоритетЧто сделатьЭффектТрудозатраты
P0 Аппаратный fail-safe на нагрев и воду: термостат/предохранительный клапан, независимо от софта. Плюс правило «нет данных 15 минут → безопасное состояние». Гарантия от порчи имущества при любом сбое софта 1–2 часа + деталь
P0 Гистерезис/машина состояний вместо парных порогов; убрать конкуренцию cron и движка за одно устройство (оставить один владелец). Дребезг реле, «кто управлял» и споры автоматики исчезают 2–4 часа
P0 Тест восстановления из бэкапа + ротация архивов + сохранение coordinator_backup.json. Дом поднимается после смерти диска 2 часа
P1 Движок на события: подписка на zigbee2mqtt/#, состояние в памяти, запись истории пачками. Сначала в режиме «только запись в лог решений» — сравнить с текущим движком. Реакция миллисекунды, база разгружена, падение БД не останавливает автоматику 1–2 вечера
P1 Подтверждение команд и учёт «не подтвердилось → тревога»; вынос отложенных действий в файл/таблицу, чтобы переживали перезапуск. Система знает, когда команда не дошла, вместо тишины вечер
P1 ACL в брокере и три отдельные учётки (движок/панель/логгер). Закрыть анонимный порт снаружи. Утечка одной учётки не даёт контроль над домом 1 час
P2 Правила в файле + в git (снимок automations при каждом изменении); роли устройств вместо имён в правилах; вычистить неиспользуемые колонки формы. Понятная история изменений, правила не ломаются от переименования вечер + час
P2 Ретенция истории (партиционирование/агрегаты), метрики (задержка реакции, число срабатываний, возраст данных) и недельный «отчёт о жизни». База не растёт бесконтрольно, проблемы видно до аварии вечер
P2 Убрать балласт: мёртвые скрипты-черновики и вторая (самодельная) копия движка правил — в карантин, а не «пусть лежит». Меньше шансов запустить не то и разбирать не тот файл 30 минут

Чек-лист «правильный самописный умный дом»

Приложение: замеры на живой системе (30.09.2026, 11:05)

Через пару часов после публикации статьи появился доступ к малине, и я прогнал проверку по факту. Ничего не менял — только смотрел. Ниже цифры, которыми подтверждаются (или уточняются) тезисы выше.

ПроверкаРезультат
СлужбыВсе семь active, NRestarts=0 у движка, логгера и модуля аномалий — ни одна не падала и не поднималась сама
Ошибки в журналах за неделю0 строк с error/fatal/traceback
Данные32 сообщения за 5 минут, 97 «живых» топиков, ключевые устройства обновляются прямо сейчас
Журнал срабатываний276 строк за сутки, следов удалённого триггера (rule_id IS NULL) — 0
СторожЕжечасный, состояние last_problem.txt = одна проблема; письмо ушло один раз в 03:05 и дальше не дублируется — защита от спама работает
Брокер MQTTОба порта слушают только 127.0.0.1: 1883 с паролем, 1884 анонимно (для внутренних скриптов). Наружу не открыт. ACL-файла нет — доступ разграничен только паролем
Диск и журналыЗанято 27 %, журнал systemd 77,6 МБ — место не проблема
История батареек12 402 точки за сутки — тренд строится

Что подтвердилось на практике

Что уточнилось против первой редакции

Вывод, который теперь подкреплён цифрами. Система в хорошем состоянии: неделя без единой ошибки в журналах, службы не перезапускались, сторож отработал ровно так, как рассчитывался. И главное — движок ведёт себя дисциплинированно там, где это важнее всего: за сутки отправлено 263 команды на весь дом (из них 119 — ваш тест), нагрев аквариума получил 2, повторов команд 0. Проблема не в стабильности сервисов и не в дребезге реле, а в двух конкретных местах: шум в журнале (15 074 строки эха таймера в сутки) и правило 158, которое шлёт сотни уведомлений. Поэтому приоритеты в плане выше стоят не на «переписать движок», а на «машина состояний + один владелец устройства + аппаратная страховка».

Итого

Проект сильнее, чем выглядит: разделение на службы, история, журнал срабатываний, внешний сторож, вынесенные секреты — это то, до чего большинство самоделок не доходит даже через год. Реальная слабость не в языке и не в базе, а в архитектурном выборе: база здесь работает шиной событий. Отсюда растёт почти всё остальное — задержка реакции, лишняя нагрузка, споры между cron и правилами, потеря отложенных действий при перезапуске.

Ответ на исходный вопрос: да, движок должен слушать брокер напрямую, а базу оставить для истории и настроек. Это не менее надёжно — при трёх условиях, которые надо написать явно: восстановление состояния при старте, поведение при потере связи (fail-safe) и guard на устаревшие данные. И делать это лучше не «в один день», а поставив новый движок рядом в режиме наблюдения и сравнив его решения с текущими.

И главное, что стоит сказать вслух: у самописного дома есть то, чего не купить — понимание каждой линии своего кода. Поэтому «переписать на Home Assistant» — не единственный правильный путь. Правильный путь — оставить контроль там, где он ценен, и не тащить на себе то, что давно решено другими. (ну это слишком просто. Легче всего HomeAsistent поставить! Но мы легких путей не ищем)

Теги: #умный_дом



Категории:

Категории

← Назад к списку

Посетителей сегодня: 0
о блоге | карта блога | 📡 Подписаться на RSS

© Digital Specialist | Не являемся сотрудниками Google, Яндекса и NASA