Категории

Ошибки скрипта iot автоматизации, не срабатывали правила с условием == 1

01.02.2026 | Статья из категории: php

🔍 Проблема: правила с == 1 не срабатывали. В ходе анализа выявлено, что правила с условием == 1 перестали срабатывать. Причина оказалась в изменённой логике обработки данных (если точнее, sql запрос поменял): изначально изменения вводились с целью снижения нагрузки на базу данных, однако это привело к полному игнорированию событий со значением 1.
После исправления ошибки стало очевидно, что текущая архитектура не масштабируется: при объёме данных ~700 тыс. строк за последние 7 дней даже после оптимизации индексов и структуры таблиц запросы выполняются слишком медленно, создавая значительную нагрузку как на СУБД, так и на CPU.
Вывод: текущая монолитная логика (проверка правил + сбор данных + построение графиков в одном потоке) неэффективна.

Предлагаемые меры:

Делать логику через отдельные скрипты, но это не красиво и без админкию. Мы легких путей не ищем, нам это не подходит )

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

Исторические данные должны агрегироваться и архивироваться отдельно от оперативной логики — это снизит объём "горячих" данных и ускорит выполнение критически важных операций.
Такой подход повысит надёжность, производительность и сопровождаемость системы в долгосрочной перспективе.

❌ Причина

В основном цикле mqtt_listener.php данные из таблицы sensor_data загружались один раз:

SELECT topic, value FROM sensor_data ORDER BY timestamp DESC

Но при наличии множества записей от разных датчиков свежее значение (например, presence = '1') могло не попасть в массив $sensorData, потому что:

  • Сортировка по timestamp DESC не гарантирует уникальность по топику
  • При обходе fetchAll(PDO::FETCH_KEY_PAIR) более старые записи с тем же топиком могли перезаписать новые

→ Правило видело старое значение ('0'), даже если в БД уже было '1'.

🔎 Как диагностировали

  • Проверили, что в БД действительно появляется '1' при движении (через SQL)
  • Написали простой тест-скрипт — он ловил '1' без проблем
  • Сравнили логику: тест делал прямой запрос, а основной скрипт — использовал общий массив
  • Вывод: проблема в способе загрузки данных в $sensorData

✅ Решение

Для триггерных правил (schedule_type = 'none') заменить использование общего $sensorData на прямой SQL-запрос:

$stmt = $pdo->prepare("SELECT value FROM sensor_data WHERE topic = ? ORDER BY timestamp DESC LIMIT 1");
$stmt->execute([$triggerTopic]);
$actualValue = $stmt->fetchColumn();
  

Это гарантирует, что правило всегда видит самое свежее значение из БД.

✅ После этого правила == 1 заработали мгновенно.

📌 Вывод

При опросе БД раз в секунду критически важно получать актуальные данные. Использование единого снимка ($sensorData) удобно, но опасно, если нет гарантии уникальности по топику. Для триггерных правил — лучше прямой запрос.

Комментарии

Пока нет комментариев. Будьте первым!

Оставить комментарий

← Назад к списку статей

Посетителей сегодня: 0
о блоге

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