diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 2149fe4c8..fdf0f323b 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -58,7 +58,7 @@ jobs: - name: ArduinoECCX08 - name: RTCZero - name: WiFi101 - - name: WiFiNINA + - source-url: https://github.com/arduino-libraries/WiFiNINA.git - name: Arduino_MKRMEM sketch-paths: '"examples/utility/Provisioning"' # LoRaWAN boards diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index 5269338c7..dd7b3e990 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -12,7 +12,6 @@ include_directories(include) include_directories(../../src) include_directories(../../src/cbor) include_directories(../../src/property) -include_directories(../../src/utility/ota) include_directories(external/catch/v2.12.1/include) include_directories(external/fakeit/v2.0.5/include) @@ -29,8 +28,6 @@ set(TEST_TARGET ${CMAKE_PROJECT_NAME}) ########################################################################## set(TEST_SRCS - src/test_OTALogic.cpp - src/test_addPropertyReal.cpp src/test_callback.cpp src/test_CloudColor.cpp @@ -46,14 +43,10 @@ set(TEST_SRCS set(TEST_UTIL_SRCS src/util/CBORTestUtil.cpp - src/util/OTATestUtil.cpp src/util/PropertyTestUtil.cpp ) set(TEST_DUT_SRCS - ../../src/utility/ota/crc.cpp - ../../src/utility/ota/OTALogic.cpp - ../../src/property/Property.cpp ../../src/property/PropertyContainer.cpp ../../src/cbor/CBORDecoder.cpp diff --git a/extras/test/include/util/OTATestUtil.h b/extras/test/include/util/OTATestUtil.h deleted file mode 100644 index 640d422a2..000000000 --- a/extras/test/include/util/OTATestUtil.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2020 Arduino. All rights reserved. - */ - -#ifndef OTA_TEST_DATA_GENERATOR_H_ -#define OTA_TEST_DATA_GENERATOR_H_ - -/************************************************************************************** - INCLUDE - **************************************************************************************/ - -#include <stdint.h> - -/************************************************************************************** - NAMESPACE - **************************************************************************************/ - -namespace ota -{ - -/************************************************************************************** - TYPEDEF - **************************************************************************************/ - -union OTAData -{ - struct __attribute__((packed)) - { - uint32_t len; - uint32_t crc32; - uint8_t bin[256*1024]; /* Maximum flash size of ATSAMD21G18 is 256 KB */ - } data; - uint8_t buf[sizeof(data)]; -}; - -/************************************************************************************** - FUNCTION DECLARATION - **************************************************************************************/ - -void generate_valid_ota_data(OTAData & ota_data); -void generate_invalid_ota_data_crc_wrong(OTAData & ota_data); - -/************************************************************************************** - NAMESPACE - **************************************************************************************/ - -} /* ota */ - -#endif /* OTA_TEST_DATA_GENERATOR_H_ */ diff --git a/extras/test/src/test_OTALogic.cpp b/extras/test/src/test_OTALogic.cpp deleted file mode 100644 index b1b8b8139..000000000 --- a/extras/test/src/test_OTALogic.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (c) 2020 Arduino. All rights reserved. - */ - -/************************************************************************************** - INCLUDE - **************************************************************************************/ - -#include <vector> -#include <algorithm> - -#include <catch.hpp> -#include <fakeit.hpp> - -#include <util/OTATestUtil.h> - -#include <OTALogic.h> -#include <OTAStorage.h> - -/************************************************************************************** - NAMESPACE - **************************************************************************************/ - -using namespace fakeit; - -/************************************************************************************** - TEST HELPER - **************************************************************************************/ - -void simulateOTABinaryReception(OTALogic & ota_logic, ota::OTAData const & ota_test_data) -{ - uint32_t bytes_written = 0; - uint32_t const bytes_to_write = sizeof(uint32_t) + sizeof(uint32_t) + ota_test_data.data.len; - for(; bytes_written < (bytes_to_write - MQTT_OTA_BUF_SIZE); bytes_written += MQTT_OTA_BUF_SIZE) - { - ota_logic.onOTADataReceived(ota_test_data.buf + bytes_written, MQTT_OTA_BUF_SIZE); - ota_logic.update(); - } - - if(bytes_written < bytes_to_write) - { - uint32_t const remaining_bytes = (bytes_to_write - bytes_written); - ota_logic.onOTADataReceived(ota_test_data.buf + bytes_written, remaining_bytes); - ota_logic.update(); - } -} - -/************************************************************************************** - TEST CODE - **************************************************************************************/ - -TEST_CASE("No OTA Storage configured", "[OTALogic-01]") -{ - /* Perform test */ - OTALogic ota_logic; - - WHEN("OTALogic::update() is called") - { - ota_logic.update(); - THEN("The OTA logic should be in the 'Error' state") - { - REQUIRE(ota_logic.state() == OTAState::Error); - } - THEN("The OTA error should be set to OTAError::NoOTAStorageConfigured") - { - REQUIRE(ota_logic.error() == OTAError::NoOTAStorageConfigured); - } - } -} - -/**************************************************************************************/ - -TEST_CASE("OTAStorage initialisation fails", "[OTAStorage::init() -> returns false]") -{ - Mock<OTAStorage> ota_storage; - - /* Configure mock object */ - When(Method(ota_storage, init)).Return(false); - Fake(Method(ota_storage, open)); - Fake(Method(ota_storage, write)); - Fake(Method(ota_storage, close)); - Fake(Method(ota_storage, remove)); - Fake(Method(ota_storage, rename)); - Fake(Method(ota_storage, deinit)); - - - /* Perform test */ - OTALogic ota_logic; - ota_logic.setOTAStorage(ota_storage.get()); - - WHEN("OTALogic::update() is called") - { - ota_logic.update(); - THEN("The OTA logic should be in the 'Error' state") - { - REQUIRE(ota_logic.state() == OTAState::Error); - } - THEN("The OTA error should be set to OTAError::StorageInitFailed") - { - REQUIRE(ota_logic.error() == OTAError::StorageInitFailed); - } - } -} - -/**************************************************************************************/ - -TEST_CASE("OTAStorage opening of storage file fails", "[OTAStorage::open() -> returns false]") -{ - Mock<OTAStorage> ota_storage; - - /* Configure mock object */ - When(Method(ota_storage, init)).Return(true); - When(Method(ota_storage, open)).Return(false); - Fake(Method(ota_storage, write)); - Fake(Method(ota_storage, close)); - Fake(Method(ota_storage, remove)); - Fake(Method(ota_storage, rename)); - Fake(Method(ota_storage, deinit)); - - - /* Perform test */ - OTALogic ota_logic; - ota_logic.setOTAStorage(ota_storage.get()); - - WHEN("OTALogic::update() is called and some bytes have been received") - { - uint8_t const SOME_FAKE_DATA[16] = {0}; - ota_logic.onOTADataReceived(SOME_FAKE_DATA, sizeof(SOME_FAKE_DATA)); - ota_logic.update(); - - THEN("The OTA logic should be in the 'Error' state") - { - REQUIRE(ota_logic.state() == OTAState::Error); - } - THEN("The OTA error should be set to OTAError::StorageOpenFailed") - { - REQUIRE(ota_logic.error() == OTAError::StorageOpenFailed); - } - } -} - - -/**************************************************************************************/ - -TEST_CASE("OTAStorage writing to storage file fails", "[OTAStorage::write() -> fails]") -{ - Mock<OTAStorage> ota_storage; - - /* Configure mock object */ - When(Method(ota_storage, init)).Return(true); - When(Method(ota_storage, open)).Return(true); - When(Method(ota_storage, write)).AlwaysDo([](uint8_t const * const /* buf */, size_t const /* num_bytes */) -> size_t { return 0 /* should return num_bytes in case of success */;}); - Fake(Method(ota_storage, close)); - Fake(Method(ota_storage, remove)); - Fake(Method(ota_storage, rename)); - Fake(Method(ota_storage, deinit)); - - - /* Perform test */ - OTALogic ota_logic; - ota_logic.setOTAStorage(ota_storage.get()); - - WHEN("OTALogic::update() is called and some bytes have been received") - { - uint8_t const SOME_FAKE_DATA[16] = {0}; - ota_logic.onOTADataReceived(SOME_FAKE_DATA, sizeof(SOME_FAKE_DATA)); - ota_logic.update(); - - THEN("The OTA logic should be in the 'Error' state") - { - REQUIRE(ota_logic.state() == OTAState::Error); - } - THEN("The OTA error should be set to OTAError::StorageWriteFailed") - { - REQUIRE(ota_logic.error() == OTAError::StorageWriteFailed); - } - } -} - -/**************************************************************************************/ - -TEST_CASE("Data overrun due to receiving too much data", "[OTALogic - Data Overrun]") -{ - Mock<OTAStorage> ota_storage; - - /* Configure mock object */ - When(Method(ota_storage, init)).Return(true); - When(Method(ota_storage, open)).Return(true); - When(Method(ota_storage, write)).AlwaysDo([](uint8_t const * const /* buf */, size_t const num_bytes) -> size_t { return num_bytes; }); - Fake(Method(ota_storage, close)); - Fake(Method(ota_storage, remove)); - Fake(Method(ota_storage, rename)); - Fake(Method(ota_storage, deinit)); - - - /* Perform test */ - OTALogic ota_logic; - ota_logic.setOTAStorage(ota_storage.get()); - - WHEN("Too much data is received before OTALogic::update() is called again to process the incoming data") - { - uint8_t const SOME_FAKE_DATA[MQTT_OTA_BUF_SIZE] = {0}; - ota_logic.onOTADataReceived(SOME_FAKE_DATA, MQTT_OTA_BUF_SIZE); - ota_logic.onOTADataReceived(SOME_FAKE_DATA, MQTT_OTA_BUF_SIZE); - ota_logic.update(); - - THEN("The OTA logic should be in the 'Error' state") - { - REQUIRE(ota_logic.state() == OTAState::Error); - } - THEN("The OTA error should be set to OTAError::ReceivedDataOverrun") - { - REQUIRE(ota_logic.error() == OTAError::ReceivedDataOverrun); - } - } -} - -/**************************************************************************************/ - -TEST_CASE("Valid OTA data is received ", "[OTALogic]") -{ - Mock<OTAStorage> ota_storage; - std::vector<uint8_t> ota_binary_data; - - /* Configure mock object */ - When(Method(ota_storage, init)).Return(true); - When(Method(ota_storage, open)).Return(true); - When(Method(ota_storage, write)).AlwaysDo( - [&ota_binary_data](uint8_t const * const buf, size_t const num_bytes) -> size_t - { - std::copy(buf, buf + num_bytes, std::back_inserter(ota_binary_data)); - return num_bytes; - }); - Fake(Method(ota_storage, close)); - Fake(Method(ota_storage, remove)); - When(Method(ota_storage, rename)).Return(true); - Fake(Method(ota_storage, deinit)); - - - /* Generate test data */ - ota::OTAData valid_ota_test_data; - ota::generate_valid_ota_data(valid_ota_test_data); - - - /* Perform test */ - OTALogic ota_logic; - ota_logic.setOTAStorage(ota_storage.get()); - simulateOTABinaryReception(ota_logic, valid_ota_test_data); - - - /* Perform checks */ - THEN("the complete binary file should have been written to the OTA storage") - { - REQUIRE(ota_binary_data.size() == valid_ota_test_data.data.len); - REQUIRE(std::equal(ota_binary_data.begin(), - ota_binary_data.end(), - valid_ota_test_data.data.bin)); - } - - THEN("The temporary file UPDATE.BIN.TMP should have been renamed to UPDATE.BIN") - { - Verify(Method(ota_storage, rename)).Once(); - } - - THEN("The OTA logic should be in the 'Reset' state") - { - REQUIRE(ota_logic.state() == OTAState::Reset); - } - - THEN("No OTA error should have occurred") - { - REQUIRE(ota_logic.error() == OTAError::None); - } -} - -/**************************************************************************************/ - -TEST_CASE("Valid OTA data is received but the rename step failed (identical too device being turned off during writing of file)", "[OTALogic - Rename fail]") -{ - Mock<OTAStorage> ota_storage; - - /* Configure mock object */ - When(Method(ota_storage, init)).Return(true); - When(Method(ota_storage, open)).Return(true); - When(Method(ota_storage, write)).AlwaysDo([](uint8_t const * const /* buf */, size_t const num_bytes) -> size_t { return num_bytes; }); - Fake(Method(ota_storage, close)); - Fake(Method(ota_storage, remove)); - When(Method(ota_storage, rename)).Return(false); - Fake(Method(ota_storage, deinit)); - - - /* Generate test data */ - ota::OTAData valid_ota_test_data; - ota::generate_valid_ota_data(valid_ota_test_data); - - - /* Perform test */ - OTALogic ota_logic; - ota_logic.setOTAStorage(ota_storage.get()); - simulateOTABinaryReception(ota_logic, valid_ota_test_data); - - - /* Perform checks */ - THEN("The OTA logic should be in the 'Error' state") - { - REQUIRE(ota_logic.state() == OTAState::Error); - } - - THEN("The OTA error should be set to OTAError::RenameOfTempFileFailed") - { - REQUIRE(ota_logic.error() == OTAError::RenameOfTempFileFailed); - } -} - -/**************************************************************************************/ - -TEST_CASE("Invalid OTA data is received ", "[OTALogic - CRC wrong]") -{ - Mock<OTAStorage> ota_storage; - - - /* Configure mock object */ - When(Method(ota_storage, init)).Return(true); - When(Method(ota_storage, open)).Return(true); - When(Method(ota_storage, write)).AlwaysDo([](uint8_t const * const /* buf */, size_t const num_bytes) -> size_t { return num_bytes; }); - Fake(Method(ota_storage, close)); - Fake(Method(ota_storage, remove)); - Fake(Method(ota_storage, rename)); - Fake(Method(ota_storage, deinit)); - - - /* Generate test data */ - ota::OTAData invalid_valid_ota_test_data_crc_wrong; - ota::generate_invalid_ota_data_crc_wrong(invalid_valid_ota_test_data_crc_wrong); - - - /* Perform test */ - OTALogic ota_logic; - ota_logic.setOTAStorage(ota_storage.get()); - simulateOTABinaryReception(ota_logic, invalid_valid_ota_test_data_crc_wrong); - - - /* Perform checks */ - THEN("there should be no binary file be stored on the OTA storage") - { - Verify(Method(ota_storage, remove)).Once(); - } - - THEN("The OTA logic should be in the 'Error' state") - { - REQUIRE(ota_logic.state() == OTAState::Error); - } - - THEN("The OTA error should be set to OTAError::ChecksumMismatch") - { - REQUIRE(ota_logic.error() == OTAError::ChecksumMismatch); - } -} \ No newline at end of file diff --git a/extras/test/src/util/OTATestUtil.cpp b/extras/test/src/util/OTATestUtil.cpp deleted file mode 100644 index ac7e26026..000000000 --- a/extras/test/src/util/OTATestUtil.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2020 Arduino. All rights reserved. - */ - -/************************************************************************************** - INCLUDE - **************************************************************************************/ - -#include <util/OTATestUtil.h> - -#include <algorithm> - -#include <crc.h> - -/************************************************************************************** - NAMESPACE - **************************************************************************************/ - -namespace ota -{ - -/************************************************************************************** - FUNCTION DEFINITION - **************************************************************************************/ - -void generate_valid_ota_data(OTAData & ota_data) -{ - /* Set length. Attention: header length (8 bytes for len and crc32 are not included - this is only the payload length. */ - ota_data.data.len = 64 * 1024; - - /* Fill array */ - std::generate(ota_data.data.bin, - ota_data.data.bin + ota_data.data.len, - [](void) -> uint8_t - { - static uint8_t val = 0; - return val++; - }); - - /* Generate CRC */ - crc_t crc32 = crc_init(); - std::for_each(ota_data.data.bin, - ota_data.data.bin + ota_data.data.len, - [&crc32](uint8_t const data) - { - crc32 = crc_update(crc32, &data, 1); - }); - ota_data.data.crc32 = crc_finalize(crc32); -} - -void generate_invalid_ota_data_crc_wrong(OTAData & ota_data) -{ - /* Set length. Attention: header length (8 bytes for len and crc32 are not included - this is only the payload length. */ - ota_data.data.len = 64 * 1024; - - /* Fill array */ - std::generate(ota_data.data.bin, - ota_data.data.bin + ota_data.data.len, - [](void) -> uint8_t - { - static uint8_t val = 0; - return val++; - }); - - /* Generate CRC */ - ota_data.data.crc32 = 0xDEADBEEF; -} - -/************************************************************************************** - NAMESPACE - **************************************************************************************/ - -} /* ota */ diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 10999e584..f1c2825c1 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -28,25 +28,11 @@ #include "tls/utility/CryptoUtil.h" #endif +#include "utility/ota/OTA.h" #include "utility/ota/FlashSHA256.h" -#include "utility/ota/OTAStorage_SNU.h" -#include "utility/ota/OTAStorage_SFU.h" -#include "utility/ota/OTAStorage_SSU.h" #include "cbor/CBOREncoder.h" -/****************************************************************************** - GLOBAL VARIABLES - ******************************************************************************/ - -#if OTA_STORAGE_SSU - static OTAStorage_SSU ota_storage_ssu; -#elif OTA_STORAGE_SFU - static OTAStorage_SFU ota_storage_sfu; -#elif OTA_STORAGE_SNU - static OTAStorage_SNU ota_storage_snu; -#endif - /****************************************************************************** GLOBAL CONSTANTS ******************************************************************************/ @@ -85,10 +71,11 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _shadowTopicIn("") , _dataTopicOut("") , _dataTopicIn("") -, _ota_topic_in{""} #if OTA_ENABLED , _ota_error{static_cast<int>(OTAError::None)} , _ota_img_sha256{"Inv."} +, _ota_url{""} +, _ota_req{false} #endif /* OTA_ENABLED */ { @@ -151,30 +138,19 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) _shadowTopicIn = getTopic_shadowin(); _dataTopicOut = getTopic_dataout(); _dataTopicIn = getTopic_datain(); - _ota_topic_in = getTopic_ota_in(); - -#if OTA_STORAGE_SSU - setOTAStorage(ota_storage_ssu); -#elif OTA_STORAGE_SFU - setOTAStorage(ota_storage_sfu); -#elif OTA_STORAGE_SNU - setOTAStorage(ota_storage_snu); -#endif + +#if OTA_ENABLED + addPropertyReal(_ota_error, "OTA_ERROR", Permission::Read); + addPropertyReal(_ota_img_sha256, "OTA_SHA256", Permission::Read); + addPropertyReal(_ota_url, "OTA_URL", Permission::ReadWrite).onSync(DEVICE_WINS); + addPropertyReal(_ota_req, "OTA_REQ", Permission::ReadWrite).onSync(DEVICE_WINS).onUpdate(ArduinoIoTCloudTCP::on_OTA_REQ_Update); +#endif /* OTA_ENABLED */ return 1; } void ArduinoIoTCloudTCP::update() { -#if OTA_ENABLED - /* If a _ota_logic object has been instantiated then we are spinning its - * 'update' method here in order to process incoming data and generally - * to transition to the OTA logic update states. - */ - OTAError const err = _ota_logic.update(); - _ota_error = static_cast<int>(err); -#endif /* OTA_ENABLED */ - /* Run through the state machine. */ State next_state = _state; switch (_state) @@ -206,15 +182,6 @@ void ArduinoIoTCloudTCP::printDebugInfo() DBG_INFO("MQTT Broker: %s:%d", _brokerAddress.c_str(), _brokerPort); } -#if OTA_ENABLED -void ArduinoIoTCloudTCP::setOTAStorage(OTAStorage & ota_storage) -{ - addPropertyReal(_ota_error, "OTA_ERROR", Permission::Read); - addPropertyReal(_ota_img_sha256, "OTA_SHA256", Permission::Read); - _ota_logic.setOTAStorage(ota_storage); -} -#endif /* OTA_ENABLED */ - /****************************************************************************** * PRIVATE MEMBER FUNCTIONS ******************************************************************************/ @@ -257,17 +224,11 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() return State::SubscribeMqttTopics; } - if (!_mqttClient.subscribe(_ota_topic_in)) - { - DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _ota_topic_in.c_str()); - return State::SubscribeMqttTopics; - } - if (_shadowTopicIn != "") { if (!_mqttClient.subscribe(_shadowTopicIn)) { - DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _ota_topic_in.c_str()); + DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); return State::SubscribeMqttTopics; } } @@ -368,12 +329,6 @@ void ArduinoIoTCloudTCP::handleMessage(int length) execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); _state = State::Connected; } - -#if OTA_ENABLED - if (_ota_topic_in == topic) { - _ota_logic.onOTADataReceived(bytes, length); - } -#endif /* OTA_ENABLED */ } void ArduinoIoTCloudTCP::sendPropertiesToCloud() @@ -415,6 +370,52 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l return 0; } +#if OTA_ENABLED +void ArduinoIoTCloudTCP::on_OTA_REQ_Update() +{ + ArduinoCloud.onOTARequest(); +} + +void ArduinoIoTCloudTCP::onOTARequest() +{ + DBG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_req = %s", __FUNCTION__, _ota_req ? "true" : "false"); + DBG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str()); + + if (_ota_req) + { + /* Clear the request flag. */ + _ota_req = false; + + /* Status flag to prevent the reset from being executed + * when HTTPS download is not supported. + */ + bool ota_download_success = false; + +#if OTA_STORAGE_SNU + /* Just to be safe delete any remains from previous updates. */ + WiFiStorage.remove("/fs/UPDATE.BIN.LZSS"); + WiFiStorage.remove("/fs/UPDATE.BIN.LZSS.TMP"); + + /* Trigger direct download to nina module. */ + uint8_t nina_ota_err_code = 0; + if (!WiFiStorage.downloadOTA(_ota_url.c_str(), &nina_ota_err_code)) + { + DBG_ERROR("ArduinoIoTCloudTCP::%s error download to nina: %d", __FUNCTION__, nina_ota_err_code); + _ota_error = static_cast<int>(OTAError::DownloadFailed); + return; + } + + /* The download was a success. */ + ota_download_success = true; +#endif /* OTA_STORAGE_SNU */ + + /* Perform the reset to reboot to SxU. */ + if (ota_download_success) + NVIC_SystemReset(); + } +} +#endif + /****************************************************************************** * EXTERN DEFINITION ******************************************************************************/ diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 2e9200725..3dc76dc61 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -35,11 +35,6 @@ #include <ArduinoMqttClient.h> -#if OTA_ENABLED - #include "utility/ota/OTALogic.h" - #include "utility/ota/OTAStorage.h" -#endif /* OTA_ENABLED */ - /****************************************************************************** CONSTANTS ******************************************************************************/ @@ -80,10 +75,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass inline String getBrokerAddress() const { return _brokerAddress; } inline uint16_t getBrokerPort () const { return _brokerPort; } -#if OTA_ENABLED - void setOTAStorage(OTAStorage & ota_storage); -#endif /* OTA_ENABLED */ - private: static const int MQTT_TRANSMIT_BUFFER_SIZE = 256; @@ -124,12 +115,12 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass String _shadowTopicIn; String _dataTopicOut; String _dataTopicIn; - String _ota_topic_in; #if OTA_ENABLED - OTALogic _ota_logic; int _ota_error; String _ota_img_sha256; + String _ota_url; + bool _ota_req; #endif /* OTA_ENABLED */ inline String getTopic_stdin () { return String("/a/d/" + getDeviceId() + "/s/i"); } @@ -138,7 +129,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass inline String getTopic_shadowin () { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/shadow/i"); } inline String getTopic_dataout () { return ( getThingId().length() == 0) ? String("/a/d/" + getDeviceId() + "/e/o") : String("/a/t/" + getThingId() + "/e/o"); } inline String getTopic_datain () { return ( getThingId().length() == 0) ? String("/a/d/" + getDeviceId() + "/e/i") : String("/a/t/" + getThingId() + "/e/i"); } - inline String getTopic_ota_in () { return String("/a/d/" + getDeviceId() + "/ota/i"); } State handle_ConnectPhy(); State handle_SyncTime(); @@ -153,6 +143,10 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass void requestLastValue(); int write(String const topic, byte const data[], int const length); +#if OTA_ENABLED + static void on_OTA_REQ_Update(); + void onOTARequest(); +#endif }; /****************************************************************************** diff --git a/src/utility/ota/OTAStorage.h b/src/utility/ota/OTA.h similarity index 67% rename from src/utility/ota/OTAStorage.h rename to src/utility/ota/OTA.h index 4029f81dd..208d5e616 100644 --- a/src/utility/ota/OTAStorage.h +++ b/src/utility/ota/OTA.h @@ -15,36 +15,38 @@ a commercial license, send an email to license@arduino.cc. */ -#ifndef ARDUINO_OTA_STORAGE_H_ -#define ARDUINO_OTA_STORAGE_H_ +#ifndef ARDUINO_OTA_LOGIC_H_ +#define ARDUINO_OTA_LOGIC_H_ /****************************************************************************** * INCLUDE ******************************************************************************/ -#include <stdlib.h> -#include <stdint.h> -#include <stdbool.h> +#include <AIoTC_Config.h> +#if OTA_ENABLED -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class OTAStorage -{ -public: +#if OTA_STORAGE_SNU + #include <SNU.h> +#endif /* OTA_STORAGE_SNU */ - virtual ~OTAStorage() { } +#if OTA_STORAGE_SSU + #include <SSU.h> +#endif /* OTA_STORAGE_SSU */ +#if OTA_STORAGE_SFU + #include <SFU.h> +#endif /* OTA_STORAGE_SFU */ - virtual bool init () = 0; - virtual bool open () = 0; - virtual size_t write (uint8_t const * const buf, size_t const num_bytes) = 0; - virtual void close () = 0; - virtual void remove() = 0; - virtual bool rename() = 0; - virtual void deinit() = 0; +/****************************************************************************** + * TYPEDEF + ******************************************************************************/ +enum class OTAError : int +{ + None = 0, + DownloadFailed = 1, }; -#endif /* ARDUINO_OTA_STORAGE_H_ */ +#endif /* OTA_ENABLED */ + +#endif /* ARDUINO_OTA_LOGIC_H_ */ diff --git a/src/utility/ota/OTALogic.cpp b/src/utility/ota/OTALogic.cpp deleted file mode 100644 index b04b4d9f2..000000000 --- a/src/utility/ota/OTALogic.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* - 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 - ******************************************************************************/ - -#ifndef HOST - #include <AIoTC_Config.h> -#else - #define OTA_ENABLED (1) -#endif -#if OTA_ENABLED - -#include "OTALogic.h" - -#ifndef HOST - #include <Arduino.h> - #include <Arduino_DebugUtils.h> -#else - #include <algorithm> /* for std::min, otherwise Arduino defines min() */ - using namespace std; -#endif - -#include <string.h> - -/****************************************************************************** - * CTOR/DTOR - ******************************************************************************/ - -OTALogic::OTALogic() -: _is_configured{false} -, _ota_storage{nullptr} -, _ota_state{OTAState::Init} -, _ota_error{OTAError::None} -{ - init_mqtt_ota_buffer(); - init_ota_binary_data(); -} - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -void OTALogic::setOTAStorage(OTAStorage & ota_storage) -{ - _ota_storage = &ota_storage; - _is_configured = true; -} - -OTAError OTALogic::update() -{ - /* This if clause should never happen. None the less we - * should insure ourselves against this scenario because - * otherwise we'll have a nullptr dereferencing. - */ - if (!_is_configured) { - _ota_state = OTAState::Error; - _ota_error = OTAError::NoOTAStorageConfigured; - return _ota_error; - } - - OTAState prev_ota_state; - /* The purpose of this loop is to allow the transition of - * more than one state per a singular call of 'update'. If - * no state transitition takes place then the loop is exited - * because it means that external input (such as the arrival) - * of new data is required. - */ - do - { - prev_ota_state = _ota_state; - switch(_ota_state) - { - case OTAState::Init: _ota_state = handle_Init (); break; - case OTAState::Idle: _ota_state = handle_Idle (); break; - case OTAState::StartDownload: _ota_state = handle_StartDownload (); break; - case OTAState::WaitForHeader: _ota_state = handle_WaitForHeader (); break; - case OTAState::HeaderReceived: _ota_state = handle_HeaderReceived(); break; - case OTAState::WaitForBinary: _ota_state = handle_WaitForBinary (); break; - case OTAState::BinaryReceived: _ota_state = handle_BinaryReceived(); break; - case OTAState::Verify: _ota_state = handle_Verify (); break; - case OTAState::Rename: _ota_state = handle_Rename (); break; - case OTAState::Reset: _ota_state = handle_Reset (); break; - case OTAState::Error: break; - } - } while(_ota_state != prev_ota_state); - - return _ota_error; -} - -void OTALogic::onOTADataReceived(uint8_t const * const data, size_t const length) -{ - size_t const bytes_available = (MQTT_OTA_BUF_SIZE - _mqtt_ota_buf.num_bytes); - if(length <= bytes_available) - { - memcpy(_mqtt_ota_buf.buf + _mqtt_ota_buf.num_bytes, data, length); - _mqtt_ota_buf.num_bytes += length; - } - else - { - _ota_state = OTAState::Error; - _ota_error = OTAError::ReceivedDataOverrun; - } -} - -/****************************************************************************** - * PRIVATE MEMBER FUNCTIONS - ******************************************************************************/ - -OTAState OTALogic::handle_Init() -{ -#ifndef HOST - DBG_VERBOSE("OTALogic::%s", __FUNCTION__); -#endif - if (_ota_storage->init()) { - return OTAState::Idle; - } else { - _ota_error = OTAError::StorageInitFailed; - return OTAState::Error; - } -} - -OTAState OTALogic::handle_Idle() -{ - if(_mqtt_ota_buf.num_bytes > 0) { - return OTAState::StartDownload; - } - return OTAState::Idle; -} - -OTAState OTALogic::handle_StartDownload() -{ -#ifndef HOST - DBG_VERBOSE("OTALogic::%s", __FUNCTION__); -#endif - if(_ota_storage->open()) { - return OTAState::WaitForHeader; - } else { - _ota_error = OTAError::StorageOpenFailed; - return OTAState::Error; - } -} - -OTAState OTALogic::handle_WaitForHeader() -{ -#ifndef HOST - DBG_VERBOSE("OTALogic::%s", __FUNCTION__); -#endif - if(_mqtt_ota_buf.num_bytes >= OTA_BINARY_HEADER_SIZE) { - return OTAState::HeaderReceived; - } - return OTAState::WaitForHeader; -} - -OTAState OTALogic::handle_HeaderReceived() -{ - /* The OTA header has been received, let's extract it - * from the MQTT OTA receive buffer. - */ - union OTAHeader - { - struct __attribute__((packed)) - { - uint32_t len; - uint32_t crc32; - } header; - uint8_t buf[sizeof(header)]; - }; - - OTAHeader ota_header; - memcpy(ota_header.buf, _mqtt_ota_buf.buf, OTA_BINARY_HEADER_SIZE); - - /* Assign the extracted header values to the member variables */ - _ota_bin_data.hdr_len = ota_header.header.len; - _ota_bin_data.hdr_crc32 = ota_header.header.crc32; - -#ifndef HOST - DBG_VERBOSE("OTALogic::%s: header length = %d", __FUNCTION__, _ota_bin_data.hdr_len); - DBG_VERBOSE("OTALogic::%s: header crc32 = %X", __FUNCTION__, _ota_bin_data.hdr_crc32); -#endif - - /* Reset the counter which is responsible for keeping tabs on how many bytes have been received */ - _ota_bin_data.bytes_received = 0; - - /* Initialize the CRC variable for calculating the CRC32 of the received data package */ - _ota_bin_data.crc32 = crc_init(); - - /* Eliminate the header from the receive buffer and transition to WaitForBinary state. */ - memcpy(_mqtt_ota_buf.buf, - _mqtt_ota_buf.buf + OTA_BINARY_HEADER_SIZE, - _mqtt_ota_buf.num_bytes - OTA_BINARY_HEADER_SIZE); - _mqtt_ota_buf.num_bytes -= OTA_BINARY_HEADER_SIZE; - - return OTAState::WaitForBinary; -} - -OTAState OTALogic::handle_WaitForBinary() -{ - if (_mqtt_ota_buf.num_bytes > 0) { - return OTAState::BinaryReceived; - } - return OTAState::WaitForBinary; -} - -OTAState OTALogic::handle_BinaryReceived() -{ - /* Write to OTA storage */ - if(_ota_storage->write(_mqtt_ota_buf.buf, _mqtt_ota_buf.num_bytes) != _mqtt_ota_buf.num_bytes) - { - _ota_error = OTAError::StorageWriteFailed; - return OTAState::Error; - } - - /* Update CRC32 */ - _ota_bin_data.crc32 = crc_update(_ota_bin_data.crc32, _mqtt_ota_buf.buf, _mqtt_ota_buf.num_bytes); - - /* Update received data counters and clear MQTT OTA receive buffer */ - _ota_bin_data.bytes_received += _mqtt_ota_buf.num_bytes; - _mqtt_ota_buf.num_bytes = 0; - -#ifndef HOST - DBG_VERBOSE("OTALogic::%s: %d bytes written", __FUNCTION__, _ota_bin_data.bytes_received); -#endif - - if(_ota_bin_data.bytes_received >= _ota_bin_data.hdr_len) { - _ota_storage->close(); - _ota_bin_data.crc32 = crc_finalize(_ota_bin_data.crc32); - return OTAState::Verify; - } - - return OTAState::WaitForBinary; -} - -OTAState OTALogic::handle_Verify() -{ -#ifndef HOST - DBG_VERBOSE("OTALogic::%s", __FUNCTION__); -#endif - if(_ota_bin_data.crc32 == _ota_bin_data.hdr_crc32) { - return OTAState::Rename; - } else { - _ota_storage->remove(); - _ota_error = OTAError::ChecksumMismatch; - return OTAState::Error; - } -} - -OTAState OTALogic::handle_Rename() -{ -#ifndef HOST - DBG_VERBOSE("OTALogic::%s", __FUNCTION__); -#endif - if(_ota_storage->rename()) { - _ota_storage->deinit(); - return OTAState::Reset; - } - else { - _ota_error = OTAError::RenameOfTempFileFailed; - return OTAState::Error; - } -} - -OTAState OTALogic::handle_Reset() -{ -#if !defined(HOST) && !defined(ESP8266) - /* After completion of the reset a second stage bootloader - * such as the SFU is examining the OTA storage medium for - * the existence of a binary update file. Should such a file - * exist the 2nd stage bootloader if performing the firmware - * update before starting the application, otherwise the app - * is started directly. - */ -#ifndef HOST - DBG_VERBOSE("OTALogic::%s", __FUNCTION__); - delay(250); -#endif - NVIC_SystemReset(); -#endif /* HOST */ - return OTAState::Reset; -} - -void OTALogic::init_mqtt_ota_buffer() -{ - memset(_mqtt_ota_buf.buf, 0U, sizeof(_mqtt_ota_buf.buf)); - _mqtt_ota_buf.num_bytes = 0; -} - -void OTALogic::init_ota_binary_data() -{ - _ota_bin_data.hdr_len = 0; - _ota_bin_data.hdr_crc32 = 0; - _ota_bin_data.bytes_received = 0; - _ota_bin_data.crc32 = crc_init(); -} - -#endif /* OTA_ENABLED */ diff --git a/src/utility/ota/OTALogic.h b/src/utility/ota/OTALogic.h deleted file mode 100644 index 3f3a3c31f..000000000 --- a/src/utility/ota/OTALogic.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - 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. -*/ - -#ifndef ARDUINO_OTA_LOGIC_H_ -#define ARDUINO_OTA_LOGIC_H_ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#ifndef HOST - #include <AIoTC_Config.h> -#else - #define OTA_ENABLED (1) -#endif -#if OTA_ENABLED - -#include "OTAStorage.h" - -#include "crc.h" - -/****************************************************************************** - * CONSTANT - ******************************************************************************/ - -static size_t const MQTT_OTA_BUF_SIZE = 256; - -/****************************************************************************** - * TYPEDEF - ******************************************************************************/ - -enum class OTAState -{ - Init, Idle, StartDownload, WaitForHeader, HeaderReceived, WaitForBinary, BinaryReceived, Verify, Rename, Reset, Error -}; - -enum class OTAError : int -{ - None = 0, - StorageInitFailed = 1, - StorageOpenFailed = 2, - StorageWriteFailed = 3, - ChecksumMismatch = 4, - ReceivedDataOverrun = 5, - RenameOfTempFileFailed = 6, - NoOTAStorageConfigured = 7 -}; - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class OTALogic -{ - -public: - - OTALogic(); - - - void setOTAStorage(OTAStorage & ota_storage); - - - OTAError update(); - void onOTADataReceived(uint8_t const * const data, size_t const length); - -#ifdef HOST - inline OTAState state() const { return _ota_state; } - inline OTAError error() const { return _ota_error; } -#endif - - -private: - - typedef struct - { - size_t num_bytes; - uint8_t buf[MQTT_OTA_BUF_SIZE]; - } sMQTTOTABuffer; - - typedef struct - { - uint32_t hdr_len; - uint32_t hdr_crc32; - uint32_t bytes_received; - crc_t crc32; - } sOTABinaryData; - - bool _is_configured; - OTAStorage * _ota_storage; - OTAState _ota_state; - OTAError _ota_error; - sMQTTOTABuffer _mqtt_ota_buf; - sOTABinaryData _ota_bin_data; - - static size_t const OTA_BINARY_HEADER_SIZE = sizeof(_ota_bin_data.hdr_len) + sizeof(_ota_bin_data.hdr_crc32); - - OTAState handle_Init(); - OTAState handle_Idle(); - OTAState handle_StartDownload(); - OTAState handle_WaitForHeader(); - OTAState handle_HeaderReceived(); - OTAState handle_WaitForBinary(); - OTAState handle_BinaryReceived(); - OTAState handle_Verify(); - OTAState handle_Rename(); - OTAState handle_Reset(); - - void init_mqtt_ota_buffer(); - void init_ota_binary_data(); - -}; - -#endif /* OTA_ENABLED */ - -#endif /* ARDUINO_OTA_LOGIC_H_ */ diff --git a/src/utility/ota/OTAStorage_SFU.cpp b/src/utility/ota/OTAStorage_SFU.cpp deleted file mode 100644 index c5046d595..000000000 --- a/src/utility/ota/OTAStorage_SFU.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - 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 <AIoTC_Config.h> -#if OTA_STORAGE_SFU - -#include "OTAStorage_SFU.h" - -#include <Arduino_DebugUtils.h> - -/****************************************************************************** - * CONSTANTS - ******************************************************************************/ - -static char const SFU_UPDATE_FILENAME[] = "UPDATE.BIN"; -static char const SFU_TEMP_UPDATE_FILENAME[] = "UPDATE.BIN.TMP"; - -/****************************************************************************** - * CTOR/DTOR - ******************************************************************************/ - -OTAStorage_SFU::OTAStorage_SFU() -: _file{nullptr} -{ - -} - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -bool OTAStorage_SFU::init() -{ - flash.begin(); - if(SPIFFS_OK != filesystem.mount()) { - DBG_ERROR("OTAStorage_SFU::init - mount() failed with error code %d", filesystem.err()); - return false; - } - - if(SPIFFS_OK != filesystem.check()) { - DBG_ERROR("OTAStorage_SFU::init - check() failed with error code %d", filesystem.err()); - return false; - } - - return true; -} - -bool OTAStorage_SFU::open() -{ - filesystem.clearerr(); - _file = new File(filesystem.open(SFU_TEMP_UPDATE_FILENAME, CREATE | WRITE_ONLY| TRUNCATE)); - if(SPIFFS_OK != filesystem.err()) { - DBG_ERROR("OTAStorage_SFU::open - open() failed with error code %d", filesystem.err()); - delete _file; - return false; - } - return true; -} - -size_t OTAStorage_SFU::write(uint8_t const * const buf, size_t const num_bytes) -{ - return _file->write(const_cast<uint8_t *>(buf), num_bytes); -} - -void OTAStorage_SFU::close() -{ - _file->close(); - delete _file; -} - -void OTAStorage_SFU::remove() -{ - filesystem.remove(SFU_TEMP_UPDATE_FILENAME); -} - -bool OTAStorage_SFU::rename() -{ - return (SPIFFS_OK == filesystem.rename(SFU_TEMP_UPDATE_FILENAME, SFU_UPDATE_FILENAME)); -} - -void OTAStorage_SFU::deinit() -{ - filesystem.unmount(); -} - -#endif /* OTA_STORAGE_SFU */ diff --git a/src/utility/ota/OTAStorage_SFU.h b/src/utility/ota/OTAStorage_SFU.h deleted file mode 100644 index c22099bee..000000000 --- a/src/utility/ota/OTAStorage_SFU.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - 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. -*/ - -#ifndef ARDUINO_OTA_STORAGE_SFU_H_ -#define ARDUINO_OTA_STORAGE_SFU_H_ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include <AIoTC_Config.h> -#if OTA_STORAGE_SFU - -#include "OTAStorage.h" - -#include <SFU.h> - -#include <Arduino_MKRMEM.h> - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class OTAStorage_SFU : public OTAStorage -{ -public: - - OTAStorage_SFU(); - virtual ~OTAStorage_SFU() { } - - - virtual bool init () override; - virtual bool open () override; - virtual size_t write (uint8_t const * const buf, size_t const num_bytes) override; - virtual void close () override; - virtual void remove() override; - virtual bool rename() override; - virtual void deinit() override; - - -private: - - File * _file; - -}; - -#endif /* OTA_STORAGE_SFU */ - -#endif /* ARDUINO_OTA_STORAGE_SFU_H_ */ diff --git a/src/utility/ota/OTAStorage_SNU.cpp b/src/utility/ota/OTAStorage_SNU.cpp deleted file mode 100644 index c3325b11b..000000000 --- a/src/utility/ota/OTAStorage_SNU.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - 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 <AIoTC_Config.h> -#if OTA_STORAGE_SNU - -#include "OTAStorage_SNU.h" - -#include <WiFiStorage.h> - -/****************************************************************************** - * CONSTANTS - ******************************************************************************/ - -static char const SNU_UPDATE_FILENAME[] = "/fs/UPDATE.BIN.LZSS"; -static char const SNU_TEMP_UPDATE_FILENAME[] = "/fs/UPDATE.BIN.TMP.LZSS"; - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -bool OTAStorage_SNU::init() -{ - /* Ensure that there are no remains of previous - * aborted downloads still existing in the memory - * of the nina module. - */ - WiFiStorage.remove(SNU_TEMP_UPDATE_FILENAME); - return true; -} - -bool OTAStorage_SNU::open() -{ - /* There's no need to explicitly open the file - * because when writing to it the file will always - * be opened with "ab+" mode and closed after each - * call to 'write'. - */ - return true; -} - -size_t OTAStorage_SNU::write(uint8_t const * const buf, size_t const num_bytes) -{ - WiFiStorageFile file(SNU_TEMP_UPDATE_FILENAME); - - /* We have to write in chunks because otherwise we exceed the size of - * the SPI buffer within the nina module. - */ - size_t bytes_written = 0; - size_t const WRITE_CHUNK_SIZE = 32; - - for(; bytes_written < (num_bytes - WRITE_CHUNK_SIZE); bytes_written += WRITE_CHUNK_SIZE) - { - if (file.write(buf + bytes_written, WRITE_CHUNK_SIZE) != WRITE_CHUNK_SIZE) - return bytes_written; - } - - bytes_written += file.write(buf + bytes_written, num_bytes - bytes_written); - - return bytes_written; -} - -void OTAStorage_SNU::close() -{ - /* Files are closed after each file operation on the nina side. */ -} - -void OTAStorage_SNU::remove() -{ - WiFiStorage.remove(SNU_TEMP_UPDATE_FILENAME); -} - -bool OTAStorage_SNU::rename() -{ - return WiFiStorage.rename(SNU_TEMP_UPDATE_FILENAME, SNU_UPDATE_FILENAME); -} - -void OTAStorage_SNU::deinit() -{ - /* Nothing to do */ -} - -#endif /* OTA_STORAGE_SNU */ diff --git a/src/utility/ota/OTAStorage_SNU.h b/src/utility/ota/OTAStorage_SNU.h deleted file mode 100644 index c9fbc2619..000000000 --- a/src/utility/ota/OTAStorage_SNU.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - 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. -*/ - -#ifndef ARDUINO_OTA_STORAGE_SNU_H_ -#define ARDUINO_OTA_STORAGE_SNU_H_ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include <AIoTC_Config.h> -#if OTA_STORAGE_SNU - -#include <SNU.h> - -#include "OTAStorage.h" - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class OTAStorage_SNU : public OTAStorage -{ -public: - - virtual ~OTAStorage_SNU() { } - - - virtual bool init () override; - virtual bool open () override; - virtual size_t write (uint8_t const * const buf, size_t const num_bytes) override; - virtual void close () override; - virtual void remove() override; - virtual bool rename() override; - virtual void deinit() override; - -}; - -#endif /* OTA_STORAGE_SNU */ - -#endif /* ARDUINO_OTA_STORAGE_SNU_H_ */ diff --git a/src/utility/ota/OTAStorage_SSU.cpp b/src/utility/ota/OTAStorage_SSU.cpp deleted file mode 100644 index a8023ac1d..000000000 --- a/src/utility/ota/OTAStorage_SSU.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - 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 <AIoTC_Config.h> -#if OTA_STORAGE_SSU - -#include "OTAStorage_SSU.h" - -/****************************************************************************** - CONSTANTS - ******************************************************************************/ - -static char const SSU_UPDATE_FILENAME[] = "UPDATE.BIN.LZSS"; -static char const SSU_CHECK_FILE_NAME[] = "UPDATE.OK"; - -/****************************************************************************** - PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -bool OTAStorage_SSU::init() -{ - if (!_fileUtils.begin()) - return false; - - if (_fileUtils.listFile(SSU_UPDATE_FILENAME) > 0) - if (!_fileUtils.deleteFile(SSU_UPDATE_FILENAME)) - return false; - - if (_fileUtils.listFile(SSU_CHECK_FILE_NAME) > 0) - if (!_fileUtils.deleteFile(SSU_CHECK_FILE_NAME)) - return false; -} - -bool OTAStorage_SSU::open() -{ - return true; -} - -size_t OTAStorage_SSU::write(uint8_t const* const buf, size_t const num_bytes) -{ - _fileUtils.appendFile(SSU_UPDATE_FILENAME, (const char*)buf, num_bytes); - return num_bytes; -} - -void OTAStorage_SSU::close() -{ - /* Nothing to do */ -} - -void OTAStorage_SSU::remove() -{ - _fileUtils.deleteFile(SSU_UPDATE_FILENAME); -} - -bool OTAStorage_SSU::rename() -{ - /* Create a file 'UPDATE.OK' which is used by the SSU - * 2nd stage bootloader to recognise that the update - * went okay. Normally this is done by renaming 'UPDATE.BIN.TMP' - * to 'UPDATE.BIN' but the SARE module does not support - * a rename function. - */ - char c = 'X'; - return (_fileUtils.appendFile(SSU_CHECK_FILE_NAME, &c, sizeof(c)) == sizeof(c)); -} - -void OTAStorage_SSU::deinit() -{ - /* Nothing to do */ -} - -#endif /* OTA_STORAGE_SSU */ diff --git a/src/utility/ota/OTAStorage_SSU.h b/src/utility/ota/OTAStorage_SSU.h deleted file mode 100644 index 99f1bf6ec..000000000 --- a/src/utility/ota/OTAStorage_SSU.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - 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. -*/ - -#ifndef ARDUINO_OTA_STORAGE_SSU_H_ -#define ARDUINO_OTA_STORAGE_SSU_H_ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include <AIoTC_Config.h> -#if OTA_STORAGE_SSU - -#include <SSU.h> - -#include "OTAStorage.h" - -#include <GSMFileUtils.h> - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class OTAStorage_SSU : public OTAStorage -{ -public: - - virtual ~OTAStorage_SSU() { } - - - virtual bool init () override; - virtual bool open () override; - virtual size_t write (uint8_t const * const buf, size_t const num_bytes) override; - virtual void close () override; - virtual void remove() override; - virtual bool rename() override; - virtual void deinit() override; - -private: - - GSMFileUtils _fileUtils; - -}; - -#endif /* OTA_STORAGE_SSU */ - -#endif /* ARDUINO_OTA_STORAGE_SSU_H_ */