Telegram бот. Библиотека
Библиотеки
В примерах из Интернета обычно используют библиотеку Universal-Arduino-Telegram-Bot. Она не очень простая в использовании, а также жутко тяжёлая и медленная за счёт использования JSON. Я написал свою библиотеку – FastBot, в ней реализованы все самые нужные инструменты для работы с ботом. Библиотека очень лёгкая и не требует дополнительной установки других библиотек.
Подробная документация, инструкция по установке и примеры находятся по ссылке выше, также библиотеку можно установить через встроенный менеджер библиотек Arduino IDE по названию FastBot.
Начало работы
- Зарегистрировать бота в Телеграм и получить его токен (читай урок)
- Опционально – узнать свой ID (читай урок)
- Обеспечить подключение платы к Интернету (читай урок)
- Подключить библиотеку
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 – бот пропускает эти сообщения
Так если бот может отправлять сообщения в чат, значит 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();” но он не перестает перезагружаться! когда будешь делать следующий урок пожалуйста покажи как можно это осуществить
else if (text == “/restart”)
{
bot.sendMessage(“restart – ok”, msg.chatID);
ESP.restart();
}
Проверьте с помощью api https://api.telegram.org/bot{BOTTOKEN}/getUpdates
может у вас много сообщений /reset.
Таже проблема. Не принимает/обрабатывает 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?