From 8cd8a36bac919ab5fb83639a2d1e3547e624e3b7 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 2 Jul 2024 11:38:31 +0700 Subject: [PATCH] Add support more Arduino boards for OTA firmware update --- README.md | 19 +++---- .../CloudStorage/Async/Callback/OTA/OTA.ino | 17 ++++-- .../CloudStorage/Async/NoCallback/OTA/OTA.ino | 17 ++++-- examples/CloudStorage/Sync/OTA/OTA.ino | 17 ++++-- .../Async/Callback/OTA/OTA.ino | 17 ++++-- .../Async/NoCallback/OTA/OTA.ino | 17 ++++-- examples/Storage/Async/Callback/OTA/OTA.ino | 17 ++++-- examples/Storage/Async/NoCallback/OTA/OTA.ino | 17 ++++-- examples/Storage/Sync/OTA/OTA.ino | 17 ++++-- keywords.txt | 1 + src/cloud_storage/CloudStorage.h | 12 +++- src/core/AsyncClient/AsyncClient.h | 21 ++++--- src/core/AsyncClient/RequestHandler.h | 1 + src/core/Base64.h | 21 ++++--- src/core/Error.h | 10 +++- src/core/JWT.cpp | 1 - src/core/OTA.h | 24 +++++--- src/core/Options.h | 7 --- .../{UpdaterArduino.cpp => OTAUpdater.cpp} | 56 +++++++++++-------- .../{UpdaterArduino.h => OTAUpdater.h} | 29 +++++++--- src/database/RealtimeDatabase.h | 12 +++- src/storage/Storage.h | 12 +++- 22 files changed, 230 insertions(+), 132 deletions(-) rename src/core/Updater/{UpdaterArduino.cpp => OTAUpdater.cpp} (56%) rename src/core/Updater/{UpdaterArduino.h => OTAUpdater.h} (71%) diff --git a/README.md b/README.md index 700fc1b..e282b9c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![GitHub Sponsors](https://img.shields.io/github/sponsors/mobizt?logo=github)](https://github.com/sponsors/mobizt) -Revision `2024-07-01T09:17:48Z` +Revision `2024-07-02T04:31:38Z` ## Table of Contents @@ -2493,23 +2493,18 @@ The OTA firmware update is supported using bin file stored in `Firebase Storage` The Arduino devices that is natively supports OTA firmware update is `ESP8266`, `ESP32` and `Raspberry Pi Pico`. -Since v1.3.1, the Arduino SAMD21 boards that use NINA firmware and WiFi101 firmware are also supported using [WiFi101OTA](https://github.com/arduino-libraries/WiFi101OTA) library. +Since v1.3.1, the Arduino SAMD21 boards that use NINA firmware and WiFi101 firmware are also supported using [Internal_Storage_OTA](https://github.com/mobizt/Internal_Storage_OTA) library. -In [WiFi101OTA](https://github.com/arduino-libraries/WiFi101OTA) library, only three files e.g. `InternalStorage.h`, `InternalStorage.cpp` and `OTAStorage.h` will be used. -To allow OTA update in Arduino SAMD21 boards, include `InternalStorage.h` in your sketch. +To allow OTA update in Arduino SAMD21 boards, you have to include `Internal_Storage_OTA.h` in your sketch. -```cpp -#if __has_include() -#include -#endif -``` +Then assign the `InternalStorage` class object to be used for `Realtume Database` via `RealtumeDatabase::setOTAStorage(InternalStorage)`, for `Google Cloud Storage` via `CloudStorage::setOTAStorage(InternalStorage)` and for `Firebase Storage` via `Storage::setOTAStorage(InternalStorage)` -In Arduino board that uses NINA firmware, you have to keep only those 3 files and delete all other files from [WiFi101OTA](https://github.com/arduino-libraries/WiFi101OTA)'s src folder and `WiFi101` library must be removed in this case. +If `InternalStorage` was not assigned before calling OTA function in case [Internal_Storage_OTA](https://github.com/mobizt/Internal_Storage_OTA) or Arduino compatible OTA library was included, the error `OTA Storage was not set` will be occurred. -Some Arduino compatible OTA library that provides the `InternalStorage.h` class that derived from `OTAStorage.h` class also can be used. +Finally, once the OTA update complete, in case [Internal_Storage_OTA](https://github.com/mobizt/Internal_Storage_OTA), you have to call `InternalStorage.apply()`. -The macro `FIREBASE_UPDATER_INTERNAL_STORAGE` is defined as `InternalStorage` class object when [WiFi101OTA](https://github.com/arduino-libraries/WiFi101OTA) and/or Arduino compatible OTA library are installed. +You can use other Arduino OTA libraries that provide `InternalStorageClass` object (`InternalStorage`) that derived from modified version of Arduino WiFi101OTA's `OTAStorage` class. ## Project Preparation and Setup diff --git a/examples/CloudStorage/Async/Callback/OTA/OTA.ino b/examples/CloudStorage/Async/Callback/OTA/OTA.ino index eeaa47f..815eff1 100644 --- a/examples/CloudStorage/Async/Callback/OTA/OTA.ino +++ b/examples/CloudStorage/Async/Callback/OTA/OTA.ino @@ -37,8 +37,8 @@ // For Arduino SAMD21 OTA supports. // See https://github.com/mobizt/FirebaseClient#ota-update. -#if __has_include() -#include +#if defined(ARDUINO_ARCH_SAMD) +#include #endif #define WIFI_SSID "WIFI_AP" @@ -148,6 +148,10 @@ void loop() Serial.println("OTA update download..."); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + cstorage.setOTAStorage(InternalStorage); +#endif + GoogleCloudStorage::GetOptions options; cstorage.ota(aClient, GoogleCloudStorage::Parent(STORAGE_BUCKET_ID, "firmware.bin"), options, asyncCB, "otaTask"); @@ -224,13 +228,14 @@ void restart() { Serial.println("Update firmware completed."); Serial.println(); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + Serial.println("Applying update..."); + InternalStorage.apply(); +#elif defined(ESP32) || defined(ESP8266) Serial.println("Restarting...\n\n"); - delay(2000); -#if defined(ESP32) || defined(ESP8266) ESP.restart(); #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) + Serial.println("Restarting...\n\n"); rp2040.restart(); -#elif defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - FIREBASE_UPDATER_INTERNAL_STORAGE.apply(); #endif } \ No newline at end of file diff --git a/examples/CloudStorage/Async/NoCallback/OTA/OTA.ino b/examples/CloudStorage/Async/NoCallback/OTA/OTA.ino index 6320063..6e0cf3c 100644 --- a/examples/CloudStorage/Async/NoCallback/OTA/OTA.ino +++ b/examples/CloudStorage/Async/NoCallback/OTA/OTA.ino @@ -36,8 +36,8 @@ // For Arduino SAMD21 OTA supports. // See https://github.com/mobizt/FirebaseClient#ota-update. -#if __has_include() -#include +#if defined(ARDUINO_ARCH_SAMD) +#include #endif #define WIFI_SSID "WIFI_AP" @@ -147,6 +147,10 @@ void loop() Serial.println("OTA update download..."); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + cstorage.setOTAStorage(InternalStorage); +#endif + GoogleCloudStorage::GetOptions options; cstorage.ota(aClient, GoogleCloudStorage::Parent(STORAGE_BUCKET_ID, "firmware.bin"), options, aResult_no_callback); @@ -217,13 +221,14 @@ void restart() { Serial.println("Update firmware completed."); Serial.println(); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + Serial.println("Applying update..."); + InternalStorage.apply(); +#elif defined(ESP32) || defined(ESP8266) Serial.println("Restarting...\n\n"); - delay(2000); -#if defined(ESP32) || defined(ESP8266) ESP.restart(); #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) + Serial.println("Restarting...\n\n"); rp2040.restart(); -#elif defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - FIREBASE_UPDATER_INTERNAL_STORAGE.apply(); #endif } \ No newline at end of file diff --git a/examples/CloudStorage/Sync/OTA/OTA.ino b/examples/CloudStorage/Sync/OTA/OTA.ino index 7f7b0ec..4e5ce40 100644 --- a/examples/CloudStorage/Sync/OTA/OTA.ino +++ b/examples/CloudStorage/Sync/OTA/OTA.ino @@ -37,8 +37,8 @@ // For Arduino SAMD21 OTA supports. // See https://github.com/mobizt/FirebaseClient#ota-update. -#if __has_include() -#include +#if defined(ARDUINO_ARCH_SAMD) +#include #endif #define WIFI_SSID "WIFI_AP" @@ -149,6 +149,10 @@ void loop() Serial.println("OTA update download..."); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + cstorage.setOTAStorage(InternalStorage); +#endif + GoogleCloudStorage::GetOptions options; // There is no OTA download progress available for sync OTA download. @@ -223,13 +227,14 @@ void restart() { Serial.println("Update firmware completed."); Serial.println(); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + Serial.println("Applying update..."); + InternalStorage.apply(); +#elif defined(ESP32) || defined(ESP8266) Serial.println("Restarting...\n\n"); - delay(2000); -#if defined(ESP32) || defined(ESP8266) ESP.restart(); #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) + Serial.println("Restarting...\n\n"); rp2040.restart(); -#elif defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - FIREBASE_UPDATER_INTERNAL_STORAGE.apply(); #endif } \ No newline at end of file diff --git a/examples/RealtimeDatabase/Async/Callback/OTA/OTA.ino b/examples/RealtimeDatabase/Async/Callback/OTA/OTA.ino index 43bacdc..a97d007 100644 --- a/examples/RealtimeDatabase/Async/Callback/OTA/OTA.ino +++ b/examples/RealtimeDatabase/Async/Callback/OTA/OTA.ino @@ -32,8 +32,8 @@ // For Arduino SAMD21 OTA supports. // See https://github.com/mobizt/FirebaseClient#ota-update. -#if __has_include() -#include +#if defined(ARDUINO_ARCH_SAMD) +#include #endif #define WIFI_SSID "WIFI_AP" @@ -128,6 +128,10 @@ void loop() Serial.println("Asynchronous OTA update... "); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + Database.setOTAStorage(InternalStorage); +#endif + Database.ota(aClient, "/test/firmware/bin", asyncCB, "otaTask"); } } @@ -180,13 +184,14 @@ void restart() { Serial.println("Update firmware completed."); Serial.println(); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + Serial.println("Applying update..."); + InternalStorage.apply(); +#elif defined(ESP32) || defined(ESP8266) Serial.println("Restarting...\n\n"); - delay(2000); -#if defined(ESP32) || defined(ESP8266) ESP.restart(); #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) + Serial.println("Restarting...\n\n"); rp2040.restart(); -#elif defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - FIREBASE_UPDATER_INTERNAL_STORAGE.apply(); #endif } \ No newline at end of file diff --git a/examples/RealtimeDatabase/Async/NoCallback/OTA/OTA.ino b/examples/RealtimeDatabase/Async/NoCallback/OTA/OTA.ino index ee755c4..2c8cbb8 100644 --- a/examples/RealtimeDatabase/Async/NoCallback/OTA/OTA.ino +++ b/examples/RealtimeDatabase/Async/NoCallback/OTA/OTA.ino @@ -31,8 +31,8 @@ // For Arduino SAMD21 OTA supports. // See https://github.com/mobizt/FirebaseClient#ota-update. -#if __has_include() -#include +#if defined(ARDUINO_ARCH_SAMD) +#include #endif #define WIFI_SSID "WIFI_AP" @@ -127,6 +127,10 @@ void loop() Serial.println("Asynchronous OTA update... "); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + Database.setOTAStorage(InternalStorage); +#endif + Database.ota(aClient, "/test/firmware/bin", aResult_no_callback); } @@ -173,13 +177,14 @@ void restart() { Serial.println("Update firmware completed."); Serial.println(); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + Serial.println("Applying update..."); + InternalStorage.apply(); +#elif defined(ESP32) || defined(ESP8266) Serial.println("Restarting...\n\n"); - delay(2000); -#if defined(ESP32) || defined(ESP8266) ESP.restart(); #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) + Serial.println("Restarting...\n\n"); rp2040.restart(); -#elif defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - FIREBASE_UPDATER_INTERNAL_STORAGE.apply(); #endif } \ No newline at end of file diff --git a/examples/Storage/Async/Callback/OTA/OTA.ino b/examples/Storage/Async/Callback/OTA/OTA.ino index 80f03cf..82fa2d5 100644 --- a/examples/Storage/Async/Callback/OTA/OTA.ino +++ b/examples/Storage/Async/Callback/OTA/OTA.ino @@ -34,8 +34,8 @@ // For Arduino SAMD21 OTA supports. // See https://github.com/mobizt/FirebaseClient#ota-update. -#if __has_include() -#include +#if defined(ARDUINO_ARCH_SAMD) +#include #endif #define WIFI_SSID "WIFI_AP" @@ -130,6 +130,10 @@ void loop() Serial.println("OTA update download..."); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + storage.setOTAStorage(InternalStorage); +#endif + storage.ota(aClient, FirebaseStorage::Parent(STORAGE_BUCKET_ID, "firmware.bin"), asyncCB, "otaTask"); } } @@ -186,13 +190,14 @@ void restart() { Serial.println("Update firmware completed."); Serial.println(); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + Serial.println("Applying update..."); + InternalStorage.apply(); +#elif defined(ESP32) || defined(ESP8266) Serial.println("Restarting...\n\n"); - delay(2000); -#if defined(ESP32) || defined(ESP8266) ESP.restart(); #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) + Serial.println("Restarting...\n\n"); rp2040.restart(); -#elif defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - FIREBASE_UPDATER_INTERNAL_STORAGE.apply(); #endif } \ No newline at end of file diff --git a/examples/Storage/Async/NoCallback/OTA/OTA.ino b/examples/Storage/Async/NoCallback/OTA/OTA.ino index a63355b..61ca478 100644 --- a/examples/Storage/Async/NoCallback/OTA/OTA.ino +++ b/examples/Storage/Async/NoCallback/OTA/OTA.ino @@ -33,8 +33,8 @@ // For Arduino SAMD21 OTA supports. // See https://github.com/mobizt/FirebaseClient#ota-update. -#if __has_include() -#include +#if defined(ARDUINO_ARCH_SAMD) +#include #endif #define WIFI_SSID "WIFI_AP" @@ -129,6 +129,10 @@ void loop() Serial.println("OTA update download..."); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + storage.setOTAStorage(InternalStorage); +#endif + storage.ota(aClient, FirebaseStorage::Parent(STORAGE_BUCKET_ID, "firmware.bin"), aResult_no_callback); } @@ -179,13 +183,14 @@ void restart() { Serial.println("Update firmware completed."); Serial.println(); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + Serial.println("Applying update..."); + InternalStorage.apply(); +#elif defined(ESP32) || defined(ESP8266) Serial.println("Restarting...\n\n"); - delay(2000); -#if defined(ESP32) || defined(ESP8266) ESP.restart(); #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) + Serial.println("Restarting...\n\n"); rp2040.restart(); -#elif defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - FIREBASE_UPDATER_INTERNAL_STORAGE.apply(); #endif } \ No newline at end of file diff --git a/examples/Storage/Sync/OTA/OTA.ino b/examples/Storage/Sync/OTA/OTA.ino index 6cc7a72..a529211 100644 --- a/examples/Storage/Sync/OTA/OTA.ino +++ b/examples/Storage/Sync/OTA/OTA.ino @@ -34,8 +34,8 @@ // For Arduino SAMD21 OTA supports. // See https://github.com/mobizt/FirebaseClient#ota-update. -#if __has_include() -#include +#if defined(ARDUINO_ARCH_SAMD) +#include #endif #define WIFI_SSID "WIFI_AP" @@ -137,6 +137,10 @@ void loop() Serial.println("OTA update download..."); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + storage.setOTAStorage(InternalStorage); +#endif + // There is no OTA download progress available for sync OTA download. // To get the OTA download progress, use async OTA download instead. @@ -191,13 +195,14 @@ void restart() { Serial.println("Update firmware completed."); Serial.println(); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + Serial.println("Applying update..."); + InternalStorage.apply(); +#elif defined(ESP32) || defined(ESP8266) Serial.println("Restarting...\n\n"); - delay(2000); -#if defined(ESP32) || defined(ESP8266) ESP.restart(); #elif defined(ARDUINO_RASPBERRY_PI_PICO_W) + Serial.println("Restarting...\n\n"); rp2040.restart(); -#elif defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - FIREBASE_UPDATER_INTERNAL_STORAGE.apply(); #endif } \ No newline at end of file diff --git a/keywords.txt b/keywords.txt index c35bf43..4e252dd 100644 --- a/keywords.txt +++ b/keywords.txt @@ -300,6 +300,7 @@ unsetAsyncResult KEYWORD2 setSSEFilters KEYWORD2 setJWTProcessor KEYWORD2 setSessionTimeout KEYWORD2 +setOTAStorage KEYWORD2 ################### # Struct (KEYWORD3) diff --git a/src/cloud_storage/CloudStorage.h b/src/cloud_storage/CloudStorage.h index cc5d283..888006d 100644 --- a/src/cloud_storage/CloudStorage.h +++ b/src/cloud_storage/CloudStorage.h @@ -1,5 +1,5 @@ /** - * Created June 26, 2024 + * Created July 1, 2024 * * The MIT License (MIT) * Copyright (c) 2024 K. Suwatchai (Mobizt) @@ -395,6 +395,14 @@ class CloudStorage sendRequest(aClient, nullptr, cb, uid, parent, nullptr, &options, nullptr, nullptr, GoogleCloudStorage::google_cloud_storage_request_type_delete, true); } +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + /** + * Set Arduino OTA Storage. + * @param storage The Arduino InternalStorageClass object. + */ + void setOTAStorage(InternalStorageClass &storage) { ota_intnl_storage_addr = reinterpret_cast(&storage); } +#endif + private: String service_url; String path; @@ -402,6 +410,7 @@ class CloudStorage // FirebaseApp address and FirebaseApp vector address uint32_t app_addr = 0, avec_addr = 0; uint32_t ul_dl_task_running_addr = 0; + uint32_t ota_intnl_storage_addr = 0; app_token_t *app_token = nullptr; Memory mem; @@ -547,6 +556,7 @@ class CloudStorage sData->request.base64 = false; sData->aResult.download_data.ota = true; sData->request.ul_dl_task_running_addr = ul_dl_task_running_addr; + sData->request.ota_intnl_storage_addr = ota_intnl_storage_addr; } if (request.file && sData->upload) diff --git a/src/core/AsyncClient/AsyncClient.h b/src/core/AsyncClient/AsyncClient.h index 93a74e6..f5d14e4 100644 --- a/src/core/AsyncClient/AsyncClient.h +++ b/src/core/AsyncClient/AsyncClient.h @@ -32,7 +32,6 @@ #include "./core/NetConfig.h" #include "./core/Memory.h" #include "./core/FileConfig.h" -#include "./core/Base64.h" #include "./core/Error.h" #include "./core/OTA.h" #include "./core/AsyncResult/AsyncResult.h" @@ -200,7 +199,8 @@ class AsyncClientClass : public ResultBase, RTDBResultBase uint16_t port; std::vector sVec; Memory mem; - Base64Util but; + Base64Util b64ut; + OTAUtil otaut; network_config_data net; uint32_t addr = 0; bool inProcess = false; @@ -361,7 +361,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase sData->request.file_data.data_pos += toSend; } - uint8_t *temp = reinterpret_cast(but.encodeToChars(mem, buf, toSend)); + uint8_t *temp = reinterpret_cast(b64ut.encodeToChars(mem, buf, toSend)); mem.release(&buf); toSend = strlen(reinterpret_cast(temp)); buf = temp; @@ -1106,7 +1106,6 @@ class AsyncClientClass : public ResultBase, RTDBResultBase bool readPayload(async_data_item_t *sData) { uint8_t *buf = nullptr; - OTAUtil otaut; if (sData->response.flags.payload_remaining) { @@ -1131,6 +1130,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase { if (sData->request.ota) { + otaut.setOTAStorage(sData->request.ota_intnl_storage_addr); otaut.prepareDownloadOTA(sData->response.payloadLen, sData->request.base64, sData->request.ota_error); if (sData->request.ota_error != 0) { @@ -1189,7 +1189,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase otaut.getPad(buf + ofs, read, sData->request.b64Pad); if (sData->request.ota) { - otaut.decodeBase64OTA(mem, &but, reinterpret_cast(buf), read - ofs, sData->request.ota_error); + otaut.decodeBase64OTA(mem, &b64ut, reinterpret_cast(buf), read - ofs, sData->request.ota_error); if (sData->request.ota_error != 0) { // In case OTA error. @@ -1199,7 +1199,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase if (sData->request.b64Pad > -1) { - otaut.endDownloadOTA(sData->request.b64Pad, sData->request.ota_error); + otaut.endDownloadOTA(b64ut, sData->request.b64Pad, sData->request.ota_error); if (sData->request.ota_error != 0) { // In case OTA error. @@ -1212,7 +1212,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase else if (sData->request.file_data.filename.length() && sData->request.file_data.cb) { - if (!but.decodeToFile(mem, sData->request.file_data.file, reinterpret_cast(buf + ofs))) + if (!b64ut.decodeToFile(mem, sData->request.file_data.file, reinterpret_cast(buf + ofs))) { // In case file write error. setAsyncError(sData, async_state_read_response, FIREBASE_ERROR_FILE_WRITE, !sData->sse, true); @@ -1221,17 +1221,17 @@ class AsyncClientClass : public ResultBase, RTDBResultBase } #endif else - but.decodeToBlob(mem, &sData->request.file_data.outB, reinterpret_cast(buf + ofs)); + b64ut.decodeToBlob(mem, &sData->request.file_data.outB, reinterpret_cast(buf + ofs)); } else { if (sData->request.ota) { - but.updateWrite(buf, read); + b64ut.updateWrite(buf, read); if (sData->response.payloadRead == sData->response.payloadLen) { - otaut.endDownloadOTA(0, sData->request.ota_error); + otaut.endDownloadOTA(b64ut, 0, sData->request.ota_error); if (sData->request.ota_error != 0) { // In case OTA error. @@ -1849,7 +1849,6 @@ class AsyncClientClass : public ResultBase, RTDBResultBase #if defined(ENABLE_FS) if ((sData->request.file_data.cb && sData->request.file_data.filename.length()) || (sData->request.file_data.data_size && sData->request.file_data.data)) { - Base64Util b64ut; size_t sz = 0; if (sData->request.file_data.cb) { diff --git a/src/core/AsyncClient/RequestHandler.h b/src/core/AsyncClient/RequestHandler.h index 6004582..7f702aa 100644 --- a/src/core/AsyncClient/RequestHandler.h +++ b/src/core/AsyncClient/RequestHandler.h @@ -99,6 +99,7 @@ struct async_request_handler_t bool base64 = false; bool ota = false; uint32_t ul_dl_task_running_addr = 0; + uint32_t ota_intnl_storage_addr = 0; uint32_t payloadLen = 0; uint32_t dataLen = 0; uint32_t payloadIndex = 0; diff --git a/src/core/Base64.h b/src/core/Base64.h index 6b0b466..09d1515 100644 --- a/src/core/Base64.h +++ b/src/core/Base64.h @@ -35,7 +35,13 @@ #include #endif -#include "./core/Updater/UpdaterArduino.h" +#include "./core/Updater/OTAUpdater.h" + +#if defined(FIREBASE_OTA_UPDATER_STORAGE) +#define FIREBASE_UPDATER OTAUpdater +#elif defined(ESP32) || defined(ESP8266) || defined(CORE_ARDUINO_PICO) +#define FIREBASE_UPDATER Update +#endif static const char firebase_boundary_table[] PROGMEM = "=_abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static const unsigned char firebase_base64_table[65] PROGMEM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -111,10 +117,8 @@ class Base64Util bool updateWrite(uint8_t *data, size_t len) { -#if defined(OTA_UPDATE_ENABLED) && (defined(ENABLE_DATABASE) || defined(ENABLE_STORAGE) || defined(ENABLE_CLOUD_STORAGE)) -#if defined(ESP32) || defined(ESP8266) || defined(CORE_ARDUINO_PICO) || defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - return Update.write(data, len) == len; -#endif +#if defined(OTA_UPDATE_ENABLED) && defined(FIREBASE_UPDATER) && (defined(ENABLE_DATABASE) || defined(ENABLE_STORAGE) || defined(ENABLE_CLOUD_STORAGE)) + return FIREBASE_UPDATER.write(data, len) == len; #endif return false; } @@ -149,8 +153,11 @@ class Base64Util return true; #if defined(OTA_UPDATE_ENABLED) - else if (out.ota && updateWrite(reinterpret_cast(out.outT), write)) - return true; + else if (out.ota) + { + if (updateWrite(reinterpret_cast(out.outT), write)) + return true; + } #endif return false; } diff --git a/src/core/Error.h b/src/core/Error.h index a646bdd..a5e5d02 100644 --- a/src/core/Error.h +++ b/src/core/Error.h @@ -1,5 +1,5 @@ /** - * Created June 26, 2024 + * Created July 1, 2024 * * The MIT License (MIT) * Copyright (c) 2024 K. Suwatchai (Mobizt) @@ -86,6 +86,7 @@ #define FIREBASE_ERROR_TIME_IS_NOT_SET_OR_INVALID -119 #define FIREBASE_ERROR_JWT_CREATION_REQUIRED -120 #define FIREBASE_ERROR_INVALID_DATABASE_SECRET -121 +#define FIREBASE_ERROR_FW_UPDATE_OTA_STORAGE_CLASS_OBJECT_UNINITIALIZE -122 #if !defined(FPSTR) #define FPSTR @@ -169,7 +170,10 @@ class FirebaseError case FIREBASE_ERROR_FW_UPDATE_TOO_LOW_FREE_SKETCH_SPACE: err.setError(code, FPSTR("too low sketch space")); break; - case FIREBASE_ERROR_FW_UPDATE_WRITE_FAILED: + case FIREBASE_ERROR_FW_UPDATE_OTA_STORAGE_CLASS_OBJECT_UNINITIALIZE: + err.setError(code, FPSTR("OTA Storage was not set")); + break; + case FIREBASE_ERROR_FW_UPDATE_WRITE_FAILED: err.setError(code, FPSTR("firmware write failed")); break; case FIREBASE_ERROR_FW_UPDATE_END_FAILED: @@ -191,7 +195,7 @@ class FirebaseError err.setError(code, FPSTR("time was not set or not valid")); break; case FIREBASE_ERROR_INVALID_DATABASE_SECRET: - err.setError(code, FPSTR("invalid database secret")); + err.setError(code, FPSTR("invalid database secret")); break; default: err.setError(code, FPSTR("undefined")); diff --git a/src/core/JWT.cpp b/src/core/JWT.cpp index 5feacf6..a75589e 100644 --- a/src/core/JWT.cpp +++ b/src/core/JWT.cpp @@ -29,7 +29,6 @@ #include "./Config.h" #include "./core/Memory.h" #include "./core/AuthConfig.h" -#include "./core/Base64.h" #include "./core/URL.h" #include "./core/JSON.h" #include "./core/Error.h" diff --git a/src/core/OTA.h b/src/core/OTA.h index 1106b99..e47445c 100644 --- a/src/core/OTA.h +++ b/src/core/OTA.h @@ -62,7 +62,6 @@ class OTAUtil bool decodeBase64OTA(Memory &mem, Base64Util *but, const char *src, size_t len, int16_t &code) { - bool ret = true; firebase_base64_io_t out; uint8_t *buf = reinterpret_cast(mem.alloc(out.bufLen)); @@ -79,32 +78,39 @@ class OTAUtil return ret; } + void setOTAStorage(uint32_t addr) + { + OTAUpdater.setOTAStorage(addr); + } + void prepareDownloadOTA(size_t payloadLen, bool base64, int16_t &code) { code = 0; -#if defined(OTA_UPDATE_ENABLED) && (defined(ESP32) || defined(ESP8266) || defined(CORE_ARDUINO_PICO) || defined(FIREBASE_UPDATER_INTERNAL_STORAGE)) +#if defined(OTA_UPDATE_ENABLED) && defined(FIREBASE_UPDATER) int size = base64 ? (3 * (payloadLen - 2) / 4) : payloadLen; - if (!Update.begin(size)) + if (!FIREBASE_UPDATER.begin(size)) code = FIREBASE_ERROR_FW_UPDATE_TOO_LOW_FREE_SKETCH_SPACE; +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + if (!OTAUpdater.isInit()) + code = FIREBASE_ERROR_FW_UPDATE_OTA_STORAGE_CLASS_OBJECT_UNINITIALIZE; +#endif #endif } - bool endDownloadOTA(int pad, int16_t &code) + bool endDownloadOTA(Base64Util &b64ut, int pad, int16_t &code) { - -#if defined(OTA_UPDATE_ENABLED) && (defined(ESP32) || defined(ESP8266) || defined(CORE_ARDUINO_PICO) || defined(FIREBASE_UPDATER_INTERNAL_STORAGE)) - Base64Util but; +#if defined(OTA_UPDATE_ENABLED) && defined(FIREBASE_UPDATER) // write extra pad if (pad > 0) { uint8_t buf[pad]; memset(buf, 0, pad); - but.updateWrite(buf, pad); + b64ut.updateWrite(buf, pad); } if (code == 0) { - if (!Update.end()) + if (!FIREBASE_UPDATER.end()) code = FIREBASE_ERROR_FW_UPDATE_END_FAILED; } diff --git a/src/core/Options.h b/src/core/Options.h index 6e19c29..c616f7b 100644 --- a/src/core/Options.h +++ b/src/core/Options.h @@ -272,11 +272,4 @@ #define FIREBASE_ASYNC_CLIENT AsyncClient #endif -#if __has_include() -#include -#if defined(_INTERNAL_STORAGE_H_INCLUDED) -#define FIREBASE_UPDATER_INTERNAL_STORAGE InternalStorage -#endif -#endif - #endif \ No newline at end of file diff --git a/src/core/Updater/UpdaterArduino.cpp b/src/core/Updater/OTAUpdater.cpp similarity index 56% rename from src/core/Updater/UpdaterArduino.cpp rename to src/core/Updater/OTAUpdater.cpp index 8d48645..4ec25fc 100644 --- a/src/core/Updater/UpdaterArduino.cpp +++ b/src/core/Updater/OTAUpdater.cpp @@ -23,62 +23,72 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef UPDATER_ARDUINO_CPP -#define UPDATER_ARDUINO_CPP +#ifndef OTA_UPDATER_CPP +#define OTA_UPDATER_CPP #include -#include "./Config.h" -#include "./core/Updater/UpdaterArduino.h" +#include "./core/Updater/OTAUpdater.h" -UpdaterArduino::UpdaterArduino() {} -UpdaterArduino::~UpdaterArduino() {} +OTAUpdaterClass::OTAUpdaterClass() {} +OTAUpdaterClass::~OTAUpdaterClass() {} -bool UpdaterArduino::begin(int size) +bool OTAUpdaterClass::begin(int size) { -#if defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - if (FIREBASE_UPDATER_INTERNAL_STORAGE.open(size) > 0) +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + if (storage && storage->open(size) > 0) return true; #endif return false; } -bool UpdaterArduino::end() +bool OTAUpdaterClass::end() { close(); return true; } -size_t UpdaterArduino::write(uint8_t *data, size_t len) +void OTAUpdaterClass::setOTAStorage(uint32_t addr) +{ +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + this->addr = addr; + storage = reinterpret_cast(addr); +#endif +} + +bool OTAUpdaterClass::isInit() { return addr > 0; } + +size_t OTAUpdaterClass::write(uint8_t *data, size_t len) { for (size_t i = 0; i < len; i++) write(data[i]); return len; } -size_t UpdaterArduino::write(uint8_t b) +size_t OTAUpdaterClass::write(uint8_t b) { -#if defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - FIREBASE_UPDATER_INTERNAL_STORAGE.write(b); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + if (storage) + storage->write(b); #endif return 1; } -void UpdaterArduino::close() +void OTAUpdaterClass::close() { -#if defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - FIREBASE_UPDATER_INTERNAL_STORAGE.close(); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + if (storage) + storage->close(); #endif } -void UpdaterArduino::apply() +void OTAUpdaterClass::apply() { -#if defined(FIREBASE_UPDATER_INTERNAL_STORAGE) - FIREBASE_UPDATER_INTERNAL_STORAGE.apply(); +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + if (storage) + storage->apply(); #endif } -#if defined(FIREBASE_UPDATER_INTERNAL_STORAGE) -UpdaterArduino Update; -#endif +OTAUpdaterClass OTAUpdater; #endif \ No newline at end of file diff --git a/src/core/Updater/UpdaterArduino.h b/src/core/Updater/OTAUpdater.h similarity index 71% rename from src/core/Updater/UpdaterArduino.h rename to src/core/Updater/OTAUpdater.h index 079dd0e..19c8aaf 100644 --- a/src/core/Updater/UpdaterArduino.h +++ b/src/core/Updater/OTAUpdater.h @@ -23,30 +23,43 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef UPDATER_ARDUINO_H -#define UPDATER_ARDUINO_H +#ifndef OTA_UPDATER_H +#define OTA_UPDATER_H #include #include "./Config.h" -class UpdaterArduino +#if __has_include() +#include +#endif + +#if __has_include() +#include +#define FIREBASE_OTA_UPDATER_STORAGE +#endif + +class OTAUpdaterClass { public: - UpdaterArduino(); - ~UpdaterArduino(); + OTAUpdaterClass(); + ~OTAUpdaterClass(); bool begin(int size); bool end(); size_t write(uint8_t *data, size_t len); + void setOTAStorage(uint32_t addr); + bool isInit(); private: +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + InternalStorageClass *storage = nullptr; +#endif + uint32_t addr = 0; size_t write(uint8_t b); void close(); void apply(); }; -#if defined(FIREBASE_UPDATER_INTERNAL_STORAGE) -extern UpdaterArduino Update; -#endif +extern OTAUpdaterClass OTAUpdater; #endif \ No newline at end of file diff --git a/src/database/RealtimeDatabase.h b/src/database/RealtimeDatabase.h index 58f6b3c..ca21f1e 100644 --- a/src/database/RealtimeDatabase.h +++ b/src/database/RealtimeDatabase.h @@ -1,5 +1,5 @@ /** - * Created June 28, 2024 + * Created July 1, 2024 * * The MIT License (MIT) * Copyright (c) 2024 K. Suwatchai (Mobizt) @@ -876,6 +876,14 @@ class RealtimeDatabase : public RTDBResultBase this->sse_events_filter = filter; } +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + /** + * Set Arduino OTA Storage. + * @param storage The Arduino InternalStorageClass object. + */ + void setOTAStorage(InternalStorageClass &storage) { ota_intnl_storage_addr = reinterpret_cast(&storage); } +#endif + /** * Perform the async task repeatedly. * Should be placed in main loop function. @@ -905,6 +913,7 @@ class RealtimeDatabase : public RTDBResultBase // FirebaseApp address and FirebaseApp vector address uint32_t app_addr = 0, avec_addr = 0; uint32_t ul_dl_task_running_addr = 0; + uint32_t ota_intnl_storage_addr = 0; app_token_t *app_token = nullptr; struct async_request_data_t @@ -1000,6 +1009,7 @@ class RealtimeDatabase : public RTDBResultBase sData->request.base64 = true; sData->aResult.download_data.ota = true; sData->request.ul_dl_task_running_addr = ul_dl_task_running_addr; + sData->request.ota_intnl_storage_addr = ota_intnl_storage_addr; } if (request.file && sData->upload) diff --git a/src/storage/Storage.h b/src/storage/Storage.h index 8f91811..0270d60 100644 --- a/src/storage/Storage.h +++ b/src/storage/Storage.h @@ -1,5 +1,5 @@ /** - * Created June 28, 2024 + * Created July 1, 2024 * * The MIT License (MIT) * Copyright (c) 2024 K. Suwatchai (Mobizt) @@ -360,6 +360,14 @@ class Storage sendRequest(aClient, nullptr, cb, uid, parent, nullptr, "", FirebaseStorage::firebase_storage_request_type_delete, true); } +#if defined(FIREBASE_OTA_UPDATER_STORAGE) + /** + * Set Arduino OTA Storage. + * @param storage The Arduino InternalStorageClass object. + */ + void setOTAStorage(InternalStorageClass &storage) { ota_intnl_storage_addr = reinterpret_cast(&storage); } +#endif + private: String service_url; String path; @@ -367,6 +375,7 @@ class Storage // FirebaseApp address and FirebaseApp vector address uint32_t app_addr = 0, avec_addr = 0; uint32_t ul_dl_task_running_addr = 0; + uint32_t ota_intnl_storage_addr = 0; app_token_t *app_token = nullptr; void url(const String &url) @@ -472,6 +481,7 @@ class Storage sData->request.base64 = false; sData->aResult.download_data.ota = true; sData->request.ul_dl_task_running_addr = ul_dl_task_running_addr; + sData->request.ota_intnl_storage_addr = ota_intnl_storage_addr; } if (request.file && sData->upload)