Telegram бот на ESP32 для удаленного мониторинга и управления насосной станцией

в 18:55, , рубрики: c++, diy или сделай сам, esp32, esp8266, telegram, telegrambot, Электроника для начинающих

Нужда родит идею, идея - действие!

Предисловие

История создания данного девайса следующая: есть очистная станция, в которой шкафы управления насосами и компрессорами на ПЛК Schneider Electric. При отключении городской электросети и переходе на дизель генератор и обратно оборудование уходит в ошибку, для квинтирования которой необходимо на месте нажать кнопки сброса аварии и запуска компрессоров. В случаи не работы компрессоров бактерии в емкостях умирают. И если рабочий день окончен некому произвести данную процедуру.

Готовые решения есть, но стоят они в десятки раз дороже данного решения.
Ни сказать чтобы компания не могла бы позволить себе купить готовые контроллеры с облачным управлением... Так как еще на своем опыте не почувствовал любовь инициативы к инициатору, решил сам сделать данный девайс.

Железо

В качестве основы был выбран ESP32 WROOM. К нему были взяты.

Для входных пинов - Модуль опторазвязки с индикаторными светодиодами 24в на 3,3в

Telegram бот на ESP32 для удаленного мониторинга и управления насосной станцией - 1

Для выходных пинов - модуль с реле 8ми канальный (сами реле на 5В)

Telegram бот на ESP32 для удаленного мониторинга и управления насосной станцией - 2

Для удобства плата ESP32 установлена на плате расширения

Telegram бот на ESP32 для удаленного мониторинга и управления насосной станцией - 3

Также для мониторинга наличия городской сети задействован эл.магнитный контактор (обычный на дин рейку)

Telegram бот на ESP32 для удаленного мониторинга и управления насосной станцией - 4

Схема подключения

8ми канальный модуль реле подключен параллельно к кнопкам управления на шкафах управления насосной (всего шкафов 3 штуки). Было задействовано 6 реле (2е штуки остались в резерве).

Модуль оптопар был подключен параллельно к индикаторным лампам на шкафу управления компрессорами, для мониторинга работы компрессоров.

Катушка реле на дин рейке (220В) подключен к шинам питающим АВР, на нем будет 220в только тогда когда есть питание от ТП городской сети.

Telegram бот на ESP32 для удаленного мониторинга и управления насосной станцией - 5

Создание бота в Телеграме

В сети полно более подробных инструкций, опишу все вкратце. Качаем и устанавливаем себе Телеграм на телефон или компьютер. Создаем аккаунт если его у вас еще нет. В поиске находим БОТА под ником BotFather.

Telegram бот на ESP32 для удаленного мониторинга и управления насосной станцией - 6

Начинаем с ним диалог сообщением: /start
Он ответит какие каманды может выполнять, нас интересует: /newbot вводим и следуем инструкциям по созданию бота.

Telegram бот на ESP32 для удаленного мониторинга и управления насосной станцией - 7

Если ваш бот успешно создан, вы получите сообщение со ссылкой для доступа к нему и токеном бота. Сохраните токен бота, он вам понадобится, чтобы обеспечить взаимодействие ESP32 с ботом.

Telegram бот на ESP32 для удаленного мониторинга и управления насосной станцией - 8

Далее я создал группу в телеграме т.к. ботом будут управлять помимо меня другие люди.
Создаем группу даем ей имя, добавляем туда созданного нами бота (в списке контактов у вас его не будет, нужно в графе поиска набрать его имя и добавить его) и других людей которые будут иметь доступ к нашему контроллеру.

Также нужно временно добавить бота который укажет нам id нашего чата, в случае группы id будет отрицательным числом.

Telegram бот на ESP32 для удаленного мониторинга и управления насосной станцией - 9

Программирование ESP32:

Для написания скетча была использована среда Arduino IDE 2.0

В качестве библиотеки для телеграм бота была выбрана библиотека fastbot

Сам код, с поясняющими комментариями:
#define WIFI_SSID "ImyaTochkiDostupa"                               //Имя сети WIFI
#define WIFI_PASS "Password"                                      	//Пароль сети WIFI
#define BOT_TOKEN "1234567890:ABCdEfghiJKlMnopQr1STUvWx23Y-4ZaBCD"  //Токен бота ТЕЛЕГРАМ
#define CHAT_ID "-123456789"                                        //ID чата в который будет писать БОТ и откуда будет принимать сообщения
#include <FastBot.h>                                                //Подключаем библиотеку телеграм бота AlexGyver

#define gorodset 12       //Городская сеть
#define BTN_14_1_start 32 //14.1 ПУСК
#define BTN_14_2_start 33 //14.2 ПУСК
#define BTN_GrO_reset 25  //Грубая очистка СБРОС
#define BTN_MlO_reset 26  //Мелкая очистка СБРОС
#define BTN_PrE_reset 27  //Приемная емкость СБРОС
#define BTN_LOS_reset 14  //ЛОС СБРОС
#define ON_14_1 34        //14.1 Включен
#define ON_14_2 35        //14.2 Включен

