В 2040 году искусственный интеллект управляет транспортом, климатом и даже выборами. Но настоящие инженеры знают: самое важное — это печка. А если печка умная — ты уже на шаг впереди цивилизации.
Эта статья — о том, как превратить обычную буржуйку в IoT-систему уровня NASA, используя только PHP, MySQL, Zigbee2MQTT, Telegram и сервопривод. Без Home Assistant автоматизаций. Без YAML. Без облаков. Только чистый код, железо, дрова — и немного логики.
А ещё — это система безопасности и автоматического управления. Потому что если печка внезапно потухла — это не всегда «пора подкинуть дров». А если она перегрелась — это уже пожарная опасность. И система должна не только оповестить — но и сама вмешаться.
[Датчик температуры Zigbee (Aqara)] → данные → [Zigbee2MQTT → MySQL] ↓ [PHP-скрипт по крону] ↓ ┌──────────────────────────┬────────────────────┴────────────────────┬──────────────────────────┐ ↓ ↓ ↓ ↓ [Telegram: "Подкинь дров"] [Telegram: "Тревога: потухла"] [Telegram: "ПЕРЕГРЕВ!"] [MQTT: команда сервоприводу] ↓ ↓ ↓ ↓ [Ты несёшь дрова] [Ты проверяешь дымоход] [Ты бежишь к печке] [Серва закрывает поддувало]
Используем Aqara Temperature & Humidity Sensor — он дешёв, надёжен, Zigbee. Но его пластик плавится при 80°C. Поэтому:
Датчик не измеряет температуру печки — он измеряет воздух рядом с печкой. Но этого достаточно, чтобы понять: горит она или нет, перегревается или тухнет.
Для автоматического управления нужен сервопривод, подключённый к микроконтроллеру (например, ESP32), который работает как Zigbee-устройство.
Пример устройства:
cover
или switch
Устройство публикует и принимает команды в MQTT-топике, например:
zigbee2mqtt/servo_damper/set → {"state": "CLOSE"} zigbee2mqtt/servo_damper → {"state": "OPEN", "position": 90}
При команде CLOSE
— серва поворачивается и закрывает поддувало. При OPEN
— открывает.
Состояние | Условие | Действие |
---|---|---|
🔥 Активный нагрев | Температура > 70°C | Запоминаем максимум — ничего не шлём |
🪵 Пора подкинуть дров | Температура < 50% от максимума И > 25°C | Отправить: «Температура упала до X°C — пора подкинуть дров!» |
🚨 Тревога: неожиданное затухание | Температура ≤ 25°C И был максимум > 60°C | Отправить: «ТРЕВОГА: печка резко потухла — проверьте дымоход!» |
⚠️ Предупреждение: перегрев | Температура > 90°C | Отправить: «Внимание! Температура высокая — X°C. Контролируйте горение.» |
🔴 Авария: критический перегрев | Температура > 100°C | Отправить: «ОПАСНОСТЬ! Температура X°C! Закрываю поддувало!» + отправить MQTT команду на закрытие сервопривода |
-- Данные с датчиков CREATE TABLE `sensor_data` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `sensor_id` VARCHAR(50), `temperature` FLOAT, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Лог уведомлений (чтобы не спамить) CREATE TABLE `notifications_log` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `type` VARCHAR(50), -- 'wood', 'alert', 'overheat_warning', 'overheat_emergency' `message` TEXT, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Опционально: хранение последнего состояния сервопривода CREATE TABLE `system_state` ( `key` VARCHAR(50) PRIMARY KEY, `value` TEXT );
connect_error) { die("Ошибка подключения к БД: " . $mysqli->connect_error); } // 1. Получить последнюю температуру $stmt = $mysqli->prepare(" SELECT temperature FROM sensor_data WHERE sensor_id = ? ORDER BY created_at DESC LIMIT 1 "); $stmt->bind_param("s", $sensor_name); $stmt->execute(); $result = $stmt->get_result(); $current_temp = $result->fetch_assoc()['temperature'] ?? null; if ($current_temp === null) { die("Нет данных от датчика.\n"); } // 2. Получить максимальную температуру за последние 12 часов $stmt = $mysqli->prepare(" SELECT MAX(temperature) as max_temp FROM sensor_data WHERE sensor_id = ? AND created_at > NOW() - INTERVAL 12 HOUR "); $stmt->bind_param("s", $sensor_name); $stmt->execute(); $result = $stmt->get_result(); $max_temp = $result->fetch_assoc()['max_temp'] ?? 20; // 3. Если максимум слишком низкий — выходим (ещё не топили) if ($max_temp < 40) { echo "Максимум слишком низкий ($max_temp°C) — игнорируем.\n"; exit; } // 4. Рассчитываем порог "пора дров" $threshold_wood = $max_temp * ($min_percent_threshold / 100); // 5. Проверяем состояние — в порядке приоритета (сначала авария!) // СЛУЧАЙ 1: Аварийный перегрев (>100°C) if ($current_temp > $overheat_emergency) { if (!notificationSentRecently($mysqli, 'overheat_emergency', 0.5)) { // каждые 30 минут $message = "🔴 ОПАСНОСТЬ! Температура: " . round($current_temp, 1) . "°C! Закрываю поддувало!"; sendTelegram($telegram_bot_token, $telegram_chat_id, $message); logNotification($mysqli, 'overheat_emergency', $message); sendMQTTCommand($mqtt_host, $mqtt_port, $servo_device_topic, '{"state": "CLOSE"}'); echo "АВАРИЯ: $message + команда CLOSE отправлена\n"; } else { echo "Авария уже отправлялась — пропускаем.\n"; } } // СЛУЧАЙ 2: Предупреждение о перегреве (>90°C) else if ($current_temp > $overheat_warning) { if (!notificationSentRecently($mysqli, 'overheat_warning', 1)) { $message = "⚠️ Внимание! Температура высокая: " . round($current_temp, 1) . "°C. Контролируйте горение."; sendTelegram($telegram_bot_token, $telegram_chat_id, $message); logNotification($mysqli, 'overheat_warning', $message); echo "Предупреждение: $message\n"; } else { echo "Предупреждение уже отправлялось — пропускаем.\n"; } } // СЛУЧАЙ 3: Пора подкинуть дров else if ($current_temp < $threshold_wood && $current_temp > $threshold_cold) { if (!notificationSentRecently($mysqli, 'wood', $cooldown_hours)) { $message = "🪵 Температура упала до " . round($current_temp, 1) . "°C (порог: " . round($threshold_wood, 1) . "°C). Пора подкинуть дров!"; sendTelegram($telegram_bot_token, $telegram_chat_id, $message); logNotification($mysqli, 'wood', $message); echo "Отправлено: $message\n"; } else { echo "Уведомление 'дров' уже отправлялось — пропускаем.\n"; } } // СЛУЧАЙ 4: Тревога — печка резко потухла else if ($current_temp <= $threshold_cold && $max_temp >= $min_max_for_alert) { if (!notificationSentRecently($mysqli, 'alert', 1)) { $message = "🚨 ТРЕВОГА: печка резко потухла! Температура: " . round($current_temp, 1) . "°C. Максимум был: " . round($max_temp, 1) . "°C. Проверьте дымоход и тягу!"; sendTelegram($telegram_bot_token, $telegram_chat_id, $message); logNotification($mysqli, 'alert', $message); echo "Отправлено: $message\n"; } else { echo "Тревога уже отправлялась — пропускаем.\n"; } } // СЛУЧАЙ 5: Всё в норме else { echo "Температура в норме: " . round($current_temp, 1) . "°C\n"; } $mysqli->close(); // ============ ФУНКЦИИ ============ function notificationSentRecently($mysqli, $type, $hours) { $stmt = $mysqli->prepare(" SELECT COUNT(*) as cnt FROM notifications_log WHERE type = ? AND created_at > NOW() - INTERVAL ? HOUR "); $stmt->bind_param("si", $type, $hours); $stmt->execute(); return $stmt->get_result()->fetch_assoc()['cnt'] > 0; } function sendTelegram($token, $chat_id, $message) { $url = "https://api.telegram.org/bot$token/sendMessage?chat_id=$chat_id&text=" . urlencode($message); file_get_contents($url); } function logNotification($mysqli, $type, $message) { $stmt = $mysqli->prepare("INSERT INTO notifications_log (type, message) VALUES (?, ?)"); $stmt->bind_param("ss", $type, $message); $stmt->execute(); } function sendMQTTCommand($host, $port, $topic, $payload) { // Простая отправка через shell + mosquitto_pub (установи mosquitto-clients) $cmd = "mosquitto_pub -h $host -p $port -t '$topic' -m '$payload' 2>&1"; exec($cmd, $output, $return_var); if ($return_var !== 0) { error_log("MQTT Error: " . implode("\n", $output)); } } ?>
*/2 * * * * /usr/bin/php /var/www/burzhuika/burzhuika_check.php >> /var/log/burzhuika.log 2>&1
prepare("SELECT temperature FROM sensor_data WHERE sensor_id = ? ORDER BY created_at DESC LIMIT 1"); $stmt->bind_param("s", $sensor_name); $stmt->execute(); $current_temp = $stmt->get_result()->fetch_assoc()['temperature'] ?? 'Нет данных'; $stmt = $mysqli->prepare("SELECT MAX(temperature) as max_temp FROM sensor_data WHERE sensor_id = ? AND created_at > NOW() - INTERVAL 12 HOUR"); $stmt->bind_param("s", $sensor_name); $stmt->execute(); $max_temp = $stmt->get_result()->fetch_assoc()['max_temp'] ?? 20; ?>Статус буржуйки 🔥 Умная буржуйка 2.0 — статус
Текущая температура: °C
Максимум за 12 ч: °C
Порог "дров": °C
Состояние: 100) echo "🔴 АВАРИЯ: перегрев!"; else if ($current_temp > 90) echo "⚠️ Предупреждение: перегрев"; else if ($current_temp >= 70) echo "🔥 Активный нагрев"; else if ($current_temp < ($max_temp * 0.5) && $current_temp > 25) echo "🪵 Пора подкинуть дров"; else if ($current_temp <= 25 && $max_temp >= 60) echo "🚨 ТРЕВОГА: проверьте дымоход!"; else echo "💤 Всё в норме"; ?>
Ты сделал не просто «умную печку» — ты создал гибридную систему отопления, безопасности и автоматики, которая:
Это не «умный дом». Это — умный выживальщик с функцией автопилота.
🪵 Подкинь дров. 🚨 Проверь дымоход. 🔥 Закрой поддувало. 💡 Ты — инженер будущего.
Внимание: Cтатьи здесь сгенерированны через нейросеть, не правил ошибки, да и не до этого пока. Блог только запустил. Просто чтобы вы знали и не запускали ядерный реактор по моим статьям ))
НО!
Каждый кейс я делал минимум один раз. Сервера стоят, клиенты довольны, дата-центры не горят.
Если у вас есть вопросы, или Нашли неточность? пишите в коментах —
вместе поправим и сделаем статью более качественной. Я лично объясню нюансы из практики.
Комментарии
Пока нет комментариев. Будьте первым!