← До всіх проєктів
Автоматизація Середній

Telegram-бот на ESP32: керування реле та сповіщення про рух

Керуємо світлом командами /on та /off з будь-якої точки світу й отримуємо повідомлення в Telegram, коли PIR-датчик помітив рух. Без білого IP та прокидання портів.

Складність
Середній
Час
1–2 h
Категорія
Автоматизація

Чому Telegram

Щоб керувати пристроєм з інтернету, зазвичай потрібні білий IP, прокидання портів чи хмарний сервіс. З Telegram усе простіше: ESP32 сам звертається до серверів Telegram і опитує нові повідомлення. Вхідних підключень немає — отже, працює за будь-яким роутером і навіть через мобільний інтернет.

Що вміє бот:

  • /on, /off — вмикає й вимикає реле;
  • /status — стан реле, рівень сигналу Wi-Fi та час роботи;
  • сам надсилає повідомлення, коли PIR-датчик фіксує рух (не частіше разу на хвилину).

Компоненти

  • ESP32 DevKit
  • Модуль реле (або світлодіод для тестів) — GPIO 26
  • PIR-датчик руху HC-SR501 або AM312 — GPIO 27
Модуль ESP32
Реле IN / VCC / GND GPIO 26 / 5V / GND
PIR OUT / VCC / GND GPIO 27 / 5V (HC-SR501) або 3V3 (AM312) / GND

Вихід HC-SR501 — 3.3 В навіть при живленні 5 В, тож його можна під'єднувати напряму.

Бібліотеки

  • UniversalTelegramBot (Brian Lough)
  • ArduinoJson (Benoît Blanchon) — залежність

Створюємо бота

  1. У Telegram напишіть @BotFather → /newbot → задайте назву. Отримаєте токен вигляду 123456789:AA....
  2. Напишіть @userinfobot — він повідомить ваш chat ID (число).
  3. Відкрийте свого нового бота й натисніть Start, інакше він не зможе вам писати.

Код

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

const char* WIFI_SSID = "YOUR_SSID";
const char* WIFI_PASS = "YOUR_PASSWORD";
#define BOT_TOKEN "123456789:AAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
const String OWNER_CHAT_ID = "123456789";   // ваш chat ID

const int RELAY_PIN = 26;
const int PIR_PIN = 27;
const unsigned long MOTION_COOLDOWN = 60000;  // 1 хв між сповіщеннями

WiFiClientSecure client;
UniversalTelegramBot bot(BOT_TOKEN, client);

unsigned long lastPoll = 0;
unsigned long lastMotionAlert = 0;

void handleMessages(int count) {
  for (int i = 0; i < count; i++) {
    const String chatId = bot.messages[i].chat_id;
    const String text = bot.messages[i].text;

    // Відповідаємо лише власнику — бота може знайти будь-хто
    if (chatId != OWNER_CHAT_ID) {
      bot.sendMessage(chatId, "Access denied", "");
      continue;
    }

    if (text == "/on") {
      digitalWrite(RELAY_PIN, HIGH);
      bot.sendMessage(chatId, "💡 Увімкнено", "");
    } else if (text == "/off") {
      digitalWrite(RELAY_PIN, LOW);
      bot.sendMessage(chatId, "🌑 Вимкнено", "");
    } else if (text == "/status") {
      String s = "Реле: " + String(digitalRead(RELAY_PIN) ? "ON" : "OFF");
      s += "\nWi-Fi: " + String(WiFi.RSSI()) + " dBm";
      s += "\nПрацює: " + String(millis() / 60000) + " хв";
      bot.sendMessage(chatId, s, "");
    } else {
      bot.sendMessage(chatId, "Команди: /on /off /status", "");
    }
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(PIR_PIN, INPUT);

  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  Serial.println(WiFi.localIP());

  client.setCACert(TELEGRAM_CERTIFICATE_ROOT);  // перевіряємо сертифікат api.telegram.org
  bot.sendMessage(OWNER_CHAT_ID, "🤖 ESP32 онлайн", "");
}

void loop() {
  // Опитуємо Telegram раз на секунду
  if (millis() - lastPoll > 1000) {
    lastPoll = millis();
    int n = bot.getUpdates(bot.last_message_received + 1);
    while (n) {
      handleMessages(n);
      n = bot.getUpdates(bot.last_message_received + 1);
    }
  }

  // Рух + пауза між сповіщеннями
  if (digitalRead(PIR_PIN) == HIGH && millis() - lastMotionAlert > MOTION_COOLDOWN) {
    lastMotionAlert = millis();
    bot.sendMessage(OWNER_CHAT_ID, "🚶 Виявлено рух!", "");
  }
}

Перевірка

  1. Після старту бот надішле вам «🤖 ESP32 онлайн».
  2. Напишіть /status, потім /on — реле клацне.
  3. Помахайте рукою перед PIR-датчиком — прийде сповіщення.

Корисно знати

  • Налаштуйте HC-SR501: лівий потенціометр — чутливість, правий — тривалість сигналу; перемичку поставте в режим H (повторне спрацювання).
  • Після ввімкнення PIR-датчику потрібно ~30–60 с на калібрування — у цей час можливі хибні спрацювання.
  • Додайте меню-кнопки через BotFather → /setcommands, щоб не набирати команди вручну.
  • Токен — це пароль. Не публікуйте скетч з ним на GitHub. Якщо токен витік — /revoke у BotFather.

Ідеї

  • Надсилати фото з ESP32-CAM при русі (bot.sendPhotoByBinary).
  • Щоденний звіт з температурою з проєкту «Міні-метеостанція».
  • Кілька користувачів — масив дозволених chat ID.