diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 62d2d7025..5d0dd8f57 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -138,7 +138,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #endif /* AVR */ #if OTA_ENABLED && !defined(__AVR__) - _ota_img_sha256 = getOTAImageSHA256(); + _ota_img_sha256 = OTA::getImageSHA256(); DEBUG_VERBOSE("SHA256: HASH(%d) = %s", strlen(_ota_img_sha256.c_str()), _ota_img_sha256.c_str()); #endif /* OTA_ENABLED */ @@ -205,38 +205,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, addPropertyReal(_tz_offset, "tz_offset", Permission::ReadWrite).onSync(CLOUD_WINS).onUpdate(updateTimezoneInfo); addPropertyReal(_tz_dst_until, "tz_dst_until", Permission::ReadWrite).onSync(CLOUD_WINS).onUpdate(updateTimezoneInfo); -#if OTA_STORAGE_PORTENTA_QSPI - #define BOOTLOADER_ADDR (0x8000000) - uint32_t bootloader_data_offset = 0x1F000; - uint8_t* bootloader_data = (uint8_t*)(BOOTLOADER_ADDR + bootloader_data_offset); - uint8_t currentBootloaderVersion = bootloader_data[1]; - if (currentBootloaderVersion < 22) { - _ota_cap = false; - DEBUG_WARNING("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, update the bootloader", __FUNCTION__); - DEBUG_WARNING("ArduinoIoTCloudTCP::%s File -> Examples -> Portenta_System -> PortentaH7_updateBootloader", __FUNCTION__); - } - else { - _ota_cap = true; - } -#endif - -#if OTA_STORAGE_SNU && OTA_ENABLED - if (String(WiFi.firmwareVersion()) < String("1.4.1")) { - _ota_cap = false; - DEBUG_WARNING("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, NINA firmware needs to be >= 1.4.1, current %s", __FUNCTION__, WiFi.firmwareVersion()); - } - else { - _ota_cap = true; - } -#endif /* OTA_STORAGE_SNU */ - -#if defined(ARDUINO_NANO_RP2040_CONNECT) || defined(ARDUINO_NICLA_VISION) - _ota_cap = true; -#endif - -#if defined(ARDUINO_ARCH_ESP32) && OTA_ENABLED - /* NOTE: here is possible to check if current partition scheme is OTA compatible */ - _ota_cap = true; +#if OTA_ENABLED + _ota_cap = OTA::isCapable(); #endif #ifdef BOARD_HAS_OFFLOADED_ECCX08 @@ -609,7 +579,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() /* Transmit the cleared request flags to the cloud. */ sendDevicePropertyToCloud("OTA_REQ"); /* Call member function to handle OTA request. */ - onOTARequest(); + _ota_error = OTA::onRequest(_ota_url, _connection->getInterface()); /* If something fails send the OTA error to the cloud */ sendDevicePropertyToCloud("OTA_ERROR"); } @@ -762,45 +732,6 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l return 0; } -#if OTA_ENABLED -void ArduinoIoTCloudTCP::onOTARequest() -{ - DEBUG_INFO("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str()); - -#ifdef ARDUINO_ARCH_SAMD - _ota_error = samd_onOTARequest(_ota_url.c_str()); -#endif - -#ifdef ARDUINO_NANO_RP2040_CONNECT - _ota_error = rp2040_connect_onOTARequest(_ota_url.c_str()); -#endif - -#ifdef BOARD_STM32H7 - bool const use_ethernet = _connection->getInterface() == NetworkAdapter::ETHERNET ? true : false; - _ota_error = portenta_h7_onOTARequest(_ota_url.c_str(), use_ethernet); -#endif - -#ifdef ARDUINO_ARCH_ESP32 - _ota_error = esp32_onOTARequest(_ota_url.c_str()); -#endif -} - -String ArduinoIoTCloudTCP::getOTAImageSHA256() -{ -#if defined (ARDUINO_ARCH_SAMD) - return samd_getOTAImageSHA256(); -#elif defined (ARDUINO_NANO_RP2040_CONNECT) - return rp2040_connect_getOTAImageSHA256(); -#elif defined (BOARD_STM32H7) - return portenta_h7_getOTAImageSHA256(); -#elif defined (ARDUINO_ARCH_ESP32) - return esp32_getOTAImageSHA256(); -#else - # error "No method for SHA256 checksum calculation over application image defined for this architecture." -#endif -} -#endif - void ArduinoIoTCloudTCP::updateThingTopics() { _shadowTopicOut = getTopic_shadowout(); diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 3b7d431da..e8218c9e1 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -201,8 +201,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass int write(String const topic, byte const data[], int const length); #if OTA_ENABLED - void onOTARequest(); - String getOTAImageSHA256(); void sendDevicePropertyToCloud(String const name); #endif diff --git a/src/utility/ota/OTA-esp32.cpp b/src/utility/ota/OTA-esp32.cpp index 97da4041c..443187c7d 100644 --- a/src/utility/ota/OTA-esp32.cpp +++ b/src/utility/ota/OTA-esp32.cpp @@ -120,4 +120,10 @@ String esp32_getOTAImageSHA256() return sha256_str; } +bool esp32_isOTACapable() +{ + /* NOTE: here is possible to check if current partition scheme is OTA compatible */ + return true; +} + #endif /* ARDUINO_ARCH_ESP32 */ diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index acdf6e8ec..4e3c1d047 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -258,4 +258,9 @@ String rp2040_connect_getOTAImageSHA256() return FlashSHA256::calc(XIP_BASE, 0x100000); } +bool rp2040_connect_isOTACapable() +{ + return true; +} + #endif /* ARDUINO_NANO_RP2040_CONNECT */ diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index 12481a7ed..bd95f6a6b 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -45,7 +45,7 @@ extern RTC_HandleTypeDef RTCHandle; * FUNCTION DEFINITION ******************************************************************************/ -int portenta_h7_onOTARequest(char const * ota_url, const bool use_ethernet) +int portenta_h7_onOTARequest(char const * ota_url, NetworkAdapter iface) { watchdog_reset(); @@ -76,7 +76,7 @@ int portenta_h7_onOTARequest(char const * ota_url, const bool use_ethernet) /* Download the OTA file from the web storage location. */ MbedSocketClass * download_socket = static_cast(&WiFi); #if defined (BOARD_HAS_ETHERNET) - if(use_ethernet) { + if(iface == NetworkAdapter::ETHERNET) { download_socket = static_cast(&Ethernet); } #endif @@ -143,4 +143,9 @@ String portenta_h7_getOTAImageSHA256() return sha256_str; } +bool portenta_h7_isOTACapable() +{ + return Arduino_Portenta_OTA::isOtaCapable(); +} + #endif /* BOARD_STM32H7 */ diff --git a/src/utility/ota/OTA-samd.cpp b/src/utility/ota/OTA-samd.cpp index fa62bb359..4ef214f32 100644 --- a/src/utility/ota/OTA-samd.cpp +++ b/src/utility/ota/OTA-samd.cpp @@ -81,4 +81,17 @@ String samd_getOTAImageSHA256() return FlashSHA256::calc(0x2000, 0x40000 - 0x2000); } +bool samd_isOTACapable() +{ +#if OTA_STORAGE_SNU + if (String(WiFi.firmwareVersion()) < String("1.4.1")) { + DEBUG_WARNING("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, NINA firmware needs to be >= 1.4.1, current %s", __FUNCTION__, WiFi.firmwareVersion()); + return false; + } else { + return true; + } +#endif + return false; +} + #endif /* ARDUINO_ARCH_SAMD */ diff --git a/src/utility/ota/OTA.cpp b/src/utility/ota/OTA.cpp new file mode 100644 index 000000000..bac388b59 --- /dev/null +++ b/src/utility/ota/OTA.cpp @@ -0,0 +1,112 @@ +/* + This file is part of ArduinoIoTCloud. + + Copyright 2020 ARDUINO SA (http://www.arduino.cc/) + + This software is released under the GNU General Public License version 3, + which covers the main part of arduino-cli. + The terms of this license can be found at: + https://www.gnu.org/licenses/gpl-3.0.en.html + + You can be released from the requirements of the above licenses by purchasing + a commercial license. Buying such a license is mandatory if you want to modify or + otherwise use the software for commercial activities involving the Arduino + software without disclosing the source code of your own applications. To purchase + a commercial license, send an email to license@arduino.cc. +*/ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include + +#if OTA_ENABLED + +#include "OTA.h" +#include + +/****************************************************************************** + * FUNCTION DECLARATION + ******************************************************************************/ + +#ifdef ARDUINO_ARCH_SAMD +int samd_onOTARequest(char const * url); +String samd_getOTAImageSHA256(); +bool samd_isOTACapable(); +#endif + +#ifdef ARDUINO_NANO_RP2040_CONNECT +int rp2040_connect_onOTARequest(char const * url); +String rp2040_connect_getOTAImageSHA256(); +bool rp2040_connect_isOTACapable(); +#endif + +#ifdef BOARD_STM32H7 +int portenta_h7_onOTARequest(char const * url, NetworkAdapter iface); +String portenta_h7_getOTAImageSHA256(); +void portenta_h7_setNetworkAdapter(NetworkAdapter iface); +bool portenta_h7_isOTACapable(); +#endif + +#ifdef ARDUINO_ARCH_ESP32 +int esp32_onOTARequest(char const * url); +String esp32_getOTAImageSHA256(); +bool esp32_isOTACapable(); +#endif + +/****************************************************************************** + * PUBLIC MEMBER FUNCTIONS + ******************************************************************************/ + +int OTA::onRequest(String url, NetworkAdapter iface) +{ + DEBUG_INFO("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, url.c_str()); + +#if defined (ARDUINO_ARCH_SAMD) + (void)iface; + return samd_onOTARequest(url.c_str()); +#elif defined (ARDUINO_NANO_RP2040_CONNECT) + (void)iface; + return rp2040_connect_onOTARequest(url.c_str()); +#elif defined (BOARD_STM32H7) + return portenta_h7_onOTARequest(url.c_str(), iface); +#elif defined (ARDUINO_ARCH_ESP32) + (void)iface; + return esp32_onOTARequest(url.c_str()); +#else + #error "OTA not supported for this architecture" +#endif +} + +String OTA::getImageSHA256() +{ +#if defined (ARDUINO_ARCH_SAMD) + return samd_getOTAImageSHA256(); +#elif defined (ARDUINO_NANO_RP2040_CONNECT) + return rp2040_connect_getOTAImageSHA256(); +#elif defined (BOARD_STM32H7) + return portenta_h7_getOTAImageSHA256(); +#elif defined (ARDUINO_ARCH_ESP32) + return esp32_getOTAImageSHA256(); +#else + #error "No method for SHA256 checksum calculation over application image defined for this architecture." +#endif +} + +bool OTA::isCapable() +{ +#if defined (ARDUINO_ARCH_SAMD) + return samd_isOTACapable(); +#elif defined (ARDUINO_NANO_RP2040_CONNECT) + return rp2040_connect_isOTACapable(); +#elif defined (BOARD_STM32H7) + return portenta_h7_isOTACapable(); +#elif defined (ARDUINO_ARCH_ESP32) + return esp32_isOTACapable(); +#else + #error "OTA not supported for this architecture" +#endif +} + +#endif /* OTA_ENABLED */ diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 26139d46d..88c7229b9 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -23,7 +23,10 @@ ******************************************************************************/ #include + +#if OTA_ENABLED #include +#include /****************************************************************************** * DEFINES @@ -52,27 +55,19 @@ enum class OTAError : int }; /****************************************************************************** - * FUNCTION DEFINITION + * CLASS DECLARATION ******************************************************************************/ -#ifdef ARDUINO_ARCH_SAMD -int samd_onOTARequest(char const * ota_url); -String samd_getOTAImageSHA256(); -#endif - -#ifdef ARDUINO_NANO_RP2040_CONNECT -int rp2040_connect_onOTARequest(char const * ota_url); -String rp2040_connect_getOTAImageSHA256(); -#endif - -#ifdef BOARD_STM32H7 -int portenta_h7_onOTARequest(char const * ota_url, const bool use_ethernet); -String portenta_h7_getOTAImageSHA256(); -#endif - -#ifdef ARDUINO_ARCH_ESP32 -int esp32_onOTARequest(char const * ota_url); -String esp32_getOTAImageSHA256(); -#endif +class OTA +{ +public: + + static int onRequest(String url, NetworkAdapter iface); + static String getImageSHA256(); + static bool isCapable(); + +}; + +#endif /* OTA_ENABLED */ #endif /* ARDUINO_OTA_LOGIC_H_ */