• Stars
    star
    183
  • Rank 210,154 (Top 5 %)
  • Language
    C++
  • License
    MIT License
  • Created over 3 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Многофункциональная быстрая библиотека для Телеграм бота на esp8266/esp32

latest Foo Foo Foo

Foo

FastBot

Многофункциональная быстрая библиотека для телеграм бота на esp8266/esp32

  • Работает на стандартных библиотеках
  • Опциональный "белый список" ID чатов
  • Проверка обновлений вручную или по таймеру
  • Отправка/удаление/редактирование/ответ на сообщения
  • Чтение и отправка в чатах, группах, каналах
  • Изменение названия и описания чата
  • Закрепление/открепление сообщений
  • Отправка стикеров
  • Сообщения с форматированием markdown/html
  • Вывод обычного меню
  • Вывод инлайн меню с поддержкой кнопок-ссылок
  • Поддержка Unicode (другие языки + эмодзи) для входящих сообщений
  • Встроенный urlencode для исходящих сообщений
  • Встроенные часы реального времени с синхронизацией от сервера Telegram
  • Возможность OTA обновления прошивки .bin файлом из чата Telegram (firmware и SPIFFS)
  • Отправка файлов из памяти в чат (+ редактирование)

Совместимость

ESP8266 (SDK v2.6+), ESP32

Создание и настройка бота

  • Инструкция как создать и настроить Telegram бота
  • Если бот у вас уже есть, убедитесь что он не в webhook режиме (отключен по умолчанию), иначе esp не сможет принимать сообщения!
  • Для того, чтобы бот читал все сообщения в группе (а не только /команды), нужно отключить параметр Group Privacy в настройках бота Bot Settings в чате с @BotFather. Данный параметр включен по умолчанию!
  • Для полноценной работы в группе (супергруппе) бота нужно сделать администратором!

Ограничения

Лимиты Telegram

Телеграм устанавливает следующие лимиты на отправку сообщений ботом (документация)

  • В чат: не чаще раза в секунду. Отправлять чаще можно, но сообщение может не дойти
  • В группу: не чаще 20 сообщений в минуту
  • Суммарный лимит: не чаще 30 сообщений в секунду
  • Бот может читать сообщения, с момента отправки которых прошло меньше 24 часов
  • Бот не может писать в личку другому боту
  • Бот не видит сообщения от других ботов в группе

Прочее

  • Телеграм разделяет текст на несколько сообщений, если длина текста превышает ~4000 символов! Эти сообщения будут иметь разный messageID в чате
  • При ответе на сообщение библиотека парсит текст исходного сообщения, а не ответа

Вывод графики

Используйте библиотеку CharDisplay для вывода графиков и рисования в чате!

Документация и проекты

Подробные уроки по работе с Телеграм ботом при помощи этой библиотеки можно найти на сайте Arduino набора GyverKIT

Сравнение с Universal-Arduino-Telegram-Bot

Universal-Arduino-Telegram-Bot

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

  • send - отправка сообщения в чат
  • update - проверка входящих сообщений
  • free heap - объём свободной оперативной памяти во время работы программы
Library Flash, B SRAM, B send, ms update, ms free heap, B
Univ..Bot 400004 29848 2000 1900 38592
FastBot 393220 28036 70 70 37552
diff 6784 1812 1930 1830 1040
  • FastBot легче почти на 7 кБ Flash и 2 кБ SRAM, но занимает на 1 кБ в SRAM больше во время работы программы. Итого легче на 2-1 = 1 кБ SRAM.
  • FastBot значительно быстрее обрабатывает чат и отправляет сообщения (на 2 секунды) за счёт ручного парсинга ответа сервера и статически выделенных HTTP клиентов
  • Тест проведён в обычном режиме работы FastBot. При активации FB_DYNAMIC библиотека будет занимать на 10кб меньше памяти, но работать будет медленнее:
    • Free heap: 48000 кБ
    • Отправка сообщения: 1 секунда
    • Запрос обновления: 1 секунда

Содержание

Установка

  • Библиотеку можно найти по названию FastBot и установить через менеджер библиотек в:
    • Arduino IDE
    • Arduino IDE v2
    • PlatformIO
  • Скачать библиотеку .zip архивом для ручной установки:
    • Распаковать и положить в C:\Program Files (x86)\Arduino\libraries (Windows x64)
    • Распаковать и положить в C:\Program Files\Arduino\libraries (Windows x32)
    • Распаковать и положить в Документы/Arduino/libraries/
    • (Arduino IDE) автоматическая установка из .zip: Скетч/Подключить библиотеку/Добавить .ZIP библиотеку… и указать скачанный архив
  • Читай более подробную инструкцию по установке библиотек здесь

Обновление

  • Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи
  • Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить"
  • Вручную: удалить папку со старой версией, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам!

Инициализация

FastBot bot;
FastBot bot(токен); // с указанием токена

Документация

// ============== НАСТРОЙКИ ==============
void setToken(String token);                    // изменить/задать токен бота
void setChatID(String chatID);                  // установка ID чата (белый список), необязательно. Можно несколько через запятую ("id1,id2,id3")
void setChatID(int64_t id);                     // то же самое, но в int64_t. Передай 0, чтобы отключить
void setPeriod(int period);                     // период опроса в мс (по умолч. 3500)
void setLimit(int limit);                       // кол-во сообщений, которое обрабатывается за один запрос, 1..100. (по умолч. 10)
void setBufferSizes(uint16_t rx, uint16_t tx);  // установить размеры буфера на приём и отправку, по умолч. 512 и 512 байт (только для esp8266)
void skipUpdates();                             // пропустить непрочитанные сообщения
    
void setTextMode(uint8_t mode);                 // режим текста "для отправки": FB_TEXT, FB_MARKDOWN, FB_HTML (см. пример textMode)
void notify(bool mode);                         // true/false вкл/выкл уведомления от сообщений бота (по умолч. вкл)
void clearServiceMessages(bool state);          // удалять из чата сервисные сообщения о смене названия и закреплении сообщений (умолч. false)


// =============== ПАРСИНГ ===============
void attach(callback);                          // подключение функции-обработчика сообщений
void detach();                                  // отключение обработчика сообщений


