Skip to contentSkip to main navigation Skip to footer

Telegram бот. Библиотека

Библиотеки


В примерах из Интернета обычно используют библиотеку Universal-Arduino-Telegram-Bot. Она не очень простая в использовании, а также жутко тяжёлая и медленная за счёт использования JSON. Я написал свою библиотеку – FastBot, в ней реализованы все самые нужные инструменты для работы с ботом. Библиотека очень лёгкая и не требует дополнительной установки других библиотек.

Подробная документация, инструкция по установке и примеры находятся по ссылке выше, также библиотеку можно установить через встроенный менеджер библиотек Arduino IDE по названию FastBot.

Начало работы


  • Зарегистрировать бота в Телеграм и получить его токен (читай урок)
  • Обеспечить подключение платы к Интернету (читай урок)
  • Подключить библиотеку FastBot.h
  • Инициализировать бота, указать токен FastBot bot(токен);
  • Теперь можно отправлять сообщения в указанный чат!

Для чтения входящих сообщений нужно:

  • Вызывать функцию-тикер бота bot.tick(); в основном цикле программы, она запрашивает новые сообщения по встроенному таймеру
  • Создать функцию вида void newMsg(FB_msg& msg){} (msg – сокращение от message, сообщение) – она будет вызываться при поступлении новых сообщений
  • Подключить функцию к боту по её имени: bot.attach(newMsg);
  • Забирать нужные данные из структуры msg внутри функции-обработчика сообщений. Основные:
    • userID – ID пользователя
    • username – имя пользователя (в API Telegram это first_name)
    • chatID – ID чата
    • messageID – ID сообщения в чате
    • text – текст сообщения
    • Остальное смотри в документации

Минимальный пример


Рассмотрим пример, который выводит в монитор порта часть информации из сообщения в любом чате с ботом:

#define WIFI_SSID "login"
#define WIFI_PASS "pass"
#define BOT_TOKEN "xxxx"

#include <FastBot.h>
FastBot bot(BOT_TOKEN);

void setup() {
  connectWiFi();
  bot.attach(newMsg);
}

// обработчик сообщений
void newMsg(FB_msg& msg) {
  // выводим ID чата, имя юзера и текст сообщения
  Serial.print(msg.chatID);     // ID чата 
  Serial.print(", ");
  Serial.print(msg.username);   // логин
  Serial.print(", ");
  Serial.println(msg.text);     // текст
}

void loop() {
  bot.tick();
}

void connectWiFi() {
  delay(2000);
  Serial.begin(115200);
  Serial.println();

  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    if (millis() > 15000) ESP.restart();
  }
  Serial.println("Connected");
}

Давайте научим бота отвечать на сообщения – пусть он отправляет текст сообщения обратно:

void newMsg(FB_msg& msg) {
  // отправить сообщение обратно
  bot.sendMessage(msg.text, msg.chatID);  
}

Бот может ответить на сообщение (с цитатой сообщения), для этого указываем ID чата и сообщения. Пусть отвечает Hello! на любые сообщения:

void newMsg(FB_msg& msg) {
  // ответить
  bot.replyMessage("Hello!", msg.messageID, msg.chatID);  
}

Задание ID чата


Чтобы бот мог сам писать сообщения, он должен знать ID чата. В предыдущих примерах мы отвечали на сообщения, из которых он мог узнать ID. Как отправить сообщение самостоятельно, например при запуске программы? Узнаём свой ID и передаём боту в bot.setChatID(id). Можно указать сразу несколько ID через запятую: bot.setChatID("1234,56789,445566");.

Теперь бот будет обрабатывать сообщения только из указанных чатов, а также будет отправлять сообщения во все указанные чаты при отправке без указания ID чата bot.sendMessage("Текст"). Поздороваемся при запуске программы:

void setup() {
  connectWiFi();
  bot.setChatID("123456");
  bot.sendMessage("Hello, World!");
}

Ответ на команды


В прошлом уроке мы создали для бота список команд. Давайте реализуем взаимодействие с ними:

  • /say_hello – отправим сообщение Hello!
  • /led_on – включим светодиод на плате (digitalWrite(LED_BUILTIN, LOW);)
  • /led_off – выключим светодиод (digitalWrite(LED_BUILTIN, HIGH);)

Примечание: поведение светодиода инвертировано, читайте в уроке про особенности платы.