unsigned short workled = 0;         //Переменная для таймера для моргания светодиода индикатора работы (быстро моргает попытка к подключения к wifi, раз в секунду проход через цикл LOOP)
uint32_t startUnix;                 //Переменная в которую записываем время включения ESP32 для игнорирования сообщений которые приходили пока ESP32 была не в сети
bool status_14_1 = false;           //Переменная для Статуса 14.1
bool prev_status_14_1 = false;      //Переменная для хранения предыдущего статуса компрессора 14.1
bool status_14_2 = false;           //Переменная для Статуса 14.2
bool prev_status_14_2 = false;      //Переменная для хранения предыдущего статуса компрессора 14.2
bool status_gorodset = true;        //Переменная для статуса городская сеть
bool prev_status_gorodset = true;   //Переменная для хранения предыдущего статуса городской сети
bool auto_sbros = true;             //Переменная (авто/вручную) сброс ошибок и запуск компрессоров при переходе на дизель и обратно. Если true то переключения будут автоматические
unsigned long prev_connect = 0;     //Время последней попытки подключения
unsigned long time_kompr = 0;       //Таймер для сообщений о том что компрессоры не запускались более 3600000 миллисекунд (ЧАС)
unsigned long prev_time_kompr = 0;  //Таймер для сообщений о том что компрессоры не запускались более 3600000 миллисекунд (ЧАС)
unsigned int time_kompr_min = 0;    //Таймер не работающих компрессоров в минутах
unsigned int prev_a_sbros = 0;      //Таймер время с момента предыдущего авто сброса в минутах
unsigned long prev_time_kompr2 = 0;
unsigned long time_notconnected = 0;  //Таймер запоминает время в котором нет подключения
unsigned long time_connected = 0;     //Таймер запоминает время в которое еще есть подключение к wifi
unsigned long time_gorset = 0;        //Таймер проверки Городской сети
unsigned long time_status_14_1 = 0;   //Таймер проверки состояния компрессора 14.1
unsigned long time_status_14_2 = 0;   //Таймер проверки состояния компрессора 14.2
unsigned long time_utro = 0;          //Таймер отправки сообщения утром(для того чтобы не отправлял сообщение многократно)
String time_izm_14_1 = "hh:mm:ss";		//Время изменения состояния компрессора 14.1
String time_izm_14_2 = "hh:mm:ss";		//Время изменения состояния компрессора 14.2
String date_izm_14_1 = "dd:mm:yy";  	//Дата изменения состояния компрессора 14.1
String date_izm_14_2 = "dd:mm:yy";  	//Дата изменения состояния компрессора 14.2
String time_izm_gorset = "hh:mm:ss";	//Время изменения состояния городской сети
String date_izm_gorset = "dd:mm:yy";  	//Дата изменения состояния городской сети

FastBot bot(BOT_TOKEN);					//Инициализируем бота

void setup() {
  //Настраиваем ПИНЫ
  pinMode(2, OUTPUT);             //2й пин, на нем сидит встроенный светодиод
  digitalWrite(2, LOW);           //изначально встроенный светодиод в выключееном состоянии
  pinMode(BTN_14_1_start, OUTPUT);
  digitalWrite(BTN_14_1_start, LOW);
  pinMode(BTN_14_2_start, OUTPUT);
  digitalWrite(BTN_14_2_start, LOW);
  pinMode(BTN_GrO_reset, OUTPUT);
  digitalWrite(BTN_GrO_reset, LOW);
  pinMode(BTN_MlO_reset, OUTPUT);
  digitalWrite(BTN_MlO_reset, LOW);
  pinMode(BTN_PrE_reset, OUTPUT);
  digitalWrite(BTN_PrE_reset, LOW);
  pinMode(BTN_LOS_reset, OUTPUT);
  digitalWrite(BTN_LOS_reset, LOW);
  pinMode(ON_14_1, INPUT);         //Нужно подтянуть к высокому уровню 3.3В через резистор, на плате DST-1R4p-N уже сделано
  pinMode(ON_14_2, INPUT);         //Нужно подтянуть к высокому уровню 3.3В через резистор, на плате DST-1R4p-N уже сделано
  pinMode(gorodset, INPUT_PULLUP); //Нужно подтянуть к высокому уровню 3.3В через резистор, на плате DST-1R4p-N уже сделано

  connectWiFi();                   //Подключаемся к ВайФай
  delay(1000);                     //ждем 1сек
  bot.setChatID(CHAT_ID);          // установить ID чата, чтобы принимать сообщения только из него, передай "" (пустую строку) чтобы отключить проверку
                                   // можно указать несколько ID через запятую
                                   //bot.setChatID("123456,7891011,12131415");
  bot.skipUpdates();               //пропустить сообщения которые приходили в момент когда плата была выключена
  bot.sendMessage("Я в сети!");    // отправить сообщение в чат указанный в setChatID
  startUnix = bot.getUnix();       //Запоминаем время включения ESP32 для игнорирования сообщений которые приходили пока ESP32 была не в сети
  bot.attach(newMsg);              //подключаем функцию-обработчик
}