// ================ ТИКЕР ================
uint8_t tick();                                 // проверка обновлений по таймеру
uint8_t tickManual();                           // ручная проверка обновлений


// ============== СООБЩЕНИЯ ==============
// отправить сообщение в указанный в setChatID чат/чаты ИЛИ передать id чата
uint8_t sendMessage(String msg);
uint8_t sendMessage(String msg, String id);

// редактировать сообщение (msgid) в указанном в setChatID чате ИЛИ передать id чата
uint8_t editMessage(int32_t msgid, String text);
uint8_t editMessage(int32_t msgid, String text, String id);

// ответить на сообщение с id (replyID) в указанный в setChatID чат ИЛИ указать чат
uint8_t replyMessage(String msg, int32_t replyID);
uint8_t replyMessage(String msg, int32_t replyID, String id);

// отправить стикер в указанный в setChatID чат/чаты ИЛИ передать id чата
uint8_t sendSticker(String stickerID);
uint8_t sendSticker(String stickerID, String id);

// ответить на callback текстом (text) и режимом (alert): FB_NOTIF - уведомление в чате, FB_ALERT - окно с кнопкой ОК
uint8_t answer(String text, bool alert);


// =============== УДАЛЕНИЕ ===============
// удалить сообщение с id (msgid) в указанном в setChatID чате ИЛИ передать id чата
// удаляет любые типы сообщений (текст, стикер, инлайн меню)
uint8_t deleteMessage(int32_t msgid);
uint8_t deleteMessage(int32_t msgid, String id);


// ============= ОБЫЧНОЕ МЕНЮ =============
// показать меню (menu) в указанном в setChatID чате/чатах ИЛИ передать id чата/чатов 
uint8_t showMenu(String menu);
uint8_t showMenu(String menu, String id);

// единоразовое меню (закроется при выборе) в текущем чате ИЛИ передать id чата
uint8_t showMenu(String menu, true);
uint8_t showMenu(String menu, String id, true);

// скрыть меню в указанном в setChatID чате/чатах ИЛИ передать id чата/чатов 
uint8_t closeMenu();
uint8_t closeMenu(String id);


// ======== ОБЫЧНОЕ МЕНЮ С ТЕКСТОМ =========
// сообщение (msg) + показать меню (menu) в указанном в setChatID чате/чатах ИЛИ передать id чата/чатов 
uint8_t showMenuText(String msg, String menu);
uint8_t showMenuText(String msg, String menu, String id);

// единоразовое меню (закроется при выборе)
uint8_t showMenuText(String msg, String menu, true);
uint8_t showMenuText(String msg, String menu, String id, true);

// сообщение (msg) + скрыть меню в указанном в setChatID чате/чатах ИЛИ передать id чата/чатов 
uint8_t closeMenuText(String msg);
uint8_t closeMenuText(String msg, String id);


// ============= ИНЛАЙН МЕНЮ =============
// сообщение (msg) с инлайн меню (menu) в указанном в setChatID чате/чатах ИЛИ передать id чата/чатов
uint8_t inlineMenu(String msg, String menu);
uint8_t inlineMenu(String msg, String menu, String id);

// редактировать меню (msgid) текстом (menu) в указанном в setChatID чате ИЛИ передать id чата
uint8_t editMenu(int32_t msgid, String menu);
uint8_t editMenu(int32_t msgid, String menu, String id);


// ======= ИНЛАЙН МЕНЮ С КОЛЛБЭКОМ =======
// сообщение (msg) с инлайн меню (menu) и коллбэком (cbck) в указанном в setChatID чате/чатах ИЛИ передать id чата/чатов
uint8_t inlineMenuCallback(String msg, String menu, String cbck);
uint8_t inlineMenuCallback(String msg, String menu, String cbck, String id);

// редактировать меню (msgid) текстом (menu) и коллбэком (cback) в указанном в setChatID чате ИЛИ передать id чата
uint8_t editMenuCallback(int32_t msgid, String menu, String cback);
uint8_t editMenuCallback(int32_t msgid, String menu, String cback, String id);


// ============== ГРУППОВЫЕ ==============
// для всех групповых команд бот должен быть админом в чате!

// установить имя группы в указанном в setChatID чате ИЛИ передать id чата
uint8_t setChatTitle(String& title);
uint8_t setChatTitle(String& title, String& id);

// установить описание группы в указанном в setChatID чате ИЛИ передать id чата
uint8_t setChatDescription(String& description);
uint8_t setChatDescription(String& description, String& id);

// закрепить сообщение с ID msgid в указанном в setChatID чате ИЛИ передать id чата
uint8_t pinMessage(int32_t msgid);
uint8_t pinMessage(int32_t msgid, String& id);

// открепить сообщение с ID msgid в указанном в setChatID чате ИЛИ передать id чата
uint8_t unpinMessage(int32_t msgid);
uint8_t unpinMessage(int32_t msgid, String& id);

// открепить все сообщения в указанном в setChatID чате ИЛИ передать id чата
uint8_t unpinAll();
uint8_t unpinAll(String& id);

// ================ ФАЙЛЫ ================
// скачать файл из чата
bool downloadFile(File &f, const String& url);
    
// отправить файл из байт-буфера buf длиной length, типа type и именем файла name в указанном в setChatID чате ИЛИ передать id чата
uint8_t sendFile(uint8_t* buf, uint32_t length, FB_FileType type, const String& name);
uint8_t sendFile(uint8_t* buf, uint32_t length, FB_FileType type, const String& name, const String& id);

// отправить файл File, типа type и именем файла name в указанном в setChatID чате ИЛИ передать id чата
uint8_t sendFile(File &file, FB_FileType type, const String& name);
uint8_t sendFile(File &file, FB_FileType type, const String& name, const String& id);

// редактировать файл из байт-буфера buf длиной length, типа type и именем файла name в сообщении msgid в указанном в setChatID чате ИЛИ передать id чата
// за исключением типа FB_VOICE!
uint8_t editFile(uint8_t* buf, uint32_t length, FB_FileType type, const String& name, int32_t msgid);
uint8_t editFile(uint8_t* buf, uint32_t length, FB_FileType type, const String& name, int32_t msgid, const String& id);

