Написал я веб-интерфейс для правил автоматизации. С вечным циклом PHP, MQTT-подписками, подтверждениями, задержками, AJAX-панелями, цветными кнопочками... Красиво, модно, молодёжно.
И всё это ради того, чтобы один раз в полчаса проверить, не засох ли можжевельник. Ну и чтобы при движении письмо приходило, когда никого дома нет.
А по факту: никто эти интерфейсы не открывает. Комментариев никто не пишет, логи никто не смотрит. Зачем тогда всё это?
Правильное решение оказалось проще: всё, что нужно, уже лежит в базе данных — таблица sensor_data хранит историю всех датчиков.
Осталось только настроить пару скриптов и добавить их в крон.
email_history не даёт отправлять повторно.
CREATE TABLE IF NOT EXISTS email_history (
id INT AUTO_INCREMENT PRIMARY KEY,
rule_name VARCHAR(100),
trigger_value VARCHAR(50),
sent_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY unique_daily (rule_name, DATE(sent_at))
);
Файл: /var/www/html/cron_motion_email.php
<?php
$pdo = new PDO("mysql:host=127.0.0.1;dbname=iot_db;charset=utf8mb4", "user", "123456");
$motionTopic = 'zigbee2mqtt/motion_sensor/presence';
$emailTo = '9447333@gmail.com';
$checkMinutes = 30;
// Было ли движение за последние 30 минут
$stmt = $pdo->prepare("
SELECT COUNT(*) as cnt FROM sensor_data
WHERE topic = ? AND value = '1'
AND timestamp > DATE_SUB(NOW(), INTERVAL ? MINUTE)
");
$stmt->execute([$motionTopic, $checkMinutes]);
$motion = $stmt->fetch();
// Проверяем, не отправляли ли уже сегодня
$stmt = $pdo->prepare("
SELECT COUNT(*) as sent FROM email_history
WHERE rule_name = 'motion' AND DATE(sent_at) = CURDATE()
");
$stmt->execute();
$sent = $stmt->fetch();
if ($motion['cnt'] > 0 && $sent['sent'] == 0) {
$subject = "📡 Обнаружено движение";
$message = "За последние $checkMinutes минут было {$motion['cnt']} срабатываний\n";
$message .= "Время: " . date('Y-m-d H:i:s');
mail($emailTo, $subject, $message, "From: it@logoakademia.ru\r\n");
$pdo->prepare("INSERT INTO email_history (rule_name) VALUES ('motion')")->execute();
echo date('Y-m-d H:i:s') . " - Email о движении отправлен\n";
}
Файл: /var/www/html/cron_water_email.php
<?php
$pdo = new PDO("mysql:host=127.0.0.1;dbname=iot_db;charset=utf8mb4", "user", "123456");
$moistureTopic = 'sensors/soil_moisture';
$emailTo = '9447333@gmail.com';
$dryThreshold = 30;
// Последнее значение влажности
$stmt = $pdo->prepare("
SELECT value, timestamp FROM sensor_data
WHERE topic = ? ORDER BY timestamp DESC LIMIT 1
");
$stmt->execute([$moistureTopic]);
$sensor = $stmt->fetch();
if (!$sensor) exit("Нет данных\n");
// Проверяем, не отправляли ли сегодня
$stmt = $pdo->prepare("
SELECT COUNT(*) as sent FROM email_history
WHERE rule_name = 'watering' AND DATE(sent_at) = CURDATE()
");
$stmt->execute();
$sent = $stmt->fetch();
if ($sensor['value'] < $dryThreshold && $sent['sent'] == 0) {
$subject = "💧 Нужно полить можжевельник!";
$message = "Влажность почвы: {$sensor['value']}%\n";
$message .= "Время замера: {$sensor['timestamp']}\n";
$message .= "Порог: ниже $dryThreshold%";
mail($emailTo, $subject, $message, "From: it@logoakademia.ru\r\n");
$pdo->prepare("INSERT INTO email_history (rule_name, trigger_value) VALUES ('watering', {$sensor['value']})")->execute();
echo date('Y-m-d H:i:s') . " - Письмо о поливе отправлено\n";
}
# Редактируем crontab sudo crontab -e # Добавляем строки: */30 * * * * /usr/bin/php /var/www/html/cron_motion_email.php >> /var/log/motion.log 2>&1 0 * * * * /usr/bin/php /var/www/html/cron_water_email.php >> /var/log/water.log 2>&1
Крон — не для секунд. Минимальный интервал — 1 минута.
| Интервал | Точность | Нагрузка | Для каких задач |
|---|---|---|---|
| 1 минута | ± несколько секунд | Низкая | Движение, протечка, дым |
| 5 минут | ± 5-10 сек | Очень низкая | Температура, влажность |
| 30 минут | ± 30 сек | Минимальная | Полив, уведомления раз в полчаса |
| 1 час | ± 1 минута | Ничтожная | Дневная статистика, отчёты |
Нагрузка: один PHP-скрипт с простым SELECT-запросом выполняется за 0.01-0.05 секунды. Даже 10 таких скриптов в минуту — это 0.5 секунды работы в минуту, или 0.8% нагрузки на одно ядро. Для Raspberry Pi — вообще копейки.
Не усложняйте там, где можно просто. Интерфейсы и свистоперделки — это круто для портфолио. Но для себя, для дома, для души — лучше надёжные скрипты в кроне, которые работают годами без присмотра.
Все данные уже есть в базе. Не нужно городить вечные циклы, подписываться на MQTT, обрабатывать подтверждения.
Просто берём sensor_data, проверяем историю, отправляем письмо, запоминаем в email_history.
🌱 Можжевельник скажет спасибо. А комментарии — ну их.
P.S. Если что-то пойдёт не так — логи всегда под рукой: /var/log/motion.log и /var/log/water.log
Комментарии
Пока нет комментариев. Будьте первым!