Для обработки команды достаточно просто сравнить текст сообщения со строкой:

void newMsg(FB_msg& msg) {
  if (msg.text == "/say_hello") bot.sendMessage("Hello!", msg.chatID);
  else if (msg.text == "/led_on") digitalWrite(LED_BUILTIN, LOW);
  else if (msg.text == "/led_off") digitalWrite(LED_BUILTIN, HIGH);
}

Не забываем сделать пин выходом в блоке setup():

void setup() {
  connectWiFi();
  bot.attach(newMsg);
  pinMode(LED_BUILTIN, OUTPUT);
}

Готово! Можете проверить на своём боте.

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

Полезный пример?

Похожие примеры
21 Комментарий
  • Привет
    Не могу понять бот подключен, сообщение в чат отправляет, а с чата когда пишу нет реакции

      • Так если бот может отправлять сообщения в чат, значит chatid верный, не знаю на что еще смотреть

  • День добрый !

    Спасибо за библиотеку FastBot , отличный инструмент!
    Есть вопросы ( я начинающий ардуинщик).
    У меня ESP8266 и не могу сообразить как написать код ожидания ответа пользователя в телеграмм , что-бы потом его использовать в скетче.

    Т.е. задача стоит в том, чтобы ввести через телеграмм в скетч номер телефона, который ESP8266 запишет в память SIM карты. В боте пишу команду /phone1, esp8266 через телеграмм сообщает, что готова принять номер телефона. А вот как заставить программу ожидать ввода номера и перехватить это сообщение не знаю, т.к. бот работает только с командами.

    Вот мой кусок программы:

    ////- запись номера телефона для ответа по СМС

    if(msg.text == “/phone1”){

    bot.sendMessage(“для отправки СМС введите 1-й номер телефона в формате +79хххххх”, msg.chatID);

    ……… код ожидания ввода телефона………

    message_telega =  msg.text; 

     int index_number00_telega = message_telega.lastIndexOf(“+79”);
        Serial.print(“index_number00_telega: “);
    Serial.println (index_number00_telega);

    mynumber1_telega  = message_telega.substring(index_number00_telega, (index_number00_telega + 12));

      Serial.print(“mynumber1_telega: “);
    Serial.println (mynumber1_telega);
    bot.sendMessage(“для отправки СМС пишу в сим-карту 1-й номер телефона”, msg.chatID);
    bot.sendMessage(mynumber1_telega, msg.chatID);
    write_sim_for_sms_from_telega();
    }

    Подскажите пожалуйста код или команды FastBot ожидания ввода телефона.

  • Спасибо за статью!
    Правильно ли я понимаю, чтобы бот отправил текст и состояние переменной в одном сообщении нужно составлять строку с помощью String?

    • Разобрался: использовал mString – всё получилось.
      Только не совсем понял: “mString str” – размер нужно указывать в кол-ве знаков или как-то по-другому нужно рассчитывать размер?

      Кстати, галочка на сайте “Сохранить моё имя, email и адрес сайта в этом браузере для последующих моих комментариев.” не работает.. Прошлый коммент писал с этой галочкой.

  • привет, Алекс! очень хорошая библиотека! Твой пример мне сильно помог в создании бота, но никак не могу разобраться как сделать перезагрузку платы через команду. пробовал “else if (msg.text == “/restart”) ESP.restart();” но он не перестает перезагружаться! когда будешь делать следующий урок пожалуйста покажи как можно это осуществить

    • Таже проблема. Не принимает/обрабатывает callback_query.
      Может что-то делаем не так? Или действительно не работает.
      Меню “обычное” работает.

      • Спасибо, Алексу!!!
        Нужно было обновить библиотеку вручную до последней версии

        Все заработало. А пример видимо был из ранней версии. Там вместо 
        msg.data
        было
        msg.text

        Понедельник, 27 июня 2022

  • Что то я не пойму, разве для работы бота не нужен белый IP для взаимодействия с ESP? Каким макаром бот будет отправлять на контроллер команду без проброшенных портов наружу?

  • Алекс привет, библиотека действительно лёгкая и быстрая, но примеры , где есть inlineMenu (menuTest,menuTest2,query)
    не смог запустить, начальное меню создаётся, но при нажатии кнопок нет сообщения для ESP, телеграмм последняя версия, проверил на AsyncTelegram2 похожий пример работает.

  • #define WIFI_SSID “xxxxxxxxxxx”
    #define WIFI_PASS “xxxxxxxxxxx”
    #define BOT_TOKEN “xxxxxxxxxxx”

    #include
    #include
    #include
    #include “SparkFunHTU21D.h”

    HTU21D myHumidity;
    FastBot bot(BOT_TOKEN);
    LiquidCrystal_I2C lcd(0x27,16,2);

    void setup(){
    connectWiFi();
    bot.attach(newMsg);

    bot.setChatID(“xxxxxxxx”);
    bot.sendMessage(“Hello!”);

    bool status;

    myHumidity.begin();
    lcd.begin(); // initialize the LCD
    lcd.backlight(); // Включаем подсветку
    }
    // обработчик сообщений
    void newMsg(FB_msg& msg) {
    // выводим ID чата, имя юзера и текст сообщения
    Serial.print(msg.chatID); // ID чата
    Serial.print(“, “);
    Serial.print(msg.username); // логин
    Serial.print(“, “);
    Serial.println(msg.text); // текст
    }

    void loop() {
    bot.tick();
    Serial.print(“Temp: “); Serial.print(myHumidity.readTemperature());
    Serial.print(“\t\tHum: “); Serial.println(myHumidity.readHumidity());
    float h = myHumidity.readHumidity();
    // Read temperature as Celsius
    float t = myHumidity.readTemperature();
    lcd.setCursor(0, 0); // Устанавливаем курсор в начало 1 строки
    lcd.print(“Hum = % “); // Выводим текст
    lcd.setCursor(7, 0); // Устанавливаем курсор на 7 символ
    lcd.print(h, 1); // Выводим на экран значение влажности
    lcd.setCursor(0, 1); // Устанавливаем курсор в начало 2 строки
    lcd.print(“Temp = C “); // Выводим текст, \1 – значок градуса
    lcd.setCursor(7, 1); // Устанавливаем курсор на 7 символ
    lcd.print(t,1); // Выводим значение температуры
    delay(20000);
    }
    void connectWiFi() {
    delay(2000);
    Serial.begin(115200);
    Serial.println();
    WiFi.begin(WIFI_SSID, WIFI_PASS);
    while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(“.”);
    if (millis() > 15000) ESP.restart();
    }
    Serial.println(“Connected”);

    }

    Добрый день! Классная библиотека – а как можно в моём скетче с датчика HTU21D запросить данные через бота?

      • #define WIFI_SSID “********”
        #define WIFI_PASS “********”
        #define BOT_TOKEN “********”

        #include “SparkFunHTU21D.h”
        #include

        HTU21D myHumidity;
        FastBot bot(BOT_TOKEN);
        LiquidCrystal_I2C lcd(0x27, 16, 2);

        float h;
        float t;

        void getTempAndHum() {
        static unsigned long tempAndHum_millis = millis();
        if ( millis() – tempAndHum_millis > 2 * 1000) {
        tempAndHum_millis = millis();

        h = myHumidity.readHumidity();
        // Read temperature as Celsius
        t = myHumidity.readTemperature();
        Serial.print(“Temp: “); Serial.print(t);
        Serial.print(“\t\tHum: “); Serial.println(h);
        }
        }

        void setTempAndHumLcd() {
        static unsigned long lct_timeout_millis = millis();
        if ( millis() – lct_timeout_millis > 5 * 1000 ) {
        lct_timeout_millis = millis();

        lcd.setCursor(0, 0); // Устанавливаем курсор в начало 1 строки
        lcd.print(“Hum = % “); // Выводим текст
        lcd.setCursor(7, 0); // Устанавливаем курсор на 7 символ
        lcd.print(h, 1); // Выводим на экран значение влажности
        lcd.setCursor(0, 1); // Устанавливаем курсор в начало 2 строки
        lcd.print(“Temp = C “); // Выводим текст, \1 – значок градуса
        lcd.setCursor(7, 1); // Устанавливаем курсор на 7 символ
        lcd.print(t, 1); // Выводим значение температуры
        }
        }

        // обработчик сообщений
        void newMsg(FB_msg& msg) {
        // выводим ID чата, имя юзера и текст сообщения
        Serial.print(msg.chatID); // ID чата
        Serial.print(“, “);
        Serial.print(msg.username); // логин
        Serial.print(“, “);
        Serial.println(msg.text); // текст

        if (msg.text == “/temp”) {
        String s = “Temp: ” + String(t) + “\nHum: ” + String(h);
        bot.sendMessage(s);
        }
        }

        void connectWiFi() {
        delay(2000);
        Serial.begin(115200);
        Serial.println();
        WiFi.begin(WIFI_SSID, WIFI_PASS);
        while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(“.”);
        if (millis() > 15000) ESP.restart();
        }
        Serial.println(“Connected”);
        }

        //==================================================================
        // SETUP SETUP SETUP SETUP SETUP SETUP
        //==================================================================
        void setup() {
        connectWiFi();
        bot.attach(newMsg);

        bot.setChatID(“********”);
        bot.sendMessage(“Hello!”);

        bool status;
        myHumidity.begin();
        lcd.begin(); // initialize the LCD
        lcd.backlight(); // Включаем подсветку
        }

        //=================================================================
        // LOOP LOOP LOOP LOOP LOOP LOOP
        //=================================================================
        void loop() {
        getTempAndHum();
        setTempAndHumLcd();
        bot.tick();
        }

    • #define WIFI_SSID “xxxxxxxxxxx”
      #define WIFI_PASS “xxxxxxxxxxx”
      #define BOT_TOKEN “xxxxxxxxxxx”

      #include “SparkFunHTU21D.h”

      HTU21D myHumidity;
      FastBot bot(BOT_TOKEN);
      LiquidCrystal_I2C lcd(0x27, 16, 2);

      void setup() {
      connectWiFi();
      bot.attach(newMsg);

      bot.setChatID(“xxxxxxxx”);
      bot.sendMessage(“Hello!”);

      bool status;
      // Лучше использовать отдельную функцию инициализации, чтобы из бота командой перезагружать lcd экран, если он зависнет
      myHumidity.begin();
      lcd.begin(); // initialize the LCD
      lcd.backlight(); // Включаем подсветку
      }

      // обработчик сообщений
      void newMsg(FB_msg& msg) {
      // выводим ID чата, имя юзера и текст сообщения
      Serial.print(msg.chatID); // ID чата
      Serial.print(“, “);
      Serial.print(msg.username); // логин
      Serial.print(“, “);
      Serial.println(msg.text); // текст

      if (msg.text == “/temp”) {
      String s = “Temp: ” + t + “\nHum: ” + “h”;
      bot.sendMessage(s);
      }
      }

      void loop() {
      getTempAndHum();
      setTempAndHumLcd();
      bot.tick();
      //delay(20000); // лучше заменить на обработчик millis
      }

      void getTempAndHum() {
      static unsigned long tempAndHum_millis = millis();
      if ( millis() – tempAndHum_millis > 20 * 1000 or millis() 5 * 1000 ) {
      lct_timeout_millis = millis();
      lcd.setCursor(0, 0); // Устанавливаем курсор в начало 1 строки
      lcd.print(“Hum = % “); // Выводим текст
      lcd.setCursor(7, 0); // Устанавливаем курсор на 7 символ
      lcd.print(h, 1); // Выводим на экран значение влажности
      lcd.setCursor(0, 1); // Устанавливаем курсор в начало 2 строки
      lcd.print(“Temp = C “); // Выводим текст, \1 – значок градуса
      lcd.setCursor(7, 1); // Устанавливаем курсор на 7 символ
      lcd.print(t, 1); // Выводим значение температуры
      }
      }

      void connectWiFi() {
      delay(2000);
      Serial.begin(115200);
      Serial.println();
      WiFi.begin(WIFI_SSID, WIFI_PASS);
      while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(“.”);
      if (millis() > 15000) ESP.restart();
      }
      Serial.println(“Connected”);
      }

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

  • 🙂 Огромное спасибо за библиотеку! 🙂 С бибилиотекой Universal-Arduino-Telegram-Bot есть еще проблема – esp8266 рандомно перезагружается, если использовать одновременно с ESP8266WebServer.

  • А как вывести в serial последнее сообщение из чата при перезагрузке контроллера?

  • Добрый день. А можно ли как-то определить в скетче, что сообщение от бота отправилось в группу, и его там могут прочитать участники группы, либо сообщение не отправилось, скажем, из-за отсутствия подключения к WiFi?

Оставить комментарий

Ваш адрес email не будет опубликован.