// редактировать файл File, типа type и именем файла name в указанном в сообщении msgid в setChatID чате ИЛИ передать id чата
// за исключением типа FB_VOICE!
uint8_t editFile(File &file, FB_FileType type, const String& name, int32_t msgid);
uint8_t editFile(File &file, FB_FileType type, const String& name, int32_t msgid, const String& id);

// где FB_FileType - тип файла
FB_PHOTO - картинка
FB_AUDIO - аудио
FB_DOC - документ
FB_VIDEO - видео
FB_GIF - анимация
FB_VOICE - голосовое сообщение

// ============= КОМАНДА API =============
// отправить команду API в указанном в setChatID чате ИЛИ передать id чата (id сам добавится в команду)
// (пример команды: "/sendSticker?sticker=123456")
uint8_t sendCommand(String& cmd);
uint8_t sendCommand(String& cmd, String& id);


// ================ СЕРВИС ===============
int32_t lastBotMsg();               // ID последнего отправленного ботом сообщения
int32_t lastUsrMsg();               // ID последнего отправленного юзером сообщения
String chatIDs;                     // указанная в setChatID строка, для отладки и редактирования списка

uint8_t sendRequest(String& req);   // отправить запрос (https://api.telegram.org/bot...)
void autoIncrement(boolean incr);   // авто инкремент сообщений (по умолч включен)
void incrementID(uint8_t val);      // вручную инкрементировать ID на val


// ============== СООБЩЕНИЕ ===============
// структура FB_msg
String& userID;     // ID юзера
String& username;   // ник юзера (в API это first_name)
bool isBot;         // юзер - бот

String& chatID;     // ID чата
int32_t messageID;  // ID сообщения
bool& edited;       // сообщение отредактировано

String& text;       // текст сообщения
String& replyText;  // текст ответа, если он есть
bool query;         // запрос
String& data;       // callback дата

bool isFile;        // это файл
String& fileName;   // имя файла
String& fileUrl;    // адрес файла для загрузки
bool OTA;           // файл - запрос на OTA обновление

uint32_t unix;      // время сообщения


// ================ ВРЕМЯ =================
FB_Time getTime(int16_t gmt);   // получить текущее время, указать часовой пояс (например Москва 3) в часах или минутах
bool timeSynced();              // проверка, синхронизировано ли время
uint32_t getUnix();             // получить текущее unix время

// структура FB_Time
uint8_t second;         // секунды
uint8_t minute;         // минуты
uint8_t hour;           // часы
uint8_t day;            // день месяца
uint8_t month;          // месяц
uint8_t dayWeek;        // день недели (пн..вс 1..7)
uint16_t year;          // год
String timeString();    // строка времени формата ЧЧ:ММ:СС
String dateString();    // строка даты формата ДД.ММ.ГГГГ


// ================ ОБНОВЛЕНИЕ =================
uint8_t update();       // ОТА обновление прошивки, вызывать внутри обработчика сообщения по флагу OTA
uint8_t updateFS();     // ОТА обновление SPIFFS, вызывать внутри обработчика сообщения по флагу OTA

// =============== СТАТУС ================
// Многие функции возвращают статус:
// 0 - ожидание
// 1 - ОК
// 2 - Переполнен
// 3 - Ошибка телеграм
// 4 - Ошибка подключения
// 5 - не задан chat ID
// 6 - множественная отправка, статус неизвестен
// 7 - не подключен обработчик
// 8 - ошибка файла


// =============== УТИЛИТЫ ===============
void FB_unicode(String &s);                 // перевести unicode
void FB_urlencode(String& s, String& dest); // urlencode из s в dest

int64_t FB_str64(const String &s);  // перевод из String в int64_t
String FB_64str(int64_t id);        // перевод из int64_t в String


// ========== ДЕФАЙНЫ НАСТРОЕК ===========
// объявлять ПЕРЕД подключением библиотеки
#define FB_NO_UNICODE       // отключить конвертацию Unicode для входящих сообщений (чуть ускорит программу)
#define FB_NO_URLENCODE     // отключить конвертацию urlencode для исходящих сообщений (чуть ускорит программу)
#define FB_NO_OTA           // отключить поддержку OTA обновлений из чата
#define FB_DYNAMIC          // включить динамический режим: библиотека дольше выполняет запрос, но занимает на 10 кб меньше памяти в SRAM

Использование

Отправка сообщений

Для отправки в чат (сообщения, стикеры, меню и так далее) обязательно должен быть указан ID чата, в который будет осуществляться отправка. Можно указать несколько ID через запятую, в пределах одной строки. Есть два способа указать ID:

  • Непосредственно в отправляющую функцию, у них у всех есть такой вариант (см. документацию выше)
bot.sendMessage("Hello!", "123456");            // в один чат
bot.sendMessage("Hello!", "123456,7891011");    // в два чата
  • Установить ID через setChatID() и все отправления пойдут в эти чат/чаты, если в отправляющей функции не указан другой ID
bot.setChatID("123456");             // один чат
//bot.setChatID("123456,7891011");   // несколько чатов
// ...
bot.sendMessage("Hello!");           // уйдёт в "123456"
bot.sendMessage("Hello!", "112233"); // уйдёт в "112233"

Примечание: Телеграм разделяет текст на несколько сообщений, если длина текста превышает ~4000 символов! Эти сообщения будут иметь разный messageID в чате.

Парсинг сообщений

Сообщения автоматически запрашиваются и читаются в tick(), при поступлении нового сообщения вызывается указанная функция-обработчик:

  • Создаём в скетче свою функцию вида void функция(FB_msg& сообщение)
  • Вызываем attach(функция)
  • Эта функция будет автоматически вызвана при входящем сообщении, если ID чата совпадает или не настроен
  • Если обработчик не подключен - сообщения не будут проверяться
  • Внутри этой функции можно пользоваться переданной переменной сообщение, которая имеет тип FB_msg (структура) и содержит в себе:
    • String userID - ID пользователя
    • String username - имя пользователя или канала
    • bool isBot - сообщение от бота
    • String chatID - ID чата
    • int32_t messageID - ID сообщения в чате
    • bool edited - сообщение отредактировано
    • String text - текст сообщения или попдпись к файлу
    • String replyText - текст ответа, если он есть
    • String data - callback данные из меню (если есть)
    • bool query - запрос
    • bool isFile - это файл
    • String fileName - имя файла
    • String fileUrl - адрес файла для загрузки
    • bool OTA - запрос на OTA обновление (получен .bin файл)
    • uint32_t unix - время сообщения