void newMsg(FB_msg& msg) {         // обработчик сообщений
  if (msg.unix < startUnix) return;// игнорировать сообщения которые приходили пока ESP32 была не в сети
  
  //+++++++ОБНОВЛЕНИЕ ПРОШИВКИ ПО ВОЗДУХУ+++++++
        if (msg.OTA && msg.fileName == "update.bin" && msg.chatID == "-123456789") bot.update();	//Прошиваем если имя файла update.bin и сообщение пришло от чата с id -123456789
  //+++++++ОБНОВЛЕНИЕ ПРОШИВКИ ПО ВОЗДУХУ+++++++
  
  if (msg.text == "/help"){               //если пришло сообщение /help...
    bot.sendMessage("Я умею:n/clock - Синхронизировать времяn/hardreset - Перезагрузкаn/auto_sbros_on - Включить автосбросn/auto_sbros_off - выключить автосбросn/on_14_1 - Пуск 14.1n/on_14_2 - Пуск 14.2n/gruboch_resetn/melkoch_resetn/priememk_resetn/los_reset", msg.chatID);
  }  

  if (msg.text == "/clock"){              //если пришло сообщение /clock...
    bot.sendMessage("Синхронизирую время с серверами ТЕЛЕГРАМ", msg.chatID);    //отправляем сообщение в чат (необходимо для получения времени в UNIX)
    bot.getUnix();                                                              //синхронизируем время с серверами ТЕЛЕГРАМ
    FB_Time t = bot.getTime(3);                 //Записываем время в UNIX в локальную переменную t
	  time_izm_gorset = t.timeString();           //записываем время изменения состояния городской сети в формате чч:мм:сс в переменную time_izm_gorset
    date_izm_gorset = t.dateString();           //записываем дату изменения состояния городской сети в формате дд:мм:гг в переменную date_izm_gorset
    time_izm_14_1 = t.timeString();       //записываем время изменения состояния компрессора 14.1 в формате чч:мм:сс в переменную time_izm_14_1
    date_izm_14_1 = t.dateString();       //записываем дату изменения состояния компрессора 14.1 в формате дд:мм:гг в переменную date_izm_14_1
    time_izm_14_2 = t.timeString();       //записываем время изменения состояния компрессора 14.2 в формате чч:мм:сс в переменную time_izm_14_2
    date_izm_14_2 = t.dateString();       //записываем дату изменения состояния компрессора 14.2 в формате дд:мм:гг в переменную date_izm_14_2
    delay(1000);                          //ждем 1сек
    proverka();                           //Запускаем функцию проверки состояния компрессоров и городской сети
    //  отправляем состояние компрессоров и городской сети в чат
    if (!status_14_1 && status_14_2) bot.sendMessage("14.1 Включен U00002705 в " + time_izm_14_1 + "  " + date_izm_14_1 + "n14.2 Выключен U0000274c в " + time_izm_14_2 + "  " + date_izm_14_2, msg.chatID);
	  if (status_14_1 && !status_14_2) bot.sendMessage("14.1 Выключен U0000274c в " + time_izm_14_1 + "  " + date_izm_14_1 + "n14.2 Включен U00002705 в " + time_izm_14_2 + "  " + date_izm_14_2, msg.chatID);
	  if (status_14_1 && status_14_2) bot.sendMessage("ВНИМАНИЕ! n14.1 Выключен U0000274c в " + time_izm_14_1 + "  " + date_izm_14_1 + "n14.2 Выключен U0000274c в " + time_izm_14_2 + "  " + date_izm_14_2 + "nНеработают " + time_kompr_min + " минут(ы),nАВТО сброс=" + String(auto_sbros), msg.chatID);
	  if (!status_14_1 && !status_14_2) bot.sendMessage("СТРАННО! n14.1 Включен U00002705 в " + time_izm_14_1 + "  " + date_izm_14_1 + "n14.2 Включен U00002705 в " + time_izm_14_2 + "  " + date_izm_14_2 + "nАВТО сброс=" + String(auto_sbros), msg.chatID);
    if (!status_gorodset) bot.sendMessage("U00002705 ЕСТЬ городская сеть c " + time_izm_gorset + " " + date_izm_gorset, CHAT_ID);
    if (status_gorodset) bot.sendMessage("U0000274c НЕТ городской сети c " + time_izm_gorset + " " + date_izm_gorset, CHAT_ID);
  }

  if (msg.text == "/hardreset"){          //если пришло сообщение /hardreset...
    bot.sendMessage("ПЕРЕЗАГРУЖАЮСЬ...", msg.chatID);                           //отправляем сообщение в чат
    delay(1000);                                                                //ждем 1сек
    bot.tickManual();                                                           //пропускаем один тик для того чтобы сообщение указалось прочитанным и плата не ушла в бесконечную перезагрузку
    ESP.restart();                                                              //перезагружаем плату
  }

  if (msg.text == "/auto_sbros_on"){      //если пришло сообщение /auto_sbros_on...
    auto_sbros = true;                                                                                    //записываем в переменную, автосброс включен
    bot.sendMessage("Автоматический сброс аварий и запуск компрессоров U00002705 ВКЛЮЧЕН nАВТО сброс=" + String(auto_sbros), msg.chatID);  //отправляем сообщение о новом состоянии функции автосброса
  }
  
  if (msg.text == "/auto_sbros_off"){     //если пришло сообщение /auto_sbros_off...
    auto_sbros = false;                                                                                   //записываем в переменную, автосброс выключен
    bot.sendMessage("Автоматический сброс аварий и запуск компрессоров U0000274c ОТКЛЮЧЕН nАВТО сброс=" + String(auto_sbros), msg.chatID); //отправляем сообщение о новом состоянии функции автосброса
  }

  if (msg.text == "/on_14_1"){            //если пришло сообщение /on_14_1...
    digitalWrite(BTN_14_1_start, HIGH);                           //включаем реле ПУСК 14.1
    delay(1000);                                                  //ждем 1сек
    digitalWrite(BTN_14_1_start, LOW);                            //выключаем реле ПУСК 14.1
    bot.sendMessage("СТАРТ 14.1", msg.chatID);                    //отправляем сообщение о пуске компрессора 14.1 в чат
  } 
  else if (msg.text == "/on_14_2"){       //если пришло сообщение /on_14_2...
    digitalWrite(BTN_14_2_start, HIGH);                           //включаем реле ПУСК 14.2
    delay(1000);                                                  //ждем 1сек
    digitalWrite(BTN_14_2_start, LOW);                            //выключаем реле ПУСК 14.2
    bot.sendMessage("СТАРТ 14.2", msg.chatID);                    //отправляем сообщение о пуске компрессора 14.2 в чат
  }
  else if (msg.text == "/gruboch_reset"){ //если пришло сообщение /gruboch_reset...
    digitalWrite(BTN_GrO_reset, HIGH);                            //включаем реле СБРОС ошибки Грубой очистки
    delay(1000);                                                  //ждем 1сек
    digitalWrite(BTN_GrO_reset, LOW);                             //выключаем реле СБРОС ошибки Грубой очистки
    bot.sendMessage("СБРОС Аварии Грубой очистки", msg.chatID);   //отправляем сообщение о сбросе ошибки грубой очистки в чат
  }
  else if (msg.text == "/melkoch_reset"){ //если пришло сообщение /melkoch_reset...
    digitalWrite(BTN_MlO_reset, HIGH);                            //включаем реле СБРОС ошибки Мелкой очистки
    delay(1000);                                                  //ждем 1сек
    digitalWrite(BTN_MlO_reset, LOW);                             //выключаем реле СБРОС ошибки Мелкой очистки
    bot.sendMessage("СБРОС Аварии Мелкой очистки", msg.chatID);   //отправляем сообщение о сбросе ошибки мелкой очистки в чат
  }
  else if (msg.text == "/priememk_reset"){ //если пришло сообщение /priememk_reset...
    digitalWrite(BTN_PrE_reset, HIGH);                             //включаем реле СБРОС ошибки приемной емкости
    delay(1000);                                                   //ждем 1сек
    digitalWrite(BTN_PrE_reset, LOW);                              //выключаем реле СБРОС ошибки приемной емкости
    bot.sendMessage("СБРОС Аварии Приемной емкости", msg.chatID);  //отправляем сообщение о сбросе ошибки приемной емкости в чат
  }
  else if (msg.text == "/los_reset"){      //если пришло сообщение /los_reset...
    digitalWrite(BTN_LOS_reset, HIGH);                             //включаем реле СБРОС ошибки ЛОС
    delay(1000);                                                   //ждем 1сек
    digitalWrite(BTN_LOS_reset, LOW);                              //выключаем реле СБРОС ошибки ЛОС
    bot.sendMessage("СБРОС Аварии ЛОС", msg.chatID);               //отправляем сообщение о сбросе ошибки ЛОС в чат
  }

  //      сверяем состояния компрессоров и состояние городской сети, исходя из этого отправляем нужное сообщение в чат
  else if (msg.text == "/status"){         //если пришло сообщение /status...
	  if (!status_14_1 && status_14_2) bot.sendMessage("14.1 Включен U00002705 в " + time_izm_14_1 + "  " + date_izm_14_1 + "n14.2 Выключен U0000274c в " + time_izm_14_2 + "  " + date_izm_14_2, msg.chatID);
	  if (status_14_1 && !status_14_2) bot.sendMessage("14.1 Выключен U0000274c в " + time_izm_14_1 + "  " + date_izm_14_1 + "n14.2 Включен U00002705 в " + time_izm_14_2 + "  " + date_izm_14_2, msg.chatID);
	  if (status_14_1 && status_14_2) bot.sendMessage("ВНИМАНИЕ! n14.1 Выключен U0000274c в " + time_izm_14_1 + "  " + date_izm_14_1 + "n14.2 Выключен U0000274c в " + time_izm_14_2 + "  " + date_izm_14_2 + "nНеработают " + time_kompr_min + " минут(ы),nАВТО сброс=" + String(auto_sbros), msg.chatID);
	  if (!status_14_1 && !status_14_2) bot.sendMessage("СТРАННО! n14.1 Включен U00002705 в " + time_izm_14_1 + "  " + date_izm_14_1 + "n14.2 Включен U00002705 в " + time_izm_14_2 + "  " + date_izm_14_2, msg.chatID);
    if (!status_gorodset) bot.sendMessage("U00002705 ЕСТЬ городская сеть c " + time_izm_gorset + " " + date_izm_gorset + "nАВТО сброс=" + String(auto_sbros), CHAT_ID);
    if (status_gorodset) bot.sendMessage("U0000274c НЕТ городской сети c " + time_izm_gorset + " " + date_izm_gorset + "nАВТО сброс=" + String(auto_sbros), CHAT_ID);
  }

  else if (msg.text == "/lllsbroslll"){    //если пришло сообщение /lllsbroslll...
    bot.sendMessage("Начинаю СБРОС после переключения электричества...", msg.chatID); //отправляем сообщение о начале сброса ошибок и запуска компрессоров в чат
    int32_t lmsgidd = bot.lastBotMsg();       //переменная куда запоминаем id сообщения отправленного ботом выше для его последующего редактирования
    digitalWrite(BTN_LOS_reset, HIGH);        //включаем реле СБРОС ошибки ЛОС
    delay(1000);                              //ждем 1сек
    digitalWrite(BTN_LOS_reset, LOW);         //выключаем реле СБРОС ошибки ЛОС
    bot.editMessage(lmsgidd, "Начинаю СБРОС после переключения электричества...nСБРОС Аварии ЛОС...", msg.chatID); //редактируем предыдущее сообщение с добавлением новой информации(аналогично сообщения ниже)
    delay(1000);                              //ждем 1сек
    digitalWrite(BTN_GrO_reset, HIGH);        //включаем реле СБРОС ошибки Грубой очистки
    delay(1000);                              //ждем 1сек
    digitalWrite(BTN_GrO_reset, LOW);         //выключаем реле СБРОС ошибки Грубой очистки
    bot.editMessage(lmsgidd, "Начинаю СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...", msg.chatID);
    delay(1000);                              //ждем 1сек
    digitalWrite(BTN_MlO_reset, HIGH);        //включаем реле СБРОС ошибки Мелкой очистки
    delay(1000);                              //ждем 1сек
    digitalWrite(BTN_MlO_reset, LOW);         //выключаем реле СБРОС ошибки Мелкой очистки
    bot.editMessage(lmsgidd, "Начинаю СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...", msg.chatID);
    delay(1000);                              //ждем 1сек
    digitalWrite(BTN_PrE_reset, HIGH);        //включаем реле СБРОС ошибки Приемной емкости
    delay(1000);                              //ждем 1сек
    digitalWrite(BTN_PrE_reset, LOW);         //выключаем реле СБРОС ошибки Приемной емкости
    bot.editMessage(lmsgidd, "Начинаю СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...", msg.chatID);
    delay(1000);                              //ждем 1сек
    digitalWrite(BTN_14_1_start, HIGH);       //включаем реле Пуск 14.1
    delay(1000);                              //ждем 1сек
    digitalWrite(BTN_14_1_start, LOW);        //выключаем реле Пуск 14.1
    bot.editMessage(lmsgidd, "Начинаю СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...nСТАРТ 14.1...", msg.chatID);
    delay(1000);                              //ждем 1сек
    digitalWrite(BTN_14_2_start, HIGH);       //включаем реле Пуск 14.2
    delay(1000);                              //ждем 1сек
    digitalWrite(BTN_14_2_start, LOW);        //выключаем реле Пуск 14.2
    bot.editMessage(lmsgidd, "Начинаю СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...nСТАРТ 14.1...nСТАРТ 14.2...", msg.chatID);
    delay(3000);                              //ждем 3сек
    proverka();                               //Запускаем функцию проверки состояния компрессоров и городской сети
    delay(500);                               //ждем 0,5сек
    
    //исходя из состояния компрессоров и городской сети, редактируем последнее сообщение с добавлением статуса компрессоров и городской сети
	  if (!status_14_1 && status_14_2) bot.editMessage(lmsgidd, "Начинаю СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...nСТАРТ 14.1...nСТАРТ 14.2...nn14.1 Включен U00002705 в " + time_izm_14_1 + " " + date_izm_14_1 + "n14.2 Выключен U0000274c в " + time_izm_14_2 + "  " + date_izm_14_2, msg.chatID);
	  if (status_14_1 && !status_14_2) bot.editMessage(lmsgidd, "Начинаю СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...nСТАРТ 14.1...nСТАРТ 14.2...nn14.1 Выключен U0000274c в " + time_izm_14_1 + " " + date_izm_14_1 + "n14.2 Включен U00002705 в " + time_izm_14_2 + "  " + date_izm_14_2, msg.chatID);
	  if (status_14_1 && status_14_2) bot.editMessage(lmsgidd, "Начинаю СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...nСТАРТ 14.1...nСТАРТ 14.2...nn!!! ВНИМАНИЕ !!!n14.1 Выключен U0000274c в " + time_izm_14_1 + " " + date_izm_14_1 + "n14.2 Выключен U0000274c в " + time_izm_14_2 + "  " + date_izm_14_2, msg.chatID);
    if (!status_14_1 && !status_14_2) bot.editMessage(lmsgidd, "Начинаю СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...nСТАРТ 14.1...nСТАРТ 14.2...nnСТРАННО!n14.1 Включен U00002705 в " + time_izm_14_1 + " " + date_izm_14_1 + "n14.2 Включен U00002705 в " + time_izm_14_2 + "  " + date_izm_14_2, msg.chatID);
    delay(1000);                              //ждем 1сек
    bot.sendMessage("ГОТОВО", msg.chatID);    //отправляем сообщение ГОТОВО в чат
  }
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void loop() {
  margun();                         //вызов функции мигания встроенного светодиода
  bot.tick();                       //тикаем в луп (проверка входящих и отметка о прочтении предыдущих)
  FB_Time t = bot.getTime(3);       //Записываем время в UNIX в локальную переменную t
	String vremya = t.timeString();   //записываем время изменения состояния городской сети в формате чч:мм:сс в переменную time_izm_gorset
  if (millis() - time_utro >= 600000){
    if (vremya == "10:00:00" || vremya == "10:00:01"){
      if (!status_14_1 && status_14_2) bot.sendMessage("14.1 Включен U00002705 в " + time_izm_14_1 + "  " + date_izm_14_1 + "n14.2 Выключен U0000274c в " + time_izm_14_2 + "  " + date_izm_14_2, CHAT_ID);
	    if (status_14_1 && !status_14_2) bot.sendMessage("14.1 Выключен U0000274c в " + time_izm_14_1 + "  " + date_izm_14_1 + "n14.2 Включен U00002705 в " + time_izm_14_2 + "  " + date_izm_14_2, CHAT_ID);
	    if (status_14_1 && status_14_2) bot.sendMessage("ВНИМАНИЕ! n14.1 Выключен U0000274c в " + time_izm_14_1 + "  " + date_izm_14_1 + "n14.2 Выключен U0000274c в " + time_izm_14_2 + "  " + date_izm_14_2 + "nНеработают " + time_kompr_min + " минут(ы),nАВТО сброс=" + String(auto_sbros), CHAT_ID);
	    if (!status_14_1 && !status_14_2) bot.sendMessage("СТРАННО! n14.1 Включен U00002705 в " + time_izm_14_1 + "  " + date_izm_14_1 + "n14.2 Включен U00002705 в " + time_izm_14_2 + "  " + date_izm_14_2, CHAT_ID);
     if (!status_gorodset) bot.sendMessage("U00002705 ЕСТЬ городская сеть c " + time_izm_gorset + " " + date_izm_gorset + "nАВТО сброс=" + String(auto_sbros), CHAT_ID);
      if (status_gorodset) bot.sendMessage("U0000274c НЕТ городской сети c " + time_izm_gorset + " " + date_izm_gorset + "nАВТО сброс=" + String(auto_sbros), CHAT_ID);
      delay(2000);
      time_utro = millis();
    }
  }
  proverka();                       //проверяем состояние компрессоров 14.1 и 14.2, если они отключены более 3600000 мсек(ЧАС) - отправляем сообщение в чат
  if (auto_sbros == true){          //если автосброс включен... (включен по умолчанию (прсле перезагрузки платы), можно отключить отправив сообщение боту /auto_sbros_off)               
    if (millis() - prev_a_sbros >= 1800000) a_sbros();  //если включен авто сброс и время с момента предыдущего а.сброса прошло больше 30ти минут, совершить авто сброс
  }  
  stat_wifi();                      //Проверка состояния подключения к сети wifi
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void connectWiFi() {              //функция подключения к сети wifi
  delay(2000);                                     //ждем 2сек
  WiFi.begin(WIFI_SSID, WIFI_PASS);                //подключаемся используя указанные выше SSID(имя сети) и PASS(пароль от данной сети)
  prev_connect = millis();                         //записываем время когда была попытка подключиться
  while (WiFi.status() != WL_CONNECTED){           //пока нет водключения к сети wifi...
    for (unsigned short x=0;x<=2;x++){             //цикл для обозначения встроенным светодиодом о том, что нет соединения с wifi сетью (быстрое мерцание) unsigned short в arduino ide 0...255
      digitalWrite(2, HIGH);    //включаем встроенный светодиод
      delay(250);               //ждем 0,25сек
      digitalWrite(2, LOW);     //выключаем встроенный светодиод
      delay(250);               //ждем 0,25сек
    }
    if ((millis() - prev_connect) > 5000) return;  //ждем 5 сек
  }
}
void stat_wifi() {                //Проверка состояния подключения к сети wifi
  if (WiFi.status() != WL_CONNECTED) {    //если нет водключения к сети wifi...
    digitalWrite(2, HIGH);                //включаем встроенный светодиод
    delay(50);                            //ждем 0,05сек
    digitalWrite(2, LOW);                 //выключаем встроенный светодиод
    delay(50);                            //ждем 0,05сек
    time_notconnected = millis();         //записываем последнее время при котором не было подключения к сети wifi для таймера переподключения
  }
  if (WiFi.status() == WL_CONNECTED) time_connected = millis();   //если плата подключена к сети wifi, записываем текущее время в переменную time_connected
  
  if (WiFi.status() != WL_CONNECTED && ((time_notconnected - time_connected) >= 60000) && (millis() - prev_connect) > 15000) connectWiFi(); //если нет подключения более 1 мин пытаемся переподключиться

}
void proverka(){                   //функция проверки (проверяем состояние компрессоров 14.1 и 14.2, если они отключены более 3600000 мсек(ЧАС) - отправляем сообщение в чат)
  
  if (millis() - time_gorset >= 1500){        //Проверяем состояние городской сети раз в 1,5сек. для избегания дребезга контактов
    status_gorodset = digitalRead(gorodset);  //записываем состояние городской сети в переменную status_gorodset
    time_gorset = millis();                   //записываем время для таймера переодичности опроса состояния городской сети
  }
  
  if (status_gorodset != prev_status_gorodset){ //Если состояние городской сети изменилось (пропала гор сеть или появилась)
    prev_status_gorodset = status_gorodset;     //записываем новое состояние гор.сети в переменную предыдущего состояния гор.сети
    FB_Time t = bot.getTime(3);                 //Записываем время в UNIX в локальную переменную t
	  time_izm_gorset = t.timeString();           //записываем время изменения состояния городской сети в формате чч:мм:сс в переменную time_izm_gorset
    date_izm_gorset = t.dateString();           //записываем дату изменения состояния городской сети в формате дд:мм:гг в переменную date_izm_gorset
    if (!status_gorodset) bot.sendMessage("U00002705 ЕСТЬ городская сеть с " + time_izm_gorset + " " + date_izm_gorset, CHAT_ID);
    if (status_gorodset) bot.sendMessage("U0000274c НЕТ городской сети с " + time_izm_gorset + " " + date_izm_gorset, CHAT_ID);
    if (auto_sbros == true) bot.sendMessage("Автоматический сброс аварий и запуск компрессоров U00002705 ВКЛЮЧЕН", CHAT_ID);
    if (auto_sbros == false) bot.sendMessage("Автоматический сброс аварий и запуск компрессоров U0000274c ВЫКЛЮЧЕН", CHAT_ID);
  }

  if (millis() - time_status_14_1 >=1500){  //Проверяем состояние 14.1 раз в 1,5сек. для избегания дребезга контактов
    status_14_1 = digitalRead(ON_14_1);     //Записываем состояние компрессора 14.1 в переменную status_14_1
    if (status_14_1 != prev_status_14_1){   //Если состояние коипрессора 14.1 изменилось...
	    prev_status_14_1 = status_14_1;       //Записываем новое состояние компрессора 14.1 в переменную последнего состояния prev_status_14_1
      FB_Time t = bot.getTime(3);           //Записываем время в UNIX в локальную переменную t
	    time_izm_14_1 = t.timeString();       //записываем время изменения состояния компрессора 14.1 в формате чч:мм:сс в переменную time_izm_14_1
      date_izm_14_1 = t.dateString();       //записываем дату изменения состояния компрессора 14.1 в формате дд:мм:гг в переменную date_izm_14_1
    }
    time_status_14_1 = millis();            //записываем время для таймера переодичности опроса состояния компрессора 14.1
  }
  
  if (millis() - time_status_14_2 >=1500){  //Проверяем состояние 14.2 раз в 1,5сек. для избегания дребезга контактов
    status_14_2 = digitalRead(ON_14_2);     //Записываем состояние компрессора 14.2 в переменную status_14_2
    if (status_14_2 != prev_status_14_2){   //Если состояние коипрессора 14.2 изменилось...
	    prev_status_14_2 = status_14_2;       //Записываем новое состояние компрессора 14.2 в переменную последнего состояния prev_status_14_2
      FB_Time t = bot.getTime(3);           //Записываем время в UNIX в локальную переменную t
	    time_izm_14_2 = t.timeString();       //записываем время изменения состояния компрессора 14.2 в формате чч:мм:сс в переменную time_izm_14_2
      date_izm_14_2 = t.dateString();       //записываем дату изменения состояния компрессора 14.2 в формате дд:мм:гг в переменную date_izm_14_2
    }
    time_status_14_2 = millis();            //записываем время для таймера переодичности опроса состояния компрессора 14.2
  }
  
  if (!status_14_1 || !status_14_2) {       //Если один из компрессоров включен...
    time_kompr = millis();                  //записываем время для таймера состояния компрессоров time_kompr
    prev_time_kompr = millis();             //записываем время для таймера предыдущего состояния компрессоров prev_time_kompr
    prev_time_kompr2 = millis();            //записываем время для таймера предыдущего состояния компрессоров prev_time_kompr2
    prev_a_sbros = millis();                //записываем время для таймера запоминания предыдущего времени автоматического сброса
  }
  
  if (status_14_1 == true && status_14_2 == true){              //если оба компрессора выключены...
    time_kompr = millis();                                      //записываем время отключенного состояния обоих компрессоров в переменную time_kompr
    time_kompr_min = ((time_kompr - prev_time_kompr2)/60000);   //считаем и записываем время которое не работают оба компрессора в минутах, в переменную time_kompr_min
  }

  if (status_14_1 == true && status_14_2 == true && ((time_kompr - prev_time_kompr) >= 3600000)){ //если оба компрессора отключены и находятся в таком состоянии болше 3600000мс-часа...
    prev_time_kompr = millis();                                                                   //записываем время для таймера переодичности оповещения о том, что таймеры не работают в чат
    bot.sendMessage("Компрессоры не работают уже " + String(time_kompr_min) + " минутnАВТО сброс=" + String(auto_sbros), CHAT_ID); //отправляем оповещение в чат
  }
}
void a_sbros(){                    //Функция автоматического сброса аварий и включения компрессоров
    prev_a_sbros = millis();            //Запоминаем время автосброса в минутах
    bot.sendMessage("Начинаю Автоматический СБРОС после переключения электричества...", CHAT_ID); //отправляем сообщение в чат
    int32_t lmsgidd = bot.lastBotMsg(); //переменная куда запоминаем id сообщения отправленного ботом выше для его последующего редактирования
    digitalWrite(BTN_LOS_reset, HIGH);  //включаем реле "Сброс аварии ЛОС"
    delay(1500);                        //ждем 1,5сек
    digitalWrite(BTN_LOS_reset, LOW);   //выключаем реле "Сброс аварии ЛОС"
    bot.editMessage(lmsgidd, "Начинаю Автоматический СБРОС после переключения электричества...nСБРОС Аварии ЛОС...", CHAT_ID); //редактируем предыдущее сообщение с дополнением
    delay(1500);                        //ждем 1,5сек
    digitalWrite(BTN_GrO_reset, HIGH);  //включаем реле "Сброс аварии Грубой очистки"
    delay(1500);                        //ждем 1,5сек
    digitalWrite(BTN_GrO_reset, LOW);   //выключаем реле "Сброс аварии Грубой очистки"
    bot.editMessage(lmsgidd, "Начинаю Автоматический СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...", CHAT_ID); //редактируем пред.сообщение
    delay(1500);                        //ждем 1,5сек
    digitalWrite(BTN_MlO_reset, HIGH);  //включаем реле "Сброс аварии Мелкой очистки(14.х)"
    delay(1500);                        //ждем 1,5сек
    digitalWrite(BTN_MlO_reset, LOW);   //выключаем реле "Сброс аварии Мелкой очистки(14.х)"
    bot.editMessage(lmsgidd, "Начинаю Автоматический СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...", CHAT_ID);
    delay(1500);                        //ждем 1,5сек
    digitalWrite(BTN_PrE_reset, HIGH);  //включаем реле "Сброс аварии Приемной емкости"
    delay(1500);                        //ждем 1,5сек
    digitalWrite(BTN_PrE_reset, LOW);   //выключаем реле "Сброс аварии Приемной емкости"
    bot.editMessage(lmsgidd, "Начинаю Автоматический СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...", CHAT_ID);
    delay(1500);                        //ждем 1,5сек
    digitalWrite(BTN_14_1_start, HIGH); //включаем реле "Пуск компрессора 14.1"
    delay(1500);                        //ждем 1,5сек
    digitalWrite(BTN_14_1_start, LOW);  //выключаем реле "Пуск компрессора 14.1"
    bot.editMessage(lmsgidd, "Начинаю Автоматический СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...nСТАРТ 14.1...", CHAT_ID);
    delay(1500);                        //ждем 1,5сек
    digitalWrite(BTN_14_2_start, HIGH); //включаем реле "Пуск компрессора 14.2"
    delay(1500);                        //ждем 1,5сек
    digitalWrite(BTN_14_2_start, LOW);  //выключаем реле "Пуск компрессора 14.2"
    bot.editMessage(lmsgidd, "Начинаю Автоматический СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...nСТАРТ 14.1...nСТАРТ 14.2...", CHAT_ID);
    delay(3000);                        //ждем 3сек
    proverka();                         //выполняем функцию проверки (опрос состояния компрессором и городской сети)

	  if (!status_14_1 && status_14_2) bot.editMessage(lmsgidd, "Начинаю Автоматический СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...nСТАРТ 14.1...nСТАРТ 14.2...nn14.1 Включен U00002705 в " + time_izm_14_1 + " " + date_izm_14_1 + "n14.2 Выключен U0000274c в " + time_izm_14_2 + "  " + date_izm_14_2, CHAT_ID);
	  if (status_14_1 && !status_14_2) bot.editMessage(lmsgidd, "Начинаю Автоматический СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...nСТАРТ 14.1...nСТАРТ 14.2...nn14.1 Выключен U0000274c в " + time_izm_14_1 + " " + date_izm_14_1 + "n14.2 Включен U00002705 в " + time_izm_14_2 + "  " + date_izm_14_2, CHAT_ID);
	  if (status_14_1 && status_14_2) bot.editMessage(lmsgidd, "Начинаю Автоматический СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...nСТАРТ 14.1...nСТАРТ 14.2...nn!!! ВНИМАНИЕ !!!n14.1 Выключен U0000274c в " + time_izm_14_1 + " " + date_izm_14_1 + "n14.2 Выключен U0000274c в " + time_izm_14_2 + "  " + date_izm_14_2, CHAT_ID);
    if (!status_14_1 && !status_14_2) bot.editMessage(lmsgidd, "Начинаю Автоматический СБРОС после переключения электричества...nСБРОС Аварии ЛОС...nСБРОС Аварии Грубой очистки...nСБРОС Аварии Мелкой очистки...nСБРОС Аварии Приемной емкости...nСТАРТ 14.1...nСТАРТ 14.2...nnСТРАННО!n14.1 Включен U00002705 в " + time_izm_14_1 + " " + date_izm_14_1 + "n14.2 Включен U00002705 в " + time_izm_14_2 + "  " + date_izm_14_2, CHAT_ID);
    delay(1000);                        //ждем 1сек
    bot.sendMessage("ГОТОВО", CHAT_ID); //отправляем сообщение в чат
}
void margun (){                    //Функция мигания встроенным светодиодом для визуального определения работы программы(если светодиод не мигает программа гдето зависла) 
  if (workled <= 2767) {           //если значение переменной workled менее или равно 2767
    digitalWrite(2, HIGH);         //включаем встроенный светодиод
    workled++;                     //увеличиваем значение в переменной workled на единицу
  }
  if (workled > 2767) {            //если значение переменной workled более 2767
    digitalWrite(2, LOW);          //выключаем встроенный светодиод
    workled++;                     //увеличиваем значение в переменной workled на единицу
  }
}

Автор:
marsel790

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js