From ac20905220a75e30b36dd47c0f6c406a379b1bfd Mon Sep 17 00:00:00 2001 From: Mit4el Date: Wed, 8 May 2024 00:37:21 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D1=80=D0=BE=D1=88=D0=B8=D0=B2=D0=BA?= =?UTF-8?q?=D0=B0=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20telegram?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/exec/Telegram_v2/Telegram_v2.cpp | 174 ++++++++++++++++++- src/modules/exec/Telegram_v2/modinfo.json | 11 +- 2 files changed, 174 insertions(+), 11 deletions(-) diff --git a/src/modules/exec/Telegram_v2/Telegram_v2.cpp b/src/modules/exec/Telegram_v2/Telegram_v2.cpp index b7b5e170..83532fa0 100644 --- a/src/modules/exec/Telegram_v2/Telegram_v2.cpp +++ b/src/modules/exec/Telegram_v2/Telegram_v2.cpp @@ -1,5 +1,6 @@ #include "Global.h" #include "classes/IoTItem.h" +#include "UpgradeFirm.h" // #define FB_NO_UNICODE // #define FB_NO_URLENCODE // #define FB_NO_OTA @@ -27,7 +28,9 @@ String _token; String _chatID; bool _autos; bool _initSD; - +bool _resolveOTA; +bool fl_rollback; +int8_t _OTAstate = -1; struct ButtonMenu { String message = ""; @@ -35,7 +38,15 @@ struct ButtonMenu String setId = ""; String value = ""; }; - +/* +struct updateFirm { + String settingsFlashJson; + String configJson; + String layoutJson; + String scenarioTxt; + String chartsData; +}; +*/ std::map mapBtnMenu; // std::map mapBtnInline; // @@ -51,8 +62,11 @@ public: { jsonRead(parameters, "token", _token); jsonRead(parameters, "autos", _autos); + if (!jsonRead(parameters, "OTA", _resolveOTA)) + _resolveOTA = 0; jsonRead(parameters, "receiveMsg", _receiveMsg); jsonRead(parameters, "chatID", _chatID); + fl_rollback = false; instanceBot(); // _myBot->setTextMode(FB_MARKDOWN); _myBot->attach(telegramMsgParse); @@ -72,6 +86,37 @@ public: if (_receiveMsg && isNetworkActive()) { _myBot->tick(); + if (fl_rollback) + { + _myBot->tickManual(); // Чтобы отметить сообщение прочитанным + if (Update.rollBack()) + { + SerialPrint("I", F("Update"), F("Откат OTA успешно выполнен")); + _myBot->sendMessage("Откат OTA запущен, плата будет перезагружена", _chatID); + ESP.restart(); + } + else + { + SerialPrint("E", F("Update"), F("Откат OTA не выполнен!")); + _myBot->sendMessage("Откат OTA не выполнен!", _chatID); + } + } + // была попытка OTA обновления. Обновляемся после ответа серверу! + if (_OTAstate >= 0) + { + _myBot->tickManual(); // Чтобы отметить сообщение прочитанным + String ota; + if (_OTAstate == 0) + ota = F("Error"); + else if (_OTAstate == 1) + ota = F("No updates"); + else if (_OTAstate == 2) + ota = F("OK"); + _myBot->sendMessage(ota, _chatID); + if (_OTAstate == 2) + ESP.restart(); + _OTAstate = -1; + } } // Далее вызов doByInterval для обработки комманд IoTItem::loop(); @@ -302,6 +347,8 @@ public: //============================================================================= void static telegramMsgParse(FB_msg &msg) { + static String OTAfilepath = ""; + static uint8_t typeOTA = 0; // FB_msg msg; SerialPrint("i", F("Telegram"), "chat ID: " + msg.chatID + ", msg: " + msg.text); // _myBot->setChatID(_chatID); @@ -309,9 +356,84 @@ public: { _chatID = msg.chatID; } + // -------------- Обработка сообщения об откате -------------- + // ------------------------------------------------------------------------- + if (msg.text.indexOf("rollback") != -1 && msg.chatID == _chatID) + { + _myBot->inlineMenu("Вы уверены, что хотите откатить прошивку? " + jsonReadStr(settingsFlashJson, F("name")) + " \n OTA_roll", F("Rollback \t Cancel")); + } + else if (msg.text.indexOf("OTA_roll") != -1) + { + // удаляем последнее сообщение от бота + _myBot->deleteMessage(_myBot->lastBotMsg()); + if (msg.data.indexOf("Rollback") != -1) + { + if (Update.canRollBack()) + { + fl_rollback = true; + } + else + { + SerialPrint("E", F("Update"), F("Откат OTA не возможен!")); + _myBot->sendMessage("Откат OTA не возможен!", _chatID); + } + } + } + // -------------- Обработка файлов *.bin для прошивки по OTA -------------- + // ------------------------------------------------------------------------- + else if (msg.OTA && _resolveOTA && msg.chatID == _chatID) + { + // _myBot->editMessage(_myBot->lastUsrMsg(), "firmware...", _chatID); + OTAfilepath = msg.fileUrl; + if (msg.fileName.indexOf("littlefs") != -1) + typeOTA = FB_SPIFFS; + else if (msg.fileName.indexOf("firmware") != -1) + typeOTA = FB_FIRMWARE; + else + SerialPrint("E", F("Update"), "Unknown file: " + msg.fileName); + _myBot->inlineMenu("Вы уверены, что хотите прошить плату? " + jsonReadStr(settingsFlashJson, F("name")) + "\n OTA_firmware", F("Firmware \t Cancel")); + } + else if (msg.text.indexOf("OTA_firmware") != -1) + { + // удаляем последнее сообщение от бота + _myBot->deleteMessage(_myBot->lastBotMsg()); + if (msg.data.indexOf("Firmware") != -1) + { + putUserDataToRam(); + if (typeOTA == FB_SPIFFS) + { + if (_updateFS((String *)&OTAfilepath) == 1) + { + saveUserDataToFlash(); + SerialPrint("!!!", F("Update"), "Start upgrade FS... "); + } + else + { + SerialPrint("E", F("Update"), F("FS Path error")); + _myBot->sendMessage("FS Path error!", _chatID); + } + } + else if (typeOTA == FB_FIRMWARE) + { + if (_update((String *)&OTAfilepath) == 1) + { + saveUserDataToFlash(); + SerialPrint("!!!", F("Update"), "Start upgrade BUILD... "); + } + else + { + SerialPrint("E", F("Update"), F("Build Path error")); + _myBot->sendMessage("Build Path error!", _chatID); + } + } + } + OTAfilepath = ""; + typeOTA = 0; + } + // -------------- Обработка кнопок меню созданного в сценарии -------------- // ------------------------------------------------------------------------- - if (auto search = mapBtnMenu.find(msg.text); search != mapBtnMenu.end()) + else if (auto search = mapBtnMenu.find(msg.text); search != mapBtnMenu.end()) { String outMsg; outMsg = mapBtnMenu[msg.text]->message; @@ -325,7 +447,7 @@ public: } if (mapBtnMenu[msg.text]->setId != "") { - //outMsg += ", " + mapBtnMenu[msg.text]->setId + "=" + mapBtnMenu[msg.text]->value; + // outMsg += ", " + mapBtnMenu[msg.text]->setId + "=" + mapBtnMenu[msg.text]->value; generateOrder(mapBtnMenu[msg.text]->setId, mapBtnMenu[msg.text]->value); } SerialPrint("i", F("Telegram"), "chat ID: " + _chatID + ", msg: " + String(outMsg)); @@ -348,12 +470,12 @@ public: if (item) { outMsg += ": " + item->getValue(); - //SerialPrint("i", F("Telegram"), "chat ID: " + _chatID + ", msg: " + String(msg.data)); + // SerialPrint("i", F("Telegram"), "chat ID: " + _chatID + ", msg: " + String(msg.data)); } } if (mapBtnInline[msg.data]->setId != "") { - //outMsg += ", " + mapBtnInline[msg.data]->setId + "=" + mapBtnInline[msg.data]->value; + // outMsg += ", " + mapBtnInline[msg.data]->setId + "=" + mapBtnInline[msg.data]->value; generateOrder(mapBtnInline[msg.data]->setId, mapBtnInline[msg.data]->value); } SerialPrint("i", F("Telegram"), "chat ID: " + _chatID + ", msg: " + String(outMsg)); @@ -638,6 +760,46 @@ public: } mapBtnInline.clear(); } + + // ===================== OTA ===================== + // ОТА обновление, вызывать внутри обработчика сообщения по флагу OTA + uint8_t static _update(String *_file_ptr, __attribute__((unused)) uint8_t type = FB_FIRMWARE) + { +#ifndef FB_NO_OTA + if (!_file_ptr) + return 8; + uint8_t OTAflag = type; + _myBot->sendMessage((type == FB_FIRMWARE) ? F("OTA firmware...") : F("OTA spiffs..."), _chatID); + +#ifdef ESP8266 + ESPhttpUpdate.rebootOnUpdate(false); +#ifdef FB_DYNAMIC + BearSSL::WiFiClientSecure client; + client.setInsecure(); +#endif + if (OTAflag == FB_FIRMWARE) + _OTAstate = ESPhttpUpdate.update(client, *_file_ptr); + else if (OTAflag == FB_SPIFFS) + _OTAstate = ESPhttpUpdate.updateFS(client, *_file_ptr); +#else + WiFiClientSecure client; + client.setInsecure(); + httpUpdate.rebootOnUpdate(false); + if (OTAflag == FB_FIRMWARE) + _OTAstate = httpUpdate.update(client, *_file_ptr); + else if (OTAflag == FB_SPIFFS) + _OTAstate = httpUpdate.updateSpiffs(client, *_file_ptr); +#endif +#endif + return 1; + } + + // ОТА обновление SPIFFS, вызывать внутри обработчика сообщения по флагу OTA + uint8_t static _updateFS(String *_file_ptr) + { + return _update(_file_ptr, FB_SPIFFS); + } + ~Telegram_v2() { clearMapMenu(); diff --git a/src/modules/exec/Telegram_v2/modinfo.json b/src/modules/exec/Telegram_v2/modinfo.json index 6c7e25f1..905663bd 100644 --- a/src/modules/exec/Telegram_v2/modinfo.json +++ b/src/modules/exec/Telegram_v2/modinfo.json @@ -11,11 +11,11 @@ "page": "", "descr": "", "int": 10, - "token": "", "autos": 1, "receiveMsg": 1, - "chatID": "" + "chatID": "", + "OTA": 0 }], "about": { @@ -24,18 +24,19 @@ "authorGit": "https://github.com/Mit4el", "specialThanks": "", "moduleName": "Telegram_v2", - "moduleVersion": "3.0", + "moduleVersion": "3.1", "usedRam": { "esp32_4mb": 37, "esp8266_4mb": 37 }, "title": "Телеграм-Бот v2", - "moduleDesc": "Добавляет возможность отправлять сообщения от имени бота контакту в Телеграм-чате и получать команды.", + "moduleDesc": "Добавляет возможность отправлять сообщения от имени бота контакту в Телеграм-чате и получать команды. Можно использовать для обновление ОТА, для этого отправить файл firmware.bin или littlefs.bin в чат боту", "propInfo": { "token": "Токен для авторизации бота в системе Telegram", "autos": "Автоматически(1) или нет(0) запоминать ChatID по входящим сообщениям. Т.е. бот будет информировать тех, кто последний прислал сообщение.", "receiveMsg": "Обрабатывать(1) или нет(0) входящие сообщения.", - "chatID": "ИД диалога с контактом. Необходим для отправки сообщений именно вам." + "chatID": "ИД диалога с контактом. Необходим для отправки сообщений именно вам.", + "OTA": "Разрешена(1) или запрещена(0) прошивка через чат бота. Если разрешена, то файл принимается только от пользователя прописанного в chatID или от всех если autos=1" }, "funcInfo": [ {