А также String toString() - вся информация из сообщения одной строкой, удобно для отладки (с версии 2.11)

Белый список

В библиотеке реализован механизм белого списка: можно указать в setChatID() ID чата (или нескольких через запятую), сообщения из которого будут приниматься. Сообщения из остальных чатов будут игнорироваться.

Тикер

Для опроса входящих сообщений нужно подключить обработчик сообщений и вызывать tick() в главном цикле программы loop(), опрос происходит по встроенному таймеру. По умолчанию период опроса установлен 3600 миллисекунд.

Можно опрашивать чаще (сменить период через setPeriod()), но лично у меня с ~2021 года сервер Телеграм стал отвечать не раньше, чем через ~3 секунды. Если запрашивать обновления чаще этого периода, программа зависает внутри tick() (внутри GET запроса) в ожидании ответа сервера на остаток от 3 секунд. При периоде ~3600 мс этого не происходит, поэтому я сделал его по умолчанию. Возможно это зависит от провайдера или страны.

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

void setup() {
  // подключаемся к WiFi
  bot.attach(newMsg);   // подключаем обработчик сообщений
}

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

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

Обращение к сообщениям

Для редактирования и удаления сообщений и меню, а также закрепления сообщений, нужно знать ID сообщения (его номер в чате):

  • ID входящего сообщения приходит в обработчик входящих сообщений
  • ID последнего принятого сообщения можно получить из lastUsrMsg()
  • ID последнего отправленного ботом сообщения можно получить из lastBotMsg()

Будьте внимательны с ID чата, у всех чатов своя нумерация сообщений!

Отправка стикеров

Для отправки стикера нужно знать ID стикера. Отправь нужный стикер боту @idstickerbot, он пришлёт ID стикера. Этот ID нужно передать в функцию sendSticker().

Меню

Примечание: для всех вариантов меню не производится url encode. Избегайте символов # и & или используйте уже закодированный url!

Для отправки меню используется строка с именами кнопок и специальным форматированием:

  • \t - горизонтальное разделение кнопок
  • \n - вертикальное разделение кнопок
  • Лишние пробелы вырезаются автоматически

Пример меню 3x1: "Menu1 \t Menu2 \t Menu3 \n Menu4"

Результат:

 _______________________
|       |       |       |
| Menu1 | Menu2 | Menu3 |
|_______|_______|_______|
|                       |
|       M e n u 4       |
|_______________________|

Обычное меню

Большое меню в нижней части чата.

showMenu("Menu1 \t Menu2 \t Menu3 \n Menu4");

Нажатие на кнопку отправляет текст с кнопки (поле сообщения text).

Инлайн меню

Меню в сообщении. Требует ввода имени меню.

inlineMenu("MyMenu", "Menu1 \t Menu2 \t Menu3 \n Menu4");

Нажатие на кнопку отправляет имя меню (поле сообщения text) и текст с кнопки (поле сообщения data).

Инлайн меню с коллбэком

Меню в сообщении. Позволяет задать каждой кнопке уникальный текст, который будет отправляться ботом вместе с именем меню. Список коллбэков перечисляется через запятую по порядку кнопок меню:

String menu1 = F("Menu 1 \t Menu 2 \t Menu 3 \n Back");
String cback1 = F("action1,action2,action3,back");
bot.inlineMenuCallback("Menu 1", menu1, cback1);

Нажатие на кнопку отправляет имя меню (поле сообщения text) и указанные данные (поле сообщения data).

  • (С версии 2.11) если callback задан как http/https адрес, кнопка автоматически станет кнопкой-ссылкой

Ответ на коллбэк

При нажатии на кнопку инлайн-меню боту отправляется коллбэк, в обработчике сообщения будет поднят флаг query. Сервер Телеграм будет ждать ответа. Ответить на коллбэк можно при помощи:

  • answer(текст, FB_NOTIF) - всплывающий текст-уведомление
  • answer(текст, FB_ALERT) - окно с предупреждением и кнопкой ОК

Отвечать нужно внутри обработчика сообщения! Пример:

void newMsg(FB_msg& msg) {
  if (msg.query) bot.answer("Hello!", true);
}

Если ничего не отвечать, библиотека сама отправит пустой ответ и "таймер" на кнопке исчезнет.

Модуль времени

В библиотеке есть тип данных FB_Time, который является структурой с полями:

uint8_t second;     // секунды
uint8_t minute;     // минуты
uint8_t hour;       // часы
uint8_t day;        // день месяца
uint8_t month;      // месяц
uint8_t dayWeek;    // день недели (пн..вс 1..7)
uint16_t year;      // год

При создании структуры можно указать unix время и часовой пояс в часах или минутах (например 3 часа ИЛИ 180 минут для Москвы (UTC+3:00), 330 минут для Индии (UTC+5:30)). После этого можно забирать нужные значения времени:

FB_Time t(1651694501, 3);
Serial.print(t.hour);
Serial.print(':');
Serial.print(t.minute);
Serial.print(':');
Serial.print(t.second);
Serial.print(' ');
Serial.print(t.day);
Serial.print(':');
Serial.print(t.month);
Serial.print(':');
Serial.println(t.year);

С версии 2.9 библиотека умеет выводить форматированное время (String):

Serial.print(t.timeString());   // ЧЧ:ММ:СС
Serial.print(' ');
Serial.println(t.dateString()); // ДД.ММ.ГГГГ

Время получения сообщения

В обработчике входящих сообщений у структуры FB_msg есть поле unix, оно хранит время сообщения в unix формате. Для перевода в более читаемый формат действуем по описанной выше схеме:

void newMsg(FB_msg& msg) {
  FB_Time t(msg.unix, 3);   // передали unix и часовой пояс
  Serial.print(t.timeString());
  Serial.print(' ');
  Serial.println(t.dateString());
}

