== 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) удобно, но опасно, если нет гарантии уникальности по топику.
Для триггерных правил — лучше прямой запрос.
Комментарии
Пока нет комментариев. Будьте первым!