// Подключение необходимых библиотек
#include <WiFi.h> // Для работы с WiFi
#include <WiFiClientSecure.h> // Для безопасного HTTPS соединения
#include <UniversalTelegramBot.h> // Для работы с Telegram Bot API
#include "DHTesp.h" // Для работы с датчиком DHT (температура/влажность)
#include <ESP32Servo.h> // Для управления сервоприводом
#include <Keypad.h> // Для работы с матричной клавиатурой
// Настройки WiFi и Telegram
#define WIFI_SSID "Wokwi-GUEST" // Имя WiFi сети (в симуляторе Wokwi)
#define WIFI_PASSWORD "" // Пароль WiFi (пустой для гостевой сети)
#define BOT_TOKEN "7978061436:AAHKc3d100Lg4JBkv4QjUOQZjXMMibXebAs" // Токен вашего Telegram бота
#define BOT_MTBS 1000 // Интервал проверки новых сообщений (в миллисекундах)
// Определение пинов для подключения датчиков и устройств
#define PIR 13 // Пин датчика движения (PIR)
#define LDR_PIN 34 // Пин датчика освещенности (LDR)
#define chsen4 35 // Пин датчика газа (CH4/MQ-4)
#define ECHO_PIN 14 // Пин Echo ультразвукового датчика расстояния
#define TRIG_PIN 12 // Пин Trig ультразвукового датчика расстояния
#define SPEAKER_PIN 23 // Пин пьезопищалки (динамика)
#define DHT_PIN 22 // Пин датчика температуры и влажности DHT22
// Пины RGB светодиода
#define pinG 26 // Зеленый канал RGB светодиода
#define pinR 27 // Красный канал RGB светодиода
#define pinB 25 // Синий канал RGB светодиода
const int servoPin = 32; // Пин сервопривода (для управления окном)
// Настройка матричной клавиатуры 4x4
const byte ROWS = 4; // Количество строк клавиатуры
const byte COLS = 4; // Количество столбцов клавиатуры
// Расположение клавиш на клавиатуре
char keys[ROWS][COLS] = {
{'1','2','3','H'}, // Первый ряд: 1, 2, 3, H
{'4','5','6','T'}, // Второй ряд: 4, 5, 6, T
{'7','8','9','O'}, // Третий ряд: 7, 8, 9, O
{'Del','0','=','!'} // Четвертый ряд: Del, 0, =, !
};
// Пины, к которым подключены строки клавиатуры
byte rowPins[ROWS] = {19, 21, 17, 16};
// Пины, к которым подключены столбцы клавиатуры
byte colPins[COLS] = {15, 2, 0, 4};
String passwordlog = "HTO!"; // Правильный пароль для системы
String password; // Переменная для хранения вводимого пароля
// Флаги состояния системы
bool alarmActive = true; // Активна ли сигнализация
bool distanceTriggered = false; // Сработал ли ультразвуковой датчик
bool pirTriggered = false; // Сработал ли PIR датчик
bool flagPIR = false; // Флаг движения (для избежания повторных срабатываний)
bool CH4 = false; // Обнаружен ли газ
bool light; // Уровень освещенности (true - темно, false - светло)
bool last_CH4_state = false; // Предыдущее состояние датчика газа
bool servoST; // Состояние сервопривода (окна)
bool lightST; // Состояние светодиода
bool lastLightState = false; // Предыдущее состояние освещенности
bool manualMode = false; // Режим работы (ручной/автоматический)
bool buzzerState = false; // Состояние пищалки
bool Serialpasswordflag = false; // Флаг ввода пароля через Serial
bool passwordflagtrue = false; // Флаг правильного пароля
bool passwordflagfalse = false; // Флаг неправильного пароля
bool timerActive = false; // Активен ли таймер
bool gas_alert_sent = false; // Отправлено ли оповещение о газе
// Переменные для хранения последнего установленного цвета светодиода
int lastRed = HIGH; // Последнее состояние красного канала
int lastGreen = HIGH; // Последнее состояние зеленого канала
int lastBlue = LOW; // Последнее состояние синего канала
// Переменные для хранения данных с датчиков
int val = 0; // Значение с PIR датчика
int distance; // Расстояние с ультразвукового датчика
int t, h; // Температура и влажность
// Таймеры и временные переменные
unsigned long passwordTimerStart = 0; // Время начала ввода пароля
unsigned long bot_lasttime; // Время последней проверки Telegram
unsigned long last_gas_alert = 0; // Время последнего оповещения о газе
// Инициализация компонентов системы
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); // Объект клавиатуры
Servo servo; // Объект сервопривода
DHTesp dhtSensor; // Объект датчика DHT
WiFiClientSecure secured_client; // Безопасный клиент для WiFi
UniversalTelegramBot bot(BOT_TOKEN, secured_client); // Объект Telegram бота
// Клавиатуры для интерфейса Telegram бота
String keyboardMain = "[[\"Доклад\", \"Периферия\"]]"; // Главное меню
String keyboardPeripheryAuto = "[[\"Смена режима\", \"Цвет света\"], [\"Назад\"]]"; // Меню периферии в авторежиме
String keyboardPeripheryManual = "[[\"Смена режима\"],[\"Окно\", \"Цвет света\"], [\"Свет ВЫКЛ\", \"Свет ВКЛ\"], [\"Пищалка ВЫКЛ\", \"Пищалка ВКЛ\"], [\"Сигнализация ВЫКЛ\", \"Сигнализация ВКЛ\"], [\"Назад\"]]"; // Меню периферии в ручном режиме
String keyboardColors = "[[\"Красный\", \"Зеленый\", \"Синий\"], [\"Желтый\", \"Фиолетовый\", \"Белый\"], [\"Периферия\"]]"; // Меню выбора цвета
String keyboardWindow = "[[\"Открыть окно\", \"Закрыть окно\"], [\"Периферия\"]]"; // Меню управления окном
String chat_id = ""; // ID чата Telegram для отправки сообщений
// Функция установки цвета RGB светодиода
void setLEDColor(bool red, bool green, bool blue) {
digitalWrite(pinR, red); // Установка красного канала
digitalWrite(pinG, green); // Установка зеленого канала
digitalWrite(pinB, blue); // Установка синего канала
// Сохраняем последний установленный цвет
lastRed = red; // Сохраняем состояние красного
lastGreen = green; // Сохраняем состояние зеленого
lastBlue = blue; // Сохраняем состояние синего
}
// Функция применения сохраненного цвета светодиода
void applySavedColor() {
digitalWrite(pinR, lastRed); // Восстанавливаем красный канал
digitalWrite(pinG, lastGreen); // Восстанавливаем зеленый канал
digitalWrite(pinB, lastBlue); // Восстанавливаем синий канал
}
// Функция анализа погодных условий на основе температуры и влажности
String getWeatherDescription(int temperature, int humidity) {
// Проверка комфортных условий
if (temperature >= 15 && temperature <= 25 && humidity >= 40 && humidity <= 70) {
return "🌤Температура и влажность в комфортном диапазоне. Идеальный день для прогулок.🌤";
}
// Низкая температура и низкая влажность
else if (temperature < 15 && humidity < 40) {
return "❄️Низкая температура сочетается с низкой влажностью. Оденьтесь теплее, пейте воду для увлажнения изнутри.❄️";
}
// Высокая температура и низкая влажность
else if (temperature > 25 && humidity < 40) {
return "🔥Высокая температура и сухой воздух. Высок риск перегрева. Пейте много воды, носите головной убор.🔥";
}
// Низкая температура и высокая влажность
else if (temperature < 15 && humidity > 70) {
return "💨Влажно и прохладно. Одевайтесь теплее, отдавайте предпочтение непромокаемой и ветрозащитной одежде.💨";
}
// Высокая температура и высокая влажность
else if (temperature > 25 && humidity > 70) {
return "💦Высокая температура и высокая влажность. Нагрузка на организм максимальна. Ограничьте активность, пейте больше воды.💦";
}
// Комфортная влажность, но экстремальная температура
else if (humidity >= 40 && humidity <= 70 && (temperature < 10 || temperature > 30)) {
return "⚠️Влажность комфортная, но температура экстремально низкая/высокая. Главный риск — сильный мороз/палящее солнце. Одевайтесь по погоде крайне тщательно.⚠️";
}
// Умеренные условия
else {
return "📊Умеренные условия. Температура и влажность в приемлемых пределах.📊";
}
}
// Функция измерения расстояния ультразвуковым датчиком
int readDistanceCM() {
digitalWrite(TRIG_PIN, LOW); // Устанавливаем Trig в LOW
delayMicroseconds(2); // Ждем 2 микросекунды
digitalWrite(TRIG_PIN, HIGH); // Отправляем импульс - устанавливаем Trig в HIGH
delayMicroseconds(10); // Ждем 10 микросекунд
digitalWrite(TRIG_PIN, LOW); // Возвращаем Trig в LOW
int duration = pulseIn(ECHO_PIN, HIGH); // Измеряем длительность импульса на Echo пине
return duration * 0.034 / 2; // Пересчитываем в сантиметры (скорость звука 340 м/с)
}
// Функция получения клавиатуры для меню периферии в зависимости от режима
String getPeripheryKeyboard() {
if (manualMode) {
return keyboardPeripheryManual; // Возвращаем полное меню для ручного режима
} else {
return keyboardPeripheryAuto; // Возвращаем сокращенное меню для авторежима
}
}
// Функция обработки новых сообщений от Telegram бота
void handleNewMessages(int numNewMessages) {
// Обрабатываем все новые сообщения
for (int i = 0; i < numNewMessages; i++) {
chat_id = bot.messages[i].chat_id; // Сохраняем ID чата
String text = bot.messages[i].text; // Текст сообщения
String nn = "\n"; // Переменная для переноса строки
String from_name = bot.messages[i].from_name; // Имя отправителя
if (from_name == "") from_name = "Guest"; // Если имя пустое, используем "Guest"
// Обработка команды "Доклад" - отправка состояния всех датчиков
if(text == "Доклад"){
String weatherInfo = getWeatherDescription(t, h); // Получаем анализ погоды
String dokl = "🗂Параметры🗂:" + nn;
dokl += "🌡Температура🌡: " + String(t) + "℃" + nn;
dokl += "💧Влажность💧: " + String(h) + "%" + nn;
dokl += "📡Ультразвук📡: " + String(distance) + " см" + nn;
dokl += "☁️Датчик газа☁️: " + String(CH4 ? "🔴Внимание газ🔴" : "🟢Чисто🟢") + nn;
dokl += "💡Датчик света💡: " + String(light ? "🌚Темно🌚" : "☀️Светло☀️") + nn;
dokl += "🏃➡️PIR датчик🏃➡️: " + String(flagPIR ? "🔴Движение🔴" : "🟢Чисто🟢") + nn;
dokl += nn;
dokl += "📡Периферия📡:" + nn;
dokl += "🚨Сигнализация🚨: " + String(alarmActive ? "🔴АКТИВНА🔴" : "🟢ВЫКЛ🟢") + nn;
dokl += "🪟Серво (окно)🪟: " + String(servoST ? "🟢Открыто🟢" : "🔴Закрыто🔴") + nn;
dokl += "💡Светодиод💡: " + String(lightST ? "🟢Включен🟢" : "🔴Выключен🔴") + nn;
dokl += "🔊Пищалка🔊: " + String(buzzerState ? "🟢Включена🟢" : "🔴Выключена🔴") + nn;
dokl += "👨💼Режим👨💼: " + String(manualMode ? "🟢Ручной🟢" : "🔴Авто🔴") + nn;
dokl += nn;
dokl += "📈Анализ погоды📈:" + nn;
dokl += weatherInfo; // Добавляем анализ погоды
// Отправляем сообщение с клавиатурой
bot.sendMessageWithReplyKeyboard(chat_id, dokl, "", keyboardMain, true);
}
// Обработка команды "Периферия" - управление устройствами
else if(text == "Периферия"){
String peri = "🛠Управление периферией🛠:" + nn;
peri += "💡Свет💡: " + String(lightST ? "🟢ВКЛ🟢" : "🔴ВЫКЛ🔴") + nn;
peri += "🪟Окно🪟: " + String(servoST ? "🟢Открыто🟢" : "🔴Закрыто🔴") + nn;
peri += "🔊Пищалка🔊: " + String(buzzerState ? "🟢ВКЛ🟢" : "🔴ВЫКЛ🔴") + nn;
peri += "🚨Сигнализация🚨: " + String(alarmActive ? "🟢ВКЛ🟢" : "🔴ВЫКЛ🔴") + nn;
peri += "👨💼Режим👨💼: " + String(manualMode ? "🟢Ручной🟢" : "🔴Авто🔴") + nn;
// Отправляем сообщение с соответствующей клавиатурой
bot.sendMessageWithReplyKeyboard(chat_id, peri, "", getPeripheryKeyboard(), true);
}
// Обработка команды "Смена режима" - переключение между ручным и авторежимом
else if(text == "Смена режима"){
manualMode = !manualMode; // Инвертируем режим работы
String peri = "🛠Периферия🛠:" + nn;
peri += "💡Свет💡: " + String(lightST ? "🟢ВКЛ🟢" : "🔴ВЫКЛ🔴") + nn;
peri += "🪟Окно🪟: " + String(servoST ? "🟢Открыто🟢" : "🔴Закрыто🔴") + nn;
peri += "🔊Пищалка🔊: " + String(buzzerState ? "🟢ВКЛ🟢" : "🔴ВЫКЛ🔴") + nn;
peri += "🚨Сигнализация🚨: " + String(alarmActive ? "🟢ВКЛ🟢" : "🔴ВЫКЛ🔴") + nn;
peri += "👨💼Режим👨💼: " + String(manualMode ? "🟢Ручной🟢" : "🔴Авто🔴") + nn;
// Отправляем обновленное состояние с новой клавиатурой
bot.sendMessageWithReplyKeyboard(chat_id, peri, "", getPeripheryKeyboard(), true);
}
// Включение света
else if(text == "Свет ВКЛ" && manualMode){
lightST = true; // Устанавливаем флаг включенного света
applySavedColor(); // Включаем свет с сохраненным цветом
bot.sendMessageWithReplyKeyboard(chat_id, "💡Свет ВКЛЮЧЕН💡", "", getPeripheryKeyboard(), true);
}
// Выключение света
else if(text == "Свет ВЫКЛ" && manualMode){
lightST = false; // Устанавливаем флаг выключенного света
// Выключаем все каналы RGB светодиода
digitalWrite(pinR, LOW);
digitalWrite(pinG, LOW);
digitalWrite(pinB, LOW);
bot.sendMessageWithReplyKeyboard(chat_id, "💡Свет ВЫКЛЮЧЕН💡", "", getPeripheryKeyboard(), true);
}
// Выбор цвета светодиода
else if(text == "Цвет света"){
bot.sendMessageWithReplyKeyboard(chat_id, "🎨Выберите цвет светодиода🎨:", "", keyboardColors, true);
}
// Управление окном
else if(text == "Окно" && manualMode){
bot.sendMessageWithReplyKeyboard(chat_id, "🪟Управление окном🪟:", "", keyboardWindow, true);
}
// Открытие окна
else if(text == "Открыть окно" && manualMode){
servo.write(180); // Поворачиваем серво в положение 180° (открыто)
servoST = true; // Устанавливаем флаг открытого окна
bot.sendMessageWithReplyKeyboard(chat_id, "🟢Окно ОТКРЫТО🟢", "", keyboardWindow, true);
}
// Закрытие окна
else if(text == "Закрыть окно" && manualMode){
servo.write(0); // Поворачиваем серво в положение 0° (закрыто)
servoST = false; // Устанавливаем флаг закрытого окна
bot.sendMessageWithReplyKeyboard(chat_id, "🔴Окно ЗАКРЫТО🔴", "", keyboardWindow, true);
}
// Включение пищалки
else if(text == "Пищалка ВКЛ" && manualMode){
buzzerState = true; // Устанавливаем флаг включенной пищалки
tone(SPEAKER_PIN, 1000); // Включаем звук частотой 1000 Гц
servo.attach(servoPin, 500, 2400); // Прикрепляем серво (если было откреплено)
bot.sendMessageWithReplyKeyboard(chat_id, "🔊Пищалка ВКЛЮЧЕНА🔊", "", getPeripheryKeyboard(), true);
}
// Выключение пищалки
else if(text == "Пищалка ВЫКЛ" && manualMode){
buzzerState = false; // Устанавливаем флаг выключенной пищалки
noTone(SPEAKER_PIN); // Выключаем звук
servo.attach(servoPin, 500, 2400); // Прикрепляем серво
bot.sendMessageWithReplyKeyboard(chat_id, "🔊Пищалка ВЫКЛЮЧЕНА🔊", "", getPeripheryKeyboard(), true);
}
// Включение сигнализации
else if(text == "Сигнализация ВКЛ" && manualMode){
alarmActive = true; // Активируем сигнализацию
bot.sendMessageWithReplyKeyboard(chat_id, "🚨Сигнализация ВКЛЮЧЕНА🚨", "", getPeripheryKeyboard(), true);
}
// Выключение сигнализации
else if(text == "Сигнализация ВЫКЛ" && manualMode){
alarmActive = false; // Деактивируем сигнализацию
bot.sendMessageWithReplyKeyboard(chat_id, "🚨Сигнализация ВЫКЛЮЧЕНА🚨", "", getPeripheryKeyboard(), true);
}
// Установка красного цвета светодиода
else if(text == "Красный"){
setLEDColor(HIGH, LOW, LOW); // Включаем только красный канал
lightST = true; // Устанавливаем флаг включенного света
bot.sendMessageWithReplyKeyboard(chat_id, "🔴Цвет изменен на КРАСНЫЙ🔴", "", keyboardColors, true);
}
// Установка зеленого цвета светодиода
else if(text == "Зеленый"){
setLEDColor(LOW, HIGH, LOW); // Включаем только зеленый канал
lightST = true; // Устанавливаем флаг включенного света
bot.sendMessageWithReplyKeyboard(chat_id, "🟢Цвет изменен на ЗЕЛЕНЫЙ🟢", "", keyboardColors, true);
}
// Установка синего цвета светодиода
else if(text == "Синий"){
setLEDColor(LOW, LOW, HIGH); // Включаем только синий канал
lightST = true; // Устанавливаем флаг включенного света
bot.sendMessageWithReplyKeyboard(chat_id, "🔵Цвет изменен на СИНИЙ🔵", "", keyboardColors, true);
}
// Установка желтого цвета светодиода
else if(text == "Желтый"){
setLEDColor(HIGH, HIGH, LOW); // Включаем красный и зеленый каналы
lightST = true; // Устанавливаем флаг включенного света
bot.sendMessageWithReplyKeyboard(chat_id, "🟡Цвет изменен на ЖЕЛТЫЙ🟡", "", keyboardColors, true);
}
// Установка фиолетового цвета светодиода
else if(text == "Фиолетовый"){
setLEDColor(HIGH, LOW, HIGH); // Включаем красный и синий каналы
lightST = true; // Устанавливаем флаг включенного света
bot.sendMessageWithReplyKeyboard(chat_id, "🟣Цвет изменен на ФИОЛЕТОВЫЙ🟣", "", keyboardColors, true);
}
// Установка белого цвета светодиода
else if(text == "Белый"){
setLEDColor(HIGH, HIGH, HIGH); // Включаем все каналы
lightST = true; // Устанавливаем флаг включенного света
bot.sendMessageWithReplyKeyboard(chat_id, "⚪Цвет изменен на БЕЛЫЙ⚪", "", keyboardColors, true);
}
// Возврат в главное меню
else if(text == "Назад"){
bot.sendMessageWithReplyKeyboard(chat_id, "📋Главное меню📋:", "", keyboardMain, true);
}
// Обработка команды /start - приветственное сообщение
else if (text == "/start") {
String welcome = "Вас приветствует бот Умного дома команды *Кибер пельмени*, " + from_name + ".\n";
welcome += "Используйте кнопки для управления:";
bot.sendMessageWithReplyKeyboard(chat_id, welcome, "Markdown", keyboardMain, true);
}
// Блокировка команд в авто режиме
else if ((text == "Свет ВКЛ" || text == "Свет ВЫКЛ" || text == "Окно" ||
text == "Открыть окно" || text == "Закрыть окно" ||
text == "Пищалка ВКЛ" || text == "Пищалка ВЫКЛ" ||
text == "Сигнализация ВКЛ" || text == "Сигнализация ВЫКЛ") && !manualMode) {
bot.sendMessage(chat_id, "❌ Эта функция недоступна в авто режиме. Переключитесь в hexyjq режим.", "");
}
}
}
// Функция setup выполняется один раз при запуске устройства
void setup() {
Serial.begin(115200); // Инициализация последовательного порта
Serial.println();
dhtSensor.setup(DHT_PIN, DHTesp::DHT22); // Инициализация датчика DHT22
servo.attach(servoPin, 500, 2400); // Прикрепление сервопривода с указанием диапазона импульсов
servo.write(0); // Установка серво в начальное положение (закрыто)
// Настройка пинов ввода/вывода
pinMode(chsen4, INPUT); // Датчик газа - вход
pinMode(PIR, INPUT); // Датчик движения - вход
pinMode(LDR_PIN, INPUT); // Датчик освещенности - вход
pinMode(pinR, OUTPUT); // Красный канал светодиода - выход
pinMode(pinG, OUTPUT); // Зеленый канал светодиода - выход
pinMode(pinB, OUTPUT); // Синий канал светодиода - выход
pinMode(SPEAKER_PIN, OUTPUT); // Пищалка - выход
pinMode(TRIG_PIN, OUTPUT); // Trig ультразвукового датчика - выход
pinMode(ECHO_PIN, INPUT); // Echo ультразвукового датчика - вход
// Подключение к WiFi сети
Serial.print("Connecting to Wifi SSID ");
Serial.print(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD); // Начало подключения к WiFi
secured_client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Установка корневого сертификата для HTTPS
// Ожидание подключения к WiFi
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500); // Пауза 500 мс между попытками
}
Serial.print("\nWiFi connected. IP address: ");
Serial.println(WiFi.localIP()); // Вывод полученного IP адреса
// Настройка времени через NTP сервер
configTime(0, 0, "pool.ntp.org"); // Настройка временной зоны и NTP сервера
time_t now = time(nullptr); // Получение текущего времени
// Ожидание успешной синхронизации времени
while (now < 24 * 3600) {
delay(100);
now = time(nullptr);
}
// Вывод начальных сообщений
Serial.println("🔴Сигнализация АКТИВИРОВАНА. Для деактивации используйте ультразвуковый датчик");
Serial.println("Пароль для активации/деактивации: " + passwordlog);
}
// Функция активации сигнализации через ввод пароля
void fastPasswordInputActivation() {
Serial.println("\n🔐 АКТИВАЦИЯ СИГНАЛИЗАЦИИ - ВВЕДИТЕ ПАРОЛЬ 🔐");
Serial.print("Введите пароль: ");
password = ""; // Сброс переменной пароля
unsigned long passwordStartTime = millis(); // Запись времени начала ввода
bool passwordEntered = false; // Флаг завершения ввода пароля
// Цикл ввода пароля (10 секунд на ввод)
while (!passwordEntered && (millis() - passwordStartTime < 10000)) {
char key = keypad.getKey(); // Получение нажатой клавиши
if (key != NO_KEY) {
// Обработка клавиши очистки (*)
if (key == '*') {
password = ""; // Сброс введенного пароля
Serial.println();
Serial.print("Введите пароль заново: ");
}
// Обработка клавиши подтверждения (=)
else if (key == '=') {
passwordEntered = true; // Установка флага завершения ввода
Serial.println();
Serial.println("Проверка пароля...");
// Проверка правильности пароля
if (password == passwordlog) {
Serial.println("✅ ПАРОЛЬ ВЕРНЫЙ! Сигнализация АКТИВИРОВАНА.");
alarmActive = true; // Активация сигнализации
distanceTriggered = false; // Сброс флага срабатывания расстояния
Serial.println("Ожидание срабатывания ультразвукового датчика...");
// Отправка уведомления в Telegram
bot.sendMessage(chat_id, "📡ПАРОЛЬ ВЕРНЫЙ! Сигнализация АКТИВИРОВАНА.📡", "");
} else {
Serial.println("❌ НЕВЕРНЫЙ ПАРОЛЬ! Сигнализация остаётся ВЫКЛЮЧЕННОЙ.");
}
}
// Добавление символа к паролю
else {
password += key; // Добавление символа к строке пароля
Serial.print("*"); // Вывод звездочки вместо символа
}
}
delay(50); // Небольшая пауза для стабильности
}
// Обработка ситуации, когда время ввода истекло
if (!passwordEntered) {
Serial.println();
Serial.println("⏰ ВРЕМЯ ВЫШЛО! Сигнализация остаётся ВЫКЛЮЧЕННОЙ.");
}
Serial.println("Режим активации завершен");
pirTriggered = false; // Сброс флага PIR срабатывания
}
// Функция деактивации сигнализации через ввод пароля
void fastPasswordInputDeactivation() {
Serial.println("\n🚨 ОБНАРУЖЕНО ПРИБЛИЖЕНИЕ! ВВЕДИТЕ ПАРОЛЬ ДЕАКТИВАЦИИ 🚨");
Serial.print("Введите пароль: ");
password = ""; // Сброс переменной пароля
unsigned long passwordStartTime = millis(); // Запись времени начала ввода
bool passwordEntered = false; // Флаг завершения ввода пароля
// Цикл ввода пароля (10 секунд на ввод)
while (!passwordEntered && (millis() - passwordStartTime < 10000)) {
char key = keypad.getKey(); // Получение нажатой клавиши
if (key != NO_KEY) {
// Обработка клавиши очистки (*)
if (key == '*') {
password = ""; // Сброс введенного пароля
Serial.println();
Serial.print("Введите пароль заново: ");
}
// Обработка клавиши подтверждения (=)
else if (key == '=') {
passwordEntered = true; // Установка флага завершения ввода
Serial.println();
Serial.println("Проверка пароля...");
// Проверка правильности пароля
if (password == passwordlog) {
Serial.println("✅ ПАРОЛЬ ВЕРНЫЙ! Сигнализация ОТКЛЮЧЕНА.");
alarmActive = false; // Деактивация сигнализации
distanceTriggered = false; // Сброс флага срабатывания расстояния
noTone(SPEAKER_PIN); // Выключение пищалки
// Отправка уведомления в Telegram
bot.sendMessage(chat_id, "📡ПАРОЛЬ ВЕРНЫЙ! Сигнализация ОТКЛЮЧЕНА.📡", "");
Serial.println("⚠️ Сигнализация ВЫКЛЮЧЕНА. Для активации нажмите =");
} else {
Serial.println("❌ НЕВЕРНЫЙ ПАРОЛЬ! Тревога!");
tone(SPEAKER_PIN, 262, 3000); // Включение тревожного сигнала (3 секунды)
delay(3000);
noTone(SPEAKER_PIN); // Выключение пищалки
servo.attach(servoPin, 500, 2400); // Прикрепление серво
// Отправка тревожного сообщения в Telegram
bot.sendMessage(chat_id, "📡ТРЕВОГА! Введён неправильный пароль!📡", "");
Serial.println("Сигнализация остается АКТИВНОЙ");
}
}
// Добавление символа к паролю
else {
password += key; // Добавление символа к строке пароля
Serial.print("*"); // Вывод звездочки вместо символа
}
}
delay(50); // Небольшая пауза для стабильности
}
// Обработка ситуации, когда время ввода истекло
if (!passwordEntered) {
Serial.println();
Serial.println("⏰ ВРЕМЯ ВЫШЛО! ТРЕВОГА!");
tone(SPEAKER_PIN, 262, 5000); // Включение тревожного сигнала (5 секунд)
delay(5000);
noTone(SPEAKER_PIN); // Выключение пищалки
servo.attach(servoPin, 500, 2400); // Прикрепление серво
// Отправка тревожного сообщения в Telegram
bot.sendMessage(chat_id, "📡ТРЕВОГА! Введён неправильный пароль!📡", "");
Serial.println("Сигнализация остается АКТИВНОЙ");
}
distanceTriggered = false; // Сброс флага срабатывания расстояния
Serial.println("Режим деактивации завершен");
}
// Главный цикл программы, выполняется постоянно
void loop() {
// Обработка событий сигнализации
if (distanceTriggered && alarmActive) {
fastPasswordInputDeactivation(); // Запуск деактивации при срабатывании расстояния
}
else if (pirTriggered && !alarmActive) {
fastPasswordInputActivation(); // Запуск активации при срабатывании PIR
}
// Чтение данных с датчиков
t = dhtSensor.getTemperature(); // Получение температуры
h = dhtSensor.getHumidity(); // Получение влажности
CH4 = !digitalRead(chsen4); // Чтение датчика газа (инвертированное значение)
light = digitalRead(LDR_PIN); // Чтение датчика освещенности
distance = readDistanceCM(); // Измерение расстояния
// Автоматическое управление светом (только в авто режиме)
if (!manualMode) {
if (light) { // Если темно
if (!lightST) {
lightST = true; // Устанавливаем флаг включенного света
applySavedColor(); // Включаем свет с сохраненным цветом
// Отправка уведомления в Telegram
if (chat_id != "") {
bot.sendMessage(chat_id, "🟢Светодиод включен (стало темно)🟢", "");
}
Serial.println("Светодиод включен - стало темно");
}
} else { // Если светло
if (lightST) {
lightST = false; // Устанавливаем флаг выключенного света
// Выключаем все каналы светодиода
digitalWrite(pinR, LOW);
digitalWrite(pinG, LOW);
digitalWrite(pinB, LOW);
// Отправка уведомления в Telegram
if (chat_id != "") {
bot.sendMessage(chat_id, "🔴Светодиод выключен (стало светло)🔴", "");
}
Serial.println("Светодиод выключен - стало светло");
}
}
}
// Обработка утечки газа (только в авто режиме)
if (!manualMode) {
// Если газ обнаружен и предыдущее состояние было "нет газа"
if (CH4 && !last_CH4_state) {
servo.write(180); // Открываем окно
servoST = true; // Устанавливаем флаг открытого окна
Serial.println("ОБНАРУЖЕН ГАЗ! Окно открыто!");
// Отправка тревожного сообщения в Telegram
if (chat_id != "") {
bot.sendMessage(chat_id, "🚨🚨🚨ВНИМАНИЕ! Обнаружена утечка газа! Окно открыто🚨🚨🚨", "");
}
}
// Если газ устранен и предыдущее состояние было "газ обнаружен"
else if (!CH4 && last_CH4_state) {
servo.write(0); // Закрываем окно
servoST = false; // Устанавливаем флаг закрытого окна
Serial.println("Газ устранен, окно закрыто");
// Отправка сообщения о нормализации в Telegram
if (chat_id != "") {
bot.sendMessage(chat_id, "✅СИТУАЦИЯ НОРМАЛИЗОВАЛАСЬ! Утечка газа устранена! Окно закрыто✅", "");
}
}
}
last_CH4_state = CH4; // Сохраняем текущее состояние газа для следующего цикла
// Обработка датчика движения PIR
val = digitalRead(PIR); // Чтение значения с PIR датчика
// Если движение обнаружено и ранее не было обнаружено
if(val == 1 && !flagPIR){
Serial.println("PIR: Обнаружено движение! Отправка в Telegram...");
// Отправка уведомления в Telegram
if (chat_id != "") {
bot.sendMessage(chat_id, "📡Обнаружено движение!📡", "");
}
flagPIR = true; // Устанавливаем флаг обнаружения движения
}
// Если движение прекратилось и ранее было обнаружено
if(val == 0 && flagPIR){
flagPIR = false; // Сбрасываем флаг обнаружения движения
}
// Обнаружение приближения ультразвуковым датчиком
if(distance < 200 && distance > 2 && alarmActive && !distanceTriggered){
Serial.println("Ультразвук: Обнаружено приближение! Расстояние: " + String(distance) + " см");
distanceTriggered = true; // Устанавливаем флаг срабатывания расстояния
}
// Обработка сообщений Telegram бота
if (millis() - bot_lasttime > BOT_MTBS) {
int numNewMessages = bot.getUpdates(bot.last_message_received + 1); // Получение новых сообщений
if (numNewMessages) {
handleNewMessages(numNewMessages); // Обработка новых сообщений
}
bot_lasttime = millis(); // Обновление времени последней проверки
}
// Обработка ввода с клавиатуры
char key = keypad.getKey(); // Получение нажатой клавиши
// Если нажата '=' и сигнализация выключена и PIR не срабатывал
if(key == '=' && !alarmActive && !pirTriggered){
Serial.println("Запрос активации сигнализации...");
pirTriggered = true; // Устанавливаем флаг запроса активации
}
// Вывод статуса системы в Serial монитор
Serial.println("=== СТАТУС ===");
Serial.println("Сигнализация: " + String(alarmActive ? "🔴АКТИВНА🔴" : "🟢ВЫКЛ🟢"));
Serial.println("PIR: " + String(val ? "🔴ДВИЖЕНИЕ🔴" : "🟢НЕТ🟢"));
Serial.println("Газ: " + String(CH4 ? "🔴ОБНАРУЖЕН🔴" : "🟢НЕТ🟢"));
Serial.println("Расстояние: " + String(distance) + " см");
Serial.println("Режим: " + String(manualMode ? "🟢Ручной🟢" : "🔴Авто🔴"));
Serial.println("====================");
delay(100); // Пауза 100 мс перед следующим циклом
}Датчик расстояния
Клавиатура
Датчик освещённости
Сервопривод
Датчик газа
Датчик движения
Буззер
Светодиод
🚨🚨🚨ВНИМАНИЕ!🚨🚨🚨
Для работы оповещений вставьте chat id в 90 строку кода
или нажмите старт в ТГ боте чтобы chat id записался сам.
ТГ бот: @cyberpelmeny_bot
Пароль от дома: НТО!
Примечание:
Для ввода пароля при активации
сигнализации зажмите =
пока не напишеться в мониторе
порта о вводе пароля