Часы реального времени

В ответ на любое сообщение от бота сервер сообщает время отправки в формате unix. С версии 2.6 это время парсится библиотекой и счёт продолжается дальше при помощи стандартных функций времени. Таким образом достаточно один раз отправить сообщение после включения платы, чтобы библиотека синхронизировала часы. При дальнейших отправках время также будет синхронизироваться и уточняться, т.к. вычисляемое средствами esp время будет уходить (~2 секунды в сутки). Инструменты:

  • uint32_t getUnix() - вернёт текущее время в unix формате или 0, если время не синхронизировано.
  • bool timeSynced() - вернёт true если часы синхронизированы.
  • FB_Time getTime(gmt) - нужно передать свой часовой пояс, она вернёт FB_Time.

Таким образом получить время можно двумя способами (см. пример timeTest):

FB_Time t = bot.getTime(3);
// или
FB_Time t(bot.getUnix(), 3);

Обновление прошивки из чата

С версии библиотеки 2.13 появилось обновление прошивки "по воздуху" (OTA) через чат. Для обновления нужно:

  • Скомпилировать программу в файл: Arduino IDE/Скетч/Экспорт бинарного файла (файл .bin появится в папке со скетчем)
  • Отправить файл в чат с ботом
    • Можно добавить подпись к файлу
    • Файл может быть переслан из другого чата
  • Файл будет обработан как обычное входящее сообщение от пользователя msg
    • Подпись к файлу можно получить из поля msg.text
    • Название файла можно получить из поля msg.fileName
    • Будет поднят флаг msg.OTA (в том случае, если файл имеет расширение .bin)
  • Для запуска процесса обновления прошивки нужно вызвать update() внутри обработчика сообщений
    • В версии 2.20 появилась возможность обновления SPIFFS - нужно вызвать updateFS()
  • В тот же чат чат будет отправлен статус обновления (OK или error)
  • После успешного обновления esp перезагрузится

Примеры сценариев обновления прошивки

// обновить, если просто прислали bin файл
if (msg.OTA) bot.update();

// обновить, если файл имеет нужную подпись
if (msg.OTA && msg.text == "update") bot.update();

// обновить, если файл имеет нужное имя
if (msg.OTA && msg.fileName == "update.bin") bot.update();

// обновить, если прислал известный человек (админ)
if (msg.OTA && msg.chatID == "123456") bot.update();

Примеры сценариев обновления SPIFFS

// обновить SPIFFS, если пришёл файл, в имени которого есть слово spiffs
if (msg.OTA && msg.fileName.indexOf("spiffs") > 0) bot.updateFS();

Сжатие бинарника

Если прошивка весит много - её можно сжать в gzip:

  • Рекомендуемый уровень сжатия - 9
  • Имя файла должно оканчиваться на .bin.gz
  • Файл точно так же отправляется в чат с ботом или пересылается ему
  • В прошивке перед подключением всех библиотек нужно объявить #define ATOMIC_FS_UPDATE

Оформление текста

Библиотека поддерживает оформление текста в сообщениях. Разметка оформления выбирается при помощи setTextMode(mode), где mode:

  • FB_TEXT - по умолчанию (оформление отключено)
  • FB_MARKDOWN - разметка Markdown v2
  • FB_HTML - разметка HTML

Доступные теги описаны в API Telegram. Например для Markdown:

bot.setTextMode(FB_MARKDOWN);
bot.sendMessage(F("*Bold*, ~Strike~, `code`, [alexgyver.ru](https://alexgyver.ru/)"));

Выведет в чат: Bold, Strike, code, alexgyver.ru

Внимание! В режиме FB_MARKDOWN нельзя использовать в сообщениях символы ! + #, сообщение не отправится. Возможно получится исправить в будущем (проблема urlencode и экранирования зарезервированных символов).

Отправка файлов (v2.20+)

Отправлять можно файлы следующих типов (тип указывается при отправке), в телеграм это разные типы сообщений:

  • FB_PHOTO - картинка (jpg, png...)
  • FB_AUDIO - аудио (mp3, wav...)
  • FB_DOC - документ (txt, pdf...)
  • FB_VIDEO - видео (avi, mp4...)
  • FB_GIF - анимация (gif)
  • FB_VOICE - голосовое сообщение (ogg)

Редактировать можно все указанные выше типы сообщений кроме FB_VOICE!

При отправке нужно указать имя файла с таким же расширением, с каким он создан или хранится в памяти.

Библиотека поддерживает два варианта отправки файлов: из буфера (оперативной памяти) и из SPIFFS.

Файл из буфера

Для отправки нужно передать буфер, его размер, тип файла, его размер и ID чата (без указания ID чата будет использован чат из setChatID). Для редактирования нужно также указать ID сообщения:

uint8_t sendFile(uint8_t* buf, uint32_t length, FB_FileType type, const String& name, const String& id);
uint8_t editFile(uint8_t* buf, uint32_t length, FB_FileType type, const String& name, int32_t msgid, const String& id);

Отправим текст в виде текстового файла, таким образом можно вести и выгружать логи:

  char buf[] = "Hello, World!";
  bot.sendFile((byte*)buf, strlen(buf), FB_DOC, "test.txt", CHAT_ID);

Отправим фотографию с камеры (см. пример sendCamPhoto):

  frame = esp_camera_fb_get();
  bot.sendFile((byte*)frame->buf, frame->len, FB_PHOTO, "photo.jpg", CHAT_ID);

Файл из памяти

Вместо буфера и его размера функция отправки принимает файл, остальное - как при отправке из буфера:

uint8_t sendFile(File &file, FB_FileType type, const String& name, const String& id);
uint8_t editFile(File &file, FB_FileType type, const String& name, int32_t msgid, const String& id);

Для работы с файлами таким образом нужно подключить библиотеку, ккоторая определяет класс File, например SPIFFS.h или LittleFS.h.

Подключать библиотеку нужно ДО (выше по коду) подключения FastBot! Иначе функции с File будут недоступны.

Отправим картинку из памяти:

  File file = LittleFS.open("/test.png", "r");
  bot.sendFile(file, FB_PHOTO, "test.png", CHAT_ID);
  file.close();

