Как я сделал систему логики автоматизации для IoT-проекта
Привет! Сегодня хочу рассказать, как я реализовал ядро системы автоматизации для своего IoT-проекта — а именно, два ключевых компонента:
- logic.php — веб-интерфейс для создания правил автоматизации.
- mqtt_listener.php — фоновый “движок”, который проверяет условия и выполняет действия.
Это не про весь “умный дом”, а именно про логику принятия решений: когда, почему и как система должна включить свет, обогреватель или закрыть шторы.
Зачем это нужно?
В IoT-системах устройства генерируют данные (температура, движение, открытие двери), а другие устройства должны на них реагировать. Но реакция должна быть умной:
- Включить обогрев только если температура ниже 18°C.
- Выключить свет через 5 минут после исчезновения движения.
- Включить кофеварку каждый будний день в 7:00, но только если ты дома (статус телефона в Wi-Fi).
Для этого нужен “мозг” — и я его сделал на PHP + MySQL + MQTT.
Структура БД: таблица automations
Всё хранится в одной таблице — automations. Вот ключевые поля:
name— название правила (для человека).trigger_topic— MQTT-топик, который “запускает” правило (например,sensors/temperature/living_room).condition_operatorиcondition_value— простое условие:>,==,<=и т.д.condition_script— альтернатива: JS-подобное выражение для сложных условий (например,sensor.temp > 20 && sensor.humidity < 60).condition_duration— сколько секунд условие должно соблюдаться, прежде чем сработать.action_topicиaction_payload— куда и что отправить (например,devices/heater/set→{"state": "ON"}).schedule_type— можно запускать не только по триггеру, но и по расписанию:daily,weekly.dependency_topicиdependency_value— дополнительное условие: “сработать только если окно закрыто”.confirmation_topic— система может ждать подтверждения от устройства (например, что реле действительно включилось).delay_seconds— задержка перед выполнением действия.enabled— можно временно отключить правило.
Таблица спроектирована так, чтобы одно правило могло охватывать множество сценариев — от простого “включил-выключил” до сложных сцен с подтверждениями, расписаниями и скриптами.
logic.php — веб-интерфейс администратора
Это PHP-страница с формой, где можно создавать, редактировать и удалять правила. Ключевые фичи:
1. Тип активации
- По триггеру — срабатывает при изменении данных в MQTT-топике.
- По расписанию — ежедневно или по дням недели в заданное время.
2. Условия
Можно выбрать один из двух типов:
- Простое — оператор + значение (например,
температура > 25). - Скриптовое — JS-подобное выражение с поддержкой
sensor.{topic}и логических операторов.
Условие работает и для триггеров, и для расписания. Например: “Каждый день в 8:00 включать обогрев, ЕСЛИ температура < 10”.
3. Действия
- Указываешь
action_topicиaction_payload. - Можно добавить задержку перед выполнением.
- Можно указать топик подтверждения — система будет ждать ответа от устройства.
- Можно настроить максимум попыток и таймаут.
4. Зависимости
Дополнительный “флаг безопасности”: правило сработает только если другой топик имеет определённое значение. Например: “Включить полив, только если датчик дождя == сухо”.
5. Безопасность скриптов
Скриптовые условия выполняются через безопасный интерпретатор:
- Замена
sensor.xxx→$sensorData['xxx']. - Проверка на запрещённые символы и функции (
eval,systemи т.д.). - Выполнение через временный PHP-файл (не
eval()!).
mqtt_listener.php — “движок” автоматизации
Это фоновый PHP-скрипт, который работает в бесконечном цикле. Он:
- Раз в 5 секунд перезагружает активные правила из БД.
- Раз в минуту проверяет, не наступило ли время по расписанию.
- Постоянно проверяет, выполнились ли условия для триггерных правил.
- Отправляет команды через
mosquitto_pub. - Ждёт подтверждений от устройств.
- Выполняет отложенные действия (если задана задержка).
Ключевые функции:
evaluateRuleCondition($rule, $pdo)
Проверяет, истинно ли условие правила — простое или скриптовое. Для скриптов использует тот же безопасный механизм, что и в logic.php.
handleAction($rule)
Выполняет действие с учётом задержки и подтверждения. Если указана delay_seconds — действие откладывается. Если указан confirmation_topic — система ждёт подтверждения и может повторять попытки.
checkPendingConfirmations($pdo)
Проверяет, пришли ли подтверждения от устройств, сравнивает с ожидаемым состоянием и помечает правило как выполненное.
Как это работает вместе?
- Ты заходишь в
logic.php, создаёшь правило: “Если температура < 10 — включить обогрев”. - Правило сохраняется в БД.
mqtt_listener.phpподхватывает его при следующей перезагрузке.- Каждые 5 секунд он проверяет: а не изменилась ли температура? А не наступило ли время по расписанию?
- Если условие выполнилось — отправляет команду в MQTT.
- Если нужно — ждёт подтверждения.
- Логирует всё в консоль (можно легко перенаправить в файл).
Что дальше?
Это основа. В будущем можно добавить:
- Историю срабатываний.
- Уведомления в Telegram.
- “Тестовый режим” — чтобы не включать реальные устройства при отладке.
- “Окно срабатывания” — чтобы правило могло сработать в течение ±5 минут от указанного времени.
- Визуальный редактор скриптов с подсветкой синтаксиса.
Заключение
Я не использовал готовые платформы вроде Node-RED или Home Assistant — мне хотелось полного контроля и понимания “под капотом”. PHP + MySQL + MQTT — оказалось, отличный стек для этого.
Система получилась гибкой, расширяемой и безопасной. И самое главное — она работает 😊
Код открыт, структура понятна — приходите, задавайте вопросы, кастомизируйте под себя. Умный дом — это не про покупку коробки, а про создание того, что действительно нужно именно тебе.
P.S. В следующей статье разберу код построчно — если хотите глубже понять, как всё устроено “под капотом”
🔐 Код пока в секрете!
Я специально не выкладываю полные исходники — хочу, чтобы вы задавали вопросы, предлагали улучшения, делились идеями.
👉 Хотите файлы logic.php и mqtt_listener.php?
Пишите в комментариях:
- Что вам интересно?
- Какие фичи хотите добавить?
- Где бы вы использовали такую систему?
Самые активные и интересные комментаторы получат код в личку 🎁
(А потом, возможно, сделаю отдельную статью с построчным разбором!)
Комментарии
Пока нет комментариев. Будьте первым!