Скачивание файлов (v2.20+)

С версии 2.20 в объекте входящего сообщения присутствует ссылка на файл, если в сообщении есть файл. Это позволяет скачать файл во внутреннюю память.

Для скачивания файлов средствами FastBot нужно подключить библиотеку, которая определяет класс File, например SPIFFS.h или LittleFS.h.

Подключать библиотеку нужно ДО (выше по коду) подключения FastBot! Иначе функции с File будут недоступны.

Для скачивания файла нужно открыть/создать файл с правами для записи и передать его в downloadFile() вместе со ссылкой на файл.

void newMsg(FB_msg& msg) {
  if (msg.isFile) {                     // это файл
    Serial.print("Downloading ");
    Serial.println(msg.fileName);

    String path = '/' + msg.fileName;   // путь вида /filename.xxx
    File f = LittleFS.open(path, "w");  // открываем для записи
    bool status = bot.downloadFile(f, msg.fileUrl);  // загружаем
    Serial.println(status ? "OK" : "Error");    // статус
  }
}

Трюки

Перезагрузка

Сообщения отмечаются прочитанными при следующем (относительно текущего обработчика сообщений) обновлении в tick(), то есть спустя как минимум настроенный тайм-аут. Если хочется перезагрузить esp по команде, то вот такая конструкция

void message(FB_msg &msg) {
  if (msg.text == "restart") ESP.restart();
}

Приведёт к бутлупу (бесконечной перезагрузке), потому что сообщение не отметится прочитанным. Можно поднять флаг, по которому уходить в перезагрузку, предварительно вызвав tickManual:

bool res = 0;
void message(FB_msg &msg) {
  if (msg.text == "restart") res = 1;
}
void loop() {
  if (res) {
    bot.tickManual();
    ESP.restart();
  }
}

Пропуск "пропущенных" сообщений на основе времени

В библиотеке есть функция skipUpdates, позволяющая пропустить все непрочитанные сообщения. Но иногда бывает удобно ориентироваться по времени.

Если нужно проигнорировать сообщения, отправленные юзером в то время как бот был оффлайн (или выключен), то можно поступить так:

  • Запомнить unix-время, когда бот вышел в онлайн
  • Сравнивать время текущего сообщения с ним. Если оно меньше - игнорировать сообщение

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

uint32_t startUnix;     // храним время

void setup() {
  //connectWiFi();

  bot.attach(newMsg);
  bot.sendMessage("start", "1234"); // отправить сообщение, чтобы получить время
  startUnix = bot.getUnix();        // запомнили
}

// обработчик сообщений
void newMsg(FB_msg& msg) {
  if (msg.unix < startUnix) return; // игнорировать сообщения
  // ....
}

Версии

  • v1.0

  • v1.1 - оптимизация

  • v1.2 - можно задать несколько chatID и отправлять в указанный чат

  • v1.3 - добавлена возможность задать текст при открытии и закрытии меню

  • v1.3.1 - исправлены ошибки с 1.3

  • v1.4 - добавлена возможность удалять сообщения

  • v1.5 - оптимизация, возможность смены токена, новый парсинг сообщений (id, имя, текст)

  • v1.5.1 - получаем также ID сообщения

  • v1.6 - добавлен режим FB_DYNAMIC_HTTP, чтение имени пользователя

  • v1.7:

    • Убрал динамический режим FB_DYNAMIC_HTTP, работает слишком медленно
    • Исправил warningи
    • Починил работу бота в "группах" (отрицательный ID чата)
    • Оптимизация памяти
    • Ускорил работу
    • Пофиксил работу через раз в сценарии "эхо"
  • v2.0:

    • Убрал минимум в 3200 мс
    • Добавил обработку Юникода (русский язык, эмодзи). Спасибо Глебу Жукову!
    • Из меню удаляются лишние пробелы, работать стало проще
    • Поддержка esp32
    • Большая оптимизация
    • Добавил коллбэки в inlineMenu
    • Добавил ID юзера
    • Добавил редактирование сообщений и кучу всего
  • v2.1:

    • Ещё оптимизация
    • Добавил форматирование текста (markdown, html)
    • Добавил ответ на сообщение
  • v2.2:

    • Большая оптимизация памяти и производительности
    • Добавил notify() - уведомления от сообщений бота
    • Добавил единоразовый показ клавиатуры
  • v2.3: Небольшая оптимизация

  • v2.4: Добавил url encode для текста сообщений

  • v2.5: Добавил флаги в FB_msg: сообщение отредактировано и сообщение отправлено ботом. Улучшил парсинг текста

  • v2.6: Добавил встроенные часы реального времени

  • v2.7: Добавил отправку стикеров

  • v2.8: Убрал лишний вывод в сериал, GMT можно в минутах

  • v2.9: Исправлена бага в парсинге, парсинг ускорен, добавлен вывод форматированного времени, добавлена фамилия и время сообщения

  • v2.10: Добавлены функции для изменения названия и описания чата, закрепления и открепления сообщений. Убраны edit/deleteMessageID, editMenuID

  • v2.11:

    • Оптимизация, исправление багов
    • Callback data теперь парсится отдельно в data
    • Переделана работа с callback
    • Добавлен toString() для FB_msg для отладки
    • В callback добавлена обработка url адресов
    • Убраны first_name и last_name (с сохранением легаси)
    • usrID и ID переименованы в userID и messageID (с сохранением легаси)
    • Окончательно убран старый обработчик входящих сообщений
  • v2.12: поправлены примеры, исправлен парсинг isBot, переделан механизм защиты от длинных сообщений, переделана инициализация

  • v2.13: Оптимизация памяти. Добавил OTA обновление

  • v2.14: Улучшен парсинг строки с ID, добавил отключение OTA, добавил парсинг названия группы/канала в username

  • v2.15: Заплатка для кривой библиотеки ESP32

  • v2.16: добавлен вывод fileName, пофикшены неотправляемые сообщения в Markdown режиме

  • v2.17: вывод текста сообщения, на которое ответил юзер + корректная работа с menu в группах

  • v2.17.1: мелкий фикс #12

  • v2.18: добавлен режим FB_DYNAMIC: библиотека дольше выполняет запрос, но занимает на 10 кб меньше памяти в SRAM

  • v2.19: поддержка OTA со сжатием gzip

  • v2.20:

    • добавил OTA обновление SPIFFS + пример
    • добавил вывод url файла для скачивания из чата + пример
    • добавил возможность скачать файл из чата
    • добавил возможность отправки файлов (из SPIFFS или буфера) + пример
    • добавил возможность редактирования файлов (из SPIFFS или буфера)
    • добавил пример отправки фото с камеры ESP32-CAM
  • v2.21: ускорил отправку файлов ботом в чат

  • v2.22: мелкая оптимизация, исправил ошибку компиляции при дефайне FB_NO_OTA

  • v2.23: пофиксил источник реального времени на editMessage

  • v2.24: фикс отправки больших файлов #17

  • v2.25: добавил skipUpdates - пропуск непрочитанных сообщений

  • v2.26: фикс некорректного отображения цифр после русских букв #37

Баги и обратная связь

При нахождении багов создавайте Issue, а лучше сразу пишите на почту [email protected]
Библиотека открыта для доработки и ваших Pull Request'ов!

При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать:

  • Версия библиотеки
  • Какой используется МК
  • Версия SDK (для ESP)
  • Версия Arduino IDE
  • Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде
  • Какой код загружался, какая работа от него ожидалась и как он работает в реальности
  • В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код

More Repositories

1

GyverPortal

Простой конструктор веб интерфейса для esp8266 и ESP32
C
298
star
2

GyverHub

Панель управления для ESP8266, ESP32 и других Arduino. Конструктор интерфейса. Интеграция в умный дом. Esp8266, esp32 and Arduino Dashboard library
C
297
star
3

EncButton

Лёгкая и очень функциональная библиотека для энкодера с кнопкой, энкодера или кнопки с Arduino
C++
133
star
4

GyverOLED

Лёгкая и быстрая библиотека для OLED дисплея
C++
119
star
5

EasyHID

Библиотека программного USB клавиатуры и мыши для Arduino Nano/UNO/Mega и прочих
C
112
star
6

QuickCharge

Библиотека для управления адаптерами с поддержкой технологии QuickCharge 2.0/3.0
C++
45
star
7

microDS18B20

Легкая и удобная в обращении библиотека для работы с 1-Wire термометрами DS18B20
C++
45
star
8

GyverPID

Библиотека PID регулятора для Arduino
C++
42
star
9

GyverStepper

Производительная библиотека для управления шаговыми моторами с Arduino. Плавное движение. Многоосевое планирование траектории
C++
39
star
10

GyverOS

Библиотека лёгкого диспетчера задач для Arduino
C++
38
star
11

TimerMs

Многофункциональный программный таймер на системном таймере millis() для Arduino
C++
37
star
12

microLED

microLED - ультра-лёгкая библиотека для работы с адресной лентой/матрицей
C++
33
star
13

FastBot2

Очень быстрая и лёгкая библиотека Telegram бота для Arduino, ESP8266, ESP32
C++
32
star
14

Gyver433

Библиотека для радиомодулей 433 МГц и Arduino
C++
28
star
15

GyverLibs

27
star
16

SimplePortal

Простой менеджер WiFi для esp8266 для задания логина-пароля WiFi и режима работы
C++
26
star
17

mString

РЕЗКАЯ КАК ПОНОС И ЛЁГКАЯ КАК ПЁРЫШКО ЗАМЕНА STRING
C++
25
star
18

EEManager

Библиотека для удобной работы с EEPROM и уменьшения износа
C++
24
star
19

GRGB

Библиотека для управления RGB светодиодами и лентами для Arduino. Облегчённая версия библиотеки GyverRGB
C++
23
star
20

GyverNTP

Библиотека для получения точного времени с NTP сервера для esp8266/esp32
C++
22
star
21

GyverButton

Библиотека для многофункциональной отработки нажатия кнопки
C++
22
star
22

GyverTM1637

Бибилотека для 7 сегментного дисплея на чипе TM1637 с кучей приколюх
C++
22
star
23

SunPosition

Библиотека для определения положения солнца по геолокации и времени для Arduino
C
22
star
24

GyverMAX7219

Cамая резкая библиотека для матриц MAX7219 на диком западе
C++
21
star
25

GyverFilters

Библиотека с некоторыми удобными фильтрами для Arduino
C++
21
star
26

microDS3231

Лёгкая библиотека для работы с RTC DS3231 для Arduino
C++
20
star
27

ServoSmooth

Библиотека для плавного управления сервоприводами с Arduino
C++
20
star
28

GParser

Простой и быстрый парсер строк в отдельные подстроки и числа для Arduino
C++
20
star
29

GyverBME280

Лёгкая библиотека для работы с BME280 по I2C для Arduino
C++
19
star
30

GyverNTC

Библиотека для работы с NTC термисторами по закону Стейнхарта-Харта
C++
19
star
31

GyverPWM

Библиотека для расширенной генерации ШИМ на ATmega328 (Arduino UNO/Nano/Pro Mini...)
C++
18
star
32

GyverBus

Библиотека для общения по протоколу GBUS
C++
17
star
33

GyverPower

GyverPower - библиотека для управления энергопотреблением МК AVR
C++
16
star
34

GyverTimers

Настройка и контроль прерываний по аппаратным таймерам ATmega328p, ATmega2560
C++
16
star
35

GyverGFX

Лёгкая библиотека двухмерной графики для дисплеев и матриц
C++
16
star
36

GyverINA

Лёгкая библиотека для INA219 и INA226
C++
16
star
37

NecDecoder

Лёгкая библиотека для декодирования ИК протокола NEC (Японский вариант)
C++
14
star
38

UnixTime

Конвертер unix time stamp в дату и время и наоборот для Arduino
C++
14
star
39

Tachometer

Библиотека тахометра для Arduino без привязки к железу
C++
14
star
40

VolAnalyzer

Библиотека для амплитудного анализа звука на Arduino
C++
13
star
41

GyverMotor

Библиотека для удобного управления коллекторными моторами через драйвер
C++
13
star
42

VirtualButton

Библиотека с логикой обработки кнопки (виртуальная кнопка) для Arduino
C++
13
star
43

GyverIO

Быстрые функции для работы с пинами AVR, ESP8266, ESP32
C++
13
star
44

AccelMotor

Библиотека для расширенного управления и стабилизации мотора с энкодером для Arduino
C++
13
star
45

Hamming

Библиотека для упаковки и распаковки данных по алгоритму Хэмминга (избыточные данные для восстановления)
C++
13
star
46

FFT_C

Библиотека преобразования Фурье на С (для esp8266)
C
12
star
47

Settings

Простой конструктор вебморды для настроек esp8266/esp32
C
12
star
48

GyverHC595

Библиотека для управления каскадом сдвиговых регистров 74HC595 для Arduino
C++
11
star
49

GyverUART

Лёгкая библиотека для работы с последовательным портом
C++
11
star
50

AsyncStream

Библиотека для асинхронного чтения объектов Stream (Serial итд) для Arduino
C++
11
star
51

GSON

Парсер и сборщик данных в формате JSON для Arduino
C++
11
star
52

BitPack

Библиотека для упаковки битовых флагов в байтовый массив (экономия места)
C++
11
star
53

Forecaster

Библиотека для определения прогноза погоды по давлению для Arduino
C++
11
star
54

GyverHX711

Библиотека работы с датчиками (АЦП) HX711 для Arduino
C++
10
star
55

GyverTimer

Полноценный таймер на базе системных millis() / micros()
C++
10
star
56

GyverEncoder

Библиотека для расширенной работы с энкодером и Arduino
C++
10
star
57

microWire

Лёгкая библиотека со стандартным набором инструментов для работы с аппаратным I2C
C++
10
star
58

GyverJoy

Библиотека для аналогового джойстика Arduino
C++
10
star
59

StringUtils

Набор инструментов для работы со строками
C++
10
star
60

FileData

Замена EEPROM для ESP8266/32 для хранения любых данных в файлах
C++
10
star
61

Random16

Библиотека для быстрой генерации 16 бит случайных чисел
C++
9
star
62

GyverMAX6675

Лёгкая библиотека для драйвера термопары MAX6675
C++
9
star
63

GyverDimmer

Библиотека для управления симисторным диммером с Arduino
C++
9
star
64

MicroUART

Лёгкая реализация UART для ATmega328 и подобных из этого поколения
C++
9
star
65

SoftServo

Библиотека для программного управления Servo (на базе millis/micros)
C++
9
star
66

GyverFIFO

Лёгкий универсальный кольцевой буфер для Arduino
C++
8
star
67

AnalogKey

Библиотека для работы с аналоговой клавиатурой для Arduino
C++
8
star
68

GyverHub-projects

База проектов на GyverHub
8
star
69

SevenSegmentsDisp

Набор быстрых и удобных библиотек для работы с семисегментными дисплеями совместно с Arduino
C++
8
star
70

CharDisplay

Графический движок на символах: полноценное рисование, индикаторы загрузки, графики для Arduino
C++
8
star
71

ProcessingPlotter

Простая библиотека для вывода графиков на Processing
Processing
7
star
72

GyverLBUF

Линейный буфер для Arduino
C++
7
star
73

Psychrometer

Библиотека для определения влажности по сухому и мокрому термометру для Arduino
C++
7
star
74

Approxy

Линейный аппроксиматор
C++
7
star
75

Stamp

Библиотека для хранения и манипуляции со временем
C++
7
star
76

buildTime

Парсинг и получение даты и времени компиляции из __DATE__ и __TIME__ для Arduino
C
7
star
77

EspSleep

Библиотека позволяет esp8266 уходить в сон на любой период (до ~585 миллиардов лет)
C++
7
star
78

directADC

Библиотека для расширенного ручного управления АЦП и компаратором ATmega328
C++
7
star
79

GyverRelay

Библиотека классического релейного регулятора для Arduino
C++
7
star
80

GyverWDT

Библиотека для управления WDT на AVR ATmega328p/32U4/2560 & ATtiny85/84/167
C++
7
star
81

GyverSegment

Самая мощная библиотека для работы с дисплеями на 7-сегментных индикаторах
C++
7
star
82

GyverTransfer

Библиотека для передачи данных по интерфейсу GyverTransfer (GT). Передача для Arduino по одному проводу
C++
7
star
83

PWMrelay

Библиотека для генерации низкочастотного ШИМ сигнала для реле (для ПИД регуляторов и проч.)
C++
6
star
84

directTimers

Библиотека для расширенного ручного управления таймерами ATMega2560, ATMega328, ATMega32u4
C++
6
star
85

OVS

Библиотека для повышения разрядности измерений Arduino (оверсэмплинг)
C++
6
star
86

fixed

Реализация вычислений с фиксированной точкой для Arduino
C++
5
star
87

GyverHTU21D

Лёгкая библиотека для датчика температуры и влажности HTU21D
C++
5
star
88

CRT

Библиотека с набором функций для CRT коррекции светодиодов для Arduino
C
5
star
89

Clap

Библиотека для распознавания хлопков в микрофон для Arduino
C++
4
star
90

gyverlibs.github.io

HTML
4
star
91

GyverDB

Простая база данных для Arduino
C++
4
star
92

TimeRandom

Библиотека для генерации набора случайных чисел с привязкой ко времени
C++
4
star
93

GyverDS18

Лёгкая библиотека для термометров Dallas DS18b20, обновлённая и более удобная версия библиотеки microDS18B20
C++
4
star
94

GyverBlinker

Библиотека для мигания светодиодом и планирования событий по таймеру
C++
4
star
95

GyverHub-web

Веб-приложение платформы GyverHub
HTML
4
star
96

Pairs

Лёгкая библиотека для хранения данных в текстовом виде в формате ключ:значение
C++
4
star
97

GyverBeeper

Библиотека для генерации писка по таймеру
C++
4
star
98

GTL

Набор шаблонных инструментов
C++
3
star
99

GyverHub-example

Образец репозитория с проектом
C++
3
star
100

GyverHub-plugins

База виджетов GyverHub
JavaScript
3
star