From e160d5428ca6e2ce66c3a39d6d682286fc238df4 Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 15 Dec 2020 01:30:25 -0800 Subject: [PATCH 001/780] Use default branch of ArduinoCore-API in CI workflow (#214) Previously, the "namespace_arduino" branch of ArduinoCore-API was used in the core library of the development version of the Mbed OS Boards platform used in the "Compile Examples" CI workflow. The default branch of ArduinoCore-API is now the latest and greatest version, so the "namespace_arduino" branch should no longer be used. for Mbed OS core library --- .github/workflows/compile-examples.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 28e48bb07..791837157 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -159,7 +159,6 @@ jobs: with: repository: arduino/ArduinoCore-API # as specified at https://github.com/arduino/ArduinoCore-mbed/blob/master/README.md#installation - ref: namespace_arduino path: ${{ env.ARDUINOCORE_API_STAGING_PATH }} - name: Install ArduinoCore-API From 15ae8856b864f643f519c06c76423315d4f924ee Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 15 Dec 2020 01:31:14 -0800 Subject: [PATCH 002/780] Remove api symlink deletion step from CI workflow (#213) The symlink for ArduinoCore-API in the Mbed OS Boards core library has been removed. This resulted in the step of the "Compile Examples" CI workflow that removes the now non-existent symlink to fail. --- .github/workflows/compile-examples.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 791837157..d448929b9 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -147,11 +147,6 @@ jobs: # the arduino/actions/libraries/compile-examples action will install the platform from this path path: ${{ env.ARDUINOCORE_MBED_STAGING_PATH }} - - name: Remove ArduinoCore-API symlink from Arduino mbed-Enabled Boards platform - # this step only needed when the Arduino mbed-Enabled Boards platform sourced from the repository is being used - if: matrix.board.type == 'mbed' - run: rm "${{ env.ARDUINOCORE_MBED_STAGING_PATH }}/cores/arduino/api" - - name: Checkout ArduinoCore-API # this step only needed when the Arduino mbed-Enabled Boards platform sourced from the repository is being used if: matrix.board.type == 'mbed' From 9ecfe6bfc5f8ceb67bc10eedeb6d5e7ca3daf6a1 Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 12 Jan 2021 19:58:13 -0800 Subject: [PATCH 003/780] Add ESP32 board to "Compile Examples" CI workflow ESP32 support has been added to the library, so the examples compilation smoke test should be done for this architecture as well. --- .github/workflows/compile-examples.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index d448929b9..594788ae4 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -46,7 +46,8 @@ jobs: {"fqbn": "arduino:samd:mkrnb1500", "type": "nb"}, {"fqbn": "arduino:mbed:envie_m4", "type": "mbed"}, {"fqbn": "arduino:mbed:envie_m7", "type": "mbed"}, - {"fqbn": "esp8266:esp8266:huzzah", "type": "esp8266"} + {"fqbn": "esp8266:esp8266:huzzah", "type": "esp8266"}, + {"fqbn": "esp32:esp32:esp32", "type": "esp32"} ] # make board type-specific customizations to the matrix jobs @@ -132,6 +133,15 @@ jobs: source-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json libraries: sketch-paths: + # ESP32 boards + - board: + type: "esp32" + platforms: | + # Install ESP32 platform via Boards Manager + - name: esp32:esp32 + source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json + libraries: + sketch-paths: steps: - name: Checkout @@ -162,6 +172,10 @@ jobs: run: | mv "${{ env.ARDUINOCORE_API_STAGING_PATH }}/api" "${{ env.ARDUINOCORE_MBED_STAGING_PATH }}/cores/arduino" + - name: Install ESP32 platform dependencies + if: matrix.board.type == 'esp32' + run: pip3 install pyserial + - name: Compile examples uses: arduino/compile-sketches@main with: From 4cb330f4ff2e3803d7d8ba2f141ecbccf96f743f Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 13 Jan 2021 11:04:53 +0100 Subject: [PATCH 004/780] Adding missing constant LED_BUILTIN to satisfy CI build. --- examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino index e5a8e4c86..51d2d97be 100644 --- a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino +++ b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino @@ -22,6 +22,10 @@ #include "arduino_secrets.h" #include "thingProperties.h" +#if defined(ESP32) +static int const LED_BUILTIN = 2; +#endif + void setup() { /* Initialize serial and wait up to 5 seconds for port to open */ Serial.begin(9600); From 70c0b64f4ea28d72f6e95129ddc3c8061c7ca70f Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 13 Jan 2021 11:15:00 +0100 Subject: [PATCH 005/780] Disabling warning -Wreturn-type to satisfy CI (This ain't correct so the reason for this behaviour shall be investigated in the near future). --- src/cbor/lib/tinycbor/src/open_memstream.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cbor/lib/tinycbor/src/open_memstream.c b/src/cbor/lib/tinycbor/src/open_memstream.c index 830a67973..e535c9c79 100644 --- a/src/cbor/lib/tinycbor/src/open_memstream.c +++ b/src/cbor/lib/tinycbor/src/open_memstream.c @@ -41,6 +41,7 @@ typedef size_t LenType; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" +#pragma GCC diagnostic ignored "-Wreturn-type" struct Buffer { From 1ffe81137251c052d5978c051d9022d4912bb9c3 Mon Sep 17 00:00:00 2001 From: per1234 Date: Wed, 13 Jan 2021 22:14:43 -0800 Subject: [PATCH 006/780] Pin Arduino CLI version used in CI to 0.13.0 (#222) When the version is not pinnec, the latest release is used (currently 0.14.0). This version has an incompatibility with the combination of ArduinoIoTCloud and ESP8266. The easy workaround is to use the previous Arduino CLI version to get the CI system working again. Once the real fix for the issue is found, this commit should be reverted so the CI system can benefit from the ongoing development work on Arduino CLI. --- .github/workflows/compile-examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 594788ae4..0efe2c596 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -179,6 +179,7 @@ jobs: - name: Compile examples uses: arduino/compile-sketches@main with: + cli-version: 0.13.0 platforms: ${{ matrix.platforms }} fqbn: ${{ matrix.board.fqbn }} libraries: | From cc55ce12af84d5f90e1f79ab71b2f5c624e920b6 Mon Sep 17 00:00:00 2001 From: ubi Date: Fri, 15 Jan 2021 07:28:50 +0100 Subject: [PATCH 007/780] Examples: added Nano 33 IoT to list of supported boards --- examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino | 1 + examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino index 181205776..aa19f05ab 100644 --- a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino +++ b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino @@ -7,6 +7,7 @@ - MKR GSM 1400 - MKR NB 1500 - MKR WAN 1300/1310 + - Nano 33 IoT - ESP 8266 */ diff --git a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino index e5a8e4c86..da432cc6f 100644 --- a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino +++ b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino @@ -16,6 +16,7 @@ - MKR GSM 1400 - MKR NB 1500 - MKR WAN 1300/1310 + - Nano 33 IoT - ESP 8266 */ From 0a9b78f9956ef08b007f0764ffdb9de6d35afd3e Mon Sep 17 00:00:00 2001 From: ubi Date: Fri, 15 Jan 2021 08:30:29 +0100 Subject: [PATCH 008/780] added example for Callbacks implementation --- .../ArduinoIoTCloud-Callbacks.ino | 80 +++++++++++++++++++ .../arduino_secrets.h | 34 ++++++++ .../thingProperties.h | 33 ++++++++ 3 files changed, 147 insertions(+) create mode 100644 examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino create mode 100644 examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h create mode 100644 examples/ArduinoIoTCloud-Callbacks/thingProperties.h diff --git a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino new file mode 100644 index 000000000..a226a1926 --- /dev/null +++ b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino @@ -0,0 +1,80 @@ +/* + This sketch demonstrates how to subscribe to IoT Cloud events and perform actions + The available events are + + CONNECT : Board successfully connects to IoT Cloud + SYNC : Data is successfully synced between Board and IoT Cloud + DISCONNECT : Board has lost connection to IoT Cloud + + You don't need any specific Properties to be created in order to demonstrate these functionalities. + Simply create a new Thing and give it 1 arbitrary Property. + Remember that the Thing ID needs to be configured in thingProperties.h + These events can be very useful in particular cases, for instance to disable a peripheral + or a connected sensor/actuator when no data connection is available, as well as to perform + specific operations on connection or right after properties values are synchronised. + + To subscribe to an event you can use the `addCallback` method and specify + which event will trigger which custom function. + One function per event can be assigned. + + IMPORTANT: + This sketch works with WiFi, GSM, NB and Lora enabled boards supported by Arduino IoT Cloud. + On a LoRa board, if it is configuered as a class A device (default and preferred option), values from Cloud dashboard are received + only after a value is sent to Cloud. + + This sketch is compatible with: + - MKR 1000 + - MKR WIFI 1010 + - MKR GSM 1400 + - MKR NB 1500 + - MKR WAN 1300/1310 + - Nano 33 IoT + - ESP 8266 +*/ + +#include "arduino_secrets.h" +#include "thingProperties.h" + +void setup() { + /* Initialize serial and wait up to 5 seconds for port to open */ + Serial.begin(9600); + for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime > 5000); ) { } + + /* This function takes care of connecting your sketch variables to the ArduinoIoTCloud object */ + initProperties(); + + /* Initialize Arduino IoT Cloud library */ + ArduinoCloud.begin(ArduinoIoTPreferredConnection); + + /* + Invoking `addCallback` on the ArduinoCloud object allows you to subscribe + to any of the available events and decide which functions to call when they are fired. + + The functions `doThisOnConnect`, `doThisOnSync`, `doThisOnDisconnect` + are custom functions and can be named to your likings and for this example + they are defined/implemented at the bottom of the Sketch + */ + ArduinoCloud.addCallback(ArduinoIoTCloudEvent::CONNECT, doThisOnConnect); + ArduinoCloud.addCallback(ArduinoIoTCloudEvent::SYNC, doThisOnSync); + ArduinoCloud.addCallback(ArduinoIoTCloudEvent::CONNECT, doThisOnDisconnect); + + setDebugMessageLevel(DBG_INFO); + ArduinoCloud.printDebugInfo(); +} + +void loop() { + ArduinoCloud.update(); +} + +void doThisOnConnect(){ + /* add your custom code here */ + Serial.println("Board successfully connected to Arduino IoT Cloud"); +} +void doThisOnSync(){ + /* add your custom code here */ + Serial.println("Thing Properties synchronised"); +} +void doThisOnDisconnect(){ + /* add your custom code here */ + Serial.println("Board disconnected from Arduino IoT Cloud"); +} \ No newline at end of file diff --git a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h new file mode 100644 index 000000000..fc0b0661e --- /dev/null +++ b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h @@ -0,0 +1,34 @@ +#include + +/* MKR1000, MKR WiFi 1010 */ +#if defined(BOARD_HAS_WIFI) + #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" + #define SECRET_PASS "YOUR_WIFI_PASSWORD" +#endif + +/* ESP8266 */ +#if defined(BOARD_ESP8266) + #define SECRET_DEVICE_KEY "my-device-password" +#endif + +/* MKR GSM 1400 */ +#if defined(BOARD_HAS_GSM) + #define SECRET_PIN "" + #define SECRET_APN "" + #define SECRET_LOGIN "" + #define SECRET_PASS "" +#endif + +/* MKR WAN 1300/1310 */ +#if defined(BOARD_HAS_LORA) + #define SECRET_APP_EUI "" + #define SECRET_APP_KEY "" +#endif + +/* MKR NB 1500 */ +#if defined(BOARD_HAS_NB) + #define SECRET_PIN "" + #define SECRET_APN "" + #define SECRET_LOGIN "" + #define SECRET_PASS "" +#endif diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h new file mode 100644 index 000000000..20ee3c9e6 --- /dev/null +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -0,0 +1,33 @@ +#include +#include + +#if defined(BOARD_HAS_WIFI) +#elif defined(BOARD_HAS_GSM) +#elif defined(BOARD_HAS_LORA) +#elif defined(BOARD_HAS_NB) +#else + #error "Arduino IoT Cloud currently only supports MKR1000, MKR WiFi 1010, MKR WAN 1300/1310, MKR NB 1500 and MKR GSM 1400" +#endif + +#define THING_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + +/* BOARD_ID is only required if you are using an ESP8266 */ +#define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + +void initProperties() { +#if defined(BOARD_ESP8266) + ArduinoCloud.setBoardId(BOARD_ID); + ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); +#endif + ArduinoCloud.setThingId(THING_ID); +} + +#if defined(BOARD_HAS_WIFI) + WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_PASS); +#elif defined(BOARD_HAS_GSM) + GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_LORA) + LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, _lora_class::CLASS_A); +#elif defined(BOARD_HAS_NB) + NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#endif From a02123e1565138bc2eb6a5b97eacb9e2be7d9cb5 Mon Sep 17 00:00:00 2001 From: per1234 Date: Sun, 17 Jan 2021 21:41:01 -0800 Subject: [PATCH 009/780] Pin esp8266:esp8266 platform version to 2.5.0 in CI builds (#223) Previously, the most recent release of the ESP8266 boards platform (currently 2.7.4) was used in the "Compile Examples" CI workflow. Arduino Create uses 2.5.0, so it's best to use that version for testing as well. --- .github/workflows/compile-examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 0efe2c596..c4d902eb9 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -131,6 +131,7 @@ jobs: # Install ESP8266 platform via Boards Manager - name: esp8266:esp8266 source-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json + version: 2.5.0 libraries: sketch-paths: # ESP32 boards From 3a665aece16a96ae594f515622b20c56393eb1f5 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 20 Oct 2020 16:41:41 +0200 Subject: [PATCH 010/780] Offload SSL Client w/ crypto on Nina modules Temporarily remove OTA support since it depends on bearssl's SHA256 APIs --- src/AIoTC_Config.h | 10 ++++++++-- src/ArduinoIoTCloudTCP.cpp | 13 ++++++++++++- src/ArduinoIoTCloudTCP.h | 12 ++++++++++-- src/tls/utility/CryptoUtil.cpp | 2 +- src/tls/utility/CryptoUtil.h | 2 +- src/tls/utility/ECCX08Cert.cpp | 2 +- src/tls/utility/ECCX08Cert.h | 2 +- 7 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 2515575c9..40d1f3114 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -72,14 +72,20 @@ #define OTA_ENABLED (0) #endif -#if defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRWIFI1010) || \ - defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ +#if defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKR1000) || \ defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_PORTENTA_H7_M7) || \ defined(ARDUINO_PORTENTA_H7_M4) #define BOARD_HAS_ECCX08 #define HAS_TCP #endif +#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) + #define BOARD_HAS_OFFLOADED_ECCX08 + #define HAS_TCP + #undef OTA_ENABLED + #define OTA_ENABLED (0) +#endif + #if defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) #define HAS_LORA #endif diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 29d2b042a..607af597a 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -28,6 +28,11 @@ #include "tls/utility/CryptoUtil.h" #endif +#ifdef BOARD_HAS_OFFLOADED_ECCX08 +#include +#include "tls/utility/CryptoUtil.h" +#endif + #include "utility/ota/OTA.h" #include "utility/ota/FlashSHA256.h" @@ -112,6 +117,12 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) _ota_img_sha256 = FlashSHA256::calc(0x2000, 0x40000 - 0x2000); #endif /* OTA_ENABLED */ + #ifdef BOARD_HAS_OFFLOADED_ECCX08 + if (!ECCX08.begin()) { DBG_ERROR(F("Cryptography processor failure. Make sure you have a compatible board.")); return 0; } + if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) { DBG_ERROR(F("Cryptography processor read failure.")); return 0; } + ECCX08.end(); + #endif + #ifdef BOARD_HAS_ECCX08 if (!ECCX08.begin()) { DBG_ERROR(F("Cryptography processor failure. Make sure you have a compatible board.")); return 0; } if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) { DBG_ERROR(F("Cryptography processor read failure.")); return 0; } @@ -146,7 +157,7 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) addPropertyReal(_ota_req, "OTA_REQ", Permission::ReadWrite).onSync(DEVICE_WINS); #endif /* OTA_ENABLED */ -#if OTA_STORAGE_SNU +#if OTA_STORAGE_SNU && OTA_ENABLED String const nina_fw_version = WiFi.firmwareVersion(); if (nina_fw_version < "1.4.1") { _ota_cap = false; diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 78eab72b1..c26e08ec3 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -33,6 +33,11 @@ #include #endif +#ifdef BOARD_HAS_OFFLOADED_ECCX08 +#include "tls/utility/ECCX08Cert.h" +#include +#endif + #include /****************************************************************************** @@ -60,7 +65,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass virtual int connected () override; virtual void printDebugInfo() override; - #ifdef BOARD_HAS_ECCX08 + #if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) int begin(ConnectionHandler & connection, String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH); #else int begin(ConnectionHandler & connection, String brokerAddress = DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_USER_PASS_AUTH); @@ -98,9 +103,12 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass int _mqtt_data_len; bool _mqtt_data_request_retransmit; - #ifdef BOARD_HAS_ECCX08 + #if defined(BOARD_HAS_ECCX08) ECCX08CertClass _eccx08_cert; BearSSLClient _sslClient; + #elif defined(BOARD_HAS_OFFLOADED_ECCX08) + ECCX08CertClass _eccx08_cert; + WiFiBearSSLClient _sslClient; #elif defined(BOARD_ESP) WiFiClientSecure _sslClient; String _password; diff --git a/src/tls/utility/CryptoUtil.cpp b/src/tls/utility/CryptoUtil.cpp index 248cc2d79..4348bc38d 100644 --- a/src/tls/utility/CryptoUtil.cpp +++ b/src/tls/utility/CryptoUtil.cpp @@ -21,7 +21,7 @@ #include "CryptoUtil.h" -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined (BOARD_HAS_OFFLOADED_ECCX08) /****************************************************************************** * PUBLIC MEMBER FUNCTIONS diff --git a/src/tls/utility/CryptoUtil.h b/src/tls/utility/CryptoUtil.h index 68e4ee5b3..32239a486 100644 --- a/src/tls/utility/CryptoUtil.h +++ b/src/tls/utility/CryptoUtil.h @@ -24,7 +24,7 @@ #include -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined (BOARD_HAS_OFFLOADED_ECCX08) #include #include diff --git a/src/tls/utility/ECCX08Cert.cpp b/src/tls/utility/ECCX08Cert.cpp index 0a232be00..164309e9a 100644 --- a/src/tls/utility/ECCX08Cert.cpp +++ b/src/tls/utility/ECCX08Cert.cpp @@ -21,7 +21,7 @@ #include -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) #include "../../tls/bearssl/bearssl_hash.h" #include diff --git a/src/tls/utility/ECCX08Cert.h b/src/tls/utility/ECCX08Cert.h index 95437b352..4e1ef6209 100644 --- a/src/tls/utility/ECCX08Cert.h +++ b/src/tls/utility/ECCX08Cert.h @@ -24,7 +24,7 @@ #include -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) #include From 8482a1a47f3323ee0154952d4b5efbee4aed7f65 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 20 Oct 2020 18:56:41 +0200 Subject: [PATCH 011/780] Initial support for Uno WiFi rev2 Need to add a patch to Arduino_ConnectionHandler: diff --git a/src/Arduino_ConnectionHandler.h b/src/Arduino_ConnectionHandler.h index 195ab13..8d80f2e 100644 --- a/src/Arduino_ConnectionHandler.h +++ b/src/Arduino_ConnectionHandler.h @@ -29,7 +29,8 @@ #define WIFI_FIRMWARE_VERSION_REQUIRED WIFI_FIRMWARE_REQUIRED #endif -#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) +#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ + defined(ARDUINO_AVR_UNO_WIFI_REV2) #include #include --- src/AIoTC_Config.h | 3 +- src/cbor/CBORDecoder.h | 4 + src/cbor/CBOREncoder.h | 5 + src/cbor/lib/tinycbor/src/cbor.h | 5 + src/cbor/lib/tinycbor/src/cborpretty.c | 4 + src/cbor/lib/tinycbor/src/cbortojson.c | 4 + src/cbor/lib/tinycbor/src/open_memstream.c | 4 + src/nonstd/nonstd.h | 235 +++++++++++++++++++++ src/property/Property.cpp | 11 +- src/property/Property.h | 11 +- 10 files changed, 283 insertions(+), 3 deletions(-) create mode 100644 src/nonstd/nonstd.h diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 40d1f3114..aa3b43f56 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -79,7 +79,8 @@ #define HAS_TCP #endif -#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) +#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ + defined(ARDUINO_AVR_UNO_WIFI_REV2) #define BOARD_HAS_OFFLOADED_ECCX08 #define HAS_TCP #undef OTA_ENABLED diff --git a/src/cbor/CBORDecoder.h b/src/cbor/CBORDecoder.h index a0f9d7360..f14d51314 100644 --- a/src/cbor/CBORDecoder.h +++ b/src/cbor/CBORDecoder.h @@ -21,6 +21,10 @@ /****************************************************************************** INCLUDE ******************************************************************************/ +#ifdef __AVR__ +#include +#include +#endif #undef max #undef min diff --git a/src/cbor/CBOREncoder.h b/src/cbor/CBOREncoder.h index abaa9d4b7..0d614c770 100644 --- a/src/cbor/CBOREncoder.h +++ b/src/cbor/CBOREncoder.h @@ -22,6 +22,11 @@ * INCLUDE ******************************************************************************/ +#ifdef __AVR__ +#include +#include +#endif + #include "../property/PropertyContainer.h" /****************************************************************************** diff --git a/src/cbor/lib/tinycbor/src/cbor.h b/src/cbor/lib/tinycbor/src/cbor.h index e81df0ec3..cb759fd5b 100644 --- a/src/cbor/lib/tinycbor/src/cbor.h +++ b/src/cbor/lib/tinycbor/src/cbor.h @@ -25,6 +25,11 @@ #ifndef CBOR_H #define CBOR_H +#ifdef __AVR__ +#define FP_NAN NAN +#define FP_INFINITE INFINITY +#endif + #ifndef assert #include #endif diff --git a/src/cbor/lib/tinycbor/src/cborpretty.c b/src/cbor/lib/tinycbor/src/cborpretty.c index 2db4b253a..b82b985ac 100644 --- a/src/cbor/lib/tinycbor/src/cborpretty.c +++ b/src/cbor/lib/tinycbor/src/cborpretty.c @@ -28,6 +28,8 @@ # define __STDC_LIMIT_MACROS 1 #endif +#ifndef __AVR__ + #include "cbor.h" #include "cborinternal_p.h" #include "compilersupport_p.h" @@ -580,4 +582,6 @@ CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *t #pragma GCC diagnostic pop +#endif // __AVR__ + /** @} */ diff --git a/src/cbor/lib/tinycbor/src/cbortojson.c b/src/cbor/lib/tinycbor/src/cbortojson.c index ed6a16666..0e669f27e 100644 --- a/src/cbor/lib/tinycbor/src/cbortojson.c +++ b/src/cbor/lib/tinycbor/src/cbortojson.c @@ -30,6 +30,8 @@ # define __STDC_LIMIT_MACROS 1 #endif +#ifndef __AVR__ + #include "cbor.h" #include "cborjson.h" #include "cborinternal_p.h" @@ -701,4 +703,6 @@ CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags) #pragma GCC diagnostic pop +#endif // __AVR__ + /** @} */ diff --git a/src/cbor/lib/tinycbor/src/open_memstream.c b/src/cbor/lib/tinycbor/src/open_memstream.c index e535c9c79..707dbb1c4 100644 --- a/src/cbor/lib/tinycbor/src/open_memstream.c +++ b/src/cbor/lib/tinycbor/src/open_memstream.c @@ -34,6 +34,10 @@ #include +#ifdef __AVR__ +typedef size_t ssize_t; +#endif + typedef ssize_t RetType; typedef size_t LenType; diff --git a/src/nonstd/nonstd.h b/src/nonstd/nonstd.h new file mode 100644 index 000000000..b591919c6 --- /dev/null +++ b/src/nonstd/nonstd.h @@ -0,0 +1,235 @@ +#pragma once +#ifdef __AVR__ +#include +extern void * operator new(size_t size, void * ptr); +namespace nonstd{ + + templatestruct tag{using type=T;}; + templateusing type_t=typename Tag::type; + + using size_t=decltype(sizeof(int)); + + //move + + template + T&& move(T&t){return static_cast(t);} + + //forward + + template + struct remove_reference:tag{}; + template + struct remove_reference:tag{}; + templateusing remove_reference_t=type_t>; + + template + T&& forward( remove_reference_t& t ) { + return static_cast(t); + } + template + T&& forward( remove_reference_t&& t ) { + return static_cast(t); + } + + //decay + + template + struct remove_const:tag{}; + template + struct remove_const:tag{}; + + template + struct remove_volatile:tag{}; + template + struct remove_volatile:tag{}; + + template + struct remove_cv:remove_const>>{}; + + + template + struct decay3:remove_cv{}; + template + struct decay3:tag{}; + template + struct decay2:decay3{}; + template + struct decay2:tag{}; + + template + struct decay:decay2>{}; + + template + using decay_t=type_t>; + + //is_convertible + + template + T declval(); // no implementation + + template + struct integral_constant{ + static constexpr T value=t; + constexpr integral_constant() {}; + constexpr operator T()const{ return value; } + constexpr T operator()()const{ return value; } + }; + template + using bool_t=integral_constant; + using true_type=bool_t; + using false_type=bool_t; + + templatestruct voider:tag{}; + templateusing void_t=type_t>; + + namespace details { + templateclass Z, class, class...Ts> + struct can_apply:false_type{}; + templateclass Z, class...Ts> + struct can_apply>, Ts...>:true_type{}; + } + templateclass Z, class...Ts> + using can_apply = details::can_apply; + + namespace details { + template + using try_convert = decltype( To{declval()} ); + } + template + struct is_convertible : can_apply< details::try_convert, From, To > {}; + template<> + struct is_convertible:true_type{}; + + //enable_if + + template + struct enable_if {}; + template + struct enable_if:tag{}; + template + using enable_if_t=type_t>; + + //res_of + + namespace details { + template + using invoke_t = decltype( declval()(declval()...) ); + + template + struct res_of {}; + template + struct res_of>>: + tag> + {}; + } + template + using res_of = details::res_of; + template + using res_of_t=type_t>; + + //aligned_storage + + template + struct alignas(align) aligned_storage_t { + char buff[size]; + }; + + //is_same + + template + struct is_same:false_type{}; + template + struct is_same:true_type{}; + + template + struct small_task; + + template + struct small_task{ + struct vtable_t { + void(*mover)(void* src, void* dest); + void(*destroyer)(void*); + R(*invoke)(void const* t, Args&&...args); + template + static vtable_t const* get() { + static const vtable_t table = { + [](void* src, void*dest) { + new(dest) T(move(*static_cast(src))); + }, + [](void* t){ static_cast(t)->~T(); }, + [](void const* t, Args&&...args)->R { + return (*static_cast(t))(forward(args)...); + } + }; + return &table; + } + }; + vtable_t const* table = nullptr; + aligned_storage_t data; + template, + enable_if_t{}>* = nullptr, + enable_if_t, R >{}>* = nullptr + > + small_task( F&& f ): + table( vtable_t::template get() ) + { + static_assert( sizeof(dF) <= sz, "object too large" ); + static_assert( alignof(dF) <= algn, "object too aligned" ); + new(&data) dF(forward(f)); + } + ~small_task() { + if (table) + table->destroyer(&data); + } + small_task(const small_task& o): + table(o.table) + { + data = o.data; + } + small_task(small_task&& o): + table(o.table) + { + if (table) + table->mover(&o.data, &data); + } + small_task(){} + small_task& operator=(const small_task& o){ + this->~small_task(); + new(this) small_task( move(o) ); + return *this; + } + small_task& operator=(small_task&& o){ + this->~small_task(); + new(this) small_task( move(o) ); + return *this; + } + explicit operator bool()const{return table;} + R operator()(Args...args)const{ + return table->invoke(&data, forward(args)...); + } + }; + + template + inline bool operator==(const small_task& __f, nullptr_t) + { return !static_cast(__f); } + + /// @overload + template + inline bool operator==(nullptr_t, const small_task& __f) + { return !static_cast(__f); } + + template + inline bool operator!=(const small_task& __f, nullptr_t) + { return static_cast(__f); } + + /// @overload + template + inline bool operator!=(nullptr_t, const small_task& __f) + { return static_cast(__f); } + + template + using function = small_task; +} + +#endif \ No newline at end of file diff --git a/src/property/Property.cpp b/src/property/Property.cpp index bccbae1b8..20be6e35b 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -189,7 +189,12 @@ CborError Property::appendAttributeReal(String value, String attributeName, Cbor }, encoder); } -CborError Property::appendAttributeName(String attributeName, std::functionappendValue, CborEncoder *encoder) { +#ifdef __AVR__ +CborError Property::appendAttributeName(String attributeName, nonstd::functionappendValue, CborEncoder *encoder) +#else +CborError Property::appendAttributeName(String attributeName, std::functionappendValue, CborEncoder *encoder) +#endif +{ if (attributeName != "") { // when the attribute name string is not empty, the attribute identifier is incremented in order to be encoded in the message if the _lightPayload flag is set _attributeIdentifier++; @@ -271,7 +276,11 @@ void Property::setAttributeReal(String& value, String attributeName) { }); } +#ifdef __AVR__ +void Property::setAttributeReal(String attributeName, nonstd::functionsetValue) +#else void Property::setAttributeReal(String attributeName, std::functionsetValue) +#endif { if (attributeName != "") { _attributeIdentifier++; diff --git a/src/property/Property.h b/src/property/Property.h index 4b5900782..f8db8a948 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -133,6 +133,10 @@ typedef void(*OnSyncCallbackFunc)(Property &); CLASS DECLARATION ******************************************************************************/ +#ifdef __AVR__ +#include "nonstd/nonstd.h" +#endif + class Property { public: @@ -177,13 +181,18 @@ class Property CborError appendAttributeReal(int value, String attributeName = "", CborEncoder *encoder = nullptr); CborError appendAttributeReal(float value, String attributeName = "", CborEncoder *encoder = nullptr); CborError appendAttributeReal(String value, String attributeName = "", CborEncoder *encoder = nullptr); +#ifndef __AVR__ CborError appendAttributeName(String attributeName, std::functionf, CborEncoder *encoder); + void setAttributeReal(String attributeName, std::functionsetValue); +#else + CborError appendAttributeName(String attributeName, nonstd::functionf, CborEncoder *encoder); + void setAttributeReal(String attributeName, nonstd::functionsetValue); +#endif void setAttributesFromCloud(std::list * map_data_list); void setAttributeReal(bool& value, String attributeName = ""); void setAttributeReal(int& value, String attributeName = ""); void setAttributeReal(float& value, String attributeName = ""); void setAttributeReal(String& value, String attributeName = ""); - void setAttributeReal(String attributeName, std::functionsetValue); String getAttributeName(String propertyName, char separator); virtual bool isDifferentFromCloud() = 0; From 6bf3889d3a8beee26aa8dcbbe935924873840aa3 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 16 Nov 2020 19:52:45 +0100 Subject: [PATCH 012/780] RFC: calculate SHA256 using ECCx08 --- src/tls/utility/SHA256.cpp | 12 +++++++++--- src/tls/utility/SHA256.h | 7 +++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/tls/utility/SHA256.cpp b/src/tls/utility/SHA256.cpp index ffed6e587..37d5dbafd 100644 --- a/src/tls/utility/SHA256.cpp +++ b/src/tls/utility/SHA256.cpp @@ -33,15 +33,21 @@ constexpr size_t SHA256::HASH_SIZE; void SHA256::begin() { - br_sha256_init(&_ctx); + spare_len = 0; + ECCX08.beginSHA256(); } void SHA256::update(uint8_t const * data, size_t const len) { - br_sha256_update(&_ctx, data, len); + if (len == 64) { + ECCX08.updateSHA256(data); + } else { + memcpy(spare_buf, data, len); + spare_len = len; + } } void SHA256::finalize(uint8_t * hash) { - br_sha256_out(&_ctx, hash); + ECCX08.endSHA256(spare_buf, spare_len, hash); } diff --git a/src/tls/utility/SHA256.h b/src/tls/utility/SHA256.h index ed0ce1d5a..4091c3eeb 100644 --- a/src/tls/utility/SHA256.h +++ b/src/tls/utility/SHA256.h @@ -22,7 +22,7 @@ * INCLUDE ******************************************************************************/ -#include "../bearssl/bearssl_hash.h" +#include "ArduinoECCX08.h" /****************************************************************************** * CLASS DECLARATION @@ -40,9 +40,8 @@ class SHA256 void finalize(uint8_t * hash); private: - - br_sha256_context _ctx; - + uint8_t spare_buf[64]; + size_t spare_len = 0; }; #endif /* ARDUINO_TLS_UTILITY_SHA256_H_ */ From 3a143a78b61ef2c1bd867ca09f8cd938822c46d3 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 16 Nov 2020 19:53:28 +0100 Subject: [PATCH 013/780] Reenable OTA for SAMD Nina targets --- src/AIoTC_Config.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index aa3b43f56..ec2aebbf5 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -83,8 +83,6 @@ defined(ARDUINO_AVR_UNO_WIFI_REV2) #define BOARD_HAS_OFFLOADED_ECCX08 #define HAS_TCP - #undef OTA_ENABLED - #define OTA_ENABLED (0) #endif #if defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) From f087d046f4c48337261d3436fd2dd3ae85b1232c Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 16 Nov 2020 19:53:55 +0100 Subject: [PATCH 014/780] OTA: prepare for UNO WiFi rev2 --- src/AIoTC_Config.h | 15 +++++++++++++-- src/ArduinoIoTCloud.cpp | 4 ++++ src/ArduinoIoTCloud.h | 3 +++ src/ArduinoIoTCloudTCP.cpp | 4 +++- src/utility/ota/FlashSHA256.cpp | 2 +- src/utility/ota/OTA.h | 2 +- 6 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index ec2aebbf5..e79145d2b 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -30,6 +30,16 @@ #define NTP_USE_RANDOM_PORT (1) #endif +#if defined(ARDUINO_AVR_UNO_WIFI_REV2) +#define DBG_ERROR +#define DBG_WARNING +#define DBG_INFO +#define DBG_DEBUG +#define DBG_VERBOSE +// avoid including debugutils +#define ARDUINO_DEBUG_UTILS_H_ +#endif + #ifndef DBG_ERROR #define DBG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) #endif @@ -54,7 +64,8 @@ * AUTOMATICALLY CONFIGURED DEFINES ******************************************************************************/ -#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) +#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ + defined(ARDUINO_AVR_UNO_WIFI_REV2) #define OTA_STORAGE_SNU (1) #else #define OTA_STORAGE_SNU (0) @@ -66,7 +77,7 @@ #define OTA_STORAGE_SSU (0) #endif -#if OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU +#if OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU && !defined(ARDUINO_AVR_UNO_WIFI_REV2) #define OTA_ENABLED (1) #else #define OTA_ENABLED (0) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index cf7557e5a..4dfe9c326 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -179,3 +179,7 @@ void ArduinoIoTCloudClass::execCloudEventCallback(ArduinoIoTCloudEvent const eve (*callback)(); } } + +__attribute__((weak)) void setDebugMessageLevel(int const level) { + //do nothing +} \ No newline at end of file diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 1be41e9e8..4c5948b76 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -154,4 +154,7 @@ class ArduinoIoTCloudClass #include "ArduinoIoTCloudLPWAN.h" #endif +// declaration for boards without debug library +void setDebugMessageLevel(int const level); + #endif diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 607af597a..064ad74d0 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -103,7 +103,7 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) _brokerAddress = brokerAddress; _brokerPort = brokerPort; -#if OTA_ENABLED +#if OTA_ENABLED && !defined(__AVR__) /* Calculate the SHA256 checksum over the firmware stored in the flash of the * MCU. Note: As we don't know the length per-se we read chunks of the flash * until we detect one containing only 0xFF (= flash erased). This only works @@ -433,9 +433,11 @@ void ArduinoIoTCloudTCP::onOTARequest() ota_download_success = true; #endif /* OTA_STORAGE_SNU */ +#ifndef __AVR__ /* Perform the reset to reboot to SxU. */ if (ota_download_success) NVIC_SystemReset(); +#endif } #endif diff --git a/src/utility/ota/FlashSHA256.cpp b/src/utility/ota/FlashSHA256.cpp index 9f908a8c8..2be6a6066 100644 --- a/src/utility/ota/FlashSHA256.cpp +++ b/src/utility/ota/FlashSHA256.cpp @@ -20,7 +20,7 @@ ******************************************************************************/ #include -#if OTA_ENABLED +#if OTA_ENABLED && !defined(__AVR__) #include "FlashSHA256.h" diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 208d5e616..bd1476fba 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -25,7 +25,7 @@ #include #if OTA_ENABLED -#if OTA_STORAGE_SNU +#if OTA_STORAGE_SNU && !defined(ARDUINO_AVR_UNO_WIFI_REV2) #include #endif /* OTA_STORAGE_SNU */ From cbb745ba3ffff30a4af31260f95e20484d826c91 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 17 Nov 2020 10:11:21 +0100 Subject: [PATCH 015/780] Restore SHA256 via bearSSL Loses 2KB of flash compared with https://github.com/arduino-libraries/ArduinoIoTCloud/commit/46aa5f6b9566f472065245e8f346d3f4d037848f but it's surely faster --- src/tls/bearssl/dec32be.c | 2 +- src/tls/bearssl/enc32be.c | 2 +- src/tls/bearssl/sha2small.c | 2 +- src/tls/utility/SHA256.cpp | 12 +++--------- src/tls/utility/SHA256.h | 7 ++++--- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/tls/bearssl/dec32be.c b/src/tls/bearssl/dec32be.c index fb1924fe6..1ba0968e4 100644 --- a/src/tls/bearssl/dec32be.c +++ b/src/tls/bearssl/dec32be.c @@ -23,7 +23,7 @@ */ #include -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) #include "inner.h" diff --git a/src/tls/bearssl/enc32be.c b/src/tls/bearssl/enc32be.c index 471cddcac..dde2295d1 100644 --- a/src/tls/bearssl/enc32be.c +++ b/src/tls/bearssl/enc32be.c @@ -23,7 +23,7 @@ */ #include -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) #include "inner.h" diff --git a/src/tls/bearssl/sha2small.c b/src/tls/bearssl/sha2small.c index fb33c9b16..c17638706 100644 --- a/src/tls/bearssl/sha2small.c +++ b/src/tls/bearssl/sha2small.c @@ -23,7 +23,7 @@ */ #include -#ifdef BOARD_HAS_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) #include "inner.h" diff --git a/src/tls/utility/SHA256.cpp b/src/tls/utility/SHA256.cpp index 37d5dbafd..ffed6e587 100644 --- a/src/tls/utility/SHA256.cpp +++ b/src/tls/utility/SHA256.cpp @@ -33,21 +33,15 @@ constexpr size_t SHA256::HASH_SIZE; void SHA256::begin() { - spare_len = 0; - ECCX08.beginSHA256(); + br_sha256_init(&_ctx); } void SHA256::update(uint8_t const * data, size_t const len) { - if (len == 64) { - ECCX08.updateSHA256(data); - } else { - memcpy(spare_buf, data, len); - spare_len = len; - } + br_sha256_update(&_ctx, data, len); } void SHA256::finalize(uint8_t * hash) { - ECCX08.endSHA256(spare_buf, spare_len, hash); + br_sha256_out(&_ctx, hash); } diff --git a/src/tls/utility/SHA256.h b/src/tls/utility/SHA256.h index 4091c3eeb..ed0ce1d5a 100644 --- a/src/tls/utility/SHA256.h +++ b/src/tls/utility/SHA256.h @@ -22,7 +22,7 @@ * INCLUDE ******************************************************************************/ -#include "ArduinoECCX08.h" +#include "../bearssl/bearssl_hash.h" /****************************************************************************** * CLASS DECLARATION @@ -40,8 +40,9 @@ class SHA256 void finalize(uint8_t * hash); private: - uint8_t spare_buf[64]; - size_t spare_len = 0; + + br_sha256_context _ctx; + }; #endif /* ARDUINO_TLS_UTILITY_SHA256_H_ */ From 2b14646254f46800ac009a73a43ae10eac76e8dd Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 18 Nov 2020 10:38:46 +0100 Subject: [PATCH 016/780] Prevent inclusion of 'Arduino_DebugUtils' on AVR in a more future-proof and maintainable way. --- src/AIoTC_Config.h | 2 -- src/ArduinoIoTCloud.h | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index e79145d2b..e9373eb20 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -36,8 +36,6 @@ #define DBG_INFO #define DBG_DEBUG #define DBG_VERBOSE -// avoid including debugutils -#define ARDUINO_DEBUG_UTILS_H_ #endif #ifndef DBG_ERROR diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 4c5948b76..bf70679e4 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -25,7 +25,10 @@ #include #include -#include + +#if !defined(__AVR__) +# include +#endif #include "AIoTC_Const.h" From 41e2392e86560d3e77302d0dcb53008329a3f027 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 18 Nov 2020 10:44:59 +0100 Subject: [PATCH 017/780] =?UTF-8?q?Renaming=20all=20'DBG=5FERROR/WARNING/I?= =?UTF-8?q?NFO/DEBUG/VERBOSE=20macros=20to=20DEBUG=5FERROR/WARNING/...=20t?= =?UTF-8?q?o=20avoid=20name=20clashes=20with=20=C3=ADdentically=20named=20?= =?UTF-8?q?constants=20within=20Arduino=5FDebugUtils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AIoTC_Config.h | 30 +++++++++++++++--------------- src/ArduinoIoTCloudLPWAN.cpp | 10 +++++----- src/utility/ota/FlashSHA256.cpp | 4 ++-- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index e9373eb20..89ef47d31 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -31,31 +31,31 @@ #endif #if defined(ARDUINO_AVR_UNO_WIFI_REV2) -#define DBG_ERROR -#define DBG_WARNING -#define DBG_INFO -#define DBG_DEBUG -#define DBG_VERBOSE +#define DEBUG_ERROR +#define DEBUG_WARNING +#define DEBUG_INFO +#define DEBUG_DEBUG +#define DEBUG_VERBOSE #endif -#ifndef DBG_ERROR - #define DBG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) +#ifndef DEBUG_ERROR + #define DEBUG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) #endif -#ifndef DBG_WARNING - #define DBG_WARNING(fmt, ...) Debug.print(DBG_WARNING, fmt, ## __VA_ARGS__) +#ifndef DEBUG_WARNING + #define DEBUG_WARNING(fmt, ...) Debug.print(DBG_WARNING, fmt, ## __VA_ARGS__) #endif -#ifndef DBG_INFO - #define DBG_INFO(fmt, ...) Debug.print(DBG_INFO, fmt, ## __VA_ARGS__) +#ifndef DEBUG_INFO + #define DEBUG_INFO(fmt, ...) Debug.print(DBG_INFO, fmt, ## __VA_ARGS__) #endif -#ifndef DBG_DEBUG - #define DBG_DEBUG(fmt, ...) Debug.print(DBG_DEBUG, fmt, ## __VA_ARGS__) +#ifndef DEBUG_DEBUG + #define DEBUG_DEBUG(fmt, ...) Debug.print(DBG_DEBUG, fmt, ## __VA_ARGS__) #endif -#ifndef DBG_VERBOSE - #define DBG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) +#ifndef DEBUG_VERBOSE + #define DEBUG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) #endif /****************************************************************************** diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 9f8bfd9b2..73ae68c61 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -87,8 +87,8 @@ void ArduinoIoTCloudLPWAN::update() void ArduinoIoTCloudLPWAN::printDebugInfo() { - DBG_INFO(F("***** Arduino IoT Cloud LPWAN - configuration info *****")); - DBG_INFO(F("Thing ID: %s"), getThingId().c_str()); + DEBUG_INFO(F("***** Arduino IoT Cloud LPWAN - configuration info *****")); + DEBUG_INFO(F("Thing ID: %s"), getThingId().c_str()); } /****************************************************************************** @@ -106,8 +106,8 @@ ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_ConnectPhy() ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_SyncTime() { unsigned long const internal_posix_time = _time_service.getTime(); - DBG_VERBOSE(F("ArduinoIoTCloudLPWAN::%s internal clock configured to posix timestamp %d"), __FUNCTION__, internal_posix_time); - DBG_INFO(F("Connected to Arduino IoT Cloud")); + DEBUG_VERBOSE(F("ArduinoIoTCloudLPWAN::%s internal clock configured to posix timestamp %d"), __FUNCTION__, internal_posix_time); + DEBUG_INFO(F("Connected to Arduino IoT Cloud")); return State::Connected; } @@ -115,7 +115,7 @@ ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_Connected() { if (!connected()) { - DBG_ERROR(F("ArduinoIoTCloudLPWAN::%s connection to gateway lost"), __FUNCTION__); + DEBUG_ERROR(F("ArduinoIoTCloudLPWAN::%s connection to gateway lost"), __FUNCTION__); return State::ConnectPhy; } diff --git a/src/utility/ota/FlashSHA256.cpp b/src/utility/ota/FlashSHA256.cpp index 2be6a6066..12290a612 100644 --- a/src/utility/ota/FlashSHA256.cpp +++ b/src/utility/ota/FlashSHA256.cpp @@ -100,8 +100,8 @@ String FlashSHA256::calc(uint32_t const start_addr, uint32_t const max_flash_siz sha256_str += buf; }); /* Do some debug printout. */ - DBG_VERBOSE("SHA256: %d bytes read", flash_addr); - DBG_VERBOSE("SHA256: HASH(%d) = %s", strlen(sha256_str.c_str()), sha256_str.c_str()); + DEBUG_VERBOSE("SHA256: %d bytes read", flash_addr); + DEBUG_VERBOSE("SHA256: HASH(%d) = %s", strlen(sha256_str.c_str()), sha256_str.c_str()); return sha256_str; } From 3640d4dd931fc357fe93fdbb7472cce4034f87ad Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 18 Nov 2020 10:58:22 +0100 Subject: [PATCH 018/780] Provide DBG_NONE/ERROR/ etc. values in case ArduinoDebugUtils is not compiled in (which is the case when working with Uno WiFi Rev. 2 --- src/AIoTC_Config.h | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 89ef47d31..d6f60843b 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -31,11 +31,24 @@ #endif #if defined(ARDUINO_AVR_UNO_WIFI_REV2) -#define DEBUG_ERROR -#define DEBUG_WARNING -#define DEBUG_INFO -#define DEBUG_DEBUG -#define DEBUG_VERBOSE +/* Define debug macros which effectively removes them from the + * the codebase for Arduino Uno WiFi. Rev. 2. + */ +# define DEBUG_ERROR +# define DEBUG_WARNING +# define DEBUG_INFO +# define DEBUG_DEBUG +# define DEBUG_VERBOSE +/* Provide defines for constants provided within Arduino_DebugUtils + * in order to allow older sketches using those constants to still + * compile. + */ +# define DBG_NONE -1 +# define DBG_ERROR 0 +# define DBG_WARNING 1 +# define DBG_INFO 2 +# define DBG_DEBUG 3 +# define DBG_VERBOSE 4 #endif #ifndef DEBUG_ERROR From ad7407476bbed5b57c9228f1b8ab82e710f2797e Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 17 Nov 2020 02:25:11 -0800 Subject: [PATCH 019/780] Add Uno WiFi Rev2 to "Compile Examples" CI workflow --- .github/workflows/compile-examples.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index c4d902eb9..6700631bf 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -41,6 +41,7 @@ jobs: {"fqbn": "arduino:samd:mkr1000", "type": "mkr1000"}, {"fqbn": "arduino:samd:mkrwifi1010", "type": "nina"}, {"fqbn": "arduino:samd:nano_33_iot", "type": "nina"}, + {"fqbn": "arduino:megaavr:uno2018", "type": "megaavr"}, {"fqbn": "arduino:samd:mkrwan1300", "type": "wan"}, {"fqbn": "arduino:samd:mkrgsm1400", "type": "gsm"}, {"fqbn": "arduino:samd:mkrnb1500", "type": "nb"}, @@ -79,6 +80,20 @@ jobs: sketch-paths: | - examples/utility/Provisioning - examples/utility/SelfProvisioning + # Uno WiFi Rev2 + - board: + type: "megaavr" + platforms: | + - name: arduino:megaavr + libraries: | + - name: ArduinoECCX08 + - name: Arduino_AVRSTL + - name: WiFiNINA + - name: Arduino_JSON + - name: ArduinoBearSSL + sketch-paths: | + - examples/utility/Provisioning + - examples/utility/SelfProvisioning # LoRaWAN boards - board: type: "wan" From 7ed85b088aa4608eeec873db0b8d289b0e8c7060 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 18 Nov 2020 17:02:14 +0100 Subject: [PATCH 020/780] Force inclusion of Arduino_AVRSTL. --- src/cbor/CBORDecoder.h | 2 +- src/cbor/CBOREncoder.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cbor/CBORDecoder.h b/src/cbor/CBORDecoder.h index f14d51314..c1cdd8330 100644 --- a/src/cbor/CBORDecoder.h +++ b/src/cbor/CBORDecoder.h @@ -23,7 +23,7 @@ ******************************************************************************/ #ifdef __AVR__ #include -#include +#include #endif #undef max diff --git a/src/cbor/CBOREncoder.h b/src/cbor/CBOREncoder.h index 0d614c770..af66bdbfe 100644 --- a/src/cbor/CBOREncoder.h +++ b/src/cbor/CBOREncoder.h @@ -24,7 +24,7 @@ #ifdef __AVR__ #include -#include +#include #endif #include "../property/PropertyContainer.h" From 1656ab0870b04120d11c61bf61f2b742467fb3a1 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 27 Jan 2021 06:23:26 +0100 Subject: [PATCH 021/780] Comment parameter out to prevent unused parameter warning. This function anyway only servers as a stub to allow compilation for megaavr architecture. --- src/ArduinoIoTCloud.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 4dfe9c326..0f117e993 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -180,6 +180,7 @@ void ArduinoIoTCloudClass::execCloudEventCallback(ArduinoIoTCloudEvent const eve } } -__attribute__((weak)) void setDebugMessageLevel(int const level) { - //do nothing -} \ No newline at end of file +__attribute__((weak)) void setDebugMessageLevel(int const /* level */) +{ + /* do nothing */ +} From 573ce66c09289c1726dc15193683b80bbb1cd846 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 27 Jan 2021 06:24:56 +0100 Subject: [PATCH 022/780] Clearly disabling DEBUG macros for megaavr architecture. --- src/AIoTC_Config.h | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index d6f60843b..f41fc5519 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -31,14 +31,6 @@ #endif #if defined(ARDUINO_AVR_UNO_WIFI_REV2) -/* Define debug macros which effectively removes them from the - * the codebase for Arduino Uno WiFi. Rev. 2. - */ -# define DEBUG_ERROR -# define DEBUG_WARNING -# define DEBUG_INFO -# define DEBUG_DEBUG -# define DEBUG_VERBOSE /* Provide defines for constants provided within Arduino_DebugUtils * in order to allow older sketches using those constants to still * compile. @@ -52,23 +44,43 @@ #endif #ifndef DEBUG_ERROR - #define DEBUG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) +# if defined(ARDUINO_AVR_UNO_WIFI_REV2) +# define DEBUG_ERROR(fmt, ...) +# else +# define DEBUG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) +# endif #endif #ifndef DEBUG_WARNING - #define DEBUG_WARNING(fmt, ...) Debug.print(DBG_WARNING, fmt, ## __VA_ARGS__) +# if defined(ARDUINO_AVR_UNO_WIFI_REV2) +# define DEBUG_WARNING(fmt, ...) +# else +# define DEBUG_WARNING(fmt, ...) Debug.print(DBG_WARNING, fmt, ## __VA_ARGS__) +# endif #endif #ifndef DEBUG_INFO - #define DEBUG_INFO(fmt, ...) Debug.print(DBG_INFO, fmt, ## __VA_ARGS__) +# if defined(ARDUINO_AVR_UNO_WIFI_REV2) +# define DEBUG_INFO(fmt, ...) +# else +# define DEBUG_INFO(fmt, ...) Debug.print(DBG_INFO, fmt, ## __VA_ARGS__) +# endif #endif #ifndef DEBUG_DEBUG - #define DEBUG_DEBUG(fmt, ...) Debug.print(DBG_DEBUG, fmt, ## __VA_ARGS__) +# if defined(ARDUINO_AVR_UNO_WIFI_REV2) +# define DEBUG_DEBUG(fmt, ...) +# else +# define DEBUG_DEBUG(fmt, ...) Debug.print(DBG_DEBUG, fmt, ## __VA_ARGS__) +# endif #endif #ifndef DEBUG_VERBOSE - #define DEBUG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) +# if defined(ARDUINO_AVR_UNO_WIFI_REV2) +# define DEBUG_VERBOSE(fmt, ...) +# else +# define DEBUG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) +# endif #endif /****************************************************************************** From 956cd772b154f6616f7d44b70f8a53b0e51e7d1c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 27 Jan 2021 06:28:37 +0100 Subject: [PATCH 023/780] Correcting debug macros to allow code to compile. --- src/ArduinoIoTCloudTCP.cpp | 64 +++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 064ad74d0..f51c96f4a 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -118,15 +118,35 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) #endif /* OTA_ENABLED */ #ifdef BOARD_HAS_OFFLOADED_ECCX08 - if (!ECCX08.begin()) { DBG_ERROR(F("Cryptography processor failure. Make sure you have a compatible board.")); return 0; } - if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) { DBG_ERROR(F("Cryptography processor read failure.")); return 0; } + if (!ECCX08.begin()) + { + DEBUG_ERROR("Cryptography processor failure. Make sure you have a compatible board."); + return 0; + } + if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) + { + DEBUG_ERROR("Cryptography processor read failure."); + return 0; + } ECCX08.end(); #endif #ifdef BOARD_HAS_ECCX08 - if (!ECCX08.begin()) { DBG_ERROR(F("Cryptography processor failure. Make sure you have a compatible board.")); return 0; } - if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) { DBG_ERROR(F("Cryptography processor read failure.")); return 0; } - if (!CryptoUtil::reconstructCertificate(_eccx08_cert, getDeviceId(), ECCX08Slot::Key, ECCX08Slot::CompressedCertificate, ECCX08Slot::SerialNumberAndAuthorityKeyIdentifier)) { DBG_ERROR(F("Cryptography certificate reconstruction failure.")); return 0; } + if (!ECCX08.begin()) + { + DEBUG_ERROR(F("Cryptography processor failure. Make sure you have a compatible board.")); + return 0; + } + if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) + { + DEBUG_ERROR(F("Cryptography processor read failure.")); + return 0; + } + if (!CryptoUtil::reconstructCertificate(_eccx08_cert, getDeviceId(), ECCX08Slot::Key, ECCX08Slot::CompressedCertificate, ECCX08Slot::SerialNumberAndAuthorityKeyIdentifier)) + { + DEBUG_ERROR(F("Cryptography certificate reconstruction failure.")); + return 0; + } _sslClient.setClient(_connection->getClient()); _sslClient.setEccSlot(static_cast(ECCX08Slot::Key), _eccx08_cert.bytes(), _eccx08_cert.length()); #elif defined(BOARD_ESP) @@ -161,7 +181,7 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) String const nina_fw_version = WiFi.firmwareVersion(); if (nina_fw_version < "1.4.1") { _ota_cap = false; - DBG_WARNING(F("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, NINA firmware needs to be >= 1.4.1, current %s"), __FUNCTION__, nina_fw_version.c_str()); + DEBUG_WARNING(F("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, NINA firmware needs to be >= 1.4.1, current %s"), __FUNCTION__, nina_fw_version.c_str()); } else { _ota_cap = true; @@ -198,10 +218,10 @@ int ArduinoIoTCloudTCP::connected() void ArduinoIoTCloudTCP::printDebugInfo() { - DBG_INFO(F("***** Arduino IoT Cloud - configuration info *****")); - DBG_INFO(F("Device ID: %s"), getDeviceId().c_str()); - DBG_INFO(F("Thing ID: %s"), getThingId().c_str()); - DBG_INFO(F("MQTT Broker: %s:%d"), _brokerAddress.c_str(), _brokerPort); + DEBUG_INFO(F("***** Arduino IoT Cloud - configuration info *****")); + DEBUG_INFO(F("Device ID: %s"), getDeviceId().c_str()); + DEBUG_INFO(F("Thing ID: %s"), getThingId().c_str()); + DEBUG_INFO(F("MQTT Broker: %s:%d"), _brokerAddress.c_str(), _brokerPort); } /****************************************************************************** @@ -219,7 +239,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() { unsigned long const internal_posix_time = _time_service.getTime(); - DBG_VERBOSE(F("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d"), __FUNCTION__, internal_posix_time); + DEBUG_VERBOSE(F("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d"), __FUNCTION__, internal_posix_time); return State::ConnectMqttBroker; } @@ -228,7 +248,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() if (_mqttClient.connect(_brokerAddress.c_str(), _brokerPort)) return State::SubscribeMqttTopics; - DBG_ERROR(F("ArduinoIoTCloudTCP::%s could not connect to %s:%d"), __FUNCTION__, _brokerAddress.c_str(), _brokerPort); + DEBUG_ERROR(F("ArduinoIoTCloudTCP::%s could not connect to %s:%d"), __FUNCTION__, _brokerAddress.c_str(), _brokerPort); return State::ConnectPhy; } @@ -236,8 +256,8 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() { if (!_mqttClient.subscribe(_dataTopicIn)) { - DBG_ERROR(F("ArduinoIoTCloudTCP::%s could not subscribe to %s"), __FUNCTION__, _dataTopicIn.c_str()); - DBG_ERROR(F("Check your thing configuration, and press the reset button on your board.")); + DEBUG_ERROR(F("ArduinoIoTCloudTCP::%s could not subscribe to %s"), __FUNCTION__, _dataTopicIn.c_str()); + DEBUG_ERROR(F("Check your thing configuration, and press the reset button on your board.")); return State::SubscribeMqttTopics; } @@ -245,13 +265,13 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() { if (!_mqttClient.subscribe(_shadowTopicIn)) { - DBG_ERROR(F("ArduinoIoTCloudTCP::%s could not subscribe to %s"), __FUNCTION__, _shadowTopicIn.c_str()); - DBG_ERROR(F("Check your thing configuration, and press the reset button on your board.")); + DEBUG_ERROR(F("ArduinoIoTCloudTCP::%s could not subscribe to %s"), __FUNCTION__, _shadowTopicIn.c_str()); + DEBUG_ERROR(F("Check your thing configuration, and press the reset button on your board.")); return State::SubscribeMqttTopics; } } - DBG_INFO(F("Connected to Arduino IoT Cloud")); + DEBUG_INFO(F("Connected to Arduino IoT Cloud")); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); if (_shadowTopicIn != "") @@ -266,7 +286,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() unsigned long const now = millis(); if ((now - _lastSyncRequestTickTime) > TIMEOUT_FOR_LASTVALUES_SYNC) { - DBG_VERBOSE(F("ArduinoIoTCloudTCP::%s [%d] last values requested"), __FUNCTION__, now); + DEBUG_VERBOSE(F("ArduinoIoTCloudTCP::%s [%d] last values requested"), __FUNCTION__, now); requestLastValue(); _lastSyncRequestTickTime = now; } @@ -278,7 +298,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() { if (!_mqttClient.connected()) { - DBG_ERROR(F("ArduinoIoTCloudTCP::%s MQTT client connection lost"), __FUNCTION__); + DEBUG_ERROR(F("ArduinoIoTCloudTCP::%s MQTT client connection lost"), __FUNCTION__); /* Forcefully disconnect MQTT client and trigger a reconnection. */ _mqttClient.stop(); @@ -358,7 +378,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) if ((_shadowTopicIn == topic) && (_state == State::RequestLastValues)) { - DBG_VERBOSE(F("ArduinoIoTCloudTCP::%s [%d] last values received"), __FUNCTION__, millis()); + DEBUG_VERBOSE(F("ArduinoIoTCloudTCP::%s [%d] last values received"), __FUNCTION__, millis()); CBORDecoder::decode(_property_container, (uint8_t*)bytes, length, true); sendPropertiesToCloud(); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); @@ -408,7 +428,7 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l #if OTA_ENABLED void ArduinoIoTCloudTCP::onOTARequest() { - DBG_VERBOSE(F("ArduinoIoTCloudTCP::%s _ota_url = %s"), __FUNCTION__, _ota_url.c_str()); + DEBUG_VERBOSE(F("ArduinoIoTCloudTCP::%s _ota_url = %s"), __FUNCTION__, _ota_url.c_str()); /* Status flag to prevent the reset from being executed * when HTTPS download is not supported. @@ -424,7 +444,7 @@ void ArduinoIoTCloudTCP::onOTARequest() uint8_t nina_ota_err_code = 0; if (!WiFiStorage.downloadOTA(_ota_url.c_str(), &nina_ota_err_code)) { - DBG_ERROR(F("ArduinoIoTCloudTCP::%s error download to nina: %d"), __FUNCTION__, nina_ota_err_code); + DEBUG_ERROR(F("ArduinoIoTCloudTCP::%s error download to nina: %d"), __FUNCTION__, nina_ota_err_code); _ota_error = static_cast(OTAError::DownloadFailed); return; } From 958f73e9bbbbe92276f8ea01ae92045f8edba925 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 27 Jan 2021 06:36:16 +0100 Subject: [PATCH 024/780] Eliminating 'F(expr)' macro since it's of no use due to the Neumann architecture in samd, mbed and megaavr (all currently supported arduino boards. --- src/ArduinoIoTCloudLPWAN.cpp | 12 +++++------ src/ArduinoIoTCloudTCP.cpp | 40 ++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 73ae68c61..29458f21a 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -87,8 +87,8 @@ void ArduinoIoTCloudLPWAN::update() void ArduinoIoTCloudLPWAN::printDebugInfo() { - DEBUG_INFO(F("***** Arduino IoT Cloud LPWAN - configuration info *****")); - DEBUG_INFO(F("Thing ID: %s"), getThingId().c_str()); + DEBUG_INFO("***** Arduino IoT Cloud LPWAN - configuration info *****"); + DEBUG_INFO("Thing ID: %s", getThingId().c_str()); } /****************************************************************************** @@ -106,8 +106,8 @@ ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_ConnectPhy() ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_SyncTime() { unsigned long const internal_posix_time = _time_service.getTime(); - DEBUG_VERBOSE(F("ArduinoIoTCloudLPWAN::%s internal clock configured to posix timestamp %d"), __FUNCTION__, internal_posix_time); - DEBUG_INFO(F("Connected to Arduino IoT Cloud")); + DEBUG_VERBOSE("ArduinoIoTCloudLPWAN::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); + DEBUG_INFO("Connected to Arduino IoT Cloud"); return State::Connected; } @@ -115,7 +115,7 @@ ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_Connected() { if (!connected()) { - DEBUG_ERROR(F("ArduinoIoTCloudLPWAN::%s connection to gateway lost"), __FUNCTION__); + DEBUG_ERROR("ArduinoIoTCloudLPWAN::%s connection to gateway lost", __FUNCTION__); return State::ConnectPhy; } @@ -175,4 +175,4 @@ int ArduinoIoTCloudLPWAN::writeProperties(const byte data[], int length) ArduinoIoTCloudLPWAN ArduinoCloud; -#endif \ No newline at end of file +#endif diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index f51c96f4a..05385ef06 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -134,17 +134,17 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) #ifdef BOARD_HAS_ECCX08 if (!ECCX08.begin()) { - DEBUG_ERROR(F("Cryptography processor failure. Make sure you have a compatible board.")); + DEBUG_ERROR("Cryptography processor failure. Make sure you have a compatible board."); return 0; } if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) { - DEBUG_ERROR(F("Cryptography processor read failure.")); + DEBUG_ERROR("Cryptography processor read failure."); return 0; } if (!CryptoUtil::reconstructCertificate(_eccx08_cert, getDeviceId(), ECCX08Slot::Key, ECCX08Slot::CompressedCertificate, ECCX08Slot::SerialNumberAndAuthorityKeyIdentifier)) { - DEBUG_ERROR(F("Cryptography certificate reconstruction failure.")); + DEBUG_ERROR("Cryptography certificate reconstruction failure."); return 0; } _sslClient.setClient(_connection->getClient()); @@ -181,7 +181,7 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) String const nina_fw_version = WiFi.firmwareVersion(); if (nina_fw_version < "1.4.1") { _ota_cap = false; - DEBUG_WARNING(F("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, NINA firmware needs to be >= 1.4.1, current %s"), __FUNCTION__, nina_fw_version.c_str()); + DEBUG_WARNING("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, NINA firmware needs to be >= 1.4.1, current %s", __FUNCTION__, nina_fw_version.c_str()); } else { _ota_cap = true; @@ -218,10 +218,10 @@ int ArduinoIoTCloudTCP::connected() void ArduinoIoTCloudTCP::printDebugInfo() { - DEBUG_INFO(F("***** Arduino IoT Cloud - configuration info *****")); - DEBUG_INFO(F("Device ID: %s"), getDeviceId().c_str()); - DEBUG_INFO(F("Thing ID: %s"), getThingId().c_str()); - DEBUG_INFO(F("MQTT Broker: %s:%d"), _brokerAddress.c_str(), _brokerPort); + DEBUG_INFO("***** Arduino IoT Cloud - configuration info *****"); + DEBUG_INFO("Device ID: %s", getDeviceId().c_str()); + DEBUG_INFO("Thing ID: %s", getThingId().c_str()); + DEBUG_INFO("MQTT Broker: %s:%d", _brokerAddress.c_str(), _brokerPort); } /****************************************************************************** @@ -239,7 +239,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() { unsigned long const internal_posix_time = _time_service.getTime(); - DEBUG_VERBOSE(F("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d"), __FUNCTION__, internal_posix_time); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); return State::ConnectMqttBroker; } @@ -248,7 +248,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() if (_mqttClient.connect(_brokerAddress.c_str(), _brokerPort)) return State::SubscribeMqttTopics; - DEBUG_ERROR(F("ArduinoIoTCloudTCP::%s could not connect to %s:%d"), __FUNCTION__, _brokerAddress.c_str(), _brokerPort); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); return State::ConnectPhy; } @@ -256,8 +256,8 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() { if (!_mqttClient.subscribe(_dataTopicIn)) { - DEBUG_ERROR(F("ArduinoIoTCloudTCP::%s could not subscribe to %s"), __FUNCTION__, _dataTopicIn.c_str()); - DEBUG_ERROR(F("Check your thing configuration, and press the reset button on your board.")); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); + DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); return State::SubscribeMqttTopics; } @@ -265,13 +265,13 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() { if (!_mqttClient.subscribe(_shadowTopicIn)) { - DEBUG_ERROR(F("ArduinoIoTCloudTCP::%s could not subscribe to %s"), __FUNCTION__, _shadowTopicIn.c_str()); - DEBUG_ERROR(F("Check your thing configuration, and press the reset button on your board.")); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); + DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); return State::SubscribeMqttTopics; } } - DEBUG_INFO(F("Connected to Arduino IoT Cloud")); + DEBUG_INFO("Connected to Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); if (_shadowTopicIn != "") @@ -286,7 +286,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() unsigned long const now = millis(); if ((now - _lastSyncRequestTickTime) > TIMEOUT_FOR_LASTVALUES_SYNC) { - DEBUG_VERBOSE(F("ArduinoIoTCloudTCP::%s [%d] last values requested"), __FUNCTION__, now); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, now); requestLastValue(); _lastSyncRequestTickTime = now; } @@ -298,7 +298,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() { if (!_mqttClient.connected()) { - DEBUG_ERROR(F("ArduinoIoTCloudTCP::%s MQTT client connection lost"), __FUNCTION__); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); /* Forcefully disconnect MQTT client and trigger a reconnection. */ _mqttClient.stop(); @@ -378,7 +378,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) if ((_shadowTopicIn == topic) && (_state == State::RequestLastValues)) { - DEBUG_VERBOSE(F("ArduinoIoTCloudTCP::%s [%d] last values received"), __FUNCTION__, millis()); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); CBORDecoder::decode(_property_container, (uint8_t*)bytes, length, true); sendPropertiesToCloud(); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); @@ -428,7 +428,7 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l #if OTA_ENABLED void ArduinoIoTCloudTCP::onOTARequest() { - DEBUG_VERBOSE(F("ArduinoIoTCloudTCP::%s _ota_url = %s"), __FUNCTION__, _ota_url.c_str()); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s"), __FUNCTION__, _ota_url.c_str()); /* Status flag to prevent the reset from being executed * when HTTPS download is not supported. @@ -444,7 +444,7 @@ void ArduinoIoTCloudTCP::onOTARequest() uint8_t nina_ota_err_code = 0; if (!WiFiStorage.downloadOTA(_ota_url.c_str(), &nina_ota_err_code)) { - DEBUG_ERROR(F("ArduinoIoTCloudTCP::%s error download to nina: %d"), __FUNCTION__, nina_ota_err_code); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s error download to nina: %d"), __FUNCTION__, nina_ota_err_code); _ota_error = static_cast(OTAError::DownloadFailed); return; } From d9d50663b36381d08aa2859278fd2e747de9aa08 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 27 Jan 2021 06:39:08 +0100 Subject: [PATCH 025/780] List 'megaavr' as supported platform. --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 9b41bd40e..0b450496c 100644 --- a/library.properties +++ b/library.properties @@ -6,6 +6,6 @@ sentence=This library allows to connect to the Arduino IoT Cloud service. paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKRGSM, MKR1000 and WiFi101. category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud -architectures=mbed,samd,esp8266 +architectures=mbed,samd,esp8266,megaavr includes=ArduinoIoTCloud.h depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero From 11217fd44bd6efcb6746652d189ab57a003b4a1b Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 27 Jan 2021 06:43:18 +0100 Subject: [PATCH 026/780] As Arduino_AVRSTL is not yet released directly link to the repository. --- .github/workflows/compile-examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 6700631bf..22d4a42a4 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -87,7 +87,7 @@ jobs: - name: arduino:megaavr libraries: | - name: ArduinoECCX08 - - name: Arduino_AVRSTL + - source-url: https://github.com/arduino-libraries/Arduino_AVRSTL.git - name: WiFiNINA - name: Arduino_JSON - name: ArduinoBearSSL From 7e3e196edf61a2f09777105daafee204bef81b10 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 27 Jan 2021 06:48:14 +0100 Subject: [PATCH 027/780] Fixing as-of-yet-not-fixed wrong braces. --- src/ArduinoIoTCloudTCP.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 05385ef06..2c5870530 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -428,7 +428,7 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l #if OTA_ENABLED void ArduinoIoTCloudTCP::onOTARequest() { - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s"), __FUNCTION__, _ota_url.c_str()); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str()); /* Status flag to prevent the reset from being executed * when HTTPS download is not supported. @@ -444,7 +444,7 @@ void ArduinoIoTCloudTCP::onOTARequest() uint8_t nina_ota_err_code = 0; if (!WiFiStorage.downloadOTA(_ota_url.c_str(), &nina_ota_err_code)) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s error download to nina: %d"), __FUNCTION__, nina_ota_err_code); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s error download to nina: %d", __FUNCTION__, nina_ota_err_code); _ota_error = static_cast(OTAError::DownloadFailed); return; } From f9e85405a4c0fd556131cc430b1d7f5a4e0fabd5 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 27 Jan 2021 09:52:55 +0100 Subject: [PATCH 028/780] Cleaning up include structure. --- src/cbor/CBORDecoder.h | 6 ++++-- src/cbor/CBOREncoder.h | 9 +++++++-- src/property/Property.h | 11 +++++++++-- src/property/PropertyContainer.h | 6 ++++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/cbor/CBORDecoder.h b/src/cbor/CBORDecoder.h index c1cdd8330..d1bf91ca0 100644 --- a/src/cbor/CBORDecoder.h +++ b/src/cbor/CBORDecoder.h @@ -21,9 +21,11 @@ /****************************************************************************** INCLUDE ******************************************************************************/ -#ifdef __AVR__ + #include -#include + +#ifdef __AVR__ +# include #endif #undef max diff --git a/src/cbor/CBOREncoder.h b/src/cbor/CBOREncoder.h index af66bdbfe..2370a7b50 100644 --- a/src/cbor/CBOREncoder.h +++ b/src/cbor/CBOREncoder.h @@ -22,11 +22,16 @@ * INCLUDE ******************************************************************************/ -#ifdef __AVR__ #include -#include + +#ifdef __AVR__ +# include #endif +#undef max +#undef min +#include + #include "../property/PropertyContainer.h" /****************************************************************************** diff --git a/src/property/Property.h b/src/property/Property.h index f8db8a948..803d77049 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -28,11 +28,18 @@ ******************************************************************************/ #include -// in order to allow to define its own max and min functions + #undef max #undef min + +#ifdef __AVR__ +# include +# include +#else +# include +#endif + #include -#include #include "../cbor/lib/tinycbor/cbor-lib.h" diff --git a/src/property/PropertyContainer.h b/src/property/PropertyContainer.h index 3fd807a34..effa7d966 100644 --- a/src/property/PropertyContainer.h +++ b/src/property/PropertyContainer.h @@ -22,8 +22,14 @@ INCLUDE ******************************************************************************/ +#include + #include "Property.h" +#ifdef __AVR__ +# include +#endif + #undef max #undef min #include From 405198a61a06464d4692a36d2b1005434cfe2ff4 Mon Sep 17 00:00:00 2001 From: per1234 Date: Wed, 27 Jan 2021 03:00:56 -0800 Subject: [PATCH 029/780] Revert "Pin Arduino CLI version used in CI to 0.13.0 (#222)" This reverts commit 1ffe81137251c052d5978c051d9022d4912bb9c3. 1ffe81137251c052d5978c051d9022d4912bb9c3 was a temporary workaround for a bug in Arduino CLI 0.14.0. This was fixed with the release of Arduino CLI 0.14.1 so we are now able to go back to using the latest Arduino CLI version in the "Compile Examples" CI workflow. --- .github/workflows/compile-examples.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index c4d902eb9..9bc629faf 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -180,7 +180,6 @@ jobs: - name: Compile examples uses: arduino/compile-sketches@main with: - cli-version: 0.13.0 platforms: ${{ matrix.platforms }} fqbn: ${{ matrix.board.fqbn }} libraries: | From b57d900e04a16034d4fc7f38345288abe7f5c637 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 27 Jan 2021 17:28:09 +0100 Subject: [PATCH 030/780] megaAVR: don't use NTP time fallback It's required by the offloaded ecc anyway, so it will be ok --- src/utility/time/TimeService.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index b5e35dcd7..07d50fec6 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -105,6 +105,7 @@ unsigned long TimeService::getRemoteTime() return connection_time; } +#ifndef __AVR__ /* If no valid network time is available try to obtain the * time via NTP next. */ @@ -112,6 +113,7 @@ unsigned long TimeService::getRemoteTime() if(isTimeValid(ntp_time)) { return ntp_time; } +#endif #endif /* ifndef HAS_LORA */ From 4865f508c4de17eafc2b2eaf40738eb5bf020fb4 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 28 Jan 2021 07:38:39 +0100 Subject: [PATCH 031/780] Add braces to ensure correct order of operant execution. --- src/AIoTC_Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index f41fc5519..09052bf58 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -100,7 +100,7 @@ #define OTA_STORAGE_SSU (0) #endif -#if OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU && !defined(ARDUINO_AVR_UNO_WIFI_REV2) +#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU) && !defined(ARDUINO_AVR_UNO_WIFI_REV2) #define OTA_ENABLED (1) #else #define OTA_ENABLED (0) From 86b117026d9d13d8cd5b9bc4c03a4bc6a0132271 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 28 Jan 2021 07:54:54 +0100 Subject: [PATCH 032/780] Prevent execution of cloud firmware if a nina firmware < 1.4.2 is present. --- src/ArduinoIoTCloudTCP.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 2c5870530..2fa5eb039 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -103,6 +103,15 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) _brokerAddress = brokerAddress; _brokerPort = brokerPort; +#if defined(__AVR__) + String const nina_fw_version = WiFi.firmwareVersion(); + if (nina_fw_version < "1.4.2") + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s NINA firmware needs to be >= 1.4.2 to support cloud on Uno WiFi Rev. 2, current %s", __FUNCTION__, nina_fw_version.c_str()); + for(;;) { } + } +#endif /* AVR */ + #if OTA_ENABLED && !defined(__AVR__) /* Calculate the SHA256 checksum over the firmware stored in the flash of the * MCU. Note: As we don't know the length per-se we read chunks of the flash From 6e0e75f2fda047406b290210283c52d8950d4c27 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 28 Jan 2021 07:58:59 +0100 Subject: [PATCH 033/780] Automatically include Arduino_DebugUtils if any of the debug macros is actually defined, i.e. if any debug output is enabled on the platform. --- src/AIoTC_Config.h | 26 +++++++++++++------------- src/ArduinoIoTCloud.h | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 09052bf58..7188a9447 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -30,19 +30,6 @@ #define NTP_USE_RANDOM_PORT (1) #endif -#if defined(ARDUINO_AVR_UNO_WIFI_REV2) -/* Provide defines for constants provided within Arduino_DebugUtils - * in order to allow older sketches using those constants to still - * compile. - */ -# define DBG_NONE -1 -# define DBG_ERROR 0 -# define DBG_WARNING 1 -# define DBG_INFO 2 -# define DBG_DEBUG 3 -# define DBG_VERBOSE 4 -#endif - #ifndef DEBUG_ERROR # if defined(ARDUINO_AVR_UNO_WIFI_REV2) # define DEBUG_ERROR(fmt, ...) @@ -83,6 +70,19 @@ # endif #endif +#if defined(ARDUINO_AVR_UNO_WIFI_REV2) && !(defined(DEBUG_ERROR) || defined(DEBUG_WARNING) || defined(DEBUG_INFO) || defined(DEBUG_DEBUG) || defined(DEBUG_VERBOSE)) +/* Provide defines for constants provided within Arduino_DebugUtils + * in order to allow older sketches using those constants to still + * compile. + */ +# define DBG_NONE -1 +# define DBG_ERROR 0 +# define DBG_WARNING 1 +# define DBG_INFO 2 +# define DBG_DEBUG 3 +# define DBG_VERBOSE 4 +#endif + /****************************************************************************** * AUTOMATICALLY CONFIGURED DEFINES ******************************************************************************/ diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index bf70679e4..0130e3efc 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -26,7 +26,7 @@ #include -#if !defined(__AVR__) +#if defined(DEBUG_ERROR) || defined(DEBUG_WARNING) || defined(DEBUG_INFO) || defined(DEBUG_DEBUG) || defined(DEBUG_VERBOSE) # include #endif From 9b49af2ffd7ca7fa663c3254457b60854b4a3242 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 28 Jan 2021 07:59:57 +0100 Subject: [PATCH 034/780] Enable ERROR message output for Uno WiFi Rev. 2 (how should you be able to see errors otherwise)? --- src/AIoTC_Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 7188a9447..59292db11 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -32,7 +32,7 @@ #ifndef DEBUG_ERROR # if defined(ARDUINO_AVR_UNO_WIFI_REV2) -# define DEBUG_ERROR(fmt, ...) +# define DEBUG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) # else # define DEBUG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) # endif From 577f305e7150849a9a357d3be4f04d59299f9ddd Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 28 Jan 2021 08:04:10 +0100 Subject: [PATCH 035/780] Bugfix: Don't loop forever, just return 0. --- src/ArduinoIoTCloudTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 2fa5eb039..d1e886eee 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -108,7 +108,7 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) if (nina_fw_version < "1.4.2") { DEBUG_ERROR("ArduinoIoTCloudTCP::%s NINA firmware needs to be >= 1.4.2 to support cloud on Uno WiFi Rev. 2, current %s", __FUNCTION__, nina_fw_version.c_str()); - for(;;) { } + return 0; } #endif /* AVR */ From 8383de1271633a79378a3e666a8dd9547ec65bac Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 28 Jan 2021 08:06:18 +0100 Subject: [PATCH 036/780] Shortening error messages to conserve flash and eliminate unneccsary error messages. --- src/ArduinoIoTCloudTCP.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index d1e886eee..4a68ac7ae 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -129,12 +129,12 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) #ifdef BOARD_HAS_OFFLOADED_ECCX08 if (!ECCX08.begin()) { - DEBUG_ERROR("Cryptography processor failure. Make sure you have a compatible board."); + DEBUG_ERROR("ECCX08.begin() failed."); return 0; } if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) { - DEBUG_ERROR("Cryptography processor read failure."); + DEBUG_ERROR("CryptoUtil::readDeviceId(...) failed."); return 0; } ECCX08.end(); @@ -266,7 +266,9 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() if (!_mqttClient.subscribe(_dataTopicIn)) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); +#if !defined(__AVR__) DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); +#endif return State::SubscribeMqttTopics; } @@ -275,7 +277,9 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() if (!_mqttClient.subscribe(_shadowTopicIn)) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); +#if !defined(__AVR__) DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); +#endif return State::SubscribeMqttTopics; } } From 6cc464a7eba3accd7f828b2d207283e998eaf00f Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 21 Dec 2020 13:02:33 +0100 Subject: [PATCH 037/780] Enable OTA for Portenta H7 target --- src/ArduinoIoTCloudTCP.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 4a68ac7ae..88755fa62 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -123,7 +123,12 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) * The bootloader is excluded from the calculation and occupies flash address * range 0 to 0x2000, total flash size of 0x40000 bytes (256 kByte). */ +#if defined(ARDUINO_PORTENTA_H7_M7) + // TODO: check if we need to checksum the whole flash or just the first megabyte + _ota_img_sha256 = FlashSHA256::calc(0x8040000, 0x200000 - 0x40000); +#else _ota_img_sha256 = FlashSHA256::calc(0x2000, 0x40000 - 0x2000); +#endif #endif /* OTA_ENABLED */ #ifdef BOARD_HAS_OFFLOADED_ECCX08 @@ -391,7 +396,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) if ((_shadowTopicIn == topic) && (_state == State::RequestLastValues)) { - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); + DBG_VERBOSE(F("ArduinoIoTCloudTCP::%s [%d] last values received"), __FUNCTION__, millis()); CBORDecoder::decode(_property_container, (uint8_t*)bytes, length, true); sendPropertiesToCloud(); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); @@ -438,6 +443,10 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l return 0; } +#if OTA_STORAGE_PORTENTA_QSPI +#include "ArduinoOTAPortenta.h" +#endif + #if OTA_ENABLED void ArduinoIoTCloudTCP::onOTARequest() { From b00e31fb4bb60042d5f3f8bf9c0f83a222a55020 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 21 Dec 2020 15:32:07 +0100 Subject: [PATCH 038/780] Force check on Portenta BL version --- src/AIoTC_Config.h | 7 +++++++ src/ArduinoIoTCloudTCP.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 59292db11..9d1008f34 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -100,6 +100,13 @@ #define OTA_STORAGE_SSU (0) #endif +#if defined(ARDUINO_PORTENTA_H7_M7) + #define OTA_STORAGE_PORTENTA_QSPI (1) + #define OTA_STORAGE_PORTENTA (1) +#else + #define OTA_STORAGE_PORTENTA_QSPI (0) +#endif + #if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU) && !defined(ARDUINO_AVR_UNO_WIFI_REV2) #define OTA_ENABLED (1) #else diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 88755fa62..e4f9d06fd 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -475,6 +475,30 @@ void ArduinoIoTCloudTCP::onOTARequest() ota_download_success = true; #endif /* OTA_STORAGE_SNU */ +#if OTA_STORAGE_PORTENTA_QSPI + /* Just to be safe delete any remains from previous updates. */ + remove("/fs/UPDATE.BIN.LZSS"); + + OTAPortenta.begin(QSPI_FLASH_FATFS_MBR, 2048); + + if (OTAPortenta.download(_ota_url.c_str())) + { + DBG_ERROR(F("ArduinoIoTCloudTCP::%s error download to nina: %d"), __FUNCTION__, nina_ota_err_code); + _ota_error = static_cast(OTAError::DownloadFailed); + return; + } + + auto update_file_size = OTAPortenta.decompress(); + OTAPortenta.setUpdateLen(update_file_size); + + /* The download was a success. */ + ota_download_success = true; + + while (1) { + OTAPortenta.update(); + } +#endif /* OTA_STORAGE_PORTENTA_QSPI */ + #ifndef __AVR__ /* Perform the reset to reboot to SxU. */ if (ota_download_success) From 080197943f94d403dc3882415c39bd7a664365ef Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 13 Jan 2021 06:24:42 +0100 Subject: [PATCH 039/780] Bugfix: _ota_cap is false per default, but we need to set it to true if the bootloader is in fact capable of OTA support. --- src/ArduinoIoTCloudTCP.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e4f9d06fd..afcbdbd2f 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -191,6 +191,20 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) addPropertyReal(_ota_req, "OTA_REQ", Permission::ReadWrite).onSync(DEVICE_WINS); #endif /* OTA_ENABLED */ +#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; + DBG_WARNING(F("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, update the bootloader"), __FUNCTION__); + } + else { + _ota_cap = true; + } +#endif + #if OTA_STORAGE_SNU && OTA_ENABLED String const nina_fw_version = WiFi.firmwareVersion(); if (nina_fw_version < "1.4.1") { @@ -479,7 +493,8 @@ void ArduinoIoTCloudTCP::onOTARequest() /* Just to be safe delete any remains from previous updates. */ remove("/fs/UPDATE.BIN.LZSS"); - OTAPortenta.begin(QSPI_FLASH_FATFS_MBR, 2048); + // Use second partition + OTAPortenta.begin(QSPI_FLASH_FATFS_MBR, 2); if (OTAPortenta.download(_ota_url.c_str())) { From 09784c884f9e38247aa419c489879c5d284cd45e Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 13 Jan 2021 06:28:12 +0100 Subject: [PATCH 040/780] Moving inclusion of ArduinoOTAPortenta into the correct spot of the codebase. --- src/ArduinoIoTCloudTCP.cpp | 4 ---- src/utility/ota/OTA.h | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index afcbdbd2f..f73ba73e8 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -457,10 +457,6 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l return 0; } -#if OTA_STORAGE_PORTENTA_QSPI -#include "ArduinoOTAPortenta.h" -#endif - #if OTA_ENABLED void ArduinoIoTCloudTCP::onOTARequest() { diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index bd1476fba..db5751cdd 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -37,6 +37,10 @@ #include #endif /* OTA_STORAGE_SFU */ +#if OTA_STORAGE_PORTENTA_QSPI + #include +#endif /* OTA_STORAGE_PORTENTA_QSPI */ + /****************************************************************************** * TYPEDEF ******************************************************************************/ From a315afbb8840ad577afaa2adf44570dacbdb8677 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 13 Jan 2021 06:43:37 +0100 Subject: [PATCH 041/780] Temporary change: Add link to latest ArduinoOTAPortenta library to be used in order to verify CI build. This needs to be replaced with the library name only as soon as this library has been properly released. --- .github/workflows/compile-examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 22d4a42a4..a6d5dd62a 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -137,6 +137,7 @@ jobs: name: arduino:mbed libraries: | - name: ArduinoECCX08 + - source-url: https://github.com/facchinm/ArduinoOTAPortenta.git sketch-paths: | - examples/utility/Provisioning # ESP8266 boards From 690108f04b49f594d7b14530d8e339615fe48632 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 19 Jan 2021 14:56:18 +0100 Subject: [PATCH 042/780] Restructuring OTA code in light of adaptions made to Arduino_OTA_Portenta library. --- .github/workflows/compile-examples.yml | 2 +- src/ArduinoIoTCloudTCP.cpp | 58 ++++++++++++++------------ src/utility/ota/OTA.h | 2 +- 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index a6d5dd62a..833acccaa 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -137,7 +137,7 @@ jobs: name: arduino:mbed libraries: | - name: ArduinoECCX08 - - source-url: https://github.com/facchinm/ArduinoOTAPortenta.git + - source-url: https://github.com/facchinm/Arduino_OTA_Portenta.git sketch-paths: | - examples/utility/Provisioning # ESP8266 boards diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index f73ba73e8..5b450d1b6 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -330,7 +330,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() { if (!_mqttClient.connected()) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); + DBG_ERROR(F("ArduinoIoTCloudTCP::%s MQTT client connection lost"), __FUNCTION__); /* Forcefully disconnect MQTT client and trigger a reconnection. */ _mqttClient.stop(); @@ -460,12 +460,7 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l #if OTA_ENABLED void ArduinoIoTCloudTCP::onOTARequest() { - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str()); - - /* Status flag to prevent the reset from being executed - * when HTTPS download is not supported. - */ - bool ota_download_success = false; + DBG_VERBOSE(F("ArduinoIoTCloudTCP::%s _ota_url = %s"), __FUNCTION__, _ota_url.c_str()); #if OTA_STORAGE_SNU /* Just to be safe delete any remains from previous updates. */ @@ -481,40 +476,49 @@ void ArduinoIoTCloudTCP::onOTARequest() return; } - /* The download was a success. */ - ota_download_success = true; + /* Perform the reset to reboot to SxU. */ + NVIC_SystemReset(); #endif /* OTA_STORAGE_SNU */ #if OTA_STORAGE_PORTENTA_QSPI /* Just to be safe delete any remains from previous updates. */ remove("/fs/UPDATE.BIN.LZSS"); - // Use second partition - OTAPortenta.begin(QSPI_FLASH_FATFS_MBR, 2); + Arduino_OTA_Portenta::Error ota_portenta_err = Arduino_OTA_Portenta::Error::None; + /* Use 2nd partition of QSPI (1st partition contains WiFi firmware) */ + Arduino_OTA_Portenta_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2); - if (OTAPortenta.download(_ota_url.c_str())) - { - DBG_ERROR(F("ArduinoIoTCloudTCP::%s error download to nina: %d"), __FUNCTION__, nina_ota_err_code); - _ota_error = static_cast(OTAError::DownloadFailed); + /* Initialize the QSPI memory for OTA handling. */ + if((ota_portenta_err = ota_portenta_qspi.begin()) != Arduino_OTA_Portenta::Error::None) { + DBG_ERROR(F("Arduino_OTA_Portenta_QSPI::begin() failed with %d"), static_cast(ota_portenta_err)); return; } - auto update_file_size = OTAPortenta.decompress(); - OTAPortenta.setUpdateLen(update_file_size); + /* Download the OTA file from the web storage location. */ + int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download((char*)(_ota_url.c_str())); + DBG_VERBOSE(F("Arduino_OTA_Portenta_QSPI::download(%s) returns %d"), _ota_url.c_str(), ota_portenta_qspi_download_ret_code); - /* The download was a success. */ - ota_download_success = true; + /* Decompress the LZSS compressed OTA file. */ + int const ota_portenta_qspi_decompress_ret_code = ota_portenta_qspi.decompress(); + DBG_VERBOSE(F("Arduino_OTA_Portenta_QSPI::decompress() returns %d"), ota_portenta_qspi_decompress_ret_code); + if (ota_portenta_qspi_decompress_ret_code < 0) + { + DBG_ERROR(F("Arduino_OTA_Portenta_QSPI::decompress() failed with %d"), ota_portenta_qspi_decompress_ret_code); + return; + } + /* Set the correct update size. */ + size_t const update_file_size = ota_portenta_qspi_decompress_ret_code; + ota_portenta_qspi.setUpdateLen(update_file_size); - while (1) { - OTAPortenta.update(); + /* Schedule the firmware update. */ + if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_OTA_Portenta::Error::None) { + DBG_ERROR(F("Arduino_OTA_Portenta_QSPI::update() failed with %d"), static_cast(ota_portenta_err)); + return; } -#endif /* OTA_STORAGE_PORTENTA_QSPI */ -#ifndef __AVR__ - /* Perform the reset to reboot to SxU. */ - if (ota_download_success) - NVIC_SystemReset(); -#endif + /* Perform the reset to reboot - then the bootloader performs the actual application update. */ + NVIC_SystemReset(); +#endif /* OTA_STORAGE_PORTENTA_QSPI */ } #endif diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index db5751cdd..7da19806f 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -38,7 +38,7 @@ #endif /* OTA_STORAGE_SFU */ #if OTA_STORAGE_PORTENTA_QSPI - #include + #include #endif /* OTA_STORAGE_PORTENTA_QSPI */ /****************************************************************************** From c915dfd585802cea6671ad212a2788ee162c1d4f Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 20 Jan 2021 07:08:41 +0100 Subject: [PATCH 043/780] Adjusting renaming of types names for Portenta OTA to follow suit with renamings within the Arduino_Portenta_OTA library itself. --- src/ArduinoIoTCloudTCP.cpp | 18 +++++++++--------- src/utility/ota/OTA.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 5b450d1b6..6f3c5da6a 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -484,26 +484,26 @@ void ArduinoIoTCloudTCP::onOTARequest() /* Just to be safe delete any remains from previous updates. */ remove("/fs/UPDATE.BIN.LZSS"); - Arduino_OTA_Portenta::Error ota_portenta_err = Arduino_OTA_Portenta::Error::None; + Arduino_Portenta_OTA::Error ota_portenta_err = Arduino_Portenta_OTA::Error::None; /* Use 2nd partition of QSPI (1st partition contains WiFi firmware) */ - Arduino_OTA_Portenta_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2); + Arduino_Portenta_OTA_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2); /* Initialize the QSPI memory for OTA handling. */ - if((ota_portenta_err = ota_portenta_qspi.begin()) != Arduino_OTA_Portenta::Error::None) { - DBG_ERROR(F("Arduino_OTA_Portenta_QSPI::begin() failed with %d"), static_cast(ota_portenta_err)); + if((ota_portenta_err = ota_portenta_qspi.begin()) != Arduino_Portenta_OTA::Error::None) { + DBG_ERROR(F("Arduino_Portenta_OTA_QSPI::begin() failed with %d"), static_cast(ota_portenta_err)); return; } /* Download the OTA file from the web storage location. */ int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download((char*)(_ota_url.c_str())); - DBG_VERBOSE(F("Arduino_OTA_Portenta_QSPI::download(%s) returns %d"), _ota_url.c_str(), ota_portenta_qspi_download_ret_code); + DBG_VERBOSE(F("Arduino_Portenta_OTA_QSPI::download(%s) returns %d"), _ota_url.c_str(), ota_portenta_qspi_download_ret_code); /* Decompress the LZSS compressed OTA file. */ int const ota_portenta_qspi_decompress_ret_code = ota_portenta_qspi.decompress(); - DBG_VERBOSE(F("Arduino_OTA_Portenta_QSPI::decompress() returns %d"), ota_portenta_qspi_decompress_ret_code); + DBG_VERBOSE(F("Arduino_Portenta_OTA_QSPI::decompress() returns %d"), ota_portenta_qspi_decompress_ret_code); if (ota_portenta_qspi_decompress_ret_code < 0) { - DBG_ERROR(F("Arduino_OTA_Portenta_QSPI::decompress() failed with %d"), ota_portenta_qspi_decompress_ret_code); + DBG_ERROR(F("Arduino_Portenta_OTA_QSPI::decompress() failed with %d"), ota_portenta_qspi_decompress_ret_code); return; } /* Set the correct update size. */ @@ -511,8 +511,8 @@ void ArduinoIoTCloudTCP::onOTARequest() ota_portenta_qspi.setUpdateLen(update_file_size); /* Schedule the firmware update. */ - if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_OTA_Portenta::Error::None) { - DBG_ERROR(F("Arduino_OTA_Portenta_QSPI::update() failed with %d"), static_cast(ota_portenta_err)); + if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) { + DBG_ERROR(F("Arduino_Portenta_OTA_QSPI::update() failed with %d"), static_cast(ota_portenta_err)); return; } diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 7da19806f..670b5ac07 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -38,7 +38,7 @@ #endif /* OTA_STORAGE_SFU */ #if OTA_STORAGE_PORTENTA_QSPI - #include + #include #endif /* OTA_STORAGE_PORTENTA_QSPI */ /****************************************************************************** From b4806cc62dc133ba712116e24953d29c9dd16f1d Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 28 Jan 2021 12:17:14 +0100 Subject: [PATCH 044/780] Renaming still incorrect debug macros. --- src/ArduinoIoTCloudTCP.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 6f3c5da6a..8f2607852 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -330,7 +330,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() { if (!_mqttClient.connected()) { - DBG_ERROR(F("ArduinoIoTCloudTCP::%s MQTT client connection lost"), __FUNCTION__); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); /* Forcefully disconnect MQTT client and trigger a reconnection. */ _mqttClient.stop(); @@ -410,7 +410,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) if ((_shadowTopicIn == topic) && (_state == State::RequestLastValues)) { - DBG_VERBOSE(F("ArduinoIoTCloudTCP::%s [%d] last values received"), __FUNCTION__, millis()); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); CBORDecoder::decode(_property_container, (uint8_t*)bytes, length, true); sendPropertiesToCloud(); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); @@ -490,7 +490,7 @@ void ArduinoIoTCloudTCP::onOTARequest() /* Initialize the QSPI memory for OTA handling. */ if((ota_portenta_err = ota_portenta_qspi.begin()) != Arduino_Portenta_OTA::Error::None) { - DBG_ERROR(F("Arduino_Portenta_OTA_QSPI::begin() failed with %d"), static_cast(ota_portenta_err)); + DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::begin() failed with %d", static_cast(ota_portenta_err)); return; } @@ -503,7 +503,7 @@ void ArduinoIoTCloudTCP::onOTARequest() DBG_VERBOSE(F("Arduino_Portenta_OTA_QSPI::decompress() returns %d"), ota_portenta_qspi_decompress_ret_code); if (ota_portenta_qspi_decompress_ret_code < 0) { - DBG_ERROR(F("Arduino_Portenta_OTA_QSPI::decompress() failed with %d"), ota_portenta_qspi_decompress_ret_code); + DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::decompress() failed with %d", ota_portenta_qspi_decompress_ret_code); return; } /* Set the correct update size. */ @@ -512,7 +512,7 @@ void ArduinoIoTCloudTCP::onOTARequest() /* Schedule the firmware update. */ if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) { - DBG_ERROR(F("Arduino_Portenta_OTA_QSPI::update() failed with %d"), static_cast(ota_portenta_err)); + DEBUG_ERROR(F("Arduino_Portenta_OTA_QSPI::update() failed with %d"), static_cast(ota_portenta_err)); return; } From 7076c27f75b49e74a699b56b5ed9cc14c89d9f1a Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 28 Jan 2021 12:28:05 +0100 Subject: [PATCH 045/780] Ensure that OTA_ENABLE is set correctly. --- src/AIoTC_Config.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 9d1008f34..bc451ad44 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -102,12 +102,11 @@ #if defined(ARDUINO_PORTENTA_H7_M7) #define OTA_STORAGE_PORTENTA_QSPI (1) - #define OTA_STORAGE_PORTENTA (1) #else #define OTA_STORAGE_PORTENTA_QSPI (0) #endif -#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU) && !defined(ARDUINO_AVR_UNO_WIFI_REV2) +#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU || OTA_STORAGE_PORTENTA_QSPI) && !defined(ARDUINO_AVR_UNO_WIFI_REV2) #define OTA_ENABLED (1) #else #define OTA_ENABLED (0) From c9dea0f32ac7b5190ff77839785c9cc2e617ec37 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 28 Jan 2021 12:28:38 +0100 Subject: [PATCH 046/780] Eliminating no longer existing API setUpdateLen. --- src/ArduinoIoTCloudTCP.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 8f2607852..cf687fb95 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -506,9 +506,6 @@ void ArduinoIoTCloudTCP::onOTARequest() DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::decompress() failed with %d", ota_portenta_qspi_decompress_ret_code); return; } - /* Set the correct update size. */ - size_t const update_file_size = ota_portenta_qspi_decompress_ret_code; - ota_portenta_qspi.setUpdateLen(update_file_size); /* Schedule the firmware update. */ if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) { From d395a2bfae3b8e23614bb972cf9434dcc09687e4 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 28 Jan 2021 12:33:22 +0100 Subject: [PATCH 047/780] Fixing a couple of more wrong debug macros. --- src/ArduinoIoTCloudTCP.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index cf687fb95..e3a59c0e6 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -198,7 +198,7 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) uint8_t currentBootloaderVersion = bootloader_data[1]; if (currentBootloaderVersion < 22) { _ota_cap = false; - DBG_WARNING(F("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, update the bootloader"), __FUNCTION__); + DEBUG_WARNING("ArduinoIoTCloudTCP::%s In order to be ready for cloud OTA, update the bootloader", __FUNCTION__); } else { _ota_cap = true; @@ -460,7 +460,7 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l #if OTA_ENABLED void ArduinoIoTCloudTCP::onOTARequest() { - DBG_VERBOSE(F("ArduinoIoTCloudTCP::%s _ota_url = %s"), __FUNCTION__, _ota_url.c_str()); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str()); #if OTA_STORAGE_SNU /* Just to be safe delete any remains from previous updates. */ @@ -496,11 +496,11 @@ void ArduinoIoTCloudTCP::onOTARequest() /* Download the OTA file from the web storage location. */ int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download((char*)(_ota_url.c_str())); - DBG_VERBOSE(F("Arduino_Portenta_OTA_QSPI::download(%s) returns %d"), _ota_url.c_str(), ota_portenta_qspi_download_ret_code); + DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::download(%s) returns %d", _ota_url.c_str(), ota_portenta_qspi_download_ret_code); /* Decompress the LZSS compressed OTA file. */ int const ota_portenta_qspi_decompress_ret_code = ota_portenta_qspi.decompress(); - DBG_VERBOSE(F("Arduino_Portenta_OTA_QSPI::decompress() returns %d"), ota_portenta_qspi_decompress_ret_code); + DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::decompress() returns %d", ota_portenta_qspi_decompress_ret_code); if (ota_portenta_qspi_decompress_ret_code < 0) { DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::decompress() failed with %d", ota_portenta_qspi_decompress_ret_code); @@ -509,7 +509,7 @@ void ArduinoIoTCloudTCP::onOTARequest() /* Schedule the firmware update. */ if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) { - DEBUG_ERROR(F("Arduino_Portenta_OTA_QSPI::update() failed with %d"), static_cast(ota_portenta_err)); + DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::update() failed with %d", static_cast(ota_portenta_err)); return; } From 66ce560336a53f3d1495964637f3f48ebbe02a35 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 1 Feb 2021 10:34:03 +0100 Subject: [PATCH 048/780] Extending bin2ota script for generating OTA file for PORTENTA_H7_M7. --- extras/tools/bin2ota.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extras/tools/bin2ota.py b/extras/tools/bin2ota.py index 99e86c0df..648aa2395 100755 --- a/extras/tools/bin2ota.py +++ b/extras/tools/bin2ota.py @@ -22,6 +22,8 @@ magic_number = 0x23418054.to_bytes(4,byteorder='little') elif board == "NANO_33_IOT": magic_number = 0x23418057.to_bytes(4,byteorder='little') +elif board == "PORTENTA_H7_M7": + magic_number = 0x2341025B.to_bytes(4,byteorder='little') else: print ("Error,", board, "is not a supported board type") sys.exit() From 194c95ca62fe4cdbd20d77202e9ed58ace3271f6 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 1 Feb 2021 14:41:28 +0100 Subject: [PATCH 049/780] Moving the delete step of any previous update file to after where the file system is initialised. --- src/ArduinoIoTCloudTCP.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e3a59c0e6..47095de4a 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -481,9 +481,6 @@ void ArduinoIoTCloudTCP::onOTARequest() #endif /* OTA_STORAGE_SNU */ #if OTA_STORAGE_PORTENTA_QSPI - /* Just to be safe delete any remains from previous updates. */ - remove("/fs/UPDATE.BIN.LZSS"); - Arduino_Portenta_OTA::Error ota_portenta_err = Arduino_Portenta_OTA::Error::None; /* Use 2nd partition of QSPI (1st partition contains WiFi firmware) */ Arduino_Portenta_OTA_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2); @@ -494,6 +491,9 @@ void ArduinoIoTCloudTCP::onOTARequest() return; } + /* Just to be safe delete any remains from previous updates. */ + remove("/fs/UPDATE.BIN.LZSS"); + /* Download the OTA file from the web storage location. */ int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download((char*)(_ota_url.c_str())); DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::download(%s) returns %d", _ota_url.c_str(), ota_portenta_qspi_download_ret_code); From 8a663ce237f4cfc02e3355fc58638af483dd9a72 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 1 Feb 2021 14:47:56 +0100 Subject: [PATCH 050/780] Also remove the update binary in case there are any remains left from previous updates. --- src/ArduinoIoTCloudTCP.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 47095de4a..49ea8841f 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -492,6 +492,7 @@ void ArduinoIoTCloudTCP::onOTARequest() } /* Just to be safe delete any remains from previous updates. */ + remove("/fs/UPDATE.BIN"); remove("/fs/UPDATE.BIN.LZSS"); /* Download the OTA file from the web storage location. */ From 8122d4703352ffe3f5f0296426ead56182f739e0 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 1 Feb 2021 14:57:30 +0100 Subject: [PATCH 051/780] Reversion: Only use BearSSL offload for Uno WiFi Rev. 2 until we figure out an upgrade path for all current MKR WIFI 1010, NANO 33 IOT users. --- src/AIoTC_Config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 59292db11..b52b9239f 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -107,14 +107,14 @@ #endif #if defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKR1000) || \ + defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_PORTENTA_H7_M7) || \ defined(ARDUINO_PORTENTA_H7_M4) #define BOARD_HAS_ECCX08 #define HAS_TCP #endif -#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ - defined(ARDUINO_AVR_UNO_WIFI_REV2) +#if defined(ARDUINO_AVR_UNO_WIFI_REV2) #define BOARD_HAS_OFFLOADED_ECCX08 #define HAS_TCP #endif From dfe1894e854d484a329fb508d09c25ab91690312 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 1 Feb 2021 15:15:53 +0100 Subject: [PATCH 052/780] Release v0.12.0 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 0b450496c..4c6c82730 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=0.11.3 +version=0.12.0 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From 52177d5db7d2ea31abdc5e1634b0de9698ac4c8b Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 2 Feb 2021 09:10:56 +0100 Subject: [PATCH 053/780] Add more detailed information on how to update the bootloader for Portenta H7. --- src/ArduinoIoTCloudTCP.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 49ea8841f..0bb7e09bd 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -199,6 +199,7 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) 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; From a6bef66cce606d2fe842262aa05503c31281656b Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 2 Feb 2021 09:54:09 +0100 Subject: [PATCH 054/780] Adapt to new dowload API call. --- src/ArduinoIoTCloudTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 0bb7e09bd..4bd44e056 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -497,7 +497,7 @@ void ArduinoIoTCloudTCP::onOTARequest() remove("/fs/UPDATE.BIN.LZSS"); /* Download the OTA file from the web storage location. */ - int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download((char*)(_ota_url.c_str())); + int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download((char*)(_ota_url.c_str()), true /* is_https */); DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::download(%s) returns %d", _ota_url.c_str(), ota_portenta_qspi_download_ret_code); /* Decompress the LZSS compressed OTA file. */ From 43476acdcdf615f7d13548e939fe67e2aafecf52 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 2 Feb 2021 11:02:13 +0100 Subject: [PATCH 055/780] Update location of Arduino_Portenta_OTA library. --- .github/workflows/compile-examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 833acccaa..d491ead03 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -137,7 +137,7 @@ jobs: name: arduino:mbed libraries: | - name: ArduinoECCX08 - - source-url: https://github.com/facchinm/Arduino_OTA_Portenta.git + - source-url: https://github.com/arduino-libraries/Arduino_Portenta_OTA.git sketch-paths: | - examples/utility/Provisioning # ESP8266 boards From dc38b8031e7a309ddce4de00ecd2bf2ce2babfef Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 2 Feb 2021 11:20:36 +0100 Subject: [PATCH 056/780] Release v0.13.0 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 4c6c82730..8f164f643 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=0.12.0 +version=0.13.0 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From 6a4e8f4ae65b948a6c1c8dea8358e3a72335e5cc Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 9 Feb 2021 09:10:10 +0100 Subject: [PATCH 057/780] Fix SHA256 calculation required for verification of a sucessful download by cloud server. --- src/ArduinoIoTCloudTCP.cpp | 55 ++++++++++++++++++++++++++++++--- src/utility/ota/FlashSHA256.cpp | 1 - 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 4bd44e056..828d47c84 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -33,11 +33,24 @@ #include "tls/utility/CryptoUtil.h" #endif +#if defined(ARDUINO_PORTENTA_H7_M7) +# include "tls/utility/SHA256.h" +# include +#endif + #include "utility/ota/OTA.h" #include "utility/ota/FlashSHA256.h" #include "cbor/CBOREncoder.h" +/****************************************************************************** + * EXTERN + ******************************************************************************/ + +#if defined(ARDUINO_PORTENTA_H7_M7) +extern RTC_HandleTypeDef RTCHandle; +#endif + /****************************************************************************** GLOBAL CONSTANTS ******************************************************************************/ @@ -113,6 +126,40 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) #endif /* AVR */ #if OTA_ENABLED && !defined(__AVR__) +#if defined(ARDUINO_PORTENTA_H7_M7) + /* The length of the application can be retrieved the same way it was + * communicated to the bootloader, that is by writing to the non-volatile + * storage registers of the RTC. + */ + SHA256 sha256; + uint32_t const app_start = 0x8040000; + uint32_t const app_size = HAL_RTCEx_BKUPRead(&RTCHandle, RTC_BKP_DR3); + + sha256.begin(); + uint32_t b = 0; + uint32_t bytes_read = 0; for(uint32_t a = app_start; + bytes_read < app_size; + bytes_read += sizeof(b), a += sizeof(b)) + { + /* Read the next chunk of memory. */ + memcpy(&b, reinterpret_cast(a), sizeof(b)); + /* Feed it to SHA256. */ + sha256.update(reinterpret_cast(&b), sizeof(b)); + } + /* Retrieve the final hash string. */ + uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; + sha256.finalize(sha256_hash); + String sha256_str; + std::for_each(sha256_hash, + sha256_hash + SHA256::HASH_SIZE, + [&sha256_str](uint8_t const elem) + { + char buf[4]; + snprintf(buf, 4, "%02X", elem); + sha256_str += buf; + }); + DEBUG_VERBOSE("SHA256: %d bytes (of %d) read", bytes_read, app_size); +#else /* Calculate the SHA256 checksum over the firmware stored in the flash of the * MCU. Note: As we don't know the length per-se we read chunks of the flash * until we detect one containing only 0xFF (= flash erased). This only works @@ -123,12 +170,10 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) * The bootloader is excluded from the calculation and occupies flash address * range 0 to 0x2000, total flash size of 0x40000 bytes (256 kByte). */ -#if defined(ARDUINO_PORTENTA_H7_M7) - // TODO: check if we need to checksum the whole flash or just the first megabyte - _ota_img_sha256 = FlashSHA256::calc(0x8040000, 0x200000 - 0x40000); -#else - _ota_img_sha256 = FlashSHA256::calc(0x2000, 0x40000 - 0x2000); + String const sha256_str = FlashSHA256::calc(0x2000, 0x40000 - 0x2000); #endif + DEBUG_VERBOSE("SHA256: HASH(%d) = %s", strlen(sha256_str.c_str()), sha256_str.c_str()); + _ota_img_sha256 = sha256_str; #endif /* OTA_ENABLED */ #ifdef BOARD_HAS_OFFLOADED_ECCX08 diff --git a/src/utility/ota/FlashSHA256.cpp b/src/utility/ota/FlashSHA256.cpp index 12290a612..3bdc034c9 100644 --- a/src/utility/ota/FlashSHA256.cpp +++ b/src/utility/ota/FlashSHA256.cpp @@ -101,7 +101,6 @@ String FlashSHA256::calc(uint32_t const start_addr, uint32_t const max_flash_siz }); /* Do some debug printout. */ DEBUG_VERBOSE("SHA256: %d bytes read", flash_addr); - DEBUG_VERBOSE("SHA256: HASH(%d) = %s", strlen(sha256_str.c_str()), sha256_str.c_str()); return sha256_str; } From 8ca47ecacf2ed126fa0baa4944adbd296acee30d Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 9 Feb 2021 09:29:18 +0100 Subject: [PATCH 058/780] Release v0.13.1 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 8f164f643..a3d606b2c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=0.13.0 +version=0.13.1 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From 85e859f7deb1bef1c255d4a9bded9e0da5ccdfe1 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 9 Feb 2021 14:19:36 +0100 Subject: [PATCH 059/780] Use latest released version for CI build for Arduino_AVRSTL and Arduino_Portenta_OTA (#229) --- .github/workflows/compile-examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index a283ed9f7..8ee6c1ac9 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -87,7 +87,7 @@ jobs: - name: arduino:megaavr libraries: | - name: ArduinoECCX08 - - source-url: https://github.com/arduino-libraries/Arduino_AVRSTL.git + - name: Arduino_AVRSTL - name: WiFiNINA - name: Arduino_JSON - name: ArduinoBearSSL @@ -137,7 +137,7 @@ jobs: name: arduino:mbed libraries: | - name: ArduinoECCX08 - - source-url: https://github.com/arduino-libraries/Arduino_Portenta_OTA.git + - name: Arduino_Portenta_OTA sketch-paths: | - examples/utility/Provisioning # ESP8266 boards From 68f4b51658d6d8440724e8519571dc65756a6aa2 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 11 Feb 2021 10:51:30 +0100 Subject: [PATCH 060/780] Use authenticated GH API requests in "Compile Examples" CI workflow (#230) The arduino/compile-sketches GitHub Actions action needs to do a GitHub API request to determine the base branch of a PR for the deltas determination. If a token is not defined via the action's github-token input, it does an unauthenticated API request, which is subject to more strict rate limiting policy. Although its unlikely for the number of API requests to exceed the unauthenticated allowance, use of a token ensures it will never happen. GitHub Actions provides a token for this purpose, so there is no need to set up a custom one. --- .github/workflows/compile-examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 8ee6c1ac9..559a184ac 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -196,6 +196,7 @@ jobs: - name: Compile examples uses: arduino/compile-sketches@main with: + github-token: ${{ secrets.GITHUB_TOKEN }} platforms: ${{ matrix.platforms }} fqbn: ${{ matrix.board.fqbn }} libraries: | From 8c60f9f686f07f778f83f4243e53591b05ad2b9f Mon Sep 17 00:00:00 2001 From: Kody Rogers Date: Sat, 20 Feb 2021 21:15:46 -0600 Subject: [PATCH 061/780] fix typo in the ArduinoIoTCloud-Callbacks example --- .../ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino index a226a1926..f78417218 100644 --- a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino +++ b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino @@ -56,7 +56,7 @@ void setup() { */ ArduinoCloud.addCallback(ArduinoIoTCloudEvent::CONNECT, doThisOnConnect); ArduinoCloud.addCallback(ArduinoIoTCloudEvent::SYNC, doThisOnSync); - ArduinoCloud.addCallback(ArduinoIoTCloudEvent::CONNECT, doThisOnDisconnect); + ArduinoCloud.addCallback(ArduinoIoTCloudEvent::DISCONNECT, doThisOnDisconnect); setDebugMessageLevel(DBG_INFO); ArduinoCloud.printDebugInfo(); From 0f70b6862f94fc5e2beea9c4fa706b928b402978 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 1 Mar 2021 08:41:22 +0100 Subject: [PATCH 062/780] Through usage of the dedicated flag _sslio_closing we do manage to prevent getting stuck up in low_read/low_write (BearSSLClient::clientRead/clientWrite. --- src/tls/BearSSLClient.cpp | 23 +++++++++++++++++++++++ src/tls/BearSSLClient.h | 1 + 2 files changed, 24 insertions(+) diff --git a/src/tls/BearSSLClient.cpp b/src/tls/BearSSLClient.cpp index 5c2cd24c8..156697a3a 100644 --- a/src/tls/BearSSLClient.cpp +++ b/src/tls/BearSSLClient.cpp @@ -36,6 +36,10 @@ extern "C" void aiotc_client_profile_init(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +bool BearSSLClient::_sslio_closing = false; + + BearSSLClient::BearSSLClient(Client* client, const br_x509_trust_anchor* myTAs, int myNumTAs, GetTimeCallbackFunc func) : _client(client), _TAs(myTAs), @@ -156,6 +160,7 @@ void BearSSLClient::stop() { if (_client->connected()) { if ((br_ssl_engine_current_state(&_sc.eng) & BR_SSL_CLOSED) == 0) { + BearSSLClient::_sslio_closing = true; br_sslio_close(&_ioc); } @@ -258,6 +263,9 @@ int BearSSLClient::errorCode() int BearSSLClient::connectSSL(const char* host) { + /* Ensure this flag is cleared so we don't terminate a just starting connection. */ + _sslio_closing = false; + // initialize client context with all necessary algorithms and hardcoded trust anchors. aiotc_client_profile_init(&_sc, &_xc, _TAs, _numTAs); @@ -313,8 +321,18 @@ int BearSSLClient::connectSSL(const char* host) // #define DEBUGSERIAL Serial +/* Define the prototype so that it can be found by the compiler, + * the correct function is then assigned at link time. + */ +extern "C" void br_ssl_engine_fail(br_ssl_engine_context *rc, int err); + int BearSSLClient::clientRead(void *ctx, unsigned char *buf, size_t len) { + if (BearSSLClient::_sslio_closing) { + br_ssl_engine_fail(reinterpret_cast(ctx)->engine, BR_ERR_IO); + return -1; + } + Client* c = (Client*)ctx; if (!c->connected()) { @@ -346,6 +364,11 @@ int BearSSLClient::clientRead(void *ctx, unsigned char *buf, size_t len) int BearSSLClient::clientWrite(void *ctx, const unsigned char *buf, size_t len) { + if (BearSSLClient::_sslio_closing) { + br_ssl_engine_fail(reinterpret_cast(ctx)->engine, BR_ERR_IO); + return -1; + } + Client* c = (Client*)ctx; #ifdef DEBUGSERIAL diff --git a/src/tls/BearSSLClient.h b/src/tls/BearSSLClient.h index dd48f9d7e..ff60214db 100644 --- a/src/tls/BearSSLClient.h +++ b/src/tls/BearSSLClient.h @@ -98,6 +98,7 @@ class BearSSLClient : public Client { br_x509_certificate _ecCert; bool _ecCertDynamic; + static bool _sslio_closing; br_ssl_client_context _sc; br_x509_minimal_context _xc; unsigned char _ibuf[BEAR_SSL_CLIENT_IBUF_SIZE]; From 5d3b90c508a05c6d688c891977fa6e077d0f4e69 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 1 Mar 2021 08:48:37 +0100 Subject: [PATCH 063/780] Also check if connection to the MQTT server is still established during topic subscription and request of last values. Otherwise it can happen that the connection is ripped out under you and you won't even notice. --- src/ArduinoIoTCloudTCP.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 828d47c84..4d6d294e4 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -328,6 +328,14 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() { + if (!_mqttClient.connected()) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); + _mqttClient.stop(); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + return State::ConnectPhy; + } + if (!_mqttClient.subscribe(_dataTopicIn)) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); @@ -360,6 +368,14 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() { + if (!_mqttClient.connected()) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); + _mqttClient.stop(); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + return State::ConnectPhy; + } + /* Check whether or not we need to send a new request. */ unsigned long const now = millis(); if ((now - _lastSyncRequestTickTime) > TIMEOUT_FOR_LASTVALUES_SYNC) From d09b90cd77b8b284b4732490f68dfea822c169ca Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 3 Mar 2021 13:41:26 +0100 Subject: [PATCH 064/780] Invalid reinterpret cast causes memory access violation. --- src/tls/BearSSLClient.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tls/BearSSLClient.cpp b/src/tls/BearSSLClient.cpp index 156697a3a..a5192dd55 100644 --- a/src/tls/BearSSLClient.cpp +++ b/src/tls/BearSSLClient.cpp @@ -329,7 +329,6 @@ extern "C" void br_ssl_engine_fail(br_ssl_engine_context *rc, int err); int BearSSLClient::clientRead(void *ctx, unsigned char *buf, size_t len) { if (BearSSLClient::_sslio_closing) { - br_ssl_engine_fail(reinterpret_cast(ctx)->engine, BR_ERR_IO); return -1; } @@ -365,7 +364,6 @@ int BearSSLClient::clientRead(void *ctx, unsigned char *buf, size_t len) int BearSSLClient::clientWrite(void *ctx, const unsigned char *buf, size_t len) { if (BearSSLClient::_sslio_closing) { - br_ssl_engine_fail(reinterpret_cast(ctx)->engine, BR_ERR_IO); return -1; } From 9852cd685fc4b38840db7ce89cbe4b6050ce57e5 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 4 Mar 2021 11:00:27 +0100 Subject: [PATCH 065/780] Removing no longer needed extern declaration of br_ssl_engine_fail. --- src/tls/BearSSLClient.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/tls/BearSSLClient.cpp b/src/tls/BearSSLClient.cpp index a5192dd55..390be4cbd 100644 --- a/src/tls/BearSSLClient.cpp +++ b/src/tls/BearSSLClient.cpp @@ -321,11 +321,6 @@ int BearSSLClient::connectSSL(const char* host) // #define DEBUGSERIAL Serial -/* Define the prototype so that it can be found by the compiler, - * the correct function is then assigned at link time. - */ -extern "C" void br_ssl_engine_fail(br_ssl_engine_context *rc, int err); - int BearSSLClient::clientRead(void *ctx, unsigned char *buf, size_t len) { if (BearSSLClient::_sslio_closing) { From 288489d8d1252f570fd179727e4853da35dc61bb Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 9 Mar 2021 08:17:48 +0100 Subject: [PATCH 066/780] Adding watchdog for SAMD architecture which is continually fed within ArduinoIoTCloud::update() to reset the board in case some function becomes stuck. --- src/ArduinoIoTCloudTCP.cpp | 27 +++++++++++++++++++++++++++ src/utility/watchdog/Watchdog.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/utility/watchdog/Watchdog.h diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 4d6d294e4..7b0ead11b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -43,6 +43,8 @@ #include "cbor/CBOREncoder.h" +#include "utility/watchdog/Watchdog.h" + /****************************************************************************** * EXTERN ******************************************************************************/ @@ -262,11 +264,36 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) } #endif /* OTA_STORAGE_SNU */ +#ifdef ARDUINO_ARCH_SAMD + /* Since we do not control what code the user inserts + * between ArduinoIoTCloudTCP::begin() and the first + * call to ArduinoIoTCloudTCP::update() it is wise to + * set a rather large timeout at first. + */ + Watchdog.enable(120 * 1000); +#endif /* ARDUINO_ARCH_SAMD */ + return 1; } void ArduinoIoTCloudTCP::update() { +#ifdef ARDUINO_ARCH_SAMD + /* Now that we are within the regularly called function + * ArduinoIoTCloudTCP::update() it's a wise idea to reduce + * the watchdog timeout to a smaller amount of time. + */ + static bool is_watchdog_set = false; + if (!is_watchdog_set) { + Watchdog.enable(30 * 1000); + is_watchdog_set = true; + } + /* Feed the watchdog. If any of the functions called below + * get stuck than we can at least reset and recover. + */ + Watchdog.reset(); +#endif /* ARDUINO_ARCH_SAMD */ + /* Run through the state machine. */ State next_state = _state; switch (_state) diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h new file mode 100644 index 000000000..b7a1c39aa --- /dev/null +++ b/src/utility/watchdog/Watchdog.h @@ -0,0 +1,29 @@ +/* + 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_AIOTC_UTILITY_WATCHDOG_H_ +#define ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#ifdef ARDUINO_ARCH_SAMD +# include +#endif /* ARDUINO_ARCH_SAMD */ + +#endif /* ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ */ From 50183c2ed40c26c5971d9c5ca7d221687bf03f0a Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 9 Mar 2021 08:20:53 +0100 Subject: [PATCH 067/780] Adding dependency 'Adafruit_SleepyDog' to CI build. --- .github/workflows/compile-examples.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 559a184ac..7e1595839 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -63,6 +63,7 @@ jobs: - name: ArduinoECCX08 - name: RTCZero - name: WiFi101 + - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | - examples/utility/Provisioning # MKR WiFi 1010, Nano 33 IoT @@ -77,6 +78,7 @@ jobs: - name: WiFiNINA - name: Arduino_JSON - name: ArduinoBearSSL + - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | - examples/utility/Provisioning - examples/utility/SelfProvisioning @@ -113,6 +115,7 @@ jobs: - name: ArduinoECCX08 - name: RTCZero - name: MKRGSM + - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | - examples/utility/Provisioning # NB boards @@ -124,6 +127,7 @@ jobs: - name: ArduinoECCX08 - name: RTCZero - name: MKRNB + - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | - examples/utility/Provisioning # Portenta From c6f03363d1af418790239eecf8fa2467f6698297 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 10 Mar 2021 11:01:21 +0100 Subject: [PATCH 068/780] Since the watchdog timeout can't be larger than 16 seconds adjust the code accordingly. Also add watchdog resets within the OTA callback to prevent the watchdog from biting during OTA. --- src/ArduinoIoTCloudTCP.cpp | 19 +++++++++---------- src/utility/watchdog/Watchdog.h | 1 + 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 7b0ead11b..d3a5db3fd 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -270,7 +270,7 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) * call to ArduinoIoTCloudTCP::update() it is wise to * set a rather large timeout at first. */ - Watchdog.enable(120 * 1000); + Watchdog.enable(SAMD_WATCHDOG_MAX_TIME_ms); #endif /* ARDUINO_ARCH_SAMD */ return 1; @@ -279,15 +279,6 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) void ArduinoIoTCloudTCP::update() { #ifdef ARDUINO_ARCH_SAMD - /* Now that we are within the regularly called function - * ArduinoIoTCloudTCP::update() it's a wise idea to reduce - * the watchdog timeout to a smaller amount of time. - */ - static bool is_watchdog_set = false; - if (!is_watchdog_set) { - Watchdog.enable(30 * 1000); - is_watchdog_set = true; - } /* Feed the watchdog. If any of the functions called below * get stuck than we can at least reset and recover. */ @@ -549,6 +540,10 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l #if OTA_ENABLED void ArduinoIoTCloudTCP::onOTARequest() { +#ifdef ARDUINO_ARCH_SAMD + Watchdog.reset(); +#endif /* ARDUINO_ARCH_SAMD */ + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str()); #if OTA_STORAGE_SNU @@ -556,6 +551,10 @@ void ArduinoIoTCloudTCP::onOTARequest() WiFiStorage.remove("/fs/UPDATE.BIN.LZSS"); WiFiStorage.remove("/fs/UPDATE.BIN.LZSS.TMP"); +#ifdef ARDUINO_ARCH_SAMD + Watchdog.reset(); +#endif /* ARDUINO_ARCH_SAMD */ + /* Trigger direct download to nina module. */ uint8_t nina_ota_err_code = 0; if (!WiFiStorage.downloadOTA(_ota_url.c_str(), &nina_ota_err_code)) diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index b7a1c39aa..9f81e372a 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -24,6 +24,7 @@ #ifdef ARDUINO_ARCH_SAMD # include +# define SAMD_WATCHDOG_MAX_TIME_ms (16 * 1000) #endif /* ARDUINO_ARCH_SAMD */ #endif /* ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ */ From 34a8d30ee0d28335226fece187457e367c39972e Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 17 Mar 2021 08:13:14 +0100 Subject: [PATCH 069/780] Adding preeliminary support for RP2040 Connect. (#236) --- src/AIoTC_Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 05e24f03a..76522c7bb 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -115,7 +115,7 @@ #if defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKR1000) || \ defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_PORTENTA_H7_M7) || \ - defined(ARDUINO_PORTENTA_H7_M4) + defined(ARDUINO_PORTENTA_H7_M4) || defined (ARDUINO_NANO_RP2040_CONNECT) #define BOARD_HAS_ECCX08 #define HAS_TCP #endif From d8a99651d30bca75f3fb4176608d16dd20d14191 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 3 Mar 2021 15:27:39 +0100 Subject: [PATCH 070/780] This change enabled BearSSL offload for Arduino MKR WiFi 1010 and Nano 33 IoT. --- src/AIoTC_Config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 76522c7bb..969cbe18a 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -113,14 +113,14 @@ #endif #if defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKR1000) || \ - defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_PORTENTA_H7_M7) || \ defined(ARDUINO_PORTENTA_H7_M4) || defined (ARDUINO_NANO_RP2040_CONNECT) #define BOARD_HAS_ECCX08 #define HAS_TCP #endif -#if defined(ARDUINO_AVR_UNO_WIFI_REV2) +#if defined(ARDUINO_AVR_UNO_WIFI_REV2) || \ + defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) #define BOARD_HAS_OFFLOADED_ECCX08 #define HAS_TCP #endif From fd0bb72153e34db41aa6779753c094593b7f7e11 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 15 Mar 2021 14:02:02 +0100 Subject: [PATCH 071/780] Bugfix: Don't call ECCX08::end() as it disable the I2C module. This has the unpleasant side-effect that any future access to the I2C bus is trying to access an uninitialized I2C module and gets stuck in a loop. --- src/ArduinoIoTCloudTCP.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index d3a5db3fd..4a5fcaf31 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -189,7 +189,6 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) DEBUG_ERROR("CryptoUtil::readDeviceId(...) failed."); return 0; } - ECCX08.end(); #endif #ifdef BOARD_HAS_ECCX08 From d766bb3cc1f21d7c52703b2977f5e4fcf9f647c0 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 17 Mar 2021 08:30:17 +0100 Subject: [PATCH 072/780] Provide strong implementation in order to override 'wifi_nina_feed_watchdog' defined weak within WiFiNINA. --- src/utility/watchdog/Watchdog.cpp | 39 +++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/utility/watchdog/Watchdog.cpp diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp new file mode 100644 index 000000000..f6606960c --- /dev/null +++ b/src/utility/watchdog/Watchdog.cpp @@ -0,0 +1,39 @@ +/* + 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 "Watchdog.h" + +/****************************************************************************** + * FUNCTION DEFINITION + ******************************************************************************/ + +#ifdef ARDUINO_ARCH_SAMD +/* This function is called within the WiFiNINA library when invoking + * the method 'connectBearSSL' in order to prevent a premature bite + * of the watchdog (max timeout on SAMD is 16 s). wifi_nina_feed... + * is defined a weak function there and overwritten by this "strong" + * function here. + */ +void wifi_nina_feed_watchdog() +{ + Watchdog.reset(); +} +#endif /* ARDUINO_ARCH_SAMD */ From ba61452fa2ce84110bea3648c87919ec9a96c667 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 24 Mar 2021 09:34:16 +0100 Subject: [PATCH 073/780] Allow central enabling/disabling of watchdog for SAMD within AIoTConfig.h --- src/AIoTC_Config.h | 6 ++++++ src/utility/watchdog/Watchdog.cpp | 6 ++++-- src/utility/watchdog/Watchdog.h | 12 ++++++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 969cbe18a..e9511bce1 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -87,6 +87,12 @@ * AUTOMATICALLY CONFIGURED DEFINES ******************************************************************************/ +#ifdef ARDUINO_ARCH_SAMD +# define WATCHDOG_ENABLED (1) +#else +# define WATCHDOG_ENABLED (0) +#endif + #if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ defined(ARDUINO_AVR_UNO_WIFI_REV2) #define OTA_STORAGE_SNU (1) diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index f6606960c..8c06cb7a5 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -25,7 +25,8 @@ * FUNCTION DEFINITION ******************************************************************************/ -#ifdef ARDUINO_ARCH_SAMD +#if WATCHDOG_ENABLED +# ifdef ARDUINO_ARCH_SAMD /* This function is called within the WiFiNINA library when invoking * the method 'connectBearSSL' in order to prevent a premature bite * of the watchdog (max timeout on SAMD is 16 s). wifi_nina_feed... @@ -36,4 +37,5 @@ void wifi_nina_feed_watchdog() { Watchdog.reset(); } -#endif /* ARDUINO_ARCH_SAMD */ +# endif /* ARDUINO_ARCH_SAMD */ +#endif /* WATCHDOG_ENABLED */ diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index 9f81e372a..d89003fda 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -22,9 +22,13 @@ * INCLUDE ******************************************************************************/ -#ifdef ARDUINO_ARCH_SAMD -# include -# define SAMD_WATCHDOG_MAX_TIME_ms (16 * 1000) -#endif /* ARDUINO_ARCH_SAMD */ +#include + +#if WATCHDOG_ENABLED +# ifdef ARDUINO_ARCH_SAMD +# include +# define SAMD_WATCHDOG_MAX_TIME_ms (16 * 1000) +# endif /* ARDUINO_ARCH_SAMD */ +#endif /* WATCHDOG_ENABLED */ #endif /* ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ */ From 11ac4365bb9d02a8d95d333794300fde121bbdf9 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 24 Mar 2021 10:27:47 +0100 Subject: [PATCH 074/780] Provide error message when NINA firmware is < 1.4.3 if the user wants to take advantage of SSL offloading. --- src/ArduinoIoTCloudTCP.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 4a5fcaf31..f3e9fe3ff 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -253,16 +253,22 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) #endif #if OTA_STORAGE_SNU && OTA_ENABLED - String const nina_fw_version = WiFi.firmwareVersion(); - if (nina_fw_version < "1.4.1") { + 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__, nina_fw_version.c_str()); + 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 */ +#ifdef BOARD_HAS_OFFLOADED_ECCX08 + if (String(WiFi.firmwareVersion()) < String("1.4.3")) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, NINA firmware needs to be >= 1.4.3, current %s", __FUNCTION__, WiFi.firmwareVersion()); + return 0; + } +#endif /* BOARD_HAS_OFFLOADED_ECCX08 */ + #ifdef ARDUINO_ARCH_SAMD /* Since we do not control what code the user inserts * between ArduinoIoTCloudTCP::begin() and the first From 2ce057809b95e8988a00a392a94ac48648b29087 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 7 Apr 2021 14:27:48 +0200 Subject: [PATCH 075/780] Adding missing dependency of Adafruit_SleepyDog for Arduino MKR WAN 1310. --- .github/workflows/compile-examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 7e1595839..3ed3c6703 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -105,6 +105,7 @@ jobs: - name: ArduinoECCX08 - name: RTCZero - name: MKRWAN + - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: # GSM boards - board: From fd2eff8003d7444a0756813f44bf0eadd0462ab0 Mon Sep 17 00:00:00 2001 From: per1234 Date: Wed, 7 Apr 2021 12:47:10 -0700 Subject: [PATCH 076/780] Use consistent formatting style in CI workflows The previous inconsistent markup style, although perfectly valid, made the workflow harder to understand. --- .github/workflows/compile-examples.yml | 56 +++++++++++++++----------- .github/workflows/spell-check.yml | 4 +- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 7e1595839..31b7d5961 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -37,25 +37,35 @@ jobs: fail-fast: false matrix: - board: [ - {"fqbn": "arduino:samd:mkr1000", "type": "mkr1000"}, - {"fqbn": "arduino:samd:mkrwifi1010", "type": "nina"}, - {"fqbn": "arduino:samd:nano_33_iot", "type": "nina"}, - {"fqbn": "arduino:megaavr:uno2018", "type": "megaavr"}, - {"fqbn": "arduino:samd:mkrwan1300", "type": "wan"}, - {"fqbn": "arduino:samd:mkrgsm1400", "type": "gsm"}, - {"fqbn": "arduino:samd:mkrnb1500", "type": "nb"}, - {"fqbn": "arduino:mbed:envie_m4", "type": "mbed"}, - {"fqbn": "arduino:mbed:envie_m7", "type": "mbed"}, - {"fqbn": "esp8266:esp8266:huzzah", "type": "esp8266"}, - {"fqbn": "esp32:esp32:esp32", "type": "esp32"} - ] + board: + - fqbn: arduino:samd:mkr1000 + type: mkr1000 + - fqbn: arduino:samd:mkrwifi1010 + type: nina + - fqbn: arduino:samd:nano_33_iot + type: nina + - fqbn: arduino:megaavr:uno2018 + type: megaavr + - fqbn: arduino:samd:mkrwan1300 + type: wan + - fqbn: arduino:samd:mkrgsm1400 + type: gsm + - fqbn: arduino:samd:mkrnb1500 + type: nb + - fqbn: arduino:mbed:envie_m4 + type: mbed + - fqbn: arduino:mbed:envie_m7 + type: mbed + - fqbn: esp8266:esp8266:huzzah + type: esp8266 + - fqbn: esp32:esp32:esp32 + type: esp32 # make board type-specific customizations to the matrix jobs include: # MKR 1000 - board: - type: "mkr1000" + type: mkr1000 platforms: | # Install Arduino SAMD Boards via Boards Manager for the toolchain - name: arduino:samd @@ -68,7 +78,7 @@ jobs: - examples/utility/Provisioning # MKR WiFi 1010, Nano 33 IoT - board: - type: "nina" + type: nina platforms: | # Install Arduino SAMD Boards via Boards Manager for the toolchain - name: arduino:samd @@ -84,7 +94,7 @@ jobs: - examples/utility/SelfProvisioning # Uno WiFi Rev2 - board: - type: "megaavr" + type: megaavr platforms: | - name: arduino:megaavr libraries: | @@ -98,7 +108,7 @@ jobs: - examples/utility/SelfProvisioning # LoRaWAN boards - board: - type: "wan" + type: wan platforms: | - name: arduino:samd libraries: | @@ -108,7 +118,7 @@ jobs: sketch-paths: # GSM boards - board: - type: "gsm" + type: gsm platforms: | - name: arduino:samd libraries: | @@ -120,7 +130,7 @@ jobs: - examples/utility/Provisioning # NB boards - board: - type: "nb" + type: nb platforms: | - name: arduino:samd libraries: | @@ -132,7 +142,7 @@ jobs: - examples/utility/Provisioning # Portenta - board: - type: "mbed" + type: mbed platforms: | # Install Arduino mbed-Enabled Boards via Boards Manager for the toolchain - name: arduino:mbed @@ -146,7 +156,7 @@ jobs: - examples/utility/Provisioning # ESP8266 boards - board: - type: "esp8266" + type: esp8266 platforms: | # Install ESP8266 platform via Boards Manager - name: esp8266:esp8266 @@ -156,7 +166,7 @@ jobs: sketch-paths: # ESP32 boards - board: - type: "esp32" + type: esp32 platforms: | # Install ESP32 platform via Boards Manager - name: esp32:esp32 @@ -209,7 +219,7 @@ jobs: sketch-paths: | ${{ env.UNIVERSAL_SKETCH_PATHS }} ${{ matrix.sketch-paths }} - enable-deltas-report: 'true' + enable-deltas-report: "true" sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} - name: Write data to size trends report spreadsheet diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml index f77b7f9cc..d6937c5be 100644 --- a/.github/workflows/spell-check.yml +++ b/.github/workflows/spell-check.yml @@ -1,6 +1,8 @@ name: Spell Check -on: [push, pull_request] +on: + - push + - pull_request jobs: build: From c1f0077ad53b2af4ee6b429c26d4ca50e995f6bf Mon Sep 17 00:00:00 2001 From: per1234 Date: Wed, 7 Apr 2021 12:54:08 -0700 Subject: [PATCH 077/780] Remove irrelevant comment from CI workflow This comment was a leftover from a previous time when the `namespace` branch of ArduinoCore-API was specified for use with the arduino:mbed boards platform. --- .github/workflows/compile-examples.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 31b7d5961..5c41f07de 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -194,7 +194,6 @@ jobs: uses: actions/checkout@v2 with: repository: arduino/ArduinoCore-API - # as specified at https://github.com/arduino/ArduinoCore-mbed/blob/master/README.md#installation path: ${{ env.ARDUINOCORE_API_STAGING_PATH }} - name: Install ArduinoCore-API From 502162c07fd691972d70c11c507d5b8fbe28c72a Mon Sep 17 00:00:00 2001 From: per1234 Date: Wed, 7 Apr 2021 12:57:45 -0700 Subject: [PATCH 078/780] Update action versions used in sketch compilation workflows Previously, due to the lack of a release, the development versions of the sketch compilation actions were used. Using release versions provides a more stable CI system for the ArduinoIoTCloud project. --- .github/workflows/compile-examples.yml | 6 +++--- .github/workflows/report-size-deltas.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 5c41f07de..2e31b0468 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -185,7 +185,7 @@ jobs: uses: actions/checkout@v2 with: repository: arduino/ArduinoCore-mbed - # the arduino/actions/libraries/compile-examples action will install the platform from this path + # the arduino/compile-sketches action will install the platform from this path path: ${{ env.ARDUINOCORE_MBED_STAGING_PATH }} - name: Checkout ArduinoCore-API @@ -207,7 +207,7 @@ jobs: run: pip3 install pyserial - name: Compile examples - uses: arduino/compile-sketches@main + uses: arduino/compile-sketches@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} platforms: ${{ matrix.platforms }} @@ -232,7 +232,7 @@ jobs: - name: Save memory usage change report as artifact if: github.event_name == 'pull_request' - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v2 with: name: ${{ env.SKETCHES_REPORTS_PATH }} path: ${{ env.SKETCHES_REPORTS_PATH }} diff --git a/.github/workflows/report-size-deltas.yml b/.github/workflows/report-size-deltas.yml index 12c162fa4..9b0f2cdb5 100644 --- a/.github/workflows/report-size-deltas.yml +++ b/.github/workflows/report-size-deltas.yml @@ -8,7 +8,7 @@ jobs: steps: - name: Comment size deltas reports to PRs - uses: arduino/report-size-deltas@main + uses: arduino/report-size-deltas@v1 with: # The name of the workflow artifact created by the "Compile Examples" workflow sketches-reports-source: sketches-reports From d92324ea625acfc6c96a386b7ba60daadbd9d4e1 Mon Sep 17 00:00:00 2001 From: per1234 Date: Wed, 7 Apr 2021 13:03:49 -0700 Subject: [PATCH 079/780] Use official GitHub Actions action for spell checking The `arduino/actions/libraries/spell-check` GitHub Actions action is now deprecated in favor of the official action from codespell. The 2.0.0 release of codespell added support for a .codespellrc configuration file. Use of this file to configure codespell allows the spell check to be run locally with the identical configuration to that used by the CI system. --- .codespellrc | 7 +++++++ .github/workflows/spell-check.yml | 5 +---- extras/codespell-ignore-words-list.txt | 2 -- 3 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 .codespellrc delete mode 100644 extras/codespell-ignore-words-list.txt diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 000000000..b6200a41d --- /dev/null +++ b/.codespellrc @@ -0,0 +1,7 @@ +# See: https://github.com/codespell-project/codespell#using-a-config-file +[codespell] +# In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here: +ignore-words-list = alocation,wan +check-filenames = +check-hidden = +skip = ./.git,./extras/test/external,./src/cbor/lib/tinycbor diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml index d6937c5be..b96e8e9d8 100644 --- a/.github/workflows/spell-check.yml +++ b/.github/workflows/spell-check.yml @@ -13,7 +13,4 @@ jobs: uses: actions/checkout@v2 - name: Spell check - uses: arduino/actions/libraries/spell-check@master - with: - ignore-words-list: extras/codespell-ignore-words-list.txt - skip-paths: ./extras/test/external,./src/cbor/lib/tinycbor + uses: codespell-project/actions-codespell@master diff --git a/extras/codespell-ignore-words-list.txt b/extras/codespell-ignore-words-list.txt deleted file mode 100644 index 513a50e47..000000000 --- a/extras/codespell-ignore-words-list.txt +++ /dev/null @@ -1,2 +0,0 @@ -wan -alocation From 66b2e478f828cff8c2ed08a3952312e04365d1e6 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 8 Apr 2021 13:18:21 +0200 Subject: [PATCH 080/780] Replace compile-time configuration of watchdog (compiled in/out) with parameter in 'begin' function. The watchdog is now always compiled in, but can be disabled when setting the parameter 'enable_watchdog' too false. The parameter is set to true by default. --- src/AIoTC_Config.h | 6 ------ src/ArduinoIoTCloudTCP.cpp | 16 +++++++++------- src/ArduinoIoTCloudTCP.h | 6 +++--- src/utility/watchdog/Watchdog.cpp | 27 ++++++++++++++++++++++----- src/utility/watchdog/Watchdog.h | 23 +++++++++++++++++------ 5 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index e9511bce1..969cbe18a 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -87,12 +87,6 @@ * AUTOMATICALLY CONFIGURED DEFINES ******************************************************************************/ -#ifdef ARDUINO_ARCH_SAMD -# define WATCHDOG_ENABLED (1) -#else -# define WATCHDOG_ENABLED (0) -#endif - #if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ defined(ARDUINO_AVR_UNO_WIFI_REV2) #define OTA_STORAGE_SNU (1) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index f3e9fe3ff..1ec314ec4 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -104,16 +104,16 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() * PUBLIC MEMBER FUNCTIONS ******************************************************************************/ -int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, String brokerAddress, uint16_t brokerPort) +int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_watchdog, String brokerAddress, uint16_t brokerPort) { _connection = &connection; _brokerAddress = brokerAddress; _brokerPort = brokerPort; _time_service.begin(&connection); - return begin(_brokerAddress, _brokerPort); + return begin(enable_watchdog, _brokerAddress, _brokerPort); } -int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) +int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, uint16_t brokerPort) { _brokerAddress = brokerAddress; _brokerPort = brokerPort; @@ -275,7 +275,9 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) * call to ArduinoIoTCloudTCP::update() it is wise to * set a rather large timeout at first. */ - Watchdog.enable(SAMD_WATCHDOG_MAX_TIME_ms); + if (enable_watchdog) { + samd_watchdog_enable(); + } #endif /* ARDUINO_ARCH_SAMD */ return 1; @@ -287,7 +289,7 @@ void ArduinoIoTCloudTCP::update() /* Feed the watchdog. If any of the functions called below * get stuck than we can at least reset and recover. */ - Watchdog.reset(); + samd_watchdog_reset(); #endif /* ARDUINO_ARCH_SAMD */ /* Run through the state machine. */ @@ -546,7 +548,7 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l void ArduinoIoTCloudTCP::onOTARequest() { #ifdef ARDUINO_ARCH_SAMD - Watchdog.reset(); + samd_watchdog_reset(); #endif /* ARDUINO_ARCH_SAMD */ DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str()); @@ -557,7 +559,7 @@ void ArduinoIoTCloudTCP::onOTARequest() WiFiStorage.remove("/fs/UPDATE.BIN.LZSS.TMP"); #ifdef ARDUINO_ARCH_SAMD - Watchdog.reset(); + samd_watchdog_reset(); #endif /* ARDUINO_ARCH_SAMD */ /* Trigger direct download to nina module. */ diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index c26e08ec3..bdf61e105 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -66,11 +66,11 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass virtual void printDebugInfo() override; #if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) - int begin(ConnectionHandler & connection, String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH); + int begin(ConnectionHandler & connection, bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH); #else - int begin(ConnectionHandler & connection, String brokerAddress = DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_USER_PASS_AUTH); + int begin(ConnectionHandler & connection, bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_USER_PASS_AUTH); #endif - int begin(String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH); + int begin(bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH); #ifdef BOARD_ESP inline void setBoardId (String const device_id) { setDeviceId(device_id); } diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 8c06cb7a5..9cabf4d15 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -21,12 +21,30 @@ #include "Watchdog.h" +/****************************************************************************** + * GLOBAL VARIABLES + ******************************************************************************/ + +static bool is_watchdog_enabled = false; + /****************************************************************************** * FUNCTION DEFINITION ******************************************************************************/ -#if WATCHDOG_ENABLED -# ifdef ARDUINO_ARCH_SAMD +#ifdef ARDUINO_ARCH_SAMD +void samd_watchdog_enable() +{ + is_watchdog_enabled = true; + Watchdog.enable(SAMD_WATCHDOG_MAX_TIME_ms); +} + +void samd_watchdog_reset() +{ + if (is_watchdog_enabled) { + Watchdog.reset(); + } +} + /* This function is called within the WiFiNINA library when invoking * the method 'connectBearSSL' in order to prevent a premature bite * of the watchdog (max timeout on SAMD is 16 s). wifi_nina_feed... @@ -35,7 +53,6 @@ */ void wifi_nina_feed_watchdog() { - Watchdog.reset(); + samd_watchdog_reset(); } -# endif /* ARDUINO_ARCH_SAMD */ -#endif /* WATCHDOG_ENABLED */ +#endif /* ARDUINO_ARCH_SAMD */ diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index d89003fda..6cdcf307a 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -24,11 +24,22 @@ #include -#if WATCHDOG_ENABLED -# ifdef ARDUINO_ARCH_SAMD -# include -# define SAMD_WATCHDOG_MAX_TIME_ms (16 * 1000) -# endif /* ARDUINO_ARCH_SAMD */ -#endif /* WATCHDOG_ENABLED */ +/****************************************************************************** + * PREPROCESSOR SECTION + ******************************************************************************/ + +#ifdef ARDUINO_ARCH_SAMD +# include +# define SAMD_WATCHDOG_MAX_TIME_ms (16 * 1000) +#endif /* ARDUINO_ARCH_SAMD */ + +/****************************************************************************** + * FUNCTION DECLARATION + ******************************************************************************/ + +#ifdef ARDUINO_ARCH_SAMD +void samd_watchdog_enable(); +void samd_watchdog_reset(); +#endif /* ARDUINO_ARCH_SAMD */ #endif /* ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ */ From e936ed1c327ca43d8065f4c85d7673422af213ed Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 19 Apr 2021 11:09:52 +0200 Subject: [PATCH 081/780] Add watchdog support for Portenta H7 on Arduino IoT Cloud. --- src/ArduinoIoTCloudTCP.cpp | 15 +++++++++---- src/utility/watchdog/Watchdog.cpp | 37 +++++++++++++++++++++++++++++++ src/utility/watchdog/Watchdog.h | 11 +++++---- 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 1ec314ec4..c68af8df0 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -269,28 +269,35 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, } #endif /* BOARD_HAS_OFFLOADED_ECCX08 */ -#ifdef ARDUINO_ARCH_SAMD /* Since we do not control what code the user inserts * between ArduinoIoTCloudTCP::begin() and the first * call to ArduinoIoTCloudTCP::update() it is wise to * set a rather large timeout at first. */ +#ifdef ARDUINO_ARCH_SAMD if (enable_watchdog) { samd_watchdog_enable(); } -#endif /* ARDUINO_ARCH_SAMD */ +#elif defined(ARDUINO_ARCH_MBED) + if (enable_watchdog) { + mbed_watchdog_enable(); + } +#endif return 1; } void ArduinoIoTCloudTCP::update() { -#ifdef ARDUINO_ARCH_SAMD /* Feed the watchdog. If any of the functions called below * get stuck than we can at least reset and recover. */ +#ifdef ARDUINO_ARCH_SAMD samd_watchdog_reset(); -#endif /* ARDUINO_ARCH_SAMD */ +#elif defined(ARDUINO_ARCH_MBED) + mbed_watchdog_reset(); +#endif + /* Run through the state machine. */ State next_state = _state; diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 9cabf4d15..0a70aabe1 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -21,6 +21,17 @@ #include "Watchdog.h" +#include + +#if defined(DEBUG_ERROR) || defined(DEBUG_WARNING) || defined(DEBUG_INFO) || defined(DEBUG_DEBUG) || defined(DEBUG_VERBOSE) +# include +#endif + +#ifdef ARDUINO_ARCH_MBED +# include +# define PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms (32760) +#endif /* ARDUINO_ARCH_MBED */ + /****************************************************************************** * GLOBAL VARIABLES ******************************************************************************/ @@ -56,3 +67,29 @@ void wifi_nina_feed_watchdog() samd_watchdog_reset(); } #endif /* ARDUINO_ARCH_SAMD */ + +#ifdef ARDUINO_ARCH_MBED +void mbed_watchdog_enable() +{ + watchdog_config_t cfg; +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M) + cfg.timeout_ms = PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms; +#else +# error "You need to define the maximum possible timeout for this architecture." +#endif + + if (hal_watchdog_init(&cfg) == WATCHDOG_STATUS_OK) { + is_watchdog_enabled = true; + } + else { + DEBUG_WARNING("%s: watchdog could not be enabled", __FUNCTION__); + } +} + +void mbed_watchdog_reset() +{ + if (is_watchdog_enabled) { + hal_watchdog_kick(); + } +} +#endif /* ARDUINO_ARCH_MBED */ diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index 6cdcf307a..bbb1b529b 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -18,12 +18,6 @@ #ifndef ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ #define ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include - /****************************************************************************** * PREPROCESSOR SECTION ******************************************************************************/ @@ -42,4 +36,9 @@ void samd_watchdog_enable(); void samd_watchdog_reset(); #endif /* ARDUINO_ARCH_SAMD */ +#ifdef ARDUINO_ARCH_MBED +void mbed_watchdog_enable(); +void mbed_watchdog_reset(); +#endif /* ARDUINO_ARCH_MBED */ + #endif /* ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ */ From f6f6863fedd7309860a2dc00dbbfaab742699f75 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 19 Apr 2021 11:10:48 +0200 Subject: [PATCH 082/780] Move inclusion of SAMD watchdog library to Watchdog.cpp file, there's no need for it to be publicly available. --- src/utility/watchdog/Watchdog.cpp | 5 +++++ src/utility/watchdog/Watchdog.h | 9 --------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 0a70aabe1..49321522b 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -27,6 +27,11 @@ # include #endif +#ifdef ARDUINO_ARCH_SAMD +# include +# define SAMD_WATCHDOG_MAX_TIME_ms (16 * 1000) +#endif /* ARDUINO_ARCH_SAMD */ + #ifdef ARDUINO_ARCH_MBED # include # define PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms (32760) diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index bbb1b529b..91161d072 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -18,15 +18,6 @@ #ifndef ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ #define ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ -/****************************************************************************** - * PREPROCESSOR SECTION - ******************************************************************************/ - -#ifdef ARDUINO_ARCH_SAMD -# include -# define SAMD_WATCHDOG_MAX_TIME_ms (16 * 1000) -#endif /* ARDUINO_ARCH_SAMD */ - /****************************************************************************** * FUNCTION DECLARATION ******************************************************************************/ From 8f2960de36672e67dc0f477298e92044cd7b18dd Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 19 Apr 2021 11:27:40 +0200 Subject: [PATCH 083/780] Add support for watchdog on Nano RP2040 Connect. --- src/utility/watchdog/Watchdog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 49321522b..ee5dcb7c9 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -35,6 +35,7 @@ #ifdef ARDUINO_ARCH_MBED # include # define PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms (32760) +# define NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms (32760) #endif /* ARDUINO_ARCH_MBED */ /****************************************************************************** @@ -79,6 +80,8 @@ void mbed_watchdog_enable() watchdog_config_t cfg; #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M) cfg.timeout_ms = PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms; +#elif defined(ARDUINO_NANO_RP2040_CONNECT) + cfg.timeout_ms = NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms; #else # error "You need to define the maximum possible timeout for this architecture." #endif From 02e0f30d96eef57148cc85bd8a1f7b632ccd47cb Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 19 Apr 2021 12:05:08 +0200 Subject: [PATCH 084/780] Fix typo: ARDUINO_PORTENTA_H7_M -> ARDUINO_PORTENTA_H7_M4. --- src/utility/watchdog/Watchdog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index ee5dcb7c9..e760fd8a7 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -78,7 +78,7 @@ void wifi_nina_feed_watchdog() void mbed_watchdog_enable() { watchdog_config_t cfg; -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) cfg.timeout_ms = PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms; #elif defined(ARDUINO_NANO_RP2040_CONNECT) cfg.timeout_ms = NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms; From 7347d06182745bd49b376474bed282db6c66963b Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 19 Apr 2021 12:22:50 +0200 Subject: [PATCH 085/780] Compile for Nano RP2040 Connect during CI build. --- .github/workflows/compile-examples.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index cefa6d900..fd76e9bdb 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -60,6 +60,8 @@ jobs: type: esp8266 - fqbn: esp32:esp32:esp32 type: esp32 + - fqbn: arduino:mbed_nano:nanorp2040connect + type: nina # make board type-specific customizations to the matrix jobs include: @@ -76,12 +78,13 @@ jobs: - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | - examples/utility/Provisioning - # MKR WiFi 1010, Nano 33 IoT + # MKR WiFi 1010, Nano 33 IoT, Nano RP2040 Connect - board: type: nina platforms: | # Install Arduino SAMD Boards via Boards Manager for the toolchain - name: arduino:samd + - name: arduino:mbed_nano libraries: | - name: ArduinoECCX08 - name: RTCZero From 27dda8951420eb679cd6ba1ba5969823e1e5b0ff Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 20 Apr 2021 10:39:08 +0200 Subject: [PATCH 086/780] Add mbed_nano and mbed_portenta as supported architectures. (#241) --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index a3d606b2c..e3f2d3518 100644 --- a/library.properties +++ b/library.properties @@ -6,6 +6,6 @@ sentence=This library allows to connect to the Arduino IoT Cloud service. paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKRGSM, MKR1000 and WiFi101. category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud -architectures=mbed,samd,esp8266,megaavr +architectures=mbed,samd,esp8266,megaavr,mbed_nano,mbed_portenta includes=ArduinoIoTCloud.h depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero From 4ecf3b1d261465ea4579d4cae4b8409b47fcfde5 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 21 Apr 2021 09:17:33 +0200 Subject: [PATCH 087/780] Feed Portenta H7 watchdog during OTA. The individual function calls during the OTA binary download process can take quite a lot of time. As the OTA callback is called from within the update() method the watchdog is not reset in its regular manner. As a consequence the watchdog needs to be fed/kicked/reset during the various OTA download steps in order to avoid a premature reset caused by watchdog-timeout. --- src/ArduinoIoTCloudTCP.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index c68af8df0..6567b0553 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -583,24 +583,34 @@ void ArduinoIoTCloudTCP::onOTARequest() #endif /* OTA_STORAGE_SNU */ #if OTA_STORAGE_PORTENTA_QSPI + mbed_watchdog_reset(); + Arduino_Portenta_OTA::Error ota_portenta_err = Arduino_Portenta_OTA::Error::None; /* Use 2nd partition of QSPI (1st partition contains WiFi firmware) */ Arduino_Portenta_OTA_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2); + mbed_watchdog_reset(); + /* Initialize the QSPI memory for OTA handling. */ if((ota_portenta_err = ota_portenta_qspi.begin()) != Arduino_Portenta_OTA::Error::None) { DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::begin() failed with %d", static_cast(ota_portenta_err)); return; } + mbed_watchdog_reset(); + /* Just to be safe delete any remains from previous updates. */ remove("/fs/UPDATE.BIN"); remove("/fs/UPDATE.BIN.LZSS"); + mbed_watchdog_reset(); + /* Download the OTA file from the web storage location. */ int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download((char*)(_ota_url.c_str()), true /* is_https */); DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::download(%s) returns %d", _ota_url.c_str(), ota_portenta_qspi_download_ret_code); + mbed_watchdog_reset(); + /* Decompress the LZSS compressed OTA file. */ int const ota_portenta_qspi_decompress_ret_code = ota_portenta_qspi.decompress(); DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::decompress() returns %d", ota_portenta_qspi_decompress_ret_code); @@ -610,6 +620,8 @@ void ArduinoIoTCloudTCP::onOTARequest() return; } + mbed_watchdog_reset(); + /* Schedule the firmware update. */ if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) { DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::update() failed with %d", static_cast(ota_portenta_err)); From 2aca407622a4f9b6e635205baef963b70a261b6a Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 28 Apr 2021 07:07:56 +0200 Subject: [PATCH 088/780] Since we'll be only using nina-fw:v1.4.4 and forward for SSL offloading the outdated warning concerning v1.4.3 needs to be replaced with 1.4.4. --- src/ArduinoIoTCloudTCP.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 6567b0553..5bcdf386f 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -263,8 +263,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #endif /* OTA_STORAGE_SNU */ #ifdef BOARD_HAS_OFFLOADED_ECCX08 - if (String(WiFi.firmwareVersion()) < String("1.4.3")) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, NINA firmware needs to be >= 1.4.3, current %s", __FUNCTION__, WiFi.firmwareVersion()); + if (String(WiFi.firmwareVersion()) < String("1.4.4")) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, NINA firmware needs to be >= 1.4.4, current %s", __FUNCTION__, WiFi.firmwareVersion()); return 0; } #endif /* BOARD_HAS_OFFLOADED_ECCX08 */ From 5ed525da4b582ff3260324930a57484047eaa6d6 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 27 Apr 2021 09:07:32 +0200 Subject: [PATCH 089/780] Bugfix: _lastSyncRequestTickTime should be of type 'unsigned long' as that's the same type as 'millis()' returns, otherwise an overrun could occur earlier than necessary. --- src/ArduinoIoTCloudTCP.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index bdf61e105..b9f3850c3 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -96,7 +96,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass State _state; - int _lastSyncRequestTickTime; + unsigned long _lastSyncRequestTickTime; String _brokerAddress; uint16_t _brokerPort; uint8_t _mqtt_data_buf[MQTT_TRANSMIT_BUFFER_SIZE]; From fb16d9ac4ca50553ec68b8c0bd8473506c3d8f37 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 27 Apr 2021 14:36:00 +0200 Subject: [PATCH 090/780] Implementation of exponential-back-off on reconnection attempt. --- src/ArduinoIoTCloudTCP.cpp | 19 ++++++++++++++++--- src/ArduinoIoTCloudTCP.h | 2 ++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 5bcdf386f..6231a3cf8 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -74,6 +74,8 @@ extern "C" unsigned long getTime() ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() : _state{State::ConnectPhy} +, _next_connection_attempt_tick{0} +, _last_connection_attempt_cnt{0} , _lastSyncRequestTickTime{0} , _mqtt_data_buf{0} , _mqtt_data_len{0} @@ -337,9 +339,13 @@ void ArduinoIoTCloudTCP::printDebugInfo() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() { if (_connection->check() == NetworkConnectionState::CONNECTED) - return State::SyncTime; - else - return State::ConnectPhy; + { + bool const is_retry_attempt = (_last_connection_attempt_cnt > 0); + if (!is_retry_attempt || (is_retry_attempt && (_next_connection_attempt_tick > millis()))) + return State::SyncTime; + } + + return State::ConnectPhy; } ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() @@ -352,7 +358,14 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() { if (_mqttClient.connect(_brokerAddress.c_str(), _brokerPort)) + { + _last_connection_attempt_cnt = 0; return State::SubscribeMqttTopics; + } + + static unsigned long const RECONNECTION_RETRY_DELAY_ms = 1000; + _last_connection_attempt_cnt = min(_last_connection_attempt_cnt + 1, 5); + _next_connection_attempt_tick = millis() + pow(2, _last_connection_attempt_cnt) * RECONNECTION_RETRY_DELAY_ms; DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); return State::ConnectPhy; diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index b9f3850c3..24ddeb10c 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -96,6 +96,8 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass State _state; + unsigned long _next_connection_attempt_tick; + unsigned int _last_connection_attempt_cnt; unsigned long _lastSyncRequestTickTime; String _brokerAddress; uint16_t _brokerPort; From f218bce9614384cea21576b56cf33cf9a858b5f8 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 27 Apr 2021 14:39:47 +0200 Subject: [PATCH 091/780] Limit max delay instead of the reconnection counter. --- src/ArduinoIoTCloudTCP.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 6231a3cf8..b760cc4c7 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -363,9 +363,11 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() return State::SubscribeMqttTopics; } - static unsigned long const RECONNECTION_RETRY_DELAY_ms = 1000; - _last_connection_attempt_cnt = min(_last_connection_attempt_cnt + 1, 5); - _next_connection_attempt_tick = millis() + pow(2, _last_connection_attempt_cnt) * RECONNECTION_RETRY_DELAY_ms; + static unsigned long const RECONNECTION_RETRY_DELAY_ms = 1000; + static unsigned long const MAX_RECONNECTION_RETRY_DELAY_ms = 32000; + _last_connection_attempt_cnt++; + unsigned long const reconnection_retry_delay = min(MAX_RECONNECTION_RETRY_DELAY_ms, pow(2, _last_connection_attempt_cnt) * RECONNECTION_RETRY_DELAY_ms); + _next_connection_attempt_tick = millis() + reconnection_retry_delay; DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); return State::ConnectPhy; From a5a91e36d6f4f2822b7af147ceb81c46b3ef1053 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 27 Apr 2021 14:44:20 +0200 Subject: [PATCH 092/780] Extract reconnection specific constants and move them to AIOTConfig.h --- src/AIoTC_Config.h | 7 +++++++ src/ArduinoIoTCloudTCP.cpp | 2 -- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 969cbe18a..c9e50f5c4 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -134,4 +134,11 @@ #define HAS_TCP #endif +/****************************************************************************** + * CONSTANTS + ******************************************************************************/ + +#define RECONNECTION_RETRY_DELAY_ms (1000UL) +#define MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) + #endif /* ARDUINO_AIOTC_CONFIG_H_ */ diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index b760cc4c7..64ee89ec0 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -363,8 +363,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() return State::SubscribeMqttTopics; } - static unsigned long const RECONNECTION_RETRY_DELAY_ms = 1000; - static unsigned long const MAX_RECONNECTION_RETRY_DELAY_ms = 32000; _last_connection_attempt_cnt++; unsigned long const reconnection_retry_delay = min(MAX_RECONNECTION_RETRY_DELAY_ms, pow(2, _last_connection_attempt_cnt) * RECONNECTION_RETRY_DELAY_ms); _next_connection_attempt_tick = millis() + reconnection_retry_delay; From f3c1f17c42ef4b681da5cf7f446ea96a9ec3efaa Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 27 Apr 2021 14:45:31 +0200 Subject: [PATCH 093/780] Prefixing constants with AIOTC_CONFIG_ in order to avoid overriding similiar named defines in other (user) libraries. --- src/AIoTC_Config.h | 4 ++-- src/ArduinoIoTCloudTCP.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index c9e50f5c4..1ad21c0ce 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -138,7 +138,7 @@ * CONSTANTS ******************************************************************************/ -#define RECONNECTION_RETRY_DELAY_ms (1000UL) -#define MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) +#define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) +#define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) #endif /* ARDUINO_AIOTC_CONFIG_H_ */ diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 64ee89ec0..fba9a4823 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -364,7 +364,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() } _last_connection_attempt_cnt++; - unsigned long const reconnection_retry_delay = min(MAX_RECONNECTION_RETRY_DELAY_ms, pow(2, _last_connection_attempt_cnt) * RECONNECTION_RETRY_DELAY_ms); + unsigned long const reconnection_retry_delay = min(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms, pow(2, _last_connection_attempt_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms); _next_connection_attempt_tick = millis() + reconnection_retry_delay; DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); From aa34d3df96618467241c6aa31f0e7c082b93bc9b Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 27 Apr 2021 14:47:21 +0200 Subject: [PATCH 094/780] Move/rename TIMEOUT_FOR_LASTVALUES_SYNC to AIOTC_Config as AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms. --- src/AIoTC_Config.h | 1 + src/ArduinoIoTCloudTCP.cpp | 8 +------- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 1ad21c0ce..cc0ecf5d4 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -140,5 +140,6 @@ #define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) #define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) +#define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (10000UL) #endif /* ARDUINO_AIOTC_CONFIG_H_ */ diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index fba9a4823..470722d1e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -53,12 +53,6 @@ extern RTC_HandleTypeDef RTCHandle; #endif -/****************************************************************************** - GLOBAL CONSTANTS - ******************************************************************************/ - -static const int TIMEOUT_FOR_LASTVALUES_SYNC = 10000; - /****************************************************************************** LOCAL MODULE FUNCTIONS ******************************************************************************/ @@ -423,7 +417,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() /* Check whether or not we need to send a new request. */ unsigned long const now = millis(); - if ((now - _lastSyncRequestTickTime) > TIMEOUT_FOR_LASTVALUES_SYNC) + if ((now - _lastSyncRequestTickTime) > AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms) { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, now); requestLastValue(); From e60d6af71b48edafab61e3136c734d992b080027 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 27 Apr 2021 15:31:41 +0200 Subject: [PATCH 095/780] Fix compilation for ESP32/8266. --- src/ArduinoIoTCloudTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 470722d1e..4c0acde5e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -358,7 +358,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() } _last_connection_attempt_cnt++; - unsigned long const reconnection_retry_delay = min(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms, pow(2, _last_connection_attempt_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms); + unsigned long const reconnection_retry_delay = min(static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms), static_cast(pow(2, _last_connection_attempt_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms)); _next_connection_attempt_tick = millis() + reconnection_retry_delay; DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); From 75abde643b94a442d40d5e567bc1709d86751805 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 28 Apr 2021 09:53:48 +0200 Subject: [PATCH 096/780] Bugfix: Wrong operand order within comparison leads to never attempting reconnect. --- src/ArduinoIoTCloudTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 4c0acde5e..8b628b4b5 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -335,7 +335,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() if (_connection->check() == NetworkConnectionState::CONNECTED) { bool const is_retry_attempt = (_last_connection_attempt_cnt > 0); - if (!is_retry_attempt || (is_retry_attempt && (_next_connection_attempt_tick > millis()))) + if (!is_retry_attempt || (is_retry_attempt && (millis() > _next_connection_attempt_tick))) return State::SyncTime; } From fde634d72c63a6b04a9eadf168e62c0c2fdd2e6e Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 28 Apr 2021 09:57:45 +0200 Subject: [PATCH 097/780] Adding error message containing number of reconnection attempts as well as the next tick time. --- src/ArduinoIoTCloudTCP.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 8b628b4b5..ba15ad73b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -362,6 +362,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() _next_connection_attempt_tick = millis() + reconnection_retry_delay; DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s %d connection attempt at tick time %d", __FUNCTION__, _last_connection_attempt_cnt, _next_connection_attempt_tick); return State::ConnectPhy; } From 2989bfcdfa18fe981569fd6a41780e949d932559 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 28 Apr 2021 10:05:26 +0200 Subject: [PATCH 098/780] Rewrite calculation of reconnection retry delay for better readability. --- src/ArduinoIoTCloudTCP.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index ba15ad73b..dd2558581 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -358,7 +358,8 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() } _last_connection_attempt_cnt++; - unsigned long const reconnection_retry_delay = min(static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms), static_cast(pow(2, _last_connection_attempt_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms)); + unsigned long reconnection_retry_delay = pow(2, _last_connection_attempt_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms; + reconnection_retry_delay = min(reconnection_retry_delay, static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms)); _next_connection_attempt_tick = millis() + reconnection_retry_delay; DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); From 7a45793822dc302bfc911c38842d8096a368640e Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 28 Apr 2021 10:08:13 +0200 Subject: [PATCH 099/780] Renaming _lastSyncRequestTickTime to _last_sync_request_tick in order to have a unified variable naming standard. --- src/ArduinoIoTCloudTCP.cpp | 6 +++--- src/ArduinoIoTCloudTCP.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index dd2558581..2e016b471 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -70,7 +70,7 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() : _state{State::ConnectPhy} , _next_connection_attempt_tick{0} , _last_connection_attempt_cnt{0} -, _lastSyncRequestTickTime{0} +, _last_sync_request_tick{0} , _mqtt_data_buf{0} , _mqtt_data_len{0} , _mqtt_data_request_retransmit{false} @@ -419,11 +419,11 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() /* Check whether or not we need to send a new request. */ unsigned long const now = millis(); - if ((now - _lastSyncRequestTickTime) > AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms) + if ((now - _last_sync_request_tick) > AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms) { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, now); requestLastValue(); - _lastSyncRequestTickTime = now; + _last_sync_request_tick = now; } return State::RequestLastValues; diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 24ddeb10c..364b4bf36 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -98,7 +98,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass unsigned long _next_connection_attempt_tick; unsigned int _last_connection_attempt_cnt; - unsigned long _lastSyncRequestTickTime; + unsigned long _last_sync_request_tick; String _brokerAddress; uint16_t _brokerPort; uint8_t _mqtt_data_buf[MQTT_TRANSMIT_BUFFER_SIZE]; From 621c1a36800896d0a1131b3da7eca377886d259c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 28 Apr 2021 11:22:49 +0200 Subject: [PATCH 100/780] Replace 'pow' with bit-shift to save ressources. --- src/ArduinoIoTCloudTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 2e016b471..86b4bca3b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -358,7 +358,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() } _last_connection_attempt_cnt++; - unsigned long reconnection_retry_delay = pow(2, _last_connection_attempt_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms; + unsigned long reconnection_retry_delay = (1 << _last_connection_attempt_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms; reconnection_retry_delay = min(reconnection_retry_delay, static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms)); _next_connection_attempt_tick = millis() + reconnection_retry_delay; From c543d1423eaeded2c30ca500b906b9a96a5b6fc1 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 28 Apr 2021 11:47:38 +0200 Subject: [PATCH 101/780] Provide strong-implementations for weak watchdog functions within Arduino_ConnectionHandler. --- src/utility/watchdog/Watchdog.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index e760fd8a7..14c5d68e6 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -72,6 +72,16 @@ void wifi_nina_feed_watchdog() { samd_watchdog_reset(); } + +void mkr_gsm_feed_watchdog() +{ + samd_watchdog_reset(); +} + +void mkr_nb_feed_watchdog() +{ + samd_watchdog_reset(); +} #endif /* ARDUINO_ARCH_SAMD */ #ifdef ARDUINO_ARCH_MBED From 3ad1a3ba33d4a01f0ed25db359b14f80dca62343 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 29 Apr 2021 09:32:30 +0200 Subject: [PATCH 102/780] Explain watchdog behaviour in README. (#247) --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bfd3a3ff5..87368dd51 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,13 @@ void onLedChange() { ``` ### FAQ -* Device can not subscribe to `THING_ID` +#### Watchdog +This [1.0.0](https://github.com/arduino-libraries/ArduinoIoTCloud/releases/tag/1.0.0) release of this library adds watchdog functionality to all ATSAMD21G18 based cloud connected boards. A watchdog is simply an electronic timer counting down from a preset start value which, upon reaching zero, triggers a reset of the microcontroller. It can be used to automatically recover from temporary hardware faults or unrecoverable software errors. In order to avoid the watchdog from reaching zero the countdown timer needs to be regularly re-set to its start value. This is happening within `ArduinoIoTCloud.update()` which is periodically called at the start of the `loop()` function. Although the watchdog is automatically enabled it can be disabled by setting the second parameter of `ArduinoIoTCloud.begin(...)` to `false`: +```C++ +ArduinoIoTCloud.begin(ArduinoIoTPreferredConnection, false). +``` + +#### Device can not subscribe to `THING_ID` ``` ArduinoIoTCloudTCP::handle_SubscribeMqttTopics could not subscribe to /a/t/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/e/i ``` From 10d35e47d5074862424e3a0b807971938ee20bba Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 3 May 2021 07:22:46 +0200 Subject: [PATCH 103/780] Increase timeout for last-value synchronisation to 30 seconds. (#248) --- src/AIoTC_Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index cc0ecf5d4..7c76d4486 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -140,6 +140,6 @@ #define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) #define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) -#define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (10000UL) +#define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 71ee27942c3f202a743925ea0727af7b7842fc9c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 3 May 2021 09:01:41 +0200 Subject: [PATCH 104/780] Track the number of unsuccessful request-last-values. (#249) In the current implementation the number the board would continously attempt to obtain the last values from the cloud. If, however, those values never arrive - then the board would never move on and become operational. It's therefore better to count the number of failed attempts and reset the connection to allow a clean re-connection from the ground up. --- src/AIoTC_Config.h | 1 + src/ArduinoIoTCloudTCP.cpp | 14 ++++++++++++++ src/ArduinoIoTCloudTCP.h | 1 + 3 files changed, 16 insertions(+) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 7c76d4486..7c54d1751 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -141,5 +141,6 @@ #define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) #define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) +#define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) #endif /* ARDUINO_AIOTC_CONFIG_H_ */ diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 86b4bca3b..54d416596 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -71,6 +71,7 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _next_connection_attempt_tick{0} , _last_connection_attempt_cnt{0} , _last_sync_request_tick{0} +, _last_sync_request_cnt{0} , _mqtt_data_buf{0} , _mqtt_data_len{0} , _mqtt_data_request_retransmit{false} @@ -424,6 +425,18 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, now); requestLastValue(); _last_sync_request_tick = now; + /* Track the number of times a get-last-values request was sent to the cloud. + * If no data is received within a certain number of retry-requests it's a better + * strategy to disconnect and re-establish connection from the ground up. + */ + _last_sync_request_cnt++; + if (_last_sync_request_cnt > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) + { + _last_sync_request_cnt = 0; + _mqttClient.stop(); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + return State::ConnectPhy; + } } return State::RequestLastValues; @@ -517,6 +530,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) CBORDecoder::decode(_property_container, (uint8_t*)bytes, length, true); sendPropertiesToCloud(); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); + _last_sync_request_cnt = 0; _state = State::Connected; } } diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 364b4bf36..f29aafde7 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -99,6 +99,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass unsigned long _next_connection_attempt_tick; unsigned int _last_connection_attempt_cnt; unsigned long _last_sync_request_tick; + unsigned int _last_sync_request_cnt; String _brokerAddress; uint16_t _brokerPort; uint8_t _mqtt_data_buf[MQTT_TRANSMIT_BUFFER_SIZE]; From b7be7055c3a2271f55f3d2332a95ff30651dc9b0 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 3 May 2021 09:02:37 +0200 Subject: [PATCH 105/780] Release v1.0.0 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index e3f2d3518..5a770ad1e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=0.13.1 +version=1.0.0 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From a9c96b907f4812e282a44d5c65b71047a85d8ed3 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 4 May 2021 11:00:56 +0200 Subject: [PATCH 106/780] Fix: Immediately trigger a sync request on the first time this function is reached. (#250) It does not make sense to let the user wait until the timeout has passed (which is now even 30 seconds) long. Therefore the logic should trigger an immediate sync the first time this function is reached. --- src/ArduinoIoTCloudTCP.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 54d416596..55ad692ae 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -420,7 +420,9 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() /* Check whether or not we need to send a new request. */ unsigned long const now = millis(); - if ((now - _last_sync_request_tick) > AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms) + bool const is_sync_request_timeout = (now - _last_sync_request_tick) > AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms; + bool const is_first_sync_request = (_last_sync_request_cnt == 0); + if (is_first_sync_request || is_sync_request_timeout) { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, now); requestLastValue(); @@ -433,6 +435,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() if (_last_sync_request_cnt > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) { _last_sync_request_cnt = 0; + _last_sync_request_tick = 0; _mqttClient.stop(); execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); return State::ConnectPhy; @@ -531,6 +534,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) sendPropertiesToCloud(); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); _last_sync_request_cnt = 0; + _last_sync_request_tick = 0; _state = State::Connected; } } From ae54b94f0d2d3672dcf5aa3994275c4a66e9904a Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 4 May 2021 11:10:34 +0200 Subject: [PATCH 107/780] Release v1.0.1. --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 5a770ad1e..3575a056e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.0.0 +version=1.0.1 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From 8697692f9258193ccd559e96e9a76eb1fbb1d5a0 Mon Sep 17 00:00:00 2001 From: Ubi de Feo Date: Mon, 10 May 2021 07:19:21 +0200 Subject: [PATCH 108/780] enabled `setInsecure()` for ESP32 (#251) Previously a call to this method had to be omitted, it was only required for ESP8266. Out of a debugging session ended up with the broker refusing connections so I enabled `insecure` mode and it now works --- src/ArduinoIoTCloudTCP.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 55ad692ae..ae9a28caa 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -207,10 +207,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _sslClient.setClient(_connection->getClient()); _sslClient.setEccSlot(static_cast(ECCX08Slot::Key), _eccx08_cert.bytes(), _eccx08_cert.length()); #elif defined(BOARD_ESP) - #ifndef ESP32 _sslClient.setInsecure(); #endif - #endif _mqttClient.setClient(_sslClient); #ifdef BOARD_ESP From c58dad775dc1074d98ce15f60311342590d57c79 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 10 May 2021 08:30:12 +0200 Subject: [PATCH 109/780] Extract samd related OTA request code into function 'samd_onOTARequest'. The main imperative behind doing this is that the method ArduinoIoTCloudTCP::onOTARequest is getting really cluttered and for the sake of clarity its better to extract the code into a separate function. --- src/ArduinoIoTCloudTCP.cpp | 24 +------------- src/utility/ota/OTA-samd.cpp | 63 ++++++++++++++++++++++++++++++++++++ src/utility/ota/OTA.h | 8 +++++ 3 files changed, 72 insertions(+), 23 deletions(-) create mode 100644 src/utility/ota/OTA-samd.cpp diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index ae9a28caa..a13e4231e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -579,34 +579,12 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l #if OTA_ENABLED void ArduinoIoTCloudTCP::onOTARequest() { -#ifdef ARDUINO_ARCH_SAMD - samd_watchdog_reset(); -#endif /* ARDUINO_ARCH_SAMD */ - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str()); -#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"); - #ifdef ARDUINO_ARCH_SAMD - samd_watchdog_reset(); + _ota_error = samd_onOTARequest(_ota_url.c_str()); #endif /* ARDUINO_ARCH_SAMD */ - /* Trigger direct download to nina module. */ - uint8_t nina_ota_err_code = 0; - if (!WiFiStorage.downloadOTA(_ota_url.c_str(), &nina_ota_err_code)) - { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s error download to nina: %d", __FUNCTION__, nina_ota_err_code); - _ota_error = static_cast(OTAError::DownloadFailed); - return; - } - - /* Perform the reset to reboot to SxU. */ - NVIC_SystemReset(); -#endif /* OTA_STORAGE_SNU */ - #if OTA_STORAGE_PORTENTA_QSPI mbed_watchdog_reset(); diff --git a/src/utility/ota/OTA-samd.cpp b/src/utility/ota/OTA-samd.cpp new file mode 100644 index 000000000..50e5fbf04 --- /dev/null +++ b/src/utility/ota/OTA-samd.cpp @@ -0,0 +1,63 @@ +/* + 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. +*/ + +#ifdef ARDUINO_ARCH_SAMD + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include "OTA.h" + +#include +#include + +#include "../watchdog/Watchdog.h" + +#if OTA_STORAGE_SNU +# include /* WiFiStorage */ +#endif + +/****************************************************************************** + * FUNCTION DEFINITION + ******************************************************************************/ + +int samd_onOTARequest(char const * ota_url) +{ + samd_watchdog_reset(); + +#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"); + + samd_watchdog_reset(); + + /* Trigger direct download to nina module. */ + uint8_t nina_ota_err_code = 0; + if (!WiFiStorage.downloadOTA(ota_url, &nina_ota_err_code)) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s error download to nina: %d", __FUNCTION__, nina_ota_err_code); + return static_cast(OTAError::DownloadFailed); + } + + /* Perform the reset to reboot to SxU. */ + NVIC_SystemReset(); +#endif /* OTA_STORAGE_SNU */ +} + +#endif /* ARDUINO_ARCH_SAMD */ diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 670b5ac07..051aface6 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -51,6 +51,14 @@ enum class OTAError : int DownloadFailed = 1, }; +/****************************************************************************** + * FUNCTION DEFINITION + ******************************************************************************/ + +#ifdef ARDUINO_ARCH_SAMD +int samd_onOTARequest(char const * ota_url); +#endif + #endif /* OTA_ENABLED */ #endif /* ARDUINO_OTA_LOGIC_H_ */ From 790fc11610a3af37b4d52f2981d1634d32811bd3 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 10 May 2021 08:32:55 +0200 Subject: [PATCH 110/780] The #if OTA_ENABLED preprocessor guards can be safely removed here, since it will not have any impact on the compilation process but enhances clarity for the programmer. --- src/utility/ota/OTA.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 051aface6..62b34a69a 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -23,7 +23,6 @@ ******************************************************************************/ #include -#if OTA_ENABLED #if OTA_STORAGE_SNU && !defined(ARDUINO_AVR_UNO_WIFI_REV2) #include @@ -59,6 +58,4 @@ enum class OTAError : int int samd_onOTARequest(char const * ota_url); #endif -#endif /* OTA_ENABLED */ - #endif /* ARDUINO_OTA_LOGIC_H_ */ From 306d569f67e440100c714885859b2beae5fd0fd4 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 10 May 2021 08:49:44 +0200 Subject: [PATCH 111/780] Extracting Portenta H7 OTA code to method 'portenta_h7_onOTARequest' --- src/ArduinoIoTCloudTCP.cpp | 54 ++---------------- src/utility/ota/OTA-portenta-h7.cpp | 85 +++++++++++++++++++++++++++++ src/utility/ota/OTA-samd.cpp | 1 - src/utility/ota/OTA.h | 4 ++ 4 files changed, 93 insertions(+), 51 deletions(-) create mode 100644 src/utility/ota/OTA-portenta-h7.cpp diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index a13e4231e..6e63d181b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -583,57 +583,11 @@ void ArduinoIoTCloudTCP::onOTARequest() #ifdef ARDUINO_ARCH_SAMD _ota_error = samd_onOTARequest(_ota_url.c_str()); -#endif /* ARDUINO_ARCH_SAMD */ - -#if OTA_STORAGE_PORTENTA_QSPI - mbed_watchdog_reset(); - - Arduino_Portenta_OTA::Error ota_portenta_err = Arduino_Portenta_OTA::Error::None; - /* Use 2nd partition of QSPI (1st partition contains WiFi firmware) */ - Arduino_Portenta_OTA_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2); - - mbed_watchdog_reset(); - - /* Initialize the QSPI memory for OTA handling. */ - if((ota_portenta_err = ota_portenta_qspi.begin()) != Arduino_Portenta_OTA::Error::None) { - DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::begin() failed with %d", static_cast(ota_portenta_err)); - return; - } - - mbed_watchdog_reset(); - - /* Just to be safe delete any remains from previous updates. */ - remove("/fs/UPDATE.BIN"); - remove("/fs/UPDATE.BIN.LZSS"); - - mbed_watchdog_reset(); - - /* Download the OTA file from the web storage location. */ - int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download((char*)(_ota_url.c_str()), true /* is_https */); - DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::download(%s) returns %d", _ota_url.c_str(), ota_portenta_qspi_download_ret_code); - - mbed_watchdog_reset(); - - /* Decompress the LZSS compressed OTA file. */ - int const ota_portenta_qspi_decompress_ret_code = ota_portenta_qspi.decompress(); - DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::decompress() returns %d", ota_portenta_qspi_decompress_ret_code); - if (ota_portenta_qspi_decompress_ret_code < 0) - { - DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::decompress() failed with %d", ota_portenta_qspi_decompress_ret_code); - return; - } - - mbed_watchdog_reset(); - - /* Schedule the firmware update. */ - if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) { - DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::update() failed with %d", static_cast(ota_portenta_err)); - return; - } +#endif - /* Perform the reset to reboot - then the bootloader performs the actual application update. */ - NVIC_SystemReset(); -#endif /* OTA_STORAGE_PORTENTA_QSPI */ +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + _ota_error = portenta_h7_onOTARequest(_ota_url.c_str()); +#endif } #endif diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp new file mode 100644 index 000000000..19c712a2a --- /dev/null +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -0,0 +1,85 @@ +/* + 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. +*/ + +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include "OTA.h" + +#include + +#include "../watchdog/Watchdog.h" + +/****************************************************************************** + * FUNCTION DEFINITION + ******************************************************************************/ + +int portenta_h7_onOTARequest(char const * ota_url) +{ + mbed_watchdog_reset(); + + Arduino_Portenta_OTA::Error ota_portenta_err = Arduino_Portenta_OTA::Error::None; + /* Use 2nd partition of QSPI (1st partition contains WiFi firmware) */ + Arduino_Portenta_OTA_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2); + + mbed_watchdog_reset(); + + /* Initialize the QSPI memory for OTA handling. */ + if((ota_portenta_err = ota_portenta_qspi.begin()) != Arduino_Portenta_OTA::Error::None) { + DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::begin() failed with %d", static_cast(ota_portenta_err)); + return static_cast(ota_portenta_err); + } + + mbed_watchdog_reset(); + + /* Just to be safe delete any remains from previous updates. */ + remove("/fs/UPDATE.BIN"); + remove("/fs/UPDATE.BIN.LZSS"); + + mbed_watchdog_reset(); + + /* Download the OTA file from the web storage location. */ + int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download(ota_url, true /* is_https */); + DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::download(%s) returns %d", ota_url, ota_portenta_qspi_download_ret_code); + + mbed_watchdog_reset(); + + /* Decompress the LZSS compressed OTA file. */ + int const ota_portenta_qspi_decompress_ret_code = ota_portenta_qspi.decompress(); + DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::decompress() returns %d", ota_portenta_qspi_decompress_ret_code); + if (ota_portenta_qspi_decompress_ret_code < 0) + { + DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::decompress() failed with %d", ota_portenta_qspi_decompress_ret_code); + return ota_portenta_qspi_decompress_ret_code; + } + + mbed_watchdog_reset(); + + /* Schedule the firmware update. */ + if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) { + DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::update() failed with %d", static_cast(ota_portenta_err)); + return static_cast(ota_portenta_err); + } + + /* Perform the reset to reboot - then the bootloader performs the actual application update. */ + NVIC_SystemReset(); +} + +#endif /* defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) */ diff --git a/src/utility/ota/OTA-samd.cpp b/src/utility/ota/OTA-samd.cpp index 50e5fbf04..06ddd3136 100644 --- a/src/utility/ota/OTA-samd.cpp +++ b/src/utility/ota/OTA-samd.cpp @@ -23,7 +23,6 @@ #include "OTA.h" -#include #include #include "../watchdog/Watchdog.h" diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 62b34a69a..cbcad0344 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -58,4 +58,8 @@ enum class OTAError : int int samd_onOTARequest(char const * ota_url); #endif +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) +int portenta_h7_onOTARequest(char const * ota_url); +#endif + #endif /* ARDUINO_OTA_LOGIC_H_ */ From 40ea7d5f76d854c44cc2b94cb1e429a621df54fe Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 10 May 2021 08:52:32 +0200 Subject: [PATCH 112/780] Move inclusion of Arduino_Portenta_OTA library within OTA-portenta-h7.cpp (no need for it to be included outside of this module. --- src/ArduinoIoTCloudTCP.cpp | 4 +++- src/utility/ota/OTA-portenta-h7.cpp | 1 + src/utility/ota/OTA.h | 4 ---- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 6e63d181b..653952e42 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -33,7 +33,8 @@ #include "tls/utility/CryptoUtil.h" #endif -#if defined(ARDUINO_PORTENTA_H7_M7) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) +# include # include "tls/utility/SHA256.h" # include #endif @@ -45,6 +46,7 @@ #include "utility/watchdog/Watchdog.h" + /****************************************************************************** * EXTERN ******************************************************************************/ diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index 19c712a2a..b8ec0772a 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -24,6 +24,7 @@ #include "OTA.h" #include +#include #include "../watchdog/Watchdog.h" diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index cbcad0344..70a5916b1 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -36,10 +36,6 @@ #include #endif /* OTA_STORAGE_SFU */ -#if OTA_STORAGE_PORTENTA_QSPI - #include -#endif /* OTA_STORAGE_PORTENTA_QSPI */ - /****************************************************************************** * TYPEDEF ******************************************************************************/ From b0fc197f920089ffa3a30af838ed7a2bcaad4400 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 10 May 2021 09:00:39 +0200 Subject: [PATCH 113/780] Moving inclusion of SNU library into OTA-samd.cpp - where it belongs. --- src/utility/ota/OTA-samd.cpp | 1 + src/utility/ota/OTA.h | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/utility/ota/OTA-samd.cpp b/src/utility/ota/OTA-samd.cpp index 06ddd3136..c5ee8a8d5 100644 --- a/src/utility/ota/OTA-samd.cpp +++ b/src/utility/ota/OTA-samd.cpp @@ -28,6 +28,7 @@ #include "../watchdog/Watchdog.h" #if OTA_STORAGE_SNU +# include # include /* WiFiStorage */ #endif diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 70a5916b1..6a9b2312f 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -24,10 +24,6 @@ #include -#if OTA_STORAGE_SNU && !defined(ARDUINO_AVR_UNO_WIFI_REV2) - #include -#endif /* OTA_STORAGE_SNU */ - #if OTA_STORAGE_SSU #include #endif /* OTA_STORAGE_SSU */ From 839fd9bb72470d4210e7c62af065785c2136e673 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 17 May 2021 08:43:45 +0200 Subject: [PATCH 114/780] Removing no-longer needed CRC module. (#253) --- src/utility/ota/crc.cpp | 82 ---------------------------- src/utility/ota/crc.h | 115 ---------------------------------------- 2 files changed, 197 deletions(-) delete mode 100644 src/utility/ota/crc.cpp delete mode 100644 src/utility/ota/crc.h diff --git a/src/utility/ota/crc.cpp b/src/utility/ota/crc.cpp deleted file mode 100644 index cb1d565c5..000000000 --- a/src/utility/ota/crc.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/** - * \file - * Functions and types for CRC checks. - * - * Generated on Tue Jan 7 07:33:25 2020 - * by pycrc v0.9.2, https://pycrc.org - * using the configuration: - * - Width = 32 - * - Poly = 0x04c11db7 - * - XorIn = 0xffffffff - * - ReflectIn = True - * - XorOut = 0xffffffff - * - ReflectOut = True - * - Algorithm = table-driven - */ - -#ifndef HOST - #include -#else - #define OTA_ENABLED (1) -#endif -#if OTA_ENABLED - -#include "crc.h" /* include the header file generated with pycrc */ -#include -#include - - - -/** - * Static table used for the table_driven implementation. - */ -static const crc_t crc_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - - -crc_t crc_update(crc_t crc, const void *data, size_t data_len) -{ - const unsigned char *d = (const unsigned char *)data; - unsigned int tbl_idx; - - while (data_len--) { - tbl_idx = (crc ^ *d) & 0xff; - crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff; - d++; - } - return crc & 0xffffffff; -} - -#endif /* OTA_ENABLED */ diff --git a/src/utility/ota/crc.h b/src/utility/ota/crc.h deleted file mode 100644 index c86fadfb7..000000000 --- a/src/utility/ota/crc.h +++ /dev/null @@ -1,115 +0,0 @@ -/** - * \file - * Functions and types for CRC checks. - * - * Generated on Tue Jan 7 07:33:20 2020 - * by pycrc v0.9.2, https://pycrc.org - * using the configuration: - * - Width = 32 - * - Poly = 0x04c11db7 - * - XorIn = 0xffffffff - * - ReflectIn = True - * - XorOut = 0xffffffff - * - ReflectOut = True - * - Algorithm = table-driven - * - * This file defines the functions crc_init(), crc_update() and crc_finalize(). - * - * The crc_init() function returns the initial \c crc value and must be called - * before the first call to crc_update(). - * Similarly, the crc_finalize() function must be called after the last call - * to crc_update(), before the \c crc is being used. - * is being used. - * - * The crc_update() function can be called any number of times (including zero - * times) in between the crc_init() and crc_finalize() calls. - * - * This pseudo-code shows an example usage of the API: - * \code{.c} - * crc_t crc; - * unsigned char data[MAX_DATA_LEN]; - * size_t data_len; - * - * crc = crc_init(); - * while ((data_len = read_data(data, MAX_DATA_LEN)) > 0) { - * crc = crc_update(crc, data, data_len); - * } - * crc = crc_finalize(crc); - * \endcode - */ -#ifndef CRC_H -#define CRC_H - -#ifndef HOST - #include -#else - #define OTA_ENABLED (1) -#endif -#if OTA_ENABLED - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * The definition of the used algorithm. - * - * This is not used anywhere in the generated code, but it may be used by the - * application code to call algorithm-specific code, if desired. - */ -#define CRC_ALGO_TABLE_DRIVEN 1 - - -/** - * The type of the CRC values. - * - * This type must be big enough to contain at least 32 bits. - */ -typedef uint_fast32_t crc_t; - - -/** - * Calculate the initial crc value. - * - * \return The initial crc value. - */ -static inline crc_t crc_init(void) -{ - return 0xffffffff; -} - - -/** - * Update the crc value with new data. - * - * \param[in] crc The current crc value. - * \param[in] data Pointer to a buffer of \a data_len bytes. - * \param[in] data_len Number of bytes in the \a data buffer. - * \return The updated crc value. - */ -crc_t crc_update(crc_t crc, const void *data, size_t data_len); - - -/** - * Calculate the final crc value. - * - * \param[in] crc The current crc value. - * \return The final crc value. - */ -static inline crc_t crc_finalize(crc_t crc) -{ - return crc ^ 0xffffffff; -} - - -#ifdef __cplusplus -} /* closing brace for extern "C" */ -#endif - -#endif /* CRC_H */ - -#endif /* OTA_ENABLED */ From d5856189abff44a316c075b5bbd8404e55cc6698 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 17 May 2021 09:19:14 +0200 Subject: [PATCH 115/780] Disable CI compilation for Uno WiFi Rev. 2 (#254) The current implementation is barely working, as it is exceeding the flash storage capacity of the Uno WiFi Rev. 2. It makes no sense for us to trouble us with a "failing CI build", when we are not really supporting Arduino Uno WiFi Rev. 2 at all." --- .github/workflows/compile-examples.yml | 30 +++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index fd76e9bdb..503ca0249 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -44,8 +44,8 @@ jobs: type: nina - fqbn: arduino:samd:nano_33_iot type: nina - - fqbn: arduino:megaavr:uno2018 - type: megaavr + #- fqbn: arduino:megaavr:uno2018 + # type: megaavr - fqbn: arduino:samd:mkrwan1300 type: wan - fqbn: arduino:samd:mkrgsm1400 @@ -96,19 +96,19 @@ jobs: - examples/utility/Provisioning - examples/utility/SelfProvisioning # Uno WiFi Rev2 - - board: - type: megaavr - platforms: | - - name: arduino:megaavr - libraries: | - - name: ArduinoECCX08 - - name: Arduino_AVRSTL - - name: WiFiNINA - - name: Arduino_JSON - - name: ArduinoBearSSL - sketch-paths: | - - examples/utility/Provisioning - - examples/utility/SelfProvisioning + #- board: + # type: megaavr + # platforms: | + # - name: arduino:megaavr + # libraries: | + # - name: ArduinoECCX08 + # - name: Arduino_AVRSTL + # - name: WiFiNINA + # - name: Arduino_JSON + # - name: ArduinoBearSSL + # sketch-paths: | + # - examples/utility/Provisioning + # - examples/utility/SelfProvisioning # LoRaWAN boards - board: type: wan From 8afff8c2ae26c827f79bdebf61438707c258340a Mon Sep 17 00:00:00 2001 From: per1234 Date: Mon, 17 May 2021 02:50:43 -0700 Subject: [PATCH 116/780] Remove claim of compatibility with megaavr architecture (#255) The library does not support the megaavr architecture, so the metadata was incorrect. --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 3575a056e..4e239f2e4 100644 --- a/library.properties +++ b/library.properties @@ -6,6 +6,6 @@ sentence=This library allows to connect to the Arduino IoT Cloud service. paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKRGSM, MKR1000 and WiFi101. category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud -architectures=mbed,samd,esp8266,megaavr,mbed_nano,mbed_portenta +architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta includes=ArduinoIoTCloud.h depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero From 90f3beda369ae7e714b5ac2cc6f2ce5346483ff5 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 20 May 2021 17:52:45 +0200 Subject: [PATCH 117/780] INITIAL: support OTA on Nano RP2040 COnnect --- src/AIoTC_Config.h | 7 +++ src/ArduinoIoTCloudTCP.cpp | 14 +++++- src/utility/ota/OTA-nano-rp2040.cpp | 72 +++++++++++++++++++++++++++++ src/utility/ota/OTA.h | 4 ++ 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 src/utility/ota/OTA-nano-rp2040.cpp diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 7c54d1751..56d430d7a 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -94,6 +94,13 @@ #define OTA_STORAGE_SNU (0) #endif +#if defined(ARDUINO_NANO_RP2040_CONNECT) + #undef OTA_STORAGE_SFU + #define OTA_STORAGE_SFU (1) +#else + #define OTA_STORAGE_SFU (0) +#endif + #ifdef ARDUINO_SAMD_MKRGSM1400 #define OTA_STORAGE_SSU (1) #else diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 653952e42..be744294e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -171,7 +171,13 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, * The bootloader is excluded from the calculation and occupies flash address * range 0 to 0x2000, total flash size of 0x40000 bytes (256 kByte). */ - String const sha256_str = FlashSHA256::calc(0x2000, 0x40000 - 0x2000); +#if defined(ARDUINO_NANO_RP2040_CONNECT) +#define FLASH_BASE XIP_BASE + _ota_cap = true; +#else +#define FLASH_BASE 0 +#endif + String const sha256_str = FlashSHA256::calc(FLASH_BASE + 0x2000, 0x40000 - 0x2000); #endif DEBUG_VERBOSE("SHA256: HASH(%d) = %s", strlen(sha256_str.c_str()), sha256_str.c_str()); _ota_img_sha256 = sha256_str; @@ -581,12 +587,16 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l #if OTA_ENABLED void ArduinoIoTCloudTCP::onOTARequest() { - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, _ota_url.c_str()); + 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 + #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) _ota_error = portenta_h7_onOTARequest(_ota_url.c_str()); #endif diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp new file mode 100644 index 000000000..426bb5fb0 --- /dev/null +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -0,0 +1,72 @@ +/* + 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. +*/ + +#if defined(ARDUINO_NANO_RP2040_CONNECT) + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include "OTA.h" + +#include + +/****************************************************************************** + * FUNCTION DEFINITION + ******************************************************************************/ + +int rp2040_connect_onOTARequest(char const * ota_url) +{ + SFU::begin(); + + /* Just to be safe delete any remains from previous updates. */ + WiFiStorage.remove("/fs/UPDATE.BIN"); + struct stat st; + int err = stat("/ota/UPDATE.BIN", &st); + if (err == 0) { + remove("/ota/UPDATE.BIN"); + } + + /* TODO: FIXME: Download into NINA then transfer to /fs/UPDATE.BIN */ + uint8_t nina_ota_err_code = 0; + if (!WiFiStorage.downloadOTA(ota_url, &nina_ota_err_code)) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s error download to nina: %d", __FUNCTION__, nina_ota_err_code); + return static_cast(OTAError::DownloadFailed); + } + + FILE* update = fopen("/ota/UPDATE.BIN", "w"); + + uint8_t tempbuf[128]; + + WiFiStorageFile nina_update = WiFiStorage.open("/fs/UPDATE.BIN"); + + while (true) { + int ret = nina_update.read(tempbuf, sizeof(tempbuf)); + if (ret == 0) { + break; + } + fwrite(tempbuf, ret, 1, update); + } + + fclose(update); + + /* Perform the reset to reboot to SxU. */ + NVIC_SystemReset(); +} + +#endif /* ARDUINO_NANO_RP2040_CONNECT */ diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 6a9b2312f..9d103d053 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -50,6 +50,10 @@ enum class OTAError : int int samd_onOTARequest(char const * ota_url); #endif +#ifdef ARDUINO_NANO_RP2040_CONNECT +int rp2040_connect_onOTARequest(char const * ota_url); +#endif + #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) int portenta_h7_onOTARequest(char const * ota_url); #endif From 60cf53faa291fc31bd08ba83b09a32234f03a039 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 25 May 2021 10:33:41 +0200 Subject: [PATCH 118/780] Remove commented-out CI code for Uno WiFi Rev. 2. (#258) --- .github/workflows/compile-examples.yml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 503ca0249..fc61f06b3 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -44,8 +44,6 @@ jobs: type: nina - fqbn: arduino:samd:nano_33_iot type: nina - #- fqbn: arduino:megaavr:uno2018 - # type: megaavr - fqbn: arduino:samd:mkrwan1300 type: wan - fqbn: arduino:samd:mkrgsm1400 @@ -95,21 +93,6 @@ jobs: sketch-paths: | - examples/utility/Provisioning - examples/utility/SelfProvisioning - # Uno WiFi Rev2 - #- board: - # type: megaavr - # platforms: | - # - name: arduino:megaavr - # libraries: | - # - name: ArduinoECCX08 - # - name: Arduino_AVRSTL - # - name: WiFiNINA - # - name: Arduino_JSON - # - name: ArduinoBearSSL - # sketch-paths: | - # - examples/utility/Provisioning - # - examples/utility/SelfProvisioning - # LoRaWAN boards - board: type: wan platforms: | From 516ad1bde2451fa75e2991e41a8443e78e2f4739 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 25 May 2021 10:34:11 +0200 Subject: [PATCH 119/780] Release v1.0.2. --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 4e239f2e4..299a711c2 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.0.1 +version=1.0.2 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From b27e30b85b20769abfa280b167be5279333cf5ba Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 25 May 2021 15:05:44 +0200 Subject: [PATCH 120/780] TEMP: add proper download via WiFi/WiFiSSL client --- src/AIoTC_Config.h | 2 +- src/ArduinoIoTCloudTCP.cpp | 5 +- src/utility/ota/OTA-nano-rp2040.cpp | 138 +++++++++++++++++++++++++--- 3 files changed, 127 insertions(+), 18 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 56d430d7a..70af6b716 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -66,7 +66,7 @@ # if defined(ARDUINO_AVR_UNO_WIFI_REV2) # define DEBUG_VERBOSE(fmt, ...) # else -# define DEBUG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) +# define DEBUG_VERBOSE(fmt, ...) Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) # endif #endif diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index be744294e..7f38bd024 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -92,8 +92,8 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _ota_cap{false} , _ota_error{static_cast(OTAError::None)} , _ota_img_sha256{"Inv."} -, _ota_url{""} -, _ota_req{false} +, _ota_url{"http://10.130.22.65/UPDATE.BIN"} +, _ota_req{true} #endif /* OTA_ENABLED */ { @@ -497,6 +497,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() /* Request a OTA download if the hidden property * OTA request has been set. */ + if (_ota_req) { /* Clear the error flag. */ diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 426bb5fb0..72da2f78d 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -23,47 +23,155 @@ #include "OTA.h" +#include "../watchdog/Watchdog.h" + #include +#include /****************************************************************************** * FUNCTION DEFINITION ******************************************************************************/ +static rtos::Thread t(osPriorityHigh); + +void kick_watchdog() { + while (1) { + mbed_watchdog_reset(); + delay(2000); + } +} + +/* Original code: http://stackoverflow.com/questions/2616011/easy-way-to-parse-a-url-in-c-cross-platform */ +#include +struct URI { + public: + URI(const std::string& url_s) { + this->parse(url_s); + } + std::string protocol_, host_, path_, query_; + private: + void parse(const std::string& url_s); +}; + +#include +#include +#include +#include +#include + +using namespace std; + +// ctors, copy, equality, ... + +void URI::parse(const string& url_s) +{ + const string prot_end("://"); + string::const_iterator prot_i = search(url_s.begin(), url_s.end(), + prot_end.begin(), prot_end.end()); + protocol_.reserve(distance(url_s.begin(), prot_i)); + transform(url_s.begin(), prot_i, + back_inserter(protocol_), + ptr_fun(tolower)); // protocol is icase + if( prot_i == url_s.end() ) + return; + advance(prot_i, prot_end.length()); + string::const_iterator path_i = find(prot_i, url_s.end(), '/'); + host_.reserve(distance(prot_i, path_i)); + transform(prot_i, path_i, + back_inserter(host_), + ptr_fun(tolower)); // host is icase + string::const_iterator query_i = find(path_i, url_s.end(), '?'); + path_.assign(path_i, query_i); + if( query_i != url_s.end() ) + ++query_i; + query_.assign(query_i, url_s.end()); +} + int rp2040_connect_onOTARequest(char const * ota_url) { SFU::begin(); + t.start(kick_watchdog); + +#if 0 /* Just to be safe delete any remains from previous updates. */ - WiFiStorage.remove("/fs/UPDATE.BIN"); struct stat st; int err = stat("/ota/UPDATE.BIN", &st); if (err == 0) { remove("/ota/UPDATE.BIN"); } +#endif + + Client* client; + + URI url(http://github.com/ota_url); + + if (url.protocol_ == "http") { + client = new WiFiClient(); + } else { + client = new WiFiSSLClient(); + } + + const char* host = url.host_.c_str(); - /* TODO: FIXME: Download into NINA then transfer to /fs/UPDATE.BIN */ - uint8_t nina_ota_err_code = 0; - if (!WiFiStorage.downloadOTA(ota_url, &nina_ota_err_code)) + IPAddress ip; + ip.fromString(host); + + int ret = client->connect(ip, 80); + if (!ret) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s error download to nina: %d", __FUNCTION__, nina_ota_err_code); - return static_cast(OTAError::DownloadFailed); + DEBUG_ERROR("%s: Connection failure with OTA storage server %s", __FUNCTION__, host); + return -1; /* TODO: Implement better error codes. */ } - FILE* update = fopen("/ota/UPDATE.BIN", "w"); + client->println(String("GET ") + url.path_.c_str() + " HTTP/1.1"); + client->println(String("Host: ") + host); + client->println("Connection: close"); + client->println(); - uint8_t tempbuf[128]; + FILE * file = fopen("/ota/UPDATE.BIN", "wb"); + if (!file) + { + DEBUG_ERROR("%s: fopen() failed", __FUNCTION__); + fclose(file); + return errno; + } - WiFiStorageFile nina_update = WiFiStorage.open("/fs/UPDATE.BIN"); + String http_header; + bool is_header_complete = false; - while (true) { - int ret = nina_update.read(tempbuf, sizeof(tempbuf)); - if (ret == 0) { - break; + while (!client->available()) { + delay(10); + } + + while (client->available()) + { + char const c = client->read(); + + if(!is_header_complete) + { + http_header += c; + if (http_header.endsWith("\r\n\r\n")) + is_header_complete = true; + } + else + { + if (fwrite(&c, 1, sizeof(c), file) != sizeof(c)) + { + DEBUG_ERROR("%s: Writing of firmware image to flash failed", __FUNCTION__); + return -2; /* TODO: Find better error codes. */ + } } - fwrite(tempbuf, ret, 1, update); } - fclose(update); + int const file_len = ftell(file); + DEBUG_DEBUG("%s: %d bytes received", __FUNCTION__, file_len); + + while (file_len == 0) { + delay(1000); + } + + fclose(file); /* Perform the reset to reboot to SxU. */ NVIC_SystemReset(); From cc1aeba51a9e64d76a73d59cb4ac13e2866d88eb Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 26 May 2021 15:43:42 +0200 Subject: [PATCH 121/780] tools/bin2ota: add nano rp2040 asupport --- extras/tools/bin2ota.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extras/tools/bin2ota.py b/extras/tools/bin2ota.py index 648aa2395..ffb21a856 100755 --- a/extras/tools/bin2ota.py +++ b/extras/tools/bin2ota.py @@ -24,6 +24,8 @@ magic_number = 0x23418057.to_bytes(4,byteorder='little') elif board == "PORTENTA_H7_M7": magic_number = 0x2341025B.to_bytes(4,byteorder='little') +elif board == "NANO_RP2040_CONNECT": + magic_number = 0x2341005E.to_bytes(4,byteorder='little') else: print ("Error,", board, "is not a supported board type") sys.exit() From 26d989f58525694547668cb8e04a9ac51157a190 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 27 May 2021 14:25:40 +0200 Subject: [PATCH 122/780] Add comments and TODO --- src/utility/ota/OTA-nano-rp2040.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 72da2f78d..f91cdb6a5 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -43,6 +43,11 @@ void kick_watchdog() { /* Original code: http://stackoverflow.com/questions/2616011/easy-way-to-parse-a-url-in-c-cross-platform */ #include +#include +#include +#include +#include + struct URI { public: URI(const std::string& url_s) { @@ -53,16 +58,10 @@ struct URI { void parse(const std::string& url_s); }; -#include -#include -#include -#include -#include - using namespace std; // ctors, copy, equality, ... - +// TODO: change me into something embedded friendly (this function adds ~100KB to flash) void URI::parse(const string& url_s) { const string prot_end("://"); @@ -104,20 +103,27 @@ int rp2040_connect_onOTARequest(char const * ota_url) Client* client; + // TODO: eventually parse port in URL + int port; + URI url(http://github.com/ota_url); if (url.protocol_ == "http") { client = new WiFiClient(); + port = 80; } else { client = new WiFiSSLClient(); + port = 443; } const char* host = url.host_.c_str(); - IPAddress ip; - ip.fromString(host); + // TODO: find if the host is an IP address and treat accordingly + // IPAddress ip; + // ip.fromString(host); + //int ret = client->connect(ip, port); - int ret = client->connect(ip, 80); + int ret = client->connect(host, port); if (!ret) { DEBUG_ERROR("%s: Connection failure with OTA storage server %s", __FUNCTION__, host); From 6359f8a02af55e8bcc2d5723c4a839ac33745c85 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 27 May 2021 14:27:20 +0200 Subject: [PATCH 123/780] squashme: don't automatically trigger an OTA --- src/ArduinoIoTCloudTCP.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 7f38bd024..842279856 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -92,8 +92,8 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _ota_cap{false} , _ota_error{static_cast(OTAError::None)} , _ota_img_sha256{"Inv."} -, _ota_url{"http://10.130.22.65/UPDATE.BIN"} -, _ota_req{true} +, _ota_url{} +, _ota_req{false} #endif /* OTA_ENABLED */ { From 08142e7dfe18e6c97905e0b7ff4ce58f2378f859 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 31 May 2021 07:14:42 +0200 Subject: [PATCH 124/780] Revert initialisation of _ota_url to empty string. --- src/ArduinoIoTCloudTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 842279856..7c9f9ef32 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -92,7 +92,7 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _ota_cap{false} , _ota_error{static_cast(OTAError::None)} , _ota_img_sha256{"Inv."} -, _ota_url{} +, _ota_url{""} , _ota_req{false} #endif /* OTA_ENABLED */ { From 171ac6d23ea56f7e739e6ca6b44c293bc9d6b55c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 31 May 2021 07:18:56 +0200 Subject: [PATCH 125/780] Cleaning up SHA256 calculation logic for better maintainability. --- src/ArduinoIoTCloudTCP.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 7c9f9ef32..b8c1c7246 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -160,7 +160,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, sha256_str += buf; }); DEBUG_VERBOSE("SHA256: %d bytes (of %d) read", bytes_read, app_size); -#else +#elif defined(ARDUINO_ARCH_SAMD) /* Calculate the SHA256 checksum over the firmware stored in the flash of the * MCU. Note: As we don't know the length per-se we read chunks of the flash * until we detect one containing only 0xFF (= flash erased). This only works @@ -171,13 +171,11 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, * The bootloader is excluded from the calculation and occupies flash address * range 0 to 0x2000, total flash size of 0x40000 bytes (256 kByte). */ -#if defined(ARDUINO_NANO_RP2040_CONNECT) -#define FLASH_BASE XIP_BASE - _ota_cap = true; + String const sha256_str = FlashSHA256::calc(0x2000, 0x40000 - 0x2000); +#elif defined(ARDUINO_NANO_RP2040_CONNECT) + String const sha256_str = FlashSHA256::calc(XIP_BASE + 0x2000, 0x40000 - 0x2000); #else -#define FLASH_BASE 0 -#endif - String const sha256_str = FlashSHA256::calc(FLASH_BASE + 0x2000, 0x40000 - 0x2000); +# error "No method for SHA256 checksum calculation over application image defined for this architecture." #endif DEBUG_VERBOSE("SHA256: HASH(%d) = %s", strlen(sha256_str.c_str()), sha256_str.c_str()); _ota_img_sha256 = sha256_str; From 48e340583dba27e9e6afb479b07870f48a59e2a3 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 31 May 2021 07:20:18 +0200 Subject: [PATCH 126/780] Signal unconditionally that the RP2040 supports OTA to the cloud. --- src/ArduinoIoTCloudTCP.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index b8c1c7246..998bb9898 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -263,6 +263,10 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, } #endif /* OTA_STORAGE_SNU */ +#if defined(ARDUINO_NANO_RP2040_CONNECT) + _ota_cap = true; +#endif + #ifdef BOARD_HAS_OFFLOADED_ECCX08 if (String(WiFi.firmwareVersion()) < String("1.4.4")) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, NINA firmware needs to be >= 1.4.4, current %s", __FUNCTION__, WiFi.firmwareVersion()); From e14a7816e085fe21aa6c6b4ed2124c563121a1f8 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 31 May 2021 07:49:43 +0200 Subject: [PATCH 127/780] Fix parameters for flash checksum calculation (used parameters were for samd architecture). --- src/ArduinoIoTCloudTCP.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 998bb9898..9988fd6eb 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -173,7 +173,10 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, */ String const sha256_str = FlashSHA256::calc(0x2000, 0x40000 - 0x2000); #elif defined(ARDUINO_NANO_RP2040_CONNECT) - String const sha256_str = FlashSHA256::calc(XIP_BASE + 0x2000, 0x40000 - 0x2000); + /* The maximum size of a RP2040 OTA update image is 1 MByte (that is 1024 * + * 1024 bytes or 0x100'000 bytes). + */ + String const sha256_str = FlashSHA256::calc(XIP_BASE, 0x100000); #else # error "No method for SHA256 checksum calculation over application image defined for this architecture." #endif From 1c783f50293a826f753e210af445dde345df8c6b Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 31 May 2021 08:04:54 +0200 Subject: [PATCH 128/780] Bugfix: Ensure that the watchdog timer thread does not run forever. In the current implementation if the OTA process fails (no reset) then the thread started to kick the watchdog timer would run forever. This does defeat the purpose of the watchdog which is only supposed to be kicked within ArduinoIoTCloud.update(). It should be enough to strategically sprinkle watchdog calls throughout the code. --- src/utility/ota/OTA-nano-rp2040.cpp | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index f91cdb6a5..2f7cd4515 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -26,21 +26,11 @@ #include "../watchdog/Watchdog.h" #include -#include /****************************************************************************** * FUNCTION DEFINITION ******************************************************************************/ -static rtos::Thread t(osPriorityHigh); - -void kick_watchdog() { - while (1) { - mbed_watchdog_reset(); - delay(2000); - } -} - /* Original code: http://stackoverflow.com/questions/2616011/easy-way-to-parse-a-url-in-c-cross-platform */ #include #include @@ -90,7 +80,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) { SFU::begin(); - t.start(kick_watchdog); + mbed_watchdog_reset(); #if 0 /* Just to be safe delete any remains from previous updates. */ @@ -118,10 +108,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) const char* host = url.host_.c_str(); - // TODO: find if the host is an IP address and treat accordingly - // IPAddress ip; - // ip.fromString(host); - //int ret = client->connect(ip, port); + mbed_watchdog_reset(); int ret = client->connect(host, port); if (!ret) @@ -130,11 +117,15 @@ int rp2040_connect_onOTARequest(char const * ota_url) return -1; /* TODO: Implement better error codes. */ } + mbed_watchdog_reset(); + client->println(String("GET ") + url.path_.c_str() + " HTTP/1.1"); client->println(String("Host: ") + host); client->println("Connection: close"); client->println(); + mbed_watchdog_reset(); + FILE * file = fopen("/ota/UPDATE.BIN", "wb"); if (!file) { @@ -146,12 +137,16 @@ int rp2040_connect_onOTARequest(char const * ota_url) String http_header; bool is_header_complete = false; - while (!client->available()) { + while (!client->available()) + { delay(10); + mbed_watchdog_reset(); } while (client->available()) { + mbed_watchdog_reset(); + char const c = client->read(); if(!is_header_complete) @@ -173,6 +168,8 @@ int rp2040_connect_onOTARequest(char const * ota_url) int const file_len = ftell(file); DEBUG_DEBUG("%s: %d bytes received", __FUNCTION__, file_len); + mbed_watchdog_reset(); + while (file_len == 0) { delay(1000); } From 1aafd84db6b305aa1088244550e1269e3d23a341 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 31 May 2021 08:09:15 +0200 Subject: [PATCH 129/780] Remove manually definition of SFU. In the early days of OTA development the SFU was used to perform a application update using a binary stored on an external SPI flash. However, this method was discarded, because it would have required for the users to purchase a MKR MEM shield additionally to their connected board. Therefore it is safe to remove the manual SFU defines from above which prevents any name collissions with the (unfortunately nambed) Nano RP2040 Connect SFU. --- src/AIoTC_Config.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 70af6b716..d76e96922 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -22,10 +22,6 @@ * USER CONFIGURABLE DEFINES ******************************************************************************/ -#ifndef OTA_STORAGE_SFU - #define OTA_STORAGE_SFU (0) -#endif - #ifndef NTP_USE_RANDOM_PORT #define NTP_USE_RANDOM_PORT (1) #endif @@ -95,7 +91,6 @@ #endif #if defined(ARDUINO_NANO_RP2040_CONNECT) - #undef OTA_STORAGE_SFU #define OTA_STORAGE_SFU (1) #else #define OTA_STORAGE_SFU (0) From 0dc6c4cc5b69941a9e51f78fbb245fa143b6e754 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 31 May 2021 08:19:06 +0200 Subject: [PATCH 130/780] Provide more meaningful (and distinct for RP2040) OTA error codes. --- src/utility/ota/OTA-nano-rp2040.cpp | 13 +++++++++---- src/utility/ota/OTA.h | 10 ++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 2f7cd4515..9e61f08fc 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -101,9 +101,12 @@ int rp2040_connect_onOTARequest(char const * ota_url) if (url.protocol_ == "http") { client = new WiFiClient(); port = 80; - } else { + } else if (url.protocol_ == "https") { client = new WiFiSSLClient(); port = 443; + } else { + DEBUG_ERROR("%s: Failed to parse OTA URL %s", __FUNCTION__, ota_url); + return static_cast(OTAError::RP2040_UrlParseError); } const char* host = url.host_.c_str(); @@ -114,7 +117,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) if (!ret) { DEBUG_ERROR("%s: Connection failure with OTA storage server %s", __FUNCTION__, host); - return -1; /* TODO: Implement better error codes. */ + return static_cast(OTAError::RP2040_ServerConnectError); } mbed_watchdog_reset(); @@ -131,7 +134,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) { DEBUG_ERROR("%s: fopen() failed", __FUNCTION__); fclose(file); - return errno; + return static_cast(OTAError::RP2040_ErrorOpenUpdateFile); } String http_header; @@ -160,7 +163,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) if (fwrite(&c, 1, sizeof(c), file) != sizeof(c)) { DEBUG_ERROR("%s: Writing of firmware image to flash failed", __FUNCTION__); - return -2; /* TODO: Find better error codes. */ + return static_cast(OTAError::RP2040_ErrorWriteUpdateFile); } } } @@ -178,6 +181,8 @@ int rp2040_connect_onOTARequest(char const * ota_url) /* Perform the reset to reboot to SxU. */ NVIC_SystemReset(); + + return static_cast(OTAError::None); } #endif /* ARDUINO_NANO_RP2040_CONNECT */ diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 9d103d053..f653c45b9 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -32,6 +32,12 @@ #include #endif /* OTA_STORAGE_SFU */ +/****************************************************************************** + * DEFINES + ******************************************************************************/ + +#define RP2040_OTA_ERROR_BASE (-100) + /****************************************************************************** * TYPEDEF ******************************************************************************/ @@ -40,6 +46,10 @@ enum class OTAError : int { None = 0, DownloadFailed = 1, + RP2040_UrlParseError = RP2040_OTA_ERROR_BASE - 0, + RP2040_ServerConnectError = RP2040_OTA_ERROR_BASE - 1, + RP2040_ErrorOpenUpdateFile = RP2040_OTA_ERROR_BASE - 2, + RP2040_ErrorWriteUpdateFile = RP2040_OTA_ERROR_BASE - 3, }; /****************************************************************************** From 5db1b978e450aad179b40ddc1c7339ef54a36dd1 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 31 May 2021 08:21:42 +0200 Subject: [PATCH 131/780] Ensure initialisation with relevant default parameters. --- src/utility/ota/OTA-nano-rp2040.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 9e61f08fc..2afde19e2 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -91,12 +91,9 @@ int rp2040_connect_onOTARequest(char const * ota_url) } #endif - Client* client; - - // TODO: eventually parse port in URL - int port; - URI url(http://github.com/ota_url); + Client * client = nullptr; + int port = 0; if (url.protocol_ == "http") { client = new WiFiClient(); From 163f84c7b54b9513a5186a4dad45ca46fc3fb458 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 31 May 2021 08:22:34 +0200 Subject: [PATCH 132/780] Replace local variable with direct access to class member string. --- src/utility/ota/OTA-nano-rp2040.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 2afde19e2..89dfea318 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -106,21 +106,19 @@ int rp2040_connect_onOTARequest(char const * ota_url) return static_cast(OTAError::RP2040_UrlParseError); } - const char* host = url.host_.c_str(); - mbed_watchdog_reset(); - int ret = client->connect(host, port); + int ret = client->connect(url.host_.c_str(), port); if (!ret) { - DEBUG_ERROR("%s: Connection failure with OTA storage server %s", __FUNCTION__, host); + DEBUG_ERROR("%s: Connection failure with OTA storage server %s", __FUNCTION__, url.host_.c_str()); return static_cast(OTAError::RP2040_ServerConnectError); } mbed_watchdog_reset(); client->println(String("GET ") + url.path_.c_str() + " HTTP/1.1"); - client->println(String("Host: ") + host); + client->println(String("Host: ") + url.host_.c_str()); client->println("Connection: close"); client->println(); From 0a60df55ffd142bf212af279c034af9ceed09f9e Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 31 May 2021 09:39:05 +0200 Subject: [PATCH 133/780] Split HTTPS-GET in 3 parts - receive header -> extract content length -> download binary. --- src/utility/ota/OTA-nano-rp2040.cpp | 55 ++++++++++++++++++++--------- src/utility/ota/OTA.h | 1 + 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 89dfea318..6e0370bd3 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -124,7 +124,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) mbed_watchdog_reset(); - FILE * file = fopen("/ota/UPDATE.BIN", "wb"); + FILE * file = fopen("/ota/UPDATE.BIN.LZSS", "wb"); if (!file) { DEBUG_ERROR("%s: fopen() failed", __FUNCTION__); @@ -132,34 +132,59 @@ int rp2040_connect_onOTARequest(char const * ota_url) return static_cast(OTAError::RP2040_ErrorOpenUpdateFile); } + /* Receive HTTP header. */ String http_header; - bool is_header_complete = false; - while (!client->available()) + for (bool is_header_complete = false; client->connected() && !is_header_complete; ) { - delay(10); mbed_watchdog_reset(); - } - - while (client->available()) - { - mbed_watchdog_reset(); - - char const c = client->read(); - if(!is_header_complete) + if (client->available()) { + char const c = client->read(); + Serial.print(c); + http_header += c; if (http_header.endsWith("\r\n\r\n")) is_header_complete = true; } - else + } + + /* Extract concent length from HTTP header. */ + int content_length_val = 0; + int const content_length_index = http_header.indexOf("Content-Length: "); + if (content_length_index > 0) + { + /* Attention: The following code is extremely ugly and needs major cleaning up. */ + String content_length; + for (char * ptr = &(http_header[content_length_index + 16]); isDigit(*ptr); ptr++) + content_length += *ptr; + + content_length_val = atoi(content_length.c_str()); + DEBUG_VERBOSE("%s: Length of OTA binary according to HTTP header = %d bytes", __FUNCTION__, content_length_val); + } + else + { + DEBUG_ERROR("%s: Failure to extract content length from http header", __FUNCTION__); + return static_cast(OTAError::RP2040_ErrorParseHttpHeader); + } + + for(int bytes_received = 0; + (bytes_received < content_length_val) && client->connected();) + { + mbed_watchdog_reset(); + + if (client->available()) { + char const c = client->read(); + if (fwrite(&c, 1, sizeof(c), file) != sizeof(c)) { DEBUG_ERROR("%s: Writing of firmware image to flash failed", __FUNCTION__); return static_cast(OTAError::RP2040_ErrorWriteUpdateFile); } + + bytes_received++; } } @@ -168,10 +193,6 @@ int rp2040_connect_onOTARequest(char const * ota_url) mbed_watchdog_reset(); - while (file_len == 0) { - delay(1000); - } - fclose(file); /* Perform the reset to reboot to SxU. */ diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index f653c45b9..e96dc6f36 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -50,6 +50,7 @@ enum class OTAError : int RP2040_ServerConnectError = RP2040_OTA_ERROR_BASE - 1, RP2040_ErrorOpenUpdateFile = RP2040_OTA_ERROR_BASE - 2, RP2040_ErrorWriteUpdateFile = RP2040_OTA_ERROR_BASE - 3, + RP2040_ErrorParseHttpHeader = RP2040_OTA_ERROR_BASE - 4, }; /****************************************************************************** From 81d68e443cc59f654a32e570cc36d6027d04ed2f Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 31 May 2021 13:44:46 +0200 Subject: [PATCH 134/780] Move watchdog feeding within the if(client->available()) check ... otherwise we might loop forever in case no data becomes available any more. --- src/utility/ota/OTA-nano-rp2040.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 6e0370bd3..c3c21768e 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -137,10 +137,10 @@ int rp2040_connect_onOTARequest(char const * ota_url) for (bool is_header_complete = false; client->connected() && !is_header_complete; ) { - mbed_watchdog_reset(); - if (client->available()) { + mbed_watchdog_reset(); + char const c = client->read(); Serial.print(c); @@ -172,10 +172,10 @@ int rp2040_connect_onOTARequest(char const * ota_url) for(int bytes_received = 0; (bytes_received < content_length_val) && client->connected();) { - mbed_watchdog_reset(); - if (client->available()) { + mbed_watchdog_reset(); + char const c = client->read(); if (fwrite(&c, 1, sizeof(c), file) != sizeof(c)) From 364319d97748fc774ae0fd21f2678a05cb0fd343 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 31 May 2021 13:46:17 +0200 Subject: [PATCH 135/780] Remove SSU (2nd stage bootloader for MKR GSM 1400) as OTA for MKR GSM has never been completed and may need a complete overhaul, mofe SFU into nano specific OTA module. --- src/utility/ota/OTA-nano-rp2040.cpp | 2 ++ src/utility/ota/OTA.h | 8 -------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index c3c21768e..f27a65934 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -27,6 +27,8 @@ #include +#include + /****************************************************************************** * FUNCTION DEFINITION ******************************************************************************/ diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index e96dc6f36..e49ba9de9 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -24,14 +24,6 @@ #include -#if OTA_STORAGE_SSU - #include -#endif /* OTA_STORAGE_SSU */ - -#if OTA_STORAGE_SFU - #include -#endif /* OTA_STORAGE_SFU */ - /****************************************************************************** * DEFINES ******************************************************************************/ From 48afe743148e63ce36de22ec88f9af88bb93f38c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 1 Jun 2021 09:30:40 +0200 Subject: [PATCH 136/780] Bugfix: Function was not working correctly when start of flash was != 0. --- src/utility/ota/FlashSHA256.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/utility/ota/FlashSHA256.cpp b/src/utility/ota/FlashSHA256.cpp index 3bdc034c9..cac4db619 100644 --- a/src/utility/ota/FlashSHA256.cpp +++ b/src/utility/ota/FlashSHA256.cpp @@ -45,11 +45,12 @@ String FlashSHA256::calc(uint32_t const start_addr, uint32_t const max_flash_siz sha256.begin(); /* Read the first two chunks of flash. */ - uint32_t flash_addr = start_addr; + uint32_t flash_addr = start_addr; + uint32_t bytes_read = 0; memcpy(chunk, reinterpret_cast(flash_addr), FLASH_READ_CHUNK_SIZE); flash_addr += FLASH_READ_CHUNK_SIZE; - for(; flash_addr < max_flash_size; flash_addr += FLASH_READ_CHUNK_SIZE) + for(; bytes_read < max_flash_size; flash_addr += FLASH_READ_CHUNK_SIZE) { /* Read the next chunk of memory. */ memcpy(next_chunk, reinterpret_cast(flash_addr), FLASH_READ_CHUNK_SIZE); @@ -75,6 +76,7 @@ String FlashSHA256::calc(uint32_t const start_addr, uint32_t const max_flash_siz } /* Update with the remaining bytes. */ sha256.update(chunk, valid_bytes_in_chunk); + bytes_read += valid_bytes_in_chunk; break; } @@ -82,6 +84,7 @@ String FlashSHA256::calc(uint32_t const start_addr, uint32_t const max_flash_siz * any erased elements, just update the SHA256 hash calcultion. */ sha256.update(chunk, FLASH_READ_CHUNK_SIZE); + bytes_read += FLASH_READ_CHUNK_SIZE; /* Copy next_chunk to chunk. */ memcpy(chunk, next_chunk, FLASH_READ_CHUNK_SIZE); @@ -100,7 +103,7 @@ String FlashSHA256::calc(uint32_t const start_addr, uint32_t const max_flash_siz sha256_str += buf; }); /* Do some debug printout. */ - DEBUG_VERBOSE("SHA256: %d bytes read", flash_addr); + DEBUG_VERBOSE("SHA256: %d bytes read", bytes_read); return sha256_str; } From cdadeffcd27e622c6d38d5bb92d945f97e591a6f Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 1 Jun 2021 09:38:07 +0200 Subject: [PATCH 137/780] Cleaning up. --- src/utility/ota/OTA-nano-rp2040.cpp | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index f27a65934..82a3a32a4 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -82,16 +82,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) { SFU::begin(); - mbed_watchdog_reset(); - -#if 0 - /* Just to be safe delete any remains from previous updates. */ - struct stat st; - int err = stat("/ota/UPDATE.BIN", &st); - if (err == 0) { - remove("/ota/UPDATE.BIN"); - } -#endif + mbed_watchdog_reset(); URI url(http://github.com/ota_url); Client * client = nullptr; @@ -136,7 +127,6 @@ int rp2040_connect_onOTARequest(char const * ota_url) /* Receive HTTP header. */ String http_header; - for (bool is_header_complete = false; client->connected() && !is_header_complete; ) { if (client->available()) @@ -168,6 +158,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) else { DEBUG_ERROR("%s: Failure to extract content length from http header", __FUNCTION__); + fclose(file); return static_cast(OTAError::RP2040_ErrorParseHttpHeader); } @@ -183,6 +174,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) if (fwrite(&c, 1, sizeof(c), file) != sizeof(c)) { DEBUG_ERROR("%s: Writing of firmware image to flash failed", __FUNCTION__); + fclose(file); return static_cast(OTAError::RP2040_ErrorWriteUpdateFile); } @@ -190,12 +182,10 @@ int rp2040_connect_onOTARequest(char const * ota_url) } } + /* Determine length. */ int const file_len = ftell(file); - DEBUG_DEBUG("%s: %d bytes received", __FUNCTION__, file_len); - - mbed_watchdog_reset(); - fclose(file); + DEBUG_DEBUG("%s: %d bytes received", __FUNCTION__, file_len); /* Perform the reset to reboot to SxU. */ NVIC_SystemReset(); From fc64b0a385a561dff824f20f45226b365a68e8d1 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 1 Jun 2021 10:07:39 +0200 Subject: [PATCH 138/780] Simplify extraction logic for HTTP header content length. --- src/utility/ota/OTA-nano-rp2040.cpp | 33 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 82a3a32a4..cb85e9508 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -134,7 +134,6 @@ int rp2040_connect_onOTARequest(char const * ota_url) mbed_watchdog_reset(); char const c = client->read(); - Serial.print(c); http_header += c; if (http_header.endsWith("\r\n\r\n")) @@ -142,26 +141,26 @@ int rp2040_connect_onOTARequest(char const * ota_url) } } - /* Extract concent length from HTTP header. */ - int content_length_val = 0; - int const content_length_index = http_header.indexOf("Content-Length: "); - if (content_length_index > 0) + /* Extract concent length from HTTP header. A typical entry looks like + * "Content-Length: 123456" + */ + char const * content_length_ptr = strstr(http_header.c_str(), "Content-Length"); + if (!content_length_ptr) { - /* Attention: The following code is extremely ugly and needs major cleaning up. */ - String content_length; - for (char * ptr = &(http_header[content_length_index + 16]); isDigit(*ptr); ptr++) - content_length += *ptr; - - content_length_val = atoi(content_length.c_str()); - DEBUG_VERBOSE("%s: Length of OTA binary according to HTTP header = %d bytes", __FUNCTION__, content_length_val); - } - else - { - DEBUG_ERROR("%s: Failure to extract content length from http header", __FUNCTION__); fclose(file); + DEBUG_ERROR("%s: Failure to extract content length from http header", __FUNCTION__); return static_cast(OTAError::RP2040_ErrorParseHttpHeader); } - + /* Find start of numerical value. */ + char * ptr = const_cast(content_length_ptr); + for (; (*ptr != '\0') && !isDigit(*ptr); ptr++) { } + /* Extract numerical value. */ + String content_length_str; + for (; isDigit(*ptr); ptr++) content_length_str += *ptr; + int const content_length_val = atoi(content_length_str.c_str()); + DEBUG_VERBOSE("%s: Length of OTA binary according to HTTP header = %d bytes", __FUNCTION__, content_length_val); + + /* Receive as many bytes as are indicated by the HTTP header - or die trying. */ for(int bytes_received = 0; (bytes_received < content_length_val) && client->connected();) { From 421eb9d7a26924f0f1fa3110a623446543c95976 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 1 Jun 2021 10:11:19 +0200 Subject: [PATCH 139/780] Disable verbose debug output in production. --- src/AIoTC_Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index d76e96922..94297350f 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -62,7 +62,7 @@ # if defined(ARDUINO_AVR_UNO_WIFI_REV2) # define DEBUG_VERBOSE(fmt, ...) # else -# define DEBUG_VERBOSE(fmt, ...) Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) +# define DEBUG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) # endif #endif From 6b1e802b52856cde89ff790624ce6b49318b47b7 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 2 Jun 2021 09:15:50 +0200 Subject: [PATCH 140/780] Replace verification if connected() with a time-out check. Otherwise it might happen that the connection has been terminated by the server, although not all available data has been read from the NINA. --- src/utility/ota/OTA-nano-rp2040.cpp | 31 +++++++++++++++++++++++++---- src/utility/ota/OTA.h | 8 +++++--- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index cb85e9508..74d702593 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -82,6 +82,8 @@ int rp2040_connect_onOTARequest(char const * ota_url) { SFU::begin(); + remove("/ota/UPDATE.BIN.LZSS"); + mbed_watchdog_reset(); URI url(http://github.com/ota_url); @@ -127,8 +129,13 @@ int rp2040_connect_onOTARequest(char const * ota_url) /* Receive HTTP header. */ String http_header; - for (bool is_header_complete = false; client->connected() && !is_header_complete; ) + bool is_header_complete = false, + is_http_header_timeout = false; + for (unsigned long const start = millis(); !is_header_complete;) { + is_http_header_timeout = (millis() - start) > (10*1000); + if (is_http_header_timeout) break; + if (client->available()) { mbed_watchdog_reset(); @@ -141,6 +148,12 @@ int rp2040_connect_onOTARequest(char const * ota_url) } } + if (!is_header_complete) { + fclose(file); + DEBUG_ERROR("%s: Error receiving HTTP header %s", __FUNCTION__, is_http_header_timeout ? "(timeout)":""); + return static_cast(OTAError::RP2040_HttpHeaderError); + } + /* Extract concent length from HTTP header. A typical entry looks like * "Content-Length: 123456" */ @@ -161,9 +174,13 @@ int rp2040_connect_onOTARequest(char const * ota_url) DEBUG_VERBOSE("%s: Length of OTA binary according to HTTP header = %d bytes", __FUNCTION__, content_length_val); /* Receive as many bytes as are indicated by the HTTP header - or die trying. */ - for(int bytes_received = 0; - (bytes_received < content_length_val) && client->connected();) + int bytes_received = 0; + bool is_http_data_timeout = false; + for(unsigned long const start = millis(); bytes_received < content_length_val;) { + is_http_data_timeout = (millis() - start) > (60*1000); + if (is_http_data_timeout) break; + if (client->available()) { mbed_watchdog_reset(); @@ -181,10 +198,16 @@ int rp2040_connect_onOTARequest(char const * ota_url) } } + if (bytes_received != content_length_val) { + fclose(file); + DEBUG_ERROR("%s: Error receiving HTTP data %s (%d bytes received, %d expected)", __FUNCTION__, is_http_data_timeout ? "(timeout)":"", bytes_received, content_length_val); + return static_cast(OTAError::RP2040_HttpDataError); + } + /* Determine length. */ int const file_len = ftell(file); fclose(file); - DEBUG_DEBUG("%s: %d bytes received", __FUNCTION__, file_len); + DEBUG_DEBUG("%s: %d bytes received (%d expected)", __FUNCTION__, file_len, content_length_val); /* Perform the reset to reboot to SxU. */ NVIC_SystemReset(); diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index e49ba9de9..cb0d7183e 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -40,9 +40,11 @@ enum class OTAError : int DownloadFailed = 1, RP2040_UrlParseError = RP2040_OTA_ERROR_BASE - 0, RP2040_ServerConnectError = RP2040_OTA_ERROR_BASE - 1, - RP2040_ErrorOpenUpdateFile = RP2040_OTA_ERROR_BASE - 2, - RP2040_ErrorWriteUpdateFile = RP2040_OTA_ERROR_BASE - 3, - RP2040_ErrorParseHttpHeader = RP2040_OTA_ERROR_BASE - 4, + RP2040_HttpHeaderError = RP2040_OTA_ERROR_BASE - 2, + RP2040_HttpDataError = RP2040_OTA_ERROR_BASE - 3, + RP2040_ErrorOpenUpdateFile = RP2040_OTA_ERROR_BASE - 4, + RP2040_ErrorWriteUpdateFile = RP2040_OTA_ERROR_BASE - 5, + RP2040_ErrorParseHttpHeader = RP2040_OTA_ERROR_BASE - 6, }; /****************************************************************************** From 756a64af30faa7481008a59d25dca1931fcbec02 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 2 Jun 2021 09:17:09 +0200 Subject: [PATCH 141/780] After the implementation of a time-out logic in the previous commit it makes sense to feed the watchdog within the main-loop body since the timeout will terminate the loop anyway. --- src/utility/ota/OTA-nano-rp2040.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 74d702593..14bbee2ed 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -136,10 +136,10 @@ int rp2040_connect_onOTARequest(char const * ota_url) is_http_header_timeout = (millis() - start) > (10*1000); if (is_http_header_timeout) break; + mbed_watchdog_reset(); + if (client->available()) { - mbed_watchdog_reset(); - char const c = client->read(); http_header += c; @@ -181,10 +181,10 @@ int rp2040_connect_onOTARequest(char const * ota_url) is_http_data_timeout = (millis() - start) > (60*1000); if (is_http_data_timeout) break; + mbed_watchdog_reset(); + if (client->available()) { - mbed_watchdog_reset(); - char const c = client->read(); if (fwrite(&c, 1, sizeof(c), file) != sizeof(c)) From b13a560668d400398767692359c5de52c9861de4 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 2 Jun 2021 09:21:20 +0200 Subject: [PATCH 142/780] Replace magic RP2040 OTA timeout values with sensibly named constants. --- src/utility/ota/OTA-nano-rp2040.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 14bbee2ed..8d17c8289 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -133,7 +133,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) is_http_header_timeout = false; for (unsigned long const start = millis(); !is_header_complete;) { - is_http_header_timeout = (millis() - start) > (10*1000); + is_http_header_timeout = (millis() - start) > AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms; if (is_http_header_timeout) break; mbed_watchdog_reset(); @@ -178,7 +178,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) bool is_http_data_timeout = false; for(unsigned long const start = millis(); bytes_received < content_length_val;) { - is_http_data_timeout = (millis() - start) > (60*1000); + is_http_data_timeout = (millis() - start) > AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms; if (is_http_data_timeout) break; mbed_watchdog_reset(); From 867a6acb9234cfd90e6156f4254ead7e0c65ae53 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 2 Jun 2021 09:24:17 +0200 Subject: [PATCH 143/780] Replace magic RP2040 OTA timeout values with sensibly named constants. --- src/AIoTC_Config.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 94297350f..60f5b5296 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -145,4 +145,7 @@ #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) +#define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10000UL) +#define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (60000UL) + #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From c65bd2b444c07d48d06774713a4b419448967ae8 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 2 Jun 2021 09:26:55 +0200 Subject: [PATCH 144/780] Move opening of update file to the very beginning of the OTA function (makes error handling easier - see next step). --- src/utility/ota/OTA-nano-rp2040.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 8d17c8289..f09e59cd8 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -80,9 +80,19 @@ void URI::parse(const string& url_s) int rp2040_connect_onOTARequest(char const * ota_url) { + mbed_watchdog_reset(); + SFU::begin(); - remove("/ota/UPDATE.BIN.LZSS"); + mbed_watchdog_reset(); + + FILE * file = fopen("/ota/UPDATE.BIN.LZSS", "wb"); + if (!file) + { + DEBUG_ERROR("%s: fopen() failed", __FUNCTION__); + fclose(file); + return static_cast(OTAError::RP2040_ErrorOpenUpdateFile); + } mbed_watchdog_reset(); @@ -103,9 +113,9 @@ int rp2040_connect_onOTARequest(char const * ota_url) mbed_watchdog_reset(); - int ret = client->connect(url.host_.c_str(), port); - if (!ret) + if (!client->connect(url.host_.c_str(), port)) { + fclose(file); DEBUG_ERROR("%s: Connection failure with OTA storage server %s", __FUNCTION__, url.host_.c_str()); return static_cast(OTAError::RP2040_ServerConnectError); } @@ -119,14 +129,6 @@ int rp2040_connect_onOTARequest(char const * ota_url) mbed_watchdog_reset(); - FILE * file = fopen("/ota/UPDATE.BIN.LZSS", "wb"); - if (!file) - { - DEBUG_ERROR("%s: fopen() failed", __FUNCTION__); - fclose(file); - return static_cast(OTAError::RP2040_ErrorOpenUpdateFile); - } - /* Receive HTTP header. */ String http_header; bool is_header_complete = false, From 6672d0e8e4a0d1909b4ca98e348f841b925c04c1 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 2 Jun 2021 09:38:13 +0200 Subject: [PATCH 145/780] Cleanup error handling to follow the same format in the whole function (debug message, fclose, return error) --- src/utility/ota/OTA-nano-rp2040.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index f09e59cd8..d49fe8a42 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -108,6 +108,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) port = 443; } else { DEBUG_ERROR("%s: Failed to parse OTA URL %s", __FUNCTION__, ota_url); + fclose(file); return static_cast(OTAError::RP2040_UrlParseError); } @@ -115,8 +116,8 @@ int rp2040_connect_onOTARequest(char const * ota_url) if (!client->connect(url.host_.c_str(), port)) { - fclose(file); DEBUG_ERROR("%s: Connection failure with OTA storage server %s", __FUNCTION__, url.host_.c_str()); + fclose(file); return static_cast(OTAError::RP2040_ServerConnectError); } @@ -150,9 +151,10 @@ int rp2040_connect_onOTARequest(char const * ota_url) } } - if (!is_header_complete) { - fclose(file); + if (!is_header_complete) + { DEBUG_ERROR("%s: Error receiving HTTP header %s", __FUNCTION__, is_http_header_timeout ? "(timeout)":""); + fclose(file); return static_cast(OTAError::RP2040_HttpHeaderError); } @@ -162,8 +164,8 @@ int rp2040_connect_onOTARequest(char const * ota_url) char const * content_length_ptr = strstr(http_header.c_str(), "Content-Length"); if (!content_length_ptr) { - fclose(file); DEBUG_ERROR("%s: Failure to extract content length from http header", __FUNCTION__); + fclose(file); return static_cast(OTAError::RP2040_ErrorParseHttpHeader); } /* Find start of numerical value. */ @@ -201,8 +203,8 @@ int rp2040_connect_onOTARequest(char const * ota_url) } if (bytes_received != content_length_val) { - fclose(file); DEBUG_ERROR("%s: Error receiving HTTP data %s (%d bytes received, %d expected)", __FUNCTION__, is_http_data_timeout ? "(timeout)":"", bytes_received, content_length_val); + fclose(file); return static_cast(OTAError::RP2040_HttpDataError); } From 4a3ff5e63cb358ea21570f3c01737397123d8e03 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 2 Jun 2021 10:22:44 +0200 Subject: [PATCH 146/780] Increase timeout values for HTTPS-GET data download to flash. --- src/AIoTC_Config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 60f5b5296..9ceb2ac62 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -145,7 +145,7 @@ #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) -#define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10000UL) -#define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (60000UL) +#define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) +#define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 92168d0a6bea40bac70e8e5f31dee2abe1854b46 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 2 Jun 2021 10:23:26 +0200 Subject: [PATCH 147/780] Removing irrelevant debug output. --- src/utility/ota/OTA-nano-rp2040.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index d49fe8a42..419849967 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -208,12 +208,9 @@ int rp2040_connect_onOTARequest(char const * ota_url) return static_cast(OTAError::RP2040_HttpDataError); } - /* Determine length. */ - int const file_len = ftell(file); + /* Perform the reset to reboot to SFU. */ + DEBUG_INFO("%s: %d bytes received", __FUNCTION__, ftell(file)); fclose(file); - DEBUG_DEBUG("%s: %d bytes received (%d expected)", __FUNCTION__, file_len, content_length_val); - - /* Perform the reset to reboot to SxU. */ NVIC_SystemReset(); return static_cast(OTAError::None); From 0e386a1faa80a39a02623ee4b582d66f485efeb3 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 2 Jun 2021 11:55:51 +0200 Subject: [PATCH 148/780] Temp - Remove later - erase flash within OTA handler. --- src/AIoTC_Config.h | 2 +- src/utility/ota/OTA-nano-rp2040.cpp | 28 +++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 9ceb2ac62..6df348af8 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -62,7 +62,7 @@ # if defined(ARDUINO_AVR_UNO_WIFI_REV2) # define DEBUG_VERBOSE(fmt, ...) # else -# define DEBUG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) +# define DEBUG_VERBOSE(fmt, ...) Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) # endif #endif diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 419849967..972c2718f 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -29,6 +29,10 @@ #include +#include "mbed.h" +#include "FATFileSystem.h" +#include "FlashIAPBlockDevice.h" + /****************************************************************************** * FUNCTION DEFINITION ******************************************************************************/ @@ -82,7 +86,28 @@ int rp2040_connect_onOTARequest(char const * ota_url) { mbed_watchdog_reset(); - SFU::begin(); + //SFU::begin(); + + int err = -1; + FlashIAPBlockDevice flash(XIP_BASE + 0xF00000, 0x100000); + if ((err = flash.init()) < 0) + { + DEBUG_ERROR("%s: flash.init() failed with %d", __FUNCTION__, err); + return err; + } + + mbed_watchdog_reset(); + + flash.erase(XIP_BASE + 0xF00000, 0x100000); + + mbed_watchdog_reset(); + + mbed::FATFileSystem fs("ota"); + if ((err = fs.mount(&flash)) != 0) + { + DEBUG_ERROR("%s: fs.mount() failed with %d", __FUNCTION__, err); + return err; + } mbed_watchdog_reset(); @@ -199,6 +224,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) } bytes_received++; + DEBUG_VERBOSE("%d", bytes_received); } } From 4f89f35e6b81d24cf58939117cc1344829ab8bf9 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 3 Jun 2021 22:56:58 +0200 Subject: [PATCH 149/780] Trigger a watchdog reset to start SFU --- src/utility/ota/OTA-nano-rp2040.cpp | 3 ++- src/utility/watchdog/Watchdog.cpp | 21 +++++++++++++++++++++ src/utility/watchdog/Watchdog.h | 1 + 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 972c2718f..2226e7d62 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -237,7 +237,8 @@ int rp2040_connect_onOTARequest(char const * ota_url) /* Perform the reset to reboot to SFU. */ DEBUG_INFO("%s: %d bytes received", __FUNCTION__, ftell(file)); fclose(file); - NVIC_SystemReset(); + //NVIC_SystemReset(); + mbed_watchdog_trigger_reset(); return static_cast(OTAError::None); } diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 14c5d68e6..edf2be5ca 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -110,4 +110,25 @@ void mbed_watchdog_reset() hal_watchdog_kick(); } } + +void mbed_watchdog_trigger_reset() +{ + watchdog_config_t cfg; +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + cfg.timeout_ms = 1; +#elif defined(ARDUINO_NANO_RP2040_CONNECT) + cfg.timeout_ms = 1; +#else +# error "You need to define the maximum possible timeout for this architecture." +#endif + + if (hal_watchdog_init(&cfg) == WATCHDOG_STATUS_OK) { + is_watchdog_enabled = true; + } + else { + DEBUG_WARNING("%s: watchdog could not be reconfigured", __FUNCTION__); + } + + while(1){} +} #endif /* ARDUINO_ARCH_MBED */ diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index 91161d072..e1c8d2c27 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -30,6 +30,7 @@ void samd_watchdog_reset(); #ifdef ARDUINO_ARCH_MBED void mbed_watchdog_enable(); void mbed_watchdog_reset(); +void mbed_watchdog_trigger_reset(); #endif /* ARDUINO_ARCH_MBED */ #endif /* ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ */ From fc5dd4f3ef4715efe5a476b08fa31c5bceca48eb Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 4 Jun 2021 08:11:47 +0200 Subject: [PATCH 150/780] Cleaning up missing comments. --- src/utility/ota/OTA-nano-rp2040.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 2226e7d62..dd9938cec 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -86,8 +86,6 @@ int rp2040_connect_onOTARequest(char const * ota_url) { mbed_watchdog_reset(); - //SFU::begin(); - int err = -1; FlashIAPBlockDevice flash(XIP_BASE + 0xF00000, 0x100000); if ((err = flash.init()) < 0) @@ -224,7 +222,6 @@ int rp2040_connect_onOTARequest(char const * ota_url) } bytes_received++; - DEBUG_VERBOSE("%d", bytes_received); } } @@ -237,7 +234,6 @@ int rp2040_connect_onOTARequest(char const * ota_url) /* Perform the reset to reboot to SFU. */ DEBUG_INFO("%s: %d bytes received", __FUNCTION__, ftell(file)); fclose(file); - //NVIC_SystemReset(); mbed_watchdog_trigger_reset(); return static_cast(OTAError::None); From 06267fbf1f27fb20d8419fb5f01bf746eb75fd29 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 4 Jun 2021 08:30:15 +0200 Subject: [PATCH 151/780] Unmount before performing a reset. --- src/utility/ota/OTA-nano-rp2040.cpp | 14 +++++++++++--- src/utility/ota/OTA.h | 3 +++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index dd9938cec..8d228cc01 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -91,7 +91,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) if ((err = flash.init()) < 0) { DEBUG_ERROR("%s: flash.init() failed with %d", __FUNCTION__, err); - return err; + return static_cast(OTAError::RP2040_ErrorFlashInit); } mbed_watchdog_reset(); @@ -104,7 +104,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) if ((err = fs.mount(&flash)) != 0) { DEBUG_ERROR("%s: fs.mount() failed with %d", __FUNCTION__, err); - return err; + return static_cast(OTAError::RP2040_ErrorMount); } mbed_watchdog_reset(); @@ -231,9 +231,17 @@ int rp2040_connect_onOTARequest(char const * ota_url) return static_cast(OTAError::RP2040_HttpDataError); } - /* Perform the reset to reboot to SFU. */ DEBUG_INFO("%s: %d bytes received", __FUNCTION__, ftell(file)); fclose(file); + + /* Unmount the filesystem. */ + if ((err = fs.unmount()) != 0) + { + DEBUG_ERROR("%s: fs.unmount() failed with %d", __FUNCTION__, err); + return static_cast(OTAError::RP2040_ErrorUnmount); + } + + /* Perform the reset to reboot to SFU. */ mbed_watchdog_trigger_reset(); return static_cast(OTAError::None); diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index cb0d7183e..6926c2e36 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -45,6 +45,9 @@ enum class OTAError : int RP2040_ErrorOpenUpdateFile = RP2040_OTA_ERROR_BASE - 4, RP2040_ErrorWriteUpdateFile = RP2040_OTA_ERROR_BASE - 5, RP2040_ErrorParseHttpHeader = RP2040_OTA_ERROR_BASE - 6, + RP2040_ErrorFlashInit = RP2040_OTA_ERROR_BASE - 7, + RP2040_ErrorMount = RP2040_OTA_ERROR_BASE - 8, + RP2040_ErrorUnmount = RP2040_OTA_ERROR_BASE - 9, }; /****************************************************************************** From 94ff8979b1607448b2674a8fe99f9bcd2d98df4d Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 4 Jun 2021 08:36:55 +0200 Subject: [PATCH 152/780] Replace mount() with reformat() which results in a reformatted and mounted file-format - now we can be super sure to have a clean set-up. https://os.mbed.com/docs/mbed-os/v6.11/mbed-os-api-doxy/classmbed_1_1_f_a_t_file_system.html#a6bb5160b6665359b9411ebc65aaa5308 --- src/utility/ota/OTA-nano-rp2040.cpp | 6 +++--- src/utility/ota/OTA.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 8d228cc01..e47a4dcea 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -101,10 +101,10 @@ int rp2040_connect_onOTARequest(char const * ota_url) mbed_watchdog_reset(); mbed::FATFileSystem fs("ota"); - if ((err = fs.mount(&flash)) != 0) + if ((err = fs.reformat(&flash)) != 0) { - DEBUG_ERROR("%s: fs.mount() failed with %d", __FUNCTION__, err); - return static_cast(OTAError::RP2040_ErrorMount); + DEBUG_ERROR("%s: fs.reformat() failed with %d", __FUNCTION__, err); + return static_cast(OTAError::RP2040_ErrorReformat); } mbed_watchdog_reset(); diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 6926c2e36..bc92dede1 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -46,7 +46,7 @@ enum class OTAError : int RP2040_ErrorWriteUpdateFile = RP2040_OTA_ERROR_BASE - 5, RP2040_ErrorParseHttpHeader = RP2040_OTA_ERROR_BASE - 6, RP2040_ErrorFlashInit = RP2040_OTA_ERROR_BASE - 7, - RP2040_ErrorMount = RP2040_OTA_ERROR_BASE - 8, + RP2040_ErrorReformat = RP2040_OTA_ERROR_BASE - 8, RP2040_ErrorUnmount = RP2040_OTA_ERROR_BASE - 9, }; From 679118cef0bd7bb00877651a0216c8f3a02c2d29 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 4 Jun 2021 11:58:24 +0200 Subject: [PATCH 153/780] Avoid infinite loop if we fail to enable/reconfigure watchdog --- src/utility/ota/OTA-nano-rp2040.cpp | 2 ++ src/utility/watchdog/Watchdog.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index e47a4dcea..8e0c3106b 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -243,6 +243,8 @@ int rp2040_connect_onOTARequest(char const * ota_url) /* Perform the reset to reboot to SFU. */ mbed_watchdog_trigger_reset(); + /* If watchdog is enabled we should not reach this point */ + NVIC_SystemReset(); return static_cast(OTAError::None); } diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index edf2be5ca..314e12e18 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -124,11 +124,11 @@ void mbed_watchdog_trigger_reset() if (hal_watchdog_init(&cfg) == WATCHDOG_STATUS_OK) { is_watchdog_enabled = true; + while(1){} } else { DEBUG_WARNING("%s: watchdog could not be reconfigured", __FUNCTION__); } - while(1){} } #endif /* ARDUINO_ARCH_MBED */ From 5ee73f7eed0fc9bc6a67a8ee7233b95397d50a11 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 7 Jun 2021 11:39:59 +0200 Subject: [PATCH 154/780] Add watchdog reset after each step of CloudTCP state machine to avoid unwanted resets --- src/ArduinoIoTCloudTCP.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 9988fd6eb..68347d97c 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -320,6 +320,16 @@ void ArduinoIoTCloudTCP::update() } _state = next_state; + /* This watchdog feed is actually needed only by the RP2040 CONNECT cause its + * maximum watchdog window is 8388ms; despite this we feed it for all + * supported ARCH to keep code aligned. + */ +#ifdef ARDUINO_ARCH_SAMD + samd_watchdog_reset(); +#elif defined(ARDUINO_ARCH_MBED) + mbed_watchdog_reset(); +#endif + /* Check for new data from the MQTT client. */ if (_mqttClient.connected()) _mqttClient.poll(); From a212ef81332df7b667db60f9896a2968ee471777 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 7 Jun 2021 14:21:52 +0200 Subject: [PATCH 155/780] Disable verbose debug output in production. --- src/AIoTC_Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 6df348af8..9ceb2ac62 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -62,7 +62,7 @@ # if defined(ARDUINO_AVR_UNO_WIFI_REV2) # define DEBUG_VERBOSE(fmt, ...) # else -# define DEBUG_VERBOSE(fmt, ...) Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) +# define DEBUG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) # endif #endif From 1b4168fad4040afea36d30995fc0d6083cf6eccc Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 8 Jun 2021 09:42:14 +0200 Subject: [PATCH 156/780] Fix NANO_RP2040 maximum watchdog timeout. WD register load value gets saturated to 16777215 --- src/ArduinoIoTCloudTCP.cpp | 2 +- src/utility/watchdog/Watchdog.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 68347d97c..0197c34db 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -321,7 +321,7 @@ void ArduinoIoTCloudTCP::update() _state = next_state; /* This watchdog feed is actually needed only by the RP2040 CONNECT cause its - * maximum watchdog window is 8388ms; despite this we feed it for all + * maximum watchdog window is 8389ms; despite this we feed it for all * supported ARCH to keep code aligned. */ #ifdef ARDUINO_ARCH_SAMD diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 314e12e18..6b9a66af0 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -35,7 +35,7 @@ #ifdef ARDUINO_ARCH_MBED # include # define PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms (32760) -# define NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms (32760) +# define NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms (8389) #endif /* ARDUINO_ARCH_MBED */ /****************************************************************************** From 936b75ca06262c232dcf685a170ee8b65beb946d Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 8 Jun 2021 11:25:16 +0200 Subject: [PATCH 157/780] Replace architecture specific watchdog handling functions with an unique implementation that takes care of the different architectures --- src/ArduinoIoTCloudTCP.cpp | 20 ++++++-------------- src/utility/ota/OTA-nano-rp2040.cpp | 20 ++++++++++---------- src/utility/ota/OTA-portenta-h7.cpp | 12 ++++++------ src/utility/ota/OTA-samd.cpp | 4 ++-- src/utility/watchdog/Watchdog.cpp | 28 ++++++++++++++++++++++++---- src/utility/watchdog/Watchdog.h | 10 ++++------ 6 files changed, 52 insertions(+), 42 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 0197c34db..3d6ba59cb 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -282,13 +282,9 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, * call to ArduinoIoTCloudTCP::update() it is wise to * set a rather large timeout at first. */ -#ifdef ARDUINO_ARCH_SAMD - if (enable_watchdog) { - samd_watchdog_enable(); - } -#elif defined(ARDUINO_ARCH_MBED) +#if defined (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) if (enable_watchdog) { - mbed_watchdog_enable(); + watchdog_enable(); } #endif @@ -300,10 +296,8 @@ void ArduinoIoTCloudTCP::update() /* Feed the watchdog. If any of the functions called below * get stuck than we can at least reset and recover. */ -#ifdef ARDUINO_ARCH_SAMD - samd_watchdog_reset(); -#elif defined(ARDUINO_ARCH_MBED) - mbed_watchdog_reset(); +#if defined (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) + watchdog_reset(); #endif @@ -324,10 +318,8 @@ void ArduinoIoTCloudTCP::update() * maximum watchdog window is 8389ms; despite this we feed it for all * supported ARCH to keep code aligned. */ -#ifdef ARDUINO_ARCH_SAMD - samd_watchdog_reset(); -#elif defined(ARDUINO_ARCH_MBED) - mbed_watchdog_reset(); +#if defined (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) + watchdog_reset(); #endif /* Check for new data from the MQTT client. */ diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 8e0c3106b..48071be7c 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -84,7 +84,7 @@ void URI::parse(const string& url_s) int rp2040_connect_onOTARequest(char const * ota_url) { - mbed_watchdog_reset(); + watchdog_reset(); int err = -1; FlashIAPBlockDevice flash(XIP_BASE + 0xF00000, 0x100000); @@ -94,11 +94,11 @@ int rp2040_connect_onOTARequest(char const * ota_url) return static_cast(OTAError::RP2040_ErrorFlashInit); } - mbed_watchdog_reset(); + watchdog_reset(); flash.erase(XIP_BASE + 0xF00000, 0x100000); - mbed_watchdog_reset(); + watchdog_reset(); mbed::FATFileSystem fs("ota"); if ((err = fs.reformat(&flash)) != 0) @@ -107,7 +107,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) return static_cast(OTAError::RP2040_ErrorReformat); } - mbed_watchdog_reset(); + watchdog_reset(); FILE * file = fopen("/ota/UPDATE.BIN.LZSS", "wb"); if (!file) @@ -117,7 +117,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) return static_cast(OTAError::RP2040_ErrorOpenUpdateFile); } - mbed_watchdog_reset(); + watchdog_reset(); URI url(http://github.com/ota_url); Client * client = nullptr; @@ -135,7 +135,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) return static_cast(OTAError::RP2040_UrlParseError); } - mbed_watchdog_reset(); + watchdog_reset(); if (!client->connect(url.host_.c_str(), port)) { @@ -144,14 +144,14 @@ int rp2040_connect_onOTARequest(char const * ota_url) return static_cast(OTAError::RP2040_ServerConnectError); } - mbed_watchdog_reset(); + watchdog_reset(); client->println(String("GET ") + url.path_.c_str() + " HTTP/1.1"); client->println(String("Host: ") + url.host_.c_str()); client->println("Connection: close"); client->println(); - mbed_watchdog_reset(); + watchdog_reset(); /* Receive HTTP header. */ String http_header; @@ -162,7 +162,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) is_http_header_timeout = (millis() - start) > AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms; if (is_http_header_timeout) break; - mbed_watchdog_reset(); + watchdog_reset(); if (client->available()) { @@ -208,7 +208,7 @@ int rp2040_connect_onOTARequest(char const * ota_url) is_http_data_timeout = (millis() - start) > AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms; if (is_http_data_timeout) break; - mbed_watchdog_reset(); + watchdog_reset(); if (client->available()) { diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index b8ec0772a..7c6a01eb9 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -34,13 +34,13 @@ int portenta_h7_onOTARequest(char const * ota_url) { - mbed_watchdog_reset(); + watchdog_reset(); Arduino_Portenta_OTA::Error ota_portenta_err = Arduino_Portenta_OTA::Error::None; /* Use 2nd partition of QSPI (1st partition contains WiFi firmware) */ Arduino_Portenta_OTA_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2); - mbed_watchdog_reset(); + watchdog_reset(); /* Initialize the QSPI memory for OTA handling. */ if((ota_portenta_err = ota_portenta_qspi.begin()) != Arduino_Portenta_OTA::Error::None) { @@ -48,19 +48,19 @@ int portenta_h7_onOTARequest(char const * ota_url) return static_cast(ota_portenta_err); } - mbed_watchdog_reset(); + watchdog_reset(); /* Just to be safe delete any remains from previous updates. */ remove("/fs/UPDATE.BIN"); remove("/fs/UPDATE.BIN.LZSS"); - mbed_watchdog_reset(); + watchdog_reset(); /* Download the OTA file from the web storage location. */ int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download(ota_url, true /* is_https */); DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::download(%s) returns %d", ota_url, ota_portenta_qspi_download_ret_code); - mbed_watchdog_reset(); + watchdog_reset(); /* Decompress the LZSS compressed OTA file. */ int const ota_portenta_qspi_decompress_ret_code = ota_portenta_qspi.decompress(); @@ -71,7 +71,7 @@ int portenta_h7_onOTARequest(char const * ota_url) return ota_portenta_qspi_decompress_ret_code; } - mbed_watchdog_reset(); + watchdog_reset(); /* Schedule the firmware update. */ if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) { diff --git a/src/utility/ota/OTA-samd.cpp b/src/utility/ota/OTA-samd.cpp index c5ee8a8d5..f555415b8 100644 --- a/src/utility/ota/OTA-samd.cpp +++ b/src/utility/ota/OTA-samd.cpp @@ -38,14 +38,14 @@ int samd_onOTARequest(char const * ota_url) { - samd_watchdog_reset(); + watchdog_reset(); #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"); - samd_watchdog_reset(); + watchdog_reset(); /* Trigger direct download to nina module. */ uint8_t nina_ota_err_code = 0; diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 6b9a66af0..e2a9e0fe9 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -49,13 +49,13 @@ static bool is_watchdog_enabled = false; ******************************************************************************/ #ifdef ARDUINO_ARCH_SAMD -void samd_watchdog_enable() +static void samd_watchdog_enable() { is_watchdog_enabled = true; Watchdog.enable(SAMD_WATCHDOG_MAX_TIME_ms); } -void samd_watchdog_reset() +static void samd_watchdog_reset() { if (is_watchdog_enabled) { Watchdog.reset(); @@ -85,7 +85,7 @@ void mkr_nb_feed_watchdog() #endif /* ARDUINO_ARCH_SAMD */ #ifdef ARDUINO_ARCH_MBED -void mbed_watchdog_enable() +static void mbed_watchdog_enable() { watchdog_config_t cfg; #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) @@ -104,7 +104,7 @@ void mbed_watchdog_enable() } } -void mbed_watchdog_reset() +static void mbed_watchdog_reset() { if (is_watchdog_enabled) { hal_watchdog_kick(); @@ -132,3 +132,23 @@ void mbed_watchdog_trigger_reset() } #endif /* ARDUINO_ARCH_MBED */ + +#if defined (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) +void watchdog_enable() +{ +#ifdef ARDUINO_ARCH_SAMD + samd_watchdog_enable(); +#else + mbed_watchdog_enable(); +#endif +} + +void watchdog_reset() +{ +#ifdef ARDUINO_ARCH_SAMD + samd_watchdog_reset(); +#else + mbed_watchdog_reset(); +#endif +} +#endif /* (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) */ diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index e1c8d2c27..f1ca98841 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -22,14 +22,12 @@ * FUNCTION DECLARATION ******************************************************************************/ -#ifdef ARDUINO_ARCH_SAMD -void samd_watchdog_enable(); -void samd_watchdog_reset(); -#endif /* ARDUINO_ARCH_SAMD */ +#if defined (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) +void watchdog_enable(); +void watchdog_reset(); +#endif /* (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) */ #ifdef ARDUINO_ARCH_MBED -void mbed_watchdog_enable(); -void mbed_watchdog_reset(); void mbed_watchdog_trigger_reset(); #endif /* ARDUINO_ARCH_MBED */ From 616a4fee6e9b4e3110df3f2fcb2204c8add7486f Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 9 Jun 2021 22:17:13 +0200 Subject: [PATCH 158/780] Configure WiFi library watchdog feed function --- src/ArduinoIoTCloudTCP.cpp | 4 ++++ src/utility/watchdog/Watchdog.cpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 3d6ba59cb..e04d41027 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -285,7 +285,11 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #if defined (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) if (enable_watchdog) { watchdog_enable(); +#ifdef WIFI_HAS_FEED_WATCHDOG_FUNC + WiFi.setFeedWatchdogFunc(watchdog_reset); +#endif } + #endif return 1; diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index e2a9e0fe9..d12b7a373 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -68,10 +68,12 @@ static void samd_watchdog_reset() * is defined a weak function there and overwritten by this "strong" * function here. */ +#ifndef WIFI_HAS_FEED_WATCHDOG_FUNC void wifi_nina_feed_watchdog() { samd_watchdog_reset(); } +#endif void mkr_gsm_feed_watchdog() { From 27742bb1b26ba8f0f947e2206b81f37c32fca16f Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 14 Jun 2021 12:38:05 +0200 Subject: [PATCH 159/780] Fix if defined preprocessor directive for watchdog handling (#263) --- src/ArduinoIoTCloudTCP.cpp | 6 +++--- src/utility/watchdog/Watchdog.cpp | 2 +- src/utility/watchdog/Watchdog.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e04d41027..e65da587e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -282,7 +282,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, * call to ArduinoIoTCloudTCP::update() it is wise to * set a rather large timeout at first. */ -#if defined (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) +#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) if (enable_watchdog) { watchdog_enable(); #ifdef WIFI_HAS_FEED_WATCHDOG_FUNC @@ -300,7 +300,7 @@ void ArduinoIoTCloudTCP::update() /* Feed the watchdog. If any of the functions called below * get stuck than we can at least reset and recover. */ -#if defined (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) +#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) watchdog_reset(); #endif @@ -322,7 +322,7 @@ void ArduinoIoTCloudTCP::update() * maximum watchdog window is 8389ms; despite this we feed it for all * supported ARCH to keep code aligned. */ -#if defined (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) +#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) watchdog_reset(); #endif diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index d12b7a373..ea0324dde 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -135,7 +135,7 @@ void mbed_watchdog_trigger_reset() } #endif /* ARDUINO_ARCH_MBED */ -#if defined (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) +#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) void watchdog_enable() { #ifdef ARDUINO_ARCH_SAMD diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index f1ca98841..879317684 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -22,7 +22,7 @@ * FUNCTION DECLARATION ******************************************************************************/ -#if defined (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) +#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) void watchdog_enable(); void watchdog_reset(); #endif /* (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) */ From c5e5d49dfef37f29ec24daf4b0c19e0a47cb47e9 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 14 Jun 2021 14:47:36 +0200 Subject: [PATCH 160/780] Release v1.1.0. --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 299a711c2..461cc8f73 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.0.2 +version=1.1.0 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From 858d6f8b562a6e0596b75c14f1aabc3c0af4c377 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 10 Jun 2021 22:20:21 +0200 Subject: [PATCH 161/780] pass wdog feed function to Arduino_Portenta_OTA library so it can be called during decompression phase --- src/utility/ota/OTA-portenta-h7.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index 7c6a01eb9..ca645ad28 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -40,6 +40,10 @@ int portenta_h7_onOTARequest(char const * ota_url) /* Use 2nd partition of QSPI (1st partition contains WiFi firmware) */ Arduino_Portenta_OTA_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2); +#if defined (PORTENTA_OTA_HAS_WATCHDOG_FEED) + ota_portenta_qspi.setFeedWatchdogFunc(watchdog_reset); +#endif + watchdog_reset(); /* Initialize the QSPI memory for OTA handling. */ From 34752c687dcf1caf6224791eef984b459fe8958e Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 10 Jun 2021 22:22:12 +0200 Subject: [PATCH 162/780] Remove stray newline --- src/ArduinoIoTCloudTCP.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e65da587e..b42edaa7f 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -289,7 +289,6 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, WiFi.setFeedWatchdogFunc(watchdog_reset); #endif } - #endif return 1; From 95e960ced3b84d6a412f76dfa9f14de794e66004 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 11 Jun 2021 10:19:30 +0200 Subject: [PATCH 163/780] align defines with Arduino_Portenta_OTA and ArduinoCore-mbed --- src/ArduinoIoTCloudTCP.cpp | 2 +- src/utility/ota/OTA-portenta-h7.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index b42edaa7f..12f66e416 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -285,7 +285,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) if (enable_watchdog) { watchdog_enable(); -#ifdef WIFI_HAS_FEED_WATCHDOG_FUNC +#if defined (WIFI_HAS_FEED_WATCHDOG_FUNC) || defined (ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC) WiFi.setFeedWatchdogFunc(watchdog_reset); #endif } diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index ca645ad28..52faf73f8 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -40,7 +40,7 @@ int portenta_h7_onOTARequest(char const * ota_url) /* Use 2nd partition of QSPI (1st partition contains WiFi firmware) */ Arduino_Portenta_OTA_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2); -#if defined (PORTENTA_OTA_HAS_WATCHDOG_FEED) +#if defined (ARDUINO_PORTENTA_OTA_HAS_WATCHDOG_FEED) ota_portenta_qspi.setFeedWatchdogFunc(watchdog_reset); #endif From af311913624e584acecc99a7e221be235d65a3de Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 11 Jun 2021 10:51:56 +0200 Subject: [PATCH 164/780] Add WiFi.h include for ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC --- src/ArduinoIoTCloudTCP.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 12f66e416..4cac10c6d 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -37,6 +37,7 @@ # include # include "tls/utility/SHA256.h" # include +# include #endif #include "utility/ota/OTA.h" From c8eac593ec6d18ab50800f3ccea837fb3f1130aa Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 15 Jun 2021 08:33:41 +0200 Subject: [PATCH 165/780] Release v1.1.1 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 461cc8f73..f99d29b06 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.1.0 +version=1.1.1 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From 277fe49cf0e008dc4729432f830b6b708c72dfce Mon Sep 17 00:00:00 2001 From: Ubi de Feo Date: Wed, 7 Jul 2021 12:20:36 +0200 Subject: [PATCH 166/780] added Adafruit_SleepyDog library to dependencies --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index f99d29b06..46ce1db38 100644 --- a/library.properties +++ b/library.properties @@ -8,4 +8,4 @@ category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta includes=ArduinoIoTCloud.h -depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero +depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit_SleepyDog From c74676c0e722bd3cd68cfaec85f10b791475fa20 Mon Sep 17 00:00:00 2001 From: per1234 Date: Thu, 15 Jul 2021 19:57:38 -0700 Subject: [PATCH 167/780] Add CI workflow to do Arduino project-specific linting On every push, pull request, and periodically, run Arduino Lint to check for common problems not related to the project code. --- .github/workflows/check-arduino.yml | 27 +++++++++++++++++++++++++++ README.md | 2 ++ 2 files changed, 29 insertions(+) create mode 100644 .github/workflows/check-arduino.yml diff --git a/.github/workflows/check-arduino.yml b/.github/workflows/check-arduino.yml new file mode 100644 index 000000000..15f7c2e73 --- /dev/null +++ b/.github/workflows/check-arduino.yml @@ -0,0 +1,27 @@ +name: Check Arduino + +# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows +on: + push: + pull_request: + schedule: + # Run every Tuesday at 8 AM UTC to catch breakage caused by new rules added to Arduino Lint. + - cron: "0 8 * * TUE" + workflow_dispatch: + repository_dispatch: + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Arduino Lint + uses: arduino/arduino-lint-action@v1 + with: + compliance: specification + library-manager: update + # Always use this setting for official repositories. Remove for 3rd party projects. + official: true diff --git a/README.md b/README.md index 87368dd51..a65e899f6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ `ArduinoIoTCloud` ================= + +[![Check Arduino status](https://github.com/arduino-libraries/ArduinoIoTCloud/actions/workflows/check-arduino.yml/badge.svg)](https://github.com/arduino-libraries/ArduinoIoTCloud/actions/workflows/check-arduino.yml) [![Compile Examples](https://github.com/arduino-libraries/ArduinoIoTCloud/workflows/Compile%20Examples/badge.svg)](https://github.com/arduino-libraries/ArduinoIoTCloud/actions?workflow=Compile+Examples) [![Spell Check](https://github.com/arduino-libraries/ArduinoIoTCloud/workflows/Spell%20Check/badge.svg)](https://github.com/arduino-libraries/ArduinoIoTCloud/actions?workflow=Spell+Check) [![Unit Tests](https://github.com/arduino-libraries/ArduinoIoTCloud/workflows/Unit%20Tests/badge.svg)](https://github.com/arduino-libraries/ArduinoIoTCloud/actions?workflow=Unit+Tests) From cc6413dfe1b0d91bdef435cc07d209bdfae703a3 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 21 Jul 2021 09:14:36 +0200 Subject: [PATCH 168/780] Bugfix: Typo within Watchdog section of FAQ (#270) Fixed by replacing ArduinoIoTCloud with ArduinoCloud. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a65e899f6..493e59ed1 100644 --- a/README.md +++ b/README.md @@ -69,9 +69,9 @@ void onLedChange() { ### FAQ #### Watchdog -This [1.0.0](https://github.com/arduino-libraries/ArduinoIoTCloud/releases/tag/1.0.0) release of this library adds watchdog functionality to all ATSAMD21G18 based cloud connected boards. A watchdog is simply an electronic timer counting down from a preset start value which, upon reaching zero, triggers a reset of the microcontroller. It can be used to automatically recover from temporary hardware faults or unrecoverable software errors. In order to avoid the watchdog from reaching zero the countdown timer needs to be regularly re-set to its start value. This is happening within `ArduinoIoTCloud.update()` which is periodically called at the start of the `loop()` function. Although the watchdog is automatically enabled it can be disabled by setting the second parameter of `ArduinoIoTCloud.begin(...)` to `false`: +This [1.0.0](https://github.com/arduino-libraries/ArduinoIoTCloud/releases/tag/1.0.0) release of this library adds watchdog functionality to all ATSAMD21G18 based cloud connected boards. A watchdog is simply an electronic timer counting down from a preset start value which, upon reaching zero, triggers a reset of the microcontroller. It can be used to automatically recover from temporary hardware faults or unrecoverable software errors. In order to avoid the watchdog from reaching zero the countdown timer needs to be regularly re-set to its start value. This is happening within `ArduinoCloud.update()` which is periodically called at the start of the `loop()` function. Although the watchdog is automatically enabled it can be disabled by setting the second parameter of `ArduinoCloud.begin(...)` to `false`: ```C++ -ArduinoIoTCloud.begin(ArduinoIoTPreferredConnection, false). +ArduinoCloud.begin(ArduinoIoTPreferredConnection, false). ``` #### Device can not subscribe to `THING_ID` From 41660e01a813de414c6e26fdfe4119465d78ffaa Mon Sep 17 00:00:00 2001 From: Fabrizio Mirabito Date: Mon, 20 Sep 2021 11:08:17 +0200 Subject: [PATCH 169/780] Fix CloudElectricPotential typo (#275) --- src/property/PropertyContainer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/property/PropertyContainer.h b/src/property/PropertyContainer.h index effa7d966..b1e83ec28 100644 --- a/src/property/PropertyContainer.h +++ b/src/property/PropertyContainer.h @@ -69,7 +69,7 @@ typedef CloudFloat CloudForce; typedef CloudFloat CloudTemperature; typedef CloudFloat CloudPower; typedef CloudFloat CloudElectricCurrent; -typedef CloudFloat CloudElectricPotention; +typedef CloudFloat CloudElectricPotential; typedef CloudFloat CloudElectricResistance; typedef CloudFloat CloudCapacitance; typedef CloudFloat CloudTime; From 1920b548afe6b8fc6926c79ea23a3b734fcf4f98 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Wed, 29 Sep 2021 06:18:54 +0200 Subject: [PATCH 170/780] Change value from float to double (#276) --- src/property/Property.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/property/Property.h b/src/property/Property.h index 803d77049..1e697609e 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -113,7 +113,7 @@ class CborMapData { MapEntry attribute_name; MapEntry attribute_identifier; MapEntry property_identifier; - MapEntry val; + MapEntry val; MapEntry str_val; MapEntry bool_val; MapEntry time; From 9ecfed7120b6dcead5413a544b949c5bb4d7bf77 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 30 Jul 2021 10:30:28 +0200 Subject: [PATCH 171/780] call mbed api to get store and get time --- src/utility/time/TimeService.cpp | 9 ++++++++- src/utility/time/TimeService.h | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 07d50fec6..dcd15f83b 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -51,7 +51,7 @@ static time_t const EPOCH_AT_COMPILE_TIME = cvt_time(__DATE__); TimeService::TimeService() : _con_hdl(nullptr) -#ifdef ARDUINO_ARCH_SAMD +#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) , _is_rtc_configured(false) #endif { @@ -79,6 +79,13 @@ unsigned long TimeService::getTime() _is_rtc_configured = true; } return rtc.getEpoch(); +#elif ARDUINO_ARCH_MBED + if(!_is_rtc_configured) + { + set_time(getRemoteTime()); + _is_rtc_configured = true; + } + return time(NULL); #else return getRemoteTime(); #endif diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index b6a4bb43a..efcea8cea 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -46,7 +46,7 @@ class TimeService private: ConnectionHandler * _con_hdl; -#ifdef ARDUINO_ARCH_SAMD +#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) bool _is_rtc_configured; #endif From 90fe691c3d569bdc9b1e725584766c0e6fe92741 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 30 Jul 2021 11:34:58 +0200 Subject: [PATCH 172/780] Add include to mbed_rtc_time.h --- src/utility/time/TimeService.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index efcea8cea..ae8c12f35 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -28,6 +28,10 @@ #include #endif +#ifdef ARDUINO_ARCH_MBED + #include +#endif + /************************************************************************************** * CLASS DECLARATION **************************************************************************************/ From c9d8fbc5975d93e66887ece48a909743b9ee3053 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 2 Aug 2021 17:16:37 +0200 Subject: [PATCH 173/780] Restrict changes to PORTENTA board --- src/utility/time/TimeService.cpp | 4 ++-- src/utility/time/TimeService.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index dcd15f83b..32a20327c 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -51,7 +51,7 @@ static time_t const EPOCH_AT_COMPILE_TIME = cvt_time(__DATE__); TimeService::TimeService() : _con_hdl(nullptr) -#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) +#if defined (ARDUINO_ARCH_SAMD) || defined (TARGET_PORTENTA_H7) , _is_rtc_configured(false) #endif { @@ -79,7 +79,7 @@ unsigned long TimeService::getTime() _is_rtc_configured = true; } return rtc.getEpoch(); -#elif ARDUINO_ARCH_MBED +#elif TARGET_PORTENTA_H7 if(!_is_rtc_configured) { set_time(getRemoteTime()); diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index ae8c12f35..cc200c813 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -28,7 +28,7 @@ #include #endif -#ifdef ARDUINO_ARCH_MBED +#ifdef TARGET_PORTENTA_H7 #include #endif @@ -50,7 +50,7 @@ class TimeService private: ConnectionHandler * _con_hdl; -#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) +#if defined (ARDUINO_ARCH_SAMD) || defined (TARGET_PORTENTA_H7) bool _is_rtc_configured; #endif From 9abe7e659a5a622aedd09ca1801a242955f7d188 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 Sep 2021 08:52:23 +0200 Subject: [PATCH 174/780] Add CloudUnsignedInt type --- src/ArduinoIoTCloud.cpp | 22 ++ src/ArduinoIoTCloud.h | 5 + src/property/Property.cpp | 15 ++ src/property/Property.h | 2 + src/property/types/CloudUnsignedInt.h | 222 +++++++++++++++++++ src/property/types/CloudWrapperUnsignedInt.h | 63 ++++++ 6 files changed, 329 insertions(+) create mode 100644 src/property/types/CloudUnsignedInt.h create mode 100644 src/property/types/CloudWrapperUnsignedInt.h diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 0f117e993..5b5637eb3 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -146,6 +146,28 @@ Property& ArduinoIoTCloudClass::addPropertyReal(int& property, String name, int return addPropertyToContainer(_property_container, *p, name, permission, tag); } +void ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +{ + addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); +} + +void ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +{ + Property* p = new CloudWrapperUnsignedInt(property); + addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, Permission const permission) +{ + return addPropertyReal(property, name, -1, permission); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, int tag, Permission const permission) +{ + Property* p = new CloudWrapperUnsignedInt(property); + return addPropertyToContainer(_property_container, *p, name, permission, tag); +} + void ArduinoIoTCloudClass::addPropertyReal(String& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 0130e3efc..7c1f9679c 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -39,6 +39,7 @@ #include "property/types/CloudWrapperBool.h" #include "property/types/CloudWrapperFloat.h" #include "property/types/CloudWrapperInt.h" +#include "property/types/CloudWrapperUnsignedInt.h" #include "property/types/CloudWrapperString.h" #include "utility/time/TimeService.h" @@ -110,12 +111,14 @@ class ArduinoIoTCloudClass void addPropertyReal(bool& property, String name, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0f, void(*synFn)(Property & property) = CLOUD_WINS) __attribute__((deprecated("Use addProperty(property, Permission::ReadWrite) instead."))); void addPropertyReal(float& property, String name, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0f, void(*synFn)(Property & property) = CLOUD_WINS) __attribute__((deprecated("Use addProperty(property, Permission::ReadWrite) instead."))); void addPropertyReal(int& property, String name, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0, void(*synFn)(Property & property) = CLOUD_WINS) __attribute__((deprecated("Use addProperty(property, Permission::ReadWrite) instead."))); + void addPropertyReal(unsigned int& property, String name, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0, void(*synFn)(Property & property) = CLOUD_WINS) __attribute__((deprecated("Use addProperty(property, Permission::ReadWrite) instead."))); void addPropertyReal(String& property, String name, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0f, void(*synFn)(Property & property) = CLOUD_WINS) __attribute__((deprecated("Use addProperty(property, Permission::ReadWrite) instead."))); Property& addPropertyReal(Property& property, String name, Permission const permission); Property& addPropertyReal(bool& property, String name, Permission const permission); Property& addPropertyReal(float& property, String name, Permission const permission); Property& addPropertyReal(int& property, String name, Permission const permission); + Property& addPropertyReal(unsigned int& property, String name, Permission const permission); Property& addPropertyReal(String& property, String name, Permission const permission); /* The following methods are for MKR WAN 1300/1310 LoRa boards since @@ -128,12 +131,14 @@ class ArduinoIoTCloudClass void addPropertyReal(bool& property, String name, int tag, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0f, void(*synFn)(Property & property) = CLOUD_WINS) __attribute__((deprecated("Use addProperty(property, Permission::ReadWrite) instead."))); void addPropertyReal(float& property, String name, int tag, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0f, void(*synFn)(Property & property) = CLOUD_WINS) __attribute__((deprecated("Use addProperty(property, Permission::ReadWrite) instead."))); void addPropertyReal(int& property, String name, int tag, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0, void(*synFn)(Property & property) = CLOUD_WINS) __attribute__((deprecated("Use addProperty(property, Permission::ReadWrite) instead."))); + void addPropertyReal(unsigned int& property, String name, int tag, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0, void(*synFn)(Property & property) = CLOUD_WINS) __attribute__((deprecated("Use addProperty(property, Permission::ReadWrite) instead."))); void addPropertyReal(String& property, String name, int tag, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0f, void(*synFn)(Property & property) = CLOUD_WINS) __attribute__((deprecated("Use addProperty(property, Permission::ReadWrite) instead."))); Property& addPropertyReal(Property& property, String name, int tag, Permission const permission); Property& addPropertyReal(bool& property, String name, int tag, Permission const permission); Property& addPropertyReal(float& property, String name, int tag, Permission const permission); Property& addPropertyReal(int& property, String name, int tag, Permission const permission); + Property& addPropertyReal(unsigned int& property, String name, int tag, Permission const permission); Property& addPropertyReal(String& property, String name, int tag, Permission const permission); protected: diff --git a/src/property/Property.cpp b/src/property/Property.cpp index 20be6e35b..201998408 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -171,6 +171,15 @@ CborError Property::appendAttributeReal(int value, String attributeName, CborEnc }, encoder); } +CborError Property::appendAttributeReal(unsigned int value, String attributeName, CborEncoder *encoder) { + return appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) + { + CHECK_CBOR(cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Value))); + CHECK_CBOR(cbor_encode_int(&mapEncoder, value)); + return CborNoError; + }, encoder); +} + CborError Property::appendAttributeReal(float value, String attributeName, CborEncoder *encoder) { return appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) { @@ -264,6 +273,12 @@ void Property::setAttributeReal(int& value, String attributeName) { }); } +void Property::setAttributeReal(unsigned int& value, String attributeName) { + setAttributeReal(attributeName, [&value](CborMapData & md) { + value = md.val.get(); + }); +} + void Property::setAttributeReal(float& value, String attributeName) { setAttributeReal(attributeName, [&value](CborMapData & md) { value = md.val.get(); diff --git a/src/property/Property.h b/src/property/Property.h index 1e697609e..1ead6f265 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -186,6 +186,7 @@ class Property CborError append(CborEncoder * encoder, bool lightPayload); CborError appendAttributeReal(bool value, String attributeName = "", CborEncoder *encoder = nullptr); CborError appendAttributeReal(int value, String attributeName = "", CborEncoder *encoder = nullptr); + CborError appendAttributeReal(unsigned int value, String attributeName = "", CborEncoder *encoder = nullptr); CborError appendAttributeReal(float value, String attributeName = "", CborEncoder *encoder = nullptr); CborError appendAttributeReal(String value, String attributeName = "", CborEncoder *encoder = nullptr); #ifndef __AVR__ @@ -198,6 +199,7 @@ class Property void setAttributesFromCloud(std::list * map_data_list); void setAttributeReal(bool& value, String attributeName = ""); void setAttributeReal(int& value, String attributeName = ""); + void setAttributeReal(unsigned int& value, String attributeName = ""); void setAttributeReal(float& value, String attributeName = ""); void setAttributeReal(String& value, String attributeName = ""); String getAttributeName(String propertyName, char separator); diff --git a/src/property/types/CloudUnsignedInt.h b/src/property/types/CloudUnsignedInt.h new file mode 100644 index 000000000..d8766762c --- /dev/null +++ b/src/property/types/CloudUnsignedInt.h @@ -0,0 +1,222 @@ +// +// This file is part of ArduinoCloudThing +// +// Copyright 2019 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of ArduinoCloudThing. +// 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 CLOUDUINT_H_ +#define CLOUDUINT_H_ + +/****************************************************************************** + INCLUDE + ******************************************************************************/ + +#include +#include "../Property.h" + +/****************************************************************************** + CLASS DECLARATION + ******************************************************************************/ + + + +class CloudUnsignedInt : public Property { + private: + unsigned int _value, + _cloud_value; + public: + CloudUnsignedInt() { + CloudUnsignedInt(0); + } + CloudUnsignedInt(unsigned int v) : _value(v), _cloud_value(v) {} + operator unsigned int() const { + return _value; + } + virtual bool isDifferentFromCloud() { + return _value != _cloud_value && (abs(_value - _cloud_value) >= Property::_min_delta_property); + } + virtual void fromCloudToLocal() { + _value = _cloud_value; + } + virtual void fromLocalToCloud() { + _cloud_value = _value; + } + virtual CborError appendAttributesToCloud() { + return appendAttribute(_value); + } + virtual void setAttributesFromCloud() { + setAttribute(_cloud_value); + } + //modifiers + CloudUnsignedInt& operator=(unsigned int v) { + _value = v; + updateLocalTimestamp(); + return *this; + } + CloudUnsignedInt& operator=(CloudUnsignedInt v) { + return operator=((unsigned int)v); + } + CloudUnsignedInt& operator+=(unsigned int v) { + return operator=(_value += v); + } + CloudUnsignedInt& operator-=(unsigned int v) { + return operator=(_value -= v); + } + CloudUnsignedInt& operator*=(unsigned int v) { + return operator=(_value *= v); + } + CloudUnsignedInt& operator/=(unsigned int v) { + return operator=(_value /= v); + } + CloudUnsignedInt& operator%=(unsigned int v) { + return operator=(_value %= v); + } + CloudUnsignedInt& operator++() { + return operator=(++_value); + } + CloudUnsignedInt& operator--() { + return operator=(--_value); + } + CloudUnsignedInt operator++(int) { + operator=(_value + 1); + return CloudUnsignedInt(_value); + } + CloudUnsignedInt operator--(int) { + operator=(_value - 1); + return CloudUnsignedInt(_value); + } + CloudUnsignedInt& operator&=(unsigned int v) { + return operator=(_value &= v); + } + CloudUnsignedInt& operator|=(unsigned int v) { + return operator=(_value |= v); + } + CloudUnsignedInt& operator^=(unsigned int v) { + return operator=(_value ^= v); + } + CloudUnsignedInt& operator<<=(unsigned int v) { + return operator=(_value <<= v); + } + CloudUnsignedInt& operator>>=(unsigned int v) { + return operator=(_value >>= v); + } + //accessors + CloudUnsignedInt operator+() const { + return CloudUnsignedInt(+_value); + } + CloudUnsignedInt operator-() const { + return CloudUnsignedInt(-_value); + } + CloudUnsignedInt operator!() const { + return CloudUnsignedInt(!_value); + } + CloudUnsignedInt operator~() const { + return CloudUnsignedInt(~_value); + } + //friends + friend CloudUnsignedInt operator+(CloudUnsignedInt iw, CloudUnsignedInt v) { + return iw += v; + } + friend CloudUnsignedInt operator+(CloudUnsignedInt iw, unsigned int v) { + return iw += v; + } + friend CloudUnsignedInt operator+(unsigned int v, CloudUnsignedInt iw) { + return CloudUnsignedInt(v) += iw; + } + friend CloudUnsignedInt operator-(CloudUnsignedInt iw, CloudUnsignedInt v) { + return iw -= v; + } + friend CloudUnsignedInt operator-(CloudUnsignedInt iw, unsigned int v) { + return iw -= v; + } + friend CloudUnsignedInt operator-(unsigned int v, CloudUnsignedInt iw) { + return CloudUnsignedInt(v) -= iw; + } + friend CloudUnsignedInt operator*(CloudUnsignedInt iw, CloudUnsignedInt v) { + return iw *= v; + } + friend CloudUnsignedInt operator*(CloudUnsignedInt iw, unsigned int v) { + return iw *= v; + } + friend CloudUnsignedInt operator*(unsigned int v, CloudUnsignedInt iw) { + return CloudUnsignedInt(v) *= iw; + } + friend CloudUnsignedInt operator/(CloudUnsignedInt iw, CloudUnsignedInt v) { + return iw /= v; + } + friend CloudUnsignedInt operator/(CloudUnsignedInt iw, unsigned int v) { + return iw /= v; + } + friend CloudUnsignedInt operator/(unsigned int v, CloudUnsignedInt iw) { + return CloudUnsignedInt(v) /= iw; + } + friend CloudUnsignedInt operator%(CloudUnsignedInt iw, CloudUnsignedInt v) { + return iw %= v; + } + friend CloudUnsignedInt operator%(CloudUnsignedInt iw, unsigned int v) { + return iw %= v; + } + friend CloudUnsignedInt operator%(unsigned int v, CloudUnsignedInt iw) { + return CloudUnsignedInt(v) %= iw; + } + friend CloudUnsignedInt operator&(CloudUnsignedInt iw, CloudUnsignedInt v) { + return iw &= v; + } + friend CloudUnsignedInt operator&(CloudUnsignedInt iw, unsigned int v) { + return iw &= v; + } + friend CloudUnsignedInt operator&(unsigned int v, CloudUnsignedInt iw) { + return CloudUnsignedInt(v) &= iw; + } + friend CloudUnsignedInt operator|(CloudUnsignedInt iw, CloudUnsignedInt v) { + return iw |= v; + } + friend CloudUnsignedInt operator|(CloudUnsignedInt iw, unsigned int v) { + return iw |= v; + } + friend CloudUnsignedInt operator|(unsigned int v, CloudUnsignedInt iw) { + return CloudUnsignedInt(v) |= iw; + } + friend CloudUnsignedInt operator^(CloudUnsignedInt iw, CloudUnsignedInt v) { + return iw ^= v; + } + friend CloudUnsignedInt operator^(CloudUnsignedInt iw, unsigned int v) { + return iw ^= v; + } + friend CloudUnsignedInt operator^(unsigned int v, CloudUnsignedInt iw) { + return CloudUnsignedInt(v) ^= iw; + } + friend CloudUnsignedInt operator<<(CloudUnsignedInt iw, CloudUnsignedInt v) { + return iw <<= v; + } + friend CloudUnsignedInt operator<<(CloudUnsignedInt iw, unsigned int v) { + return iw <<= v; + } + friend CloudUnsignedInt operator<<(unsigned int v, CloudUnsignedInt iw) { + return CloudUnsignedInt(v) <<= iw; + } + friend CloudUnsignedInt operator>>(CloudUnsignedInt iw, CloudUnsignedInt v) { + return iw >>= v; + } + friend CloudUnsignedInt operator>>(CloudUnsignedInt iw, unsigned int v) { + return iw >>= v; + } + friend CloudUnsignedInt operator>>(unsigned int v, CloudUnsignedInt iw) { + return CloudUnsignedInt(v) >>= iw; + } + +}; + + +#endif /* CLOUDUINT_H_ */ diff --git a/src/property/types/CloudWrapperUnsignedInt.h b/src/property/types/CloudWrapperUnsignedInt.h new file mode 100644 index 000000000..227418c0d --- /dev/null +++ b/src/property/types/CloudWrapperUnsignedInt.h @@ -0,0 +1,63 @@ +// +// This file is part of ArduinoCloudThing +// +// Copyright 2019 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of ArduinoCloudThing. +// 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 CLOUDWRAPPERUINT_H_ +#define CLOUDWRAPPERUINT_H_ + +/****************************************************************************** + INCLUDE + ******************************************************************************/ + +#include +#include "CloudWrapperBase.h" + +/****************************************************************************** + CLASS DECLARATION + ******************************************************************************/ + +class CloudWrapperUnsignedInt : public CloudWrapperBase { + private: + unsigned int &_primitive_value, + _cloud_value, + _local_value; + public: + CloudWrapperUnsignedInt(unsigned int& v) : _primitive_value(v), _cloud_value(v), _local_value(v) {} + virtual bool isDifferentFromCloud() { + return _primitive_value != _cloud_value && (abs(_primitive_value - _cloud_value) >= Property::_min_delta_property); + } + virtual void fromCloudToLocal() { + _primitive_value = _cloud_value; + } + virtual void fromLocalToCloud() { + _cloud_value = _primitive_value; + } + virtual CborError appendAttributesToCloud() { + return appendAttribute(_primitive_value); + } + virtual void setAttributesFromCloud() { + setAttribute(_cloud_value); + } + virtual bool isPrimitive() { + return true; + } + virtual bool isChangedLocally() { + return _primitive_value != _local_value; + } +}; + + +#endif /* CLOUDWRAPPERINT_H_ */ From cc580be6e0dd4ca039b251d0e627cf40efe2cf2a Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 Sep 2021 10:27:54 +0200 Subject: [PATCH 175/780] Make CloudTime an unsigned int --- src/property/PropertyContainer.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/property/PropertyContainer.h b/src/property/PropertyContainer.h index b1e83ec28..fc038f583 100644 --- a/src/property/PropertyContainer.h +++ b/src/property/PropertyContainer.h @@ -37,6 +37,7 @@ #include "types/CloudBool.h" #include "types/CloudFloat.h" #include "types/CloudInt.h" +#include "types/CloudUnsignedInt.h" #include "types/CloudString.h" #include "types/CloudLocation.h" #include "types/CloudColor.h" @@ -72,7 +73,7 @@ typedef CloudFloat CloudElectricCurrent; typedef CloudFloat CloudElectricPotential; typedef CloudFloat CloudElectricResistance; typedef CloudFloat CloudCapacitance; -typedef CloudFloat CloudTime; +typedef CloudUnsignedInt CloudTime; typedef CloudFloat CloudFrequency; typedef CloudFloat CloudDataRate; typedef CloudFloat CloudHeartRate; From dfb8c40983bb5c5443b7e0004428a5cd6b824c59 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 Sep 2021 11:02:47 +0200 Subject: [PATCH 176/780] Fix threshold check --- src/property/types/CloudUnsignedInt.h | 2 +- src/property/types/CloudWrapperUnsignedInt.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/property/types/CloudUnsignedInt.h b/src/property/types/CloudUnsignedInt.h index d8766762c..7ca664cb2 100644 --- a/src/property/types/CloudUnsignedInt.h +++ b/src/property/types/CloudUnsignedInt.h @@ -44,7 +44,7 @@ class CloudUnsignedInt : public Property { return _value; } virtual bool isDifferentFromCloud() { - return _value != _cloud_value && (abs(_value - _cloud_value) >= Property::_min_delta_property); + return _value != _cloud_value && ((max(_value , _cloud_value) - min(_value , _cloud_value)) >= Property::_min_delta_property); } virtual void fromCloudToLocal() { _value = _cloud_value; diff --git a/src/property/types/CloudWrapperUnsignedInt.h b/src/property/types/CloudWrapperUnsignedInt.h index 227418c0d..22ed67043 100644 --- a/src/property/types/CloudWrapperUnsignedInt.h +++ b/src/property/types/CloudWrapperUnsignedInt.h @@ -37,7 +37,7 @@ class CloudWrapperUnsignedInt : public CloudWrapperBase { public: CloudWrapperUnsignedInt(unsigned int& v) : _primitive_value(v), _cloud_value(v), _local_value(v) {} virtual bool isDifferentFromCloud() { - return _primitive_value != _cloud_value && (abs(_primitive_value - _cloud_value) >= Property::_min_delta_property); + return _primitive_value != _cloud_value && ((max(_primitive_value , _cloud_value) - min(_primitive_value , _cloud_value)) >= Property::_min_delta_property); } virtual void fromCloudToLocal() { _primitive_value = _cloud_value; From dae7cd54d1e80a22b377e20768642f9c24ded3f8 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 Sep 2021 11:56:45 +0200 Subject: [PATCH 177/780] Fix unit test error --- src/property/types/CloudUnsignedInt.h | 2 +- src/property/types/CloudWrapperUnsignedInt.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/property/types/CloudUnsignedInt.h b/src/property/types/CloudUnsignedInt.h index 7ca664cb2..37ec2d1cb 100644 --- a/src/property/types/CloudUnsignedInt.h +++ b/src/property/types/CloudUnsignedInt.h @@ -44,7 +44,7 @@ class CloudUnsignedInt : public Property { return _value; } virtual bool isDifferentFromCloud() { - return _value != _cloud_value && ((max(_value , _cloud_value) - min(_value , _cloud_value)) >= Property::_min_delta_property); + return _value != _cloud_value && ((std::max(_value , _cloud_value) - std::min(_value , _cloud_value)) >= Property::_min_delta_property); } virtual void fromCloudToLocal() { _value = _cloud_value; diff --git a/src/property/types/CloudWrapperUnsignedInt.h b/src/property/types/CloudWrapperUnsignedInt.h index 22ed67043..d722f585f 100644 --- a/src/property/types/CloudWrapperUnsignedInt.h +++ b/src/property/types/CloudWrapperUnsignedInt.h @@ -37,7 +37,7 @@ class CloudWrapperUnsignedInt : public CloudWrapperBase { public: CloudWrapperUnsignedInt(unsigned int& v) : _primitive_value(v), _cloud_value(v), _local_value(v) {} virtual bool isDifferentFromCloud() { - return _primitive_value != _cloud_value && ((max(_primitive_value , _cloud_value) - min(_primitive_value , _cloud_value)) >= Property::_min_delta_property); + return _primitive_value != _cloud_value && ((std::max(_primitive_value , _cloud_value) - std::min(_primitive_value , _cloud_value)) >= Property::_min_delta_property); } virtual void fromCloudToLocal() { _primitive_value = _cloud_value; From 9dba1b23ed642b4638e6a9058d5951677568bad8 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 4 Oct 2021 12:06:56 +0200 Subject: [PATCH 178/780] Add decode test for CloudTime type --- extras/test/src/test_decode.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/extras/test/src/test_decode.cpp b/extras/test/src/test_decode.cpp index 7b66ef90e..c95d4afe9 100644 --- a/extras/test/src/test_decode.cpp +++ b/extras/test/src/test_decode.cpp @@ -382,6 +382,24 @@ SCENARIO("Arduino Cloud Properties are decoded", "[ArduinoCloudThing::decode]") /************************************************************************************/ + WHEN("A Time property is changed via CBOR message") + { + PropertyContainer property_container; + + CloudTime test; + test = 0; + addPropertyToContainer(property_container, test, "test", Permission::ReadWrite); + + /* [{0: "test", 2: 4294967295}] = 81 A2 00 64 74 65 73 74 02 1A FF FF FF FF */ + uint8_t const payload[] = {0x81, 0xA2, 0x00, 0x64, 0x74, 0x65, 0x73, 0x74, 0x02, 0x1A, 0xFF, 0xFF, 0xFF, 0xFF}; + int const payload_length = sizeof(payload) / sizeof(uint8_t); + CBORDecoder::decode(property_container, payload, payload_length); + + REQUIRE(test == 4294967295); + } + + /************************************************************************************/ + WHEN("Multiple properties is changed via CBOR message") { WHEN("Multiple properties of different type are changed via CBOR message") From 72471adab88b9c386c414c89198d25c8d3ccafa7 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 4 Oct 2021 12:22:33 +0200 Subject: [PATCH 179/780] Add encode test for CloudTime type --- extras/test/src/test_encode.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/extras/test/src/test_encode.cpp b/extras/test/src/test_encode.cpp index 985d1c2dc..5b199bbe7 100644 --- a/extras/test/src/test_encode.cpp +++ b/extras/test/src/test_encode.cpp @@ -306,6 +306,22 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode-1]" /************************************************************************************/ + WHEN("A time property is added") + { + PropertyContainer property_container; + cbor::encode(property_container); + + CloudTime test = 1633342784; + addPropertyToContainer(property_container, test, "test", Permission::ReadWrite); + + /* [{0: "test", 2: 1633342784}] = 9F A2 00 64 74 65 73 74 02 1A 61 5A D5 40 FF*/ + std::vector const expected = {0x9F, 0xA2, 0x00, 0x64, 0x74, 0x65, 0x73, 0x74, 0x02, 0x1A, 0x61, 0x5A, 0xD5, 0x40, 0xFF}; + std::vector const actual = cbor::encode(property_container); + REQUIRE(actual == expected); + } + + /************************************************************************************/ + WHEN("Multiple properties are added") { PropertyContainer property_container; From 5213f2d258cf6cad82b6b1799b6ddc1de5f02fe7 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 4 Oct 2021 13:06:30 +0200 Subject: [PATCH 180/780] Fix typos in comments --- extras/test/src/test_encode.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/extras/test/src/test_encode.cpp b/extras/test/src/test_encode.cpp index 5b199bbe7..8a4904fc6 100644 --- a/extras/test/src/test_encode.cpp +++ b/extras/test/src/test_encode.cpp @@ -65,7 +65,7 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode-1]" CloudInt int_test = 123; addPropertyToContainer(property_container, int_test, "test", Permission::ReadWrite); - /* [{0: "test", 3: 123}] = 9F A2 00 64 74 65 73 74 02 18 7B FF */ + /* [{0: "test", 2: 123}] = 9F A2 00 64 74 65 73 74 02 18 7B FF */ std::vector const expected = {0x9F, 0xA2, 0x00, 0x64, 0x74, 0x65, 0x73, 0x74, 0x02, 0x18, 0x7B, 0xFF}; std::vector const actual = cbor::encode(property_container); REQUIRE(actual == expected); @@ -114,7 +114,7 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode-1]" CloudLocation location_test = CloudLocation(2.0f, 3.0f); addPropertyToContainer(property_container, location_test, "test", Permission::ReadWrite); - /* [{0: "test:lat", 3: 2},{0: "test:lon", 3: 3}] = 9F A2 00 68 74 65 73 74 3A 6C 61 74 02 FA 40 00 00 00 A2 00 68 74 65 73 74 3A 6C 6F 6E 02 FA 40 40 00 00 FF*/ + /* [{0: "test:lat", 2: 2},{0: "test:lon", 2: 3}] = 9F A2 00 68 74 65 73 74 3A 6C 61 74 02 FA 40 00 00 00 A2 00 68 74 65 73 74 3A 6C 6F 6E 02 FA 40 40 00 00 FF*/ std::vector const expected = { 0x9F, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x6C, 0x61, 0x74, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x6C, 0x6F, 0x6E, 0x02, 0xFA, 0x40, 0x40, 0x00, 0x00, 0xFF }; std::vector const actual = cbor::encode(property_container); REQUIRE(actual == expected); @@ -164,7 +164,7 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode-1]" CloudColoredLight color_test = CloudColoredLight(true, 2.0, 2.0, 2.0); addPropertyToContainer(property_container, color_test, "test", Permission::ReadWrite); - /* [{0: "test:swi", 4: true},{0: "test:hue", 2: 2.0},{0: "test:sat", 2: 2.0},{0: "test:bri", 2: 2.0}] = 83 A2 00 68 74 65 73 74 3A 73 77 69 04 F5 //A2 00 68 74 65 73 74 3A 68 75 65 02 FA 40 00 00 00 A2 00 68 74 65 73 74 3A 73 61 74 02 FA 40 00 00 00 A2 00 68 74 65 73 74 3A 62 72 69 02 FA 40 00 00 00 FF*/ + /* [{0: "test:swi", 4: true},{0: "test:hue", 2: 2.0},{0: "test:sat", 2: 2.0},{0: "test:bri", 2: 2.0}] = 9F A2 00 68 74 65 73 74 3A 73 77 69 04 F5 A2 00 68 74 65 73 74 3A 68 75 65 02 FA 40 00 00 00 A2 00 68 74 65 73 74 3A 73 61 74 02 FA 40 00 00 00 A2 00 68 74 65 73 74 3A 62 72 69 02 FA 40 00 00 00 FF*/ std::vector const expected = {0x9F, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x73, 0x77, 0x69, 0x04, 0xF5, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x68, 0x75, 0x65, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x73, 0x61, 0x74, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x62, 0x72, 0x69, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xFF }; std::vector const actual = cbor::encode(property_container); REQUIRE(actual == expected); @@ -180,7 +180,7 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode-1]" CloudTelevision tv_test = CloudTelevision(true, 50, false, PlaybackCommands::Play, InputValue::TV, 7); addPropertyToContainer(property_container, tv_test, "test", Permission::ReadWrite); - /* [{0: "test:swi", 4: true},{0: "test:vol", 2: 50},{0: "test:mut", 2: false},{0: "test:pbc", 2: 3},{0: "test:inp", 2: 55},{0: "test:cha", 2: 7}] = 9F A2 00 68 74 65 73 74 3A 73 77 69 04 F5 A2 00 68 74 65 73 74 3A 76 6F 6C 02 18 32 A2 00 68 74 65 73 74 3A 6D 75 74 04 F4 A2 00 68 74 65 73 74 3A 70 62 63 02 03 A2 00 68 74 65 73 74 3A 69 6E 70 02 18 37 A2 00 68 74 65 73 74 3A 63 68 61 02 07 FF */ + /* [{0: "test:swi", 4: true},{0: "test:vol", 2: 50},{0: "test:mut", 4: false},{0: "test:pbc", 2: 3},{0: "test:inp", 2: 55},{0: "test:cha", 2: 7}] = 9F A2 00 68 74 65 73 74 3A 73 77 69 04 F5 A2 00 68 74 65 73 74 3A 76 6F 6C 02 18 32 A2 00 68 74 65 73 74 3A 6D 75 74 04 F4 A2 00 68 74 65 73 74 3A 70 62 63 02 03 A2 00 68 74 65 73 74 3A 69 6E 70 02 18 37 A2 00 68 74 65 73 74 3A 63 68 61 02 07 FF */ std::vector const expected = {0x9F, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x73, 0x77, 0x69, 0x04, 0xF5, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x76, 0x6F, 0x6C, 0x02, 0x18, 0x32, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x6D, 0x75, 0x74, 0x04, 0xF4, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x70, 0x62, 0x63, 0x02, 0x03, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x69, 0x6E, 0x70, 0x02, 0x18, 0x37, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x63, 0x68, 0x61, 0x02, 0x07, 0xFF}; std::vector const actual = cbor::encode(property_container); REQUIRE(actual == expected); @@ -196,7 +196,7 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode-1]" CloudDimmedLight color_test = CloudDimmedLight(true, 2.0); addPropertyToContainer(property_container, color_test, "test", Permission::ReadWrite); - /* [{0: "test:swi", 4: true},{0: "test:hue", 2: 0.0},{0: "test:sat", 2: 0.0},{0: "test:bri", 2: 2.0}] = 83 A2 00 68 74 65 73 74 3A 73 77 69 04 F5 //A2 00 68 74 65 73 74 3A 68 75 65 02 FA 00 00 00 00 A2 00 68 74 65 73 74 3A 73 61 74 02 FA 00 00 00 00 A2 00 68 74 65 73 74 3A 62 72 69 02 FA 40 00 00 00 FF*/ + /* [{0: "test:swi", 4: true},{0: "test:hue", 2: 0.0},{0: "test:sat", 2: 0.0},{0: "test:bri", 2: 2.0}] = 9F A2 00 68 74 65 73 74 3A 73 77 69 04 F5 A2 00 68 74 65 73 74 3A 68 75 65 02 FA 00 00 00 00 A2 00 68 74 65 73 74 3A 73 61 74 02 FA 00 00 00 00 A2 00 68 74 65 73 74 3A 62 72 69 02 FA 40 00 00 00 FF*/ std::vector const expected = {0x9F, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x73, 0x77, 0x69, 0x04, 0xF5, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x68, 0x75, 0x65, 0x02, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x73, 0x61, 0x74, 0x02, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x62, 0x72, 0x69, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xFF }; std::vector const actual = cbor::encode(property_container); REQUIRE(actual == expected); From 315cb27ace5955277a084b36c5809edf61c594c2 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 5 Oct 2021 14:04:47 +0200 Subject: [PATCH 181/780] Do not write "No RTC available..." message for PORTENTA target --- src/property/Property.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index 201998408..a26a7535c 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -21,7 +21,7 @@ #undef min #include -#ifndef ARDUINO_ARCH_SAMD +#if !defined ARDUINO_ARCH_SAMD && !defined TARGET_PORTENTA_H7 #pragma message "No RTC available on this architecture - ArduinoIoTCloud will not keep track of local change timestamps ." #endif From e02c2842616f1cc4f2c0169b3268ac551a3d4135 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Tue, 5 Oct 2021 15:08:53 +0200 Subject: [PATCH 182/780] Release v1.2.0 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 46ce1db38..16eee5476 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.1.1 +version=1.2.0 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From d76e5c315c00aadf0f64ab89d6375a0159acf199 Mon Sep 17 00:00:00 2001 From: per1234 Date: Tue, 5 Oct 2021 23:42:24 -0700 Subject: [PATCH 183/780] Correct library dependency name in metadata (#279) The `depends` field of the library.properties metadata file can be used to provide a list of library dependencies that should be installed in addition during a Library Manager installation. The library names must match exactly to the `name` value in the dependency's library.properties metadata file, which is the unique identifier used by Library Manager. The name of the "Adafruit SleepyDog Library" is just like that, but an incorrect name "Adafruit_SleepyDog" was used instead. This resulted in the following: - Classic Arduino IDE: the incorrect name was ignored and the dependency not installed - Arduino IDE 2.x: installation of the ArduinoIoTCloud library fails silently - Arduino CLI: installation of the ArduinoIoTCloud library fails with "Error installing ArduinoIoTCloud: No valid dependencies solution found: dependency 'Adafruit_SleepyDog' is not available" --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 16eee5476..164440fb0 100644 --- a/library.properties +++ b/library.properties @@ -8,4 +8,4 @@ category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta includes=ArduinoIoTCloud.h -depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit_SleepyDog +depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library From 5e19f337270632d069eae8d22a4aeede983690cd Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Wed, 6 Oct 2021 10:06:22 +0200 Subject: [PATCH 184/780] Release v1.2.1 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 164440fb0..d85a4eb08 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.2.0 +version=1.2.1 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From cd906d9885bc4a5ec77e79d5c311676ac6b7d933 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 4 Nov 2021 12:30:55 +0100 Subject: [PATCH 185/780] Add missing channelMask parameter --- examples/ArduinoIoTCloud-Advanced/thingProperties.h | 2 +- examples/ArduinoIoTCloud-Basic/thingProperties.h | 2 +- examples/ArduinoIoTCloud-Callbacks/thingProperties.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index 467e2e5e4..ad9788514 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -33,7 +33,7 @@ void initProperties() { #elif defined(BOARD_HAS_GSM) GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_LORA) - LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, _lora_class::CLASS_A); + LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #endif diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index b2bfb5d67..fbf2ea960 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -40,7 +40,7 @@ void initProperties() { #elif defined(BOARD_HAS_GSM) GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_LORA) - LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, _lora_class::CLASS_A); + LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #endif diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index 20ee3c9e6..9b2aa47b6 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -27,7 +27,7 @@ void initProperties() { #elif defined(BOARD_HAS_GSM) GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_LORA) - LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, _lora_class::CLASS_A); + LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #endif From b9bf84d2b6ee449fa5366b295bc2c9531b2e62d6 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 2 Jul 2021 17:04:57 +0200 Subject: [PATCH 186/780] Add hook for OTA confirmation --- src/ArduinoIoTCloudTCP.cpp | 18 ++++++++++-------- src/ArduinoIoTCloudTCP.h | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 4cac10c6d..2289c00fe 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -511,14 +511,16 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() if (_ota_req) { - /* Clear the error flag. */ - _ota_error = static_cast(OTAError::None); - /* Transmit the cleared error flag to the cloud. */ - sendPropertiesToCloud(); - /* Clear the request flag. */ - _ota_req = false; - /* Call member function to handle OTA request. */ - onOTARequest(); + if (_automatic_ota || (_get_ota_confirmation != nullptr && _get_ota_confirmation())) { + /* Clear the error flag. */ + _ota_error = static_cast(OTAError::None); + /* Transmit the cleared error flag to the cloud. */ + sendPropertiesToCloud(); + /* Clear the request flag. */ + _ota_req = false; + /* Call member function to handle OTA request. */ + onOTARequest(); + } } #endif /* OTA_ENABLED */ diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index f29aafde7..38dee3ab2 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -49,6 +49,8 @@ static uint16_t const DEFAULT_BROKER_PORT_SECURE_AUTH = 8883; static char const DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH[] = "mqtts-up.iot.arduino.cc"; static uint16_t const DEFAULT_BROKER_PORT_USER_PASS_AUTH = 8884; +typedef bool (*otaConfirmationStatus)(void); + /****************************************************************************** * CLASS DECLARATION ******************************************************************************/ @@ -80,6 +82,15 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass inline String getBrokerAddress() const { return _brokerAddress; } inline uint16_t getBrokerPort () const { return _brokerPort; } +#if OTA_ENABLED + /* The callback is triggered when the OTA is initiated and it gets executed until _ota_req flag is cleared. + * It should return true when the OTA can be applied or false otherwise. + */ + void onOTARequestCb(otaConfirmationStatus cb) { + _get_ota_confirmation = cb; + _automatic_ota = false; + } +#endif private: static const int MQTT_TRANSMIT_BUFFER_SIZE = 256; @@ -130,6 +141,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass String _ota_img_sha256; String _ota_url; bool _ota_req; + bool _automatic_ota = true; #endif /* OTA_ENABLED */ inline String getTopic_shadowout() { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/shadow/o"); } @@ -153,6 +165,8 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #if OTA_ENABLED void onOTARequest(); #endif + + otaConfirmationStatus _get_ota_confirmation = {nullptr}; }; /****************************************************************************** From 9938936977b5c622e671ad6fc59a2d0672662f3c Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 2 Jul 2021 17:08:05 +0200 Subject: [PATCH 187/780] Add example for Deferred OTA --- .../ArduinoIoTCloud-DeferredOTA.ino | 81 +++++++++++++++++++ .../arduino_secrets.h | 34 ++++++++ .../thingProperties.h | 40 +++++++++ 3 files changed, 155 insertions(+) create mode 100644 examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino create mode 100644 examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h create mode 100644 examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h diff --git a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino new file mode 100644 index 000000000..dba9927fb --- /dev/null +++ b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino @@ -0,0 +1,81 @@ +/* + This sketch demonstrates how to handle deferred OTA from Arduino IoT Cloud. + + Deferred OTA can be triggered using the arduino-cloud-cli with the following command: + ./arduino-cloud-cli ota upload --device-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --file filename.ino.bin --deferred + The update file and the download link will be available to be used within one week. + + * always_deny callback will always postpone the OTA update + * always_allow callback will immediately apply the OTA update + * ask_user_via_serial callback will read user input from serial to apply or postpone OTA update + + This sketch is compatible with: + - MKR WIFI 1010 + - Nano 33 IoT + - Portenta + - Nano RP2040 +*/ + +#include "arduino_secrets.h" +#include "thingProperties.h" + +#if defined(ESP32) +static int const LED_BUILTIN = 2; +#endif + +bool always_deny() { + return false; +} + +bool always_allow() { + return true; +} + +static bool ask_user_via_serial_first_run = true; +bool ask_user_via_serial() { + if (ask_user_via_serial_first_run) { + Serial.println("Apply OTA? y / [n]"); + ask_user_via_serial_first_run = false; + } + if (Serial.available()) { + char c = Serial.read(); + if (c == 'y' || c == 'Y') { + return true; + } + } + return false; +} + +void setup() { + /* Initialize serial and wait up to 5 seconds for port to open */ + Serial.begin(9600); + for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime > 5000); ) { } + + /* Configure LED pin as an output */ + pinMode(LED_BUILTIN, OUTPUT); + + /* This function takes care of connecting your sketch variables to the ArduinoIoTCloud object */ + initProperties(); + + /* Initialize Arduino IoT Cloud library */ + ArduinoCloud.begin(ArduinoIoTPreferredConnection); + + /* Setup OTA callback */ + ArduinoCloud.onOTARequestCb(always_deny); + + setDebugMessageLevel(DBG_INFO); + ArduinoCloud.printDebugInfo(); +} + +void loop() { + ArduinoCloud.update(); +} + +/* + * 'onLedChange' is called when the "led" property of your Thing changes + */ +void onLedChange() { + Serial.print("LED set to "); + Serial.println(led); + digitalWrite(LED_BUILTIN, led); +} diff --git a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h new file mode 100644 index 000000000..fc0b0661e --- /dev/null +++ b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h @@ -0,0 +1,34 @@ +#include + +/* MKR1000, MKR WiFi 1010 */ +#if defined(BOARD_HAS_WIFI) + #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" + #define SECRET_PASS "YOUR_WIFI_PASSWORD" +#endif + +/* ESP8266 */ +#if defined(BOARD_ESP8266) + #define SECRET_DEVICE_KEY "my-device-password" +#endif + +/* MKR GSM 1400 */ +#if defined(BOARD_HAS_GSM) + #define SECRET_PIN "" + #define SECRET_APN "" + #define SECRET_LOGIN "" + #define SECRET_PASS "" +#endif + +/* MKR WAN 1300/1310 */ +#if defined(BOARD_HAS_LORA) + #define SECRET_APP_EUI "" + #define SECRET_APP_KEY "" +#endif + +/* MKR NB 1500 */ +#if defined(BOARD_HAS_NB) + #define SECRET_PIN "" + #define SECRET_APN "" + #define SECRET_LOGIN "" + #define SECRET_PASS "" +#endif diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h new file mode 100644 index 000000000..f5628033a --- /dev/null +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -0,0 +1,40 @@ +#include +#include + +#if defined(BOARD_HAS_WIFI) +#elif defined(BOARD_HAS_GSM) +#elif defined(BOARD_HAS_LORA) +#elif defined(BOARD_HAS_NB) +#else + #error "Arduino IoT Cloud currently only supports MKR1000, MKR WiFi 1010, MKR WAN 1300/1310, MKR NB 1500 and MKR GSM 1400" +#endif + +#define THING_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + +void onLedChange(); + +bool led; + +void initProperties() { +#if defined(BOARD_ESP8266) + ArduinoCloud.setBoardId(BOARD_ID); + ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); +#endif + ArduinoCloud.setThingId(THING_ID); +#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) + ArduinoCloud.addProperty(led, Permission::Write).onUpdate(onLedChange); +#elif defined(BOARD_HAS_LORA) + ArduinoCloud.addProperty(led, 1, READWRITE, ON_CHANGE, onLedChange); +#endif +} + +#if defined(BOARD_HAS_WIFI) + WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_PASS); +#elif defined(BOARD_HAS_GSM) + GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_LORA) + LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, _lora_class::CLASS_A); +#elif defined(BOARD_HAS_NB) + NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#endif From 29417af9adb242de578a0ace547bc9201fd0c2f8 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 15 Oct 2021 10:10:41 +0200 Subject: [PATCH 188/780] Change sync strategy to CLOUD_WINS --- src/ArduinoIoTCloudTCP.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 2289c00fe..3c0685ac6 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -238,8 +238,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, addPropertyReal(_ota_cap, "OTA_CAP", Permission::Read); 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); + addPropertyReal(_ota_url, "OTA_URL", Permission::ReadWrite).onSync(CLOUD_WINS); + addPropertyReal(_ota_req, "OTA_REQ", Permission::ReadWrite).onSync(CLOUD_WINS); #endif /* OTA_ENABLED */ #if OTA_STORAGE_PORTENTA_QSPI From 1be94146e063815b178efe121105d126c0da60c3 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 20 Oct 2021 08:44:04 +0200 Subject: [PATCH 189/780] Send cleared _ota_req to cloud to avoid recurring requests --- src/ArduinoIoTCloudTCP.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 3c0685ac6..55a82153b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -514,10 +514,10 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() if (_automatic_ota || (_get_ota_confirmation != nullptr && _get_ota_confirmation())) { /* Clear the error flag. */ _ota_error = static_cast(OTAError::None); - /* Transmit the cleared error flag to the cloud. */ - sendPropertiesToCloud(); /* Clear the request flag. */ _ota_req = false; + /* Transmit the cleared error and request flags to the cloud. */ + sendPropertiesToCloud(); /* Call member function to handle OTA request. */ onOTARequest(); } From f650739f30bbc4d3e6c5ac5a0febe54cf6c96537 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 20 Oct 2021 15:45:21 +0200 Subject: [PATCH 190/780] Add example information --- src/ArduinoIoTCloudTCP.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 38dee3ab2..2eaccb27a 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -85,6 +85,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #if OTA_ENABLED /* The callback is triggered when the OTA is initiated and it gets executed until _ota_req flag is cleared. * It should return true when the OTA can be applied or false otherwise. + * See example ArduinoIoTCloud-DeferredOTA.ino */ void onOTARequestCb(otaConfirmationStatus cb) { _get_ota_confirmation = cb; From 18f84ecd942385bfe93ca99a583341dd7a7480a3 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 25 Oct 2021 17:08:47 +0200 Subject: [PATCH 191/780] Handle _ota_req flag first to avoid running into minimum time between updates check and fail to update the cloud --- src/ArduinoIoTCloudTCP.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 55a82153b..6eabc60c9 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -499,11 +499,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() _mqtt_data_request_retransmit = false; } - /* Check if any properties need encoding and send them to - * the cloud if necessary. - */ - sendPropertiesToCloud(); - #if OTA_ENABLED /* Request a OTA download if the hidden property * OTA request has been set. @@ -524,6 +519,11 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() } #endif /* OTA_ENABLED */ + /* Check if any properties need encoding and send them to + * the cloud if necessary. + */ + sendPropertiesToCloud(); + return State::Connected; } } From 6e9113ce97059d7b57064f4d20b9124185d9c011 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 27 Oct 2021 13:14:48 +0200 Subject: [PATCH 192/780] Use more meaningful name for _automatic_ota and clarify conditions to run OTA update --- src/ArduinoIoTCloudTCP.cpp | 5 ++++- src/ArduinoIoTCloudTCP.h | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 6eabc60c9..b166c25f9 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -95,6 +95,7 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _ota_img_sha256{"Inv."} , _ota_url{""} , _ota_req{false} +, _ask_user_before_executing_ota{false} #endif /* OTA_ENABLED */ { @@ -506,7 +507,9 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() if (_ota_req) { - if (_automatic_ota || (_get_ota_confirmation != nullptr && _get_ota_confirmation())) { + bool const ota_execution_allowed_by_user = (_get_ota_confirmation != nullptr && _get_ota_confirmation()); + bool const perform_ota_now = ota_execution_allowed_by_user || !_ask_user_before_executing_ota; + if (perform_ota_now) { /* Clear the error flag. */ _ota_error = static_cast(OTAError::None); /* Clear the request flag. */ diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 2eaccb27a..bca27e304 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -89,7 +89,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass */ void onOTARequestCb(otaConfirmationStatus cb) { _get_ota_confirmation = cb; - _automatic_ota = false; + _ask_user_before_executing_ota = true; } #endif @@ -142,7 +142,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass String _ota_img_sha256; String _ota_url; bool _ota_req; - bool _automatic_ota = true; + bool _ask_user_before_executing_ota; #endif /* OTA_ENABLED */ inline String getTopic_shadowout() { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/shadow/o"); } From 00a2f6bdfc7c68a293d10b800818074f3b8f93ca Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 27 Oct 2021 13:24:46 +0200 Subject: [PATCH 193/780] Initialize _get_ota_confirmation within constructor and chage type name --- src/ArduinoIoTCloudTCP.cpp | 1 + src/ArduinoIoTCloudTCP.h | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index b166c25f9..6ac511cba 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -96,6 +96,7 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _ota_url{""} , _ota_req{false} , _ask_user_before_executing_ota{false} +, _get_ota_confirmation{nullptr} #endif /* OTA_ENABLED */ { diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index bca27e304..fa04a6e33 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -49,7 +49,11 @@ static uint16_t const DEFAULT_BROKER_PORT_SECURE_AUTH = 8883; static char const DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH[] = "mqtts-up.iot.arduino.cc"; static uint16_t const DEFAULT_BROKER_PORT_USER_PASS_AUTH = 8884; -typedef bool (*otaConfirmationStatus)(void); +/****************************************************************************** + * TYPEDEF + ******************************************************************************/ + +typedef bool (*onOTARequestCallbackFunc)(void); /****************************************************************************** * CLASS DECLARATION @@ -87,7 +91,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass * It should return true when the OTA can be applied or false otherwise. * See example ArduinoIoTCloud-DeferredOTA.ino */ - void onOTARequestCb(otaConfirmationStatus cb) { + void onOTARequestCb(onOTARequestCallbackFunc cb) { _get_ota_confirmation = cb; _ask_user_before_executing_ota = true; } @@ -143,6 +147,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass String _ota_url; bool _ota_req; bool _ask_user_before_executing_ota; + onOTARequestCallbackFunc _get_ota_confirmation; #endif /* OTA_ENABLED */ inline String getTopic_shadowout() { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/shadow/o"); } @@ -167,7 +172,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass void onOTARequest(); #endif - otaConfirmationStatus _get_ota_confirmation = {nullptr}; }; /****************************************************************************** From 6f51148822a73a6688e34b6f726b90d8c3a72af4 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 27 Oct 2021 13:40:30 +0200 Subject: [PATCH 194/780] Clarify onOTARequestCb usage in the example sketch --- .../ArduinoIoTCloud-DeferredOTA.ino | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino index dba9927fb..34abcdc38 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino +++ b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino @@ -46,6 +46,14 @@ bool ask_user_via_serial() { return false; } +bool onOTARequestCallback() +{ + /* Select the preferred behaviour changing the called function */ + //return always_deny(); + //return always_allow(); + return ask_user_via_serial(); +} + void setup() { /* Initialize serial and wait up to 5 seconds for port to open */ Serial.begin(9600); @@ -61,7 +69,7 @@ void setup() { ArduinoCloud.begin(ArduinoIoTPreferredConnection); /* Setup OTA callback */ - ArduinoCloud.onOTARequestCb(always_deny); + ArduinoCloud.onOTARequestCb(onOTARequestCallback); setDebugMessageLevel(DBG_INFO); ArduinoCloud.printDebugInfo(); From 93bb40aaeb6e69d3c9858947ae60dba6b4bbd17d Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 4 Nov 2021 13:05:03 +0100 Subject: [PATCH 195/780] Add missing channelMask parameter for LoraConnectionHandler --- examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index f5628033a..549f80f7b 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -34,7 +34,7 @@ void initProperties() { #elif defined(BOARD_HAS_GSM) GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_LORA) - LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, _lora_class::CLASS_A); + LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #endif From 4c3af93292665da522f79fce88f152df825fd756 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Thu, 4 Nov 2021 14:09:55 +0100 Subject: [PATCH 196/780] Release v1.3.0 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index d85a4eb08..f84fb820b 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.2.1 +version=1.3.0 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From 533e969eaf382b9c100c89e3d0f58d28671a8da8 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 9 Nov 2021 10:03:29 +0100 Subject: [PATCH 197/780] Enable RTC support for NANO_RP2040_CONNECT --- src/property/Property.cpp | 2 +- src/utility/time/TimeService.cpp | 4 ++-- src/utility/time/TimeService.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index a26a7535c..18eff23b8 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -21,7 +21,7 @@ #undef min #include -#if !defined ARDUINO_ARCH_SAMD && !defined TARGET_PORTENTA_H7 +#if !defined ARDUINO_ARCH_SAMD && !defined ARDUINO_ARCH_MBED #pragma message "No RTC available on this architecture - ArduinoIoTCloud will not keep track of local change timestamps ." #endif diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 32a20327c..dcd15f83b 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -51,7 +51,7 @@ static time_t const EPOCH_AT_COMPILE_TIME = cvt_time(__DATE__); TimeService::TimeService() : _con_hdl(nullptr) -#if defined (ARDUINO_ARCH_SAMD) || defined (TARGET_PORTENTA_H7) +#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) , _is_rtc_configured(false) #endif { @@ -79,7 +79,7 @@ unsigned long TimeService::getTime() _is_rtc_configured = true; } return rtc.getEpoch(); -#elif TARGET_PORTENTA_H7 +#elif ARDUINO_ARCH_MBED if(!_is_rtc_configured) { set_time(getRemoteTime()); diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index cc200c813..ae8c12f35 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -28,7 +28,7 @@ #include #endif -#ifdef TARGET_PORTENTA_H7 +#ifdef ARDUINO_ARCH_MBED #include #endif @@ -50,7 +50,7 @@ class TimeService private: ConnectionHandler * _con_hdl; -#if defined (ARDUINO_ARCH_SAMD) || defined (TARGET_PORTENTA_H7) +#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) bool _is_rtc_configured; #endif From 4d1a0d6901d868f5d848c2e12d855f1165cc5110 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 11 Nov 2021 12:17:56 +0100 Subject: [PATCH 198/780] Fix ota properties synchronization ensuring all ota properties are sent together in a single message. --- src/ArduinoIoTCloudTCP.cpp | 36 +++++++++++++++++++++++++++++++++--- src/ArduinoIoTCloudTCP.h | 1 + 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 6ac511cba..9c3524fe0 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -34,7 +34,6 @@ #endif #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) -# include # include "tls/utility/SHA256.h" # include # include @@ -42,7 +41,7 @@ #include "utility/ota/OTA.h" #include "utility/ota/FlashSHA256.h" - +#include #include "cbor/CBOREncoder.h" #include "utility/watchdog/Watchdog.h" @@ -516,7 +515,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() /* Clear the request flag. */ _ota_req = false; /* Transmit the cleared error and request flags to the cloud. */ - sendPropertiesToCloud(); + sendOTAPropertiesToCloud(); /* Call member function to handle OTA request. */ onOTARequest(); } @@ -581,6 +580,37 @@ void ArduinoIoTCloudTCP::sendPropertiesToCloud() } } +void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() +{ + int bytes_encoded = 0; + uint8_t data[MQTT_TRANSMIT_BUFFER_SIZE]; + + PropertyContainer ota_property_container; + + std::list const ota_property_list {"OTA_CAP", "OTA_ERROR", "OTA_SHA256", "OTA_URL", "OTA_REQ"}; + std::for_each(ota_property_list.cbegin(), + ota_property_list.cend(), + [this, &ota_property_container ] (String const & name) + { + Property* p = getProperty(this->_property_container, name); + if(p != nullptr) + addPropertyToContainer(ota_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); + } + ); + + if (CBOREncoder::encode(ota_property_container, data, sizeof(data), bytes_encoded, false) == CborNoError) + if (bytes_encoded > 0) + { + /* If properties have been encoded store them in the back-up buffer + * in order to allow retransmission in case of failure. + */ + _mqtt_data_len = bytes_encoded; + memcpy(_mqtt_data_buf, data, _mqtt_data_len); + /* Transmit the properties to the MQTT broker */ + write(_dataTopicOut, _mqtt_data_buf, _mqtt_data_len); + } +} + void ArduinoIoTCloudTCP::requestLastValue() { // Send the getLastValues CBOR message to the cloud diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index fa04a6e33..351bc6f40 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -165,6 +165,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass static void onMessage(int length); void handleMessage(int length); void sendPropertiesToCloud(); + void sendOTAPropertiesToCloud(); void requestLastValue(); int write(String const topic, byte const data[], int const length); From 052b30e8b200a82f239a66d764f45b5644bb78f1 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 11 Nov 2021 16:14:13 +0100 Subject: [PATCH 199/780] Added generic function ArduinoIoTCloudTCP::sendPropertyContainerToCloud --- src/ArduinoIoTCloudTCP.cpp | 24 ++++++++---------------- src/ArduinoIoTCloudTCP.h | 1 + 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 9c3524fe0..4d4f86b9d 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -562,12 +562,12 @@ void ArduinoIoTCloudTCP::handleMessage(int length) } } -void ArduinoIoTCloudTCP::sendPropertiesToCloud() +void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(PropertyContainer & property_container) { int bytes_encoded = 0; uint8_t data[MQTT_TRANSMIT_BUFFER_SIZE]; - if (CBOREncoder::encode(_property_container, data, sizeof(data), bytes_encoded, false) == CborNoError) + if (CBOREncoder::encode(property_container, data, sizeof(data), bytes_encoded, false) == CborNoError) if (bytes_encoded > 0) { /* If properties have been encoded store them in the back-up buffer @@ -580,11 +580,13 @@ void ArduinoIoTCloudTCP::sendPropertiesToCloud() } } -void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() +void ArduinoIoTCloudTCP::sendPropertiesToCloud() { - int bytes_encoded = 0; - uint8_t data[MQTT_TRANSMIT_BUFFER_SIZE]; + sendPropertyContainerToCloud(_property_container); +} +void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() +{ PropertyContainer ota_property_container; std::list const ota_property_list {"OTA_CAP", "OTA_ERROR", "OTA_SHA256", "OTA_URL", "OTA_REQ"}; @@ -598,17 +600,7 @@ void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() } ); - if (CBOREncoder::encode(ota_property_container, data, sizeof(data), bytes_encoded, false) == CborNoError) - if (bytes_encoded > 0) - { - /* If properties have been encoded store them in the back-up buffer - * in order to allow retransmission in case of failure. - */ - _mqtt_data_len = bytes_encoded; - memcpy(_mqtt_data_buf, data, _mqtt_data_len); - /* Transmit the properties to the MQTT broker */ - write(_dataTopicOut, _mqtt_data_buf, _mqtt_data_len); - } + sendPropertyContainerToCloud(ota_property_container); } void ArduinoIoTCloudTCP::requestLastValue() diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 351bc6f40..21063c29f 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -164,6 +164,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass static void onMessage(int length); void handleMessage(int length); + void sendPropertyContainerToCloud(PropertyContainer & property_container); void sendPropertiesToCloud(); void sendOTAPropertiesToCloud(); void requestLastValue(); From c7ed9d793d882773939e9ae30135fd4ceeae778a Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Fri, 12 Nov 2021 12:37:01 +0100 Subject: [PATCH 200/780] Release v1.3.1 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index f84fb820b..7306aa2ec 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.3.0 +version=1.3.1 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From 30cfea3db02c47630b96e5a7069335b98a524036 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 5 Oct 2021 11:52:19 +0200 Subject: [PATCH 201/780] Initial scheduler implementation --- src/property/PropertyContainer.h | 1 + src/property/types/CloudScheduler.h | 190 ++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 src/property/types/CloudScheduler.h diff --git a/src/property/PropertyContainer.h b/src/property/PropertyContainer.h index fc038f583..65882afe4 100644 --- a/src/property/PropertyContainer.h +++ b/src/property/PropertyContainer.h @@ -40,6 +40,7 @@ #include "types/CloudUnsignedInt.h" #include "types/CloudString.h" #include "types/CloudLocation.h" +#include "types/CloudScheduler.h" #include "types/CloudColor.h" #include "types/CloudWrapperBase.h" diff --git a/src/property/types/CloudScheduler.h b/src/property/types/CloudScheduler.h new file mode 100644 index 000000000..97d6f45fe --- /dev/null +++ b/src/property/types/CloudScheduler.h @@ -0,0 +1,190 @@ +// +// This file is part of ArduinoCloudThing +// +// Copyright 2021 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of ArduinoCloudThing. +// 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 CLOUDSCHEDULER_H_ +#define CLOUDSCHEDULER_H_ + +/****************************************************************************** + INCLUDE + ******************************************************************************/ + +#include +#include "../Property.h" +#include "utility/time/TimeService.h" +#include + +/****************************************************************************** + CLASS DECLARATION + ******************************************************************************/ +enum class MaskType : int { + minute = 0, + hour = 1, + day = 2, + week = 3, /*Weekly daymask */ + month = 4, /*Day of the month 1-31 */ + year = 5 /*Month 1-12 + Day of the month 1-31 */ +}; + +class Scheduler : public TimeService { + public: + unsigned int start, end, duration; + int type; + unsigned int mask; + Scheduler(unsigned int s, unsigned int e, unsigned int d, int t, unsigned int m): start(s), end(e), duration(d), type(t), mask(m) {} + + bool isActive() { + + unsigned int now = getTime(); + if(now >= start && (now < end || end == 0)) { + /* We are in the schedule range */ + + if(type == 3 || type == 4 || type == 5) { + unsigned int nowmask = timeToMask(type, now); + if ( (nowmask & mask) == 0) { + /* This is not the correct Day or Month */ + return false; + } + } + + /* We can assume now that the schedule is always repeating with fixed delta */ + unsigned int delta = getScheduleDelta(type, mask); + if ( ( (std::max(now , start) - std::min(now , start)) % delta ) <= duration ) { + return true; + } + } + return false; + } + + Scheduler& operator=(Scheduler & aScheduler) { + start = aScheduler.start; + end = aScheduler.end; + duration = aScheduler.duration; + type = aScheduler.type; + mask = aScheduler.mask; + return *this; + } + + bool operator==(Scheduler & aScheduler) { + return start == aScheduler.start && end == aScheduler.end && duration == aScheduler.duration && type == aScheduler.type && mask == aScheduler.mask; + } + + bool operator!=(Scheduler & aScheduler) { + return !(operator==(aScheduler)); + } + private: + + unsigned int timeToMask(int type, time_t rawtime) { + struct tm * ptm; + ptm = gmtime ( &rawtime ); + + if (type == 3) { + return 1 << ptm->tm_wday; + } + + if (type == 4) { + return ptm->tm_mday; + } + + if (type == 5) { + return (tm->tm_mon << 16) | ptm->tm_mday; + } + return 0; + } + + unsigned int getScheduleDelta(int type, unsigned int mask) { + if (type == 0) { + return 60 * mask; + } + + if (type == 1) { + return 60 * 60 * mask; + } + + if (type == 2) { + return 60 * 60 * 24 * mask; + } + + if (type == 3) { + return 60 * 60 * 24; + } + + if (type == 4) { + return 60 * 60 * 24; + } + + if (type == 5) { + return 60 * 60 * 24; + } + return 0; + } +}; + +class CloudScheduler : public Property { + private: + Scheduler _value, + _cloud_value; + public: + CloudScheduler() : _value(0, 0, 0, 0, 0), _cloud_value(0, 0, 0, 0, 0) {} + CloudScheduler(unsigned int start, unsigned int end, unsigned int duration, int type, unsigned int mask) : _value(start, end, duration, type, mask), _cloud_value(start, end, duration, type, mask) {} + + virtual bool isDifferentFromCloud() { + + return _value != _cloud_value; + } + + CloudScheduler& operator=(Scheduler aScheduler) { + _value.start = aScheduler.start; + _value.end = aScheduler.end; + _value.duration = aScheduler.duration; + _value.type = aScheduler.type; + _value.mask = aScheduler.mask; + updateLocalTimestamp(); + return *this; + } + + Scheduler getCloudValue() { + return _cloud_value; + } + + Scheduler getValue() { + return _value; + } + + virtual void fromCloudToLocal() { + _value = _cloud_value; + } + virtual void fromLocalToCloud() { + _cloud_value = _value; + } + virtual CborError appendAttributesToCloud() { + CHECK_CBOR(appendAttribute(_value.start)); + CHECK_CBOR(appendAttribute(_value.end)); + CHECK_CBOR(appendAttribute(_value.duration)); + CHECK_CBOR(appendAttribute(_value.type)); + CHECK_CBOR(appendAttribute(_value.mask)); + return CborNoError; + } + virtual void setAttributesFromCloud() { + setAttribute(_cloud_value.start); + setAttribute(_cloud_value.end); + setAttribute(_cloud_value.duration); + setAttribute(_cloud_value.type); + setAttribute(_cloud_value.mask); + } +}; + +#endif /* CLOUDSCHEDULER_H_ */ From dd0ccf55df4c9536f875e9693b5ed47fa8c746d1 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 6 Oct 2021 17:05:13 +0200 Subject: [PATCH 202/780] Initial Scheduler tests --- extras/test/CMakeLists.txt | 1 + .../test/include/Arduino_ConnectionHandler.h | 14 +++++ extras/test/src/test_CloudScheduler.cpp | 53 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 extras/test/include/Arduino_ConnectionHandler.h create mode 100644 extras/test/src/test_CloudScheduler.cpp diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index dd7b3e990..92b1c3a14 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -32,6 +32,7 @@ set(TEST_SRCS src/test_callback.cpp src/test_CloudColor.cpp src/test_CloudLocation.cpp + src/test_CloudScheduler.cpp src/test_decode.cpp src/test_encode.cpp src/test_publishEvery.cpp diff --git a/extras/test/include/Arduino_ConnectionHandler.h b/extras/test/include/Arduino_ConnectionHandler.h new file mode 100644 index 000000000..babc86f08 --- /dev/null +++ b/extras/test/include/Arduino_ConnectionHandler.h @@ -0,0 +1,14 @@ +/* + Copyright (c) 2019 Arduino. All rights reserved. +*/ + +#ifndef TEST_ARDUINO_CONNECTION_HANDLER_H_ +#define TEST_ARDUINO_CONNECTION_HANDLER_H_ + +/****************************************************************************** + TYPEDEF + ******************************************************************************/ + +typedef void ConnectionHandler; + +#endif /* TEST_ARDUINO_CONNECTION_HANDLER_H_ */ diff --git a/extras/test/src/test_CloudScheduler.cpp b/extras/test/src/test_CloudScheduler.cpp new file mode 100644 index 000000000..475dfb282 --- /dev/null +++ b/extras/test/src/test_CloudScheduler.cpp @@ -0,0 +1,53 @@ +/* + Copyright (c) 2021 Arduino. All rights reserved. +*/ + +/************************************************************************************** + INCLUDE + **************************************************************************************/ + +#include + +#include + +unsigned long time_now = 1; + +/************************************************************************************** + * TimeService Fake CTOR/DTOR + **************************************************************************************/ + +TimeService::TimeService() {} + +/************************************************************************************** + * TimeService Fake Methods + **************************************************************************************/ + +unsigned long TimeService::getTime() {return time_now;} + +/************************************************************************************** + TEST CODE + **************************************************************************************/ + +SCENARIO("Tesing cloud type 'Scheduler' Ctor", "[Scheduler::Scheduler]") +{ + WHEN("A Scheduler(0,0,0,0,0) is being instantiated") + { + Scheduler schedule(0,0,0,0,0); + THEN("The member variable 'start' should be 0") { + REQUIRE(schedule.start == 0); + } + THEN("The member variable 'end' should be 0") { + REQUIRE(schedule.end == 0); + } + THEN("The member variable 'duration' should be 0") { + REQUIRE(schedule.duration == 0); + } + THEN("The member variable 'type' should be 0") { + REQUIRE(schedule.type == 0); + } + THEN("The member variable 'mask' should be 0") { + REQUIRE(schedule.mask == 0); + } + } +} + From 5c30e04ba8f76c9f21032e68c00dd5d05abdfd56 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 7 Oct 2021 11:30:50 +0200 Subject: [PATCH 203/780] Add tests for x minutes and weekly schedule --- extras/test/src/test_CloudScheduler.cpp | 143 ++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/extras/test/src/test_CloudScheduler.cpp b/extras/test/src/test_CloudScheduler.cpp index 475dfb282..119599b07 100644 --- a/extras/test/src/test_CloudScheduler.cpp +++ b/extras/test/src/test_CloudScheduler.cpp @@ -51,3 +51,146 @@ SCENARIO("Tesing cloud type 'Scheduler' Ctor", "[Scheduler::Scheduler]") } } +/**************************************************************************************/ + +SCENARIO("Setup a schedule that repeats each 20 minutes and test isActive Method", "[Scheduler::isActive]") +{ + Scheduler schedule(1633305600, /* Start 4/10/2021 00:00:00 */ + 1633651200, /* End 8/10/2021 00:00:00 */ + 600, /* Duration 00:10:00 */ + 0, /* Minutes */ + 20 /* Repeats 00:20:00 */ + ); + + WHEN("Time is 4/10/2021 00:00:00") + { + time_now = 1633305600; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 4/10/2021 00:10:00") + { + time_now = 1633306200; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 4/10/2021 00:10:01") + { + time_now = 1633306201; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 4/10/2021 00:19:59") + { + time_now = 1633306799; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 4/10/2021 00:20:00") + { + time_now = 1633306800; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 7/10/2021 23:45:00") + { + time_now = 1633650300; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 7/10/2021 23:55:00") + { + time_now = 1633650900; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 8/10/2021 00:00:00") + { + time_now = 1633651200; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 8/10/2021 00:05:00") + { + time_now = 1633651500; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } +} + +/**************************************************************************************/ + +SCENARIO("Setup a weekly schedule and test isActive Method", "[Scheduler::isActive]") +{ + Scheduler schedule(1633305600, /* Start 4/10/2021 00:00:00 */ + 1633651200, /* End 8/10/2021 00:00:00 */ + 600, /* Duration 00:10:00 */ + 3, /* Weekly */ + 70 /* Daymask 1000110 */ + ); + + WHEN("Time is 4/10/2021 00:05:00") + { + time_now = 1633305900; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 4/10/2021 00:25:00") + { + time_now = 1633307100; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 5/10/2021 00:05:00") + { + time_now = 1633392300; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 5/10/2021 00:25:00") + { + time_now = 1633393500; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 6/10/2021 00:05:00") + { + time_now = 1633478700; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 7/10/2021 00:05:00") + { + time_now = 1633565100; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } +} From e8273838d8b87099e8a277ca9a652a1b91d7a9a8 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 26 Oct 2021 13:20:08 +0200 Subject: [PATCH 204/780] Scheduler property refactoring --- extras/test/src/test_CloudScheduler.cpp | 15 +- src/property/types/CloudScheduler.h | 228 ++++++++++++++++++------ 2 files changed, 180 insertions(+), 63 deletions(-) diff --git a/extras/test/src/test_CloudScheduler.cpp b/extras/test/src/test_CloudScheduler.cpp index 119599b07..530a54c6a 100644 --- a/extras/test/src/test_CloudScheduler.cpp +++ b/extras/test/src/test_CloudScheduler.cpp @@ -30,9 +30,9 @@ unsigned long TimeService::getTime() {return time_now;} SCENARIO("Tesing cloud type 'Scheduler' Ctor", "[Scheduler::Scheduler]") { - WHEN("A Scheduler(0,0,0,0,0) is being instantiated") + WHEN("A Scheduler(0,0,0,0) is being instantiated") { - Scheduler schedule(0,0,0,0,0); + Scheduler schedule(0,0,0,0); THEN("The member variable 'start' should be 0") { REQUIRE(schedule.start == 0); } @@ -42,9 +42,6 @@ SCENARIO("Tesing cloud type 'Scheduler' Ctor", "[Scheduler::Scheduler]") THEN("The member variable 'duration' should be 0") { REQUIRE(schedule.duration == 0); } - THEN("The member variable 'type' should be 0") { - REQUIRE(schedule.type == 0); - } THEN("The member variable 'mask' should be 0") { REQUIRE(schedule.mask == 0); } @@ -58,8 +55,8 @@ SCENARIO("Setup a schedule that repeats each 20 minutes and test isActive Method Scheduler schedule(1633305600, /* Start 4/10/2021 00:00:00 */ 1633651200, /* End 8/10/2021 00:00:00 */ 600, /* Duration 00:10:00 */ - 0, /* Minutes */ - 20 /* Repeats 00:20:00 */ + 1140850708 /* Minutes */ + /* Repeats 00:20:00 */ ); WHEN("Time is 4/10/2021 00:00:00") @@ -142,8 +139,8 @@ SCENARIO("Setup a weekly schedule and test isActive Method", "[Scheduler::isActi Scheduler schedule(1633305600, /* Start 4/10/2021 00:00:00 */ 1633651200, /* End 8/10/2021 00:00:00 */ 600, /* Duration 00:10:00 */ - 3, /* Weekly */ - 70 /* Daymask 1000110 */ + 134217798 /* Weekly */ + /* Daymask 1000110 */ ); WHEN("Time is 4/10/2021 00:05:00") diff --git a/src/property/types/CloudScheduler.h b/src/property/types/CloudScheduler.h index 97d6f45fe..c0d258a93 100644 --- a/src/property/types/CloudScheduler.h +++ b/src/property/types/CloudScheduler.h @@ -30,41 +30,25 @@ /****************************************************************************** CLASS DECLARATION ******************************************************************************/ -enum class MaskType : int { - minute = 0, - hour = 1, - day = 2, - week = 3, /*Weekly daymask */ - month = 4, /*Day of the month 1-31 */ - year = 5 /*Month 1-12 + Day of the month 1-31 */ -}; - class Scheduler : public TimeService { public: - unsigned int start, end, duration; - int type; - unsigned int mask; - Scheduler(unsigned int s, unsigned int e, unsigned int d, int t, unsigned int m): start(s), end(e), duration(d), type(t), mask(m) {} + unsigned int start, end, duration, mask; + Scheduler(unsigned int s, unsigned int e, unsigned int d, unsigned int m): start(s), end(e), duration(d), mask(m) {} bool isActive() { unsigned int now = getTime(); - if(now >= start && (now < end || end == 0)) { + if(checkSchedulePeriod(now, start, end)) { /* We are in the schedule range */ - if(type == 3 || type == 4 || type == 5) { - unsigned int nowmask = timeToMask(type, now); - if ( (nowmask & mask) == 0) { - /* This is not the correct Day or Month */ - return false; + if(checkScheduleMask(now, mask)) { + + /* We can assume now that the schedule is always repeating with fixed delta */ + unsigned int delta = getScheduleDelta(mask); + if ( ( (std::max(now , start) - std::min(now , start)) % delta ) <= duration ) { + return true; } } - - /* We can assume now that the schedule is always repeating with fixed delta */ - unsigned int delta = getScheduleDelta(type, mask); - if ( ( (std::max(now , start) - std::min(now , start)) % delta ) <= duration ) { - return true; - } } return false; } @@ -73,62 +57,201 @@ class Scheduler : public TimeService { start = aScheduler.start; end = aScheduler.end; duration = aScheduler.duration; - type = aScheduler.type; mask = aScheduler.mask; return *this; } bool operator==(Scheduler & aScheduler) { - return start == aScheduler.start && end == aScheduler.end && duration == aScheduler.duration && type == aScheduler.type && mask == aScheduler.mask; + return start == aScheduler.start && end == aScheduler.end && duration == aScheduler.duration && mask == aScheduler.mask; } bool operator!=(Scheduler & aScheduler) { return !(operator==(aScheduler)); } private: + bool isScheduleOneShot(unsigned int mask) { + if((mask & 0x3C000000) == 0x00000000) { + return true; + } else { + return false; + } + } - unsigned int timeToMask(int type, time_t rawtime) { - struct tm * ptm; - ptm = gmtime ( &rawtime ); + bool isScheduleFixed(unsigned int mask) { + if((mask & 0x3C000000) == 0x04000000) { + return true; + } else { + return false; + } + } - if (type == 3) { - return 1 << ptm->tm_wday; + bool isScheduleWeekly(unsigned int mask) { + if((mask & 0x3C000000) == 0x08000000) { + return true; + } else { + return false; } + } - if (type == 4) { - return ptm->tm_mday; + bool isScheduleMonthly(unsigned int mask) { + if((mask & 0x3C000000) == 0x0C000000) { + return true; + } else { + return false; } + } - if (type == 5) { - return (tm->tm_mon << 16) | ptm->tm_mday; + bool isScheduleYearly(unsigned int mask) { + if((mask & 0x3C000000) == 0x10000000) { + return true; + } else { + return false; } - return 0; } - unsigned int getScheduleDelta(int type, unsigned int mask) { - if (type == 0) { - return 60 * mask; + bool isScheduleInSeconds(unsigned int mask) { + if((mask & 0xC0000000) == 0x00000000) { + return true; + } else { + return false; } + } - if (type == 1) { - return 60 * 60 * mask; + bool isScheduleInMinutes(unsigned int mask) { + if((mask & 0xC0000000) == 0x40000000) { + return true; + } else { + return false; } + } - if (type == 2) { - return 60 * 60 * 24 * mask; + bool isScheduleInHours(unsigned int mask) { + if((mask & 0xC0000000) == 0x80000000) { + return true; + } else { + return false; } + } - if (type == 3) { - return 60 * 60 * 24; + bool isScheduleInDays(unsigned int mask) { + if((mask & 0xC0000000) == 0xC0000000) { + return true; + } else { + return false; } + } - if (type == 4) { - return 60 * 60 * 24; + unsigned int timeToWeekMask(time_t rawtime) { + struct tm * ptm; + ptm = gmtime ( &rawtime ); + + return 1 << ptm->tm_wday; + } + + unsigned int timeToDay(time_t rawtime) { + struct tm * ptm; + ptm = gmtime ( &rawtime ); + + return ptm->tm_mday; + } + + unsigned int timeToMonth(time_t rawtime) { + struct tm * ptm; + ptm = gmtime ( &rawtime ); + + return ptm->tm_mon; + } + + unsigned int getScheduleRawMask(unsigned int mask) { + return mask & 0x03FFFFFF; + } + + unsigned int getScheduleWeekMask(unsigned int mask) { + return mask & 0x000000FF; + } + + unsigned int getScheduleDay(unsigned int mask) { + return mask & 0x000000FF; + } + + unsigned int getScheduleMonth(unsigned int mask) { + return (mask & 0x0000FF00) >> 8; + } + + bool checkSchedulePeriod(unsigned int now, unsigned int start, unsigned int end) { + if(now >= start && (now < end || end == 0)) { + return true; + } else { + return false; + } + } + + bool checkScheduleMask(unsigned int now, unsigned int mask) { + if(isScheduleFixed(mask) || isScheduleOneShot(mask)) { + return true; + } + + if(isScheduleWeekly(mask)) { + unsigned int nowMask = timeToWeekMask(now); + unsigned int scheduleMask = getScheduleWeekMask(mask); + + if((nowMask & scheduleMask) == 0) { + return false; + } else { + return true; + } + } + + if(isScheduleMonthly(mask)) { + unsigned int nowDay = timeToDay(now); + unsigned int scheduleDay = getScheduleDay(mask); + + if(nowDay != scheduleDay) { + return false; + } else { + return true; + } + } + + if(isScheduleYearly(mask)) { + unsigned int nowDay = timeToDay(now); + unsigned int scheduleDay = getScheduleDay(mask); + unsigned int nowMonth = timeToMonth(now); + unsigned int scheduleMonth = getScheduleMonth(mask); + + if((nowDay != scheduleDay) || (nowMonth != scheduleMonth)) { + return false; + } else { + return true; + } + } + + return false; + } + + unsigned int getScheduleDelta(unsigned int mask) { + if(isScheduleOneShot(mask)) { + return 0xFFFFFFFF; } + + if(isScheduleFixed(mask)) { + if(isScheduleInSeconds(mask)) { + return getScheduleRawMask(mask); + } + + if(isScheduleInMinutes(mask)) { + return 60 * getScheduleRawMask(mask); + } - if (type == 5) { + if(isScheduleInHours(mask)) { + return 60 * 60 * getScheduleRawMask(mask); + } + } + + if(isScheduleWeekly(mask) || isScheduleMonthly(mask) || isScheduleYearly(mask)) { return 60 * 60 * 24; } + return 0; } }; @@ -138,8 +261,8 @@ class CloudScheduler : public Property { Scheduler _value, _cloud_value; public: - CloudScheduler() : _value(0, 0, 0, 0, 0), _cloud_value(0, 0, 0, 0, 0) {} - CloudScheduler(unsigned int start, unsigned int end, unsigned int duration, int type, unsigned int mask) : _value(start, end, duration, type, mask), _cloud_value(start, end, duration, type, mask) {} + CloudScheduler() : _value(0, 0, 0, 0), _cloud_value(0, 0, 0, 0) {} + CloudScheduler(unsigned int start, unsigned int end, unsigned int duration, unsigned int mask) : _value(start, end, duration, mask), _cloud_value(start, end, duration, mask) {} virtual bool isDifferentFromCloud() { @@ -150,7 +273,6 @@ class CloudScheduler : public Property { _value.start = aScheduler.start; _value.end = aScheduler.end; _value.duration = aScheduler.duration; - _value.type = aScheduler.type; _value.mask = aScheduler.mask; updateLocalTimestamp(); return *this; @@ -174,7 +296,6 @@ class CloudScheduler : public Property { CHECK_CBOR(appendAttribute(_value.start)); CHECK_CBOR(appendAttribute(_value.end)); CHECK_CBOR(appendAttribute(_value.duration)); - CHECK_CBOR(appendAttribute(_value.type)); CHECK_CBOR(appendAttribute(_value.mask)); return CborNoError; } @@ -182,7 +303,6 @@ class CloudScheduler : public Property { setAttribute(_cloud_value.start); setAttribute(_cloud_value.end); setAttribute(_cloud_value.duration); - setAttribute(_cloud_value.type); setAttribute(_cloud_value.mask); } }; From a3a739e57d22759461bf0258dde33ef7ce975ecc Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 26 Oct 2021 14:09:46 +0200 Subject: [PATCH 205/780] Add monthly yearly and oneshot schedule tests --- extras/test/src/test_CloudScheduler.cpp | 316 ++++++++++++++++++++++++ 1 file changed, 316 insertions(+) diff --git a/extras/test/src/test_CloudScheduler.cpp b/extras/test/src/test_CloudScheduler.cpp index 530a54c6a..a505cea15 100644 --- a/extras/test/src/test_CloudScheduler.cpp +++ b/extras/test/src/test_CloudScheduler.cpp @@ -191,3 +191,319 @@ SCENARIO("Setup a weekly schedule and test isActive Method", "[Scheduler::isActi } } } + +/**************************************************************************************/ + +SCENARIO("Setup a monthly schedule and test isActive Method", "[Scheduler::isActive]") +{ + Scheduler schedule(1633305600, /* Start 4/10/2021 00:00:00 */ + 1664841600, /* End 4/10/2022 00:00:00 */ + 600, /* Duration 00:10:00 */ + 201326598 /* Monthly */ + /* Day of month 6 */ + ); + + WHEN("Time is 6/09/2021 00:05:00") + { + time_now = 1630886700; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 6/10/2021 00:05:00") + { + time_now = 1633478700; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/10/2021 00:25:00") + { + time_now = 1633479900; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 6/11/2021 00:05:00") + { + time_now = 1636157100; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/11/2021 00:25:00") + { + time_now = 1636158300; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 7/11/2021 00:05:00") + { + time_now = 1636243500; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 6/12/2021 00:05:00") + { + time_now = 1638749100; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/01/2022 00:05:00") + { + time_now = 1641427500; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/02/2022 00:05:00") + { + time_now = 1644105900; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/03/2022 00:05:00") + { + time_now = 1646525100; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/04/2022 00:05:00") + { + time_now = 1649203500; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/05/2022 00:05:00") + { + time_now = 1651795500; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/06/2022 00:05:00") + { + time_now = 1654473900; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/07/2022 00:05:00") + { + time_now = 1657065900; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/08/2022 00:05:00") + { + time_now = 1659744300; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/09/2022 00:05:00") + { + time_now = 1662422700; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/10/2022 00:05:00") + { + time_now = 1665014700; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } +} + +/**************************************************************************************/ + +SCENARIO("Setup a yearly schedule and test isActive Method", "[Scheduler::isActive]") +{ + Scheduler schedule(1633305600, /* Start 4/10/2021 00:00:00 */ + 1759536000, /* End 4/10/2025 00:00:00 */ + 600, /* Duration 00:10:00 */ + 268438022 /* Yearly */ + /* Month 11, Day of month 6 */ + ); + + WHEN("Time is 6/11/2020 00:05:00") + { + time_now = 1604621100; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 6/11/2021 00:05:00") + { + time_now = 1636157100; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/11/2021 00:25:00") + { + time_now = 1636158300; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 6/11/2022 00:05:00") + { + time_now = 1667693100; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/11/2022 00:25:00") + { + time_now = 1667694300; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 7/11/2021 00:05:00") + { + time_now = 1636243500; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 6/11/2023 00:05:00") + { + time_now = 1699229100; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/11/2024 00:05:00") + { + time_now = 1730851500; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/11/2025 00:05:00") + { + time_now = 1762387500; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } +} + +/**************************************************************************************/ + +SCENARIO("Setup a one shot schedule and test isActive Method", "[Scheduler::isActive]") +{ + Scheduler schedule(1636156800, /* Start 6/11/2021 00:00:00 */ + 1636243199, /* End 6/11/2021 23:59:59 */ + 600, /* Duration 00:10:00 */ + 0 /* One shot */ + ); + + WHEN("Time is 6/11/2020 00:05:00") + { + time_now = 1604621100; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 6/11/2021 00:05:00") + { + time_now = 1636157100; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 6/11/2021 00:25:00") + { + time_now = 1636158300; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 6/11/2022 00:05:00") + { + time_now = 1667693100; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 7/11/2021 00:05:00") + { + time_now = 1636243500; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 7/11/2021 00:15:00") + { + time_now = 1636244100; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 6/11/2021 00:11:00") + { + time_now = 1636157460; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } + + WHEN("Time is 6/11/2021 00:01:00") + { + time_now = 1636156860; + THEN("Schedule must be active") { + REQUIRE(schedule.isActive() == true); + } + } + + WHEN("Time is 7/11/2021 00:11:00") + { + time_now = 1636243860; + THEN("Schedule must be inactive") { + REQUIRE(schedule.isActive() == false); + } + } +} + From a8e1a772f46536c43d1e328ef09c65bae84b174b Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 27 Oct 2021 10:20:57 +0200 Subject: [PATCH 206/780] Fix typo in comment --- extras/test/src/test_decode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/test/src/test_decode.cpp b/extras/test/src/test_decode.cpp index c95d4afe9..d67afd440 100644 --- a/extras/test/src/test_decode.cpp +++ b/extras/test/src/test_decode.cpp @@ -143,7 +143,7 @@ SCENARIO("Arduino Cloud Properties are decoded", "[ArduinoCloudThing::decode]") CloudLocation location_test = CloudLocation(0, 1); addPropertyToContainer(property_container, location_test, "test", Permission::ReadWrite); - /* [{0: "test:lat", 3: 2},{0: "test:lon", 3: 3}] = 82 A2 00 68 74 65 73 74 3A 6C 61 74 02 02 A2 00 68 74 65 73 74 3A 6C 6F 6E 02 03*/ + /* [{0: "test:lat", 2: 2},{0: "test:lon", 2: 3}] = 82 A2 00 68 74 65 73 74 3A 6C 61 74 02 02 A2 00 68 74 65 73 74 3A 6C 6F 6E 02 03*/ uint8_t const payload[] = { 0x82, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x6C, 0x61, 0x74, 0x02, 0x02, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x6C, 0x6F, 0x6E, 0x02, 0x03 }; CBORDecoder::decode(property_container, payload, sizeof(payload) / sizeof(uint8_t)); Location location_compare = Location(2, 3); From 116851fe7bfff94cb7864bc9db05520fc9c71c03 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 27 Oct 2021 10:46:49 +0200 Subject: [PATCH 207/780] Rename property Scheduler/CloudScheduler to Schedule/CloudSchedule --- extras/test/CMakeLists.txt | 2 +- ...udScheduler.cpp => test_CloudSchedule.cpp} | 28 +++++------ src/property/PropertyContainer.h | 2 +- .../{CloudScheduler.h => CloudSchedule.h} | 50 +++++++++---------- 4 files changed, 41 insertions(+), 41 deletions(-) rename extras/test/src/{test_CloudScheduler.cpp => test_CloudSchedule.cpp} (94%) rename src/property/types/{CloudScheduler.h => CloudSchedule.h} (84%) diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index 92b1c3a14..a2b9c749e 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -32,7 +32,7 @@ set(TEST_SRCS src/test_callback.cpp src/test_CloudColor.cpp src/test_CloudLocation.cpp - src/test_CloudScheduler.cpp + src/test_CloudSchedule.cpp src/test_decode.cpp src/test_encode.cpp src/test_publishEvery.cpp diff --git a/extras/test/src/test_CloudScheduler.cpp b/extras/test/src/test_CloudSchedule.cpp similarity index 94% rename from extras/test/src/test_CloudScheduler.cpp rename to extras/test/src/test_CloudSchedule.cpp index a505cea15..e8d307e2b 100644 --- a/extras/test/src/test_CloudScheduler.cpp +++ b/extras/test/src/test_CloudSchedule.cpp @@ -8,7 +8,7 @@ #include -#include +#include unsigned long time_now = 1; @@ -28,11 +28,11 @@ unsigned long TimeService::getTime() {return time_now;} TEST CODE **************************************************************************************/ -SCENARIO("Tesing cloud type 'Scheduler' Ctor", "[Scheduler::Scheduler]") +SCENARIO("Tesing cloud type 'Schedule' Ctor", "[Schedule::Schedule]") { - WHEN("A Scheduler(0,0,0,0) is being instantiated") + WHEN("A Schedule(0,0,0,0) is being instantiated") { - Scheduler schedule(0,0,0,0); + Schedule schedule(0,0,0,0); THEN("The member variable 'start' should be 0") { REQUIRE(schedule.start == 0); } @@ -50,9 +50,9 @@ SCENARIO("Tesing cloud type 'Scheduler' Ctor", "[Scheduler::Scheduler]") /**************************************************************************************/ -SCENARIO("Setup a schedule that repeats each 20 minutes and test isActive Method", "[Scheduler::isActive]") +SCENARIO("Setup a schedule that repeats each 20 minutes and test isActive Method", "[Schedule::isActive]") { - Scheduler schedule(1633305600, /* Start 4/10/2021 00:00:00 */ + Schedule schedule(1633305600, /* Start 4/10/2021 00:00:00 */ 1633651200, /* End 8/10/2021 00:00:00 */ 600, /* Duration 00:10:00 */ 1140850708 /* Minutes */ @@ -134,9 +134,9 @@ SCENARIO("Setup a schedule that repeats each 20 minutes and test isActive Method /**************************************************************************************/ -SCENARIO("Setup a weekly schedule and test isActive Method", "[Scheduler::isActive]") +SCENARIO("Setup a weekly schedule and test isActive Method", "[Schedule::isActive]") { - Scheduler schedule(1633305600, /* Start 4/10/2021 00:00:00 */ + Schedule schedule(1633305600, /* Start 4/10/2021 00:00:00 */ 1633651200, /* End 8/10/2021 00:00:00 */ 600, /* Duration 00:10:00 */ 134217798 /* Weekly */ @@ -194,9 +194,9 @@ SCENARIO("Setup a weekly schedule and test isActive Method", "[Scheduler::isActi /**************************************************************************************/ -SCENARIO("Setup a monthly schedule and test isActive Method", "[Scheduler::isActive]") +SCENARIO("Setup a monthly schedule and test isActive Method", "[Schedule::isActive]") { - Scheduler schedule(1633305600, /* Start 4/10/2021 00:00:00 */ + Schedule schedule(1633305600, /* Start 4/10/2021 00:00:00 */ 1664841600, /* End 4/10/2022 00:00:00 */ 600, /* Duration 00:10:00 */ 201326598 /* Monthly */ @@ -342,9 +342,9 @@ SCENARIO("Setup a monthly schedule and test isActive Method", "[Scheduler::isAct /**************************************************************************************/ -SCENARIO("Setup a yearly schedule and test isActive Method", "[Scheduler::isActive]") +SCENARIO("Setup a yearly schedule and test isActive Method", "[Schedule::isActive]") { - Scheduler schedule(1633305600, /* Start 4/10/2021 00:00:00 */ + Schedule schedule(1633305600, /* Start 4/10/2021 00:00:00 */ 1759536000, /* End 4/10/2025 00:00:00 */ 600, /* Duration 00:10:00 */ 268438022 /* Yearly */ @@ -426,9 +426,9 @@ SCENARIO("Setup a yearly schedule and test isActive Method", "[Scheduler::isActi /**************************************************************************************/ -SCENARIO("Setup a one shot schedule and test isActive Method", "[Scheduler::isActive]") +SCENARIO("Setup a one shot schedule and test isActive Method", "[Schedule::isActive]") { - Scheduler schedule(1636156800, /* Start 6/11/2021 00:00:00 */ + Schedule schedule(1636156800, /* Start 6/11/2021 00:00:00 */ 1636243199, /* End 6/11/2021 23:59:59 */ 600, /* Duration 00:10:00 */ 0 /* One shot */ diff --git a/src/property/PropertyContainer.h b/src/property/PropertyContainer.h index 65882afe4..8c254875e 100644 --- a/src/property/PropertyContainer.h +++ b/src/property/PropertyContainer.h @@ -40,7 +40,7 @@ #include "types/CloudUnsignedInt.h" #include "types/CloudString.h" #include "types/CloudLocation.h" -#include "types/CloudScheduler.h" +#include "types/CloudSchedule.h" #include "types/CloudColor.h" #include "types/CloudWrapperBase.h" diff --git a/src/property/types/CloudScheduler.h b/src/property/types/CloudSchedule.h similarity index 84% rename from src/property/types/CloudScheduler.h rename to src/property/types/CloudSchedule.h index c0d258a93..a5ecaf288 100644 --- a/src/property/types/CloudScheduler.h +++ b/src/property/types/CloudSchedule.h @@ -15,8 +15,8 @@ // a commercial license, send an email to license@arduino.cc. // -#ifndef CLOUDSCHEDULER_H_ -#define CLOUDSCHEDULER_H_ +#ifndef CLOUDSCHEDULE_H_ +#define CLOUDSCHEDULE_H_ /****************************************************************************** INCLUDE @@ -30,10 +30,10 @@ /****************************************************************************** CLASS DECLARATION ******************************************************************************/ -class Scheduler : public TimeService { +class Schedule : public TimeService { public: unsigned int start, end, duration, mask; - Scheduler(unsigned int s, unsigned int e, unsigned int d, unsigned int m): start(s), end(e), duration(d), mask(m) {} + Schedule(unsigned int s, unsigned int e, unsigned int d, unsigned int m): start(s), end(e), duration(d), mask(m) {} bool isActive() { @@ -53,20 +53,20 @@ class Scheduler : public TimeService { return false; } - Scheduler& operator=(Scheduler & aScheduler) { - start = aScheduler.start; - end = aScheduler.end; - duration = aScheduler.duration; - mask = aScheduler.mask; + Schedule& operator=(Schedule & aSchedule) { + start = aSchedule.start; + end = aSchedule.end; + duration = aSchedule.duration; + mask = aSchedule.mask; return *this; } - bool operator==(Scheduler & aScheduler) { - return start == aScheduler.start && end == aScheduler.end && duration == aScheduler.duration && mask == aScheduler.mask; + bool operator==(Schedule & aSchedule) { + return start == aSchedule.start && end == aSchedule.end && duration == aSchedule.duration && mask == aSchedule.mask; } - bool operator!=(Scheduler & aScheduler) { - return !(operator==(aScheduler)); + bool operator!=(Schedule & aSchedule) { + return !(operator==(aSchedule)); } private: bool isScheduleOneShot(unsigned int mask) { @@ -256,33 +256,33 @@ class Scheduler : public TimeService { } }; -class CloudScheduler : public Property { +class CloudSchedule : public Property { private: - Scheduler _value, + Schedule _value, _cloud_value; public: - CloudScheduler() : _value(0, 0, 0, 0), _cloud_value(0, 0, 0, 0) {} - CloudScheduler(unsigned int start, unsigned int end, unsigned int duration, unsigned int mask) : _value(start, end, duration, mask), _cloud_value(start, end, duration, mask) {} + CloudSchedule() : _value(0, 0, 0, 0), _cloud_value(0, 0, 0, 0) {} + CloudSchedule(unsigned int start, unsigned int end, unsigned int duration, unsigned int mask) : _value(start, end, duration, mask), _cloud_value(start, end, duration, mask) {} virtual bool isDifferentFromCloud() { return _value != _cloud_value; } - CloudScheduler& operator=(Scheduler aScheduler) { - _value.start = aScheduler.start; - _value.end = aScheduler.end; - _value.duration = aScheduler.duration; - _value.mask = aScheduler.mask; + CloudSchedule& operator=(Schedule aSchedule) { + _value.start = aSchedule.start; + _value.end = aSchedule.end; + _value.duration = aSchedule.duration; + _value.mask = aSchedule.mask; updateLocalTimestamp(); return *this; } - Scheduler getCloudValue() { + Schedule getCloudValue() { return _cloud_value; } - Scheduler getValue() { + Schedule getValue() { return _value; } @@ -307,4 +307,4 @@ class CloudScheduler : public Property { } }; -#endif /* CLOUDSCHEDULER_H_ */ +#endif /* CLOUDSCHEDULE_H_ */ From b75b8cdc8bb727baa23fb5734b08b019b4add872 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 27 Oct 2021 17:14:42 +0200 Subject: [PATCH 208/780] Add isActive method to CloudSchedule --- src/property/types/CloudSchedule.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index a5ecaf288..83de15c34 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -286,6 +286,10 @@ class CloudSchedule : public Property { return _value; } + bool isActive() { + return _value.isActive(); + } + virtual void fromCloudToLocal() { _value = _cloud_value; } From 76647d94f2aa6facebc6e5847a58fffa39c8debf Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 28 Oct 2021 11:02:11 +0200 Subject: [PATCH 209/780] Rename CloudSchedule fields from start end duration mask to frm to len msk --- extras/test/src/test_CloudSchedule.cpp | 26 ++--- src/property/types/CloudSchedule.h | 144 ++++++++++++------------- 2 files changed, 85 insertions(+), 85 deletions(-) diff --git a/extras/test/src/test_CloudSchedule.cpp b/extras/test/src/test_CloudSchedule.cpp index e8d307e2b..aba4aad0f 100644 --- a/extras/test/src/test_CloudSchedule.cpp +++ b/extras/test/src/test_CloudSchedule.cpp @@ -33,17 +33,17 @@ SCENARIO("Tesing cloud type 'Schedule' Ctor", "[Schedule::Schedule]") WHEN("A Schedule(0,0,0,0) is being instantiated") { Schedule schedule(0,0,0,0); - THEN("The member variable 'start' should be 0") { - REQUIRE(schedule.start == 0); + THEN("The member variable 'frm' should be 0") { + REQUIRE(schedule.frm == 0); } - THEN("The member variable 'end' should be 0") { - REQUIRE(schedule.end == 0); + THEN("The member variable 'to' should be 0") { + REQUIRE(schedule.to == 0); } - THEN("The member variable 'duration' should be 0") { - REQUIRE(schedule.duration == 0); + THEN("The member variable 'len' should be 0") { + REQUIRE(schedule.len == 0); } - THEN("The member variable 'mask' should be 0") { - REQUIRE(schedule.mask == 0); + THEN("The member variable 'msk' should be 0") { + REQUIRE(schedule.msk == 0); } } } @@ -52,7 +52,7 @@ SCENARIO("Tesing cloud type 'Schedule' Ctor", "[Schedule::Schedule]") SCENARIO("Setup a schedule that repeats each 20 minutes and test isActive Method", "[Schedule::isActive]") { - Schedule schedule(1633305600, /* Start 4/10/2021 00:00:00 */ + Schedule schedule( 1633305600, /* Start 4/10/2021 00:00:00 */ 1633651200, /* End 8/10/2021 00:00:00 */ 600, /* Duration 00:10:00 */ 1140850708 /* Minutes */ @@ -136,7 +136,7 @@ SCENARIO("Setup a schedule that repeats each 20 minutes and test isActive Method SCENARIO("Setup a weekly schedule and test isActive Method", "[Schedule::isActive]") { - Schedule schedule(1633305600, /* Start 4/10/2021 00:00:00 */ + Schedule schedule( 1633305600, /* Start 4/10/2021 00:00:00 */ 1633651200, /* End 8/10/2021 00:00:00 */ 600, /* Duration 00:10:00 */ 134217798 /* Weekly */ @@ -196,7 +196,7 @@ SCENARIO("Setup a weekly schedule and test isActive Method", "[Schedule::isActiv SCENARIO("Setup a monthly schedule and test isActive Method", "[Schedule::isActive]") { - Schedule schedule(1633305600, /* Start 4/10/2021 00:00:00 */ + Schedule schedule( 1633305600, /* Start 4/10/2021 00:00:00 */ 1664841600, /* End 4/10/2022 00:00:00 */ 600, /* Duration 00:10:00 */ 201326598 /* Monthly */ @@ -344,7 +344,7 @@ SCENARIO("Setup a monthly schedule and test isActive Method", "[Schedule::isActi SCENARIO("Setup a yearly schedule and test isActive Method", "[Schedule::isActive]") { - Schedule schedule(1633305600, /* Start 4/10/2021 00:00:00 */ + Schedule schedule( 1633305600, /* Start 4/10/2021 00:00:00 */ 1759536000, /* End 4/10/2025 00:00:00 */ 600, /* Duration 00:10:00 */ 268438022 /* Yearly */ @@ -428,7 +428,7 @@ SCENARIO("Setup a yearly schedule and test isActive Method", "[Schedule::isActiv SCENARIO("Setup a one shot schedule and test isActive Method", "[Schedule::isActive]") { - Schedule schedule(1636156800, /* Start 6/11/2021 00:00:00 */ + Schedule schedule( 1636156800, /* Start 6/11/2021 00:00:00 */ 1636243199, /* End 6/11/2021 23:59:59 */ 600, /* Duration 00:10:00 */ 0 /* One shot */ diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index 83de15c34..fc018b15f 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -32,20 +32,20 @@ ******************************************************************************/ class Schedule : public TimeService { public: - unsigned int start, end, duration, mask; - Schedule(unsigned int s, unsigned int e, unsigned int d, unsigned int m): start(s), end(e), duration(d), mask(m) {} + unsigned int frm, to, len, msk; + Schedule(unsigned int s, unsigned int e, unsigned int d, unsigned int m): frm(s), to(e), len(d), msk(m) {} bool isActive() { unsigned int now = getTime(); - if(checkSchedulePeriod(now, start, end)) { + if(checkSchedulePeriod(now, frm, to)) { /* We are in the schedule range */ - if(checkScheduleMask(now, mask)) { + if(checkScheduleMask(now, msk)) { /* We can assume now that the schedule is always repeating with fixed delta */ - unsigned int delta = getScheduleDelta(mask); - if ( ( (std::max(now , start) - std::min(now , start)) % delta ) <= duration ) { + unsigned int delta = getScheduleDelta(msk); + if ( ( (std::max(now , frm) - std::min(now , frm)) % delta ) <= len ) { return true; } } @@ -54,87 +54,87 @@ class Schedule : public TimeService { } Schedule& operator=(Schedule & aSchedule) { - start = aSchedule.start; - end = aSchedule.end; - duration = aSchedule.duration; - mask = aSchedule.mask; + frm = aSchedule.frm; + to = aSchedule.to; + len = aSchedule.len; + msk = aSchedule.msk; return *this; } bool operator==(Schedule & aSchedule) { - return start == aSchedule.start && end == aSchedule.end && duration == aSchedule.duration && mask == aSchedule.mask; + return frm == aSchedule.frm && to == aSchedule.to && len == aSchedule.len && msk == aSchedule.msk; } bool operator!=(Schedule & aSchedule) { return !(operator==(aSchedule)); } private: - bool isScheduleOneShot(unsigned int mask) { - if((mask & 0x3C000000) == 0x00000000) { + bool isScheduleOneShot(unsigned int msk) { + if((msk & 0x3C000000) == 0x00000000) { return true; } else { return false; } } - bool isScheduleFixed(unsigned int mask) { - if((mask & 0x3C000000) == 0x04000000) { + bool isScheduleFixed(unsigned int msk) { + if((msk & 0x3C000000) == 0x04000000) { return true; } else { return false; } } - bool isScheduleWeekly(unsigned int mask) { - if((mask & 0x3C000000) == 0x08000000) { + bool isScheduleWeekly(unsigned int msk) { + if((msk & 0x3C000000) == 0x08000000) { return true; } else { return false; } } - bool isScheduleMonthly(unsigned int mask) { - if((mask & 0x3C000000) == 0x0C000000) { + bool isScheduleMonthly(unsigned int msk) { + if((msk & 0x3C000000) == 0x0C000000) { return true; } else { return false; } } - bool isScheduleYearly(unsigned int mask) { - if((mask & 0x3C000000) == 0x10000000) { + bool isScheduleYearly(unsigned int msk) { + if((msk & 0x3C000000) == 0x10000000) { return true; } else { return false; } } - bool isScheduleInSeconds(unsigned int mask) { - if((mask & 0xC0000000) == 0x00000000) { + bool isScheduleInSeconds(unsigned int msk) { + if((msk & 0xC0000000) == 0x00000000) { return true; } else { return false; } } - bool isScheduleInMinutes(unsigned int mask) { - if((mask & 0xC0000000) == 0x40000000) { + bool isScheduleInMinutes(unsigned int msk) { + if((msk & 0xC0000000) == 0x40000000) { return true; } else { return false; } } - bool isScheduleInHours(unsigned int mask) { - if((mask & 0xC0000000) == 0x80000000) { + bool isScheduleInHours(unsigned int msk) { + if((msk & 0xC0000000) == 0x80000000) { return true; } else { return false; } } - bool isScheduleInDays(unsigned int mask) { - if((mask & 0xC0000000) == 0xC0000000) { + bool isScheduleInDays(unsigned int msk) { + if((msk & 0xC0000000) == 0xC0000000) { return true; } else { return false; @@ -162,38 +162,38 @@ class Schedule : public TimeService { return ptm->tm_mon; } - unsigned int getScheduleRawMask(unsigned int mask) { - return mask & 0x03FFFFFF; + unsigned int getScheduleRawMask(unsigned int msk) { + return msk & 0x03FFFFFF; } - unsigned int getScheduleWeekMask(unsigned int mask) { - return mask & 0x000000FF; + unsigned int getScheduleWeekMask(unsigned int msk) { + return msk & 0x000000FF; } - unsigned int getScheduleDay(unsigned int mask) { - return mask & 0x000000FF; + unsigned int getScheduleDay(unsigned int msk) { + return msk & 0x000000FF; } - unsigned int getScheduleMonth(unsigned int mask) { - return (mask & 0x0000FF00) >> 8; + unsigned int getScheduleMonth(unsigned int msk) { + return (msk & 0x0000FF00) >> 8; } - bool checkSchedulePeriod(unsigned int now, unsigned int start, unsigned int end) { - if(now >= start && (now < end || end == 0)) { + bool checkSchedulePeriod(unsigned int now, unsigned int frm, unsigned int to) { + if(now >= frm && (now < to || to == 0)) { return true; } else { return false; } } - bool checkScheduleMask(unsigned int now, unsigned int mask) { - if(isScheduleFixed(mask) || isScheduleOneShot(mask)) { + bool checkScheduleMask(unsigned int now, unsigned int msk) { + if(isScheduleFixed(msk) || isScheduleOneShot(msk)) { return true; } - if(isScheduleWeekly(mask)) { + if(isScheduleWeekly(msk)) { unsigned int nowMask = timeToWeekMask(now); - unsigned int scheduleMask = getScheduleWeekMask(mask); + unsigned int scheduleMask = getScheduleWeekMask(msk); if((nowMask & scheduleMask) == 0) { return false; @@ -202,9 +202,9 @@ class Schedule : public TimeService { } } - if(isScheduleMonthly(mask)) { + if(isScheduleMonthly(msk)) { unsigned int nowDay = timeToDay(now); - unsigned int scheduleDay = getScheduleDay(mask); + unsigned int scheduleDay = getScheduleDay(msk); if(nowDay != scheduleDay) { return false; @@ -213,11 +213,11 @@ class Schedule : public TimeService { } } - if(isScheduleYearly(mask)) { + if(isScheduleYearly(msk)) { unsigned int nowDay = timeToDay(now); - unsigned int scheduleDay = getScheduleDay(mask); + unsigned int scheduleDay = getScheduleDay(msk); unsigned int nowMonth = timeToMonth(now); - unsigned int scheduleMonth = getScheduleMonth(mask); + unsigned int scheduleMonth = getScheduleMonth(msk); if((nowDay != scheduleDay) || (nowMonth != scheduleMonth)) { return false; @@ -229,26 +229,26 @@ class Schedule : public TimeService { return false; } - unsigned int getScheduleDelta(unsigned int mask) { - if(isScheduleOneShot(mask)) { + unsigned int getScheduleDelta(unsigned int msk) { + if(isScheduleOneShot(msk)) { return 0xFFFFFFFF; } - if(isScheduleFixed(mask)) { - if(isScheduleInSeconds(mask)) { - return getScheduleRawMask(mask); + if(isScheduleFixed(msk)) { + if(isScheduleInSeconds(msk)) { + return getScheduleRawMask(msk); } - if(isScheduleInMinutes(mask)) { - return 60 * getScheduleRawMask(mask); + if(isScheduleInMinutes(msk)) { + return 60 * getScheduleRawMask(msk); } - if(isScheduleInHours(mask)) { - return 60 * 60 * getScheduleRawMask(mask); + if(isScheduleInHours(msk)) { + return 60 * 60 * getScheduleRawMask(msk); } } - if(isScheduleWeekly(mask) || isScheduleMonthly(mask) || isScheduleYearly(mask)) { + if(isScheduleWeekly(msk) || isScheduleMonthly(msk) || isScheduleYearly(msk)) { return 60 * 60 * 24; } @@ -259,10 +259,10 @@ class Schedule : public TimeService { class CloudSchedule : public Property { private: Schedule _value, - _cloud_value; + _cloud_value; public: CloudSchedule() : _value(0, 0, 0, 0), _cloud_value(0, 0, 0, 0) {} - CloudSchedule(unsigned int start, unsigned int end, unsigned int duration, unsigned int mask) : _value(start, end, duration, mask), _cloud_value(start, end, duration, mask) {} + CloudSchedule(unsigned int frm, unsigned int to, unsigned int len, unsigned int msk) : _value(frm, to, len, msk), _cloud_value(frm, to, len, msk) {} virtual bool isDifferentFromCloud() { @@ -270,10 +270,10 @@ class CloudSchedule : public Property { } CloudSchedule& operator=(Schedule aSchedule) { - _value.start = aSchedule.start; - _value.end = aSchedule.end; - _value.duration = aSchedule.duration; - _value.mask = aSchedule.mask; + _value.frm = aSchedule.frm; + _value.to = aSchedule.to; + _value.len = aSchedule.len; + _value.msk = aSchedule.msk; updateLocalTimestamp(); return *this; } @@ -297,17 +297,17 @@ class CloudSchedule : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - CHECK_CBOR(appendAttribute(_value.start)); - CHECK_CBOR(appendAttribute(_value.end)); - CHECK_CBOR(appendAttribute(_value.duration)); - CHECK_CBOR(appendAttribute(_value.mask)); + CHECK_CBOR(appendAttribute(_value.frm)); + CHECK_CBOR(appendAttribute(_value.to)); + CHECK_CBOR(appendAttribute(_value.len)); + CHECK_CBOR(appendAttribute(_value.msk)); return CborNoError; } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value.start); - setAttribute(_cloud_value.end); - setAttribute(_cloud_value.duration); - setAttribute(_cloud_value.mask); + setAttribute(_cloud_value.frm); + setAttribute(_cloud_value.to); + setAttribute(_cloud_value.len); + setAttribute(_cloud_value.msk); } }; From 089a633ce4297729c7e08e246f5aef3929f33506 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 3 Nov 2021 16:59:13 +0100 Subject: [PATCH 210/780] CloudSchedule refactor --- src/property/types/CloudSchedule.h | 188 ++++++++++++++++------------- 1 file changed, 104 insertions(+), 84 deletions(-) diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index fc018b15f..2f1effef0 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -24,9 +24,46 @@ #include #include "../Property.h" +#include "../../AIoTC_Const.h" #include "utility/time/TimeService.h" #include +/****************************************************************************** + * DEFINE + ******************************************************************************/ +#define SCHEDULE_UNIT_MASK 0xC0000000 +#define SCHEDULE_UNIT_SHIFT 30 + +#define SCHEDULE_TYPE_MASK 0x3C000000 +#define SCHEDULE_TYPE_SHIFT 26 + +#define SCHEDULE_MONTH_MASK 0x0000FF00 +#define SCHEDULE_MONTH_SHIFT 8 + +#define SCHEDULE_REP_MASK 0x03FFFFFF +#define SCHEDULE_WEEK_MASK 0x000000FF +#define SCHEDULE_DAY_MASK 0x000000FF + +#define SCHEDULE_ONE_SHOT 0xFFFFFFFF + +/****************************************************************************** + ENUM + ******************************************************************************/ +enum class ScheduleUnit : int { + Seconds = 0, + Minutes = 1, + Hours = 2, + Days = 3 +}; + +enum class ScheduleType : int { + OneShot = 0, + FixedDelta = 1, + Weekly = 2, + Monthly = 3, + Yearly = 4 +}; + /****************************************************************************** CLASS DECLARATION ******************************************************************************/ @@ -69,116 +106,107 @@ class Schedule : public TimeService { return !(operator==(aSchedule)); } private: + ScheduleUnit getScheduleUnit(unsigned int msk) { + return static_cast((msk & SCHEDULE_UNIT_MASK) >> SCHEDULE_UNIT_SHIFT); + } + + ScheduleType getScheduleType(unsigned int msk) { + return static_cast((msk & SCHEDULE_TYPE_MASK) >> SCHEDULE_TYPE_SHIFT); + } + + unsigned int getScheduleRepetition(unsigned int msk) { + return (msk & SCHEDULE_REP_MASK); + } + + unsigned int getScheduleWeekMask(unsigned int msk) { + return (msk & SCHEDULE_WEEK_MASK); + } + + unsigned int getScheduleDay(unsigned int msk) { + return (msk & SCHEDULE_DAY_MASK); + } + + unsigned int getScheduleMonth(unsigned int msk) { + return ((msk & SCHEDULE_MONTH_MASK) >> SCHEDULE_MONTH_SHIFT); + } + bool isScheduleOneShot(unsigned int msk) { - if((msk & 0x3C000000) == 0x00000000) { - return true; - } else { - return false; - } + return (getScheduleType(msk) == ScheduleType::OneShot) ? true : false ; } bool isScheduleFixed(unsigned int msk) { - if((msk & 0x3C000000) == 0x04000000) { - return true; - } else { - return false; - } + return (getScheduleType(msk) == ScheduleType::FixedDelta) ? true : false ; } bool isScheduleWeekly(unsigned int msk) { - if((msk & 0x3C000000) == 0x08000000) { - return true; - } else { - return false; - } + return (getScheduleType(msk) == ScheduleType::Weekly) ? true : false ; } bool isScheduleMonthly(unsigned int msk) { - if((msk & 0x3C000000) == 0x0C000000) { - return true; - } else { - return false; - } + return (getScheduleType(msk) == ScheduleType::Monthly) ? true : false ; } bool isScheduleYearly(unsigned int msk) { - if((msk & 0x3C000000) == 0x10000000) { - return true; - } else { - return false; - } + return (getScheduleType(msk) == ScheduleType::Yearly) ? true : false ; } bool isScheduleInSeconds(unsigned int msk) { - if((msk & 0xC0000000) == 0x00000000) { - return true; + if(isScheduleFixed(msk)) { + return (getScheduleUnit(msk) == ScheduleUnit::Seconds) ? true : false ; } else { return false; } } bool isScheduleInMinutes(unsigned int msk) { - if((msk & 0xC0000000) == 0x40000000) { - return true; + if(isScheduleFixed(msk)) { + return (getScheduleUnit(msk) == ScheduleUnit::Minutes) ? true : false ; } else { return false; } } bool isScheduleInHours(unsigned int msk) { - if((msk & 0xC0000000) == 0x80000000) { - return true; + if(isScheduleFixed(msk)) { + return (getScheduleUnit(msk) == ScheduleUnit::Hours) ? true : false ; } else { return false; } } bool isScheduleInDays(unsigned int msk) { - if((msk & 0xC0000000) == 0xC0000000) { - return true; + if(isScheduleFixed(msk)) { + return (getScheduleUnit(msk) == ScheduleUnit::Days) ? true : false ; } else { return false; } } - unsigned int timeToWeekMask(time_t rawtime) { + unsigned int getCurrentDayMask(time_t time) { struct tm * ptm; - ptm = gmtime ( &rawtime ); + ptm = gmtime (&time); return 1 << ptm->tm_wday; } - unsigned int timeToDay(time_t rawtime) { + unsigned int getCurrentDay(time_t time) { struct tm * ptm; - ptm = gmtime ( &rawtime ); + ptm = gmtime (&time); return ptm->tm_mday; } - unsigned int timeToMonth(time_t rawtime) { + unsigned int getCurrentMonth(time_t time) { struct tm * ptm; - ptm = gmtime ( &rawtime ); + ptm = gmtime (&time); return ptm->tm_mon; } - unsigned int getScheduleRawMask(unsigned int msk) { - return msk & 0x03FFFFFF; - } - - unsigned int getScheduleWeekMask(unsigned int msk) { - return msk & 0x000000FF; - } - - unsigned int getScheduleDay(unsigned int msk) { - return msk & 0x000000FF; - } - - unsigned int getScheduleMonth(unsigned int msk) { - return (msk & 0x0000FF00) >> 8; - } - bool checkSchedulePeriod(unsigned int now, unsigned int frm, unsigned int to) { + /* Check if current time is inside the schedule period. If 'to' is equal to + * 0 the schedule has no end. + */ if(now >= frm && (now < to || to == 0)) { return true; } else { @@ -189,39 +217,33 @@ class Schedule : public TimeService { bool checkScheduleMask(unsigned int now, unsigned int msk) { if(isScheduleFixed(msk) || isScheduleOneShot(msk)) { return true; - } + } if(isScheduleWeekly(msk)) { - unsigned int nowMask = timeToWeekMask(now); + unsigned int currentDayMask = getCurrentDayMask(now); unsigned int scheduleMask = getScheduleWeekMask(msk); - if((nowMask & scheduleMask) == 0) { - return false; - } else { + if((currentDayMask & scheduleMask) != 0) { return true; } } if(isScheduleMonthly(msk)) { - unsigned int nowDay = timeToDay(now); + unsigned int currentDay = getCurrentDay(now); unsigned int scheduleDay = getScheduleDay(msk); - if(nowDay != scheduleDay) { - return false; - } else { + if(currentDay == scheduleDay) { return true; } } if(isScheduleYearly(msk)) { - unsigned int nowDay = timeToDay(now); + unsigned int currentDay = getCurrentDay(now); unsigned int scheduleDay = getScheduleDay(msk); - unsigned int nowMonth = timeToMonth(now); + unsigned int currentMonth = getCurrentMonth(now); unsigned int scheduleMonth = getScheduleMonth(msk); - if((nowDay != scheduleDay) || (nowMonth != scheduleMonth)) { - return false; - } else { + if((currentDay == scheduleDay) && (currentMonth == scheduleMonth)) { return true; } } @@ -230,29 +252,27 @@ class Schedule : public TimeService { } unsigned int getScheduleDelta(unsigned int msk) { - if(isScheduleOneShot(msk)) { - return 0xFFFFFFFF; + if(isScheduleInSeconds(msk)) { + return SECONDS * getScheduleRepetition(msk); } - - if(isScheduleFixed(msk)) { - if(isScheduleInSeconds(msk)) { - return getScheduleRawMask(msk); - } - if(isScheduleInMinutes(msk)) { - return 60 * getScheduleRawMask(msk); - } + if(isScheduleInMinutes(msk)) { + return MINUTES * getScheduleRepetition(msk); + } - if(isScheduleInHours(msk)) { - return 60 * 60 * getScheduleRawMask(msk); - } + if(isScheduleInHours(msk)) { + return HOURS * getScheduleRepetition(msk); + } + + if(isScheduleInDays(msk)) { + return DAYS * getScheduleRepetition(msk); } if(isScheduleWeekly(msk) || isScheduleMonthly(msk) || isScheduleYearly(msk)) { - return 60 * 60 * 24; + return DAYS; } - return 0; + return SCHEDULE_ONE_SHOT; } }; From 5af2f89e98109f89f8ce237be87dcc822beeeea7 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 4 Nov 2021 15:29:00 +0100 Subject: [PATCH 211/780] Add encode and decode test --- extras/test/src/test_decode.cpp | 26 ++++++++++++++++++++++++++ extras/test/src/test_encode.cpp | 18 ++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/extras/test/src/test_decode.cpp b/extras/test/src/test_decode.cpp index d67afd440..fab8c18d4 100644 --- a/extras/test/src/test_decode.cpp +++ b/extras/test/src/test_decode.cpp @@ -400,6 +400,32 @@ SCENARIO("Arduino Cloud Properties are decoded", "[ArduinoCloudThing::decode]") /************************************************************************************/ + WHEN("A Schedule property is changed via CBOR message") + { + PropertyContainer property_container; + + CloudSchedule schedule_test = CloudSchedule(0, 0, 0, 0); + addPropertyToContainer(property_container, schedule_test, "test", Permission::ReadWrite); + + /* [{0: "test:frm", 2: 1633305600}, {0: "test:to", 2: 1633651200}, {0: "test:len", 2: 600}, {0: "test:msk", 2: 1140850708}] + = 84 A2 00 68 74 65 73 74 3A 66 72 6D 02 1A 61 5A 44 00 A2 00 67 74 65 73 74 3A 74 6F 02 1A 61 5F 8A 00 A2 00 68 74 65 73 74 3A 6C 65 6E 02 19 02 58 A2 00 68 74 65 73 74 3A 6D 73 6B 02 1A 44 00 00 14 + */ + uint8_t const payload[] = {0x84, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x66, 0x72, 0x6D, 0x02, 0x1A, 0x61, 0x5A, 0x44, 0x00, 0xA2, 0x00, 0x67, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x74, 0x6F, 0x02, 0x1A, 0x61, 0x5F, 0x8A, 0x00, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x6C, 0x65, 0x6E, 0x02, 0x19, 0x02, 0x58, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x6D, 0x73, 0x6B, 0x02, 0x1A, 0x44, 0x00, 0x00, 0x14}; + CBORDecoder::decode(property_container, payload, sizeof(payload) / sizeof(uint8_t)); + + Schedule schedule_compare = Schedule(1633305600, 1633651200, 600, 1140850708); + Schedule value_schedule_test = schedule_test.getValue(); + + bool verify = (value_schedule_test == schedule_compare); + REQUIRE(verify); + REQUIRE(value_schedule_test.frm == schedule_compare.frm); + REQUIRE(value_schedule_test.to == schedule_compare.to); + REQUIRE(value_schedule_test.len == schedule_compare.len); + REQUIRE(value_schedule_test.msk == schedule_compare.msk); + } + + /************************************************************************************/ + WHEN("Multiple properties is changed via CBOR message") { WHEN("Multiple properties of different type are changed via CBOR message") diff --git a/extras/test/src/test_encode.cpp b/extras/test/src/test_encode.cpp index 8a4904fc6..f0667166b 100644 --- a/extras/test/src/test_encode.cpp +++ b/extras/test/src/test_encode.cpp @@ -322,6 +322,24 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode-1]" /************************************************************************************/ + WHEN("A 'Schedule' property is added") + { + PropertyContainer property_container; + cbor::encode(property_container); + + CloudSchedule schedule_test = CloudSchedule(1633305600, 1633651200, 600, 1140850708); + addPropertyToContainer(property_container, schedule_test, "test", Permission::ReadWrite); + + /* [{0: "test:frm", 2: 1633305600}, {0: "test:to", 2: 1633651200}, {0: "test:len", 2: 600}, {0: "test:msk", 2: 1140850708}] + = 9F A2 00 68 74 65 73 74 3A 66 72 6D 02 1A 61 5A 44 00 A2 00 67 74 65 73 74 3A 74 6F 02 1A 61 5F 8A 00 A2 00 68 74 65 73 74 3A 6C 65 6E 02 19 02 58 A2 00 68 74 65 73 74 3A 6D 73 6B 02 1A 44 00 00 14 FF + */ + std::vector const expected = {0x9F, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x66, 0x72, 0x6D, 0x02, 0x1A, 0x61, 0x5A, 0x44, 0x00, 0xA2, 0x00, 0x67, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x74, 0x6F, 0x02, 0x1A, 0x61, 0x5F, 0x8A, 0x00, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x6C, 0x65, 0x6E, 0x02, 0x19, 0x02, 0x58, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x6D, 0x73, 0x6B, 0x02, 0x1A, 0x44, 0x00, 0x00, 0x14, 0xFF }; + std::vector const actual = cbor::encode(property_container); + REQUIRE(actual == expected); + } + + /************************************************************************************/ + WHEN("Multiple properties are added") { PropertyContainer property_container; From e901a85bf50c8e63049353294fca5b4902809731 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 9 Nov 2021 11:08:12 +0100 Subject: [PATCH 212/780] Add example sketch for CloudSchedule property --- .../ArduinoIoTCloud-Schedule.ino | 54 +++++++++++++++++++ .../arduino_secrets.h | 34 ++++++++++++ .../thingProperties.h | 35 ++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino create mode 100644 examples/ArduinoIoTCloud-Schedule/arduino_secrets.h create mode 100644 examples/ArduinoIoTCloud-Schedule/thingProperties.h diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino new file mode 100644 index 000000000..eccd4c1f1 --- /dev/null +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -0,0 +1,54 @@ +/* + This sketch demonstrates how to use cloud schedule data type. + + This sketch is compatible with: + - MKR 1000 + - MKR WIFI 1010 + - MKR GSM 1400 + - MKR NB 1500 + - MKR WAN 1300/1310 + - Nano 33 IoT + - ESP 8266 +*/ + +#include "arduino_secrets.h" +#include "thingProperties.h" + +#if defined(ESP32) +static int const LED_BUILTIN = 2; +#endif + +void setup() { + /* Initialize serial and wait up to 5 seconds for port to open */ + Serial.begin(9600); + for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime > 5000); ) { } + + /* Configure LED pin as an output */ + pinMode(LED_BUILTIN, OUTPUT); + + /* This function takes care of connecting your sketch variables to the ArduinoIoTCloud object */ + initProperties(); + + /* Initialize Arduino IoT Cloud library */ + ArduinoCloud.begin(ArduinoIoTPreferredConnection); + + setDebugMessageLevel(DBG_INFO); + ArduinoCloud.printDebugInfo(); + + /* Configure a schedule for LED. This should be done with Arduino create Scheduler widget */ + unsigned int startingFrom = 1635786000; /* From 01/11/2021 17:00 */ + unsigned int untilTo = startingFrom + ( DAYS * 28 ); /* To 29/11/2021 17:00 */ + unsigned int executionPeriod = MINUTES * 6; /* For 6 minutes */ + unsigned int scheduleConfiguration = 134217770; /* On monday wednesday and friday */ + + led = Schedule(startingFrom, untilTo, executionPeriod, scheduleConfiguration); +} + +void loop() { + ArduinoCloud.update(); + + /* Activate LED when schedule is active */ + digitalWrite(LED_BUILTIN, led.isActive()); + +} + diff --git a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h new file mode 100644 index 000000000..fc0b0661e --- /dev/null +++ b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h @@ -0,0 +1,34 @@ +#include + +/* MKR1000, MKR WiFi 1010 */ +#if defined(BOARD_HAS_WIFI) + #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" + #define SECRET_PASS "YOUR_WIFI_PASSWORD" +#endif + +/* ESP8266 */ +#if defined(BOARD_ESP8266) + #define SECRET_DEVICE_KEY "my-device-password" +#endif + +/* MKR GSM 1400 */ +#if defined(BOARD_HAS_GSM) + #define SECRET_PIN "" + #define SECRET_APN "" + #define SECRET_LOGIN "" + #define SECRET_PASS "" +#endif + +/* MKR WAN 1300/1310 */ +#if defined(BOARD_HAS_LORA) + #define SECRET_APP_EUI "" + #define SECRET_APP_KEY "" +#endif + +/* MKR NB 1500 */ +#if defined(BOARD_HAS_NB) + #define SECRET_PIN "" + #define SECRET_APN "" + #define SECRET_LOGIN "" + #define SECRET_PASS "" +#endif diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h new file mode 100644 index 000000000..fd63b76a1 --- /dev/null +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -0,0 +1,35 @@ +#include +#include + +#define THING_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + +void onSwitchButtonChange(); + +bool switchButton; +CloudSchedule led; + +void initProperties() { +#if defined(BOARD_ESP8266) + ArduinoCloud.setBoardId(BOARD_ID); + ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); +#endif + ArduinoCloud.setThingId(THING_ID); +#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) + ArduinoCloud.addProperty(switchButton, WRITE, ON_CHANGE); + ArduinoCloud.addProperty(led, READWRITE, ON_CHANGE); +#elif defined(BOARD_HAS_LORA) + ArduinoCloud.addProperty(switchButton, 1, WRITE, ON_CHANGE; + ArduinoCloud.addProperty(led, 2, READWRITE, ON_CHANGE); +#endif +} + +#if defined(BOARD_HAS_WIFI) + WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_PASS); +#elif defined(BOARD_HAS_GSM) + GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_LORA) + LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); +#elif defined(BOARD_HAS_NB) + NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#endif From e2b952621a50f7437081a67e70624b76c209b8a7 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 2 Nov 2021 10:09:46 +0100 Subject: [PATCH 213/780] Add properties and logic to handle timezone and dst changes --- src/ArduinoIoTCloud.h | 6 +++++- src/ArduinoIoTCloudTCP.cpp | 16 +++++++++++++++- src/property/types/CloudSchedule.h | 2 +- src/utility/time/TimeService.cpp | 12 ++++++++++++ src/utility/time/TimeService.h | 8 ++++++++ 5 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 7c1f9679c..9aad29ea8 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -97,7 +97,9 @@ class ArduinoIoTCloudClass inline ConnectionHandler * getConnection() { return _connection; } - inline unsigned long getInternalTime() { return _time_service.getTime(); } + inline unsigned long getInternalTime() { return _time_service.getTime(); } + inline unsigned long getLocalTime() { return _time_service.getLocalTime(); } + inline void updateInternalTimezoneInfo() { _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); } void addCallback(ArduinoIoTCloudEvent const event, OnCloudEventCallback callback); @@ -146,6 +148,8 @@ class ArduinoIoTCloudClass ConnectionHandler * _connection = nullptr; PropertyContainer _property_container; TimeService _time_service; + int _tz_offset = 0; + unsigned int _tz_dst_until = 0; void execCloudEventCallback(ArduinoIoTCloudEvent const event); diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 4d4f86b9d..11245ea85 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -64,6 +64,11 @@ extern "C" unsigned long getTime() return ArduinoCloud.getInternalTime(); } +extern "C" void updateTimezoneInfo() +{ + ArduinoCloud.updateInternalTimezoneInfo(); +} + /****************************************************************************** CTOR/DTOR ******************************************************************************/ @@ -243,6 +248,9 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, addPropertyReal(_ota_req, "OTA_REQ", Permission::ReadWrite).onSync(CLOUD_WINS); #endif /* OTA_ENABLED */ + 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; @@ -527,7 +535,12 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() */ sendPropertiesToCloud(); - return State::Connected; + unsigned long const internal_posix_time = _time_service.getTime(); + if(internal_posix_time < _tz_dst_until) { + return State::Connected; + } else { + return State::RequestLastValues; + } } } @@ -555,6 +568,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); CBORDecoder::decode(_property_container, (uint8_t*)bytes, length, true); sendPropertiesToCloud(); + _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); _last_sync_request_cnt = 0; _last_sync_request_tick = 0; diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index 2f1effef0..b7b696214 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -74,7 +74,7 @@ class Schedule : public TimeService { bool isActive() { - unsigned int now = getTime(); + unsigned int now = getLocalTime(); if(checkSchedulePeriod(now, frm, to)) { /* We are in the schedule range */ diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index dcd15f83b..6b80c2b51 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -91,6 +91,18 @@ unsigned long TimeService::getTime() #endif } +void TimeService::setTimeZoneData(long offset, unsigned long dst_until) +{ + _timezone_offset = offset; + _timezone_dst_until = dst_until; +} + +unsigned long TimeService::getLocalTime() +{ + unsigned long utc = getTime(); + return utc + _timezone_offset; +} + /************************************************************************************** * PRIVATE MEMBER FUNCTIONS **************************************************************************************/ diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index ae8c12f35..73335f0b7 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -24,6 +24,7 @@ #include + #ifdef ARDUINO_ARCH_SAMD #include #endif @@ -46,6 +47,8 @@ class TimeService void begin (ConnectionHandler * con_hdl); unsigned long getTime(); + unsigned long getLocalTime(); + void setTimeZoneData(long offset, unsigned long valid_until); private: @@ -55,8 +58,13 @@ class TimeService #endif unsigned long getRemoteTime(); + static bool isTimeValid(unsigned long const time); +private: + long _timezone_offset; + unsigned long _timezone_dst_until; + }; #endif /* ARDUINO_IOT_CLOUD_TIME_SERVICE_H_ */ From a52d001a8bd1f01c752168807a2700b6f74eab40 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 17 Nov 2021 11:46:43 +0100 Subject: [PATCH 214/780] Add TimeService::getLocalTime() fake to unit tests --- extras/test/CMakeLists.txt | 1 + extras/test/src/util/PropertyTestUtil.cpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index a2b9c749e..b707b5254 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -12,6 +12,7 @@ include_directories(include) include_directories(../../src) include_directories(../../src/cbor) include_directories(../../src/property) +include_directories(../../src/utility/time) include_directories(external/catch/v2.12.1/include) include_directories(external/fakeit/v2.0.5/include) diff --git a/extras/test/src/util/PropertyTestUtil.cpp b/extras/test/src/util/PropertyTestUtil.cpp index 35717a385..0048dd38d 100644 --- a/extras/test/src/util/PropertyTestUtil.cpp +++ b/extras/test/src/util/PropertyTestUtil.cpp @@ -7,6 +7,8 @@ **************************************************************************************/ #include +#include +#include /************************************************************************************** FUNCTION DEFINITION @@ -16,3 +18,8 @@ unsigned long getTime() { return 0; } + +unsigned long TimeService::getLocalTime() +{ + return getTime(); +} From 74cf0b2d080c392a68880824fe5dfbbb1444fb6b Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 12 Nov 2021 10:02:11 +0100 Subject: [PATCH 215/780] Add DEBUG_DEBUG print to keep track of offset and dst_until changes --- src/utility/time/TimeService.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 6b80c2b51..07e0f7a69 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -93,7 +93,12 @@ unsigned long TimeService::getTime() void TimeService::setTimeZoneData(long offset, unsigned long dst_until) { + if(_timezone_offset != offset) + DEBUG_DEBUG("ArduinoIoTCloudTCP::%s tz_offset: [%d]", __FUNCTION__, offset); _timezone_offset = offset; + + if(_timezone_dst_until != dst_until) + DEBUG_DEBUG("ArduinoIoTCloudTCP::%s tz_dst_unitl: [%ul]", __FUNCTION__, dst_until); _timezone_dst_until = dst_until; } From 394da9a0dc5b6a73aa57f6e0a744e58d598786a2 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Nov 2021 13:59:26 +0100 Subject: [PATCH 216/780] Add functions to ease Schedule configuration --- src/property/types/CloudSchedule.h | 87 ++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index b7b696214..2b7058c66 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -64,6 +64,44 @@ enum class ScheduleType : int { Yearly = 4 }; +enum class ScheduleMonth : int { + Jan = 0, + Feb = 1, + Mar = 2, + Apr = 3, + May = 4, + Jun = 5, + Jul = 6, + Aug = 7, + Sep = 8, + Oct = 9, + Nov = 10, + Dec = 11 +}; + +enum class ScheduleWeekDay : int { + Sun = 0, + Mon = 1, + Tue = 2, + Wed = 3, + Thu = 4, + Fri = 5, + Sat = 6 +}; + +enum class ScheduleState : int { + Inactive = 0, + Active = 1 +}; + +/****************************************************************************** + * TYPEDEF + ******************************************************************************/ +typedef struct ScheduleWeeklyMask { + ScheduleState& operator[](ScheduleWeekDay i) { return day[static_cast(i)];} + ScheduleState day[7]; +}ScheduleWeeklyMask; + /****************************************************************************** CLASS DECLARATION ******************************************************************************/ @@ -90,6 +128,55 @@ class Schedule : public TimeService { return false; } + static unsigned int createOneShotScheduleConfiguration() { + return 0; + } + + static unsigned int createFixedDeltaScheduleConfiguration(ScheduleUnit unit, unsigned int delta) { + unsigned int temp_unit = static_cast(unit); + unsigned int temp_type = static_cast(ScheduleType::FixedDelta); + unsigned int temp_delta = delta; + + if (temp_delta > SCHEDULE_REP_MASK) { + temp_delta = SCHEDULE_REP_MASK; + } + return (temp_unit << SCHEDULE_UNIT_SHIFT) | (temp_type << SCHEDULE_TYPE_SHIFT) | temp_delta; + } + + static unsigned int createWeeklyScheduleConfiguration(ScheduleWeeklyMask weekMask) { + unsigned int temp_week = 0; + unsigned int temp_type = static_cast(ScheduleType::Weekly); + + for(int i = 0; i<7; i++) { + if(weekMask[static_cast(i)] == ScheduleState::Active) { + temp_week |= 1 << i; + } + } + return (temp_type << SCHEDULE_TYPE_SHIFT) | temp_week; + } + + static unsigned int createMonthlyScheduleConfiguration(int dayOfTheMonth) { + int temp_day = dayOfTheMonth; + unsigned int temp_type = static_cast(ScheduleType::Monthly); + + if(temp_day < 1) { + temp_day = 1; + } + + if(temp_day > 31) { + temp_day = 31; + } + return (temp_type << SCHEDULE_TYPE_SHIFT) | temp_day; + } + + static unsigned int createYearlyScheduleConfiguration(ScheduleMonth month, int dayOfTheMonth) { + int temp_day = createMonthlyScheduleConfiguration(dayOfTheMonth); + int temp_month = static_cast(month); + unsigned int temp_type = static_cast(ScheduleType::Yearly); + + return (temp_type << SCHEDULE_TYPE_SHIFT) | (temp_month << SCHEDULE_MONTH_SHIFT)| temp_day; + } + Schedule& operator=(Schedule & aSchedule) { frm = aSchedule.frm; to = aSchedule.to; From c035af88cf08beb11a39dffbcdfbdde406775ba9 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Nov 2021 13:38:18 +0100 Subject: [PATCH 217/780] Add getTimeFromString() function to convert an input string into a Schedule timestamp --- src/utility/time/TimeService.cpp | 60 ++++++++++++++++++++++++++++++++ src/utility/time/TimeService.h | 5 ++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 07e0f7a69..e84efbb6a 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -108,6 +108,66 @@ unsigned long TimeService::getLocalTime() return utc + _timezone_offset; } +unsigned long TimeService::getTimeFromString(const String& input) +{ + struct tm t = + { + 0 /* tm_sec */, + 0 /* tm_min */, + 0 /* tm_hour */, + 0 /* tm_mday */, + 0 /* tm_mon */, + 0 /* tm_year */, + 0 /* tm_wday */, + 0 /* tm_yday */, + 0 /* tm_isdst */ + }; + + char s_month[16]; + int month, day, year, hour, min, sec; + static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + static const int expected_length = 20; + static const int expected_parameters = 6; + + if(input == nullptr || input.length() != expected_length) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s invalid input length", __FUNCTION__); + return 0; + } + + int scanned_parameters = sscanf(input.c_str(), "%d %s %d %d:%d:%d", &year, s_month, &day, &hour, &min, &sec); + + if(scanned_parameters != expected_parameters) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s invalid input parameters number", __FUNCTION__); + return 0; + } + + char * s_month_position = strstr(month_names, s_month); + + if(s_month_position == nullptr || strlen(s_month) != 3) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s invalid month name, use %s", __FUNCTION__, month_names); + return 0; + } + + month = (s_month_position - month_names) / 3; + + if(month < 0 || month > 11 || day < 1 || day > 31 || year < 1900 || hour < 0 || + hour > 24 || min < 0 || min > 60 || sec < 0 || sec > 60) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s invalid date values", __FUNCTION__); + return 0; + } + + t.tm_mon = month; + t.tm_mday = day; + t.tm_year = year - 1900; + t.tm_hour = hour; + t.tm_min = min; + t.tm_sec = sec; + t.tm_isdst = -1; + + return mktime(&t); +} /************************************************************************************** * PRIVATE MEMBER FUNCTIONS **************************************************************************************/ diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 73335f0b7..3582dd608 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -24,7 +24,6 @@ #include - #ifdef ARDUINO_ARCH_SAMD #include #endif @@ -49,6 +48,10 @@ class TimeService unsigned long getTime(); unsigned long getLocalTime(); void setTimeZoneData(long offset, unsigned long valid_until); + /* Helper function to convert an input String into a UNIX timestamp. + * The input String format must be as follow "2021 Nov 01 17:00:00" + */ + static unsigned long getTimeFromString(const String& input); private: From d4cfdd6bdc4619e457a5d13cfdfa3de6eca946d3 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Nov 2021 13:39:01 +0100 Subject: [PATCH 218/780] Update example adding all schedules types and using schedule configuration functions --- .../ArduinoIoTCloud-Schedule.ino | 197 +++++++++++++++++- .../thingProperties.h | 17 +- 2 files changed, 200 insertions(+), 14 deletions(-) diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index eccd4c1f1..71be7f0bf 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -1,7 +1,7 @@ /* - This sketch demonstrates how to use cloud schedule data type. + This sketch demonstrates how to use the cloud schedule variable type. - This sketch is compatible with: + This sketch is compatible with the following boards: - MKR 1000 - MKR WIFI 1010 - MKR GSM 1400 @@ -19,7 +19,7 @@ static int const LED_BUILTIN = 2; #endif void setup() { - /* Initialize serial and wait up to 5 seconds for port to open */ + /* Initialize the serial port and wait up to 5 seconds for a connection */ Serial.begin(9600); for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime > 5000); ) { } @@ -35,20 +35,195 @@ void setup() { setDebugMessageLevel(DBG_INFO); ArduinoCloud.printDebugInfo(); - /* Configure a schedule for LED. This should be done with Arduino create Scheduler widget */ - unsigned int startingFrom = 1635786000; /* From 01/11/2021 17:00 */ - unsigned int untilTo = startingFrom + ( DAYS * 28 ); /* To 29/11/2021 17:00 */ - unsigned int executionPeriod = MINUTES * 6; /* For 6 minutes */ - unsigned int scheduleConfiguration = 134217770; /* On monday wednesday and friday */ + /* Setup one shot schedule example */ + setupOneShotSchedule(); - led = Schedule(startingFrom, untilTo, executionPeriod, scheduleConfiguration); + /* Setup per minute schedule example */ + setupMinuteSchedule(); + + /* Setup hourly schedule example */ + setupHourlySchedule(); + + /* Setup daily schedule example */ + setupDailySchedule(); + + /* Setup weekly schedule example */ + setupWeeklySchedule(); + + /* Setup monthly schedule example */ + setupMonthlySchedule(); + + /* Setup yearly schedule example */ + setupYearlySchedule(); +} + + /* Setup a schedule with an active period of 5 minutes that doesn't repeat + * Starting from 2021 11 01 17:00:00 + * Until 2021 11 02 17:00:00 + */ +void setupOneShotSchedule() { + + unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 01 17:00:00"); + unsigned int until = startingFrom + ( DAYS * 1 ); + unsigned int activePeriod = MINUTES * 5; + + /* Warning: there is no cross check between until and activePeriod */ + unsigned int scheduleConfiguration = Schedule::createOneShotScheduleConfiguration(); + + oneShot = Schedule(startingFrom, until, activePeriod, scheduleConfiguration); +} + + /* Setup a schedule with an active period of 15 seconds that repeats each minute + * Starting from 2021 11 01 17:00:00 + * Until 2021 11 02 17:00:00 + */ +void setupMinuteSchedule() { + + unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 01 17:00:00"); + unsigned int until = startingFrom + ( DAYS * 1 ); + unsigned int activePeriod = SECONDS * 15; + unsigned int repetitionPeriod = 1; + + /* Warning: there is no cross check between repetitionPeriod and activePeriod */ + unsigned int scheduleConfiguration = Schedule::createFixedDeltaScheduleConfiguration(ScheduleUnit::Minutes, repetitionPeriod); + + minute = Schedule(startingFrom, until, activePeriod, scheduleConfiguration); +} + +/* Setup a schedule with an active period of 20 minutes that repeats each hour + * Starting from 2021 11 01 17:00:00 + * Until 2021 11 15 13:00:00 + */ +void setupHourlySchedule() { + + unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 01 17:00:00"); + unsigned int until = Schedule::getTimeFromString("2021 Nov 15 13:00:00"); + unsigned int activePeriod = MINUTES * 20; + unsigned int repetitionPeriod = 1; + + /* Warning: there is no cross check between repetitionPeriod and activePeriod */ + unsigned int scheduleConfiguration = Schedule::createFixedDeltaScheduleConfiguration(ScheduleUnit::Hours, repetitionPeriod); + + hourly = Schedule(startingFrom, until, activePeriod, scheduleConfiguration); +} + +/* Setup a schedule with an active period of 2 hours that repeats each day + * Starting from 2021 11 01 17:00:00 + * Until 2021 11 15 13:00:00 + */ +void setupDailySchedule() { + + unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 01 17:00:00"); + unsigned int until = Schedule::getTimeFromString("2021 Nov 15 13:00:00"); + unsigned int activePeriod = HOURS * 2; + unsigned int repetitionPeriod = 1; + + /* Warning: there is no cross check between repetitionPeriod and activePeriod */ + unsigned int scheduleConfiguration = Schedule::createFixedDeltaScheduleConfiguration(ScheduleUnit::Days, repetitionPeriod); + + daily = Schedule(startingFrom, until, activePeriod, scheduleConfiguration); +} + +/* Setup a schedule with an active period of 3 minutes with a weekly configuration + * Starting from 2021 11 01 17:00:00 + * Until 2021 11 31 17:00:00 + * Weekly configuration + * Sunday -> Inactive + * Monday -> Active + * Tuesday -> Inactive + * Wednesday -> Active + * Thursday -> Inactive + * Friday -> Active + * Saturday -> Inactive + */ +void setupWeeklySchedule() { + unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 01 17:00:00"); + unsigned int until = startingFrom + ( DAYS * 30 ); + unsigned int executionPeriod = MINUTES * 3; + + ScheduleWeeklyMask WeeklyMask = { + ScheduleState::Inactive, /* Sunday */ + ScheduleState::Active, /* Monday */ + ScheduleState::Inactive, /* Tuesday */ + ScheduleState::Active, /* Wednesday */ + ScheduleState::Inactive, /* Thursday */ + ScheduleState::Active, /* Friday */ + ScheduleState::Inactive, /* Saturday */ + }; + + unsigned int scheduleConfiguration = Schedule::createWeeklyScheduleConfiguration(WeeklyMask); + + weekly = Schedule(startingFrom, until, executionPeriod, scheduleConfiguration); +} + +/* Setup a schedule with an active period of 1 day that repeats each third day of the month + * Starting from 2021 11 01 17:00:00 + * Until 2022 11 15 13:00:00 + */ +void setupMonthlySchedule() { + + unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 01 17:00:00"); + unsigned int until = Schedule::getTimeFromString("2021 Nov 15 13:00:00"); + unsigned int activePeriod = DAYS * 1; + unsigned int dayOfMonth = 3; + + unsigned int scheduleConfiguration = Schedule::createMonthlyScheduleConfiguration(dayOfMonth); + + monthly = Schedule(startingFrom, until, activePeriod, scheduleConfiguration); +} + + +/* Setup a schedule with an active period of 2 days that repeats each year on November 6th + * Starting from 2021 11 06 17:00:00 + * Until 2041 11 15 13:00:00 + */ +void setupYearlySchedule() { + + unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 06 17:00:00"); + unsigned int until = Schedule::getTimeFromString("2041 Nov 06 13:00:00"); + unsigned int activePeriod = DAYS * 2; + unsigned int dayOfMonth = 6; + + unsigned int scheduleConfiguration = Schedule::createYearlyScheduleConfiguration(ScheduleMonth::Nov, dayOfMonth); + + yearly = Schedule(startingFrom, until, activePeriod, scheduleConfiguration); } void loop() { ArduinoCloud.update(); - /* Activate LED when schedule is active */ - digitalWrite(LED_BUILTIN, led.isActive()); + /* Print a message when the oneShot schedule is active */ + if(oneShot.isActive()) { + Serial.println("One shot schedule is active"); + } + + /* Print a message when the per minute schedule is active */ + if(minute.isActive()) { + Serial.println("Per minute schedule is active"); + } + + /* Print a message when the hourly schedule is active */ + if(hourly.isActive()) { + Serial.println("Hourly schedule is active"); + } + + /* Print a message when the daily schedule is active */ + if(daily.isActive()) { + Serial.println("Daily schedule is active"); + } + /* Activate LED when the weekly schedule is active */ + digitalWrite(LED_BUILTIN, weekly.isActive()); + + /* Print a message when the monthly schedule is active */ + if(monthly.isActive()) { + Serial.println("Monthly schedule is active"); + } + + /* Print a message when the yearly schedule is active */ + if(yearly.isActive()) { + Serial.println("Yearly schedule is active"); + } + } diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index fd63b76a1..a426978ce 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -7,7 +7,13 @@ void onSwitchButtonChange(); bool switchButton; -CloudSchedule led; +CloudSchedule oneShot; +CloudSchedule minute; +CloudSchedule hourly; +CloudSchedule daily; +CloudSchedule weekly; +CloudSchedule monthly; +CloudSchedule yearly; void initProperties() { #if defined(BOARD_ESP8266) @@ -17,10 +23,15 @@ void initProperties() { ArduinoCloud.setThingId(THING_ID); #if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) ArduinoCloud.addProperty(switchButton, WRITE, ON_CHANGE); - ArduinoCloud.addProperty(led, READWRITE, ON_CHANGE); + ArduinoCloud.addProperty(oneShot, READWRITE, ON_CHANGE); + ArduinoCloud.addProperty(minute, READWRITE, ON_CHANGE); + ArduinoCloud.addProperty(hourly, READWRITE, ON_CHANGE); + ArduinoCloud.addProperty(daily, READWRITE, ON_CHANGE); + ArduinoCloud.addProperty(weekly, READWRITE, ON_CHANGE); + ArduinoCloud.addProperty(monthly, READWRITE, ON_CHANGE); + ArduinoCloud.addProperty(yearly, READWRITE, ON_CHANGE); #elif defined(BOARD_HAS_LORA) ArduinoCloud.addProperty(switchButton, 1, WRITE, ON_CHANGE; - ArduinoCloud.addProperty(led, 2, READWRITE, ON_CHANGE); #endif } From 14736a1c06d88338f1df8915745d57918c3d7cf1 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 25 Nov 2021 08:53:50 +0100 Subject: [PATCH 219/780] Make TimeService instance reusable --- .../ArduinoIoTCloud-Schedule.ino | 23 ++++++++++--------- extras/test/src/util/PropertyTestUtil.cpp | 5 ++++ src/ArduinoIoTCloud.h | 8 +++---- src/ArduinoIoTCloudLPWAN.cpp | 4 ++-- src/ArduinoIoTCloudTCP.cpp | 8 +++---- src/property/types/CloudSchedule.h | 6 +++-- src/utility/time/TimeService.cpp | 5 ++++ src/utility/time/TimeService.h | 2 ++ 8 files changed, 38 insertions(+), 23 deletions(-) diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index 71be7f0bf..a64b94f7a 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -63,7 +63,7 @@ void setup() { */ void setupOneShotSchedule() { - unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 01 17:00:00"); + unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); unsigned int until = startingFrom + ( DAYS * 1 ); unsigned int activePeriod = MINUTES * 5; @@ -79,7 +79,7 @@ void setupOneShotSchedule() { */ void setupMinuteSchedule() { - unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 01 17:00:00"); + unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); unsigned int until = startingFrom + ( DAYS * 1 ); unsigned int activePeriod = SECONDS * 15; unsigned int repetitionPeriod = 1; @@ -96,8 +96,8 @@ void setupMinuteSchedule() { */ void setupHourlySchedule() { - unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 01 17:00:00"); - unsigned int until = Schedule::getTimeFromString("2021 Nov 15 13:00:00"); + unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); + unsigned int until = TimeService::getTimeFromString("2021 Nov 15 13:00:00"); unsigned int activePeriod = MINUTES * 20; unsigned int repetitionPeriod = 1; @@ -113,8 +113,8 @@ void setupHourlySchedule() { */ void setupDailySchedule() { - unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 01 17:00:00"); - unsigned int until = Schedule::getTimeFromString("2021 Nov 15 13:00:00"); + unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); + unsigned int until = TimeService::getTimeFromString("2021 Nov 15 13:00:00"); unsigned int activePeriod = HOURS * 2; unsigned int repetitionPeriod = 1; @@ -137,7 +137,8 @@ void setupDailySchedule() { * Saturday -> Inactive */ void setupWeeklySchedule() { - unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 01 17:00:00"); + + unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); unsigned int until = startingFrom + ( DAYS * 30 ); unsigned int executionPeriod = MINUTES * 3; @@ -162,8 +163,8 @@ void setupWeeklySchedule() { */ void setupMonthlySchedule() { - unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 01 17:00:00"); - unsigned int until = Schedule::getTimeFromString("2021 Nov 15 13:00:00"); + unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); + unsigned int until = TimeService::getTimeFromString("2021 Nov 15 13:00:00"); unsigned int activePeriod = DAYS * 1; unsigned int dayOfMonth = 3; @@ -179,8 +180,8 @@ void setupMonthlySchedule() { */ void setupYearlySchedule() { - unsigned int startingFrom = Schedule::getTimeFromString("2021 Nov 06 17:00:00"); - unsigned int until = Schedule::getTimeFromString("2041 Nov 06 13:00:00"); + unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 06 17:00:00"); + unsigned int until = TimeService::getTimeFromString("2041 Nov 06 13:00:00"); unsigned int activePeriod = DAYS * 2; unsigned int dayOfMonth = 6; diff --git a/extras/test/src/util/PropertyTestUtil.cpp b/extras/test/src/util/PropertyTestUtil.cpp index 0048dd38d..ef6d85a99 100644 --- a/extras/test/src/util/PropertyTestUtil.cpp +++ b/extras/test/src/util/PropertyTestUtil.cpp @@ -23,3 +23,8 @@ unsigned long TimeService::getLocalTime() { return getTime(); } + +TimeService* ArduinoIoTCloudTimeService() { + static TimeService _timeService_instance; + return &_timeService_instance; +} diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 9aad29ea8..5041bc359 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -97,9 +97,9 @@ class ArduinoIoTCloudClass inline ConnectionHandler * getConnection() { return _connection; } - inline unsigned long getInternalTime() { return _time_service.getTime(); } - inline unsigned long getLocalTime() { return _time_service.getLocalTime(); } - inline void updateInternalTimezoneInfo() { _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); } + inline unsigned long getInternalTime() { return _time_service->getTime(); } + inline unsigned long getLocalTime() { return _time_service->getLocalTime(); } + inline void updateInternalTimezoneInfo() { _time_service->setTimeZoneData(_tz_offset, _tz_dst_until); } void addCallback(ArduinoIoTCloudEvent const event, OnCloudEventCallback callback); @@ -147,7 +147,7 @@ class ArduinoIoTCloudClass ConnectionHandler * _connection = nullptr; PropertyContainer _property_container; - TimeService _time_service; + TimeService * _time_service = ArduinoIoTCloudTimeService(); int _tz_offset = 0; unsigned int _tz_dst_until = 0; diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 29458f21a..17da1f651 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -68,7 +68,7 @@ int ArduinoIoTCloudLPWAN::begin(ConnectionHandler& connection, bool retry) { _connection = &connection; _retryEnable = retry; - _time_service.begin(nullptr); + _time_service->begin(nullptr); return 1; } @@ -105,7 +105,7 @@ ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_ConnectPhy() ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_SyncTime() { - unsigned long const internal_posix_time = _time_service.getTime(); + unsigned long const internal_posix_time = _time_service->getTime(); DEBUG_VERBOSE("ArduinoIoTCloudLPWAN::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); DEBUG_INFO("Connected to Arduino IoT Cloud"); return State::Connected; diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 11245ea85..c4e469e53 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -115,7 +115,7 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_ _connection = &connection; _brokerAddress = brokerAddress; _brokerPort = brokerPort; - _time_service.begin(&connection); + _time_service->begin(&connection); return begin(enable_watchdog, _brokerAddress, _brokerPort); } @@ -371,7 +371,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() { - unsigned long const internal_posix_time = _time_service.getTime(); + unsigned long const internal_posix_time = _time_service->getTime(); DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); return State::ConnectMqttBroker; } @@ -535,7 +535,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() */ sendPropertiesToCloud(); - unsigned long const internal_posix_time = _time_service.getTime(); + unsigned long const internal_posix_time = _time_service->getTime(); if(internal_posix_time < _tz_dst_until) { return State::Connected; } else { @@ -568,7 +568,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); CBORDecoder::decode(_property_container, (uint8_t*)bytes, length, true); sendPropertiesToCloud(); - _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); + _time_service->setTimeZoneData(_tz_offset, _tz_dst_until); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); _last_sync_request_cnt = 0; _last_sync_request_tick = 0; diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index 2b7058c66..ba898fedf 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -105,14 +105,14 @@ typedef struct ScheduleWeeklyMask { /****************************************************************************** CLASS DECLARATION ******************************************************************************/ -class Schedule : public TimeService { +class Schedule { public: unsigned int frm, to, len, msk; Schedule(unsigned int s, unsigned int e, unsigned int d, unsigned int m): frm(s), to(e), len(d), msk(m) {} bool isActive() { - unsigned int now = getLocalTime(); + unsigned int now = _schedule_time_service->getLocalTime(); if(checkSchedulePeriod(now, frm, to)) { /* We are in the schedule range */ @@ -193,6 +193,8 @@ class Schedule : public TimeService { return !(operator==(aSchedule)); } private: + TimeService * _schedule_time_service = ArduinoIoTCloudTimeService(); + ScheduleUnit getScheduleUnit(unsigned int msk) { return static_cast((msk & SCHEDULE_UNIT_MASK) >> SCHEDULE_UNIT_SHIFT); } diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index e84efbb6a..e919b2ea6 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -247,3 +247,8 @@ time_t cvt_time(char const * time) return mktime(&t); } + +TimeService* ArduinoIoTCloudTimeService() { + static TimeService _timeService_instance; + return &_timeService_instance; +} diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 3582dd608..4de6c222c 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -70,4 +70,6 @@ class TimeService }; +TimeService* ArduinoIoTCloudTimeService(); + #endif /* ARDUINO_IOT_CLOUD_TIME_SERVICE_H_ */ From 4bbe08716e1f1eebefbae1a067e76b4911989f38 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 25 Nov 2021 10:34:05 +0100 Subject: [PATCH 220/780] Add check for valid time --- src/property/types/CloudSchedule.h | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index ba898fedf..9de6f62c9 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -113,15 +113,20 @@ class Schedule { bool isActive() { unsigned int now = _schedule_time_service->getLocalTime(); - if(checkSchedulePeriod(now, frm, to)) { - /* We are in the schedule range */ - if(checkScheduleMask(now, msk)) { + if(checkTimeValid(now)) { + /* We have to wait RTC configuration and Timezone setting from the cloud */ + + if(checkSchedulePeriod(now, frm, to)) { + /* We are in the schedule range */ + + if(checkScheduleMask(now, msk)) { - /* We can assume now that the schedule is always repeating with fixed delta */ - unsigned int delta = getScheduleDelta(msk); - if ( ( (std::max(now , frm) - std::min(now , frm)) % delta ) <= len ) { - return true; + /* We can assume now that the schedule is always repeating with fixed delta */ + unsigned int delta = getScheduleDelta(msk); + if ( ( (std::max(now , frm) - std::min(now , frm)) % delta ) <= len ) { + return true; + } } } } @@ -292,6 +297,10 @@ class Schedule { return ptm->tm_mon; } + bool checkTimeValid(unsigned int now) { + return (now != 0); + } + bool checkSchedulePeriod(unsigned int now, unsigned int frm, unsigned int to) { /* Check if current time is inside the schedule period. If 'to' is equal to * 0 the schedule has no end. From d5a676adf5cd9b8672687cb5a5a0a02c58d96836 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 25 Nov 2021 10:37:59 +0100 Subject: [PATCH 221/780] Return a valid localtime only if timezone is configured and initialize private varibles in constructor --- src/utility/time/TimeService.cpp | 12 +++++++++++- src/utility/time/TimeService.h | 8 +++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index e919b2ea6..18b53e297 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -44,6 +44,7 @@ time_t cvt_time(char const * time); **************************************************************************************/ static time_t const EPOCH_AT_COMPILE_TIME = cvt_time(__DATE__); +static time_t const EPOCH = 0; /************************************************************************************** * CTOR/DTOR @@ -54,6 +55,9 @@ TimeService::TimeService() #if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) , _is_rtc_configured(false) #endif +, _is_tz_configured(false) +, _timezone_offset(0) +, _timezone_dst_until(0) { } @@ -100,12 +104,18 @@ void TimeService::setTimeZoneData(long offset, unsigned long dst_until) if(_timezone_dst_until != dst_until) DEBUG_DEBUG("ArduinoIoTCloudTCP::%s tz_dst_unitl: [%ul]", __FUNCTION__, dst_until); _timezone_dst_until = dst_until; + + _is_tz_configured = true; } unsigned long TimeService::getLocalTime() { unsigned long utc = getTime(); - return utc + _timezone_offset; + if(_is_tz_configured) { + return utc + _timezone_offset; + } else { + return EPOCH; + } } unsigned long TimeService::getTimeFromString(const String& input) diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 4de6c222c..88b3ca986 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -59,15 +59,13 @@ class TimeService #if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) bool _is_rtc_configured; #endif + bool _is_tz_configured; + long _timezone_offset; + unsigned long _timezone_dst_until; unsigned long getRemoteTime(); - static bool isTimeValid(unsigned long const time); -private: - long _timezone_offset; - unsigned long _timezone_dst_until; - }; TimeService* ArduinoIoTCloudTimeService(); From cb39907dd2db0ce107a7ede8470c09aabfb8c74d Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 25 Nov 2021 12:22:36 +0100 Subject: [PATCH 222/780] Do not store EPOCH_AT_COMPILE_TIME into the RTC --- src/utility/time/TimeService.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 18b53e297..83b9bc4e9 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -79,15 +79,25 @@ unsigned long TimeService::getTime() #ifdef ARDUINO_ARCH_SAMD if(!_is_rtc_configured) { - rtc.setEpoch(getRemoteTime()); - _is_rtc_configured = true; + unsigned long utc = getRemoteTime(); + if(EPOCH_AT_COMPILE_TIME != utc) + { + rtc.setEpoch(utc); + _is_rtc_configured = true; + } + return utc; } return rtc.getEpoch(); #elif ARDUINO_ARCH_MBED if(!_is_rtc_configured) { - set_time(getRemoteTime()); - _is_rtc_configured = true; + unsigned long utc = getRemoteTime(); + if(EPOCH_AT_COMPILE_TIME != utc) + { + set_time(utc); + _is_rtc_configured = true; + } + return utc; } return time(NULL); #else From 0776f4b8baef9e450dc0d9f91ff7930e05b0587d Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 29 Nov 2021 16:36:46 +0100 Subject: [PATCH 223/780] Use correct destination type when casting enums --- src/property/types/CloudSchedule.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index 9de6f62c9..5d0b09dbe 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -138,8 +138,8 @@ class Schedule { } static unsigned int createFixedDeltaScheduleConfiguration(ScheduleUnit unit, unsigned int delta) { - unsigned int temp_unit = static_cast(unit); - unsigned int temp_type = static_cast(ScheduleType::FixedDelta); + int temp_unit = static_cast(unit); + int temp_type = static_cast(ScheduleType::FixedDelta); unsigned int temp_delta = delta; if (temp_delta > SCHEDULE_REP_MASK) { @@ -150,7 +150,7 @@ class Schedule { static unsigned int createWeeklyScheduleConfiguration(ScheduleWeeklyMask weekMask) { unsigned int temp_week = 0; - unsigned int temp_type = static_cast(ScheduleType::Weekly); + int temp_type = static_cast(ScheduleType::Weekly); for(int i = 0; i<7; i++) { if(weekMask[static_cast(i)] == ScheduleState::Active) { @@ -162,7 +162,7 @@ class Schedule { static unsigned int createMonthlyScheduleConfiguration(int dayOfTheMonth) { int temp_day = dayOfTheMonth; - unsigned int temp_type = static_cast(ScheduleType::Monthly); + int temp_type = static_cast(ScheduleType::Monthly); if(temp_day < 1) { temp_day = 1; @@ -175,9 +175,9 @@ class Schedule { } static unsigned int createYearlyScheduleConfiguration(ScheduleMonth month, int dayOfTheMonth) { - int temp_day = createMonthlyScheduleConfiguration(dayOfTheMonth); + unsigned int temp_day = createMonthlyScheduleConfiguration(dayOfTheMonth); int temp_month = static_cast(month); - unsigned int temp_type = static_cast(ScheduleType::Yearly); + int temp_type = static_cast(ScheduleType::Yearly); return (temp_type << SCHEDULE_TYPE_SHIFT) | (temp_month << SCHEDULE_MONTH_SHIFT)| temp_day; } From 028c2998f372282c900cbd20c8244fe9a0b3e49b Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 29 Nov 2021 16:30:30 +0100 Subject: [PATCH 224/780] Use ScheduleTimeType and ScheduleConfigurationType instead of unsigned int --- .../ArduinoIoTCloud-Schedule.ino | 54 ++++++++-------- src/property/types/CloudSchedule.h | 61 ++++++++++--------- 2 files changed, 59 insertions(+), 56 deletions(-) diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index a64b94f7a..c035079e4 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -63,12 +63,12 @@ void setup() { */ void setupOneShotSchedule() { - unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); - unsigned int until = startingFrom + ( DAYS * 1 ); - unsigned int activePeriod = MINUTES * 5; + ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); + ScheduleTimeType until = startingFrom + ( DAYS * 1 ); + ScheduleTimeType activePeriod = MINUTES * 5; /* Warning: there is no cross check between until and activePeriod */ - unsigned int scheduleConfiguration = Schedule::createOneShotScheduleConfiguration(); + ScheduleConfigurationType scheduleConfiguration = Schedule::createOneShotScheduleConfiguration(); oneShot = Schedule(startingFrom, until, activePeriod, scheduleConfiguration); } @@ -79,13 +79,13 @@ void setupOneShotSchedule() { */ void setupMinuteSchedule() { - unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); - unsigned int until = startingFrom + ( DAYS * 1 ); - unsigned int activePeriod = SECONDS * 15; + ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); + ScheduleTimeType until = startingFrom + ( DAYS * 1 ); + ScheduleTimeType activePeriod = SECONDS * 15; unsigned int repetitionPeriod = 1; /* Warning: there is no cross check between repetitionPeriod and activePeriod */ - unsigned int scheduleConfiguration = Schedule::createFixedDeltaScheduleConfiguration(ScheduleUnit::Minutes, repetitionPeriod); + ScheduleConfigurationType scheduleConfiguration = Schedule::createFixedDeltaScheduleConfiguration(ScheduleUnit::Minutes, repetitionPeriod); minute = Schedule(startingFrom, until, activePeriod, scheduleConfiguration); } @@ -96,13 +96,13 @@ void setupMinuteSchedule() { */ void setupHourlySchedule() { - unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); - unsigned int until = TimeService::getTimeFromString("2021 Nov 15 13:00:00"); - unsigned int activePeriod = MINUTES * 20; + ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); + ScheduleTimeType until = TimeService::getTimeFromString("2021 Nov 15 13:00:00"); + ScheduleTimeType activePeriod = MINUTES * 20; unsigned int repetitionPeriod = 1; /* Warning: there is no cross check between repetitionPeriod and activePeriod */ - unsigned int scheduleConfiguration = Schedule::createFixedDeltaScheduleConfiguration(ScheduleUnit::Hours, repetitionPeriod); + ScheduleConfigurationType scheduleConfiguration = Schedule::createFixedDeltaScheduleConfiguration(ScheduleUnit::Hours, repetitionPeriod); hourly = Schedule(startingFrom, until, activePeriod, scheduleConfiguration); } @@ -113,13 +113,13 @@ void setupHourlySchedule() { */ void setupDailySchedule() { - unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); - unsigned int until = TimeService::getTimeFromString("2021 Nov 15 13:00:00"); - unsigned int activePeriod = HOURS * 2; + ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); + ScheduleTimeType until = TimeService::getTimeFromString("2021 Nov 15 13:00:00"); + ScheduleTimeType activePeriod = HOURS * 2; unsigned int repetitionPeriod = 1; /* Warning: there is no cross check between repetitionPeriod and activePeriod */ - unsigned int scheduleConfiguration = Schedule::createFixedDeltaScheduleConfiguration(ScheduleUnit::Days, repetitionPeriod); + ScheduleConfigurationType scheduleConfiguration = Schedule::createFixedDeltaScheduleConfiguration(ScheduleUnit::Days, repetitionPeriod); daily = Schedule(startingFrom, until, activePeriod, scheduleConfiguration); } @@ -152,7 +152,7 @@ void setupWeeklySchedule() { ScheduleState::Inactive, /* Saturday */ }; - unsigned int scheduleConfiguration = Schedule::createWeeklyScheduleConfiguration(WeeklyMask); + ScheduleConfigurationType scheduleConfiguration = Schedule::createWeeklyScheduleConfiguration(WeeklyMask); weekly = Schedule(startingFrom, until, executionPeriod, scheduleConfiguration); } @@ -163,12 +163,12 @@ void setupWeeklySchedule() { */ void setupMonthlySchedule() { - unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); - unsigned int until = TimeService::getTimeFromString("2021 Nov 15 13:00:00"); - unsigned int activePeriod = DAYS * 1; - unsigned int dayOfMonth = 3; + ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); + ScheduleTimeType until = TimeService::getTimeFromString("2021 Nov 15 13:00:00"); + ScheduleTimeType activePeriod = DAYS * 1; + int dayOfMonth = 3; - unsigned int scheduleConfiguration = Schedule::createMonthlyScheduleConfiguration(dayOfMonth); + ScheduleConfigurationType scheduleConfiguration = Schedule::createMonthlyScheduleConfiguration(dayOfMonth); monthly = Schedule(startingFrom, until, activePeriod, scheduleConfiguration); } @@ -180,12 +180,12 @@ void setupMonthlySchedule() { */ void setupYearlySchedule() { - unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 06 17:00:00"); - unsigned int until = TimeService::getTimeFromString("2041 Nov 06 13:00:00"); - unsigned int activePeriod = DAYS * 2; - unsigned int dayOfMonth = 6; + ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 06 17:00:00"); + ScheduleTimeType until = TimeService::getTimeFromString("2041 Nov 06 13:00:00"); + ScheduleTimeType activePeriod = DAYS * 2; + int dayOfMonth = 6; - unsigned int scheduleConfiguration = Schedule::createYearlyScheduleConfiguration(ScheduleMonth::Nov, dayOfMonth); + ScheduleConfigurationType scheduleConfiguration = Schedule::createYearlyScheduleConfiguration(ScheduleMonth::Nov, dayOfMonth); yearly = Schedule(startingFrom, until, activePeriod, scheduleConfiguration); } diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index 5d0b09dbe..0dcdf4cf6 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -102,17 +102,20 @@ typedef struct ScheduleWeeklyMask { ScheduleState day[7]; }ScheduleWeeklyMask; +typedef unsigned int ScheduleTimeType; +typedef unsigned int ScheduleConfigurationType; + /****************************************************************************** CLASS DECLARATION ******************************************************************************/ class Schedule { public: - unsigned int frm, to, len, msk; - Schedule(unsigned int s, unsigned int e, unsigned int d, unsigned int m): frm(s), to(e), len(d), msk(m) {} + ScheduleTimeType frm, to, len, msk; + Schedule(ScheduleTimeType s, ScheduleTimeType e, ScheduleTimeType d, ScheduleConfigurationType m): frm(s), to(e), len(d), msk(m) {} bool isActive() { - unsigned int now = _schedule_time_service->getLocalTime(); + ScheduleTimeType now = _schedule_time_service->getLocalTime(); if(checkTimeValid(now)) { /* We have to wait RTC configuration and Timezone setting from the cloud */ @@ -121,9 +124,9 @@ class Schedule { /* We are in the schedule range */ if(checkScheduleMask(now, msk)) { - + /* We can assume now that the schedule is always repeating with fixed delta */ - unsigned int delta = getScheduleDelta(msk); + ScheduleTimeType delta = getScheduleDelta(msk); if ( ( (std::max(now , frm) - std::min(now , frm)) % delta ) <= len ) { return true; } @@ -133,11 +136,11 @@ class Schedule { return false; } - static unsigned int createOneShotScheduleConfiguration() { + static ScheduleConfigurationType createOneShotScheduleConfiguration() { return 0; } - static unsigned int createFixedDeltaScheduleConfiguration(ScheduleUnit unit, unsigned int delta) { + static ScheduleConfigurationType createFixedDeltaScheduleConfiguration(ScheduleUnit unit, unsigned int delta) { int temp_unit = static_cast(unit); int temp_type = static_cast(ScheduleType::FixedDelta); unsigned int temp_delta = delta; @@ -148,7 +151,7 @@ class Schedule { return (temp_unit << SCHEDULE_UNIT_SHIFT) | (temp_type << SCHEDULE_TYPE_SHIFT) | temp_delta; } - static unsigned int createWeeklyScheduleConfiguration(ScheduleWeeklyMask weekMask) { + static ScheduleConfigurationType createWeeklyScheduleConfiguration(ScheduleWeeklyMask weekMask) { unsigned int temp_week = 0; int temp_type = static_cast(ScheduleType::Weekly); @@ -160,7 +163,7 @@ class Schedule { return (temp_type << SCHEDULE_TYPE_SHIFT) | temp_week; } - static unsigned int createMonthlyScheduleConfiguration(int dayOfTheMonth) { + static ScheduleConfigurationType createMonthlyScheduleConfiguration(int dayOfTheMonth) { int temp_day = dayOfTheMonth; int temp_type = static_cast(ScheduleType::Monthly); @@ -174,7 +177,7 @@ class Schedule { return (temp_type << SCHEDULE_TYPE_SHIFT) | temp_day; } - static unsigned int createYearlyScheduleConfiguration(ScheduleMonth month, int dayOfTheMonth) { + static ScheduleConfigurationType createYearlyScheduleConfiguration(ScheduleMonth month, int dayOfTheMonth) { unsigned int temp_day = createMonthlyScheduleConfiguration(dayOfTheMonth); int temp_month = static_cast(month); int temp_type = static_cast(ScheduleType::Yearly); @@ -200,51 +203,51 @@ class Schedule { private: TimeService * _schedule_time_service = ArduinoIoTCloudTimeService(); - ScheduleUnit getScheduleUnit(unsigned int msk) { + ScheduleUnit getScheduleUnit(ScheduleConfigurationType msk) { return static_cast((msk & SCHEDULE_UNIT_MASK) >> SCHEDULE_UNIT_SHIFT); } - ScheduleType getScheduleType(unsigned int msk) { + ScheduleType getScheduleType(ScheduleConfigurationType msk) { return static_cast((msk & SCHEDULE_TYPE_MASK) >> SCHEDULE_TYPE_SHIFT); } - unsigned int getScheduleRepetition(unsigned int msk) { + unsigned int getScheduleRepetition(ScheduleConfigurationType msk) { return (msk & SCHEDULE_REP_MASK); } - unsigned int getScheduleWeekMask(unsigned int msk) { + unsigned int getScheduleWeekMask(ScheduleConfigurationType msk) { return (msk & SCHEDULE_WEEK_MASK); } - unsigned int getScheduleDay(unsigned int msk) { + unsigned int getScheduleDay(ScheduleConfigurationType msk) { return (msk & SCHEDULE_DAY_MASK); } - unsigned int getScheduleMonth(unsigned int msk) { + unsigned int getScheduleMonth(ScheduleConfigurationType msk) { return ((msk & SCHEDULE_MONTH_MASK) >> SCHEDULE_MONTH_SHIFT); } - bool isScheduleOneShot(unsigned int msk) { + bool isScheduleOneShot(ScheduleConfigurationType msk) { return (getScheduleType(msk) == ScheduleType::OneShot) ? true : false ; } - bool isScheduleFixed(unsigned int msk) { + bool isScheduleFixed(ScheduleConfigurationType msk) { return (getScheduleType(msk) == ScheduleType::FixedDelta) ? true : false ; } - bool isScheduleWeekly(unsigned int msk) { + bool isScheduleWeekly(ScheduleConfigurationType msk) { return (getScheduleType(msk) == ScheduleType::Weekly) ? true : false ; } - bool isScheduleMonthly(unsigned int msk) { + bool isScheduleMonthly(ScheduleConfigurationType msk) { return (getScheduleType(msk) == ScheduleType::Monthly) ? true : false ; } - bool isScheduleYearly(unsigned int msk) { + bool isScheduleYearly(ScheduleConfigurationType msk) { return (getScheduleType(msk) == ScheduleType::Yearly) ? true : false ; } - bool isScheduleInSeconds(unsigned int msk) { + bool isScheduleInSeconds(ScheduleConfigurationType msk) { if(isScheduleFixed(msk)) { return (getScheduleUnit(msk) == ScheduleUnit::Seconds) ? true : false ; } else { @@ -252,7 +255,7 @@ class Schedule { } } - bool isScheduleInMinutes(unsigned int msk) { + bool isScheduleInMinutes(ScheduleConfigurationType msk) { if(isScheduleFixed(msk)) { return (getScheduleUnit(msk) == ScheduleUnit::Minutes) ? true : false ; } else { @@ -260,7 +263,7 @@ class Schedule { } } - bool isScheduleInHours(unsigned int msk) { + bool isScheduleInHours(ScheduleConfigurationType msk) { if(isScheduleFixed(msk)) { return (getScheduleUnit(msk) == ScheduleUnit::Hours) ? true : false ; } else { @@ -268,7 +271,7 @@ class Schedule { } } - bool isScheduleInDays(unsigned int msk) { + bool isScheduleInDays(ScheduleConfigurationType msk) { if(isScheduleFixed(msk)) { return (getScheduleUnit(msk) == ScheduleUnit::Days) ? true : false ; } else { @@ -297,11 +300,11 @@ class Schedule { return ptm->tm_mon; } - bool checkTimeValid(unsigned int now) { + bool checkTimeValid(ScheduleTimeType now) { return (now != 0); } - bool checkSchedulePeriod(unsigned int now, unsigned int frm, unsigned int to) { + bool checkSchedulePeriod(ScheduleTimeType now, ScheduleTimeType frm, ScheduleTimeType to) { /* Check if current time is inside the schedule period. If 'to' is equal to * 0 the schedule has no end. */ @@ -312,7 +315,7 @@ class Schedule { } } - bool checkScheduleMask(unsigned int now, unsigned int msk) { + bool checkScheduleMask(ScheduleTimeType now, ScheduleConfigurationType msk) { if(isScheduleFixed(msk) || isScheduleOneShot(msk)) { return true; } @@ -349,7 +352,7 @@ class Schedule { return false; } - unsigned int getScheduleDelta(unsigned int msk) { + ScheduleTimeType getScheduleDelta(ScheduleConfigurationType msk) { if(isScheduleInSeconds(msk)) { return SECONDS * getScheduleRepetition(msk); } From d42e419fd7caa19a8be4f6f7c685ca7c68d60ef4 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 30 Nov 2021 15:07:09 +0100 Subject: [PATCH 225/780] Move TimeService::getLocalTime() into CloudSchedule test file to make more clear how the time is configured --- extras/test/src/test_CloudSchedule.cpp | 2 +- extras/test/src/util/PropertyTestUtil.cpp | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/extras/test/src/test_CloudSchedule.cpp b/extras/test/src/test_CloudSchedule.cpp index aba4aad0f..53b582aef 100644 --- a/extras/test/src/test_CloudSchedule.cpp +++ b/extras/test/src/test_CloudSchedule.cpp @@ -22,7 +22,7 @@ TimeService::TimeService() {} * TimeService Fake Methods **************************************************************************************/ -unsigned long TimeService::getTime() {return time_now;} +unsigned long TimeService::getLocalTime() {return time_now;} /************************************************************************************** TEST CODE diff --git a/extras/test/src/util/PropertyTestUtil.cpp b/extras/test/src/util/PropertyTestUtil.cpp index ef6d85a99..a4b4e0345 100644 --- a/extras/test/src/util/PropertyTestUtil.cpp +++ b/extras/test/src/util/PropertyTestUtil.cpp @@ -19,11 +19,6 @@ unsigned long getTime() return 0; } -unsigned long TimeService::getLocalTime() -{ - return getTime(); -} - TimeService* ArduinoIoTCloudTimeService() { static TimeService _timeService_instance; return &_timeService_instance; From 71059d045269c8e21bdfc4f6250e2d6aa30c1c65 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 30 Nov 2021 14:01:23 +0100 Subject: [PATCH 226/780] Make ArduinoIoTCloudTimeService return a reference instead of a pointer --- extras/test/src/util/PropertyTestUtil.cpp | 4 ++-- src/ArduinoIoTCloud.h | 8 ++++---- src/ArduinoIoTCloudLPWAN.cpp | 4 ++-- src/ArduinoIoTCloudTCP.cpp | 8 ++++---- src/property/types/CloudSchedule.h | 4 ++-- src/utility/time/TimeService.cpp | 4 ++-- src/utility/time/TimeService.h | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/extras/test/src/util/PropertyTestUtil.cpp b/extras/test/src/util/PropertyTestUtil.cpp index a4b4e0345..ca71cd765 100644 --- a/extras/test/src/util/PropertyTestUtil.cpp +++ b/extras/test/src/util/PropertyTestUtil.cpp @@ -19,7 +19,7 @@ unsigned long getTime() return 0; } -TimeService* ArduinoIoTCloudTimeService() { +TimeService & ArduinoIoTCloudTimeService() { static TimeService _timeService_instance; - return &_timeService_instance; + return _timeService_instance; } diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 5041bc359..b73cd1cf9 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -97,9 +97,9 @@ class ArduinoIoTCloudClass inline ConnectionHandler * getConnection() { return _connection; } - inline unsigned long getInternalTime() { return _time_service->getTime(); } - inline unsigned long getLocalTime() { return _time_service->getLocalTime(); } - inline void updateInternalTimezoneInfo() { _time_service->setTimeZoneData(_tz_offset, _tz_dst_until); } + inline unsigned long getInternalTime() { return _time_service.getTime(); } + inline unsigned long getLocalTime() { return _time_service.getLocalTime(); } + inline void updateInternalTimezoneInfo() { _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); } void addCallback(ArduinoIoTCloudEvent const event, OnCloudEventCallback callback); @@ -147,7 +147,7 @@ class ArduinoIoTCloudClass ConnectionHandler * _connection = nullptr; PropertyContainer _property_container; - TimeService * _time_service = ArduinoIoTCloudTimeService(); + TimeService & _time_service = ArduinoIoTCloudTimeService(); int _tz_offset = 0; unsigned int _tz_dst_until = 0; diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 17da1f651..29458f21a 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -68,7 +68,7 @@ int ArduinoIoTCloudLPWAN::begin(ConnectionHandler& connection, bool retry) { _connection = &connection; _retryEnable = retry; - _time_service->begin(nullptr); + _time_service.begin(nullptr); return 1; } @@ -105,7 +105,7 @@ ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_ConnectPhy() ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_SyncTime() { - unsigned long const internal_posix_time = _time_service->getTime(); + unsigned long const internal_posix_time = _time_service.getTime(); DEBUG_VERBOSE("ArduinoIoTCloudLPWAN::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); DEBUG_INFO("Connected to Arduino IoT Cloud"); return State::Connected; diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index c4e469e53..11245ea85 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -115,7 +115,7 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_ _connection = &connection; _brokerAddress = brokerAddress; _brokerPort = brokerPort; - _time_service->begin(&connection); + _time_service.begin(&connection); return begin(enable_watchdog, _brokerAddress, _brokerPort); } @@ -371,7 +371,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() { - unsigned long const internal_posix_time = _time_service->getTime(); + unsigned long const internal_posix_time = _time_service.getTime(); DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); return State::ConnectMqttBroker; } @@ -535,7 +535,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() */ sendPropertiesToCloud(); - unsigned long const internal_posix_time = _time_service->getTime(); + unsigned long const internal_posix_time = _time_service.getTime(); if(internal_posix_time < _tz_dst_until) { return State::Connected; } else { @@ -568,7 +568,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); CBORDecoder::decode(_property_container, (uint8_t*)bytes, length, true); sendPropertiesToCloud(); - _time_service->setTimeZoneData(_tz_offset, _tz_dst_until); + _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); _last_sync_request_cnt = 0; _last_sync_request_tick = 0; diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index 0dcdf4cf6..93090c507 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -115,7 +115,7 @@ class Schedule { bool isActive() { - ScheduleTimeType now = _schedule_time_service->getLocalTime(); + ScheduleTimeType now = _schedule_time_service.getLocalTime(); if(checkTimeValid(now)) { /* We have to wait RTC configuration and Timezone setting from the cloud */ @@ -201,7 +201,7 @@ class Schedule { return !(operator==(aSchedule)); } private: - TimeService * _schedule_time_service = ArduinoIoTCloudTimeService(); + TimeService & _schedule_time_service = ArduinoIoTCloudTimeService(); ScheduleUnit getScheduleUnit(ScheduleConfigurationType msk) { return static_cast((msk & SCHEDULE_UNIT_MASK) >> SCHEDULE_UNIT_SHIFT); diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 83b9bc4e9..112745d06 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -268,7 +268,7 @@ time_t cvt_time(char const * time) return mktime(&t); } -TimeService* ArduinoIoTCloudTimeService() { +TimeService & ArduinoIoTCloudTimeService() { static TimeService _timeService_instance; - return &_timeService_instance; + return _timeService_instance; } diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 88b3ca986..fbe81986d 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -68,6 +68,6 @@ class TimeService }; -TimeService* ArduinoIoTCloudTimeService(); +TimeService & ArduinoIoTCloudTimeService(); #endif /* ARDUINO_IOT_CLOUD_TIME_SERVICE_H_ */ From fda11b53c9373a7f4c5b5fdcef2100042b964873 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 2 Dec 2021 07:06:56 +0100 Subject: [PATCH 227/780] Add ArduinoIoTCloudClass CTOR and initialize variables in it --- src/ArduinoIoTCloud.cpp | 16 ++++++++++++++++ src/ArduinoIoTCloud.h | 15 ++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 5b5637eb3..b62a91990 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -21,6 +21,22 @@ #include +/****************************************************************************** + CTOR/DTOR + ******************************************************************************/ + +ArduinoIoTCloudClass::ArduinoIoTCloudClass() +: _connection{nullptr} +, _time_service(ArduinoIoTCloudTimeService()) +, _tz_offset{0} +, _tz_dst_until{0} +, _thing_id{""} +, _device_id{""} +, _cloud_event_callback{nullptr} +{ + +} + /****************************************************************************** * PUBLIC MEMBER FUNCTIONS ******************************************************************************/ diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index b73cd1cf9..ae8ac1a86 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -80,6 +80,7 @@ class ArduinoIoTCloudClass { public: + ArduinoIoTCloudClass(); virtual ~ArduinoIoTCloudClass() { } @@ -145,19 +146,19 @@ class ArduinoIoTCloudClass protected: - ConnectionHandler * _connection = nullptr; + ConnectionHandler * _connection; PropertyContainer _property_container; - TimeService & _time_service = ArduinoIoTCloudTimeService(); - int _tz_offset = 0; - unsigned int _tz_dst_until = 0; + TimeService & _time_service; + int _tz_offset; + unsigned int _tz_dst_until; void execCloudEventCallback(ArduinoIoTCloudEvent const event); private: - String _thing_id = ""; - String _device_id = ""; - OnCloudEventCallback _cloud_event_callback[3] = {nullptr}; + String _thing_id; + String _device_id; + OnCloudEventCallback _cloud_event_callback[3]; }; #ifdef HAS_TCP From 070eb73074bb1a5caff91eacb8acb94d84df6150 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 6 Dec 2021 10:51:24 +0100 Subject: [PATCH 228/780] Release v1.4.0 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 7306aa2ec..39ee1b3a5 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.3.1 +version=1.4.0 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From 676b4fe83a1e779354eedf8b9bc71d1a4f7d2abd Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 26 Nov 2021 11:19:00 +0100 Subject: [PATCH 229/780] Move ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() inside #if OTA_ENABLED directive --- src/ArduinoIoTCloudTCP.cpp | 2 ++ src/ArduinoIoTCloudTCP.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 4d4f86b9d..4fc6c4b50 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -585,6 +585,7 @@ void ArduinoIoTCloudTCP::sendPropertiesToCloud() sendPropertyContainerToCloud(_property_container); } +#if OTA_ENABLED void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() { PropertyContainer ota_property_container; @@ -602,6 +603,7 @@ void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() sendPropertyContainerToCloud(ota_property_container); } +#endif void ArduinoIoTCloudTCP::requestLastValue() { diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 21063c29f..c36fae4d8 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -166,12 +166,12 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass void handleMessage(int length); void sendPropertyContainerToCloud(PropertyContainer & property_container); void sendPropertiesToCloud(); - void sendOTAPropertiesToCloud(); void requestLastValue(); int write(String const topic, byte const data[], int const length); #if OTA_ENABLED void onOTARequest(); + void sendOTAPropertiesToCloud(); #endif }; From 0cfc02f6d13ea347fc9b542b8a83d53b466e0e9b Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 9 Dec 2021 13:26:34 +0100 Subject: [PATCH 230/780] Minor change: Schedule example sketch: Fix supported board list removing MKR WAN from header comment --- examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index c035079e4..3e01f9703 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -6,7 +6,6 @@ - MKR WIFI 1010 - MKR GSM 1400 - MKR NB 1500 - - MKR WAN 1300/1310 - Nano 33 IoT - ESP 8266 */ From 97a98cb13ac040ff4c38e4e8d55e18eeeab6f8c1 Mon Sep 17 00:00:00 2001 From: per1234 Date: Mon, 10 Jan 2022 00:47:20 -0800 Subject: [PATCH 231/780] Add GitHub Actions workflow to synchronize with shared repository labels (#296) On every push that changes relevant files, and periodically, configure the repository's issue and pull request labels according to the universal, shared, and local label configuration files. --- .github/workflows/sync-labels.yml | 138 ++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 .github/workflows/sync-labels.yml diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml new file mode 100644 index 000000000..3ee6febdc --- /dev/null +++ b/.github/workflows/sync-labels.yml @@ -0,0 +1,138 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels.md +name: Sync Labels + +# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows +on: + push: + paths: + - ".github/workflows/sync-labels.ya?ml" + - ".github/label-configuration-files/*.ya?ml" + pull_request: + paths: + - ".github/workflows/sync-labels.ya?ml" + - ".github/label-configuration-files/*.ya?ml" + schedule: + # Run daily at 8 AM UTC to sync with changes to shared label configurations. + - cron: "0 8 * * *" + workflow_dispatch: + repository_dispatch: + +env: + CONFIGURATIONS_FOLDER: .github/label-configuration-files + CONFIGURATIONS_ARTIFACT: label-configuration-files + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Download JSON schema for labels configuration file + id: download-schema + uses: carlosperate/download-file-action@v1 + with: + file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json + location: ${{ runner.temp }}/label-configuration-schema + + - name: Install JSON schema validator + run: | + sudo npm install \ + --global \ + ajv-cli \ + ajv-formats + + - name: Validate local labels configuration + run: | + # See: https://github.com/ajv-validator/ajv-cli#readme + ajv validate \ + --all-errors \ + -c ajv-formats \ + -s "${{ steps.download-schema.outputs.file-path }}" \ + -d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}" + + download: + needs: check + runs-on: ubuntu-latest + + strategy: + matrix: + filename: + # Filenames of the shared configurations to apply to the repository in addition to the local configuration. + # https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels + - universal.yml + + steps: + - name: Download + uses: carlosperate/download-file-action@v1 + with: + file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} + + - name: Pass configuration files to next job via workflow artifact + uses: actions/upload-artifact@v2 + with: + path: | + *.yaml + *.yml + if-no-files-found: error + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + + sync: + needs: download + runs-on: ubuntu-latest + + steps: + - name: Set environment variables + run: | + # See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable + echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV" + + - name: Determine whether to dry run + id: dry-run + if: > + github.event_name == 'pull_request' || + ( + ( + github.event_name == 'push' || + github.event_name == 'workflow_dispatch' + ) && + github.ref != format('refs/heads/{0}', github.event.repository.default_branch) + ) + run: | + # Use of this flag in the github-label-sync command will cause it to only check the validity of the + # configuration. + echo "::set-output name=flag::--dry-run" + + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Download configuration files artifact + uses: actions/download-artifact@v2 + with: + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + path: ${{ env.CONFIGURATIONS_FOLDER }} + + - name: Remove unneeded artifact + uses: geekyeggo/delete-artifact@v1 + with: + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + + - name: Merge label configuration files + run: | + # Merge all configuration files + shopt -s extglob + cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}" + + - name: Install github-label-sync + run: sudo npm install --global github-label-sync + + - name: Sync labels + env: + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # See: https://github.com/Financial-Times/github-label-sync + github-label-sync \ + --labels "${{ env.MERGED_CONFIGURATION_PATH }}" \ + ${{ steps.dry-run.outputs.flag }} \ + ${{ github.repository }} From cb71b92f2a2cc37b4131cac86a58bca9ed36f5d8 Mon Sep 17 00:00:00 2001 From: Ubi de Feo Date: Mon, 10 Jan 2022 10:40:47 +0100 Subject: [PATCH 232/780] added definition of generic ESP32 to ARCH test (#294) Some platforms do not define `ARDUINO_ARCH_ESP32` in favour of their own (see InkPlate's `ARCH_ARDUINO_INKPLATE). This will cause compilation to fail for those devices. Since every `ESP32` core defines `ESP32`, this has been added to the ARCH test in order to define `BOARD_ESP` --- src/AIoTC_Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 9ceb2ac62..26be67d51 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -131,7 +131,7 @@ #define HAS_LORA #endif -#if defined(ARDUINO_ESP8266_ESP12) || defined(ARDUINO_ARCH_ESP32) || defined(ESP8266) +#if defined(ARDUINO_ESP8266_ESP12) || defined(ARDUINO_ARCH_ESP32) || defined(ESP8266) || defined(ESP32) #define BOARD_ESP #define HAS_TCP #endif From eef26053d0b947ef9de784c7f225f2357fcbaede Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 13 Jan 2022 10:48:26 +0100 Subject: [PATCH 233/780] Add retry delay on topic subscription failures --- src/AIoTC_Config.h | 2 ++ src/ArduinoIoTCloudTCP.cpp | 62 +++++++++++++++++++++++++++----------- src/ArduinoIoTCloudTCP.h | 2 ++ 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 26be67d51..6949524d6 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -142,6 +142,8 @@ #define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) #define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) +#define AIOT_CONFIG_SUBSCRIBE_RETRY_DELAY_ms (1000UL) +#define AIOT_CONFIG_SUBSCRIBE_MAX_RETRY_CNT (10UL) #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 8bd632ad8..b1d61a7d6 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -79,6 +79,8 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _last_connection_attempt_cnt{0} , _last_sync_request_tick{0} , _last_sync_request_cnt{0} +, _last_subscribe_request_tick{0} +, _last_subscribe_request_cnt{0} , _mqtt_data_buf{0} , _mqtt_data_len{0} , _mqtt_data_request_retransmit{false} @@ -404,34 +406,58 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() return State::ConnectPhy; } - if (!_mqttClient.subscribe(_dataTopicIn)) + unsigned long const now = millis(); + bool const is_subscribe_retry_delay_expired = (now - _last_subscribe_request_tick) > AIOT_CONFIG_SUBSCRIBE_RETRY_DELAY_ms; + bool const is_first_subscribe_request = (_last_subscribe_request_cnt == 0); + if (is_first_subscribe_request || is_subscribe_retry_delay_expired) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); -#if !defined(__AVR__) - DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); -#endif - return State::SubscribeMqttTopics; - } + if (_last_subscribe_request_cnt > AIOT_CONFIG_SUBSCRIBE_MAX_RETRY_CNT) + { + _last_subscribe_request_cnt = 0; + _last_subscribe_request_tick = 0; + _mqttClient.stop(); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + return State::ConnectPhy; + } - if (_shadowTopicIn != "") - { - if (!_mqttClient.subscribe(_shadowTopicIn)) + _last_subscribe_request_tick = now; + _last_subscribe_request_cnt++; + + if (!_mqttClient.subscribe(_dataTopicIn)) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); #if !defined(__AVR__) DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); #endif return State::SubscribeMqttTopics; } - } - DEBUG_INFO("Connected to Arduino IoT Cloud"); - execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); + if (_shadowTopicIn != "") + { + if (!_mqttClient.subscribe(_shadowTopicIn)) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); +#if !defined(__AVR__) + DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); +#endif + return State::SubscribeMqttTopics; + } + } - if (_shadowTopicIn != "") - return State::RequestLastValues; - else - return State::Connected; + _last_subscribe_request_cnt = 0; + _last_subscribe_request_tick = 0; + + DEBUG_INFO("Connected to Arduino IoT Cloud"); + execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); + + if (_shadowTopicIn != "") + return State::RequestLastValues; + else + return State::Connected; + + } + + return State::SubscribeMqttTopics; } ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index c36fae4d8..7d91d86d3 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -116,6 +116,8 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass unsigned int _last_connection_attempt_cnt; unsigned long _last_sync_request_tick; unsigned int _last_sync_request_cnt; + unsigned long _last_subscribe_request_tick; + unsigned int _last_subscribe_request_cnt; String _brokerAddress; uint16_t _brokerPort; uint8_t _mqtt_data_buf[MQTT_TRANSMIT_BUFFER_SIZE]; From f0328c067e78cf1b932f41f3a3c0eb6c58343623 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 15 Dec 2021 12:17:32 +0100 Subject: [PATCH 234/780] Clear has_been_modified_in_callback after a succesful append --- src/property/Property.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index 18eff23b8..a9b703987 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -107,7 +107,6 @@ bool Property::shouldBeUpdated() { } if (_has_been_modified_in_callback) { - _has_been_modified_in_callback = false; return true; } @@ -148,6 +147,7 @@ CborError Property::append(CborEncoder *encoder, bool lightPayload) { CHECK_CBOR(appendAttributesToCloudReal(encoder)); fromLocalToCloud(); _has_been_updated_once = true; + _has_been_modified_in_callback = false; _update_requested = false; _last_updated_millis = millis(); return CborNoError; From 6136b404ab9383100ecdbf4c2de2ebd0c6c6e664 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 15 Dec 2021 12:20:16 +0100 Subject: [PATCH 235/780] Create CHECK_CBOR_MULTI macro to return CborErrorTooManyItems error if the whole property cannot be appended to the CBOR buffer. Doing so the complete CBOR message will be discarded. --- src/cbor/lib/tinycbor/cbor-lib.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/cbor/lib/tinycbor/cbor-lib.h b/src/cbor/lib/tinycbor/cbor-lib.h index d66553bf8..a9cbe2ca2 100644 --- a/src/cbor/lib/tinycbor/cbor-lib.h +++ b/src/cbor/lib/tinycbor/cbor-lib.h @@ -21,4 +21,16 @@ } while(0); #endif /* CHECK_CBOR */ +#ifndef CHECK_CBOR_MULTI + #define CHECK_CBOR_MULTI(expr) \ + do { \ + CborError error = CborNoError; \ + error = (expr); \ + if (CborErrorOutOfMemory == error) \ + return CborErrorTooManyItems; \ + if (CborNoError != error) \ + return error; \ + } while(0); +#endif /* CHECK_CBOR_MULTI */ + #endif \ No newline at end of file From a89f2d13db3fd923d6b209bc354832a9c10a62f8 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 15 Dec 2021 12:24:41 +0100 Subject: [PATCH 236/780] Use CHECK_CBOR_MULTI in all multivalue properties --- src/property/types/CloudColor.h | 6 +++--- src/property/types/CloudLocation.h | 4 ++-- src/property/types/CloudSchedule.h | 8 ++++---- src/property/types/automation/CloudColoredLight.h | 8 ++++---- src/property/types/automation/CloudDimmedLight.h | 8 ++++---- src/property/types/automation/CloudTelevision.h | 12 ++++++------ 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/property/types/CloudColor.h b/src/property/types/CloudColor.h index 205423165..294a2bb8d 100644 --- a/src/property/types/CloudColor.h +++ b/src/property/types/CloudColor.h @@ -189,9 +189,9 @@ class CloudColor : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - CHECK_CBOR(appendAttribute(_value.hue)); - CHECK_CBOR(appendAttribute(_value.sat)); - CHECK_CBOR(appendAttribute(_value.bri)); + CHECK_CBOR_MULTI(appendAttribute(_value.hue)); + CHECK_CBOR_MULTI(appendAttribute(_value.sat)); + CHECK_CBOR_MULTI(appendAttribute(_value.bri)); return CborNoError; } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudLocation.h b/src/property/types/CloudLocation.h index 0968fea3d..25636cd97 100644 --- a/src/property/types/CloudLocation.h +++ b/src/property/types/CloudLocation.h @@ -90,8 +90,8 @@ class CloudLocation : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - CHECK_CBOR(appendAttribute(_value.lat)); - CHECK_CBOR(appendAttribute(_value.lon)); + CHECK_CBOR_MULTI(appendAttribute(_value.lat)); + CHECK_CBOR_MULTI(appendAttribute(_value.lon)); return CborNoError; } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index 93090c507..47827c59c 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -418,10 +418,10 @@ class CloudSchedule : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - CHECK_CBOR(appendAttribute(_value.frm)); - CHECK_CBOR(appendAttribute(_value.to)); - CHECK_CBOR(appendAttribute(_value.len)); - CHECK_CBOR(appendAttribute(_value.msk)); + CHECK_CBOR_MULTI(appendAttribute(_value.frm)); + CHECK_CBOR_MULTI(appendAttribute(_value.to)); + CHECK_CBOR_MULTI(appendAttribute(_value.len)); + CHECK_CBOR_MULTI(appendAttribute(_value.msk)); return CborNoError; } virtual void setAttributesFromCloud() { diff --git a/src/property/types/automation/CloudColoredLight.h b/src/property/types/automation/CloudColoredLight.h index 8d8c0519b..f38b8354a 100644 --- a/src/property/types/automation/CloudColoredLight.h +++ b/src/property/types/automation/CloudColoredLight.h @@ -119,10 +119,10 @@ class CloudColoredLight : public CloudColor { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - CHECK_CBOR(appendAttribute(_value.swi)); - CHECK_CBOR(appendAttribute(_value.hue)); - CHECK_CBOR(appendAttribute(_value.sat)); - CHECK_CBOR(appendAttribute(_value.bri)); + CHECK_CBOR_MULTI(appendAttribute(_value.swi)); + CHECK_CBOR_MULTI(appendAttribute(_value.hue)); + CHECK_CBOR_MULTI(appendAttribute(_value.sat)); + CHECK_CBOR_MULTI(appendAttribute(_value.bri)); return CborNoError; } virtual void setAttributesFromCloud() { diff --git a/src/property/types/automation/CloudDimmedLight.h b/src/property/types/automation/CloudDimmedLight.h index 1a8f78eef..e14da0f75 100644 --- a/src/property/types/automation/CloudDimmedLight.h +++ b/src/property/types/automation/CloudDimmedLight.h @@ -99,14 +99,14 @@ class CloudDimmedLight : public Property { } virtual CborError appendAttributesToCloud() { - appendAttribute(_value.swi); + CHECK_CBOR_MULTI(appendAttribute(_value.swi)); // To allow visualization through color widget // Start float hue = 0; float sat = 0; - CHECK_CBOR(appendAttributeReal(hue, getAttributeName(".hue", '.'), encoder)); - CHECK_CBOR(appendAttributeReal(sat, getAttributeName(".sat", '.'), encoder)); - CHECK_CBOR(appendAttribute(_value.bri)); + CHECK_CBOR_MULTI(appendAttributeReal(hue, getAttributeName(".hue", '.'), encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(sat, getAttributeName(".sat", '.'), encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.bri)); // should be only: // appendAttribute(_value.bri); // end diff --git a/src/property/types/automation/CloudTelevision.h b/src/property/types/automation/CloudTelevision.h index 1d4ecd2dd..921f1ea56 100644 --- a/src/property/types/automation/CloudTelevision.h +++ b/src/property/types/automation/CloudTelevision.h @@ -214,12 +214,12 @@ class CloudTelevision : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - CHECK_CBOR(appendAttribute(_value.swi)); - CHECK_CBOR(appendAttribute(_value.vol)); - CHECK_CBOR(appendAttribute(_value.mut)); - CHECK_CBOR(appendAttribute((int)_value.pbc)); - CHECK_CBOR(appendAttribute((int)_value.inp)); - CHECK_CBOR(appendAttribute(_value.cha)); + CHECK_CBOR_MULTI(appendAttribute(_value.swi)); + CHECK_CBOR_MULTI(appendAttribute(_value.vol)); + CHECK_CBOR_MULTI(appendAttribute(_value.mut)); + CHECK_CBOR_MULTI(appendAttribute((int)_value.pbc)); + CHECK_CBOR_MULTI(appendAttribute((int)_value.inp)); + CHECK_CBOR_MULTI(appendAttribute(_value.cha)); return CborNoError; } virtual void setAttributesFromCloud() { From 7141e71f75e7a2797bc5c80a8d27fc7c3e127503 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 15 Dec 2021 14:15:35 +0100 Subject: [PATCH 237/780] Proceed encoding properties only if no error occurred --- src/cbor/CBOREncoder.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index 399d521fa..5fbd4a3e2 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -49,13 +49,16 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * property_container.end(), [lightPayload, &arrayEncoder, &error, &num_encoded_properties](Property * p) { - if (p->shouldBeUpdated() && p->isReadableByCloud()) + if(error == CborNoError) { - error = p->append(&arrayEncoder, lightPayload); - if(error == CborNoError) - num_encoded_properties++; - else - return; + if (p->shouldBeUpdated() && p->isReadableByCloud()) + { + error = p->append(&arrayEncoder, lightPayload); + if(error == CborNoError) + num_encoded_properties++; + else + return; + } } }); if ((CborNoError != error) && From f16a696027777d119b0236ba22dbc6cb27cfa918 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 15 Dec 2021 09:20:22 +0100 Subject: [PATCH 238/780] Use a more fair way to send properties to the cloud --- src/cbor/CBOREncoder.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index 5fbd4a3e2..48d783de0 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -24,6 +24,7 @@ #undef max #undef min #include +#include #include "lib/tinycbor/cbor-lib.h" @@ -45,9 +46,18 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * */ CborError error = CborNoError; int num_encoded_properties = 0; - std::for_each(property_container.begin(), + int num_checked_properties = 0; + static unsigned int last_property_index = 0; + + if(last_property_index >= property_container.size()) + last_property_index = 0; + + PropertyContainer::iterator iter = property_container.begin(); + std::advance(iter, last_property_index); + + std::for_each(iter, property_container.end(), - [lightPayload, &arrayEncoder, &error, &num_encoded_properties](Property * p) + [lightPayload, &arrayEncoder, &error, &num_encoded_properties, &num_checked_properties](Property * p) { if(error == CborNoError) { @@ -59,8 +69,12 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * else return; } + num_checked_properties++; } }); + + last_property_index += num_checked_properties; + if ((CborNoError != error) && (CborErrorOutOfMemory != error)) return error; From f35fe82f986f65e0274c42bd2dd52606cefe4d65 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 15 Dec 2021 15:07:57 +0100 Subject: [PATCH 239/780] Move last_property index out of CBOREncoder::encode function and fix unit tests --- extras/test/src/util/CBORTestUtil.cpp | 3 ++- src/ArduinoIoTCloudLPWAN.cpp | 3 ++- src/ArduinoIoTCloudTCP.cpp | 10 ++++++---- src/ArduinoIoTCloudTCP.h | 2 +- src/cbor/CBOREncoder.cpp | 11 +++++------ src/cbor/CBOREncoder.h | 2 +- 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/extras/test/src/util/CBORTestUtil.cpp b/extras/test/src/util/CBORTestUtil.cpp index 021ffc6b7..33182f9cd 100644 --- a/extras/test/src/util/CBORTestUtil.cpp +++ b/extras/test/src/util/CBORTestUtil.cpp @@ -27,9 +27,10 @@ namespace cbor std::vector encode(PropertyContainer & property_container, bool lightPayload) { int bytes_encoded = 0; + unsigned int starting_property_index = 0; uint8_t buf[200] = {0}; - if (CBOREncoder::encode(property_container, buf, 200, bytes_encoded, lightPayload) == CborNoError) + if (CBOREncoder::encode(property_container, buf, 200, bytes_encoded, starting_property_index, lightPayload) == CborNoError) return std::vector(buf, buf + bytes_encoded); else return std::vector(); diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 29458f21a..b30fbfa83 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -149,8 +149,9 @@ void ArduinoIoTCloudLPWAN::sendPropertiesToCloud() { int bytes_encoded = 0; uint8_t data[CBOR_LORA_MSG_MAX_SIZE]; + static unsigned int last_checked_property_index = 0; - if (CBOREncoder::encode(_property_container, data, sizeof(data), bytes_encoded, true) == CborNoError) + if (CBOREncoder::encode(_property_container, data, sizeof(data), bytes_encoded, last_checked_property_index, true) == CborNoError) if (bytes_encoded > 0) writeProperties(data, bytes_encoded); } diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 8bd632ad8..a0c94ef7a 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -576,12 +576,12 @@ void ArduinoIoTCloudTCP::handleMessage(int length) } } -void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(PropertyContainer & property_container) +void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(PropertyContainer & property_container, unsigned int & current_property_index) { int bytes_encoded = 0; uint8_t data[MQTT_TRANSMIT_BUFFER_SIZE]; - if (CBOREncoder::encode(property_container, data, sizeof(data), bytes_encoded, false) == CborNoError) + if (CBOREncoder::encode(property_container, data, sizeof(data), bytes_encoded, current_property_index, false) == CborNoError) if (bytes_encoded > 0) { /* If properties have been encoded store them in the back-up buffer @@ -596,13 +596,15 @@ void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(PropertyContainer & proper void ArduinoIoTCloudTCP::sendPropertiesToCloud() { - sendPropertyContainerToCloud(_property_container); + static unsigned int last_checked_property_index = 0; + sendPropertyContainerToCloud(_property_container, last_checked_property_index); } #if OTA_ENABLED void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() { PropertyContainer ota_property_container; + unsigned int last_ota_property_index = 0; std::list const ota_property_list {"OTA_CAP", "OTA_ERROR", "OTA_SHA256", "OTA_URL", "OTA_REQ"}; std::for_each(ota_property_list.cbegin(), @@ -615,7 +617,7 @@ void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() } ); - sendPropertyContainerToCloud(ota_property_container); + sendPropertyContainerToCloud(ota_property_container, last_ota_property_index); } #endif diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index c36fae4d8..3e1ff13af 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -164,7 +164,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass static void onMessage(int length); void handleMessage(int length); - void sendPropertyContainerToCloud(PropertyContainer & property_container); + void sendPropertyContainerToCloud(PropertyContainer & property_container, unsigned int & current_property_index); void sendPropertiesToCloud(); void requestLastValue(); int write(String const topic, byte const data[], int const length); diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index 48d783de0..925043956 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -32,7 +32,7 @@ * PUBLIC MEMBER FUNCTIONS ******************************************************************************/ -CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * data, size_t const size, int & bytes_encoded, bool lightPayload) +CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * data, size_t const size, int & bytes_encoded, unsigned int & current_property_index, bool lightPayload) { CborEncoder encoder, arrayEncoder; @@ -47,13 +47,12 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * CborError error = CborNoError; int num_encoded_properties = 0; int num_checked_properties = 0; - static unsigned int last_property_index = 0; - if(last_property_index >= property_container.size()) - last_property_index = 0; + if(current_property_index >= property_container.size()) + current_property_index = 0; PropertyContainer::iterator iter = property_container.begin(); - std::advance(iter, last_property_index); + std::advance(iter, current_property_index); std::for_each(iter, property_container.end(), @@ -73,7 +72,7 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * } }); - last_property_index += num_checked_properties; + current_property_index += num_checked_properties; if ((CborNoError != error) && (CborErrorOutOfMemory != error)) diff --git a/src/cbor/CBOREncoder.h b/src/cbor/CBOREncoder.h index 2370a7b50..00b48b4ea 100644 --- a/src/cbor/CBOREncoder.h +++ b/src/cbor/CBOREncoder.h @@ -45,7 +45,7 @@ class CBOREncoder /* encode return > 0 if a property has changed and encodes the changed properties in CBOR format into the provided buffer */ /* if lightPayload is true the integer identifier of the property will be encoded in the message instead of the property name in order to reduce the size of the message payload*/ - static CborError encode(PropertyContainer & property_container, uint8_t * data, size_t const size, int & bytes_encoded, bool lightPayload = false); + static CborError encode(PropertyContainer & property_container, uint8_t * data, size_t const size, int & bytes_encoded, unsigned int & current_property_index, bool lightPayload = false); private: From 5c416f26bd54a0db10089587adf4974da401ab6e Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 16 Dec 2021 11:07:52 +0100 Subject: [PATCH 240/780] Add bool flag and functions to handle properties appended to a CBOR message that may be discarded --- src/property/Property.cpp | 12 ++++++++++++ src/property/Property.h | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index a9b703987..9312b5eed 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -39,6 +39,7 @@ Property::Property() , _update_policy{UpdatePolicy::OnChange} , _has_been_updated_once{false} , _has_been_modified_in_callback{false} +, _has_been_appended_but_not_sended{false} , _last_updated_millis{0} , _update_interval_millis{0} , _last_local_change_timestamp{0} @@ -106,6 +107,10 @@ bool Property::shouldBeUpdated() { return true; } + if (_has_been_appended_but_not_sended) { + return true; + } + if (_has_been_modified_in_callback) { return true; } @@ -126,6 +131,13 @@ void Property::requestUpdate() _update_requested = true; } +void Property::appendCompleted() +{ + if (_has_been_appended_but_not_sended) { + _has_been_appended_but_not_sended = false; + } +} + void Property::execCallbackOnChange() { if (_update_callback_func != nullptr) { _update_callback_func(); diff --git a/src/property/Property.h b/src/property/Property.h index 1ead6f265..46288a44d 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -174,6 +174,7 @@ class Property void setTimestamp(unsigned long const timestamp); bool shouldBeUpdated(); void requestUpdate(); + void appendCompleted(); void execCallbackOnChange(); void execCallbackOnSync(); void setLastCloudChangeTimestamp(unsigned long cloudChangeTime); @@ -229,7 +230,8 @@ class Property UpdatePolicy _update_policy; bool _has_been_updated_once, - _has_been_modified_in_callback; + _has_been_modified_in_callback, + _has_been_appended_but_not_sended; /* Variables used for UpdatePolicy::TimeInterval */ unsigned long _last_updated_millis, _update_interval_millis; From 803bcde34ef1a70a65a45a27e79d0fc99afca156 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 16 Dec 2021 11:09:42 +0100 Subject: [PATCH 241/780] Instead of simply discard the message containing a splitted multivalue property, do not advance the property index and mark discarded properties has appended but not sended. Compute the exact number of properties that would fit the CBOR buffer and retry send next loop. When no error occurs restore property limit to NO_LIMIT and advance property index. --- src/cbor/CBOREncoder.cpp | 33 ++++++++++++++++++++++++++++----- src/property/Property.cpp | 1 + 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index 925043956..1906d5747 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -47,6 +47,7 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * CborError error = CborNoError; int num_encoded_properties = 0; int num_checked_properties = 0; + static int encoded_properties_message_limit = -1; if(current_property_index >= property_container.size()) current_property_index = 0; @@ -58,7 +59,7 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * property_container.end(), [lightPayload, &arrayEncoder, &error, &num_encoded_properties, &num_checked_properties](Property * p) { - if(error == CborNoError) + if((error == CborNoError) && ((num_encoded_properties < encoded_properties_message_limit) || (encoded_properties_message_limit == -1))) { if (p->shouldBeUpdated() && p->isReadableByCloud()) { @@ -72,14 +73,36 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * } }); - current_property_index += num_checked_properties; - - if ((CborNoError != error) && - (CborErrorOutOfMemory != error)) + if ((CborNoError != error) && (CborErrorOutOfMemory != error)) + { + /* Trim the number of properties to be included in the next message to avoid multivalue property split */ + encoded_properties_message_limit = num_encoded_properties; return error; + } + + /* Restore property message limit to NO_LIMIT */ + encoded_properties_message_limit = -1; CHECK_CBOR(cbor_encoder_close_container(&encoder, &arrayEncoder)); + /* The append process has been successful, so we don't need to terty to send this properties set. Cleanup _has_been_appended_but_not_sended flag */ + iter = property_container.begin(); + std::advance(iter, current_property_index); + int num_appended_properties = 0; + std::for_each(iter, + property_container.end(), + [&num_appended_properties, &num_checked_properties](Property * p) + { + if (num_appended_properties < num_checked_properties) + { + p->appendCompleted(); + num_appended_properties++; + } + }); + + /* Advance property index for the nex message */ + current_property_index += num_checked_properties; + if (num_encoded_properties > 0) bytes_encoded = cbor_encoder_get_buffer_size(&encoder, data); else diff --git a/src/property/Property.cpp b/src/property/Property.cpp index 9312b5eed..d630c7dde 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -161,6 +161,7 @@ CborError Property::append(CborEncoder *encoder, bool lightPayload) { _has_been_updated_once = true; _has_been_modified_in_callback = false; _update_requested = false; + _has_been_appended_but_not_sended = true; _last_updated_millis = millis(); return CborNoError; } From bb33feb3cf223ebd29153c0f07516fdd9d02a390 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 16 Dec 2021 12:59:32 +0100 Subject: [PATCH 242/780] In case of cbor_encoder_close_container failure, reduce the number of properties to be appended by one and retry send --- src/cbor/CBOREncoder.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index 1906d5747..69c583cc3 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -80,11 +80,17 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * return error; } + error = cbor_encoder_close_container(&encoder, &arrayEncoder); + if (CborNoError != error) + { + /* Trim the number of properties to be included in the next message to avoid error closing container */ + encoded_properties_message_limit = num_encoded_properties - 1; + return error; + } + /* Restore property message limit to NO_LIMIT */ encoded_properties_message_limit = -1; - CHECK_CBOR(cbor_encoder_close_container(&encoder, &arrayEncoder)); - /* The append process has been successful, so we don't need to terty to send this properties set. Cleanup _has_been_appended_but_not_sended flag */ iter = property_container.begin(); std::advance(iter, current_property_index); From 591224ead6bbdc202ca568846c2d62ab4e2b5400 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 16 Dec 2021 14:48:33 +0100 Subject: [PATCH 243/780] Make more explicit and clear that properties are echoed back to the cloud even if not changed in callback --- src/property/Property.cpp | 13 ++++++++++++- src/property/Property.h | 3 +++ src/property/PropertyContainer.cpp | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index d630c7dde..243c2ab47 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -49,6 +49,7 @@ Property::Property() , _lightPayload{false} , _update_requested{false} , _encode_timestamp{false} +, _echo_requested{false} , _timestamp{0} { @@ -115,6 +116,10 @@ bool Property::shouldBeUpdated() { return true; } + if (_echo_requested) { + return true; + } + if (_update_policy == UpdatePolicy::OnChange) { return (isDifferentFromCloud() && ((millis() - _last_updated_millis) >= (_min_time_between_updates_millis))); } else if (_update_policy == UpdatePolicy::TimeInterval) { @@ -131,6 +136,11 @@ void Property::requestUpdate() _update_requested = true; } +void Property::provideEcho() +{ + _echo_requested = true; +} + void Property::appendCompleted() { if (_has_been_appended_but_not_sended) { @@ -142,7 +152,7 @@ void Property::execCallbackOnChange() { if (_update_callback_func != nullptr) { _update_callback_func(); } - if (!isDifferentFromCloud()) { + if (isDifferentFromCloud()) { _has_been_modified_in_callback = true; } } @@ -161,6 +171,7 @@ CborError Property::append(CborEncoder *encoder, bool lightPayload) { _has_been_updated_once = true; _has_been_modified_in_callback = false; _update_requested = false; + _echo_requested = false; _has_been_appended_but_not_sended = true; _last_updated_millis = millis(); return CborNoError; diff --git a/src/property/Property.h b/src/property/Property.h index 46288a44d..bc7aa665a 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -175,6 +175,7 @@ class Property bool shouldBeUpdated(); void requestUpdate(); void appendCompleted(); + void provideEcho(); void execCallbackOnChange(); void execCallbackOnSync(); void setLastCloudChangeTimestamp(unsigned long cloudChangeTime); @@ -248,6 +249,8 @@ class Property bool _update_requested; /* Indicates whether the timestamp shall be encoded in the property or not */ bool _encode_timestamp; + /* Indicates if the property shall be echoed back to the cloud even if unchanged */ + bool _echo_requested; unsigned long _timestamp; }; diff --git a/src/property/PropertyContainer.cpp b/src/property/PropertyContainer.cpp index 7a699ee97..833250f02 100644 --- a/src/property/PropertyContainer.cpp +++ b/src/property/PropertyContainer.cpp @@ -123,6 +123,7 @@ void updateProperty(PropertyContainer & prop_cont, String propertyName, unsigned } else { property->fromCloudToLocal(); property->execCallbackOnChange(); + property->provideEcho(); } } } From 750860719c33cda34b777b10785905f0432bdefe Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 16 Dec 2021 16:16:40 +0100 Subject: [PATCH 244/780] Use a constant value for CBOR_ENCODER_NO_PROPERTIES_LIMIT --- src/cbor/CBOREncoder.cpp | 8 ++++---- src/cbor/CBOREncoder.h | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index 69c583cc3..9bcf5ed8a 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -47,7 +47,7 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * CborError error = CborNoError; int num_encoded_properties = 0; int num_checked_properties = 0; - static int encoded_properties_message_limit = -1; + static int encoded_properties_message_limit = CBOR_ENCODER_NO_PROPERTIES_LIMIT; if(current_property_index >= property_container.size()) current_property_index = 0; @@ -59,7 +59,7 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * property_container.end(), [lightPayload, &arrayEncoder, &error, &num_encoded_properties, &num_checked_properties](Property * p) { - if((error == CborNoError) && ((num_encoded_properties < encoded_properties_message_limit) || (encoded_properties_message_limit == -1))) + if((error == CborNoError) && ((num_encoded_properties < encoded_properties_message_limit) || (encoded_properties_message_limit == CBOR_ENCODER_NO_PROPERTIES_LIMIT))) { if (p->shouldBeUpdated() && p->isReadableByCloud()) { @@ -88,8 +88,8 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * return error; } - /* Restore property message limit to NO_LIMIT */ - encoded_properties_message_limit = -1; + /* Restore property message limit to CBOR_ENCODER_NO_PROPERTIES_LIMIT */ + encoded_properties_message_limit = CBOR_ENCODER_NO_PROPERTIES_LIMIT; /* The append process has been successful, so we don't need to terty to send this properties set. Cleanup _has_been_appended_but_not_sended flag */ iter = property_container.begin(); diff --git a/src/cbor/CBOREncoder.h b/src/cbor/CBOREncoder.h index 00b48b4ea..694642c7e 100644 --- a/src/cbor/CBOREncoder.h +++ b/src/cbor/CBOREncoder.h @@ -34,6 +34,12 @@ #include "../property/PropertyContainer.h" +/****************************************************************************** + * CONSTANTS + ******************************************************************************/ + +static int const CBOR_ENCODER_NO_PROPERTIES_LIMIT = -1; + /****************************************************************************** * CLASS DECLARATION ******************************************************************************/ From 537e7229743c94e5daa862cd052ce4ba1a1441cf Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 16 Dec 2021 16:24:44 +0100 Subject: [PATCH 245/780] Use bool variables to make if condition more readable --- src/cbor/CBOREncoder.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index 9bcf5ed8a..a724068e4 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -59,7 +59,9 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * property_container.end(), [lightPayload, &arrayEncoder, &error, &num_encoded_properties, &num_checked_properties](Property * p) { - if((error == CborNoError) && ((num_encoded_properties < encoded_properties_message_limit) || (encoded_properties_message_limit == CBOR_ENCODER_NO_PROPERTIES_LIMIT))) + bool maximum_number_of_properties_reached = (num_encoded_properties >= encoded_properties_message_limit) && (encoded_properties_message_limit != CBOR_ENCODER_NO_PROPERTIES_LIMIT); + bool cbor_encoder_error = (error != CborNoError); + if((!cbor_encoder_error) && (!maximum_number_of_properties_reached)) { if (p->shouldBeUpdated() && p->isReadableByCloud()) { From cc3aa38f30dde385a4bb874850d3c30cbdeac724 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 17 Dec 2021 08:21:53 +0100 Subject: [PATCH 246/780] Use for loop instead of for_each to be able to break loop when condition is met --- src/cbor/CBOREncoder.cpp | 56 +++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index a724068e4..7530347b3 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -55,25 +55,23 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * PropertyContainer::iterator iter = property_container.begin(); std::advance(iter, current_property_index); - std::for_each(iter, - property_container.end(), - [lightPayload, &arrayEncoder, &error, &num_encoded_properties, &num_checked_properties](Property * p) - { - bool maximum_number_of_properties_reached = (num_encoded_properties >= encoded_properties_message_limit) && (encoded_properties_message_limit != CBOR_ENCODER_NO_PROPERTIES_LIMIT); - bool cbor_encoder_error = (error != CborNoError); - if((!cbor_encoder_error) && (!maximum_number_of_properties_reached)) - { - if (p->shouldBeUpdated() && p->isReadableByCloud()) - { - error = p->append(&arrayEncoder, lightPayload); - if(error == CborNoError) - num_encoded_properties++; - else - return; - } - num_checked_properties++; - } - }); + for(; iter != property_container.end(); iter++) + { + Property * p = * iter; + bool maximum_number_of_properties_reached = (num_encoded_properties >= encoded_properties_message_limit) && (encoded_properties_message_limit != -1); + bool cbor_encoder_error = (error != CborNoError); + + if (maximum_number_of_properties_reached || cbor_encoder_error) + break; + + if (p->shouldBeUpdated() && p->isReadableByCloud()) + { + error = p->append(&arrayEncoder, lightPayload); + if(error == CborNoError) + num_encoded_properties++; + } + num_checked_properties++; + } if ((CborNoError != error) && (CborErrorOutOfMemory != error)) { @@ -97,16 +95,16 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * iter = property_container.begin(); std::advance(iter, current_property_index); int num_appended_properties = 0; - std::for_each(iter, - property_container.end(), - [&num_appended_properties, &num_checked_properties](Property * p) - { - if (num_appended_properties < num_checked_properties) - { - p->appendCompleted(); - num_appended_properties++; - } - }); + + for(; iter != property_container.end(); iter++) + { + Property * p = * iter; + if (num_appended_properties >= num_checked_properties) + break; + + p->appendCompleted(); + num_appended_properties++; + } /* Advance property index for the nex message */ current_property_index += num_checked_properties; From 2a8c87926d655539156c8a87cf50e1e0fc4e9e44 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 21 Dec 2021 11:18:48 +0100 Subject: [PATCH 247/780] Change test buffer size in order to match real application buffer size --- extras/test/src/util/CBORTestUtil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/test/src/util/CBORTestUtil.cpp b/extras/test/src/util/CBORTestUtil.cpp index 33182f9cd..ea010413e 100644 --- a/extras/test/src/util/CBORTestUtil.cpp +++ b/extras/test/src/util/CBORTestUtil.cpp @@ -28,9 +28,9 @@ std::vector encode(PropertyContainer & property_container, bool lightPa { int bytes_encoded = 0; unsigned int starting_property_index = 0; - uint8_t buf[200] = {0}; + uint8_t buf[256] = {0}; - if (CBOREncoder::encode(property_container, buf, 200, bytes_encoded, starting_property_index, lightPayload) == CborNoError) + if (CBOREncoder::encode(property_container, buf, 256, bytes_encoded, starting_property_index, lightPayload) == CborNoError) return std::vector(buf, buf + bytes_encoded); else return std::vector(); From 4b991e3e29d5ec80a4859bc78ef7bc0eddb2f19c Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 21 Dec 2021 11:20:33 +0100 Subject: [PATCH 248/780] Change test case in order to match the new buffer size --- extras/test/src/test_encode.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/extras/test/src/test_encode.cpp b/extras/test/src/test_encode.cpp index f0667166b..e3bdcdf4e 100644 --- a/extras/test/src/test_encode.cpp +++ b/extras/test/src/test_encode.cpp @@ -427,26 +427,19 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode-1]" * once they are encoded in subsequent calls to CBOREncoder::encode. */ - /* [{0: "str_0", 3: "This string is 30 bytes long."}, {0: "str_1", 3: "This string is 30 bytes long."}, {0: "str_2", 3: "This string is 30 bytes long."}, {0: "str_3", 3: "This string is 30 bytes long."}] - * = 9F A2 00 65 73 74 72 5F 30 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 31 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 32 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 33 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E FF + /* [{0: "str_0", 3: "This string is 30 bytes long."}, {0: "str_1", 3: "This string is 30 bytes long."}, {0: "str_2", 3: "This string is 30 bytes long."}, {0: "str_3", 3: "This string is 30 bytes long."}, {0: "str_4", 3: "This string is 30 bytes long."}, {0: "str_5", 3: "This string is 30 bytes long."}] + * = 9F A2 00 65 73 74 72 5F 30 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 31 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 32 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 33 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 34 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 35 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E FF */ - std::vector const expected_1 = {0x9F, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x30, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x31, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x32, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x33, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xFF}; + std::vector const expected_1 = {0x9F, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x30, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x31, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x32, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x33, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x34, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x35, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xFF}; std::vector const actual_1 = cbor::encode(property_container); REQUIRE(actual_1 == expected_1); - /* [{0: "str_4", 3: "This string is 30 bytes long."}, {0: "str_5", 3: "This string is 30 bytes long."}, {0: "str_6", 3: "This string is 30 bytes long."}, {0: "str_7", 3: "This string is 30 bytes long."}] - * = 9F A2 00 65 73 74 72 5F 34 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 35 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 36 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 37 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E FF + /* [{0: "str_6", 3: "This string is 30 bytes long."}, {0: "str_7", 3: "This string is 30 bytes long."}, {0: "str_8", 3: "This string is 30 bytes long."}, {0: "str_9", 3: "This string is 30 bytes long."}] + * = 9F A2 00 65 73 74 72 5F 36 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 37 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 38 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 39 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E FF */ - std::vector const expected_2 = {0x9F, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x34, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x35, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x36, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x37, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xFF}; + std::vector const expected_2 = {0x9F, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x36, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x37, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x38, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x39, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xFF}; std::vector const actual_2 = cbor::encode(property_container); REQUIRE(actual_2 == expected_2); - - /* [{0: "str_8", 3: "This string is 30 bytes long."}, {0: "str_9", 3: "This string is 30 bytes long."}] - * = 9F A2 00 65 73 74 72 5F 38 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 39 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E FF - */ - std::vector const expected_3 = {0x9F, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x38, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x39, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xFF}; - std::vector const actual_3 = cbor::encode(property_container); - REQUIRE(actual_3 == expected_3); } /************************************************************************************/ From f6af6a7fea939acac5df9f9ee1d15cfe23e46617 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 21 Dec 2021 11:21:47 +0100 Subject: [PATCH 249/780] Add test case to check multivalue properties split --- extras/test/src/test_encode.cpp | 49 +++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/extras/test/src/test_encode.cpp b/extras/test/src/test_encode.cpp index e3bdcdf4e..f37a6ee10 100644 --- a/extras/test/src/test_encode.cpp +++ b/extras/test/src/test_encode.cpp @@ -443,4 +443,53 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode-1]" } /************************************************************************************/ + + WHEN("The size of the encoded properties is exceeding the CBOR buffer size and includes a multivalue property") + { + PropertyContainer property_container; + + CloudInt int_0; int_0 = 1000000; + CloudInt int_1; int_1 = 1000001; + CloudInt int_2; int_2 = 1000002; + CloudInt int_3; int_3 = 1000003; + CloudInt int_4; int_4 = 1000004; + CloudInt int_5; int_5 = 1000005; + CloudInt int_6; int_6 = 1000006; + CloudInt int_7; int_7 = 1000007; + CloudInt int_8; int_8 = 1000008; + CloudInt int_9; int_9 = 1000009; + CloudInt int_A; int_A = 1000010; + CloudSchedule schedule = CloudSchedule(1633305600, 1633651200, 600, 1140850708); + + addPropertyToContainer(property_container, int_0, "int_value_0", Permission::ReadWrite); + addPropertyToContainer(property_container, int_1, "int_value_1", Permission::ReadWrite); + addPropertyToContainer(property_container, int_2, "int_value_2", Permission::ReadWrite); + addPropertyToContainer(property_container, int_3, "int_value_3", Permission::ReadWrite); + addPropertyToContainer(property_container, int_4, "int_value_4", Permission::ReadWrite); + addPropertyToContainer(property_container, int_5, "int_value_5", Permission::ReadWrite); + addPropertyToContainer(property_container, int_6, "int_value_6", Permission::ReadWrite); + addPropertyToContainer(property_container, int_7, "int_value_7", Permission::ReadWrite); + addPropertyToContainer(property_container, int_8, "int_value_8", Permission::ReadWrite); + addPropertyToContainer(property_container, int_9, "int_value_9", Permission::ReadWrite); + addPropertyToContainer(property_container, int_A, "int_value_A", Permission::ReadWrite); + addPropertyToContainer(property_container, schedule, "schedule", Permission::ReadWrite); + + /* Due to the size if the encoded properties exceeding 256 bytes if encoded all at + * once they are encoded in subsequent calls to CBOREncoder::encode. + */ + + /* [{0: "int_value_0", 2: 1000000}, {0: "int_value_1", 2: 1000001}, {0: "int_value_2", 2: 1000002}, {0: "int_value_3", 2: 1000003}, {0: "int_value_4", 2: 1000004}, {0: "int_value_5", 2: 1000005}, {0: "int_value_6", 2: 1000006}, {0: "int_value_7", 2: 1000007}, {0: "int_value_8", 2: 1000008}, {0: "int_value_9", 2: 1000009}, {0: "int_value_A", 2: 1000010}] + * = 9F A2 00 6B 69 6E 74 5F 76 61 6C 75 65 5F 30 02 1A 00 0F 42 40 A2 00 6B 69 6E 74 5F 76 61 6C 75 65 5F 31 02 1A 00 0F 42 41 A2 00 6B 69 6E 74 5F 76 61 6C 75 65 5F 32 02 1A 00 0F 42 42 A2 00 6B 69 6E 74 5F 76 61 6C 75 65 5F 33 02 1A 00 0F 42 43 A2 00 6B 69 6E 74 5F 76 61 6C 75 65 5F 34 02 1A 00 0F 42 44 A2 00 6B 69 6E 74 5F 76 61 6C 75 65 5F 35 02 1A 00 0F 42 45 A2 00 6B 69 6E 74 5F 76 61 6C 75 65 5F 36 02 1A 00 0F 42 46 A2 00 6B 69 6E 74 5F 76 61 6C 75 65 5F 37 02 1A 00 0F 42 47 A2 00 6B 69 6E 74 5F 76 61 6C 75 65 5F 38 02 1A 00 0F 42 48 A2 00 6B 69 6E 74 5F 76 61 6C 75 65 5F 39 02 1A 00 0F 42 49 A2 00 6B 69 6E 74 5F 76 61 6C 75 65 5F 41 02 1A 00 0F 42 4A FF + */ + std::vector const expected_1 = {0x9F, 0xA2, 0x00, 0x6B, 0x69, 0x6E, 0x74, 0x5F, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x30, 0x02, 0x1A, 0x00, 0x0F, 0x42, 0x40, 0xA2, 0x00, 0x6B, 0x69, 0x6E, 0x74, 0x5F, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x31, 0x02, 0x1A, 0x00, 0x0F, 0x42, 0x41, 0xA2, 0x00, 0x6B, 0x69, 0x6E, 0x74, 0x5F, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x32, 0x02, 0x1A, 0x00, 0x0F, 0x42, 0x42, 0xA2, 0x00, 0x6B, 0x69, 0x6E, 0x74, 0x5F, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x33, 0x02, 0x1A, 0x00, 0x0F, 0x42, 0x43, 0xA2, 0x00, 0x6B, 0x69, 0x6E, 0x74, 0x5F, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x34, 0x02, 0x1A, 0x00, 0x0F, 0x42, 0x44, 0xA2, 0x00, 0x6B, 0x69, 0x6E, 0x74, 0x5F, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x35, 0x02, 0x1A, 0x00, 0x0F, 0x42, 0x45, 0xA2, 0x00, 0x6B, 0x69, 0x6E, 0x74, 0x5F, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x36, 0x02, 0x1A, 0x00, 0x0F, 0x42, 0x46, 0xA2, 0x00, 0x6B, 0x69, 0x6E, 0x74, 0x5F, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x37, 0x02, 0x1A, 0x00, 0x0F, 0x42, 0x47, 0xA2, 0x00, 0x6B, 0x69, 0x6E, 0x74, 0x5F, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x38, 0x02, 0x1A, 0x00, 0x0F, 0x42, 0x48, 0xA2, 0x00, 0x6B, 0x69, 0x6E, 0x74, 0x5F, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x39, 0x02, 0x1A, 0x00, 0x0F, 0x42, 0x49, 0xA2, 0x00, 0x6B, 0x69, 0x6E, 0x74, 0x5F, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x41, 0x02, 0x1A, 0x00, 0x0F, 0x42, 0x4A, 0xFF}; + std::vector const actual_1 = cbor::encode(property_container); + REQUIRE(actual_1 == expected_1); + + /* [{0: "schedule:frm", 2: 1633305600}, {0: "schedule:to", 2: 1633651200}, {0: "schedule:len", 2: 600}, {0: "schedule:msk", 2: 1140850708}] + * = 9F A2 00 6C 73 63 68 65 64 75 6C 65 3A 66 72 6D 02 1A 61 5A 44 00 A2 00 6B 73 63 68 65 64 75 6C 65 3A 74 6F 02 1A 61 5F 8A 00 A2 00 6C 73 63 68 65 64 75 6C 65 3A 6C 65 6E 02 19 02 58 A2 00 6C 73 63 68 65 64 75 6C 65 3A 6D 73 6B 02 1A 44 00 00 14 FF + */ + std::vector const expected_2 = {0x9F, 0xA2, 0x00, 0x6C, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6C, 0x65, 0x3A, 0x66, 0x72, 0x6D, 0x02, 0x1A, 0x61, 0x5A, 0x44, 0x00, 0xA2, 0x00, 0x6B, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6C, 0x65, 0x3A, 0x74, 0x6F, 0x02, 0x1A, 0x61, 0x5F, 0x8A, 0x00, 0xA2, 0x00, 0x6C, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6C, 0x65, 0x3A, 0x6C, 0x65, 0x6E, 0x02, 0x19, 0x02, 0x58, 0xA2, 0x00, 0x6C, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6C, 0x65, 0x3A, 0x6D, 0x73, 0x6B, 0x02, 0x1A, 0x44, 0x00, 0x00, 0x14, 0xFF}; + std::vector const actual_2 = cbor::encode(property_container); + REQUIRE(actual_2 == expected_2); + } } From 61033be33d1faf65b391df39f2f762a4738bac1d Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 21 Dec 2021 12:44:22 +0100 Subject: [PATCH 250/780] Use FSM to encode CBOR messages --- src/cbor/CBOREncoder.cpp | 186 +++++++++++++++++++++++++++++---------- src/cbor/CBOREncoder.h | 47 ++++++++-- 2 files changed, 180 insertions(+), 53 deletions(-) diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index 7530347b3..45ba82345 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -34,85 +34,179 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * data, size_t const size, int & bytes_encoded, unsigned int & current_property_index, bool lightPayload) { - CborEncoder encoder, arrayEncoder; + EncoderState current_state = EncoderState::InitPropertyEncoder, + next_state = EncoderState::InitPropertyEncoder; + + PropertyContainerEncoder propertyEncoder(property_container, current_property_index); + + while (current_state != EncoderState::SendMessage) { + + switch (current_state) { + case EncoderState::InitPropertyEncoder : next_state = handle_InitPropertyEncoder(propertyEncoder); break; + case EncoderState::OpenCBORContainer : next_state = handle_OpenCBORContainer(propertyEncoder, data, size); break; + case EncoderState::TryAppend : next_state = handle_TryAppend(propertyEncoder, lightPayload); break; + case EncoderState::OutOfMemory : next_state = handle_OutOfMemory(propertyEncoder); break; + case EncoderState::SkipProperty : next_state = handle_SkipProperty(propertyEncoder); break; + case EncoderState::TrimAppend : next_state = handle_TrimAppend(propertyEncoder); break; + case EncoderState::CloseCBORContainer : next_state = handle_CloseCBORContainer(propertyEncoder); break; + case EncoderState::TrimClose : next_state = handle_TrimClose(propertyEncoder); break; + case EncoderState::FinishAppend : next_state = handle_FinishAppend(propertyEncoder); break; + case EncoderState::AdvancePropertyContainer : next_state = handle_AdvancePropertyContainer(propertyEncoder); break; + case EncoderState::SendMessage : /* Nothing to do */ break; + case EncoderState::Error : return CborErrorInternalError; break; + } + + current_state = next_state; + } - cbor_encoder_init(&encoder, data, size, 0); + if (propertyEncoder.encoded_property_count > 0) + bytes_encoded = cbor_encoder_get_buffer_size(&propertyEncoder.encoder, data); + else + bytes_encoded = 0; - CHECK_CBOR(cbor_encoder_create_array(&encoder, &arrayEncoder, CborIndefiniteLength)); + return CborNoError; +} - /* Check if backing storage and cloud has diverged - * time interval may be elapsed or property may be changed +/****************************************************************************** + PRIVATE MEMBER FUNCTIONS + ******************************************************************************/ + +CBOREncoder::EncoderState CBOREncoder::handle_InitPropertyEncoder(PropertyContainerEncoder & propertyEncoder) +{ + propertyEncoder.encoded_property_count = 0; + propertyEncoder.checked_property_count = 0; + propertyEncoder.encoded_property_limit = 0; + propertyEncoder.property_limit_active = false; + return EncoderState::OpenCBORContainer; +} + +CBOREncoder::EncoderState CBOREncoder::handle_OpenCBORContainer(PropertyContainerEncoder & propertyEncoder, uint8_t * data, size_t const size) +{ + propertyEncoder.encoded_property_count = 0; + propertyEncoder.checked_property_count = 0; + cbor_encoder_init(&propertyEncoder.encoder, data, size, 0); + cbor_encoder_create_array(&propertyEncoder.encoder, &propertyEncoder.arrayEncoder, CborIndefiniteLength); + return EncoderState::TryAppend; +} + +CBOREncoder::EncoderState CBOREncoder::handle_TryAppend(PropertyContainerEncoder & propertyEncoder, bool & lightPayload) +{ + /* Check if backing storage and cloud has diverged. Time interval may be elapsed or property may be changed * and if that's the case encode the property into the CBOR. */ CborError error = CborNoError; - int num_encoded_properties = 0; - int num_checked_properties = 0; - static int encoded_properties_message_limit = CBOR_ENCODER_NO_PROPERTIES_LIMIT; - - if(current_property_index >= property_container.size()) - current_property_index = 0; - - PropertyContainer::iterator iter = property_container.begin(); - std::advance(iter, current_property_index); + PropertyContainer::iterator iter = propertyEncoder.property_container.begin(); + std::advance(iter, propertyEncoder.current_property_index); - for(; iter != property_container.end(); iter++) + for(; iter != propertyEncoder.property_container.end(); iter++) { Property * p = * iter; - bool maximum_number_of_properties_reached = (num_encoded_properties >= encoded_properties_message_limit) && (encoded_properties_message_limit != -1); - bool cbor_encoder_error = (error != CborNoError); - - if (maximum_number_of_properties_reached || cbor_encoder_error) - break; if (p->shouldBeUpdated() && p->isReadableByCloud()) { - error = p->append(&arrayEncoder, lightPayload); + error = p->append(&propertyEncoder.arrayEncoder, lightPayload); if(error == CborNoError) - num_encoded_properties++; + propertyEncoder.encoded_property_count++; } - num_checked_properties++; - } + if(error == CborNoError) + propertyEncoder.checked_property_count++; - if ((CborNoError != error) && (CborErrorOutOfMemory != error)) - { - /* Trim the number of properties to be included in the next message to avoid multivalue property split */ - encoded_properties_message_limit = num_encoded_properties; - return error; + bool const maximum_number_of_properties_reached = (propertyEncoder.encoded_property_count >= propertyEncoder.encoded_property_limit) && (propertyEncoder.property_limit_active == true); + bool const cbor_encoder_error = (error != CborNoError); + + if (maximum_number_of_properties_reached || cbor_encoder_error) + break; } - error = cbor_encoder_close_container(&encoder, &arrayEncoder); + if (CborErrorOutOfMemory == error) + return EncoderState::OutOfMemory; + else if (CborNoError == error) + return EncoderState::CloseCBORContainer; + else if (CborErrorSplitItems == error) + return EncoderState::TrimAppend; + else + return EncoderState::Error; +} + +CBOREncoder::EncoderState CBOREncoder::handle_OutOfMemory(PropertyContainerEncoder & propertyEncoder) +{ + if(propertyEncoder.encoded_property_count > 0) + return EncoderState::CloseCBORContainer; + else + return EncoderState::SkipProperty; +} + +CBOREncoder::EncoderState CBOREncoder::handle_SkipProperty(PropertyContainerEncoder & propertyEncoder) +{ + /* Better to skip this property otherwise we will stay blocked here. This happens only with a message property + * that not fits into the CBOR buffer + */ + propertyEncoder.current_property_index++; + if(propertyEncoder.current_property_index >= propertyEncoder.property_container.size()) + propertyEncoder.current_property_index = 0; + return EncoderState::Error; +} + +CBOREncoder::EncoderState CBOREncoder::handle_TrimAppend(PropertyContainerEncoder & propertyEncoder) +{ + /* Trim the number of properties to be included in the next message to avoid multivalue property split */ + propertyEncoder.encoded_property_limit = propertyEncoder.encoded_property_count; + propertyEncoder.property_limit_active = true; + if(propertyEncoder.encoded_property_limit > 0) + return EncoderState::OpenCBORContainer; + else + return EncoderState::Error; +} + +CBOREncoder::EncoderState CBOREncoder::handle_CloseCBORContainer(PropertyContainerEncoder & propertyEncoder) +{ + CborError error = cbor_encoder_close_container(&propertyEncoder.encoder, &propertyEncoder.arrayEncoder); if (CborNoError != error) - { - /* Trim the number of properties to be included in the next message to avoid error closing container */ - encoded_properties_message_limit = num_encoded_properties - 1; - return error; - } + return EncoderState::TrimClose; + else + return EncoderState::FinishAppend; +} + +CBOREncoder::EncoderState CBOREncoder::handle_TrimClose(PropertyContainerEncoder & propertyEncoder) +{ + /* Trim the number of properties to be included in the next message to avoid error closing container */ + propertyEncoder.encoded_property_limit = propertyEncoder.encoded_property_count - 1; + propertyEncoder.property_limit_active = true; + if(propertyEncoder.encoded_property_limit > 0) + return EncoderState::OpenCBORContainer; + else + return EncoderState::Error; +} +CBOREncoder::EncoderState CBOREncoder::handle_FinishAppend(PropertyContainerEncoder & propertyEncoder) +{ /* Restore property message limit to CBOR_ENCODER_NO_PROPERTIES_LIMIT */ - encoded_properties_message_limit = CBOR_ENCODER_NO_PROPERTIES_LIMIT; + propertyEncoder.property_limit_active = false; /* The append process has been successful, so we don't need to terty to send this properties set. Cleanup _has_been_appended_but_not_sended flag */ - iter = property_container.begin(); - std::advance(iter, current_property_index); + PropertyContainer::iterator iter = propertyEncoder.property_container.begin(); + std::advance(iter, propertyEncoder.current_property_index); int num_appended_properties = 0; - for(; iter != property_container.end(); iter++) + for(; iter != propertyEncoder.property_container.end(); iter++) { Property * p = * iter; - if (num_appended_properties >= num_checked_properties) + if (num_appended_properties >= propertyEncoder.checked_property_count) break; p->appendCompleted(); num_appended_properties++; } + return EncoderState::AdvancePropertyContainer; +} +CBOREncoder::EncoderState CBOREncoder::handle_AdvancePropertyContainer(PropertyContainerEncoder & propertyEncoder) +{ /* Advance property index for the nex message */ - current_property_index += num_checked_properties; + propertyEncoder.current_property_index += propertyEncoder.checked_property_count; - if (num_encoded_properties > 0) - bytes_encoded = cbor_encoder_get_buffer_size(&encoder, data); - else - bytes_encoded = 0; + if(propertyEncoder.current_property_index >= propertyEncoder.property_container.size()) + propertyEncoder.current_property_index = 0; - return CborNoError; + return EncoderState::SendMessage; } diff --git a/src/cbor/CBOREncoder.h b/src/cbor/CBOREncoder.h index 694642c7e..7acdc3f72 100644 --- a/src/cbor/CBOREncoder.h +++ b/src/cbor/CBOREncoder.h @@ -34,12 +34,6 @@ #include "../property/PropertyContainer.h" -/****************************************************************************** - * CONSTANTS - ******************************************************************************/ - -static int const CBOR_ENCODER_NO_PROPERTIES_LIMIT = -1; - /****************************************************************************** * CLASS DECLARATION ******************************************************************************/ @@ -48,7 +42,6 @@ class CBOREncoder { public: - /* encode return > 0 if a property has changed and encodes the changed properties in CBOR format into the provided buffer */ /* if lightPayload is true the integer identifier of the property will be encoded in the message instead of the property name in order to reduce the size of the message payload*/ static CborError encode(PropertyContainer & property_container, uint8_t * data, size_t const size, int & bytes_encoded, unsigned int & current_property_index, bool lightPayload = false); @@ -58,6 +51,46 @@ class CBOREncoder CBOREncoder() { } CBOREncoder(CborEncoder const &) { } + enum class EncoderState + { + InitPropertyEncoder, + OpenCBORContainer, + TryAppend, + OutOfMemory, + SkipProperty, + TrimAppend, + CloseCBORContainer, + TrimClose, + FinishAppend, + AdvancePropertyContainer, + SendMessage, + Error + }; + + struct PropertyContainerEncoder + { + PropertyContainerEncoder(PropertyContainer & _property_container, unsigned int & _current_property_index): property_container(_property_container), current_property_index(_current_property_index) { } + PropertyContainer & property_container; + unsigned int & current_property_index; + int encoded_property_count; + int checked_property_count; + int encoded_property_limit; + bool property_limit_active; + CborEncoder encoder; + CborEncoder arrayEncoder; + }; + + static EncoderState handle_InitPropertyEncoder(PropertyContainerEncoder & propertyEncoder); + static EncoderState handle_OpenCBORContainer(PropertyContainerEncoder & propertyEncoder, uint8_t * data, size_t const size); + static EncoderState handle_TryAppend(PropertyContainerEncoder & propertyEncoder, bool & lightPayload); + static EncoderState handle_OutOfMemory(PropertyContainerEncoder & propertyEncoder); + static EncoderState handle_SkipProperty(PropertyContainerEncoder & propertyEncoder); + static EncoderState handle_TrimAppend(PropertyContainerEncoder & propertyEncoder); + static EncoderState handle_CloseCBORContainer(PropertyContainerEncoder & propertyEncoder); + static EncoderState handle_TrimClose(PropertyContainerEncoder & propertyEncoder); + static EncoderState handle_FinishAppend(PropertyContainerEncoder & propertyEncoder); + static EncoderState handle_AdvancePropertyContainer(PropertyContainerEncoder & propertyEncoder); + }; #endif /* ARDUINO_CBOR_CBOR_ENCODER_H_ */ From bba3144b61b208abdcf87296e5113d98929920d4 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 21 Dec 2021 14:21:35 +0100 Subject: [PATCH 251/780] Add test for a single property not fitting inside 256 bytes --- extras/test/src/test_encode.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/extras/test/src/test_encode.cpp b/extras/test/src/test_encode.cpp index f37a6ee10..4c702cffc 100644 --- a/extras/test/src/test_encode.cpp +++ b/extras/test/src/test_encode.cpp @@ -492,4 +492,28 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode-1]" std::vector const actual_2 = cbor::encode(property_container); REQUIRE(actual_2 == expected_2); } + + + /************************************************************************************/ + + WHEN("The size of a single encoded properties is exceeding the CBOR buffer size") + { + PropertyContainer property_container; + + CloudString str_0; str_0 = "I am trying to create a single property in such a way it does not fit the CBOR encoder message buffer size (that is 256 bytes) in order to test what happens trying to encode it. It looks easy, but in reality 256 bytes are a lot of characters to fill. Done!"; + + addPropertyToContainer(property_container, str_0, "str_0", Permission::ReadWrite); + + /* Due to the size if the encoded properties exceeding 256 bytes if encoded all at + * once they are encoded in subsequent calls to CBOREncoder::encode. + */ + + /* [{0: "str_0", 3: "I am trying to create a single property in such a way it does not fit the CBOR encoder message buffer size (that is 256 bytes) in order to test what happens trying to encode it. It looks easy, but in reality 256 bytes are a lot of characters to fill. Done!"}] + * = 9F A2 00 65 73 74 72 5F 30 03 78 FF 49 20 61 6D 20 74 72 79 69 6E 67 20 74 6F 20 63 72 65 61 74 65 20 61 20 73 69 6E 67 6C 65 20 70 72 6F 70 65 72 74 79 20 69 6E 20 73 75 63 68 20 61 20 77 61 79 20 69 74 20 64 6F 65 73 20 6E 6F 74 20 66 69 74 20 74 68 65 20 43 42 4F 52 20 65 6E 63 6F 64 65 72 20 6D 65 73 73 61 67 65 20 62 75 66 66 65 72 20 73 69 7A 65 20 28 74 68 61 74 20 69 73 20 32 35 36 20 62 79 74 65 73 29 20 69 6E 20 6F 72 64 65 72 20 74 6F 20 74 65 73 74 20 77 68 61 74 20 68 61 70 70 65 6E 73 20 74 72 79 69 6E 67 20 74 6F 20 65 6E 63 6F 64 65 20 69 74 2E 20 49 74 20 6C 6F 6F 6B 73 20 65 61 73 79 2C 20 62 75 74 20 69 6E 20 72 65 61 6C 69 74 79 20 32 35 36 20 62 79 74 65 73 20 61 72 65 20 61 20 6C 6F 74 20 6F 66 20 63 68 61 72 61 63 74 65 72 73 20 74 6F 20 66 69 6C 6C 2E 20 44 6F 6E 65 21 FF + */ + std::vector const expected_1 = {}; + std::vector const actual_1 = cbor::encode(property_container); + REQUIRE(actual_1 == expected_1); + } + } From e2852737e91060c0e9c7f29179808360bb9ceb73 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 21 Dec 2021 14:39:46 +0100 Subject: [PATCH 252/780] Add custom and dedicated error for splitted items --- src/cbor/lib/tinycbor/cbor-lib.h | 2 +- src/cbor/lib/tinycbor/src/cbor.h | 1 + src/cbor/lib/tinycbor/src/cborerrorstrings.c | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cbor/lib/tinycbor/cbor-lib.h b/src/cbor/lib/tinycbor/cbor-lib.h index a9cbe2ca2..e8d8004e7 100644 --- a/src/cbor/lib/tinycbor/cbor-lib.h +++ b/src/cbor/lib/tinycbor/cbor-lib.h @@ -27,7 +27,7 @@ CborError error = CborNoError; \ error = (expr); \ if (CborErrorOutOfMemory == error) \ - return CborErrorTooManyItems; \ + return CborErrorSplitItems; \ if (CborNoError != error) \ return error; \ } while(0); diff --git a/src/cbor/lib/tinycbor/src/cbor.h b/src/cbor/lib/tinycbor/src/cbor.h index cb759fd5b..93d448daf 100644 --- a/src/cbor/lib/tinycbor/src/cbor.h +++ b/src/cbor/lib/tinycbor/src/cbor.h @@ -189,6 +189,7 @@ typedef enum CborError { /* encoder errors */ CborErrorTooManyItems = 768, CborErrorTooFewItems, + CborErrorSplitItems, /* internal implementation errors */ CborErrorDataTooLarge = 1024, diff --git a/src/cbor/lib/tinycbor/src/cborerrorstrings.c b/src/cbor/lib/tinycbor/src/cborerrorstrings.c index e24be536f..d0ba66c34 100644 --- a/src/cbor/lib/tinycbor/src/cborerrorstrings.c +++ b/src/cbor/lib/tinycbor/src/cborerrorstrings.c @@ -163,6 +163,9 @@ const char *cbor_error_string(CborError error) case CborErrorTooFewItems: return _("too few items added to encoder"); + case CborErrorSplitItems: + return _("splitted item added to encoder"); + case CborErrorDataTooLarge: return _("internal error: data too large"); From 5576a608dba2186e87c8cdc8f8f81be42a0687fd Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 18 Jan 2022 10:59:57 +0100 Subject: [PATCH 253/780] Declare last_checked_property_index as protected variable of ArduinoIoTCloud --- src/ArduinoIoTCloud.cpp | 1 + src/ArduinoIoTCloud.h | 1 + src/ArduinoIoTCloudLPWAN.cpp | 3 +-- src/ArduinoIoTCloudTCP.cpp | 3 +-- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index b62a91990..115ce3a0d 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -27,6 +27,7 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() : _connection{nullptr} +, _last_checked_property_index{0} , _time_service(ArduinoIoTCloudTimeService()) , _tz_offset{0} , _tz_dst_until{0} diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index ae8ac1a86..565a91501 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -148,6 +148,7 @@ class ArduinoIoTCloudClass ConnectionHandler * _connection; PropertyContainer _property_container; + unsigned int _last_checked_property_index; TimeService & _time_service; int _tz_offset; unsigned int _tz_dst_until; diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index b30fbfa83..fc85d0471 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -149,9 +149,8 @@ void ArduinoIoTCloudLPWAN::sendPropertiesToCloud() { int bytes_encoded = 0; uint8_t data[CBOR_LORA_MSG_MAX_SIZE]; - static unsigned int last_checked_property_index = 0; - if (CBOREncoder::encode(_property_container, data, sizeof(data), bytes_encoded, last_checked_property_index, true) == CborNoError) + if (CBOREncoder::encode(_property_container, data, sizeof(data), bytes_encoded, _last_checked_property_index, true) == CborNoError) if (bytes_encoded > 0) writeProperties(data, bytes_encoded); } diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index a0c94ef7a..fa741785b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -596,8 +596,7 @@ void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(PropertyContainer & proper void ArduinoIoTCloudTCP::sendPropertiesToCloud() { - static unsigned int last_checked_property_index = 0; - sendPropertyContainerToCloud(_property_container, last_checked_property_index); + sendPropertyContainerToCloud(_property_container, _last_checked_property_index); } #if OTA_ENABLED From 78b31586b9117d5483704902ea38543220f10ad1 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 18 Jan 2022 11:12:49 +0100 Subject: [PATCH 254/780] Merge FinishAppend and AdvancePropertyContainer encoder states --- src/cbor/CBOREncoder.cpp | 5 ----- src/cbor/CBOREncoder.h | 1 - 2 files changed, 6 deletions(-) diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index 45ba82345..b15b20837 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -51,7 +51,6 @@ CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * case EncoderState::CloseCBORContainer : next_state = handle_CloseCBORContainer(propertyEncoder); break; case EncoderState::TrimClose : next_state = handle_TrimClose(propertyEncoder); break; case EncoderState::FinishAppend : next_state = handle_FinishAppend(propertyEncoder); break; - case EncoderState::AdvancePropertyContainer : next_state = handle_AdvancePropertyContainer(propertyEncoder); break; case EncoderState::SendMessage : /* Nothing to do */ break; case EncoderState::Error : return CborErrorInternalError; break; } @@ -197,11 +196,7 @@ CBOREncoder::EncoderState CBOREncoder::handle_FinishAppend(PropertyContainerEnco p->appendCompleted(); num_appended_properties++; } - return EncoderState::AdvancePropertyContainer; -} -CBOREncoder::EncoderState CBOREncoder::handle_AdvancePropertyContainer(PropertyContainerEncoder & propertyEncoder) -{ /* Advance property index for the nex message */ propertyEncoder.current_property_index += propertyEncoder.checked_property_count; diff --git a/src/cbor/CBOREncoder.h b/src/cbor/CBOREncoder.h index 7acdc3f72..fa68d2200 100644 --- a/src/cbor/CBOREncoder.h +++ b/src/cbor/CBOREncoder.h @@ -62,7 +62,6 @@ class CBOREncoder CloseCBORContainer, TrimClose, FinishAppend, - AdvancePropertyContainer, SendMessage, Error }; From 696b48eb557a9884557ebd57566d366700efb231 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 18 Jan 2022 09:53:05 +0100 Subject: [PATCH 255/780] Avoid big nested 'if' when checking for subscribe_retry_delay --- src/ArduinoIoTCloudTCP.cpp | 72 +++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index b1d61a7d6..33c87f32c 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -409,55 +409,55 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() unsigned long const now = millis(); bool const is_subscribe_retry_delay_expired = (now - _last_subscribe_request_tick) > AIOT_CONFIG_SUBSCRIBE_RETRY_DELAY_ms; bool const is_first_subscribe_request = (_last_subscribe_request_cnt == 0); - if (is_first_subscribe_request || is_subscribe_retry_delay_expired) + + if (!is_first_subscribe_request && !is_subscribe_retry_delay_expired) { - if (_last_subscribe_request_cnt > AIOT_CONFIG_SUBSCRIBE_MAX_RETRY_CNT) - { - _last_subscribe_request_cnt = 0; - _last_subscribe_request_tick = 0; - _mqttClient.stop(); - execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - return State::ConnectPhy; - } + return State::SubscribeMqttTopics; + } + + if (_last_subscribe_request_cnt > AIOT_CONFIG_SUBSCRIBE_MAX_RETRY_CNT) + { + _last_subscribe_request_cnt = 0; + _last_subscribe_request_tick = 0; + _mqttClient.stop(); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + return State::ConnectPhy; + } - _last_subscribe_request_tick = now; - _last_subscribe_request_cnt++; + _last_subscribe_request_tick = now; + _last_subscribe_request_cnt++; - if (!_mqttClient.subscribe(_dataTopicIn)) - { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); + if (!_mqttClient.subscribe(_dataTopicIn)) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); #if !defined(__AVR__) - DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); + DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); #endif - return State::SubscribeMqttTopics; - } + return State::SubscribeMqttTopics; + } - if (_shadowTopicIn != "") + if (_shadowTopicIn != "") + { + if (!_mqttClient.subscribe(_shadowTopicIn)) { - if (!_mqttClient.subscribe(_shadowTopicIn)) - { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); #if !defined(__AVR__) - DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); + DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); #endif - return State::SubscribeMqttTopics; - } + return State::SubscribeMqttTopics; } + } - _last_subscribe_request_cnt = 0; - _last_subscribe_request_tick = 0; - - DEBUG_INFO("Connected to Arduino IoT Cloud"); - execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); + DEBUG_INFO("Connected to Arduino IoT Cloud"); + execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); + _last_subscribe_request_cnt = 0; + _last_subscribe_request_tick = 0; - if (_shadowTopicIn != "") - return State::RequestLastValues; - else - return State::Connected; - - } + if (_shadowTopicIn != "") + return State::RequestLastValues; + else + return State::Connected; - return State::SubscribeMqttTopics; } ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() From b0b75cd05fba87ae5212b9143648d7324d6ba358 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 24 Jan 2022 11:00:33 +0100 Subject: [PATCH 256/780] Release v1.4.1 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 39ee1b3a5..37dff6432 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.4.0 +version=1.4.1 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From fc0ddb9c034c86d644f417272f71610111292461 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 3 Feb 2022 14:43:25 +0100 Subject: [PATCH 257/780] Split _property_container in _device_property_container and _thing_property container --- src/ArduinoIoTCloud.cpp | 92 +++++++++++++++++++++++++++++------- src/ArduinoIoTCloud.h | 22 ++++++++- src/ArduinoIoTCloudLPWAN.cpp | 6 +-- src/ArduinoIoTCloudTCP.cpp | 32 +++++++------ src/ArduinoIoTCloudTCP.h | 4 +- 5 files changed, 118 insertions(+), 38 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 115ce3a0d..ff83facc1 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -44,12 +44,12 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() void ArduinoIoTCloudClass::push() { - requestUpdateForAllProperties(_property_container); + requestUpdateForAllProperties(_thing_property_container); } bool ArduinoIoTCloudClass::setTimestamp(String const & prop_name, unsigned long const timestamp) { - Property * p = getProperty(_property_container, prop_name); + Property * p = getProperty(_thing_property_container, prop_name); if (p == nullptr) return false; @@ -81,20 +81,30 @@ void ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, int } if (seconds == ON_CHANGE) { - addPropertyToContainer(_property_container, property, name, permission, tag).publishOnChange(minDelta, Property::DEFAULT_MIN_TIME_BETWEEN_UPDATES_MILLIS).onUpdate(fn).onSync(synFn); + addPropertyToContainer(_thing_property_container, property, name, permission, tag).publishOnChange(minDelta, Property::DEFAULT_MIN_TIME_BETWEEN_UPDATES_MILLIS).onUpdate(fn).onSync(synFn); } else { - addPropertyToContainer(_property_container, property, name, permission, tag).publishEvery(seconds).onUpdate(fn).onSync(synFn); + addPropertyToContainer(_thing_property_container, property, name, permission, tag).publishEvery(seconds).onUpdate(fn).onSync(synFn); } } Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, Permission const permission) { - return addPropertyToContainer(_property_container, property, name, permission); + return addPropertyToContainer(_thing_property_container, property, name, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, int tag, Permission const permission) { - return addPropertyToContainer(_property_container, property, name, permission, tag); + return addPropertyToContainer(_thing_property_container, property, name, permission, tag); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, Permission const permission) +{ + return addPropertyToContainer(prop_cont, property, name, permission, -1); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) +{ + return addPropertyToContainer(prop_cont, property, name, permission, tag); } void ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) @@ -110,13 +120,23 @@ void ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, int tag, Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, Permission const permission) { - return addPropertyReal(property, name, -1, permission); + return addPropertyReal(property, _thing_property_container, name, -1, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, int tag, Permission const permission) +{ + return addPropertyReal(property, _thing_property_container, name, tag, permission); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, Permission const permission) +{ + return addPropertyReal(property, prop_cont, name, -1, permission); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) { Property* p = new CloudWrapperBool(property); - return addPropertyToContainer(_property_container, *p, name, permission, tag); + return addPropertyToContainer(prop_cont, *p, name, permission, tag); } void ArduinoIoTCloudClass::addPropertyReal(float& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) @@ -132,13 +152,23 @@ void ArduinoIoTCloudClass::addPropertyReal(float& property, String name, int tag Property& ArduinoIoTCloudClass::addPropertyReal(float& property, String name, Permission const permission) { - return addPropertyReal(property, name, -1, permission); + return addPropertyReal(property, _thing_property_container, name, -1, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(float& property, String name, int tag, Permission const permission) +{ + return addPropertyReal(property, _thing_property_container, name, tag, permission); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(float& property, PropertyContainer &prop_cont, String name, Permission const permission) +{ + return addPropertyReal(property, prop_cont, name, -1, permission); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(float& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) { Property* p = new CloudWrapperFloat(property); - return addPropertyToContainer(_property_container, *p, name, permission, tag); + return addPropertyToContainer(prop_cont, *p, name, permission, tag); } void ArduinoIoTCloudClass::addPropertyReal(int& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) @@ -154,13 +184,23 @@ void ArduinoIoTCloudClass::addPropertyReal(int& property, String name, int tag, Property& ArduinoIoTCloudClass::addPropertyReal(int& property, String name, Permission const permission) { - return addPropertyReal(property, name, -1, permission); + return addPropertyReal(property, _thing_property_container, name, -1, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(int& property, String name, int tag, Permission const permission) +{ + return addPropertyReal(property, _thing_property_container, name, tag, permission); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(int& property, PropertyContainer &prop_cont, String name, Permission const permission) +{ + return addPropertyReal(property, prop_cont, name, -1, permission); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) { Property* p = new CloudWrapperInt(property); - return addPropertyToContainer(_property_container, *p, name, permission, tag); + return addPropertyToContainer(prop_cont, *p, name, permission, tag); } void ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) @@ -176,13 +216,23 @@ void ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, Permission const permission) { - return addPropertyReal(property, name, -1, permission); + return addPropertyReal(property, _thing_property_container, name, -1, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, int tag, Permission const permission) +{ + return addPropertyReal(property, _thing_property_container, name, tag, permission); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, Permission const permission) +{ + return addPropertyReal(property, prop_cont, name, -1, permission); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) { Property* p = new CloudWrapperUnsignedInt(property); - return addPropertyToContainer(_property_container, *p, name, permission, tag); + return addPropertyToContainer(prop_cont, *p, name, permission, tag); } void ArduinoIoTCloudClass::addPropertyReal(String& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) @@ -198,13 +248,23 @@ void ArduinoIoTCloudClass::addPropertyReal(String& property, String name, int ta Property& ArduinoIoTCloudClass::addPropertyReal(String& property, String name, Permission const permission) { - return addPropertyReal(property, name, -1, permission); + return addPropertyReal(property, _thing_property_container, name, -1, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(String& property, String name, int tag, Permission const permission) +{ + return addPropertyReal(property, _thing_property_container, name, tag, permission); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(String& property, PropertyContainer &prop_cont, String name, Permission const permission) +{ + return addPropertyReal(property, prop_cont, name, -1, permission); +} + +Property& ArduinoIoTCloudClass::addPropertyReal(String& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) { Property* p = new CloudWrapperString(property); - return addPropertyToContainer(_property_container, *p, name, permission, tag); + return addPropertyToContainer(prop_cont, *p, name, permission, tag); } /****************************************************************************** diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 565a91501..558b8c96f 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -96,6 +96,9 @@ class ArduinoIoTCloudClass inline void setDeviceId(String const device_id) { _device_id = device_id; }; inline String & getDeviceId() { return _device_id; }; + inline bool deviceNotAttached() { return _thing_id == "null";} + inline bool deviceNotConfigured() { return _thing_id == "";} + inline ConnectionHandler * getConnection() { return _connection; } inline unsigned long getInternalTime() { return _time_service.getTime(); } @@ -124,6 +127,20 @@ class ArduinoIoTCloudClass Property& addPropertyReal(unsigned int& property, String name, Permission const permission); Property& addPropertyReal(String& property, String name, Permission const permission); + Property& addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); + Property& addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); + Property& addPropertyReal(float& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); + Property& addPropertyReal(int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); + Property& addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); + Property& addPropertyReal(String& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); + + Property& addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, Permission const permission); + Property& addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, Permission const permission); + Property& addPropertyReal(float& property, PropertyContainer &prop_cont, String name, Permission const permission); + Property& addPropertyReal(int& property, PropertyContainer &prop_cont, String name, Permission const permission); + Property& addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, Permission const permission); + Property& addPropertyReal(String& property, PropertyContainer &prop_cont, String name, Permission const permission); + /* The following methods are for MKR WAN 1300/1310 LoRa boards since * they use a number to identify a given property within a CBOR message. * This approach reduces the required amount of data which is of great @@ -147,17 +164,18 @@ class ArduinoIoTCloudClass protected: ConnectionHandler * _connection; - PropertyContainer _property_container; + PropertyContainer _device_property_container; + PropertyContainer _thing_property_container; unsigned int _last_checked_property_index; TimeService & _time_service; int _tz_offset; unsigned int _tz_dst_until; + String _thing_id; void execCloudEventCallback(ArduinoIoTCloudEvent const event); private: - String _thing_id; String _device_id; OnCloudEventCallback _cloud_event_callback[3]; }; diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index fc85d0471..5d501dd30 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -121,7 +121,7 @@ ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_Connected() /* Check if a primitive property wrapper is locally changed. */ updateTimestampOnLocallyChangedProperties(_property_container); - + /* Decode available data. */ if (_connection->available()) decodePropertiesFromCloud(); @@ -142,7 +142,7 @@ void ArduinoIoTCloudLPWAN::decodePropertiesFromCloud() { lora_msg_buf[bytes_received] = _connection->read(); } - CBORDecoder::decode(_property_container, lora_msg_buf, bytes_received); + CBORDecoder::decode(_thing_property_container, lora_msg_buf, bytes_received); } void ArduinoIoTCloudLPWAN::sendPropertiesToCloud() @@ -150,7 +150,7 @@ void ArduinoIoTCloudLPWAN::sendPropertiesToCloud() int bytes_encoded = 0; uint8_t data[CBOR_LORA_MSG_MAX_SIZE]; - if (CBOREncoder::encode(_property_container, data, sizeof(data), bytes_encoded, _last_checked_property_index, true) == CborNoError) + if (CBOREncoder::encode(_thing_property_container, data, sizeof(data), bytes_encoded, _last_checked_property_index, true) == CborNoError) if (bytes_encoded > 0) writeProperties(data, bytes_encoded); } diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e78011852..7d154a896 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -243,15 +243,17 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _dataTopicIn = getTopic_datain(); #if OTA_ENABLED - addPropertyReal(_ota_cap, "OTA_CAP", Permission::Read); - addPropertyReal(_ota_error, "OTA_ERROR", Permission::Read); - addPropertyReal(_ota_img_sha256, "OTA_SHA256", Permission::Read); - addPropertyReal(_ota_url, "OTA_URL", Permission::ReadWrite).onSync(CLOUD_WINS); - addPropertyReal(_ota_req, "OTA_REQ", Permission::ReadWrite).onSync(CLOUD_WINS); + addPropertyReal(_ota_cap, _device_property_container, "OTA_CAP", Permission::Read); + addPropertyReal(_ota_error, _device_property_container, "OTA_ERROR", Permission::Read); + addPropertyReal(_ota_img_sha256, _device_property_container, "OTA_SHA256", Permission::Read); + addPropertyReal(_ota_url, _device_property_container, "OTA_URL", Permission::ReadWrite).onSync(CLOUD_WINS); + addPropertyReal(_ota_req, _device_property_container, "OTA_REQ", Permission::ReadWrite).onSync(CLOUD_WINS); #endif /* OTA_ENABLED */ - 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); + addPropertyReal(_tz_offset, _thing_property_container, "tz_offset", Permission::ReadWrite).onSync(CLOUD_WINS).onUpdate(updateTimezoneInfo); + addPropertyReal(_tz_dst_until, _thing_property_container, "tz_dst_until", Permission::ReadWrite).onSync(CLOUD_WINS).onUpdate(updateTimezoneInfo); + + addPropertyReal(_thing_id, _device_property_container, "thing_id", Permission::ReadWrite); #if OTA_STORAGE_PORTENTA_QSPI #define BOOTLOADER_ADDR (0x8000000) @@ -524,7 +526,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() * the connection from being established due to a wrong data * in the reconstructed certificate. */ - updateTimestampOnLocallyChangedProperties(_property_container); + updateTimestampOnLocallyChangedProperties(_thing_property_container); /* Retransmit data in case there was a lost transaction due * to phy layer or MQTT connectivity loss. @@ -586,13 +588,13 @@ void ArduinoIoTCloudTCP::handleMessage(int length) } if (_dataTopicIn == topic) { - CBORDecoder::decode(_property_container, (uint8_t*)bytes, length); + CBORDecoder::decode(_thing_property_container, (uint8_t*)bytes, length); } if ((_shadowTopicIn == topic) && (_state == State::RequestLastValues)) { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); - CBORDecoder::decode(_property_container, (uint8_t*)bytes, length, true); + CBORDecoder::decode(_thing_property_container, (uint8_t*)bytes, length, true); sendPropertiesToCloud(); _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); @@ -602,7 +604,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) } } -void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(PropertyContainer & property_container, unsigned int & current_property_index) +void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(String const topic, PropertyContainer & property_container, unsigned int & current_property_index) { int bytes_encoded = 0; uint8_t data[MQTT_TRANSMIT_BUFFER_SIZE]; @@ -616,13 +618,13 @@ void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(PropertyContainer & proper _mqtt_data_len = bytes_encoded; memcpy(_mqtt_data_buf, data, _mqtt_data_len); /* Transmit the properties to the MQTT broker */ - write(_dataTopicOut, _mqtt_data_buf, _mqtt_data_len); + write(topic, _mqtt_data_buf, _mqtt_data_len); } } void ArduinoIoTCloudTCP::sendPropertiesToCloud() { - sendPropertyContainerToCloud(_property_container, _last_checked_property_index); + sendPropertyContainerToCloud(_dataTopicOut, _thing_property_container, _last_checked_property_index); } #if OTA_ENABLED @@ -636,13 +638,13 @@ void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() ota_property_list.cend(), [this, &ota_property_container ] (String const & name) { - Property* p = getProperty(this->_property_container, name); + Property* p = getProperty(this->_device_property_container, name); if(p != nullptr) addPropertyToContainer(ota_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); } ); - sendPropertyContainerToCloud(ota_property_container, last_ota_property_index); + sendPropertyContainerToCloud(_dataTopicOut, ota_property_container, last_ota_property_index); } #endif diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 59caba7a2..663acd111 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -166,7 +166,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass static void onMessage(int length); void handleMessage(int length); - void sendPropertyContainerToCloud(PropertyContainer & property_container, unsigned int & current_property_index); + void sendPropertyContainerToCloud(String const topic, PropertyContainer & property_container, unsigned int & current_property_index); void sendPropertiesToCloud(); void requestLastValue(); int write(String const topic, byte const data[], int const length); @@ -184,4 +184,4 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass extern ArduinoIoTCloudTCP ArduinoCloud; -#endif \ No newline at end of file +#endif From 1af47011e7f717d586ad8d72b2108f433bbff0c2 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 11 Jan 2022 13:36:47 +0100 Subject: [PATCH 258/780] ArduinoIoTCloudTCP state machine changes to handle thig_id discovery protocol --- src/ArduinoIoTCloud.h | 9 +- src/ArduinoIoTCloudLPWAN.cpp | 2 +- src/ArduinoIoTCloudTCP.cpp | 191 +++++++++++++++++++++++++++++++---- src/ArduinoIoTCloudTCP.h | 29 ++++-- 4 files changed, 202 insertions(+), 29 deletions(-) diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 558b8c96f..bad570c7e 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -96,8 +96,12 @@ class ArduinoIoTCloudClass inline void setDeviceId(String const device_id) { _device_id = device_id; }; inline String & getDeviceId() { return _device_id; }; - inline bool deviceNotAttached() { return _thing_id == "null";} - inline bool deviceNotConfigured() { return _thing_id == "";} + inline void setThingIdOutdatedFlag() { _thing_id_outdated = true ; } + inline void clrThingIdOutdatedFlag() { _thing_id_outdated = false ; } + inline bool getThingIdOutdatedFlag() { return _thing_id_outdated; } + + inline bool deviceNotAttached() { return _thing_id == "null"; } + inline bool deviceNotConfigured() { return _thing_id == ""; } inline ConnectionHandler * getConnection() { return _connection; } @@ -178,6 +182,7 @@ class ArduinoIoTCloudClass String _device_id; OnCloudEventCallback _cloud_event_callback[3]; + bool _thing_id_outdated; }; #ifdef HAS_TCP diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 5d501dd30..fbc42b628 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -120,7 +120,7 @@ ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_Connected() } /* Check if a primitive property wrapper is locally changed. */ - updateTimestampOnLocallyChangedProperties(_property_container); + updateTimestampOnLocallyChangedProperties(_thing_property_container); /* Decode available data. */ if (_connection->available()) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 7d154a896..992b9b2c2 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -69,6 +69,11 @@ extern "C" void updateTimezoneInfo() ArduinoCloud.updateInternalTimezoneInfo(); } +extern "C" void setThingIdOutdated() +{ + ArduinoCloud.setThingIdOutdatedFlag(); +} + /****************************************************************************** CTOR/DTOR ******************************************************************************/ @@ -77,6 +82,8 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() : _state{State::ConnectPhy} , _next_connection_attempt_tick{0} , _last_connection_attempt_cnt{0} +, _next_device_subscribe_attempt_tick{0} +, _last_device_subscribe_cnt{0} , _last_sync_request_tick{0} , _last_sync_request_cnt{0} , _last_subscribe_request_tick{0} @@ -91,10 +98,13 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _password("") #endif , _mqttClient{nullptr} +, _deviceTopicOut("") +, _deviceTopicIn("") , _shadowTopicOut("") , _shadowTopicIn("") , _dataTopicOut("") , _dataTopicIn("") +, _deviceSubscribedToThing{false} #if OTA_ENABLED , _ota_cap{false} , _ota_error{static_cast(OTAError::None)} @@ -237,10 +247,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _mqttClient.setConnectionTimeout(1500); _mqttClient.setId(getDeviceId().c_str()); - _shadowTopicOut = getTopic_shadowout(); - _shadowTopicIn = getTopic_shadowin(); - _dataTopicOut = getTopic_dataout(); - _dataTopicIn = getTopic_datain(); + _deviceTopicOut = getTopic_deviceout(); + _deviceTopicIn = getTopic_devicein(); #if OTA_ENABLED addPropertyReal(_ota_cap, _device_property_container, "OTA_CAP", Permission::Read); @@ -253,7 +261,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, addPropertyReal(_tz_offset, _thing_property_container, "tz_offset", Permission::ReadWrite).onSync(CLOUD_WINS).onUpdate(updateTimezoneInfo); addPropertyReal(_tz_dst_until, _thing_property_container, "tz_dst_until", Permission::ReadWrite).onSync(CLOUD_WINS).onUpdate(updateTimezoneInfo); - addPropertyReal(_thing_id, _device_property_container, "thing_id", Permission::ReadWrite); + addPropertyReal(_thing_id, _device_property_container, "thing_id", Permission::ReadWrite).onUpdate(setThingIdOutdated); #if OTA_STORAGE_PORTENTA_QSPI #define BOOTLOADER_ADDR (0x8000000) @@ -322,12 +330,16 @@ void ArduinoIoTCloudTCP::update() State next_state = _state; switch (_state) { - case State::ConnectPhy: next_state = handle_ConnectPhy(); break; - case State::SyncTime: next_state = handle_SyncTime(); break; - case State::ConnectMqttBroker: next_state = handle_ConnectMqttBroker(); break; - case State::SubscribeMqttTopics: next_state = handle_SubscribeMqttTopics(); break; - case State::RequestLastValues: next_state = handle_RequestLastValues(); break; - case State::Connected: next_state = handle_Connected(); break; + case State::ConnectPhy: next_state = handle_ConnectPhy(); break; + case State::SyncTime: next_state = handle_SyncTime(); break; + case State::ConnectMqttBroker: next_state = handle_ConnectMqttBroker(); break; + case State::SendDeviceProperties: next_state = handle_SendDeviceProperties(); break; + case State::SubscribeDeviceTopic: next_state = handle_SubscribeDeviceTopic(); break; + case State::WaitDeviceConfig: next_state = handle_WaitDeviceConfig(); break; + case State::CheckDeviceConfig: next_state = handle_CheckDeviceConfig(); break; + case State::SubscribeThingTopics: next_state = handle_SubscribeThingTopics(); break; + case State::RequestLastValues: next_state = handle_RequestLastValues(); break; + case State::Connected: next_state = handle_Connected(); break; } _state = next_state; @@ -385,7 +397,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() if (_mqttClient.connect(_brokerAddress.c_str(), _brokerPort)) { _last_connection_attempt_cnt = 0; - return State::SubscribeMqttTopics; + return State::SendDeviceProperties; } _last_connection_attempt_cnt++; @@ -398,7 +410,127 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() return State::ConnectPhy; } -ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SendDeviceProperties() +{ + if (!_mqttClient.connected()) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); + _mqttClient.stop(); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + return State::ConnectPhy; + } + +#if OTA_ENABLED + sendOTAPropertiesToCloud(); +#endif + return State::SubscribeDeviceTopic; +} + +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() +{ + if (!_mqttClient.connected()) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); + _mqttClient.stop(); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + return State::ConnectPhy; + } + + if (!_mqttClient.subscribe(_deviceTopicIn)) + { + return State::SubscribeDeviceTopic; + } + + if (_last_device_subscribe_cnt > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) + { + _last_device_subscribe_cnt = 0; + _next_device_subscribe_attempt_tick = 0; + _mqttClient.stop(); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + return State::ConnectPhy; + } + + unsigned long reconnection_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms; + reconnection_retry_delay = min(reconnection_retry_delay, static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms)); + _next_device_subscribe_attempt_tick = millis() + reconnection_retry_delay; + _last_device_subscribe_cnt++; + + return State::WaitDeviceConfig; +} + +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() +{ + if (!_mqttClient.connected()) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); + _mqttClient.stop(); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + return State::ConnectPhy; + } + + if (millis() > _next_device_subscribe_attempt_tick) + { + /* Configuration not received try to resubscribe */ + if (_mqttClient.unsubscribe(_deviceTopicIn)) + { + return State::SubscribeDeviceTopic; + } + } + + return State::WaitDeviceConfig; +} + +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() +{ + if (!_mqttClient.connected()) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); + _mqttClient.stop(); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + return State::ConnectPhy; + } + + if(getThingIdOutdatedFlag()) + { + if(_deviceSubscribedToThing == true) + { + /* Unsubscribe from old things topics and go on with a new subsctiption */ + _mqttClient.unsubscribe(_shadowTopicIn); + _mqttClient.unsubscribe(_dataTopicIn); + + _deviceSubscribedToThing = false; + } + } + + updateThingTopics(); + + if (deviceNotConfigured()) + { + /* maybe we have only missed the thing_id property... + * unsubsribe and resubscribe immediately to trigger a new configuration command + */ + _mqttClient.unsubscribe(_deviceTopicIn); + return State::SubscribeDeviceTopic; + } + + if (deviceNotAttached()) + { + /* start long timeout counter + * return return State::SubscribeThingTopics + * if long timeout expired unsubscribe and + * return State::SubscribeDeviceTopic + */ + unsigned long reconnection_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms * 10000; + reconnection_retry_delay = min(reconnection_retry_delay, static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms)); + _next_device_subscribe_attempt_tick = millis() + reconnection_retry_delay; + _last_device_subscribe_cnt++; + return State::WaitDeviceConfig; + } + + return State::SubscribeThingTopics; +} + +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() { if (!_mqttClient.connected()) { @@ -414,7 +546,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() if (!is_first_subscribe_request && !is_subscribe_retry_delay_expired) { - return State::SubscribeMqttTopics; + return State::SubscribeThingTopics; } if (_last_subscribe_request_cnt > AIOT_CONFIG_SUBSCRIBE_MAX_RETRY_CNT) @@ -435,7 +567,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() #if !defined(__AVR__) DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); #endif - return State::SubscribeMqttTopics; + return State::SubscribeThingTopics; } if (_shadowTopicIn != "") @@ -446,14 +578,13 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() #if !defined(__AVR__) DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); #endif - return State::SubscribeMqttTopics; + return State::SubscribeThingTopics; } } DEBUG_INFO("Connected to Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); - _last_subscribe_request_cnt = 0; - _last_subscribe_request_tick = 0; + _deviceSubscribedToThing = true; if (_shadowTopicIn != "") return State::RequestLastValues; @@ -587,10 +718,20 @@ void ArduinoIoTCloudTCP::handleMessage(int length) bytes[i] = _mqttClient.read(); } + /* Topic for OTA properties and device configuration */ + if (_deviceTopicIn == topic) { + CBORDecoder::decode(_device_property_container, (uint8_t*)bytes, length); + _last_device_subscribe_cnt = 0; + _next_device_subscribe_attempt_tick = 0; + _state = State::CheckDeviceConfig; + } + + /* Topic for user input data */ if (_dataTopicIn == topic) { CBORDecoder::decode(_thing_property_container, (uint8_t*)bytes, length); } + /* Topic for sync Thing last values on connect */ if ((_shadowTopicIn == topic) && (_state == State::RequestLastValues)) { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); @@ -633,7 +774,7 @@ void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() PropertyContainer ota_property_container; unsigned int last_ota_property_index = 0; - std::list const ota_property_list {"OTA_CAP", "OTA_ERROR", "OTA_SHA256", "OTA_URL", "OTA_REQ"}; + std::list const ota_property_list {"OTA_CAP", "OTA_ERROR", "OTA_SHA256"}; std::for_each(ota_property_list.cbegin(), ota_property_list.cend(), [this, &ota_property_container ] (String const & name) @@ -644,7 +785,7 @@ void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() } ); - sendPropertyContainerToCloud(_dataTopicOut, ota_property_container, last_ota_property_index); + sendPropertyContainerToCloud(_deviceTopicOut, ota_property_container, last_ota_property_index); } #endif @@ -688,6 +829,16 @@ void ArduinoIoTCloudTCP::onOTARequest() } #endif +void ArduinoIoTCloudTCP::updateThingTopics() +{ + _shadowTopicOut = getTopic_shadowout(); + _shadowTopicIn = getTopic_shadowin(); + _dataTopicOut = getTopic_dataout(); + _dataTopicIn = getTopic_datain(); + + clrThingIdOutdatedFlag(); +} + /****************************************************************************** * EXTERN DEFINITION ******************************************************************************/ diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 663acd111..861482f5e 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -105,7 +105,11 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass ConnectPhy, SyncTime, ConnectMqttBroker, - SubscribeMqttTopics, + SendDeviceProperties, + SubscribeDeviceTopic, + WaitDeviceConfig, + CheckDeviceConfig, + SubscribeThingTopics, RequestLastValues, Connected, }; @@ -114,6 +118,8 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass unsigned long _next_connection_attempt_tick; unsigned int _last_connection_attempt_cnt; + unsigned long _next_device_subscribe_attempt_tick; + unsigned int _last_device_subscribe_cnt; unsigned long _last_sync_request_tick; unsigned int _last_sync_request_cnt; unsigned long _last_subscribe_request_tick; @@ -137,11 +143,15 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass MqttClient _mqttClient; + String _deviceTopicOut; + String _deviceTopicIn; String _shadowTopicOut; String _shadowTopicIn; String _dataTopicOut; String _dataTopicIn; + bool _deviceSubscribedToThing; + #if OTA_ENABLED bool _ota_cap; int _ota_error; @@ -152,15 +162,21 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass onOTARequestCallbackFunc _get_ota_confirmation; #endif /* OTA_ENABLED */ - inline String getTopic_shadowout() { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/shadow/o"); } - 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_deviceout() { return String("/a/d/" + getDeviceId() + "/e/o");} + inline String getTopic_devicein () { return String("/a/d/" + getDeviceId() + "/e/i");} + inline String getTopic_shadowout() { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/shadow/o"); } + inline String getTopic_shadowin () { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/shadow/i"); } + inline String getTopic_dataout () { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/e/o"); } + inline String getTopic_datain () { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/e/i"); } State handle_ConnectPhy(); State handle_SyncTime(); State handle_ConnectMqttBroker(); - State handle_SubscribeMqttTopics(); + State handle_SendDeviceProperties(); + State handle_WaitDeviceConfig(); + State handle_CheckDeviceConfig(); + State handle_SubscribeDeviceTopic(); + State handle_SubscribeThingTopics(); State handle_RequestLastValues(); State handle_Connected(); @@ -176,6 +192,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass void sendOTAPropertiesToCloud(); #endif + void updateThingTopics(); }; /****************************************************************************** From f4af0d2ecdbe921273e8c1220779fa7d9d59eec3 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 7 Dec 2021 09:04:33 +0100 Subject: [PATCH 259/780] If board has a valid _dataTopicIn also _shadowTopicIn is valid --- src/ArduinoIoTCloudTCP.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 992b9b2c2..b8eafb9ff 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -570,27 +570,20 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() return State::SubscribeThingTopics; } - if (_shadowTopicIn != "") + if (!_mqttClient.subscribe(_shadowTopicIn)) { - if (!_mqttClient.subscribe(_shadowTopicIn)) - { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); #if !defined(__AVR__) - DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); + DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); #endif - return State::SubscribeThingTopics; - } + return State::SubscribeThingTopics; } DEBUG_INFO("Connected to Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); _deviceSubscribedToThing = true; - if (_shadowTopicIn != "") - return State::RequestLastValues; - else - return State::Connected; - + return State::RequestLastValues; } ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() From 79656c40e6b78abdfdc8b1ac9368930196238097 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 10 Dec 2021 15:59:56 +0100 Subject: [PATCH 260/780] Add configuration flag to sendOTAPropertiesToCloud() fuction in order to append OTA_REQ property --- src/ArduinoIoTCloudTCP.cpp | 10 ++++++---- src/ArduinoIoTCloudTCP.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index b8eafb9ff..c657993c1 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -762,14 +762,16 @@ void ArduinoIoTCloudTCP::sendPropertiesToCloud() } #if OTA_ENABLED -void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud() +void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud(bool include_ota_req) { PropertyContainer ota_property_container; unsigned int last_ota_property_index = 0; - std::list const ota_property_list {"OTA_CAP", "OTA_ERROR", "OTA_SHA256"}; - std::for_each(ota_property_list.cbegin(), - ota_property_list.cend(), + std::list ota_property_list {"OTA_CAP", "OTA_ERROR", "OTA_SHA256"}; + if (include_ota_req) + ota_property_list.push_back("OTA_REQ"); + std::for_each(ota_property_list.begin(), + ota_property_list.end(), [this, &ota_property_container ] (String const & name) { Property* p = getProperty(this->_device_property_container, name); diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 861482f5e..dd7c3ebb8 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -189,7 +189,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #if OTA_ENABLED void onOTARequest(); - void sendOTAPropertiesToCloud(); + void sendOTAPropertiesToCloud(bool include_ota_req = false); #endif void updateThingTopics(); From 48494faa610869eaf2faee63b9e4b9bbb5dedfa2 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 10 Dec 2021 16:22:47 +0100 Subject: [PATCH 261/780] Execute handle_CheckDeviceConfig() only on thing_id changes ignoring other messages on device topic --- src/ArduinoIoTCloudTCP.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index c657993c1..1c2459c5c 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -326,6 +326,11 @@ void ArduinoIoTCloudTCP::update() #endif + if(getThingIdOutdatedFlag()) { + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s Thing id outdated, reconfiguring...", __FUNCTION__); + _state = State::CheckDeviceConfig; + } + /* Run through the state machine. */ State next_state = _state; switch (_state) @@ -476,7 +481,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() return State::SubscribeDeviceTopic; } } - return State::WaitDeviceConfig; } @@ -490,16 +494,13 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() return State::ConnectPhy; } - if(getThingIdOutdatedFlag()) + if(_deviceSubscribedToThing == true) { - if(_deviceSubscribedToThing == true) - { - /* Unsubscribe from old things topics and go on with a new subsctiption */ - _mqttClient.unsubscribe(_shadowTopicIn); - _mqttClient.unsubscribe(_dataTopicIn); + /* Unsubscribe from old things topics and go on with a new subsctiption */ + _mqttClient.unsubscribe(_shadowTopicIn); + _mqttClient.unsubscribe(_dataTopicIn); - _deviceSubscribedToThing = false; - } + _deviceSubscribedToThing = false; } updateThingTopics(); @@ -716,7 +717,6 @@ void ArduinoIoTCloudTCP::handleMessage(int length) CBORDecoder::decode(_device_property_container, (uint8_t*)bytes, length); _last_device_subscribe_cnt = 0; _next_device_subscribe_attempt_tick = 0; - _state = State::CheckDeviceConfig; } /* Topic for user input data */ From 65b82e6f8f2dd19d676ed5e5d9a258b32ae73baa Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 23 Dec 2021 14:52:02 +0100 Subject: [PATCH 262/780] Do not try to reconfigure device if connection is dropped --- src/ArduinoIoTCloudTCP.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 1c2459c5c..b69484e29 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -328,7 +328,8 @@ void ArduinoIoTCloudTCP::update() if(getThingIdOutdatedFlag()) { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s Thing id outdated, reconfiguring...", __FUNCTION__); - _state = State::CheckDeviceConfig; + if (_mqttClient.connected()) + _state = State::CheckDeviceConfig; } /* Run through the state machine. */ From 850095ddda61743dcfdb7f6369ed9a36f28ce8b3 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 10 Jan 2022 09:53:54 +0100 Subject: [PATCH 263/780] There is no more distinction between not configured and not attached --- src/ArduinoIoTCloud.h | 3 +-- src/ArduinoIoTCloudTCP.cpp | 9 --------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index bad570c7e..ee1d4d812 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -100,8 +100,7 @@ class ArduinoIoTCloudClass inline void clrThingIdOutdatedFlag() { _thing_id_outdated = false ; } inline bool getThingIdOutdatedFlag() { return _thing_id_outdated; } - inline bool deviceNotAttached() { return _thing_id == "null"; } - inline bool deviceNotConfigured() { return _thing_id == ""; } + inline bool deviceNotAttached() { return _thing_id == ""; } inline ConnectionHandler * getConnection() { return _connection; } diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index b69484e29..fcfbd0613 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -506,15 +506,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() updateThingTopics(); - if (deviceNotConfigured()) - { - /* maybe we have only missed the thing_id property... - * unsubsribe and resubscribe immediately to trigger a new configuration command - */ - _mqttClient.unsubscribe(_deviceTopicIn); - return State::SubscribeDeviceTopic; - } - if (deviceNotAttached()) { /* start long timeout counter From 08964b394c84a5e93bd0a6d7721ca77a0740e3af Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 10 Jan 2022 11:22:09 +0100 Subject: [PATCH 264/780] Move thing_id outdated flag check outside update function and add handle_Disconnect() function --- src/ArduinoIoTCloud.cpp | 1 + src/ArduinoIoTCloudTCP.cpp | 76 ++++++++++++++++++-------------------- src/ArduinoIoTCloudTCP.h | 2 + 3 files changed, 39 insertions(+), 40 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index ff83facc1..91c5ac9d2 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -34,6 +34,7 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() , _thing_id{""} , _device_id{""} , _cloud_event_callback{nullptr} +, _thing_id_outdated{false} { } diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index fcfbd0613..52cadbd46 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -326,12 +326,6 @@ void ArduinoIoTCloudTCP::update() #endif - if(getThingIdOutdatedFlag()) { - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s Thing id outdated, reconfiguring...", __FUNCTION__); - if (_mqttClient.connected()) - _state = State::CheckDeviceConfig; - } - /* Run through the state machine. */ State next_state = _state; switch (_state) @@ -346,6 +340,7 @@ void ArduinoIoTCloudTCP::update() case State::SubscribeThingTopics: next_state = handle_SubscribeThingTopics(); break; case State::RequestLastValues: next_state = handle_RequestLastValues(); break; case State::Connected: next_state = handle_Connected(); break; + case State::Disconnect: next_state = handle_Disconnect(); break; } _state = next_state; @@ -420,10 +415,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SendDeviceProperties() { if (!_mqttClient.connected()) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); - _mqttClient.stop(); - execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - return State::ConnectPhy; + return State::Disconnect; } #if OTA_ENABLED @@ -436,10 +428,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() { if (!_mqttClient.connected()) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); - _mqttClient.stop(); - execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - return State::ConnectPhy; + return State::Disconnect; } if (!_mqttClient.subscribe(_deviceTopicIn)) @@ -468,10 +457,12 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() { if (!_mqttClient.connected()) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); - _mqttClient.stop(); - execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - return State::ConnectPhy; + return State::Disconnect; + } + + if (getThingIdOutdatedFlag()) + { + return State::CheckDeviceConfig; } if (millis() > _next_device_subscribe_attempt_tick) @@ -489,10 +480,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() { if (!_mqttClient.connected()) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); - _mqttClient.stop(); - execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - return State::ConnectPhy; + return State::Disconnect; } if(_deviceSubscribedToThing == true) @@ -527,10 +515,12 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() { if (!_mqttClient.connected()) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); - _mqttClient.stop(); - execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - return State::ConnectPhy; + return State::Disconnect; + } + + if (getThingIdOutdatedFlag()) + { + return State::CheckDeviceConfig; } unsigned long const now = millis(); @@ -583,10 +573,12 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() { if (!_mqttClient.connected()) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); - _mqttClient.stop(); - execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - return State::ConnectPhy; + return State::Disconnect; + } + + if (getThingIdOutdatedFlag()) + { + return State::CheckDeviceConfig; } /* Check whether or not we need to send a new request. */ @@ -620,22 +612,18 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() { if (!_mqttClient.connected()) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); - - /* Forcefully disconnect MQTT client and trigger a reconnection. */ - _mqttClient.stop(); - /* The last message was definitely lost, trigger a retransmit. */ _mqtt_data_request_retransmit = true; - - /* We are not connected anymore, trigger the callback for a disconnected event. */ - execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - - return State::ConnectPhy; + return State::Disconnect; } /* We are connected so let's to our stuff here. */ else { + if (getThingIdOutdatedFlag()) + { + return State::CheckDeviceConfig; + } + /* Check if a primitive property wrapper is locally changed. * This function requires an existing time service which in * turn requires an established connection. Not having that @@ -689,6 +677,14 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() } } +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect() +{ + DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); + _mqttClient.stop(); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + return State::ConnectPhy; +} + void ArduinoIoTCloudTCP::onMessage(int length) { ArduinoCloud.handleMessage(length); diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index dd7c3ebb8..103f10cff 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -112,6 +112,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass SubscribeThingTopics, RequestLastValues, Connected, + Disconnect, }; State _state; @@ -179,6 +180,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass State handle_SubscribeThingTopics(); State handle_RequestLastValues(); State handle_Connected(); + State handle_Disconnect(); static void onMessage(int length); void handleMessage(int length); From 95eeec8a89a52432442ba09c8959783da3ca28f4 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 3 Feb 2022 13:17:33 +0100 Subject: [PATCH 265/780] Use specific macros to define device topic subscription delays --- src/AIoTC_Config.h | 18 ++++++++++-------- src/ArduinoIoTCloudTCP.cpp | 19 ++++++++----------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 6949524d6..abcdd38ee 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -140,14 +140,16 @@ * CONSTANTS ******************************************************************************/ -#define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) -#define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) -#define AIOT_CONFIG_SUBSCRIBE_RETRY_DELAY_ms (1000UL) -#define AIOT_CONFIG_SUBSCRIBE_MAX_RETRY_CNT (10UL) -#define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) -#define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) - -#define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) +#define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) +#define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) +#define AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (5*1000UL) +#define AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (32000UL) +#define AIOT_CONFIG_SUBSCRIBE_RETRY_DELAY_ms (1000UL) +#define AIOT_CONFIG_SUBSCRIBE_MAX_RETRY_CNT (10UL) +#define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) +#define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) + +#define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) #endif /* ARDUINO_AIOTC_CONFIG_H_ */ diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 52cadbd46..6191b722e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -445,9 +445,10 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() return State::ConnectPhy; } - unsigned long reconnection_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms; - reconnection_retry_delay = min(reconnection_retry_delay, static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms)); - _next_device_subscribe_attempt_tick = millis() + reconnection_retry_delay; + /* No device configuration reply. Wait: 5s -> 10s -> 20s -> 30s */ + unsigned long subscribe_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms; + subscribe_retry_delay = min(subscribe_retry_delay, static_cast(AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms)); + _next_device_subscribe_attempt_tick = millis() + subscribe_retry_delay; _last_device_subscribe_cnt++; return State::WaitDeviceConfig; @@ -496,14 +497,10 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() if (deviceNotAttached()) { - /* start long timeout counter - * return return State::SubscribeThingTopics - * if long timeout expired unsubscribe and - * return State::SubscribeDeviceTopic - */ - unsigned long reconnection_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms * 10000; - reconnection_retry_delay = min(reconnection_retry_delay, static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms)); - _next_device_subscribe_attempt_tick = millis() + reconnection_retry_delay; + /* Configuration received but device not attached. Wait: 40s */ + unsigned long subscribe_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms * 10; + subscribe_retry_delay = min(subscribe_retry_delay, static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms * 10)); + _next_device_subscribe_attempt_tick = millis() + subscribe_retry_delay; _last_device_subscribe_cnt++; return State::WaitDeviceConfig; } From ae45d0c93c2dc6c07403acbe5669e3d3613c34bf Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 11 Jan 2022 11:05:38 +0100 Subject: [PATCH 266/780] Use incremental long delay before retry subscribtion when the device is not attached to a thing --- src/AIoTC_Config.h | 1 + src/ArduinoIoTCloudTCP.cpp | 15 +++++++++------ src/ArduinoIoTCloudTCP.h | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index abcdd38ee..363c3a070 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -146,6 +146,7 @@ #define AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (32000UL) #define AIOT_CONFIG_SUBSCRIBE_RETRY_DELAY_ms (1000UL) #define AIOT_CONFIG_SUBSCRIBE_MAX_RETRY_CNT (10UL) +#define AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (1280000UL) #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 6191b722e..65b7d02f3 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -468,7 +468,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() if (millis() > _next_device_subscribe_attempt_tick) { - /* Configuration not received try to resubscribe */ + /* Configuration not received or device not attached to a valid thing. Try to resubscribe */ if (_mqttClient.unsubscribe(_deviceTopicIn)) { return State::SubscribeDeviceTopic; @@ -489,7 +489,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() /* Unsubscribe from old things topics and go on with a new subsctiption */ _mqttClient.unsubscribe(_shadowTopicIn); _mqttClient.unsubscribe(_dataTopicIn); - _deviceSubscribedToThing = false; } @@ -498,13 +497,16 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() if (deviceNotAttached()) { /* Configuration received but device not attached. Wait: 40s */ - unsigned long subscribe_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms * 10; - subscribe_retry_delay = min(subscribe_retry_delay, static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms * 10)); - _next_device_subscribe_attempt_tick = millis() + subscribe_retry_delay; - _last_device_subscribe_cnt++; + unsigned long attach_retry_delay = (1 << _last_device_attach_cnt) * AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms; + attach_retry_delay = min(attach_retry_delay, static_cast(AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms)); + _next_device_subscribe_attempt_tick = millis() + attach_retry_delay; + _last_device_attach_cnt++; return State::WaitDeviceConfig; } + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s Device attached to a new valid Thing %s", __FUNCTION__, getThingId().c_str()); + _last_device_attach_cnt = 0; + return State::SubscribeThingTopics; } @@ -563,6 +565,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); _deviceSubscribedToThing = true; + /*Add retry wait time otherwise we are trying to reconnect every 250ms...*/ return State::RequestLastValues; } diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 103f10cff..79e43aaed 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -121,6 +121,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass unsigned int _last_connection_attempt_cnt; unsigned long _next_device_subscribe_attempt_tick; unsigned int _last_device_subscribe_cnt; + unsigned int _last_device_attach_cnt; unsigned long _last_sync_request_tick; unsigned int _last_sync_request_cnt; unsigned long _last_subscribe_request_tick; From 221b176ba3a2ee7147185fb87aef1798fa5fc3dc Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 24 Jan 2022 16:25:10 +0100 Subject: [PATCH 267/780] Add LIB_VERSION property to let cloud decide to use thing_topic or device_topic for OTA properties --- src/AIoTC_Config.h | 2 ++ src/ArduinoIoTCloud.cpp | 1 + src/ArduinoIoTCloud.h | 1 + src/ArduinoIoTCloudTCP.cpp | 3 ++- 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 363c3a070..6fb33ba43 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -153,4 +153,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) +#define AIOT_CONFIG_LIB_VERSION "1.5.0" + #endif /* ARDUINO_AIOTC_CONFIG_H_ */ diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 91c5ac9d2..0b2794ade 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -33,6 +33,7 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() , _tz_dst_until{0} , _thing_id{""} , _device_id{""} +, _lib_version{AIOT_CONFIG_LIB_VERSION} , _cloud_event_callback{nullptr} , _thing_id_outdated{false} { diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index ee1d4d812..8be318b25 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -174,6 +174,7 @@ class ArduinoIoTCloudClass int _tz_offset; unsigned int _tz_dst_until; String _thing_id; + String _lib_version; void execCloudEventCallback(ArduinoIoTCloudEvent const event); diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 65b7d02f3..fa47c0c6a 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -250,6 +250,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _deviceTopicOut = getTopic_deviceout(); _deviceTopicIn = getTopic_devicein(); + addPropertyReal(_lib_version, _device_property_container, "LIB_VERSION", Permission::Read); #if OTA_ENABLED addPropertyReal(_ota_cap, _device_property_container, "OTA_CAP", Permission::Read); addPropertyReal(_ota_error, _device_property_container, "OTA_ERROR", Permission::Read); @@ -755,7 +756,7 @@ void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud(bool include_ota_req) PropertyContainer ota_property_container; unsigned int last_ota_property_index = 0; - std::list ota_property_list {"OTA_CAP", "OTA_ERROR", "OTA_SHA256"}; + std::list ota_property_list {"LIB_VERSION", "OTA_CAP", "OTA_ERROR", "OTA_SHA256"}; if (include_ota_req) ota_property_list.push_back("OTA_REQ"); std::for_each(ota_property_list.begin(), From 4aa628a70f10e2338d83d074f4383b8b6ffb8aaf Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 24 Jan 2022 16:31:28 +0100 Subject: [PATCH 268/780] Spit sendPropertiesToCloud() in sendThingPropertiesToCloud() and sendDevicePropertiesToCloud(). Provide functions to clear OTA_REQ flag and update OTA_ERROR and OTA_URL. --- src/ArduinoIoTCloudTCP.cpp | 85 ++++++++++++++++++++++++++++++++------ src/ArduinoIoTCloudTCP.h | 7 +++- 2 files changed, 77 insertions(+), 15 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index fa47c0c6a..607db79f1 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -261,7 +261,6 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, addPropertyReal(_tz_offset, _thing_property_container, "tz_offset", Permission::ReadWrite).onSync(CLOUD_WINS).onUpdate(updateTimezoneInfo); addPropertyReal(_tz_dst_until, _thing_property_container, "tz_dst_until", Permission::ReadWrite).onSync(CLOUD_WINS).onUpdate(updateTimezoneInfo); - addPropertyReal(_thing_id, _device_property_container, "thing_id", Permission::ReadWrite).onUpdate(setThingIdOutdated); #if OTA_STORAGE_PORTENTA_QSPI @@ -419,9 +418,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SendDeviceProperties() return State::Disconnect; } -#if OTA_ENABLED - sendOTAPropertiesToCloud(); -#endif + sendDevicePropertiesToCloud(); return State::SubscribeDeviceTopic; } @@ -656,18 +653,26 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() _ota_error = static_cast(OTAError::None); /* Clear the request flag. */ _ota_req = false; - /* Transmit the cleared error and request flags to the cloud. */ - sendOTAPropertiesToCloud(); + /* Transmit the cleared request flags to the cloud. */ + sendClearedOTARequestToCloud(); /* Call member function to handle OTA request. */ onOTARequest(); + /* If something fails send the OTA error to the cloud */ + sendOTAErrorToCloud(); } } + + /* Check if we have received the OTA_URL property and provide + * echo to the cloud. + */ + sendOTAUrlToCloud(); + #endif /* OTA_ENABLED */ /* Check if any properties need encoding and send them to * the cloud if necessary. */ - sendPropertiesToCloud(); + sendThingPropertiesToCloud(); unsigned long const internal_posix_time = _time_service.getTime(); if(internal_posix_time < _tz_dst_until) { @@ -718,7 +723,6 @@ void ArduinoIoTCloudTCP::handleMessage(int length) { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); CBORDecoder::decode(_thing_property_container, (uint8_t*)bytes, length, true); - sendPropertiesToCloud(); _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); _last_sync_request_cnt = 0; @@ -745,20 +749,75 @@ void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(String const topic, Proper } } -void ArduinoIoTCloudTCP::sendPropertiesToCloud() +void ArduinoIoTCloudTCP::sendThingPropertiesToCloud() { sendPropertyContainerToCloud(_dataTopicOut, _thing_property_container, _last_checked_property_index); } +void ArduinoIoTCloudTCP::sendDevicePropertiesToCloud() +{ + PropertyContainer ro_device_property_container; + unsigned int last_device_property_index = 0; + + std::list ro_device_property_list {"LIB_VERSION", "OTA_CAP", "OTA_ERROR", "OTA_SHA256"}; + std::for_each(ro_device_property_list.begin(), + ro_device_property_list.end(), + [this, &ro_device_property_container ] (String const & name) + { + Property* p = getProperty(this->_device_property_container, name); + if(p != nullptr) + addPropertyToContainer(ro_device_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); + } + ); + + sendPropertyContainerToCloud(_deviceTopicOut, ro_device_property_container, last_device_property_index); +} + #if OTA_ENABLED -void ArduinoIoTCloudTCP::sendOTAPropertiesToCloud(bool include_ota_req) +void ArduinoIoTCloudTCP::sendClearedOTARequestToCloud() +{ + PropertyContainer ota_property_container; + unsigned int last_ota_property_index = 0; + + std::list ota_property_list {"OTA_REQ"}; + std::for_each(ota_property_list.begin(), + ota_property_list.end(), + [this, &ota_property_container ] (String const & name) + { + Property* p = getProperty(this->_device_property_container, name); + if(p != nullptr) + addPropertyToContainer(ota_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); + } + ); + + sendPropertyContainerToCloud(_deviceTopicOut, ota_property_container, last_ota_property_index); +} + +void ArduinoIoTCloudTCP::sendOTAErrorToCloud() +{ + PropertyContainer ota_property_container; + unsigned int last_ota_property_index = 0; + + std::list ota_property_list {"OTA_ERROR"}; + std::for_each(ota_property_list.begin(), + ota_property_list.end(), + [this, &ota_property_container ] (String const & name) + { + Property* p = getProperty(this->_device_property_container, name); + if(p != nullptr) + addPropertyToContainer(ota_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); + } + ); + + sendPropertyContainerToCloud(_deviceTopicOut, ota_property_container, last_ota_property_index); +} + +void ArduinoIoTCloudTCP::sendOTAUrlToCloud() { PropertyContainer ota_property_container; unsigned int last_ota_property_index = 0; - std::list ota_property_list {"LIB_VERSION", "OTA_CAP", "OTA_ERROR", "OTA_SHA256"}; - if (include_ota_req) - ota_property_list.push_back("OTA_REQ"); + std::list ota_property_list {"OTA_URL"}; std::for_each(ota_property_list.begin(), ota_property_list.end(), [this, &ota_property_container ] (String const & name) diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 79e43aaed..787df535c 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -186,13 +186,16 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass static void onMessage(int length); void handleMessage(int length); void sendPropertyContainerToCloud(String const topic, PropertyContainer & property_container, unsigned int & current_property_index); - void sendPropertiesToCloud(); + void sendThingPropertiesToCloud(); + void sendDevicePropertiesToCloud(); void requestLastValue(); int write(String const topic, byte const data[], int const length); #if OTA_ENABLED void onOTARequest(); - void sendOTAPropertiesToCloud(bool include_ota_req = false); + void sendClearedOTARequestToCloud(); + void sendOTAErrorToCloud(); + void sendOTAUrlToCloud(); #endif void updateThingTopics(); From 0ebefe8e97ccff39f31c5e65a951d0a85e269aee Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 24 Jan 2022 15:33:18 +0100 Subject: [PATCH 269/780] Remove the onSync callback end event from device properties --- src/ArduinoIoTCloudTCP.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 607db79f1..ceb4391f7 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -255,8 +255,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, addPropertyReal(_ota_cap, _device_property_container, "OTA_CAP", Permission::Read); addPropertyReal(_ota_error, _device_property_container, "OTA_ERROR", Permission::Read); addPropertyReal(_ota_img_sha256, _device_property_container, "OTA_SHA256", Permission::Read); - addPropertyReal(_ota_url, _device_property_container, "OTA_URL", Permission::ReadWrite).onSync(CLOUD_WINS); - addPropertyReal(_ota_req, _device_property_container, "OTA_REQ", Permission::ReadWrite).onSync(CLOUD_WINS); + addPropertyReal(_ota_url, _device_property_container, "OTA_URL", Permission::ReadWrite); + addPropertyReal(_ota_req, _device_property_container, "OTA_REQ", Permission::ReadWrite); #endif /* OTA_ENABLED */ addPropertyReal(_tz_offset, _thing_property_container, "tz_offset", Permission::ReadWrite).onSync(CLOUD_WINS).onUpdate(updateTimezoneInfo); From 366bde189317bf1eb0a62447da2b5ad57b795d86 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 24 Jan 2022 15:33:54 +0100 Subject: [PATCH 270/780] Use a single function to keep OTA properties in sync with cloud --- src/ArduinoIoTCloudTCP.cpp | 68 +++++++------------------------------- src/ArduinoIoTCloudTCP.h | 4 +-- 2 files changed, 13 insertions(+), 59 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index ceb4391f7..e76651309 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -654,18 +654,18 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() /* Clear the request flag. */ _ota_req = false; /* Transmit the cleared request flags to the cloud. */ - sendClearedOTARequestToCloud(); + sendDevicePropertyToCloud("OTA_REQ"); /* Call member function to handle OTA request. */ onOTARequest(); /* If something fails send the OTA error to the cloud */ - sendOTAErrorToCloud(); + sendDevicePropertyToCloud("OTA_ERROR"); } } /* Check if we have received the OTA_URL property and provide * echo to the cloud. */ - sendOTAUrlToCloud(); + sendDevicePropertyToCloud("OTA_URL"); #endif /* OTA_ENABLED */ @@ -774,61 +774,17 @@ void ArduinoIoTCloudTCP::sendDevicePropertiesToCloud() } #if OTA_ENABLED -void ArduinoIoTCloudTCP::sendClearedOTARequestToCloud() +void ArduinoIoTCloudTCP::sendDevicePropertyToCloud(String const name) { - PropertyContainer ota_property_container; - unsigned int last_ota_property_index = 0; - - std::list ota_property_list {"OTA_REQ"}; - std::for_each(ota_property_list.begin(), - ota_property_list.end(), - [this, &ota_property_container ] (String const & name) - { - Property* p = getProperty(this->_device_property_container, name); - if(p != nullptr) - addPropertyToContainer(ota_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); - } - ); - - sendPropertyContainerToCloud(_deviceTopicOut, ota_property_container, last_ota_property_index); -} - -void ArduinoIoTCloudTCP::sendOTAErrorToCloud() -{ - PropertyContainer ota_property_container; - unsigned int last_ota_property_index = 0; - - std::list ota_property_list {"OTA_ERROR"}; - std::for_each(ota_property_list.begin(), - ota_property_list.end(), - [this, &ota_property_container ] (String const & name) - { - Property* p = getProperty(this->_device_property_container, name); - if(p != nullptr) - addPropertyToContainer(ota_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); - } - ); - - sendPropertyContainerToCloud(_deviceTopicOut, ota_property_container, last_ota_property_index); -} - -void ArduinoIoTCloudTCP::sendOTAUrlToCloud() -{ - PropertyContainer ota_property_container; - unsigned int last_ota_property_index = 0; - - std::list ota_property_list {"OTA_URL"}; - std::for_each(ota_property_list.begin(), - ota_property_list.end(), - [this, &ota_property_container ] (String const & name) - { - Property* p = getProperty(this->_device_property_container, name); - if(p != nullptr) - addPropertyToContainer(ota_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); - } - ); + PropertyContainer temp_device_property_container; + unsigned int last_device_property_index = 0; - sendPropertyContainerToCloud(_deviceTopicOut, ota_property_container, last_ota_property_index); + Property* p = getProperty(this->_device_property_container, name); + if(p != nullptr) + { + addPropertyToContainer(temp_device_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); + sendPropertyContainerToCloud(_deviceTopicOut, temp_device_property_container, last_device_property_index); + } } #endif diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 787df535c..b704f6762 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -193,9 +193,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #if OTA_ENABLED void onOTARequest(); - void sendClearedOTARequestToCloud(); - void sendOTAErrorToCloud(); - void sendOTAUrlToCloud(); + void sendDevicePropertyToCloud(String const name); #endif void updateThingTopics(); From e0a1d5ac4a93ee2818af081f1f6669697c7a183b Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 24 Jan 2022 17:32:14 +0100 Subject: [PATCH 271/780] Use better define name to distinguish between topic and device SUBSCRIBE_RETRY_DELAY --- src/AIoTC_Config.h | 4 ++-- src/ArduinoIoTCloudTCP.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 6fb33ba43..eed12f5fc 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -144,8 +144,8 @@ #define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) #define AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (5*1000UL) #define AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (32000UL) -#define AIOT_CONFIG_SUBSCRIBE_RETRY_DELAY_ms (1000UL) -#define AIOT_CONFIG_SUBSCRIBE_MAX_RETRY_CNT (10UL) +#define AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_RETRY_DELAY_ms (1000UL) +#define AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_MAX_RETRY_CNT (10UL) #define AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (1280000UL) #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e76651309..88081c8a9 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -521,7 +521,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() } unsigned long const now = millis(); - bool const is_subscribe_retry_delay_expired = (now - _last_subscribe_request_tick) > AIOT_CONFIG_SUBSCRIBE_RETRY_DELAY_ms; + bool const is_subscribe_retry_delay_expired = (now - _last_subscribe_request_tick) > AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_RETRY_DELAY_ms; bool const is_first_subscribe_request = (_last_subscribe_request_cnt == 0); if (!is_first_subscribe_request && !is_subscribe_retry_delay_expired) @@ -529,7 +529,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() return State::SubscribeThingTopics; } - if (_last_subscribe_request_cnt > AIOT_CONFIG_SUBSCRIBE_MAX_RETRY_CNT) + if (_last_subscribe_request_cnt > AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_MAX_RETRY_CNT) { _last_subscribe_request_cnt = 0; _last_subscribe_request_tick = 0; From 12d3b26ca01708211aefc98329a8b5a9de5f4880 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 3 Feb 2022 13:36:16 +0100 Subject: [PATCH 272/780] Remove extern C declaration from local module functions --- src/ArduinoIoTCloudLPWAN.cpp | 2 +- src/ArduinoIoTCloudTCP.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index fbc42b628..0f96d36db 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -37,7 +37,7 @@ static size_t const CBOR_LORA_MSG_MAX_SIZE = 255; LOCAL MODULE FUNCTIONS ******************************************************************************/ -extern "C" unsigned long getTime() +unsigned long getTime() { return ArduinoCloud.getInternalTime(); } diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 88081c8a9..964152a8d 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -59,17 +59,17 @@ extern RTC_HandleTypeDef RTCHandle; LOCAL MODULE FUNCTIONS ******************************************************************************/ -extern "C" unsigned long getTime() +unsigned long getTime() { return ArduinoCloud.getInternalTime(); } -extern "C" void updateTimezoneInfo() +void updateTimezoneInfo() { ArduinoCloud.updateInternalTimezoneInfo(); } -extern "C" void setThingIdOutdated() +void setThingIdOutdated() { ArduinoCloud.setThingIdOutdatedFlag(); } From c35be6f4d5bf97210d2518448ff0dd5c9c83e06d Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 3 Feb 2022 14:08:05 +0100 Subject: [PATCH 273/780] Do not print Thing ID at startup because its value will be ignored --- src/ArduinoIoTCloudTCP.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 964152a8d..6329b68ef 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -366,7 +366,6 @@ void ArduinoIoTCloudTCP::printDebugInfo() { DEBUG_INFO("***** Arduino IoT Cloud - configuration info *****"); DEBUG_INFO("Device ID: %s", getDeviceId().c_str()); - DEBUG_INFO("Thing ID: %s", getThingId().c_str()); DEBUG_INFO("MQTT Broker: %s:%d", _brokerAddress.c_str(), _brokerPort); } From c9cd3f51e2d5251f2cf4dd2b2bef1136aa7b1ee5 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 3 Feb 2022 15:38:22 +0100 Subject: [PATCH 274/780] Print Thing ID on serial monitor when board connects to the cloud --- src/ArduinoIoTCloudTCP.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 6329b68ef..554c48ce0 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -559,6 +559,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() } DEBUG_INFO("Connected to Arduino IoT Cloud"); + DEBUG_INFO("Thing ID: %s", getThingId().c_str()); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); _deviceSubscribedToThing = true; From d3734054b07615bb543218345f6915e043b7618e Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 3 Feb 2022 15:40:26 +0100 Subject: [PATCH 275/780] Call DISCONNECT event when device is detached from a thing and print "Disconnected from Arduino IoT Cloud" on serial monitor --- src/ArduinoIoTCloudTCP.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 554c48ce0..b00670811 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -487,6 +487,8 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() _mqttClient.unsubscribe(_shadowTopicIn); _mqttClient.unsubscribe(_dataTopicIn); _deviceSubscribedToThing = false; + DEBUG_INFO("Disconnected from Arduino IoT Cloud"); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); } updateThingTopics(); From 4a121ae40ee60fd76e021f15327ab4b29df31e8b Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 8 Feb 2022 11:07:05 +0100 Subject: [PATCH 276/780] Add DEBUG_ERROR if device fails to subscribe to _deviceTopicIn --- src/ArduinoIoTCloudTCP.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index b00670811..7958ff71e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -430,6 +430,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() if (!_mqttClient.subscribe(_deviceTopicIn)) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _deviceTopicIn.c_str()); return State::SubscribeDeviceTopic; } From 93d6fa85ebcb7a836afd241f6207b823cffec29f Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 8 Feb 2022 11:38:28 +0100 Subject: [PATCH 277/780] Add DEBUG_ERROR if device is not receiving a valid thing_id from the cloud --- src/ArduinoIoTCloudTCP.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 7958ff71e..ed0e46cd4 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -469,6 +469,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() /* Configuration not received or device not attached to a valid thing. Try to resubscribe */ if (_mqttClient.unsubscribe(_deviceTopicIn)) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s device waiting for valid thing_id", __FUNCTION__); return State::SubscribeDeviceTopic; } } From 57a6cacb7b4a0645ec3f54b7e804db0725708d27 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Tue, 8 Feb 2022 13:38:44 +0100 Subject: [PATCH 278/780] Release v1.5.0 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 37dff6432..5c57a7b07 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.4.1 +version=1.5.0 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. From e9c5059ac938d5380cbae175177bf460f36acfb5 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 9 Feb 2022 17:10:36 +0100 Subject: [PATCH 279/780] ArduinoIoTCloudCertClass: Add Generic cert class to produce ArduinoIoTCloud certificates --- src/tls/utility/Cert.cpp | 912 +++++++++++++++++++++++++++++++++++++++ src/tls/utility/Cert.h | 189 ++++++++ 2 files changed, 1101 insertions(+) create mode 100644 src/tls/utility/Cert.cpp create mode 100644 src/tls/utility/Cert.h diff --git a/src/tls/utility/Cert.cpp b/src/tls/utility/Cert.cpp new file mode 100644 index 000000000..39ed76253 --- /dev/null +++ b/src/tls/utility/Cert.cpp @@ -0,0 +1,912 @@ +/* + This file is part of the ArduinoECCX08 library. + Copyright (c) 2019 Arduino SA. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include + +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) + +#include "Cert.h" + +/****************************************************************************** + * DEFINE + ******************************************************************************/ + +#define ASN1_INTEGER 0x02 +#define ASN1_BIT_STRING 0x03 +#define ASN1_NULL 0x05 +#define ASN1_OBJECT_IDENTIFIER 0x06 +#define ASN1_PRINTABLE_STRING 0x13 +#define ASN1_SEQUENCE 0x30 +#define ASN1_SET 0x31 + +/****************************************************************************** + * LOCAL MODULE FUNCTIONS + ******************************************************************************/ + +static String base64Encode(const byte in[], unsigned int length, const char* prefix, const char* suffix) { + static const char* CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + + int b; + String out; + + int reserveLength = 4 * ((length + 2) / 3) + ((length / 3 * 4) / 76) + strlen(prefix) + strlen(suffix); + out.reserve(reserveLength); + + if (prefix) { + out += prefix; + } + + for (unsigned int i = 0; i < length; i += 3) { + if (i > 0 && (i / 3 * 4) % 76 == 0) { + out += '\n'; + } + + b = (in[i] & 0xFC) >> 2; + out += CODES[b]; + + b = (in[i] & 0x03) << 4; + if (i + 1 < length) { + b |= (in[i + 1] & 0xF0) >> 4; + out += CODES[b]; + b = (in[i + 1] & 0x0F) << 2; + if (i + 2 < length) { + b |= (in[i + 2] & 0xC0) >> 6; + out += CODES[b]; + b = in[i + 2] & 0x3F; + out += CODES[b]; + } else { + out += CODES[b]; + out += '='; + } + } else { + out += CODES[b]; + out += "=="; + } + } + + if (suffix) { + out += suffix; + } + + return out; +} + +/****************************************************************************** + * CTOR/DTOR + ******************************************************************************/ + +ArduinoIoTCloudCertClass::ArduinoIoTCloudCertClass() +: _certBuffer(NULL) +, _certBufferLen(0) +{ + +} + +ArduinoIoTCloudCertClass::~ArduinoIoTCloudCertClass() +{ + if (_certBuffer) { + free(_certBuffer); + _certBuffer = NULL; + } +} + +/****************************************************************************** + * PUBLIC MEMBER FUNCTIONS + ******************************************************************************/ + +int ArduinoIoTCloudCertClass::begin() +{ + memset(_compressedCert.data, 0x00, CERT_COMPRESSED_CERT_LENGTH); + memset(_publicKey, 0x00, CERT_PUBLIC_KEY_LENGTH); + return 1; +} + +int ArduinoIoTCloudCertClass::buildCSR() +{ + int csrInfoLen = CSRInfoLength(); + int subjectLen = issuerOrSubjectLength(_subjectData); + + _certBufferLen = getCSRSize(); + _certBuffer = (byte*)malloc(_certBufferLen); + + if (_certBuffer == nullptr) { + return 0; + } + + byte* out = _certBuffer; + + // header + out += appendSequenceHeader(csrInfoLen, out); + + // version + out += appendVersion(0x00, out); + + // subject + out += appendSequenceHeader(subjectLen, out); + out += appendIssuerOrSubject(_subjectData, out); + + // public key + out += appendPublicKey(_publicKey, out); + + // terminator + *out++ = 0xa0; + *out++ = 0x00; + + return 1; +} + +int ArduinoIoTCloudCertClass::signCSR(byte * signature) +{ + /* copy old certbuffer in a temp buffer */ + byte* tempBuffer = (byte*)malloc(_certBufferLen); + + if (tempBuffer == nullptr) { + return 0; + } + + memcpy(tempBuffer, _certBuffer, _certBufferLen); + + _certBufferLen = getCSRSignedSize(signature); + _certBuffer = (byte*)realloc(_certBuffer, _certBufferLen); + + if (_certBuffer == nullptr) { + return 0; + } + + byte* out = _certBuffer; + + // header + out += appendSequenceHeader(getCSRSize() + signatureLength(signature), out); + + // info + memcpy(out, tempBuffer, getCSRSize()); + free(tempBuffer); + out += getCSRSize(); + + // signature + out += appendSignature(signature, out); + + return 1; +} + +String ArduinoIoTCloudCertClass::getCSRPEM() +{ + return base64Encode(_certBuffer, _certBufferLen, "-----BEGIN CERTIFICATE REQUEST-----\n", "\n-----END CERTIFICATE REQUEST-----\n"); +} + +int ArduinoIoTCloudCertClass::buildCert() +{ + _certBufferLen = getCertSize(); + _certBuffer = (byte*)malloc(_certBufferLen); + + if (_certBuffer == nullptr) { + return 0; + } + + uint8_t* out = _certBuffer; + + int certInfoLen = certInfoLength(); + + // header + out += appendSequenceHeader(certInfoLen, out); + + // version + *out++ = 0xA0; + *out++ = 0x03; + *out++ = 0x02; + *out++ = 0x01; + *out++ = 0x02; + + // serial number + out += appendSerialNumber(_compressedCert.slot.two.values.serialNumber, CERT_SERIAL_NUMBER_LENGTH, out); + + // signature type + out += appendEcdsaWithSHA256(out); + + // issuer + int issuerDataLen = issuerOrSubjectLength(_issuerData); + out += appendSequenceHeader(issuerDataLen, out); + out += appendIssuerOrSubject(_issuerData, out); + + // dates + DateInfo dateData; + getDateFromCompressedData(dateData); + + *out++ = ASN1_SEQUENCE; + *out++ = 30 + ((dateData.issueYear > 2049) ? 2 : 0) + (((dateData.issueYear + dateData.expireYears) > 2049) ? 2 : 0); + out += appendDate(dateData.issueYear, dateData.issueMonth, dateData.issueDay, dateData.issueHour, 0, 0, out); + out += appendDate(dateData.issueYear + dateData.expireYears, dateData.issueMonth, dateData.issueDay, dateData.issueHour, 0, 0, out); + + // subject + int subjectDataLen = issuerOrSubjectLength(_subjectData); + out += appendSequenceHeader(subjectDataLen, out); + out += appendIssuerOrSubject(_subjectData, out); + + // public key + out += appendPublicKey(_publicKey, out); + + int authorityKeyIdLen = authorityKeyIdLength(_compressedCert.slot.two.values.authorityKeyId, CERT_AUTHORITY_KEY_ID_LENGTH); + if (authorityKeyIdLen) + { + out += appendAuthorityKeyId(_compressedCert.slot.two.values.authorityKeyId, CERT_AUTHORITY_KEY_ID_LENGTH, out); + } + else + { + // null sequence + *out++ = 0xA3; + *out++ = 0x02; + *out++ = 0x30; + *out++ = 0x00; + } + + return 1; +} + +int ArduinoIoTCloudCertClass::signCert(const byte * signature) +{ + /* copy old certbuffer in a temp buffer */ + byte* tempBuffer = (byte*)malloc(_certBufferLen); + + if (tempBuffer == nullptr) { + return 0; + } + + memcpy(tempBuffer, _certBuffer, _certBufferLen); + + _certBufferLen = getCertSignedSize(signature); + _certBuffer = (byte*)realloc(_certBuffer, _certBufferLen); + + if (_certBuffer == nullptr) { + return 0; + } + + byte* out = _certBuffer; + + // header + out +=appendSequenceHeader(getCertSize() + signatureLength(signature), out); + + // info + memcpy(out, tempBuffer, getCertSize()); + free(tempBuffer); + out += getCertSize(); + + // signature + out += appendSignature(signature, out); + + return 1; +} + +int ArduinoIoTCloudCertClass::importCert(const byte certDER[], size_t derLen) +{ + _certBufferLen = derLen; + _certBuffer = (byte*)malloc(_certBufferLen); + + if (_certBuffer == nullptr) { + return 0; + } + + memcpy(_certBuffer, certDER, _certBufferLen); + + return 1; +} + +int ArduinoIoTCloudCertClass::signCert() +{ + return signCert(_compressedCert.slot.one.values.signature); +} + +String ArduinoIoTCloudCertClass::getCertPEM() +{ + return base64Encode(_certBuffer, _certBufferLen, "-----BEGIN CERTIFICATE-----\n", "\n-----END CERTIFICATE-----\n"); +} + +void ArduinoIoTCloudCertClass::getDateFromCompressedData(DateInfo& date) { + date.issueYear = (_compressedCert.slot.one.values.dates[0] >> 3) + 2000; + date.issueMonth = ((_compressedCert.slot.one.values.dates[0] & 0x07) << 1) | (_compressedCert.slot.one.values.dates[1] >> 7); + date.issueDay = (_compressedCert.slot.one.values.dates[1] & 0x7c) >> 2; + date.issueHour = ((_compressedCert.slot.one.values.dates[1] & 0x03) << 3) | (_compressedCert.slot.one.values.dates[2] >> 5); + date.expireYears = (_compressedCert.slot.one.values.dates[2] & 0x1f); +} + +void ArduinoIoTCloudCertClass::setIssueYear(int issueYear) { + _compressedCert.slot.one.values.dates[0] &= 0x07; + _compressedCert.slot.one.values.dates[0] |= (issueYear - 2000) << 3; +} + +void ArduinoIoTCloudCertClass::setIssueMonth(int issueMonth) { + _compressedCert.slot.one.values.dates[0] &= 0xf8; + _compressedCert.slot.one.values.dates[0] |= issueMonth >> 1; + + _compressedCert.slot.one.values.dates[1] &= 0x7f; + _compressedCert.slot.one.values.dates[1] |= issueMonth << 7; +} + +void ArduinoIoTCloudCertClass::setIssueDay(int issueDay) { + _compressedCert.slot.one.values.dates[1] &= 0x83; + _compressedCert.slot.one.values.dates[1] |= issueDay << 2; +} + +void ArduinoIoTCloudCertClass::setIssueHour(int issueHour) { + _compressedCert.slot.one.values.dates[2] &= 0x1f; + _compressedCert.slot.one.values.dates[2] |= issueHour << 5; + + _compressedCert.slot.one.values.dates[1] &= 0xfc; + _compressedCert.slot.one.values.dates[1] |= issueHour >> 3; +} + +void ArduinoIoTCloudCertClass::setExpireYears(int expireYears) { + _compressedCert.slot.one.values.dates[2] &= 0xe0; + _compressedCert.slot.one.values.dates[2] |= expireYears; +} + +int ArduinoIoTCloudCertClass::setSerialNumber(const uint8_t serialNumber[], int serialNumberLen) { + if (serialNumberLen == CERT_SERIAL_NUMBER_LENGTH) { + memcpy(_compressedCert.slot.two.values.serialNumber, serialNumber, CERT_SERIAL_NUMBER_LENGTH); + return 1; + } + return 0; +} + +int ArduinoIoTCloudCertClass::setAuthorityKeyId(const uint8_t authorityKeyId[], int authorityKeyIdLen) { + if (authorityKeyIdLen == CERT_AUTHORITY_KEY_ID_LENGTH) { + memcpy(_compressedCert.slot.two.values.authorityKeyId, authorityKeyId, CERT_AUTHORITY_KEY_ID_LENGTH); + return 1; + } + return 0; +} + +int ArduinoIoTCloudCertClass::setPublicKey(const byte* publicKey, int publicKeyLen) { + if (publicKeyLen == CERT_PUBLIC_KEY_LENGTH) { + memcpy(_publicKey, publicKey, CERT_PUBLIC_KEY_LENGTH); + return 1; + } + return 0; +} + +int ArduinoIoTCloudCertClass::setSignature(const byte* signature, int signatureLen) { + if (signatureLen == CERT_SIGNATURE_LENGTH) { + memcpy(_compressedCert.slot.one.values.signature, signature, CERT_SIGNATURE_LENGTH); + return 1; + } + return 0; +} + +/****************************************************************************** + * PRIVATE MEMBER FUNCTIONS + ******************************************************************************/ + +int ArduinoIoTCloudCertClass::versionLength() +{ + return 3; +} + +int ArduinoIoTCloudCertClass::issuerOrSubjectLength(const CertInfo& issuerOrSubjectData) +{ + int length = 0; + int countryNameLength = issuerOrSubjectData.countryName.length(); + int stateProvinceNameLength = issuerOrSubjectData.stateProvinceName.length(); + int localityNameLength = issuerOrSubjectData.localityName.length(); + int organizationNameLength = issuerOrSubjectData.organizationName.length(); + int organizationalUnitNameLength = issuerOrSubjectData.organizationalUnitName.length(); + int commonNameLength = issuerOrSubjectData.commonName.length(); + + if (countryNameLength) { + length += (11 + countryNameLength); + } + + if (stateProvinceNameLength) { + length += (11 + stateProvinceNameLength); + } + + if (localityNameLength) { + length += (11 + localityNameLength); + } + + if (organizationNameLength) { + length += (11 + organizationNameLength); + } + + if (organizationalUnitNameLength) { + length += (11 + organizationalUnitNameLength); + } + + if (commonNameLength) { + length += (11 + commonNameLength); + } + + return length; +} + +int ArduinoIoTCloudCertClass::sequenceHeaderLength(int length) +{ + if (length > 255) { + return 4; + } else if (length > 127) { + return 3; + } else { + return 2; + } +} + +int ArduinoIoTCloudCertClass::publicKeyLength() +{ + return (2 + 2 + 9 + 10 + 4 + 64); +} + +int ArduinoIoTCloudCertClass::signatureLength(const byte signature[]) +{ + const byte* r = &signature[0]; + const byte* s = &signature[32]; + + int rLength = 32; + int sLength = 32; + + while (*r == 0x00 && rLength) { + r++; + rLength--; + } + + if (*r & 0x80) { + rLength++; + } + + while (*s == 0x00 && sLength) { + s++; + sLength--; + } + + if (*s & 0x80) { + sLength++; + } + + return (21 + rLength + sLength); +} + +int ArduinoIoTCloudCertClass::serialNumberLength(const byte serialNumber[], int length) +{ + while (*serialNumber == 0 && length) { + serialNumber++; + length--; + } + + if (*serialNumber & 0x80) { + length++; + } + + return (2 + length); +} + +int ArduinoIoTCloudCertClass::authorityKeyIdLength(const byte authorityKeyId[], int length) { + bool set = false; + + // check if the authority key identifier is non-zero + for (int i = 0; i < length; i++) { + if (authorityKeyId[i] != 0) { + set = true; + break; + } + } + + return (set ? (length + 17) : 0); +} + +int ArduinoIoTCloudCertClass::CSRInfoLength() +{ + int versionLen = versionLength(); + int subjectLen = issuerOrSubjectLength(_subjectData); + int subjectHeaderLen = sequenceHeaderLength(subjectLen); + int publicKeyLen = publicKeyLength(); + + int csrInfoLen = versionLen + subjectHeaderLen + subjectLen + publicKeyLen + 2; + + return csrInfoLen; +} + +int ArduinoIoTCloudCertClass::getCSRSize() +{ + int csrInfoLen = CSRInfoLength(); + int csrInfoHeaderLen = sequenceHeaderLength(csrInfoLen); + + return (csrInfoLen + csrInfoHeaderLen); +} + +int ArduinoIoTCloudCertClass::getCSRSignedSize(byte * signature) +{ + int signatureLen = signatureLength(signature); + int csrLen = getCSRSize() + signatureLen; + return sequenceHeaderLength(csrLen) + csrLen; +} + +int ArduinoIoTCloudCertClass::certInfoLength() +{ + int datesSizeLen = 30; + DateInfo dates; + + getDateFromCompressedData(dates); + + if (dates.issueYear > 2049) { + // two more bytes for GeneralizedTime + datesSizeLen += 2; + } + + if ((dates.issueYear + dates.expireYears) > 2049) { + // two more bytes for GeneralizedTime + datesSizeLen += 2; + } + + int serialNumberLen = serialNumberLength(_compressedCert.slot.two.values.serialNumber, CERT_SERIAL_NUMBER_LENGTH); + + int issuerLen = issuerOrSubjectLength(_issuerData); + + int issuerHeaderLen = sequenceHeaderLength(issuerLen); + + int subjectLen = issuerOrSubjectLength(_subjectData); + + int subjectHeaderLen = sequenceHeaderLength(subjectLen); + + int publicKeyLen = publicKeyLength(); + + int certInfoLen = 5 + serialNumberLen + 12 + issuerHeaderLen + issuerLen + (datesSizeLen + 2) + + subjectHeaderLen + subjectLen + publicKeyLen; + + int authorityKeyIdLen = authorityKeyIdLength(_compressedCert.slot.two.values.authorityKeyId, CERT_AUTHORITY_KEY_ID_LENGTH); + + if (authorityKeyIdLen) + { + certInfoLen += authorityKeyIdLen; + } + else + { + certInfoLen += 4; + } + + return certInfoLen; +} + +int ArduinoIoTCloudCertClass::getCertSize() +{ + int certInfoLen = certInfoLength(); + int certInfoHeaderLen = sequenceHeaderLength(certInfoLen); + + return (certInfoLen + certInfoHeaderLen); +} + +int ArduinoIoTCloudCertClass::getCertSignedSize(const byte * signature) +{ + int signatureLen = signatureLength(signature); + int certLen = getCertSize() + signatureLen; + return sequenceHeaderLength(certLen) + certLen; +} + +int ArduinoIoTCloudCertClass::appendSequenceHeader(int length, byte out[]) +{ + *out++ = ASN1_SEQUENCE; + if (length > 255) { + *out++ = 0x82; + *out++ = (length >> 8) & 0xff; + } else if (length > 127) { + *out++ = 0x81; + } + *out++ = (length) & 0xff; + + if (length > 255) { + return 4; + } else if (length > 127) { + return 3; + } else { + return 2; + } +} + +int ArduinoIoTCloudCertClass::appendVersion(int version, byte out[]) +{ + out[0] = ASN1_INTEGER; + out[1] = 0x01; + out[2] = version; + + return versionLength(); +} + +int ArduinoIoTCloudCertClass::appendName(const String& name, int type, byte out[]) +{ + int nameLength = name.length(); + + *out++ = ASN1_SET; + *out++ = nameLength + 9; + + *out++ = ASN1_SEQUENCE; + *out++ = nameLength + 7; + + *out++ = ASN1_OBJECT_IDENTIFIER; + *out++ = 0x03; + *out++ = 0x55; + *out++ = 0x04; + *out++ = type; + + *out++ = ASN1_PRINTABLE_STRING; + *out++ = nameLength; + memcpy(out, name.c_str(), nameLength); + + return (nameLength + 11); +} + +int ArduinoIoTCloudCertClass::appendIssuerOrSubject(const CertInfo& issuerOrSubjectData, byte out[]) +{ + if (issuerOrSubjectData.countryName.length() > 0) { + out += appendName(issuerOrSubjectData.countryName, 0x06, out); + } + + if (issuerOrSubjectData.stateProvinceName.length() > 0) { + out += appendName(issuerOrSubjectData.stateProvinceName, 0x08, out); + } + + if (issuerOrSubjectData.localityName.length() > 0) { + out += appendName(issuerOrSubjectData.localityName, 0x07, out); + } + + if (issuerOrSubjectData.organizationName.length() > 0) { + out += appendName(issuerOrSubjectData.organizationName, 0x0a, out); + } + + if (issuerOrSubjectData.organizationalUnitName.length() > 0) { + out += appendName(issuerOrSubjectData.organizationalUnitName, 0x0b, out); + } + + if (issuerOrSubjectData.commonName.length() > 0) { + out += appendName(issuerOrSubjectData.commonName, 0x03, out); + } + + return issuerOrSubjectLength(issuerOrSubjectData); +} + +int ArduinoIoTCloudCertClass::appendPublicKey(const byte publicKey[], byte out[]) +{ + int subjectPublicKeyDataLength = 2 + 9 + 10 + 4 + 64; + + // subject public key + *out++ = ASN1_SEQUENCE; + *out++ = (subjectPublicKeyDataLength) & 0xff; + + *out++ = ASN1_SEQUENCE; + *out++ = 0x13; + + // EC public key + *out++ = ASN1_OBJECT_IDENTIFIER; + *out++ = 0x07; + *out++ = 0x2a; + *out++ = 0x86; + *out++ = 0x48; + *out++ = 0xce; + *out++ = 0x3d; + *out++ = 0x02; + *out++ = 0x01; + + // PRIME 256 v1 + *out++ = ASN1_OBJECT_IDENTIFIER; + *out++ = 0x08; + *out++ = 0x2a; + *out++ = 0x86; + *out++ = 0x48; + *out++ = 0xce; + *out++ = 0x3d; + *out++ = 0x03; + *out++ = 0x01; + *out++ = 0x07; + + *out++ = 0x03; + *out++ = 0x42; + *out++ = 0x00; + *out++ = 0x04; + + memcpy(out, publicKey, 64); + + return publicKeyLength(); +} + +int ArduinoIoTCloudCertClass::appendSignature(const byte signature[], byte out[]) +{ + // signature algorithm + *out++ = ASN1_SEQUENCE; + *out++ = 0x0a; + *out++ = ASN1_OBJECT_IDENTIFIER; + *out++ = 0x08; + + // ECDSA with SHA256 + *out++ = 0x2a; + *out++ = 0x86; + *out++ = 0x48; + *out++ = 0xce; + *out++ = 0x3d; + *out++ = 0x04; + *out++ = 0x03; + *out++ = 0x02; + + const byte* r = &signature[0]; + const byte* s = &signature[32]; + + int rLength = 32; + int sLength = 32; + + while (*r == 0 && rLength) { + r++; + rLength--; + } + + while (*s == 0 && sLength) { + s++; + sLength--; + } + + if (*r & 0x80) { + rLength++; + } + + if (*s & 0x80) { + sLength++; + } + + *out++ = ASN1_BIT_STRING; + *out++ = (rLength + sLength + 7); + *out++ = 0; + + *out++ = ASN1_SEQUENCE; + *out++ = (rLength + sLength + 4); + + *out++ = ASN1_INTEGER; + *out++ = rLength; + if ((*r & 0x80) && rLength) { + *out++ = 0; + rLength--; + } + memcpy(out, r, rLength); + out += rLength; + + *out++ = ASN1_INTEGER; + *out++ = sLength; + if ((*s & 0x80) && sLength) { + *out++ = 0; + sLength--; + } + memcpy(out, s, sLength); + out += rLength; + + return signatureLength(signature); +} + +int ArduinoIoTCloudCertClass::appendSerialNumber(const byte serialNumber[], int length, byte out[]) +{ + while (*serialNumber == 0 && length) { + serialNumber++; + length--; + } + + if (*serialNumber & 0x80) { + length++; + } + + *out++ = ASN1_INTEGER; + *out++ = length; + + if (*serialNumber & 0x80) { + *out++ = 0x00; + length--; + } + + memcpy(out, serialNumber, length); + + if (*serialNumber & 0x80) { + length++; + } + + return (2 + length); +} + +int ArduinoIoTCloudCertClass::appendDate(int year, int month, int day, int hour, int minute, int second, byte out[]) +{ + bool useGeneralizedTime = (year > 2049); + + if (useGeneralizedTime) { + *out++ = 0x18; + *out++ = 0x0f; + *out++ = '0' + (year / 1000); + *out++ = '0' + ((year % 1000) / 100); + *out++ = '0' + ((year % 100) / 10); + *out++ = '0' + (year % 10); + } else { + year -= 2000; + + *out++ = 0x17; + *out++ = 0x0d; + *out++ = '0' + (year / 10); + *out++ = '0' + (year % 10); + } + *out++ = '0' + (month / 10); + *out++ = '0' + (month % 10); + *out++ = '0' + (day / 10); + *out++ = '0' + (day % 10); + *out++ = '0' + (hour / 10); + *out++ = '0' + (hour % 10); + *out++ = '0' + (minute / 10); + *out++ = '0' + (minute % 10); + *out++ = '0' + (second / 10); + *out++ = '0' + (second % 10); + *out++ = 0x5a; // UTC + + return (useGeneralizedTime ? 17 : 15); +} + +int ArduinoIoTCloudCertClass::appendEcdsaWithSHA256(byte out[]) +{ + *out++ = ASN1_SEQUENCE; + *out++ = 0x0A; + *out++ = ASN1_OBJECT_IDENTIFIER; + *out++ = 0x08; + *out++ = 0x2A; + *out++ = 0x86; + *out++ = 0x48; + *out++ = 0xCE; + *out++ = 0x3D; + *out++ = 0x04; + *out++ = 0x03; + *out++ = 0x02; + + return 12; +} + +int ArduinoIoTCloudCertClass::appendAuthorityKeyId(const byte authorityKeyId[], int length, byte out[]) { + // [3] + *out++ = 0xa3; + *out++ = 0x23; + + // sequence + *out++ = ASN1_SEQUENCE; + *out++ = 0x21; + + // sequence + *out++ = ASN1_SEQUENCE; + *out++ = 0x1f; + + // 2.5.29.35 authorityKeyIdentifier(X.509 extension) + *out++ = 0x06; + *out++ = 0x03; + *out++ = 0x55; + *out++ = 0x1d; + *out++ = 0x23; + + // octet string + *out++ = 0x04; + *out++ = 0x18; + + // sequence + *out++ = ASN1_SEQUENCE; + *out++ = 0x16; + + *out++ = 0x80; + *out++ = 0x14; + + memcpy(out, authorityKeyId, length); + + return length + 17; +} + +#endif /* (BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) */ diff --git a/src/tls/utility/Cert.h b/src/tls/utility/Cert.h new file mode 100644 index 000000000..944a2eac1 --- /dev/null +++ b/src/tls/utility/Cert.h @@ -0,0 +1,189 @@ +/* + This file is part of ArduinoIoTCloud. + + Copyright 2019 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_IOT_CLOUD_CERT_H +#define ARDUINO_IOT_CLOUD_CERT_H + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include + +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) + +/****************************************************************************** + * DEFINE + ******************************************************************************/ + +#define CERT_SERIAL_NUMBER_LENGTH 16 +#define CERT_AUTHORITY_KEY_ID_LENGTH 20 +#define CERT_PUBLIC_KEY_LENGTH 64 +#define CERT_SIGNATURE_LENGTH 64 +#define CERT_DATES_LENGTH 3 +#define CERT_COMPRESSED_CERT_LENGTH 144 +#define CERT_COMPRESSED_CERT_SLOT_LENGTH 72 + +#include + +class ArduinoIoTCloudCertClass { +public: + ArduinoIoTCloudCertClass(); + virtual ~ArduinoIoTCloudCertClass(); + + int begin(); + int end(); + + /* APIs used only for Certificate generation*/ + void setIssueYear(int issueYear); + void setIssueMonth(int issueMonth); + void setIssueDay(int issueDay); + void setIssueHour(int issueHour); + void setExpireYears(int expireYears); + int setSerialNumber(const uint8_t serialNumber[], int serialNumberLen); + int setAuthorityKeyId(const uint8_t authorityKeyId[], int authorityKeyIdLen); + + inline void setIssuerCountryName(const String& countryName) { _issuerData.countryName = countryName; } + inline void setIssuerStateProvinceName(const String& stateProvinceName) { _issuerData.stateProvinceName = stateProvinceName; } + inline void setIssuerLocalityName(const String& localityName) { _issuerData.localityName = localityName; } + inline void setIssuerOrganizationName(const String& organizationName) { _issuerData.organizationName = organizationName; } + inline void setIssuerOrganizationalUnitName(const String& organizationalUnitName) { _issuerData.organizationalUnitName = organizationalUnitName; } + inline void setIssuerCommonName(const String& commonName) { _issuerData.commonName = commonName; } + + /* APIs used for both CSR and Certificate generation */ + inline void setSubjectCountryName(const String& countryName) { _subjectData.countryName = countryName; } + inline void setSubjectStateProvinceName(const String& stateProvinceName) { _subjectData.stateProvinceName = stateProvinceName; } + inline void setSubjectLocalityName(const String& localityName) { _subjectData.localityName = localityName; } + inline void setSubjectOrganizationName(const String& organizationName) { _subjectData.organizationName = organizationName; } + inline void setSubjectOrganizationalUnitName(const String& organizationalUnitName) { _subjectData.organizationalUnitName = organizationalUnitName; } + inline void setSubjectCommonName(const String& commonName) { _subjectData.commonName = commonName; } + + int setPublicKey(const byte* publicKey, int publicKeyLen); + int setSignature(const byte* signature, int signatureLen); + + /* Get Buffer */ + inline byte* bytes() { return _certBuffer; } + inline int length() { return _certBufferLen; } + +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) + /* Get Data to create ECCX08 compressed cert */ + inline byte* compressedCertBytes() { return _compressedCert.data; } + inline int compressedCertLenght() {return CERT_COMPRESSED_CERT_LENGTH; } + inline byte* compressedCertSignatureAndDatesBytes() { return _compressedCert.slot.one.data; } + inline int compressedCertSignatureAndDatesLength() {return CERT_COMPRESSED_CERT_SLOT_LENGTH; } + inline byte* compressedCertSerialAndAuthorityKeyIdBytes() { return _compressedCert.slot.two.data; } + inline int compressedCertSerialAndAuthorityKeyIdLenght() {return CERT_COMPRESSED_CERT_SLOT_LENGTH; } +#endif + + /* Build CSR */ + int buildCSR(); + int signCSR(byte signature[]); + String getCSRPEM(); + + /* Build Certificate */ + int buildCert(); + int signCert(const byte signature[]); + int signCert(); + String getCertPEM(); + + /* Import DER buffer into CertClass*/ + int importCert(const byte certDER[], size_t derLen); + +private: + + struct CertInfo { + String countryName; + String stateProvinceName; + String localityName; + String organizationName; + String organizationalUnitName; + String commonName; + }_issuerData, _subjectData; + + struct DateInfo { + int issueYear; + int issueMonth; + int issueDay; + int issueHour; + int expireYears; + }; + + union SignatureAndDateUType { + struct __attribute__((__packed__)) SignatureAndDateType { + byte signature[CERT_SIGNATURE_LENGTH]; + byte dates[CERT_DATES_LENGTH]; + byte unused[5]; + } values; + byte data[CERT_COMPRESSED_CERT_SLOT_LENGTH]; + }; + + union SerialNumberAndAuthorityKeyIdUType { + struct __attribute__((__packed__)) SerialNumberAndAuthorityKeyIdType { + byte serialNumber[CERT_SERIAL_NUMBER_LENGTH]; + byte authorityKeyId[CERT_AUTHORITY_KEY_ID_LENGTH]; + byte unused[36]; + } values; + byte data[CERT_COMPRESSED_CERT_SLOT_LENGTH]; + }; + + union CompressedCertDataUType { + struct __attribute__((__packed__)) CompressedCertDataType { + SignatureAndDateUType one; + SerialNumberAndAuthorityKeyIdUType two; + }slot; + byte data[CERT_COMPRESSED_CERT_LENGTH]; + } _compressedCert; + + /* only raw EC X Y values 64 byte */ + byte _publicKey[CERT_PUBLIC_KEY_LENGTH]; + int _publicKeyLen; + + byte * _certBuffer; + int _certBufferLen; + + int versionLength(); + int issuerOrSubjectLength(const CertInfo& issuerOrSubjectData); + int sequenceHeaderLength(int length); + int publicKeyLength(); + int signatureLength(const byte signature[]); + int serialNumberLength(const byte serialNumber[], int length); + int authorityKeyIdLength(const byte authorityKeyId[], int length); + int CSRInfoLength(); + int getCSRSize(); + int getCSRSignedSize(byte signature[]); + int certInfoLength(); + int getCertSize(); + int getCertSignedSize(const byte signature[]); + + void getDateFromCompressedData(DateInfo& date); + + int appendSequenceHeader(int length, byte out[]); + int appendVersion(int version, byte out[]); + int appendName(const String& name, int type, byte out[]); + int appendIssuerOrSubject(const CertInfo& issuerOrSubjectData, byte out[]); + int appendPublicKey(const byte publicKey[], byte out[]); + int appendSignature(const byte signature[], byte out[]); + int appendSerialNumber(const byte serialNumber[], int length, byte out[]); + int appendDate(int year, int month, int day, int hour, int minute, int second, byte out[]); + int appendEcdsaWithSHA256(byte out[]); + int appendAuthorityKeyId(const byte authorityKeyId[], int length, byte out[]); + +}; + +#endif /* BOARD_HAS_ECCX08 || BOARD_HAS_OFFLOADED_ECCX08 */ + +#endif /* ARDUINO_IOT_CLOUD_CERT_H */ From 75bbfd3ee9f284be433b9eafe590ec5d2f947adc Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 9 Feb 2022 18:22:49 +0100 Subject: [PATCH 280/780] CryptoUtil: extend class in order to abstract hardware crypto and update ArduinoIoTCloudTCP --- src/ArduinoIoTCloudTCP.cpp | 16 +-- src/ArduinoIoTCloudTCP.h | 10 +- src/tls/utility/CryptoUtil.cpp | 174 ++++++++++++++++++++++++++++----- src/tls/utility/CryptoUtil.h | 29 +++--- 4 files changed, 183 insertions(+), 46 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index ed0e46cd4..00c416c87 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -204,36 +204,36 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #endif /* OTA_ENABLED */ #ifdef BOARD_HAS_OFFLOADED_ECCX08 - if (!ECCX08.begin()) + if (!_crypto.begin()) { - DEBUG_ERROR("ECCX08.begin() failed."); + DEBUG_ERROR("_crypto.begin() failed."); return 0; } - if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) + if (!_crypto.readDeviceId(getDeviceId(), CryptoSlot::DeviceId)) { - DEBUG_ERROR("CryptoUtil::readDeviceId(...) failed."); + DEBUG_ERROR("_crypto.readDeviceId(...) failed."); return 0; } #endif #ifdef BOARD_HAS_ECCX08 - if (!ECCX08.begin()) + if (!_crypto.begin()) { DEBUG_ERROR("Cryptography processor failure. Make sure you have a compatible board."); return 0; } - if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) + if (!_crypto.readDeviceId(getDeviceId(), CryptoSlot::DeviceId)) { DEBUG_ERROR("Cryptography processor read failure."); return 0; } - if (!CryptoUtil::reconstructCertificate(_eccx08_cert, getDeviceId(), ECCX08Slot::Key, ECCX08Slot::CompressedCertificate, ECCX08Slot::SerialNumberAndAuthorityKeyIdentifier)) + if (!_crypto.readCert(_cert, CryptoSlot::CompressedCertificate)) { DEBUG_ERROR("Cryptography certificate reconstruction failure."); return 0; } _sslClient.setClient(_connection->getClient()); - _sslClient.setEccSlot(static_cast(ECCX08Slot::Key), _eccx08_cert.bytes(), _eccx08_cert.length()); + _sslClient.setEccSlot(static_cast(CryptoSlot::Key), _cert.bytes(), _cert.length()); #elif defined(BOARD_ESP) _sslClient.setInsecure(); #endif diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index b704f6762..2167b4d19 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -28,13 +28,13 @@ #ifdef BOARD_HAS_ECCX08 #include "tls/BearSSLClient.h" - #include "tls/utility/ECCX08Cert.h" + #include "tls/utility/CryptoUtil.h" #elif defined(BOARD_ESP) #include #endif #ifdef BOARD_HAS_OFFLOADED_ECCX08 -#include "tls/utility/ECCX08Cert.h" +#include "tls/utility/CryptoUtil.h" #include #endif @@ -133,11 +133,13 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass bool _mqtt_data_request_retransmit; #if defined(BOARD_HAS_ECCX08) - ECCX08CertClass _eccx08_cert; + ArduinoIoTCloudCertClass _cert; BearSSLClient _sslClient; + CryptoUtil _crypto; #elif defined(BOARD_HAS_OFFLOADED_ECCX08) - ECCX08CertClass _eccx08_cert; + ArduinoIoTCloudCertClass _cert; WiFiBearSSLClient _sslClient; + CryptoUtil _crypto; #elif defined(BOARD_ESP) WiFiClientSecure _sslClient; String _password; diff --git a/src/tls/utility/CryptoUtil.cpp b/src/tls/utility/CryptoUtil.cpp index 4348bc38d..3d1fdf880 100644 --- a/src/tls/utility/CryptoUtil.cpp +++ b/src/tls/utility/CryptoUtil.cpp @@ -19,43 +19,171 @@ * INCLUDE ******************************************************************************/ +#include + +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) + #include "CryptoUtil.h" +#include "SHA256.h" + +/****************************************************************************** + * DEFINE + ******************************************************************************/ +#define CRYPTO_SHA256_BUFFER_LENGTH 32 +#define CRYPTO_CERT_BUFFER_LENGTH 1024 + +/************************************************************************************** + * CTOR/DTOR + **************************************************************************************/ +CryptoUtil::CryptoUtil() +: _crypto {ECCX08} +{ -#if defined(BOARD_HAS_ECCX08) || defined (BOARD_HAS_OFFLOADED_ECCX08) +} /****************************************************************************** * PUBLIC MEMBER FUNCTIONS ******************************************************************************/ -bool CryptoUtil::readDeviceId(ECCX08Class & eccx08, String & device_id, ECCX08Slot const device_id_slot) +int CryptoUtil::buildCSR(ArduinoIoTCloudCertClass & cert, const CryptoSlot keySlot, bool newPrivateKey) +{ + byte publicKey[CERT_PUBLIC_KEY_LENGTH]; + byte signature[CERT_SIGNATURE_LENGTH]; + + if (newPrivateKey) { + if (!_crypto.generatePrivateKey(static_cast(keySlot), publicKey)) { + return 0; + } + } else { + if (!_crypto.generatePublicKey(static_cast(keySlot), publicKey)) { + return 0; + } + } + + /* Store public key in csr */ + if (!cert.setPublicKey(publicKey, CERT_PUBLIC_KEY_LENGTH)) { + return 0; + } + + /* Build CSR */ + if (!cert.buildCSR()) { + return 0; + } + + /* compute CSR SHA256 */ + SHA256 sha256; + byte sha256buf[CRYPTO_SHA256_BUFFER_LENGTH]; + sha256.begin(); + sha256.update(cert.bytes(), cert.length()); + sha256.finalize(sha256buf); + + if (!_crypto.ecSign(static_cast(keySlot), sha256buf, signature)) { + return 0; + } + + /* sign CSR */ + return cert.signCSR(signature); +} + +int CryptoUtil::buildCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot keySlot) +{ + byte publicKey[CERT_PUBLIC_KEY_LENGTH]; + + if (!_crypto.generatePublicKey(static_cast(keySlot), publicKey)) { + return 0; + } + + /* Store public key in csr */ + if (!cert.setPublicKey(publicKey, CERT_PUBLIC_KEY_LENGTH)) { + return 0; + } + + /* Build CSR */ + if (!cert.buildCert()) { + return 0; + } + + /* sign CSR */ + return cert.signCert(); +} + +int CryptoUtil::readDeviceId(String & device_id, const CryptoSlot device_id_slot) +{ + byte device_id_bytes[CERT_COMPRESSED_CERT_SLOT_LENGTH] = {0}; + + if (!_crypto.readSlot(static_cast(device_id_slot), device_id_bytes, sizeof(device_id_bytes))) { + return 0; + } + + device_id = String(reinterpret_cast(device_id_bytes)); + return 1; +} + +int CryptoUtil::writeDeviceId(String & device_id, const CryptoSlot device_id_slot) { - byte device_id_bytes[72] = {0}; + byte device_id_bytes[CERT_COMPRESSED_CERT_SLOT_LENGTH] = {0}; + + device_id.getBytes(device_id_bytes, sizeof(device_id_bytes)); - if (eccx08.readSlot(static_cast(device_id_slot), device_id_bytes, sizeof(device_id_bytes))) { - device_id = String(reinterpret_cast(device_id_bytes)); - return true; + if (!_crypto.writeSlot(static_cast(device_id_slot), device_id_bytes, sizeof(device_id_bytes))) { + return 0; } - else - { - return false; + return 1; +} + +int CryptoUtil::writeCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot certSlot) +{ + if (!_crypto.writeSlot(static_cast(certSlot), cert.compressedCertSignatureAndDatesBytes(), cert.compressedCertSignatureAndDatesLength())) { + return 0; } + + if (!_crypto.writeSlot(static_cast(certSlot) + 1, cert.compressedCertSerialAndAuthorityKeyIdBytes(), cert.compressedCertSerialAndAuthorityKeyIdLenght())) { + return 0; + } + return 1; } -bool CryptoUtil::reconstructCertificate(ECCX08CertClass & cert, String const & device_id, ECCX08Slot const key, ECCX08Slot const compressed_certificate, ECCX08Slot const serial_number_and_authority_key) +int CryptoUtil::readCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot certSlot) { - if (cert.beginReconstruction(static_cast(key), static_cast(compressed_certificate), static_cast(serial_number_and_authority_key))) - { - cert.setSubjectCommonName(device_id); - cert.setIssuerCountryName("US"); - cert.setIssuerOrganizationName("Arduino LLC US"); - cert.setIssuerOrganizationalUnitName("IT"); - cert.setIssuerCommonName("Arduino"); - return cert.endReconstruction(); - } - else - { - return false; + String deviceId; + byte publicKey[CERT_PUBLIC_KEY_LENGTH]; + + cert.begin(); + + if (!readDeviceId(deviceId, CryptoSlot::DeviceId)) { + return 0; + } + + if (!_crypto.readSlot(static_cast(certSlot), cert.compressedCertSignatureAndDatesBytes(), cert.compressedCertSignatureAndDatesLength())) { + return 0; + } + + if (!_crypto.readSlot(static_cast(certSlot) + 1, cert.compressedCertSerialAndAuthorityKeyIdBytes(), cert.compressedCertSerialAndAuthorityKeyIdLenght())) { + return 0; + } + + if (!_crypto.generatePublicKey(static_cast(CryptoSlot::Key), publicKey)) { + return 0; + } + + cert.setSubjectCommonName(deviceId); + cert.setIssuerCountryName("US"); + cert.setIssuerOrganizationName("Arduino LLC US"); + cert.setIssuerOrganizationalUnitName("IT"); + cert.setIssuerCommonName("Arduino"); + + if (!cert.setPublicKey(publicKey, CERT_PUBLIC_KEY_LENGTH)) { + return 0; + } + + if (!cert.buildCert()) { + return 0; + } + + if (!cert.signCert()) { + return 0; } + return 1; } -#endif /* BOARD_HAS_ECCX08 */ +#endif /* (BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) */ diff --git a/src/tls/utility/CryptoUtil.h b/src/tls/utility/CryptoUtil.h index 32239a486..35da6b81e 100644 --- a/src/tls/utility/CryptoUtil.h +++ b/src/tls/utility/CryptoUtil.h @@ -24,17 +24,15 @@ #include -#if defined(BOARD_HAS_ECCX08) || defined (BOARD_HAS_OFFLOADED_ECCX08) - +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) #include +#include "Cert.h" #include -#include "ECCX08Cert.h" /****************************************************************************** TYPEDEF ******************************************************************************/ - -enum class ECCX08Slot : int +enum class CryptoSlot : int { Key = 0, CompressedCertificate = 10, @@ -50,17 +48,26 @@ class CryptoUtil { public: - static bool readDeviceId(ECCX08Class & eccx08, String & device_id, ECCX08Slot const device_id_slot); - static bool reconstructCertificate(ECCX08CertClass & cert, String const & device_id, ECCX08Slot const key, ECCX08Slot const compressed_certificate, ECCX08Slot const serial_number_and_authority_key); + CryptoUtil(); + inline int begin() { return _crypto.begin(); } + inline int locked() { return _crypto.locked(); } + inline int writeConfiguration(const byte config[]) { return _crypto.writeConfiguration(config); } + inline int lock() { return _crypto.lock(); } -private: + int buildCSR(ArduinoIoTCloudCertClass & cert, const CryptoSlot keySlot, bool newPrivateKey); + int buildCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot keySlot); - CryptoUtil() { } - CryptoUtil(CryptoUtil const & other) { } + int readDeviceId(String & device_id, const CryptoSlot device_id_slot); + int writeDeviceId(String & device_id, const CryptoSlot device_id_slot); + int writeCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot certSlot); + int readCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot certSlot); + +private: + ECCX08Class & _crypto; }; -#endif /* BOARD_HAS_ECCX08 */ +#endif /* BOARD_HAS_ECCX08 || BOARD_HAS_OFFLOADED_ECCX08 */ #endif /* ARDUINO_IOT_CLOUD_UTILITY_CRYPTO_CRYPTO_UTIL_H_ */ From e2ac7e8c6a6ace34c9a6cf5ea319529a527b3e46 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 14 Feb 2022 15:00:38 +0100 Subject: [PATCH 281/780] ECCX08Cert: remove files --- src/tls/utility/ECCX08Cert.cpp | 945 --------------------------------- src/tls/utility/ECCX08Cert.h | 147 ----- 2 files changed, 1092 deletions(-) delete mode 100644 src/tls/utility/ECCX08Cert.cpp delete mode 100644 src/tls/utility/ECCX08Cert.h diff --git a/src/tls/utility/ECCX08Cert.cpp b/src/tls/utility/ECCX08Cert.cpp deleted file mode 100644 index 164309e9a..000000000 --- a/src/tls/utility/ECCX08Cert.cpp +++ /dev/null @@ -1,945 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2019 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 defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) - -#include "../../tls/bearssl/bearssl_hash.h" -#include - -#include "ECCX08Cert.h" - -/****************************************************************************** - * DEFINE - ******************************************************************************/ - -#define ASN1_INTEGER 0x02 -#define ASN1_BIT_STRING 0x03 -#define ASN1_NULL 0x05 -#define ASN1_OBJECT_IDENTIFIER 0x06 -#define ASN1_PRINTABLE_STRING 0x13 -#define ASN1_SEQUENCE 0x30 -#define ASN1_SET 0x31 - -struct __attribute__((__packed__)) CompressedCert { - byte signature[64]; - byte dates[3]; - byte unused[5]; -}; - -#define SERIAL_NUMBER_LENGTH 16 -#define AUTHORITY_KEY_IDENTIFIER_LENGTH 20 - -struct __attribute__((__packed__)) SerialNumberAndAuthorityKeyIdentifier { - byte serialNumber[SERIAL_NUMBER_LENGTH]; - byte authorityKeyIdentifier[AUTHORITY_KEY_IDENTIFIER_LENGTH]; -}; - -/****************************************************************************** - * LOCAL MODULE FUNCTIONS - ******************************************************************************/ - -static String base64Encode(const byte in[], unsigned int length, const char* prefix, const char* suffix) { - static const char* CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - - int b; - String out; - - int reserveLength = 4 * ((length + 2) / 3) + ((length / 3 * 4) / 76) + strlen(prefix) + strlen(suffix); - out.reserve(reserveLength); - - if (prefix) { - out += prefix; - } - - for (unsigned int i = 0; i < length; i += 3) { - if (i > 0 && (i / 3 * 4) % 76 == 0) { - out += '\n'; - } - - b = (in[i] & 0xFC) >> 2; - out += CODES[b]; - - b = (in[i] & 0x03) << 4; - if (i + 1 < length) { - b |= (in[i + 1] & 0xF0) >> 4; - out += CODES[b]; - b = (in[i + 1] & 0x0F) << 2; - if (i + 2 < length) { - b |= (in[i + 2] & 0xC0) >> 6; - out += CODES[b]; - b = in[i + 2] & 0x3F; - out += CODES[b]; - } else { - out += CODES[b]; - out += '='; - } - } else { - out += CODES[b]; - out += "=="; - } - } - - if (suffix) { - out += suffix; - } - - return out; -} - -/****************************************************************************** - * CTOR/DTOR - ******************************************************************************/ - -ECCX08CertClass::ECCX08CertClass() : - _keySlot(-1), - _compressedCertSlot(-1), - _serialNumberAndAuthorityKeyIdentifierSlot(-1), - _bytes(NULL), - _length(0) { -} - -ECCX08CertClass::~ECCX08CertClass() { - if (_bytes) { - free(_bytes); - _bytes = NULL; - } -} - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -int ECCX08CertClass::beginCSR(int keySlot, bool newPrivateKey) { - if (keySlot < 0 || keySlot > 8) { - return 0; - } - - _keySlot = keySlot; - - if (newPrivateKey) { - if (!ECCX08.generatePrivateKey(_keySlot, _temp)) { - return 0; - } - } else { - if (!ECCX08.generatePublicKey(_keySlot, _temp)) { - return 0; - } - } - - return 1; -} - -String ECCX08CertClass::endCSR() { - int versionLen = versionLength(); - int subjectLen = issuerOrSubjectLength(_subjectCountryName, - _subjectStateProvinceName, - _subjectLocalityName, - _subjectOrganizationName, - _subjectOrganizationalUnitName, - _subjectCommonName); - int subjectHeaderLen = sequenceHeaderLength(subjectLen); - int publicKeyLen = publicKeyLength(); - - int csrInfoLen = versionLen + subjectHeaderLen + subjectLen + publicKeyLen + 2; - int csrInfoHeaderLen = sequenceHeaderLength(csrInfoLen); - - byte csrInfo[csrInfoHeaderLen + csrInfoLen]; - byte* out = csrInfo; - - appendSequenceHeader(csrInfoLen, out); - out += csrInfoHeaderLen; - - // version - appendVersion(0x00, out); - out += versionLen; - - // subject - appendSequenceHeader(subjectLen, out); - out += subjectHeaderLen; - appendIssuerOrSubject(_subjectCountryName, - _subjectStateProvinceName, - _subjectLocalityName, - _subjectOrganizationName, - _subjectOrganizationalUnitName, - _subjectCommonName, out); - out += subjectLen; - - // public key - appendPublicKey(_temp, out); - out += publicKeyLen; - - // terminator - *out++ = 0xa0; - *out++ = 0x00; - - br_sha256_context sha256Context; - byte csrInfoSha256[64]; - byte signature[64]; - - br_sha256_init(&sha256Context); - br_sha256_update(&sha256Context, csrInfo, csrInfoHeaderLen + csrInfoLen); - br_sha256_out(&sha256Context, csrInfoSha256); - - if (!ECCX08.ecSign(_keySlot, csrInfoSha256, signature)) { - return ""; - } - - int signatureLen = signatureLength(signature); - int csrLen = csrInfoHeaderLen + csrInfoLen + signatureLen; - int csrHeaderLen = sequenceHeaderLength(csrLen); - - byte csr[csrLen + csrHeaderLen]; - out = csr; - - appendSequenceHeader(csrLen, out); - out += csrHeaderLen; - - // info - memcpy(out, csrInfo, csrInfoHeaderLen + csrInfoLen); - out += (csrInfoHeaderLen + csrInfoLen); - - // signature - appendSignature(signature, out); - out += signatureLen; - - return base64Encode(csr, csrLen + csrHeaderLen, "-----BEGIN CERTIFICATE REQUEST-----\n", "\n-----END CERTIFICATE REQUEST-----\n"); -} - -int ECCX08CertClass::beginStorage(int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot) { - if (compressedCertSlot < 8 || compressedCertSlot > 15) { - return 0; - } - - if (serialNumberAndAuthorityKeyIdentifierSlot < 8 || serialNumberAndAuthorityKeyIdentifierSlot > 15) { - return 0; - } - - _compressedCertSlot = compressedCertSlot; - _serialNumberAndAuthorityKeyIdentifierSlot = serialNumberAndAuthorityKeyIdentifierSlot; - - memset(_temp, 0x00, sizeof(_temp)); - - return 1; -} - -void ECCX08CertClass::setSignature(byte signature[]) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - memcpy(compressedCert->signature, signature, 64); -} - -void ECCX08CertClass::setIssueYear(int issueYear) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[0] &= 0x07; - compressedCert->dates[0] |= (issueYear - 2000) << 3; -} - -void ECCX08CertClass::setIssueMonth(int issueMonth) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[0] &= 0xf8; - compressedCert->dates[0] |= issueMonth >> 1; - - compressedCert->dates[1] &= 0x7f; - compressedCert->dates[1] |= issueMonth << 7; -} - -void ECCX08CertClass::setIssueDay(int issueDay) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[1] &= 0x83; - compressedCert->dates[1] |= issueDay << 2; -} - -void ECCX08CertClass::setIssueHour(int issueHour) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[2] &= 0x1f; - compressedCert->dates[2] |= issueHour << 5; - - compressedCert->dates[1] &= 0xfc; - compressedCert->dates[1] |= issueHour >> 3; -} - -void ECCX08CertClass::setExpireYears(int expireYears) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[2] &= 0xe0; - compressedCert->dates[2] |= expireYears; -} - -void ECCX08CertClass::setSerialNumber(const byte serialNumber[]) { - memcpy(&_temp[72], serialNumber, SERIAL_NUMBER_LENGTH); -} - -void ECCX08CertClass::setAuthorityKeyIdentifier(const byte authorityKeyIdentifier[]) { - memcpy(&_temp[88], authorityKeyIdentifier, AUTHORITY_KEY_IDENTIFIER_LENGTH); -} - -int ECCX08CertClass::endStorage() { - if (!ECCX08.writeSlot(_compressedCertSlot, &_temp[0], 72)) { - return 0; - } - - if (!ECCX08.writeSlot(_serialNumberAndAuthorityKeyIdentifierSlot, &_temp[72], SERIAL_NUMBER_LENGTH + AUTHORITY_KEY_IDENTIFIER_LENGTH)) { - return 0; - } - - return 1; -} - -int ECCX08CertClass::beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot) { - if (keySlot < 0 || keySlot > 8) { - return 0; - } - - if (compressedCertSlot < 8 || compressedCertSlot > 15) { - return 0; - } - - if (serialNumberAndAuthorityKeyIdentifierSlot < 8 || serialNumberAndAuthorityKeyIdentifierSlot > 15) { - return 0; - } - - _keySlot = keySlot; - _compressedCertSlot = compressedCertSlot; - _serialNumberAndAuthorityKeyIdentifierSlot = serialNumberAndAuthorityKeyIdentifierSlot; - - return 1; -} - -int ECCX08CertClass::endReconstruction() { - byte publicKey[64]; - struct CompressedCert compressedCert; - struct SerialNumberAndAuthorityKeyIdentifier serialNumberAndAuthorityKeyIdentifier; - - if (!ECCX08.generatePublicKey(_keySlot, publicKey)) { - return 0; - } - - if (!ECCX08.readSlot(_compressedCertSlot, (byte*)&compressedCert, sizeof(compressedCert))) { - return 0; - } - - if (!ECCX08.readSlot(_serialNumberAndAuthorityKeyIdentifierSlot, (byte*)&serialNumberAndAuthorityKeyIdentifier, sizeof(serialNumberAndAuthorityKeyIdentifier))) { - return 0; - } - - // dates - int year = (compressedCert.dates[0] >> 3) + 2000; - int month = ((compressedCert.dates[0] & 0x07) << 1) | (compressedCert.dates[1] >> 7); - int day = (compressedCert.dates[1] & 0x7c) >> 2; - int hour = ((compressedCert.dates[1] & 0x03) << 3) | (compressedCert.dates[2] >> 5); - int expireYears = (compressedCert.dates[2] & 0x1f); - - int datesSize = 30; - - if (year > 2049) { - // two more bytes for GeneralizedTime - datesSize += 2; - } - - if ((year + expireYears) > 2049) { - // two more bytes for GeneralizedTime - datesSize += 2; - } - - int serialNumberLen = serialNumberLength(serialNumberAndAuthorityKeyIdentifier.serialNumber); - - int issuerLen = issuerOrSubjectLength(_issuerCountryName, - _issuerStateProvinceName, - _issuerLocalityName, - _issuerOrganizationName, - _issuerOrganizationalUnitName, - _issuerCommonName); - - int issuerHeaderLen = sequenceHeaderLength(issuerLen); - - int subjectLen = issuerOrSubjectLength(_subjectCountryName, - _subjectStateProvinceName, - _subjectLocalityName, - _subjectOrganizationName, - _subjectOrganizationalUnitName, - _subjectCommonName); - - int subjectHeaderLen = sequenceHeaderLength(subjectLen); - - int publicKeyLen = publicKeyLength(); - - int authorityKeyIdentifierLen = authorityKeyIdentifierLength(serialNumberAndAuthorityKeyIdentifier.authorityKeyIdentifier); - - int signatureLen = signatureLength(compressedCert.signature); - - int certInfoLen = 5 + serialNumberLen + 12 + issuerHeaderLen + issuerLen + (datesSize + 2) + - subjectHeaderLen + subjectLen + publicKeyLen; - - if (authorityKeyIdentifierLen) { - certInfoLen += authorityKeyIdentifierLen; - } else { - certInfoLen += 4; - } - - int certInfoHeaderLen = sequenceHeaderLength(certInfoLen); - - int certDataLen = certInfoLen + certInfoHeaderLen + signatureLen; - int certDataHeaderLen = sequenceHeaderLength(certDataLen); - - _length = certDataLen + certDataHeaderLen; - _bytes = (byte*)realloc(_bytes, _length); - - if (!_bytes) { - _length = 0; - return 0; - } - - byte* out = _bytes; - - appendSequenceHeader(certDataLen, out); - out += certDataHeaderLen; - - appendSequenceHeader(certInfoLen, out); - out += certInfoHeaderLen; - - // version - *out++ = 0xA0; - *out++ = 0x03; - *out++ = 0x02; - *out++ = 0x01; - *out++ = 0x02; - - // serial number - appendSerialNumber(serialNumberAndAuthorityKeyIdentifier.serialNumber, out); - out += serialNumberLen; - - // ecdsaWithSHA256 - out += appendEcdsaWithSHA256(out); - - // issuer - appendSequenceHeader(issuerLen, out); - out += issuerHeaderLen; - appendIssuerOrSubject(_issuerCountryName, - _issuerStateProvinceName, - _issuerLocalityName, - _issuerOrganizationName, - _issuerOrganizationalUnitName, - _issuerCommonName, out); - out += issuerLen; - - *out++ = ASN1_SEQUENCE; - *out++ = datesSize; - out += appendDate(year, month, day, hour, 0, 0, out); - out += appendDate(year + expireYears, month, day, hour, 0, 0, out); - - // subject - appendSequenceHeader(subjectLen, out); - out += subjectHeaderLen; - appendIssuerOrSubject(_subjectCountryName, - _subjectStateProvinceName, - _subjectLocalityName, - _subjectOrganizationName, - _subjectOrganizationalUnitName, - _subjectCommonName, out); - out += subjectLen; - - // public key - appendPublicKey(publicKey, out); - out += publicKeyLen; - - if (authorityKeyIdentifierLen) { - appendAuthorityKeyIdentifier(serialNumberAndAuthorityKeyIdentifier.authorityKeyIdentifier, out); - out += authorityKeyIdentifierLen; - } else { - // null sequence - *out++ = 0xA3; - *out++ = 0x02; - *out++ = 0x30; - *out++ = 0x00; - } - - // signature - appendSignature(compressedCert.signature, out); - out += signatureLen; - - return 1; -} - -byte* ECCX08CertClass::bytes() { - return _bytes; -} - -int ECCX08CertClass::length() { - return _length; -} - -void ECCX08CertClass::setIssuerCountryName(const String& countryName) { - _issuerCountryName = countryName; -} - -void ECCX08CertClass::setIssuerStateProvinceName(const String& stateProvinceName) { - _issuerStateProvinceName = stateProvinceName; -} - -void ECCX08CertClass::setIssuerLocalityName(const String& localityName) { - _issuerLocalityName = localityName; -} - -void ECCX08CertClass::setIssuerOrganizationName(const String& organizationName) { - _issuerOrganizationName = organizationName; -} - -void ECCX08CertClass::setIssuerOrganizationalUnitName(const String& organizationalUnitName) { - _issuerOrganizationalUnitName = organizationalUnitName; -} - -void ECCX08CertClass::setIssuerCommonName(const String& commonName) { - _issuerCommonName = commonName; -} - -void ECCX08CertClass::setSubjectCountryName(const String& countryName) { - _subjectCountryName = countryName; -} - -void ECCX08CertClass::setSubjectStateProvinceName(const String& stateProvinceName) { - _subjectStateProvinceName = stateProvinceName; -} - -void ECCX08CertClass::setSubjectLocalityName(const String& localityName) { - _subjectLocalityName = localityName; -} - -void ECCX08CertClass::setSubjectOrganizationName(const String& organizationName) { - _subjectOrganizationName = organizationName; -} - -void ECCX08CertClass::setSubjectOrganizationalUnitName(const String& organizationalUnitName) { - _subjectOrganizationName = organizationalUnitName; -} - -void ECCX08CertClass::setSubjectCommonName(const String& commonName) { - _subjectCommonName = commonName; -} - -int ECCX08CertClass::versionLength() { - return 3; -} - -int ECCX08CertClass::issuerOrSubjectLength(const String& countryName, - const String& stateProvinceName, - const String& localityName, - const String& organizationName, - const String& organizationalUnitName, - const String& commonName) { - int length = 0; - int countryNameLength = countryName.length(); - int stateProvinceNameLength = stateProvinceName.length(); - int localityNameLength = localityName.length(); - int organizationNameLength = organizationName.length(); - int organizationalUnitNameLength = organizationalUnitName.length(); - int commonNameLength = commonName.length(); - - if (countryNameLength) { - length += (11 + countryNameLength); - } - - if (stateProvinceNameLength) { - length += (11 + stateProvinceNameLength); - } - - if (localityNameLength) { - length += (11 + localityNameLength); - } - - if (organizationNameLength) { - length += (11 + organizationNameLength); - } - - if (organizationalUnitNameLength) { - length += (11 + organizationalUnitNameLength); - } - - if (commonNameLength) { - length += (11 + commonNameLength); - } - - return length; -} - -int ECCX08CertClass::publicKeyLength() { - return (2 + 2 + 9 + 10 + 4 + 64); -} - -int ECCX08CertClass::authorityKeyIdentifierLength(const byte authorityKeyIdentifier[]) { - bool set = false; - - // check if the authority key identifier is non-zero - for (int i = 0; i < AUTHORITY_KEY_IDENTIFIER_LENGTH; i++) { - if (authorityKeyIdentifier[i] != 0) { - set = true; - break; - } - } - - return (set ? 37 : 0); -} - -int ECCX08CertClass::signatureLength(const byte signature[]) { - const byte* r = &signature[0]; - const byte* s = &signature[32]; - - int rLength = 32; - int sLength = 32; - - while (*r == 0x00 && rLength) { - r++; - rLength--; - } - - if (*r & 0x80) { - rLength++; - } - - while (*s == 0x00 && sLength) { - s++; - sLength--; - } - - if (*s & 0x80) { - sLength++; - } - - return (21 + rLength + sLength); -} - -int ECCX08CertClass::serialNumberLength(const byte serialNumber[]) { - int length = SERIAL_NUMBER_LENGTH; - - while (*serialNumber == 0 && length) { - serialNumber++; - length--; - } - - if (*serialNumber & 0x80) { - length++; - } - - return (2 + length); -} - -int ECCX08CertClass::sequenceHeaderLength(int length) { - if (length > 255) { - return 4; - } else if (length > 127) { - return 3; - } else { - return 2; - } -} - -void ECCX08CertClass::appendVersion(int version, byte out[]) { - out[0] = ASN1_INTEGER; - out[1] = 0x01; - out[2] = version; -} - -void ECCX08CertClass::appendIssuerOrSubject(const String& countryName, - const String& stateProvinceName, - const String& localityName, - const String& organizationName, - const String& organizationalUnitName, - const String& commonName, - byte out[]) { - if (countryName.length() > 0) { - out += appendName(countryName, 0x06, out); - } - - if (stateProvinceName.length() > 0) { - out += appendName(stateProvinceName, 0x08, out); - } - - if (localityName.length() > 0) { - out += appendName(localityName, 0x07, out); - } - - if (organizationName.length() > 0) { - out += appendName(organizationName, 0x0a, out); - } - - if (organizationalUnitName.length() > 0) { - out += appendName(organizationalUnitName, 0x0b, out); - } - - if (commonName.length() > 0) { - out += appendName(commonName, 0x03, out); - } -} - -void ECCX08CertClass::appendPublicKey(const byte publicKey[], byte out[]) { - int subjectPublicKeyDataLength = 2 + 9 + 10 + 4 + 64; - - // subject public key - *out++ = ASN1_SEQUENCE; - *out++ = (subjectPublicKeyDataLength) & 0xff; - - *out++ = ASN1_SEQUENCE; - *out++ = 0x13; - - // EC public key - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x07; - *out++ = 0x2a; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xce; - *out++ = 0x3d; - *out++ = 0x02; - *out++ = 0x01; - - // PRIME 256 v1 - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x08; - *out++ = 0x2a; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xce; - *out++ = 0x3d; - *out++ = 0x03; - *out++ = 0x01; - *out++ = 0x07; - - *out++ = 0x03; - *out++ = 0x42; - *out++ = 0x00; - *out++ = 0x04; - - memcpy(out, publicKey, 64); -} - -void ECCX08CertClass::appendAuthorityKeyIdentifier(const byte authorityKeyIdentifier[], byte out[]) { - // [3] - *out++ = 0xa3; - *out++ = 0x23; - - // sequence - *out++ = ASN1_SEQUENCE; - *out++ = 0x21; - - // sequence - *out++ = ASN1_SEQUENCE; - *out++ = 0x1f; - - // 2.5.29.35 authorityKeyIdentifier(X.509 extension) - *out++ = 0x06; - *out++ = 0x03; - *out++ = 0x55; - *out++ = 0x1d; - *out++ = 0x23; - - // octet string - *out++ = 0x04; - *out++ = 0x18; - - // sequence - *out++ = ASN1_SEQUENCE; - *out++ = 0x16; - - *out++ = 0x80; - *out++ = 0x14; - - memcpy(out, authorityKeyIdentifier, 20); -} - -void ECCX08CertClass::appendSignature(const byte signature[], byte out[]) { - // signature algorithm - *out++ = ASN1_SEQUENCE; - *out++ = 0x0a; - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x08; - - // ECDSA with SHA256 - *out++ = 0x2a; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xce; - *out++ = 0x3d; - *out++ = 0x04; - *out++ = 0x03; - *out++ = 0x02; - - const byte* r = &signature[0]; - const byte* s = &signature[32]; - - int rLength = 32; - int sLength = 32; - - while (*r == 0 && rLength) { - r++; - rLength--; - } - - while (*s == 0 && sLength) { - s++; - sLength--; - } - - if (*r & 0x80) { - rLength++; - } - - if (*s & 0x80) { - sLength++; - } - - *out++ = ASN1_BIT_STRING; - *out++ = (rLength + sLength + 7); - *out++ = 0; - - *out++ = ASN1_SEQUENCE; - *out++ = (rLength + sLength + 4); - - *out++ = ASN1_INTEGER; - *out++ = rLength; - if ((*r & 0x80) && rLength) { - *out++ = 0; - rLength--; - } - memcpy(out, r, rLength); - out += rLength; - - *out++ = ASN1_INTEGER; - *out++ = sLength; - if ((*s & 0x80) && sLength) { - *out++ = 0; - sLength--; - } - memcpy(out, s, sLength); - out += rLength; -} - -void ECCX08CertClass::appendSerialNumber(const byte serialNumber[], byte out[]) { - int length = SERIAL_NUMBER_LENGTH; - - while (*serialNumber == 0 && length) { - serialNumber++; - length--; - } - - if (*serialNumber & 0x80) { - length++; - } - - *out++ = ASN1_INTEGER; - *out++ = length; - - if (*serialNumber & 0x80) { - *out++ = 0x00; - length--; - } - - memcpy(out, serialNumber, length); -} - -int ECCX08CertClass::appendName(const String& name, int type, byte out[]) { - int nameLength = name.length(); - - *out++ = ASN1_SET; - *out++ = nameLength + 9; - - *out++ = ASN1_SEQUENCE; - *out++ = nameLength + 7; - - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x03; - *out++ = 0x55; - *out++ = 0x04; - *out++ = type; - - *out++ = ASN1_PRINTABLE_STRING; - *out++ = nameLength; - memcpy(out, name.c_str(), nameLength); - - return (nameLength + 11); -} - -void ECCX08CertClass::appendSequenceHeader(int length, byte out[]) { - *out++ = ASN1_SEQUENCE; - if (length > 255) { - *out++ = 0x82; - *out++ = (length >> 8) & 0xff; - } else if (length > 127) { - *out++ = 0x81; - } - *out++ = (length) & 0xff; -} - -int ECCX08CertClass::appendDate(int year, int month, int day, int hour, int minute, int second, byte out[]) { - bool useGeneralizedTime = (year > 2049); - - if (useGeneralizedTime) { - *out++ = 0x18; - *out++ = 0x0f; - *out++ = '0' + (year / 1000); - *out++ = '0' + ((year % 1000) / 100); - *out++ = '0' + ((year % 100) / 10); - *out++ = '0' + (year % 10); - } else { - year -= 2000; - - *out++ = 0x17; - *out++ = 0x0d; - *out++ = '0' + (year / 10); - *out++ = '0' + (year % 10); - } - *out++ = '0' + (month / 10); - *out++ = '0' + (month % 10); - *out++ = '0' + (day / 10); - *out++ = '0' + (day % 10); - *out++ = '0' + (hour / 10); - *out++ = '0' + (hour % 10); - *out++ = '0' + (minute / 10); - *out++ = '0' + (minute % 10); - *out++ = '0' + (second / 10); - *out++ = '0' + (second % 10); - *out++ = 0x5a; // UTC - - return (useGeneralizedTime ? 17 : 15); -} - -int ECCX08CertClass::appendEcdsaWithSHA256(byte out[]) { - *out++ = ASN1_SEQUENCE; - *out++ = 0x0A; - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x08; - *out++ = 0x2A; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xCE; - *out++ = 0x3D; - *out++ = 0x04; - *out++ = 0x03; - *out++ = 0x02; - - return 12; -} - -#endif /* BOARD_HAS_ECCX08 */ diff --git a/src/tls/utility/ECCX08Cert.h b/src/tls/utility/ECCX08Cert.h deleted file mode 100644 index 4e1ef6209..000000000 --- a/src/tls/utility/ECCX08Cert.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2019 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 _ECCX08_CERT_H_ -#define _ECCX08_CERT_H_ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include - -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) - -#include - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class ECCX08CertClass { - - public: - ECCX08CertClass(); - virtual ~ECCX08CertClass(); - - int beginCSR(int keySlot, bool newPrivateKey = true); - String endCSR(); - - int beginStorage(int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot); - void setSignature(byte signature[]); - void setIssueYear(int issueYear); - void setIssueMonth(int issueMonth); - void setIssueDay(int issueDay); - void setIssueHour(int issueHour); - void setExpireYears(int expireYears); - void setSerialNumber(const byte serialNumber[]); - void setAuthorityKeyIdentifier(const byte authorityKeyIdentifier[]); - int endStorage(); - - int beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot); - int endReconstruction(); - - byte* bytes(); - int length(); - - void setIssuerCountryName(const String& countryName); - void setIssuerStateProvinceName(const String& stateProvinceName); - void setIssuerLocalityName(const String& localityName); - void setIssuerOrganizationName(const String& organizationName); - void setIssuerOrganizationalUnitName(const String& organizationalUnitName); - void setIssuerCommonName(const String& commonName); - - void setSubjectCountryName(const String& countryName); - void setSubjectStateProvinceName(const String& stateProvinceName); - void setSubjectLocalityName(const String& localityName); - void setSubjectOrganizationName(const String& organizationName); - void setSubjectOrganizationalUnitName(const String& organizationalUnitName); - void setSubjectCommonName(const String& commonName); - - private: - int versionLength(); - - int issuerOrSubjectLength(const String& countryName, - const String& stateProvinceName, - const String& localityName, - const String& organizationName, - const String& organizationalUnitName, - const String& commonName); - - int publicKeyLength(); - - int authorityKeyIdentifierLength(const byte authorityKeyIdentifier[]); - - int signatureLength(const byte signature[]); - - int serialNumberLength(const byte serialNumber[]); - - int sequenceHeaderLength(int length); - - void appendVersion(int version, byte out[]); - - void appendIssuerOrSubject(const String& countryName, - const String& stateProvinceName, - const String& localityName, - const String& organizationName, - const String& organizationalUnitName, - const String& commonName, - byte out[]); - - void appendPublicKey(const byte publicKey[], byte out[]); - - void appendAuthorityKeyIdentifier(const byte authorityKeyIdentifier[], byte out[]); - - void appendSignature(const byte signature[], byte out[]); - - void appendSerialNumber(const byte serialNumber[], byte out[]); - - int appendName(const String& name, int type, byte out[]); - - void appendSequenceHeader(int length, byte out[]); - - int appendDate(int year, int month, int day, int hour, int minute, int second, byte out[]); - - int appendEcdsaWithSHA256(byte out[]); - - private: - int _keySlot; - int _compressedCertSlot; - int _serialNumberAndAuthorityKeyIdentifierSlot; - - String _issuerCountryName; - String _issuerStateProvinceName; - String _issuerLocalityName; - String _issuerOrganizationName; - String _issuerOrganizationalUnitName; - String _issuerCommonName; - - String _subjectCountryName; - String _subjectStateProvinceName; - String _subjectLocalityName; - String _subjectOrganizationName; - String _subjectOrganizationalUnitName; - String _subjectCommonName; - - byte _temp[108]; - byte* _bytes; - int _length; -}; - -#endif /* BOARD_HAS_ECCX08 */ - -#endif /* _ECCX08_CERT_H_ */ From 9c565ac407bd72a98dd3022a8bdc8be0b6937793 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 2 Mar 2022 08:44:54 +0100 Subject: [PATCH 282/780] Examples: update Provisioning.ino --- .../utility/Provisioning/Provisioning.ino | 99 +++++++++---------- 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/examples/utility/Provisioning/Provisioning.ino b/examples/utility/Provisioning/Provisioning.ino index e4ea8ce1b..c1503afcb 100644 --- a/examples/utility/Provisioning/Provisioning.ino +++ b/examples/utility/Provisioning/Provisioning.ino @@ -1,27 +1,22 @@ #include #include "ECCX08TLSConfig.h" -#include - const bool DEBUG = true; -const int keySlot = 0; -const int compressedCertSlot = 10; -const int serialNumberAndAuthorityKeyIdentifierSlot = 11; -const int deviceIdSlot = 12; -ECCX08CertClass ECCX08Cert; +ArduinoIoTCloudCertClass Certificate; +CryptoUtil Crypto; void setup() { Serial.begin(9600); while (!Serial); - if (!ECCX08.begin()) { - Serial.println("No ECCX08 present!"); + if (!Crypto.begin()) { + Serial.println("No crypto present!"); while (1); } - if (!ECCX08.locked()) { - String lockConfirm = promptAndReadLine("Your ECCX08 is unlocked, would you like to lock it (y/N): "); + if (!Crypto.locked()) { + String lockConfirm = promptAndReadLine("Your crypto is unlocked, would you like to lock it (y/N): "); lockConfirm.toLowerCase(); if (lockConfirm != "y") { @@ -29,17 +24,17 @@ void setup() { while (1); } - if (!ECCX08.writeConfiguration(DEFAULT_ECCX08_TLS_CONFIG)) { - Serial.println("Writing ECCX08 configuration failed!"); + if (!Crypto.writeConfiguration(DEFAULT_ECCX08_TLS_CONFIG)) { + Serial.println("Writing crypto configuration failed!"); while (1); } - if (!ECCX08.lock()) { - Serial.println("Locking ECCX08 configuration failed!"); + if (!Crypto.lock()) { + Serial.println("Locking crypto configuration failed!"); while (1); } - Serial.println("ECCX08 locked successfully"); + Serial.println("crypto locked successfully"); Serial.println(); } @@ -51,15 +46,20 @@ void setup() { while (1); } - if (!ECCX08Cert.beginCSR(keySlot, true)) { + if (!Certificate.begin()) { Serial.println("Error starting CSR generation!"); while (1); } String deviceId = promptAndReadLine("Please enter the device id: "); - ECCX08Cert.setSubjectCommonName(deviceId); + Certificate.setSubjectCommonName(deviceId); + + if (!Crypto.buildCSR(Certificate, CryptoSlot::Key, true)) { + Serial.println("Error generating CSR!"); + while (1); + } - String csr = ECCX08Cert.endCSR(); + String csr = Certificate.getCSRPEM(); if (!csr) { Serial.println("Error generating CSR!"); @@ -79,52 +79,45 @@ void setup() { String authorityKeyIdentifier = promptAndReadLine("Please enter the certificates authority key identifier: "); String signature = promptAndReadLine("Please enter the certificates signature: "); - byte deviceIdBytes[72]; - byte serialNumberBytes[16]; - byte authorityKeyIdentifierBytes[20]; - byte signatureBytes[64]; + byte serialNumberBytes[CERT_SERIAL_NUMBER_LENGTH]; + byte authorityKeyIdentifierBytes[CERT_AUTHORITY_KEY_ID_LENGTH]; + byte signatureBytes[CERT_SIGNATURE_LENGTH]; - deviceId.getBytes(deviceIdBytes, sizeof(deviceIdBytes)); hexStringToBytes(serialNumber, serialNumberBytes, sizeof(serialNumberBytes)); hexStringToBytes(authorityKeyIdentifier, authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); hexStringToBytes(signature, signatureBytes, sizeof(signatureBytes)); - if (!ECCX08.writeSlot(deviceIdSlot, deviceIdBytes, sizeof(deviceIdBytes))) { + if (!Crypto.writeDeviceId(deviceId, CryptoSlot::DeviceId)) { Serial.println("Error storing device id!"); while (1); } - if (!ECCX08Cert.beginStorage(compressedCertSlot, serialNumberAndAuthorityKeyIdentifierSlot)) { - Serial.println("Error starting ECCX08 storage!"); + if (!Certificate.begin()) { + Serial.println("Error starting crypto storage!"); while (1); } - ECCX08Cert.setSignature(signatureBytes); - ECCX08Cert.setAuthorityKeyIdentifier(authorityKeyIdentifierBytes); - ECCX08Cert.setSerialNumber(serialNumberBytes); - ECCX08Cert.setIssueYear(issueYear.toInt()); - ECCX08Cert.setIssueMonth(issueMonth.toInt()); - ECCX08Cert.setIssueDay(issueDay.toInt()); - ECCX08Cert.setIssueHour(issueHour.toInt()); - ECCX08Cert.setExpireYears(expireYears.toInt()); - - if (!ECCX08Cert.endStorage()) { - Serial.println("Error storing ECCX08 compressed cert!"); + Certificate.setSubjectCommonName(deviceId); + Certificate.setIssuerCountryName("US"); + Certificate.setIssuerOrganizationName("Arduino LLC US"); + Certificate.setIssuerOrganizationalUnitName("IT"); + Certificate.setIssuerCommonName("Arduino"); + Certificate.setSignature(signatureBytes, sizeof(signatureBytes)); + Certificate.setAuthorityKeyId(authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); + Certificate.setSerialNumber(serialNumberBytes, sizeof(serialNumberBytes)); + Certificate.setIssueYear(issueYear.toInt()); + Certificate.setIssueMonth(issueMonth.toInt()); + Certificate.setIssueDay(issueDay.toInt()); + Certificate.setIssueHour(issueHour.toInt()); + Certificate.setExpireYears(expireYears.toInt()); + + if (!Crypto.buildCert(Certificate, CryptoSlot::Key)) { + Serial.println("Error building cert!"); while (1); } - - if (!ECCX08Cert.beginReconstruction(keySlot, compressedCertSlot, serialNumberAndAuthorityKeyIdentifierSlot)) { - Serial.println("Error starting ECCX08 cert reconstruction!"); - while (1); - } - - ECCX08Cert.setIssuerCountryName("US"); - ECCX08Cert.setIssuerOrganizationName("Arduino LLC US"); - ECCX08Cert.setIssuerOrganizationalUnitName("IT"); - ECCX08Cert.setIssuerCommonName("Arduino"); - - if (!ECCX08Cert.endReconstruction()) { - Serial.println("Error reconstructing ECCX08 compressed cert!"); + + if (!Crypto.writeCert(Certificate, CryptoSlot::CompressedCertificate)) { + Serial.println("Error storing cert!"); while (1); } @@ -134,8 +127,8 @@ void setup() { Serial.println("Compressed cert = "); - const byte* certData = ECCX08Cert.bytes(); - int certLength = ECCX08Cert.length(); + const byte* certData = Certificate.bytes(); + int certLength = Certificate.length(); for (int i = 0; i < certLength; i++) { byte b = certData[i]; From bc88de4f7d920bba77f52c9588e20c635d73572b Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 2 Mar 2022 13:58:22 +0100 Subject: [PATCH 283/780] ArduinoIoTCloudCertClass: reduce RAM usage --- src/tls/utility/Cert.cpp | 14 ++++++++++---- src/tls/utility/Cert.h | 12 +++++------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/tls/utility/Cert.cpp b/src/tls/utility/Cert.cpp index 39ed76253..9a32bc97e 100644 --- a/src/tls/utility/Cert.cpp +++ b/src/tls/utility/Cert.cpp @@ -96,8 +96,9 @@ static String base64Encode(const byte in[], unsigned int length, const char* pre ******************************************************************************/ ArduinoIoTCloudCertClass::ArduinoIoTCloudCertClass() -: _certBuffer(NULL) +: _certBuffer(nullptr) , _certBufferLen(0) +, _publicKey(nullptr) { } @@ -106,7 +107,7 @@ ArduinoIoTCloudCertClass::~ArduinoIoTCloudCertClass() { if (_certBuffer) { free(_certBuffer); - _certBuffer = NULL; + _certBuffer = nullptr; } } @@ -117,7 +118,6 @@ ArduinoIoTCloudCertClass::~ArduinoIoTCloudCertClass() int ArduinoIoTCloudCertClass::begin() { memset(_compressedCert.data, 0x00, CERT_COMPRESSED_CERT_LENGTH); - memset(_publicKey, 0x00, CERT_PUBLIC_KEY_LENGTH); return 1; } @@ -146,6 +146,9 @@ int ArduinoIoTCloudCertClass::buildCSR() out += appendIssuerOrSubject(_subjectData, out); // public key + if (_publicKey == nullptr) { + return 0; + } out += appendPublicKey(_publicKey, out); // terminator @@ -243,6 +246,9 @@ int ArduinoIoTCloudCertClass::buildCert() out += appendIssuerOrSubject(_subjectData, out); // public key + if (_publicKey == nullptr) { + return 0; + } out += appendPublicKey(_publicKey, out); int authorityKeyIdLen = authorityKeyIdLength(_compressedCert.slot.two.values.authorityKeyId, CERT_AUTHORITY_KEY_ID_LENGTH); @@ -377,7 +383,7 @@ int ArduinoIoTCloudCertClass::setAuthorityKeyId(const uint8_t authorityKeyId[], int ArduinoIoTCloudCertClass::setPublicKey(const byte* publicKey, int publicKeyLen) { if (publicKeyLen == CERT_PUBLIC_KEY_LENGTH) { - memcpy(_publicKey, publicKey, CERT_PUBLIC_KEY_LENGTH); + _publicKey = publicKey; return 1; } return 0; diff --git a/src/tls/utility/Cert.h b/src/tls/utility/Cert.h index 944a2eac1..756747473 100644 --- a/src/tls/utility/Cert.h +++ b/src/tls/utility/Cert.h @@ -35,8 +35,8 @@ #define CERT_PUBLIC_KEY_LENGTH 64 #define CERT_SIGNATURE_LENGTH 64 #define CERT_DATES_LENGTH 3 -#define CERT_COMPRESSED_CERT_LENGTH 144 #define CERT_COMPRESSED_CERT_SLOT_LENGTH 72 +#define CERT_COMPRESSED_CERT_LENGTH CERT_COMPRESSED_CERT_SLOT_LENGTH + CERT_SERIAL_NUMBER_LENGTH + CERT_AUTHORITY_KEY_ID_LENGTH #include @@ -86,7 +86,7 @@ class ArduinoIoTCloudCertClass { inline byte* compressedCertSignatureAndDatesBytes() { return _compressedCert.slot.one.data; } inline int compressedCertSignatureAndDatesLength() {return CERT_COMPRESSED_CERT_SLOT_LENGTH; } inline byte* compressedCertSerialAndAuthorityKeyIdBytes() { return _compressedCert.slot.two.data; } - inline int compressedCertSerialAndAuthorityKeyIdLenght() {return CERT_COMPRESSED_CERT_SLOT_LENGTH; } + inline int compressedCertSerialAndAuthorityKeyIdLenght() {return CERT_SERIAL_NUMBER_LENGTH + CERT_AUTHORITY_KEY_ID_LENGTH; } #endif /* Build CSR */ @@ -135,9 +135,8 @@ class ArduinoIoTCloudCertClass { struct __attribute__((__packed__)) SerialNumberAndAuthorityKeyIdType { byte serialNumber[CERT_SERIAL_NUMBER_LENGTH]; byte authorityKeyId[CERT_AUTHORITY_KEY_ID_LENGTH]; - byte unused[36]; } values; - byte data[CERT_COMPRESSED_CERT_SLOT_LENGTH]; + byte data[CERT_SERIAL_NUMBER_LENGTH + CERT_AUTHORITY_KEY_ID_LENGTH]; }; union CompressedCertDataUType { @@ -145,12 +144,11 @@ class ArduinoIoTCloudCertClass { SignatureAndDateUType one; SerialNumberAndAuthorityKeyIdUType two; }slot; - byte data[CERT_COMPRESSED_CERT_LENGTH]; + byte data[CERT_COMPRESSED_CERT_SLOT_LENGTH + CERT_SERIAL_NUMBER_LENGTH + CERT_AUTHORITY_KEY_ID_LENGTH]; } _compressedCert; /* only raw EC X Y values 64 byte */ - byte _publicKey[CERT_PUBLIC_KEY_LENGTH]; - int _publicKeyLen; + const byte * _publicKey; byte * _certBuffer; int _certBufferLen; From 3215020fe6ddc494e527295eb4530b37e02464fa Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 2 Mar 2022 14:49:05 +0100 Subject: [PATCH 284/780] Bearssl: Include bearssl sha256 functions in the build also for devices using SE050 crypto --- src/tls/bearssl/dec32be.c | 2 +- src/tls/bearssl/enc32be.c | 2 +- src/tls/bearssl/sha2small.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tls/bearssl/dec32be.c b/src/tls/bearssl/dec32be.c index 1ba0968e4..064f9bf98 100644 --- a/src/tls/bearssl/dec32be.c +++ b/src/tls/bearssl/dec32be.c @@ -23,7 +23,7 @@ */ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) #include "inner.h" diff --git a/src/tls/bearssl/enc32be.c b/src/tls/bearssl/enc32be.c index dde2295d1..b6be4e13f 100644 --- a/src/tls/bearssl/enc32be.c +++ b/src/tls/bearssl/enc32be.c @@ -23,7 +23,7 @@ */ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) #include "inner.h" diff --git a/src/tls/bearssl/sha2small.c b/src/tls/bearssl/sha2small.c index c17638706..789623de0 100644 --- a/src/tls/bearssl/sha2small.c +++ b/src/tls/bearssl/sha2small.c @@ -23,7 +23,7 @@ */ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) #include "inner.h" From 4d34ba1c7f9a55feac3665f1cc35023e3666a91d Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 2 Mar 2022 14:50:56 +0100 Subject: [PATCH 285/780] ArduinoIoTCloudCertClass: include certificate class in the build also for devices using SE050 crypto --- src/tls/utility/Cert.cpp | 4 ++-- src/tls/utility/Cert.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tls/utility/Cert.cpp b/src/tls/utility/Cert.cpp index 9a32bc97e..f4ce3b42b 100644 --- a/src/tls/utility/Cert.cpp +++ b/src/tls/utility/Cert.cpp @@ -23,7 +23,7 @@ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) #include "Cert.h" @@ -915,4 +915,4 @@ int ArduinoIoTCloudCertClass::appendAuthorityKeyId(const byte authorityKeyId[], return length + 17; } -#endif /* (BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) */ +#endif /* (BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) */ diff --git a/src/tls/utility/Cert.h b/src/tls/utility/Cert.h index 756747473..45f531869 100644 --- a/src/tls/utility/Cert.h +++ b/src/tls/utility/Cert.h @@ -24,7 +24,7 @@ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) /****************************************************************************** * DEFINE @@ -182,6 +182,6 @@ class ArduinoIoTCloudCertClass { }; -#endif /* BOARD_HAS_ECCX08 || BOARD_HAS_OFFLOADED_ECCX08 */ +#endif /* BOARD_HAS_ECCX08 || BOARD_HAS_OFFLOADED_ECCX08 || BOARD_HAS_SE050*/ #endif /* ARDUINO_IOT_CLOUD_CERT_H */ From 7f72d757c8051a09ec0ae1a1aeaa9f6ccfecb61a Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 2 Mar 2022 14:53:32 +0100 Subject: [PATCH 286/780] CryptoUtil: include in the build and add support for devices using SE050 crypto --- src/tls/utility/CryptoUtil.cpp | 26 ++++++++++++++++++++++++-- src/tls/utility/CryptoUtil.h | 30 ++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/tls/utility/CryptoUtil.cpp b/src/tls/utility/CryptoUtil.cpp index 3d1fdf880..24f03121d 100644 --- a/src/tls/utility/CryptoUtil.cpp +++ b/src/tls/utility/CryptoUtil.cpp @@ -21,7 +21,7 @@ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) #include "CryptoUtil.h" #include "SHA256.h" @@ -36,7 +36,11 @@ * CTOR/DTOR **************************************************************************************/ CryptoUtil::CryptoUtil() +#if defined(BOARD_HAS_SE050) +: _crypto {SE05X} +#else : _crypto {ECCX08} +#endif { } @@ -133,6 +137,11 @@ int CryptoUtil::writeDeviceId(String & device_id, const CryptoSlot device_id_slo int CryptoUtil::writeCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot certSlot) { +#if defined(BOARD_HAS_SE050) + if (!_crypto.writeSlot(static_cast(certSlot), cert.bytes(), cert.length())) { + return 0; + } +#else if (!_crypto.writeSlot(static_cast(certSlot), cert.compressedCertSignatureAndDatesBytes(), cert.compressedCertSignatureAndDatesLength())) { return 0; } @@ -140,11 +149,23 @@ int CryptoUtil::writeCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot cert if (!_crypto.writeSlot(static_cast(certSlot) + 1, cert.compressedCertSerialAndAuthorityKeyIdBytes(), cert.compressedCertSerialAndAuthorityKeyIdLenght())) { return 0; } +#endif return 1; } int CryptoUtil::readCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot certSlot) { +#if defined(BOARD_HAS_SE050) + byte derBuffer[CRYPTO_CERT_BUFFER_LENGTH]; + size_t derLen; + if (!_crypto.readBinaryObject(static_cast(certSlot), derBuffer, sizeof(derBuffer), &derLen)) { + return 0; + } + + if (!cert.importCert(derBuffer, derLen)) { + return 0; + } +#else String deviceId; byte publicKey[CERT_PUBLIC_KEY_LENGTH]; @@ -183,7 +204,8 @@ int CryptoUtil::readCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot certS if (!cert.signCert()) { return 0; } +#endif return 1; } -#endif /* (BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) */ +#endif /* (BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) */ diff --git a/src/tls/utility/CryptoUtil.h b/src/tls/utility/CryptoUtil.h index 35da6b81e..ba75f7021 100644 --- a/src/tls/utility/CryptoUtil.h +++ b/src/tls/utility/CryptoUtil.h @@ -24,20 +24,34 @@ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) #include #include "Cert.h" + +#if defined(BOARD_HAS_SE050) +#include +#else #include +#endif + +/****************************************************************************** + * DEFINE + ******************************************************************************/ +#if defined(BOARD_HAS_SE050) +#define CRYPTO_SLOT_OFFSET 100 +#else +#define CRYPTO_SLOT_OFFSET 0 +#endif /****************************************************************************** TYPEDEF ******************************************************************************/ enum class CryptoSlot : int { - Key = 0, - CompressedCertificate = 10, - SerialNumberAndAuthorityKeyIdentifier = 11, - DeviceId = 12 + Key = (0 + CRYPTO_SLOT_OFFSET), + CompressedCertificate = (10 + CRYPTO_SLOT_OFFSET), + SerialNumberAndAuthorityKeyIdentifier = (11 + CRYPTO_SLOT_OFFSET), + DeviceId = (12 + CRYPTO_SLOT_OFFSET) }; /****************************************************************************** @@ -64,10 +78,14 @@ class CryptoUtil int readCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot certSlot); private: +#if defined(BOARD_HAS_SE050) + SE05XClass & _crypto; +#else ECCX08Class & _crypto; +#endif }; -#endif /* BOARD_HAS_ECCX08 || BOARD_HAS_OFFLOADED_ECCX08 */ +#endif /* BOARD_HAS_ECCX08 || BOARD_HAS_OFFLOADED_ECCX08 || BOARD_HAS_SE050 */ #endif /* ARDUINO_IOT_CLOUD_UTILITY_CRYPTO_CRYPTO_UTIL_H_ */ From 0d4e7904c8fb290698285d139952c850808bed39 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 2 Mar 2022 14:55:41 +0100 Subject: [PATCH 287/780] ArduinoIoTCloud: Add certificate used to verify cloud server identity. Equivalent to BearSSLTrustAnchors.h file. --- src/tls/AIoTCSSCert.h | 48 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/tls/AIoTCSSCert.h diff --git a/src/tls/AIoTCSSCert.h b/src/tls/AIoTCSSCert.h new file mode 100644 index 000000000..1dc8206d9 --- /dev/null +++ b/src/tls/AIoTCSSCert.h @@ -0,0 +1,48 @@ +/* + This file is part of ArduinoIoTBearSSL. + + Copyright 2019 ARDUINO SA (http://www.arduino.cc/) + + This software is released under the GNU General Public License version 3, + which covers the main part of ArduinoIoTBearSSL. + 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 _AIOTC_SS_CERT_H_ +#define _AIOTC_SS_CERT_H_ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include +#ifdef BOARD_HAS_SE050 + +/****************************************************************************** + * CONSTANTS + ******************************************************************************/ +static const char AIoTSSCert[] = +"-----BEGIN CERTIFICATE-----\n" +"MIIBzzCCAXSgAwIBAgIUHxAd66fhJecnwaOR4+wNF03tSlkwCgYIKoZIzj0EAwIw\n" +"RTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkFyZHVpbm8gTExDIFVTMQswCQYDVQQL\n" +"EwJJVDEQMA4GA1UEAxMHQXJkdWlubzAeFw0xODA3MjQwOTQ3MDBaFw00ODA3MTYw\n" +"OTQ3MDBaMEUxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5BcmR1aW5vIExMQyBVUzEL\n" +"MAkGA1UECxMCSVQxEDAOBgNVBAMTB0FyZHVpbm8wWTATBgcqhkjOPQIBBggqhkjO\n" +"PQMBBwNCAARtd2xaz2EcfUSYUfJe4QJAd7ecvUmio4xOq16YrIL8aVtEIne0TS6O\n" +"3ypxwTls1jkUvdlrGEtL7LPV7kKJiVUio0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD\n" +"VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWz4qa47JsBqoVOY2m4wJ+fzhuYAwCgYI\n" +"KoZIzj0EAwIDSQAwRgIhAL/T3CNmaLUK3D8NDsNz4grH92CqEA3TIL/hApabawXY\n" +"AiEA6tnZ2lrNElKXCajtZg/hjWRE/+giFzBP8riar8qOz2w=\n" +"-----END CERTIFICATE-----\n"; + +#endif /* #ifdef BOARD_HAS_SE050 */ + +#endif /* _AIOTC_SS_CERT_H_ */ From ad8fa555b97d330ceffbce12620b6f817ead2a41 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 2 Mar 2022 14:58:49 +0100 Subject: [PATCH 288/780] ArduinoIoTCloudTCP: Add support for devices using SE050 crypto and WiFiSSLSE050Client --- src/ArduinoIoTCloudTCP.cpp | 11 ++++++++++- src/ArduinoIoTCloudTCP.h | 6 ++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 00c416c87..a2f42ea4a 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -28,6 +28,11 @@ #include "tls/utility/CryptoUtil.h" #endif +#ifdef BOARD_HAS_SE050 + #include "tls/AIoTCSSCert.h" + #include "tls/utility/CryptoUtil.h" +#endif + #ifdef BOARD_HAS_OFFLOADED_ECCX08 #include #include "tls/utility/CryptoUtil.h" @@ -216,7 +221,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, } #endif - #ifdef BOARD_HAS_ECCX08 + #if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_SE050) if (!_crypto.begin()) { DEBUG_ERROR("Cryptography processor failure. Make sure you have a compatible board."); @@ -232,7 +237,11 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, DEBUG_ERROR("Cryptography certificate reconstruction failure."); return 0; } + #ifndef BOARD_HAS_SE050 _sslClient.setClient(_connection->getClient()); + #else + _sslClient.appendCustomCACert(AIoTSSCert); + #endif _sslClient.setEccSlot(static_cast(CryptoSlot::Key), _cert.bytes(), _cert.length()); #elif defined(BOARD_ESP) _sslClient.setInsecure(); diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 2167b4d19..0104e8c92 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -31,6 +31,8 @@ #include "tls/utility/CryptoUtil.h" #elif defined(BOARD_ESP) #include +#elif defined(BOARD_HAS_SE050) + #include "tls/utility/CryptoUtil.h" #endif #ifdef BOARD_HAS_OFFLOADED_ECCX08 @@ -143,6 +145,10 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #elif defined(BOARD_ESP) WiFiClientSecure _sslClient; String _password; + #elif defined(BOARD_HAS_SE050) + ArduinoIoTCloudCertClass _cert; + WiFiSSLSE050Client _sslClient; + CryptoUtil _crypto; #endif MqttClient _mqttClient; From f55081815872caa076d0412744b3cbd0f603d608 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 2 Mar 2022 16:13:41 +0100 Subject: [PATCH 289/780] ArduinoIoTCloudTCP: simplify ifdefs for _sslClient initialization --- src/ArduinoIoTCloudTCP.cpp | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index a2f42ea4a..79cfcc341 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -208,7 +208,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _ota_img_sha256 = sha256_str; #endif /* OTA_ENABLED */ - #ifdef BOARD_HAS_OFFLOADED_ECCX08 +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) if (!_crypto.begin()) { DEBUG_ERROR("_crypto.begin() failed."); @@ -219,38 +219,29 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, DEBUG_ERROR("_crypto.readDeviceId(...) failed."); return 0; } - #endif +#endif - #if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_SE050) - if (!_crypto.begin()) - { - DEBUG_ERROR("Cryptography processor failure. Make sure you have a compatible board."); - return 0; - } - if (!_crypto.readDeviceId(getDeviceId(), CryptoSlot::DeviceId)) - { - DEBUG_ERROR("Cryptography processor read failure."); - return 0; - } +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_SE050) if (!_crypto.readCert(_cert, CryptoSlot::CompressedCertificate)) { DEBUG_ERROR("Cryptography certificate reconstruction failure."); return 0; } - #ifndef BOARD_HAS_SE050 + _sslClient.setEccSlot(static_cast(CryptoSlot::Key), _cert.bytes(), _cert.length()); +#endif + +#if defined(BOARD_HAS_ECCX08) _sslClient.setClient(_connection->getClient()); - #else +#elif defined(BOARD_HAS_SE050) _sslClient.appendCustomCACert(AIoTSSCert); - #endif - _sslClient.setEccSlot(static_cast(CryptoSlot::Key), _cert.bytes(), _cert.length()); - #elif defined(BOARD_ESP) +#elif defined(BOARD_ESP) _sslClient.setInsecure(); - #endif +#endif _mqttClient.setClient(_sslClient); - #ifdef BOARD_ESP +#ifdef BOARD_ESP _mqttClient.setUsernamePassword(getDeviceId(), _password); - #endif +#endif _mqttClient.onMessage(ArduinoIoTCloudTCP::onMessage); _mqttClient.setKeepAliveInterval(30 * 1000); _mqttClient.setConnectionTimeout(1500); From a27021c6491291054b57a2875df1044a289a33a8 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 3 Mar 2022 12:50:41 +0100 Subject: [PATCH 290/780] ArduinoIoTCloudTCP: Add missing build option to correctly configure connection --- src/ArduinoIoTCloudTCP.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 0104e8c92..94f5dfd54 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -73,7 +73,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass virtual int connected () override; virtual void printDebugInfo() override; - #if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) + #if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) int begin(ConnectionHandler & connection, bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH); #else int begin(ConnectionHandler & connection, bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_USER_PASS_AUTH); From 6aad61667d21875faf9e0a3a7a952dd5bc61131e Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 4 Mar 2022 10:17:05 +0100 Subject: [PATCH 291/780] ArduinoIoTCloudTCP: Add missing include to WiFiSSLSE050Client --- src/ArduinoIoTCloudTCP.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 94f5dfd54..28c6315be 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -33,6 +33,7 @@ #include #elif defined(BOARD_HAS_SE050) #include "tls/utility/CryptoUtil.h" + #include #endif #ifdef BOARD_HAS_OFFLOADED_ECCX08 From c15eec73efce8178bdbb17dc5d50626db152d3f8 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 9 Feb 2022 09:21:09 +0100 Subject: [PATCH 292/780] Add build configuration for ARDUINO_NICLA_VISION --- src/AIoTC_Config.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index eed12f5fc..76b4dc99e 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -121,6 +121,11 @@ #define HAS_TCP #endif +#if defined(ARDUINO_NICLA_VISION) + #define BOARD_HAS_SE050 + #define HAS_TCP +#endif + #if defined(ARDUINO_AVR_UNO_WIFI_REV2) || \ defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) #define BOARD_HAS_OFFLOADED_ECCX08 From 6cfab472e653caff20eb10362ed555937a1271bd Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 9 Feb 2022 14:37:44 +0100 Subject: [PATCH 293/780] Add watchdog support for ARDUINO_NICLA_VISION --- src/ArduinoIoTCloudTCP.cpp | 4 ++-- src/utility/watchdog/Watchdog.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 79cfcc341..7ff9f201e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -38,7 +38,7 @@ #include "tls/utility/CryptoUtil.h" #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) # include "tls/utility/SHA256.h" # include # include @@ -56,7 +56,7 @@ * EXTERN ******************************************************************************/ -#if defined(ARDUINO_PORTENTA_H7_M7) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) extern RTC_HandleTypeDef RTCHandle; #endif diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index ea0324dde..21d93a395 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -90,7 +90,7 @@ void mkr_nb_feed_watchdog() static void mbed_watchdog_enable() { watchdog_config_t cfg; -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) cfg.timeout_ms = PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms; #elif defined(ARDUINO_NANO_RP2040_CONNECT) cfg.timeout_ms = NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms; @@ -116,7 +116,7 @@ static void mbed_watchdog_reset() void mbed_watchdog_trigger_reset() { watchdog_config_t cfg; -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) cfg.timeout_ms = 1; #elif defined(ARDUINO_NANO_RP2040_CONNECT) cfg.timeout_ms = 1; From 8cc111edfc3c0d93fc303e807b99a34169e7e489 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 4 Mar 2022 12:25:00 +0100 Subject: [PATCH 294/780] Add OTA support for ARDUINO_NICLA_VISION --- src/AIoTC_Config.h | 2 +- src/ArduinoIoTCloudTCP.cpp | 6 +++--- src/utility/ota/OTA-portenta-h7.cpp | 4 ++-- src/utility/ota/OTA.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 76b4dc99e..6c4080434 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -102,7 +102,7 @@ #define OTA_STORAGE_SSU (0) #endif -#if defined(ARDUINO_PORTENTA_H7_M7) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) #define OTA_STORAGE_PORTENTA_QSPI (1) #else #define OTA_STORAGE_PORTENTA_QSPI (0) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 7ff9f201e..95c05d62c 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -151,7 +151,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #endif /* AVR */ #if OTA_ENABLED && !defined(__AVR__) -#if defined(ARDUINO_PORTENTA_H7_M7) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) /* The length of the application can be retrieved the same way it was * communicated to the bootloader, that is by writing to the non-volatile * storage registers of the RTC. @@ -288,7 +288,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, } #endif /* OTA_STORAGE_SNU */ -#if defined(ARDUINO_NANO_RP2040_CONNECT) +#if defined(ARDUINO_NANO_RP2040_CONNECT) || defined(ARDUINO_NICLA_VISION) _ota_cap = true; #endif @@ -826,7 +826,7 @@ void ArduinoIoTCloudTCP::onOTARequest() _ota_error = rp2040_connect_onOTARequest(_ota_url.c_str()); #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) _ota_error = portenta_h7_onOTARequest(_ota_url.c_str()); #endif } diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index 52faf73f8..664043ae5 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -15,7 +15,7 @@ a commercial license, send an email to license@arduino.cc. */ -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) /****************************************************************************** * INCLUDE @@ -87,4 +87,4 @@ int portenta_h7_onOTARequest(char const * ota_url) NVIC_SystemReset(); } -#endif /* defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) */ +#endif /* defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) */ diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index bc92dede1..405f18430 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -62,7 +62,7 @@ int samd_onOTARequest(char const * ota_url); int rp2040_connect_onOTARequest(char const * ota_url); #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) int portenta_h7_onOTARequest(char const * ota_url); #endif From 86ff1d0762ea5ef8425a70235f8e866e42d2e150 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 4 Mar 2022 14:33:36 +0100 Subject: [PATCH 295/780] Add mbed_nicla_to supported architectures --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 5c57a7b07..494c2d234 100644 --- a/library.properties +++ b/library.properties @@ -6,6 +6,6 @@ sentence=This library allows to connect to the Arduino IoT Cloud service. paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKRGSM, MKR1000 and WiFi101. category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud -architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta +architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla includes=ArduinoIoTCloud.h depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library From fbad3a3dff1f216d9730ea3b43976e229d9fcdd0 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 8 Mar 2022 17:10:46 +0100 Subject: [PATCH 296/780] Add mbed_nicla to compile examples workflow --- .github/workflows/compile-examples.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index fc61f06b3..0331c0302 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -60,6 +60,8 @@ jobs: type: esp32 - fqbn: arduino:mbed_nano:nanorp2040connect type: nina + - fqbn: arduino:mbed_nicla:nicla_vision + type: mbed_nicla # make board type-specific customizations to the matrix jobs include: @@ -141,6 +143,15 @@ jobs: - name: Arduino_Portenta_OTA sketch-paths: | - examples/utility/Provisioning + - board: + type: mbed_nicla + platforms: | + # Install Arduino mbed-Enabled Boards via Boards Manager for the toolchain + - name: arduino:mbed_nicla + libraries: | + - name: Arduino_Portenta_OTA + sketch-paths: | + - examples/utility/Provisioning # ESP8266 boards - board: type: esp8266 From 45d5672c4473c9663720dc1f187c03bffce46c6e Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Tue, 8 Mar 2022 18:37:43 +0100 Subject: [PATCH 297/780] Release v1.6.0 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 494c2d234..ec570b5f3 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.5.0 +version=1.6.0 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 6c4080434..5ec857ca3 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -158,6 +158,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.5.0" +#define AIOT_CONFIG_LIB_VERSION "1.6.0" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 97e64723732e8b5fdddb0392524e9a07e5abfaa7 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 8 Mar 2022 21:22:23 +0100 Subject: [PATCH 298/780] Do not build OTA functions for PORTENTA_H7_M4 --- src/ArduinoIoTCloudTCP.cpp | 2 +- src/utility/ota/OTA-portenta-h7.cpp | 4 ++-- src/utility/ota/OTA.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 95c05d62c..96e959cd1 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -826,7 +826,7 @@ void ArduinoIoTCloudTCP::onOTARequest() _ota_error = rp2040_connect_onOTARequest(_ota_url.c_str()); #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) _ota_error = portenta_h7_onOTARequest(_ota_url.c_str()); #endif } diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index 664043ae5..cb8358290 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -15,7 +15,7 @@ a commercial license, send an email to license@arduino.cc. */ -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) /****************************************************************************** * INCLUDE @@ -87,4 +87,4 @@ int portenta_h7_onOTARequest(char const * ota_url) NVIC_SystemReset(); } -#endif /* defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) */ +#endif /* defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) */ diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 405f18430..d5364242a 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -62,7 +62,7 @@ int samd_onOTARequest(char const * ota_url); int rp2040_connect_onOTARequest(char const * ota_url); #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) int portenta_h7_onOTARequest(char const * ota_url); #endif From 21d91176ed8d367e85f26d46a382d40c369eab47 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 9 Mar 2022 11:21:09 +0100 Subject: [PATCH 299/780] Completely remove ARDUINO_PORTENTA_H7_M4 from the code since wifi module is not working on the M4 --- src/AIoTC_Config.h | 2 +- src/ArduinoIoTCloudTCP.cpp | 2 +- src/utility/watchdog/Watchdog.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 5ec857ca3..af76df907 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -116,7 +116,7 @@ #if defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKR1000) || \ defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_PORTENTA_H7_M7) || \ - defined(ARDUINO_PORTENTA_H7_M4) || defined (ARDUINO_NANO_RP2040_CONNECT) + defined (ARDUINO_NANO_RP2040_CONNECT) #define BOARD_HAS_ECCX08 #define HAS_TCP #endif diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 96e959cd1..4d08e4a36 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -38,7 +38,7 @@ #include "tls/utility/CryptoUtil.h" #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) # include "tls/utility/SHA256.h" # include # include diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 21d93a395..8e91b1ecd 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -90,7 +90,7 @@ void mkr_nb_feed_watchdog() static void mbed_watchdog_enable() { watchdog_config_t cfg; -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) cfg.timeout_ms = PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms; #elif defined(ARDUINO_NANO_RP2040_CONNECT) cfg.timeout_ms = NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms; @@ -116,7 +116,7 @@ static void mbed_watchdog_reset() void mbed_watchdog_trigger_reset() { watchdog_config_t cfg; -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) cfg.timeout_ms = 1; #elif defined(ARDUINO_NANO_RP2040_CONNECT) cfg.timeout_ms = 1; From c31c2da06b3e3ff0e49b70ee6347a2c1b6e9f42c Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 9 Mar 2022 11:36:42 +0100 Subject: [PATCH 300/780] Remove envie_m4 from compile-examples workflow --- .github/workflows/compile-examples.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 0331c0302..25e4c90d7 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -50,8 +50,6 @@ jobs: type: gsm - fqbn: arduino:samd:mkrnb1500 type: nb - - fqbn: arduino:mbed:envie_m4 - type: mbed - fqbn: arduino:mbed:envie_m7 type: mbed - fqbn: esp8266:esp8266:huzzah From 27a340450a191ed4495a9b634884184ad140c3b9 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 4 May 2022 08:48:15 +0200 Subject: [PATCH 301/780] Remove ArduinoBearSSL as a CI build dependency. The code formerly integrated in ArduinoBearSSL has long since been integrated with ArduinoIoTCloud library. --- .github/workflows/compile-examples.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 25e4c90d7..dc33f1379 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -88,7 +88,6 @@ jobs: - name: RTCZero - name: WiFiNINA - name: Arduino_JSON - - name: ArduinoBearSSL - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | - examples/utility/Provisioning From 956de5a52bbb92a6e3d6b34e6cbd72b4ad28b571 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 24 May 2022 11:20:07 +0200 Subject: [PATCH 302/780] TimeService: Add connected() method to check connection status --- src/utility/time/TimeService.cpp | 9 +++++++++ src/utility/time/TimeService.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 112745d06..a229de29b 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -192,6 +192,15 @@ unsigned long TimeService::getTimeFromString(const String& input) * PRIVATE MEMBER FUNCTIONS **************************************************************************************/ +bool TimeService::connected() +{ + if(_con_hdl == nullptr) { + return false; + } else { + return _con_hdl->getStatus() == NetworkConnectionState::CONNECTED; + } +} + unsigned long TimeService::getRemoteTime() { #include "../../AIoTC_Config.h" diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index fbe81986d..8d8862287 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -64,6 +64,7 @@ class TimeService unsigned long _timezone_dst_until; unsigned long getRemoteTime(); + bool connected(); static bool isTimeValid(unsigned long const time); }; From 398bef817d477e79cea3eb207bbe1eb3df9c60b4 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 24 May 2022 11:23:21 +0200 Subject: [PATCH 303/780] Check if board is connected before trying to get time from network/NTP --- src/utility/time/TimeService.cpp | 35 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index a229de29b..88c60a1a2 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -206,27 +206,26 @@ unsigned long TimeService::getRemoteTime() #include "../../AIoTC_Config.h" #ifndef HAS_LORA - if(_con_hdl == nullptr) - return EPOCH_AT_COMPILE_TIME; - - /* At first try to see if a valid time can be obtained - * using the network time available via the connection - * handler. - */ - unsigned long const connection_time = _con_hdl->getTime(); - if(isTimeValid(connection_time)) { - return connection_time; - } + if(connected()) { + /* At first try to see if a valid time can be obtained + * using the network time available via the connection + * handler. + */ + unsigned long const connection_time = _con_hdl->getTime(); + if(isTimeValid(connection_time)) { + return connection_time; + } #ifndef __AVR__ - /* If no valid network time is available try to obtain the - * time via NTP next. - */ - unsigned long const ntp_time = NTPUtils::getTime(_con_hdl->getUDP()); - if(isTimeValid(ntp_time)) { - return ntp_time; - } + /* If no valid network time is available try to obtain the + * time via NTP next. + */ + unsigned long const ntp_time = NTPUtils::getTime(_con_hdl->getUDP()); + if(isTimeValid(ntp_time)) { + return ntp_time; + } #endif + } #endif /* ifndef HAS_LORA */ From 31fcfed316020c714c27e734824aa82b596a87c0 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 30 May 2022 13:55:59 +0200 Subject: [PATCH 304/780] Release v1.6.1 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index ec570b5f3..d476a7882 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.6.0 +version=1.6.1 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index af76df907..db51f845b 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -158,6 +158,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.6.0" +#define AIOT_CONFIG_LIB_VERSION "1.6.1" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 87155dedc4a4b3b207f07a3eb9b628e7ddd7dfb9 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 6 Jul 2022 11:40:02 +0200 Subject: [PATCH 305/780] Add esp32 architecture --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index d476a7882..0d9b080b9 100644 --- a/library.properties +++ b/library.properties @@ -6,6 +6,6 @@ sentence=This library allows to connect to the Arduino IoT Cloud service. paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKRGSM, MKR1000 and WiFi101. category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud -architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla +architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32 includes=ArduinoIoTCloud.h depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library From 0e9eeb40407dd3db6199edd71ef897d9fafe3600 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 6 Jul 2022 12:06:33 +0200 Subject: [PATCH 306/780] Add ESP32 boards with link to the used core release --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 493e59ed1..f48e3e628 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ### What? The `ArduinoIoTCloud` library is the central element of the firmware enabling certain Arduino boards to connect to the [Arduino IoT Cloud](https://www.arduino.cc/en/IoT/HomePage). The following boards are supported: -* **WiFi**: [`MKR 1000`](https://store.arduino.cc/arduino-mkr1000-wifi), [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), `ESP8266` +* **WiFi**: [`MKR 1000`](https://store.arduino.cc/arduino-mkr1000-wifi), [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), `ESP8266`, [`ESP32`](https://github.com/espressif/arduino-esp32/releases/tag/1.0.6) * **GSM**: [`MKR GSM 1400`](https://store.arduino.cc/arduino-mkr-gsm-1400-1415) * **5G**: [`MKR NB 1500`](https://store.arduino.cc/arduino-mkr-nb-1500-1413) * **LoRa**: [`MKR WAN 1300/1310`](https://store.arduino.cc/mkr-wan-1310) From 77a528561037afae3de860d36f1c4a023b36adf6 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 6 Jul 2022 12:09:27 +0200 Subject: [PATCH 307/780] Add link to the core release used for ESP8266 boards --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f48e3e628..0f367550d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ### What? The `ArduinoIoTCloud` library is the central element of the firmware enabling certain Arduino boards to connect to the [Arduino IoT Cloud](https://www.arduino.cc/en/IoT/HomePage). The following boards are supported: -* **WiFi**: [`MKR 1000`](https://store.arduino.cc/arduino-mkr1000-wifi), [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), `ESP8266`, [`ESP32`](https://github.com/espressif/arduino-esp32/releases/tag/1.0.6) +* **WiFi**: [`MKR 1000`](https://store.arduino.cc/arduino-mkr1000-wifi), [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`ESP8266`](https://github.com/esp8266/Arduino/releases/tag/2.5.0), [`ESP32`](https://github.com/espressif/arduino-esp32/releases/tag/1.0.6) * **GSM**: [`MKR GSM 1400`](https://store.arduino.cc/arduino-mkr-gsm-1400-1415) * **5G**: [`MKR NB 1500`](https://store.arduino.cc/arduino-mkr-nb-1500-1413) * **LoRa**: [`MKR WAN 1300/1310`](https://store.arduino.cc/mkr-wan-1310) From ecb852ec1a432d443d1ef2fdf974055bda54be9e Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 6 Jul 2022 12:42:12 +0200 Subject: [PATCH 308/780] Add ESP boards section into FAQ --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 0f367550d..c18fd2805 100644 --- a/README.md +++ b/README.md @@ -79,3 +79,10 @@ ArduinoCloud.begin(ArduinoIoTPreferredConnection, false). ArduinoIoTCloudTCP::handle_SubscribeMqttTopics could not subscribe to /a/t/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/e/i ``` In this case either the device has not been associated with the thing within the Arduino IoT Cloud GUI configuration or there's a typo in the thing id. + +#### ESP Boards +Support for ESP boards is obtained through third-party core with some differences and limitations compared to Arduino boards. + +- **Authentication scheme**: Board authentication is done through `DEVICE_LOGIN_NAME` and `DEVICE_KEY`, both values are included in the `thingProperties.h` file. +- **RTC**: RTC support is not included thus each `ArduinoCould.update()` call will lead to an NTP request introducing delay in your `loop()` function. The scheduler widget will not work correctly if connection is lost after configuration. +- **Watchdog**: Watchdog support is not included. From c9e814b499df93c14a9b9712dceb7d9b154c8ef8 Mon Sep 17 00:00:00 2001 From: per1234 Date: Wed, 6 Jul 2022 08:40:30 -0700 Subject: [PATCH 309/780] Add comment to "Compile Examples" workflow re: esp8266:esp8266 version A specific version of the "esp8266" boards platform is installed on the Arduino Cloud servers. Since that is the primary environment the sketches using this library are compiled in, it is necessary for the "Compile Examples" GitHub Actions workflow to use the same version of the platform when running the test compilations of the library examples in order to ensure the results from the CI system will match those from real usage. This requirement is not obvious. Since the workflow does not pin the other platform versions (because Arduino Cloud typically uses the latest version), the pinning of this platform specifically might be the source of confusion for the maintainers. So it is worth documenting the reason. --- .github/workflows/compile-examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 25e4c90d7..f7c88d425 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -157,6 +157,7 @@ jobs: # Install ESP8266 platform via Boards Manager - name: esp8266:esp8266 source-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json + # Use the version currently installed in Arduino Cloud version: 2.5.0 libraries: sketch-paths: From 7e73a36ed39230ee140b79bc9b093436a43745b7 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 7 Jul 2022 13:27:30 +0200 Subject: [PATCH 310/780] Fix variable initialization order The change will fix a build error raised with the last esp32 core 2.0.4 --- src/ArduinoIoTCloud.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 0b2794ade..0d9102d67 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -32,8 +32,8 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() , _tz_offset{0} , _tz_dst_until{0} , _thing_id{""} -, _device_id{""} , _lib_version{AIOT_CONFIG_LIB_VERSION} +, _device_id{""} , _cloud_event_callback{nullptr} , _thing_id_outdated{false} { From ac87510024a5cf8b049f2ada090fbfe61e410faf Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 7 Jul 2022 16:31:26 +0200 Subject: [PATCH 311/780] Ignore unused-variable warning for internal_posix_time variable Otherwise in combination with -Werror=all used in newer ESP32 cores will trigger a compilation error. --- src/ArduinoIoTCloudTCP.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 4d08e4a36..5aab44f95 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -387,7 +387,10 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" unsigned long const internal_posix_time = _time_service.getTime(); +#pragma GCC diagnostic pop DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); return State::ConnectMqttBroker; } From 5b03e5062b10f414896a3d66d26c86c6971a7f04 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 7 Jul 2022 16:34:32 +0200 Subject: [PATCH 312/780] Declare is_watchdog_enabled only for platform supporting watchdog --- src/utility/watchdog/Watchdog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 8e91b1ecd..7fdbbd347 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -41,8 +41,9 @@ /****************************************************************************** * GLOBAL VARIABLES ******************************************************************************/ - +#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_MBED) static bool is_watchdog_enabled = false; +#endif /****************************************************************************** * FUNCTION DEFINITION From c0ac252e3920b1f823be62998377dfb570509814 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 7 Jul 2022 16:35:28 +0200 Subject: [PATCH 313/780] Ignore unused funtion warning Otherwise in combination with -Werror=all used in newer ESP32 cores will trigger a compilation er ror. --- src/cbor/lib/tinycbor/src/open_memstream.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cbor/lib/tinycbor/src/open_memstream.c b/src/cbor/lib/tinycbor/src/open_memstream.c index 707dbb1c4..4d79a726e 100644 --- a/src/cbor/lib/tinycbor/src/open_memstream.c +++ b/src/cbor/lib/tinycbor/src/open_memstream.c @@ -46,6 +46,7 @@ typedef size_t LenType; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" #pragma GCC diagnostic ignored "-Wreturn-type" +#pragma GCC diagnostic ignored "-Wunused-function" struct Buffer { From 0b7789489983a105c0de4a59b85d0750423677e4 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 20 Jul 2022 10:41:45 +0200 Subject: [PATCH 314/780] Fix SelfProvisioning example build using SHA256 from ArduinoIoTCloud library --- examples/utility/SelfProvisioning/ECCX08Cert.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/examples/utility/SelfProvisioning/ECCX08Cert.cpp b/examples/utility/SelfProvisioning/ECCX08Cert.cpp index a2e199e62..db037d4e0 100644 --- a/examples/utility/SelfProvisioning/ECCX08Cert.cpp +++ b/examples/utility/SelfProvisioning/ECCX08Cert.cpp @@ -19,12 +19,10 @@ * INCLUDE ******************************************************************************/ -#include - -#include "bearssl/bearssl_hash.h" +#include #include - #include "ECCX08Cert.h" +#include "tls/utility/SHA256.h" /****************************************************************************** * DEFINE @@ -190,13 +188,13 @@ String ECCX08CertClass::endCSR() { *out++ = 0xa0; *out++ = 0x00; - br_sha256_context sha256Context; + SHA256 sha256; byte csrInfoSha256[64]; byte signature[64]; - br_sha256_init(&sha256Context); - br_sha256_update(&sha256Context, csrInfo, csrInfoHeaderLen + csrInfoLen); - br_sha256_out(&sha256Context, csrInfoSha256); + sha256.begin(); + sha256.update(csrInfo, csrInfoHeaderLen + csrInfoLen); + sha256.finalize(csrInfoSha256); if (!ECCX08.ecSign(_keySlot, csrInfoSha256, signature)) { return ""; From dc034517ae9e53b4bdde007946d4081b502b88c9 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 21 Jul 2022 09:18:46 +0200 Subject: [PATCH 315/780] remove setThingId(THING_ID) from examples --- examples/ArduinoIoTCloud-Advanced/thingProperties.h | 2 -- examples/ArduinoIoTCloud-Basic/thingProperties.h | 2 -- examples/ArduinoIoTCloud-Callbacks/thingProperties.h | 3 --- examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h | 2 -- examples/ArduinoIoTCloud-Schedule/thingProperties.h | 2 -- .../utility/ArduinoIoTCloud_Travis_CI/thingProperties.h | 8 -------- 6 files changed, 19 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index ad9788514..eff1564b7 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -1,7 +1,6 @@ #include #include -#define THING_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" void onSwitchButtonChange(); @@ -16,7 +15,6 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif - ArduinoCloud.setThingId(THING_ID); #if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) ArduinoCloud.addProperty(switchButton, WRITE, ON_CHANGE, onSwitchButtonChange); ArduinoCloud.addProperty(location, READ, ON_CHANGE); diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index fbf2ea960..5d3de1619 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -9,7 +9,6 @@ #error "Arduino IoT Cloud currently only supports MKR1000, MKR WiFi 1010, MKR WAN 1300/1310, MKR NB 1500 and MKR GSM 1400" #endif -#define THING_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" void onLedChange(); @@ -23,7 +22,6 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif - ArduinoCloud.setThingId(THING_ID); #if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) ArduinoCloud.addProperty(led, Permission::Write).onUpdate(onLedChange); ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10); diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index 9b2aa47b6..4eda5314a 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -9,8 +9,6 @@ #error "Arduino IoT Cloud currently only supports MKR1000, MKR WiFi 1010, MKR WAN 1300/1310, MKR NB 1500 and MKR GSM 1400" #endif -#define THING_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" - /* BOARD_ID is only required if you are using an ESP8266 */ #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" @@ -19,7 +17,6 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif - ArduinoCloud.setThingId(THING_ID); } #if defined(BOARD_HAS_WIFI) diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index 549f80f7b..2f84ea4f3 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -9,7 +9,6 @@ #error "Arduino IoT Cloud currently only supports MKR1000, MKR WiFi 1010, MKR WAN 1300/1310, MKR NB 1500 and MKR GSM 1400" #endif -#define THING_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" void onLedChange(); @@ -21,7 +20,6 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif - ArduinoCloud.setThingId(THING_ID); #if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) ArduinoCloud.addProperty(led, Permission::Write).onUpdate(onLedChange); #elif defined(BOARD_HAS_LORA) diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index a426978ce..63231a700 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -1,7 +1,6 @@ #include #include -#define THING_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" void onSwitchButtonChange(); @@ -20,7 +19,6 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif - ArduinoCloud.setThingId(THING_ID); #if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) ArduinoCloud.addProperty(switchButton, WRITE, ON_CHANGE); ArduinoCloud.addProperty(oneShot, READWRITE, ON_CHANGE); diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index c0dded7a5..c21820265 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -13,12 +13,6 @@ #error "Arduino IoT Cloud currently only supports MKR1000, MKR WiFi 1010, MKR WAN 1300/1310, MKR NB 1500 and MKR GSM 1400" #endif -/****************************************************************************** - DEFINES - ******************************************************************************/ - -#define THING_ID "ARDUINO_IOT_CLOUD_THING_ID" - /****************************************************************************** GLOBAL CONSTANTS ******************************************************************************/ @@ -78,7 +72,6 @@ void onStringPropertyChange(); ******************************************************************************/ #if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined (BOARD_HAS_NB) void initProperties() { - ArduinoCloud.setThingId(THING_ID); ArduinoCloud.addProperty(bool_property_1, READWRITE, 1 * SECONDS); ArduinoCloud.addProperty(int_property_1, READ, 2 * MINUTES); @@ -109,7 +102,6 @@ void initProperties() { #elif defined(BOARD_HAS_LORA) void initProperties() { - ArduinoCloud.setThingId(THING_ID); ArduinoCloud.addProperty(bool_property_1, 1, READWRITE, 1 * SECONDS); ArduinoCloud.addProperty(int_property_1, 2, READ, 2 * MINUTES); From cd1b6b17598fa27d5d6be5e146007ceefca0ed2c Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 1 Aug 2022 13:19:35 +0200 Subject: [PATCH 316/780] README: Add Nicla Vision and Nano RP2040 Connect --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c18fd2805..eb830114c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ### What? The `ArduinoIoTCloud` library is the central element of the firmware enabling certain Arduino boards to connect to the [Arduino IoT Cloud](https://www.arduino.cc/en/IoT/HomePage). The following boards are supported: -* **WiFi**: [`MKR 1000`](https://store.arduino.cc/arduino-mkr1000-wifi), [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`ESP8266`](https://github.com/esp8266/Arduino/releases/tag/2.5.0), [`ESP32`](https://github.com/espressif/arduino-esp32/releases/tag/1.0.6) +* **WiFi**: [`MKR 1000`](https://store.arduino.cc/arduino-mkr1000-wifi), [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`Nano RP2040 Connect`](https://store.arduino.cc/products/arduino-nano-rp2040-connect), [`Nicla Vision`](https://store.arduino.cc/products/nicla-vision), [`ESP8266`](https://github.com/esp8266/Arduino/releases/tag/2.5.0), [`ESP32`](https://github.com/espressif/arduino-esp32/releases/tag/1.0.6) * **GSM**: [`MKR GSM 1400`](https://store.arduino.cc/arduino-mkr-gsm-1400-1415) * **5G**: [`MKR NB 1500`](https://store.arduino.cc/arduino-mkr-nb-1500-1413) * **LoRa**: [`MKR WAN 1300/1310`](https://store.arduino.cc/mkr-wan-1310) From 2e0c1e7bd0c68b0a86bfdb01196c9faddac26564 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 1 Aug 2022 13:28:33 +0200 Subject: [PATCH 317/780] README: Add list of boards supporting OTA --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index c18fd2805..f2cd1ae79 100644 --- a/README.md +++ b/README.md @@ -80,9 +80,14 @@ ArduinoIoTCloudTCP::handle_SubscribeMqttTopics could not subscribe to /a/t/xxxxx ``` In this case either the device has not been associated with the thing within the Arduino IoT Cloud GUI configuration or there's a typo in the thing id. +#### OTA +OTA is supported by the following boards: +[`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`Nano RP2040 Connect`](https://store.arduino.cc/products/arduino-nano-rp2040-connect), [`Nicla Vision`](https://store.arduino.cc/products/nicla-vision) + #### ESP Boards Support for ESP boards is obtained through third-party core with some differences and limitations compared to Arduino boards. - **Authentication scheme**: Board authentication is done through `DEVICE_LOGIN_NAME` and `DEVICE_KEY`, both values are included in the `thingProperties.h` file. - **RTC**: RTC support is not included thus each `ArduinoCould.update()` call will lead to an NTP request introducing delay in your `loop()` function. The scheduler widget will not work correctly if connection is lost after configuration. - **Watchdog**: Watchdog support is not included. +- **OTA**: OTA support is not included From ffc3d830fdf973a43f8359244059abd7a5791075 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 29 Jul 2022 09:05:58 +0200 Subject: [PATCH 318/780] Use escape sequence \x1b to clear messenger widget --- src/property/Property.cpp | 8 ++++++++ src/property/Property.h | 8 ++++++++ src/property/types/CloudString.h | 3 +++ 3 files changed, 19 insertions(+) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index 243c2ab47..833d9c68d 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -55,6 +55,14 @@ Property::Property() } +/****************************************************************************** + CONST + ******************************************************************************/ +namespace PropertyActions +{ + const String CLEAR = "\x1b"; +} + /****************************************************************************** PUBLIC MEMBER FUNCTIONS ******************************************************************************/ diff --git a/src/property/Property.h b/src/property/Property.h index bc7aa665a..6571bf625 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -51,6 +51,14 @@ #define appendAttribute(x) appendAttributeReal(x, getAttributeName(#x, '.'), encoder) #define setAttribute(x) setAttributeReal(x, getAttributeName(#x, '.')) +/****************************************************************************** + CONST + ******************************************************************************/ +namespace PropertyActions +{ + extern const String CLEAR; +} + /****************************************************************************** ENUM ******************************************************************************/ diff --git a/src/property/types/CloudString.h b/src/property/types/CloudString.h index 027179411..f07f59ccf 100644 --- a/src/property/types/CloudString.h +++ b/src/property/types/CloudString.h @@ -46,6 +46,9 @@ class CloudString : public Property { operator String() const { return _value; } + void clear() { + _value = PropertyActions::CLEAR; + } virtual bool isDifferentFromCloud() { return _value != _cloud_value; } From 9673032ac981dbc40134f1d4132aecedb3bd5776 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Tue, 2 Aug 2022 16:53:57 +0200 Subject: [PATCH 319/780] Release v1.7.0 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 0d9b080b9..75ecb7a71 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.6.1 +version=1.7.0 author=Arduino maintainer=Arduino sentence=This library allows to connect to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index db51f845b..c81a298c9 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -158,6 +158,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.6.1" +#define AIOT_CONFIG_LIB_VERSION "1.7.0" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 90d659c40f8474d5f837b0d647eaf28fee232c48 Mon Sep 17 00:00:00 2001 From: per1234 Date: Thu, 8 Sep 2022 04:13:02 -0700 Subject: [PATCH 320/780] Exclude BearSSL library files from spell check The latest release of the codespell tool used for automated spell checking of the files of this project included an expansion of the misspelled words dictionary. This caused the spell checker to trigger on some content in the BearSSL library vendored in this project. These included both false and true positives. Although the former can be fixed by ignoring the specific word and the latter by fixing the typo, it doesn't really make sense to be checking these files which appear to be mostly copies of content maintained externally. For this reason, the best approach will be to exclude the files from the check entirely. --- .codespellrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codespellrc b/.codespellrc index b6200a41d..66275a3f7 100644 --- a/.codespellrc +++ b/.codespellrc @@ -4,4 +4,4 @@ ignore-words-list = alocation,wan check-filenames = check-hidden = -skip = ./.git,./extras/test/external,./src/cbor/lib/tinycbor +skip = ./.git,./extras/test/external,./src/cbor/lib/tinycbor,./src/tls/bearssl From 80d22e97cf438958819265a64b778a6734333a82 Mon Sep 17 00:00:00 2001 From: per1234 Date: Thu, 8 Sep 2022 04:33:26 -0700 Subject: [PATCH 321/780] Fix spell check false positive by ignoring word In the latest release of the codespell tool used for automated spell checking of the files of this project, the word "bu" was added to the codespell misspelled words dictionary as a misspelling of "by". This caused a false detection of a CBOR map label `bu` as a misspelling, resulting in a failing spell check result. Since the occurrence of this word is correct and intended in this project, the false positive is resolved by configuring codespell to ignore the problematic word. --- .codespellrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codespellrc b/.codespellrc index 66275a3f7..b10d11ce9 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,7 +1,7 @@ # See: https://github.com/codespell-project/codespell#using-a-config-file [codespell] # In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here: -ignore-words-list = alocation,wan +ignore-words-list = alocation,bu,wan check-filenames = check-hidden = skip = ./.git,./extras/test/external,./src/cbor/lib/tinycbor,./src/tls/bearssl From 292e1b16808b80a4d9dc555abdb831122260ba72 Mon Sep 17 00:00:00 2001 From: per1234 Date: Thu, 8 Sep 2022 05:17:01 -0700 Subject: [PATCH 322/780] Fix typos in documentation --- README.md | 6 +++--- .../ArduinoIoTCloud-Advanced.ino | 4 ++-- .../ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino | 6 +++--- .../ArduinoIoTCloud-Callbacks.ino | 6 +++--- .../ArduinoIoTCloud-DeferredOTA.ino | 2 +- .../ArduinoIoTCloud-Schedule.ino | 4 ++-- .../ArduinoIoTCloud_Travis_CI.ino | 2 +- examples/utility/Provisioning/Provisioning.ino | 4 ++-- extras/test/src/test_CloudLocation.cpp | 12 ++++++------ extras/test/src/test_CloudSchedule.cpp | 2 +- extras/test/src/test_publishOnChange.cpp | 2 +- extras/test/src/test_publishOnChangeRateLimit.cpp | 2 +- extras/test/src/test_readOnly.cpp | 2 +- extras/test/src/test_writeOnly.cpp | 2 +- library.properties | 4 ++-- src/ArduinoIoTCloudTCP.cpp | 8 ++++---- src/cbor/CBOREncoder.cpp | 6 +++--- src/utility/ota/OTA-samd.cpp | 2 +- 18 files changed, 38 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 3c4a8473d..cde81db0b 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ void onLedChange() { ### FAQ #### Watchdog -This [1.0.0](https://github.com/arduino-libraries/ArduinoIoTCloud/releases/tag/1.0.0) release of this library adds watchdog functionality to all ATSAMD21G18 based cloud connected boards. A watchdog is simply an electronic timer counting down from a preset start value which, upon reaching zero, triggers a reset of the microcontroller. It can be used to automatically recover from temporary hardware faults or unrecoverable software errors. In order to avoid the watchdog from reaching zero the countdown timer needs to be regularly re-set to its start value. This is happening within `ArduinoCloud.update()` which is periodically called at the start of the `loop()` function. Although the watchdog is automatically enabled it can be disabled by setting the second parameter of `ArduinoCloud.begin(...)` to `false`: +The [1.0.0](https://github.com/arduino-libraries/ArduinoIoTCloud/releases/tag/1.0.0) release of this library adds watchdog functionality to all ATSAMD21G18 based cloud connected boards. A watchdog is simply an electronic timer counting down from a preset start value which, upon reaching zero, triggers a reset of the microcontroller. It can be used to automatically recover from temporary hardware faults or unrecoverable software errors. In order to avoid the watchdog from reaching zero the countdown timer needs to be regularly re-set to its start value. This is happening within `ArduinoCloud.update()` which is periodically called at the start of the `loop()` function. Although the watchdog is automatically enabled it can be disabled by setting the second parameter of `ArduinoCloud.begin(...)` to `false`: ```C++ ArduinoCloud.begin(ArduinoIoTPreferredConnection, false). ``` @@ -78,14 +78,14 @@ ArduinoCloud.begin(ArduinoIoTPreferredConnection, false). ``` ArduinoIoTCloudTCP::handle_SubscribeMqttTopics could not subscribe to /a/t/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/e/i ``` -In this case either the device has not been associated with the thing within the Arduino IoT Cloud GUI configuration or there's a typo in the thing id. +In this case either the device has not been associated with the thing within the Arduino IoT Cloud GUI configuration or there's a typo in the thing ID. #### OTA OTA is supported by the following boards: [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`Nano RP2040 Connect`](https://store.arduino.cc/products/arduino-nano-rp2040-connect), [`Nicla Vision`](https://store.arduino.cc/products/nicla-vision) #### ESP Boards -Support for ESP boards is obtained through third-party core with some differences and limitations compared to Arduino boards. +Support for ESP boards is obtained through a third-party core with some differences and limitations compared to Arduino boards. - **Authentication scheme**: Board authentication is done through `DEVICE_LOGIN_NAME` and `DEVICE_KEY`, both values are included in the `thingProperties.h` file. - **RTC**: RTC support is not included thus each `ArduinoCould.update()` call will lead to an NTP request introducing delay in your `loop()` function. The scheduler widget will not work correctly if connection is lost after configuration. diff --git a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino index aa19f05ab..247860cff 100644 --- a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino +++ b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino @@ -3,12 +3,12 @@ This sketch is compatible with: - MKR 1000 - - MKR WIFI 1010 + - MKR WiFi 1010 - MKR GSM 1400 - MKR NB 1500 - MKR WAN 1300/1310 - Nano 33 IoT - - ESP 8266 + - ESP8266 */ #include "arduino_secrets.h" diff --git a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino index 011a1fef8..097afb6f3 100644 --- a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino +++ b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino @@ -7,17 +7,17 @@ IMPORTANT: This sketch works with WiFi, GSM, NB and Lora enabled boards supported by Arduino IoT Cloud. - On a LoRa board, if it is configuered as a class A device (default and preferred option), values from Cloud dashboard are received + On a LoRa board, if it is configured as a class A device (default and preferred option), values from Cloud dashboard are received only after a value is sent to Cloud. This sketch is compatible with: - MKR 1000 - - MKR WIFI 1010 + - MKR WiFi 1010 - MKR GSM 1400 - MKR NB 1500 - MKR WAN 1300/1310 - Nano 33 IoT - - ESP 8266 + - ESP8266 */ #include "arduino_secrets.h" diff --git a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino index f78417218..27c9d8f4d 100644 --- a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino +++ b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino @@ -19,17 +19,17 @@ IMPORTANT: This sketch works with WiFi, GSM, NB and Lora enabled boards supported by Arduino IoT Cloud. - On a LoRa board, if it is configuered as a class A device (default and preferred option), values from Cloud dashboard are received + On a LoRa board, if it is configured as a class A device (default and preferred option), values from Cloud dashboard are received only after a value is sent to Cloud. This sketch is compatible with: - MKR 1000 - - MKR WIFI 1010 + - MKR WiFi 1010 - MKR GSM 1400 - MKR NB 1500 - MKR WAN 1300/1310 - Nano 33 IoT - - ESP 8266 + - ESP8266 */ #include "arduino_secrets.h" diff --git a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino index 34abcdc38..bd5b6a4d2 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino +++ b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino @@ -10,7 +10,7 @@ * ask_user_via_serial callback will read user input from serial to apply or postpone OTA update This sketch is compatible with: - - MKR WIFI 1010 + - MKR WiFi 1010 - Nano 33 IoT - Portenta - Nano RP2040 diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index 3e01f9703..3c97e49f4 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -3,11 +3,11 @@ This sketch is compatible with the following boards: - MKR 1000 - - MKR WIFI 1010 + - MKR WiFi 1010 - MKR GSM 1400 - MKR NB 1500 - Nano 33 IoT - - ESP 8266 + - ESP8266 */ #include "arduino_secrets.h" diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino b/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino index bcb46b680..d74f9bc66 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino @@ -1,6 +1,6 @@ /* This sketch is used in combination with Travis CI to check if - unintentional breaking changes are made to the used facing + unintentional breaking changes are made to the user facing Arduino IoT Cloud API. This sketch is compatible with: diff --git a/examples/utility/Provisioning/Provisioning.ino b/examples/utility/Provisioning/Provisioning.ino index c1503afcb..97394fc2c 100644 --- a/examples/utility/Provisioning/Provisioning.ino +++ b/examples/utility/Provisioning/Provisioning.ino @@ -51,7 +51,7 @@ void setup() { while (1); } - String deviceId = promptAndReadLine("Please enter the device id: "); + String deviceId = promptAndReadLine("Please enter the device ID: "); Certificate.setSubjectCommonName(deviceId); if (!Crypto.buildCSR(Certificate, CryptoSlot::Key, true)) { @@ -88,7 +88,7 @@ void setup() { hexStringToBytes(signature, signatureBytes, sizeof(signatureBytes)); if (!Crypto.writeDeviceId(deviceId, CryptoSlot::DeviceId)) { - Serial.println("Error storing device id!"); + Serial.println("Error storing device ID!"); while (1); } diff --git a/extras/test/src/test_CloudLocation.cpp b/extras/test/src/test_CloudLocation.cpp index d9acd0ae4..a24186d91 100644 --- a/extras/test/src/test_CloudLocation.cpp +++ b/extras/test/src/test_CloudLocation.cpp @@ -14,7 +14,7 @@ TEST CODE **************************************************************************************/ -SCENARIO("Tesing cloud type 'Location' Ctor", "[Location::Location]") +SCENARIO("Testing cloud type 'Location' Ctor", "[Location::Location]") { WHEN("A Location(1.0f, 2.0f) is being instantiated") { @@ -30,7 +30,7 @@ SCENARIO("Tesing cloud type 'Location' Ctor", "[Location::Location]") /**************************************************************************************/ -SCENARIO("Tesing cloud type 'Location' assignment operator", "[Location::operator =]") +SCENARIO("Testing cloud type 'Location' assignment operator", "[Location::operator =]") { Location loc1(1.0f, 2.0f), loc2(3.0f, 4.0f); @@ -47,7 +47,7 @@ SCENARIO("Tesing cloud type 'Location' assignment operator", "[Location::operato /**************************************************************************************/ -SCENARIO("Tesing cloud type 'Location' operator -", "[Location::operator -]") +SCENARIO("Testing cloud type 'Location' operator -", "[Location::operator -]") { Location loc1(1.0f, 2.0f), loc2(3.0f, 4.0f); @@ -64,7 +64,7 @@ SCENARIO("Tesing cloud type 'Location' operator -", "[Location::operator -]") /**************************************************************************************/ -SCENARIO("Tesing cloud type 'Location' comparison operator ==", "[Location::operator ==]") +SCENARIO("Testing cloud type 'Location' comparison operator ==", "[Location::operator ==]") { Location loc1(1.0f, 2.0f), loc2(3.0f, 4.0f), @@ -87,7 +87,7 @@ SCENARIO("Tesing cloud type 'Location' comparison operator ==", "[Location::oper /**************************************************************************************/ -SCENARIO("Tesing cloud type 'Location' comparison operator !=", "[Location::operator !=]") +SCENARIO("Testing cloud type 'Location' comparison operator !=", "[Location::operator !=]") { Location loc1(1.0f, 2.0f), loc2(3.0f, 4.0f), @@ -110,7 +110,7 @@ SCENARIO("Tesing cloud type 'Location' comparison operator !=", "[Location::oper /**************************************************************************************/ -SCENARIO("Tesing cloud type 'Location' function distance for calculating euclidean 2d distance between two points", "[Location::distance]") +SCENARIO("Testing cloud type 'Location' function distance for calculating Euclidean 2d distance between two points", "[Location::distance]") { Location loc1(0.0f, 0.0f), loc2(1.0f, 1.0f); diff --git a/extras/test/src/test_CloudSchedule.cpp b/extras/test/src/test_CloudSchedule.cpp index 53b582aef..88acad6ab 100644 --- a/extras/test/src/test_CloudSchedule.cpp +++ b/extras/test/src/test_CloudSchedule.cpp @@ -28,7 +28,7 @@ unsigned long TimeService::getLocalTime() {return time_now;} TEST CODE **************************************************************************************/ -SCENARIO("Tesing cloud type 'Schedule' Ctor", "[Schedule::Schedule]") +SCENARIO("Testing cloud type 'Schedule' Ctor", "[Schedule::Schedule]") { WHEN("A Schedule(0,0,0,0) is being instantiated") { diff --git a/extras/test/src/test_publishOnChange.cpp b/extras/test/src/test_publishOnChange.cpp index 7b4592790..8d5f3f533 100644 --- a/extras/test/src/test_publishOnChange.cpp +++ b/extras/test/src/test_publishOnChange.cpp @@ -14,7 +14,7 @@ TEST CODE **************************************************************************************/ -SCENARIO("A Arduino cloud property is published on value change", "[ArduinoCloudThing::publishOnChange]") +SCENARIO("An Arduino cloud property is published on value change", "[ArduinoCloudThing::publishOnChange]") { PropertyContainer property_container; diff --git a/extras/test/src/test_publishOnChangeRateLimit.cpp b/extras/test/src/test_publishOnChangeRateLimit.cpp index 9f96a5610..92f8bc40e 100644 --- a/extras/test/src/test_publishOnChangeRateLimit.cpp +++ b/extras/test/src/test_publishOnChangeRateLimit.cpp @@ -14,7 +14,7 @@ TEST CODE **************************************************************************************/ -SCENARIO("A Arduino cloud property is published on value change but the update rate is limited", "[ArduinoCloudThing::publishOnChange]") +SCENARIO("An Arduino cloud property is published on value change but the update rate is limited", "[ArduinoCloudThing::publishOnChange]") { PropertyContainer property_container; diff --git a/extras/test/src/test_readOnly.cpp b/extras/test/src/test_readOnly.cpp index ef080922d..91bcf5cab 100644 --- a/extras/test/src/test_readOnly.cpp +++ b/extras/test/src/test_readOnly.cpp @@ -17,7 +17,7 @@ TEST CODE **************************************************************************************/ -SCENARIO("A Arduino cloud property is marked 'read only'", "[ArduinoCloudThing::decode]") +SCENARIO("An Arduino cloud property is marked 'read only'", "[ArduinoCloudThing::decode]") { PropertyContainer property_container; diff --git a/extras/test/src/test_writeOnly.cpp b/extras/test/src/test_writeOnly.cpp index 82283752e..6a45c3494 100644 --- a/extras/test/src/test_writeOnly.cpp +++ b/extras/test/src/test_writeOnly.cpp @@ -17,7 +17,7 @@ TEST CODE **************************************************************************************/ -SCENARIO("A Arduino cloud property is marked 'write only'", "[ArduinoCloudThing::encode]") +SCENARIO("An Arduino cloud property is marked 'write only'", "[ArduinoCloudThing::encode]") { PropertyContainer property_container; diff --git a/library.properties b/library.properties index 75ecb7a71..e15d45ab0 100644 --- a/library.properties +++ b/library.properties @@ -2,8 +2,8 @@ name=ArduinoIoTCloud version=1.7.0 author=Arduino maintainer=Arduino -sentence=This library allows to connect to the Arduino IoT Cloud service. -paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKRGSM, MKR1000 and WiFi101. +sentence=This library allows connecting to the Arduino IoT Cloud service. +paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKR GSM, MKR1000 and WiFi101. category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32 diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 5aab44f95..f7e0c4ca6 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -344,8 +344,8 @@ void ArduinoIoTCloudTCP::update() } _state = next_state; - /* This watchdog feed is actually needed only by the RP2040 CONNECT cause its - * maximum watchdog window is 8389ms; despite this we feed it for all + /* This watchdog feed is actually needed only by the RP2040 Connect because its + * maximum watchdog window is 8389 ms; despite this we feed it for all * supported ARCH to keep code aligned. */ #if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) @@ -488,7 +488,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() if(_deviceSubscribedToThing == true) { - /* Unsubscribe from old things topics and go on with a new subsctiption */ + /* Unsubscribe from old things topics and go on with a new subscription */ _mqttClient.unsubscribe(_shadowTopicIn); _mqttClient.unsubscribe(_dataTopicIn); _deviceSubscribedToThing = false; @@ -570,7 +570,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); _deviceSubscribedToThing = true; - /*Add retry wait time otherwise we are trying to reconnect every 250ms...*/ + /*Add retry wait time otherwise we are trying to reconnect every 250 ms...*/ return State::RequestLastValues; } diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index b15b20837..d166756d4 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -138,7 +138,7 @@ CBOREncoder::EncoderState CBOREncoder::handle_OutOfMemory(PropertyContainerEncod CBOREncoder::EncoderState CBOREncoder::handle_SkipProperty(PropertyContainerEncoder & propertyEncoder) { /* Better to skip this property otherwise we will stay blocked here. This happens only with a message property - * that not fits into the CBOR buffer + * that doesn't fit into the CBOR buffer */ propertyEncoder.current_property_index++; if(propertyEncoder.current_property_index >= propertyEncoder.property_container.size()) @@ -182,7 +182,7 @@ CBOREncoder::EncoderState CBOREncoder::handle_FinishAppend(PropertyContainerEnco /* Restore property message limit to CBOR_ENCODER_NO_PROPERTIES_LIMIT */ propertyEncoder.property_limit_active = false; - /* The append process has been successful, so we don't need to terty to send this properties set. Cleanup _has_been_appended_but_not_sended flag */ + /* The append process has been successful, so we don't need to try to send this properties set. Cleanup _has_been_appended_but_not_sended flag */ PropertyContainer::iterator iter = propertyEncoder.property_container.begin(); std::advance(iter, propertyEncoder.current_property_index); int num_appended_properties = 0; @@ -197,7 +197,7 @@ CBOREncoder::EncoderState CBOREncoder::handle_FinishAppend(PropertyContainerEnco num_appended_properties++; } - /* Advance property index for the nex message */ + /* Advance property index for the next message */ propertyEncoder.current_property_index += propertyEncoder.checked_property_count; if(propertyEncoder.current_property_index >= propertyEncoder.property_container.size()) diff --git a/src/utility/ota/OTA-samd.cpp b/src/utility/ota/OTA-samd.cpp index f555415b8..dc5e1cc1f 100644 --- a/src/utility/ota/OTA-samd.cpp +++ b/src/utility/ota/OTA-samd.cpp @@ -47,7 +47,7 @@ int samd_onOTARequest(char const * ota_url) watchdog_reset(); - /* Trigger direct download to nina module. */ + /* Trigger direct download to NINA module. */ uint8_t nina_ota_err_code = 0; if (!WiFiStorage.downloadOTA(ota_url, &nina_ota_err_code)) { From fcbc7c8924161dac99693595d7222214e501b4e7 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 8 Sep 2022 17:30:04 +0200 Subject: [PATCH 323/780] Fix Unexpected input warning running unit-tests workflow --- .github/workflows/unit-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index e4288e97f..a6734b970 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -27,7 +27,7 @@ jobs: - uses: arduino/cpp-test-action@main with: - runtime-path: extras/test/build/bin/testArduinoIoTCloud + runtime-paths: extras/test/build/bin/testArduinoIoTCloud coverage-exclude-paths: | - '*/extras/test/*' - '/usr/*' From 18899020725ea6ae69bd93110f293fb154ee4cf6 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Fri, 9 Sep 2022 08:15:47 +0200 Subject: [PATCH 324/780] Fix runtime-paths input using YAML sequence Co-authored-by: per1234 --- .github/workflows/unit-tests.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index a6734b970..f3b66c2c8 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -27,7 +27,8 @@ jobs: - uses: arduino/cpp-test-action@main with: - runtime-paths: extras/test/build/bin/testArduinoIoTCloud + runtime-paths: | + - extras/test/build/bin/testArduinoIoTCloud coverage-exclude-paths: | - '*/extras/test/*' - '/usr/*' From 8c676c5a796d601db979de42f6ad769e89a89074 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 8 Sep 2022 16:01:42 +0200 Subject: [PATCH 325/780] Use mbed_portenta released core instead of ArduinoCore-mbed HEAD --- .github/workflows/compile-examples.yml | 38 ++++---------------------- 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 949f67fa7..c8486647c 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -29,8 +29,6 @@ jobs: - examples/ArduinoIoTCloud-Advanced - examples/ArduinoIoTCloud-Basic - examples/utility/ArduinoIoTCloud_Travis_CI - ARDUINOCORE_MBED_STAGING_PATH: extras/ArduinoCore-mbed - ARDUINOCORE_API_STAGING_PATH: extras/ArduinoCore-API SKETCHES_REPORTS_PATH: sketches-reports strategy: @@ -50,8 +48,8 @@ jobs: type: gsm - fqbn: arduino:samd:mkrnb1500 type: nb - - fqbn: arduino:mbed:envie_m7 - type: mbed + - fqbn: arduino:mbed_portenta:envie_m7 + type: mbed_portenta - fqbn: esp8266:esp8266:huzzah type: esp8266 - fqbn: esp32:esp32:esp32 @@ -128,18 +126,16 @@ jobs: - examples/utility/Provisioning # Portenta - board: - type: mbed + type: mbed_portenta platforms: | # Install Arduino mbed-Enabled Boards via Boards Manager for the toolchain - - name: arduino:mbed - # Overwrite the Arduino mbed-Enabled Boards release version with version from the tip of the master branch (located in local path because of the need to first install ArduinoCore-API) - - source-path: extras/ArduinoCore-mbed - name: arduino:mbed + - name: arduino:mbed_portenta libraries: | - name: ArduinoECCX08 - name: Arduino_Portenta_OTA sketch-paths: | - examples/utility/Provisioning + # Nicla Vision - board: type: mbed_nicla platforms: | @@ -174,30 +170,6 @@ jobs: - name: Checkout uses: actions/checkout@v2 - # it's necessary to checkout the platform before installing it so that the ArduinoCore-API dependency can be added - - name: Checkout ArduinoCore-mbed - # this step only needed when the Arduino mbed-Enabled Boards platform sourced from the repository is being used - if: matrix.board.type == 'mbed' - uses: actions/checkout@v2 - with: - repository: arduino/ArduinoCore-mbed - # the arduino/compile-sketches action will install the platform from this path - path: ${{ env.ARDUINOCORE_MBED_STAGING_PATH }} - - - name: Checkout ArduinoCore-API - # this step only needed when the Arduino mbed-Enabled Boards platform sourced from the repository is being used - if: matrix.board.type == 'mbed' - uses: actions/checkout@v2 - with: - repository: arduino/ArduinoCore-API - path: ${{ env.ARDUINOCORE_API_STAGING_PATH }} - - - name: Install ArduinoCore-API - # this step only needed when the Arduino mbed-Enabled Boards platform sourced from the repository is being used - if: matrix.board.type == 'mbed' - run: | - mv "${{ env.ARDUINOCORE_API_STAGING_PATH }}/api" "${{ env.ARDUINOCORE_MBED_STAGING_PATH }}/cores/arduino" - - name: Install ESP32 platform dependencies if: matrix.board.type == 'esp32' run: pip3 install pyserial From d404e8d547266d7c26cb8b4c9f65361c3540347e Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 9 Sep 2022 09:40:03 +0200 Subject: [PATCH 326/780] Fix comment about platform installation --- .github/workflows/compile-examples.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index c8486647c..99e1f0bf8 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -65,7 +65,7 @@ jobs: - board: type: mkr1000 platforms: | - # Install Arduino SAMD Boards via Boards Manager for the toolchain + # Install samd platform via Boards Manager - name: arduino:samd libraries: | - name: ArduinoECCX08 @@ -78,7 +78,7 @@ jobs: - board: type: nina platforms: | - # Install Arduino SAMD Boards via Boards Manager for the toolchain + # Install samd and mbed_nano platform via Boards Manager - name: arduino:samd - name: arduino:mbed_nano libraries: | @@ -93,6 +93,7 @@ jobs: - board: type: wan platforms: | + # Install samd platform via Boards Manager - name: arduino:samd libraries: | - name: ArduinoECCX08 @@ -104,6 +105,7 @@ jobs: - board: type: gsm platforms: | + # Install samd platform via Boards Manager - name: arduino:samd libraries: | - name: ArduinoECCX08 @@ -116,6 +118,7 @@ jobs: - board: type: nb platforms: | + # Install samd platform via Boards Manager - name: arduino:samd libraries: | - name: ArduinoECCX08 @@ -128,7 +131,7 @@ jobs: - board: type: mbed_portenta platforms: | - # Install Arduino mbed-Enabled Boards via Boards Manager for the toolchain + # Install mbed_portenta platform via Boards Manager - name: arduino:mbed_portenta libraries: | - name: ArduinoECCX08 @@ -139,7 +142,7 @@ jobs: - board: type: mbed_nicla platforms: | - # Install Arduino mbed-Enabled Boards via Boards Manager for the toolchain + # Install mbed_nicla platform via Boards Manager - name: arduino:mbed_nicla libraries: | - name: Arduino_Portenta_OTA From 6123f80e39cbe5b8c8a4b4f5407b1fa04402e998 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 20 Sep 2022 10:54:26 +0200 Subject: [PATCH 327/780] Add common define for STM32H7 boards --- src/AIoTC_Config.h | 4 ++++ src/ArduinoIoTCloudTCP.cpp | 8 ++++---- src/utility/ota/OTA-portenta-h7.cpp | 8 +++++--- src/utility/ota/OTA.h | 2 +- src/utility/watchdog/Watchdog.cpp | 4 ++-- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index c81a298c9..e92d9647e 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -141,6 +141,10 @@ #define HAS_TCP #endif +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) + #define BOARD_STM32H7 +#endif + /****************************************************************************** * CONSTANTS ******************************************************************************/ diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index f7e0c4ca6..f33f09c5e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -38,7 +38,7 @@ #include "tls/utility/CryptoUtil.h" #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) +#ifdef BOARD_STM32H7 # include "tls/utility/SHA256.h" # include # include @@ -56,7 +56,7 @@ * EXTERN ******************************************************************************/ -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) +#ifdef BOARD_STM32H7 extern RTC_HandleTypeDef RTCHandle; #endif @@ -151,7 +151,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #endif /* AVR */ #if OTA_ENABLED && !defined(__AVR__) -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) +#if defined(BOARD_STM32H7) /* The length of the application can be retrieved the same way it was * communicated to the bootloader, that is by writing to the non-volatile * storage registers of the RTC. @@ -829,7 +829,7 @@ void ArduinoIoTCloudTCP::onOTARequest() _ota_error = rp2040_connect_onOTARequest(_ota_url.c_str()); #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) +#ifdef BOARD_STM32H7 _ota_error = portenta_h7_onOTARequest(_ota_url.c_str()); #endif } diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index cb8358290..4b0c635da 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -15,12 +15,14 @@ a commercial license, send an email to license@arduino.cc. */ -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) - /****************************************************************************** * INCLUDE ******************************************************************************/ +#include + +#ifdef BOARD_STM32H7 + #include "OTA.h" #include @@ -87,4 +89,4 @@ int portenta_h7_onOTARequest(char const * ota_url) NVIC_SystemReset(); } -#endif /* defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) */ +#endif /* BOARD_STM32H7 */ diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index d5364242a..ce47a3ad2 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -62,7 +62,7 @@ int samd_onOTARequest(char const * ota_url); int rp2040_connect_onOTARequest(char const * ota_url); #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) +#ifdef BOARD_STM32H7 int portenta_h7_onOTARequest(char const * ota_url); #endif diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 7fdbbd347..d639d30a7 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -91,7 +91,7 @@ void mkr_nb_feed_watchdog() static void mbed_watchdog_enable() { watchdog_config_t cfg; -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) +#if defined(BOARD_STM32H7) cfg.timeout_ms = PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms; #elif defined(ARDUINO_NANO_RP2040_CONNECT) cfg.timeout_ms = NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms; @@ -117,7 +117,7 @@ static void mbed_watchdog_reset() void mbed_watchdog_trigger_reset() { watchdog_config_t cfg; -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) +#if defined(BOARD_STM32H7) cfg.timeout_ms = 1; #elif defined(ARDUINO_NANO_RP2040_CONNECT) cfg.timeout_ms = 1; From 31c55ef8329067bbd79bc56e99054e5de4d440a2 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 26 Sep 2022 13:56:12 +0200 Subject: [PATCH 328/780] fix write() in BearSSLClient.cpp --- src/tls/BearSSLClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tls/BearSSLClient.cpp b/src/tls/BearSSLClient.cpp index 390be4cbd..cdc58794f 100644 --- a/src/tls/BearSSLClient.cpp +++ b/src/tls/BearSSLClient.cpp @@ -94,7 +94,7 @@ size_t BearSSLClient::write(const uint8_t *buf, size_t size) size_t written = 0; while (written < size) { - int result = br_sslio_write(&_ioc, buf, size); + int result = br_sslio_write(&_ioc, buf, size - written); if (result < 0) { break; From fdd32f510d4b4e6c13a93e25c292cdc617d0caff Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 18 Oct 2022 14:49:07 +0200 Subject: [PATCH 329/780] ESP32: use core internal functions to configure and get time --- src/utility/time/TimeService.cpp | 9 +++++++-- src/utility/time/TimeService.h | 2 -- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 88c60a1a2..729206554 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -52,9 +52,7 @@ static time_t const EPOCH = 0; TimeService::TimeService() : _con_hdl(nullptr) -#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) , _is_rtc_configured(false) -#endif , _is_tz_configured(false) , _timezone_offset(0) , _timezone_dst_until(0) @@ -100,6 +98,13 @@ unsigned long TimeService::getTime() return utc; } return time(NULL); +#elif ARDUINO_ARCH_ESP32 || ARDUINO_ARCH_ESP8266 + if(!_is_rtc_configured) + { + configTime(0, 0, "time.arduino.cc", "pool.ntp.org", "time.nist.gov"); + _is_rtc_configured = true; + } + return time(NULL); #else return getRemoteTime(); #endif diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 8d8862287..adf8495ab 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -56,9 +56,7 @@ class TimeService private: ConnectionHandler * _con_hdl; -#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) bool _is_rtc_configured; -#endif bool _is_tz_configured; long _timezone_offset; unsigned long _timezone_dst_until; From 8c7a8345e1c9972cceb06668420ffcd6f810f929 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 19 Oct 2022 12:03:45 +0200 Subject: [PATCH 330/780] ESP8266: add soft rtc --- src/utility/time/TimeService.cpp | 20 +++++++++++++++++++- src/utility/time/TimeService.h | 4 ++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 729206554..3a3f8e363 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -56,6 +56,10 @@ TimeService::TimeService() , _is_tz_configured(false) , _timezone_offset(0) , _timezone_dst_until(0) +#ifdef ARDUINO_ARCH_ESP8266 +, _soft_rtc_value(0) +, _soft_rtc_offset(0) +#endif { } @@ -98,13 +102,27 @@ unsigned long TimeService::getTime() return utc; } return time(NULL); -#elif ARDUINO_ARCH_ESP32 || ARDUINO_ARCH_ESP8266 +#elif ARDUINO_ARCH_ESP32 if(!_is_rtc_configured) { configTime(0, 0, "time.arduino.cc", "pool.ntp.org", "time.nist.gov"); _is_rtc_configured = true; } return time(NULL); +#elif ARDUINO_ARCH_ESP8266 + if(!_is_rtc_configured || millis() < _soft_rtc_offset) + { + _is_rtc_configured = false; + unsigned long utc = getRemoteTime(); + if(EPOCH_AT_COMPILE_TIME != utc) + { + _soft_rtc_value = utc; + _soft_rtc_offset = millis(); + _is_rtc_configured = true; + } + return utc; + } + return _soft_rtc_value + ((millis() - _soft_rtc_offset) / 1000); #else return getRemoteTime(); #endif diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index adf8495ab..56b8ac22f 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -60,6 +60,10 @@ class TimeService bool _is_tz_configured; long _timezone_offset; unsigned long _timezone_dst_until; +#ifdef ARDUINO_ARCH_ESP8266 + unsigned long _soft_rtc_value; + unsigned long _soft_rtc_offset; +#endif unsigned long getRemoteTime(); bool connected(); From 5c85ac161ba862abc23473c603393b99d560e00d Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 25 Oct 2022 09:54:54 +0200 Subject: [PATCH 331/780] ESP8266: add NTP sync timeout --- src/utility/time/TimeService.cpp | 24 ++++++++++++++++++------ src/utility/time/TimeService.h | 5 +++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 3a3f8e363..dc90048ad 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -43,6 +43,9 @@ time_t cvt_time(char const * time); * CONSTANTS **************************************************************************************/ +#ifdef ARDUINO_ARCH_ESP8266 +static unsigned long const AIOT_TIMESERVICE_ESP8266_NTP_SYNC_TIMEOUT_ms = 86400000; +#endif static time_t const EPOCH_AT_COMPILE_TIME = cvt_time(__DATE__); static time_t const EPOCH = 0; @@ -57,8 +60,9 @@ TimeService::TimeService() , _timezone_offset(0) , _timezone_dst_until(0) #ifdef ARDUINO_ARCH_ESP8266 -, _soft_rtc_value(0) -, _soft_rtc_offset(0) +, _last_ntp_sync_tick(0) +, _last_rtc_update_tick(0) +, _rtc(0) #endif { @@ -110,19 +114,27 @@ unsigned long TimeService::getTime() } return time(NULL); #elif ARDUINO_ARCH_ESP8266 - if(!_is_rtc_configured || millis() < _soft_rtc_offset) + unsigned long const now = millis(); + bool const is_ntp_sync_timeout = (now - _last_ntp_sync_tick) > AIOT_TIMESERVICE_ESP8266_NTP_SYNC_TIMEOUT_ms; + if(!_is_rtc_configured || is_ntp_sync_timeout) { _is_rtc_configured = false; unsigned long utc = getRemoteTime(); if(EPOCH_AT_COMPILE_TIME != utc) { - _soft_rtc_value = utc; - _soft_rtc_offset = millis(); + _rtc = utc; + _last_ntp_sync_tick = now; + _last_rtc_update_tick = now; _is_rtc_configured = true; } return utc; } - return _soft_rtc_value + ((millis() - _soft_rtc_offset) / 1000); + unsigned long const elapsed_s = (now - _last_rtc_update_tick) / 1000; + if(elapsed_s) { + _rtc += elapsed_s; + _last_rtc_update_tick = now; + } + return _rtc; #else return getRemoteTime(); #endif diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 56b8ac22f..bf8eef1a1 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -61,8 +61,9 @@ class TimeService long _timezone_offset; unsigned long _timezone_dst_until; #ifdef ARDUINO_ARCH_ESP8266 - unsigned long _soft_rtc_value; - unsigned long _soft_rtc_offset; + unsigned long _last_ntp_sync_tick; + unsigned long _last_rtc_update_tick; + unsigned long _rtc; #endif unsigned long getRemoteTime(); From 6879eb74728dfb2b8d20cad486c658692fd2784b Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 2 Nov 2022 12:40:54 +0100 Subject: [PATCH 332/780] ESP: remove note about RTC in the readme --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index cde81db0b..28915c6fd 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,5 @@ OTA is supported by the following boards: Support for ESP boards is obtained through a third-party core with some differences and limitations compared to Arduino boards. - **Authentication scheme**: Board authentication is done through `DEVICE_LOGIN_NAME` and `DEVICE_KEY`, both values are included in the `thingProperties.h` file. -- **RTC**: RTC support is not included thus each `ArduinoCould.update()` call will lead to an NTP request introducing delay in your `loop()` function. The scheduler widget will not work correctly if connection is lost after configuration. - **Watchdog**: Watchdog support is not included. - **OTA**: OTA support is not included From f9a0ed958e85ce5159570190260917f02db735c1 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 1 Aug 2022 13:53:06 +0200 Subject: [PATCH 333/780] Use link to README.md instead of list supported boards --- .../ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino | 8 +------- examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino | 8 +------- .../ArduinoIoTCloud-Callbacks.ino | 8 +------- .../ArduinoIoTCloud-DeferredOTA.ino | 5 +---- .../ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino | 7 +------ .../ArduinoIoTCloud_Travis_CI.ino | 5 +---- 6 files changed, 6 insertions(+), 35 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino index 247860cff..22ba8c295 100644 --- a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino +++ b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino @@ -2,13 +2,7 @@ This sketch demonstrates how to use more complex cloud data types such as a colour or coordinates. This sketch is compatible with: - - MKR 1000 - - MKR WiFi 1010 - - MKR GSM 1400 - - MKR NB 1500 - - MKR WAN 1300/1310 - - Nano 33 IoT - - ESP8266 + - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ #include "arduino_secrets.h" diff --git a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino index 097afb6f3..d772c2d83 100644 --- a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino +++ b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino @@ -11,13 +11,7 @@ only after a value is sent to Cloud. This sketch is compatible with: - - MKR 1000 - - MKR WiFi 1010 - - MKR GSM 1400 - - MKR NB 1500 - - MKR WAN 1300/1310 - - Nano 33 IoT - - ESP8266 + - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ #include "arduino_secrets.h" diff --git a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino index 27c9d8f4d..dcd7f2fa5 100644 --- a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino +++ b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino @@ -23,13 +23,7 @@ only after a value is sent to Cloud. This sketch is compatible with: - - MKR 1000 - - MKR WiFi 1010 - - MKR GSM 1400 - - MKR NB 1500 - - MKR WAN 1300/1310 - - Nano 33 IoT - - ESP8266 + - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ #include "arduino_secrets.h" diff --git a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino index bd5b6a4d2..7aa206637 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino +++ b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino @@ -10,10 +10,7 @@ * ask_user_via_serial callback will read user input from serial to apply or postpone OTA update This sketch is compatible with: - - MKR WiFi 1010 - - Nano 33 IoT - - Portenta - - Nano RP2040 + - https://github.com/arduino-libraries/ArduinoIoTCloud/#ota */ #include "arduino_secrets.h" diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index 3c97e49f4..1897481de 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -2,12 +2,7 @@ This sketch demonstrates how to use the cloud schedule variable type. This sketch is compatible with the following boards: - - MKR 1000 - - MKR WiFi 1010 - - MKR GSM 1400 - - MKR NB 1500 - - Nano 33 IoT - - ESP8266 + - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ #include "arduino_secrets.h" diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino b/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino index d74f9bc66..729cc9098 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino @@ -4,10 +4,7 @@ Arduino IoT Cloud API. This sketch is compatible with: - - MKR 1000 - - MKR WIFI 1010 - - MKR GSM 1400 - - MKR WAN 1300/1310 + - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ #include "arduino_secrets.h" From c3f2c201cab4760d94e9908aee029da75607b99f Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 1 Aug 2022 14:09:26 +0200 Subject: [PATCH 334/780] Use generic define BOARD_ESP to check build options --- examples/ArduinoIoTCloud-Advanced/arduino_secrets.h | 5 +++-- examples/ArduinoIoTCloud-Advanced/thingProperties.h | 2 +- examples/ArduinoIoTCloud-Basic/arduino_secrets.h | 2 +- examples/ArduinoIoTCloud-Basic/thingProperties.h | 2 +- examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h | 5 +++-- examples/ArduinoIoTCloud-Callbacks/thingProperties.h | 2 +- .../ArduinoIoTCloud-DeferredOTA/arduino_secrets.h | 5 +++-- .../ArduinoIoTCloud-DeferredOTA/thingProperties.h | 2 +- examples/ArduinoIoTCloud-Schedule/arduino_secrets.h | 5 +++-- examples/ArduinoIoTCloud-Schedule/thingProperties.h | 2 +- .../ArduinoIoTCloud_Travis_CI/arduino_secrets.h | 6 ++++++ .../ArduinoIoTCloud_Travis_CI/thingProperties.h | 12 +++++++++++- 12 files changed, 35 insertions(+), 15 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h index fc0b0661e..7adeb4426 100644 --- a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h @@ -1,3 +1,4 @@ +#include #include /* MKR1000, MKR WiFi 1010 */ @@ -6,8 +7,8 @@ #define SECRET_PASS "YOUR_WIFI_PASSWORD" #endif -/* ESP8266 */ -#if defined(BOARD_ESP8266) +/* ESP8266 ESP32*/ +#if defined(BOARD_ESP) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index eff1564b7..b723c7bb1 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -11,7 +11,7 @@ CloudLocation location; CloudColor color; void initProperties() { -#if defined(BOARD_ESP8266) +#if defined(BOARD_ESP) ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif diff --git a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h index fc0b0661e..66ec8d9ad 100644 --- a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h @@ -7,7 +7,7 @@ #endif /* ESP8266 */ -#if defined(BOARD_ESP8266) +#if defined(BOARD_ESP) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index 5d3de1619..5ff715d8f 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -18,7 +18,7 @@ int potentiometer; int seconds; void initProperties() { -#if defined(BOARD_ESP8266) +#if defined(BOARD_ESP) ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif diff --git a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h index fc0b0661e..7adeb4426 100644 --- a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h @@ -1,3 +1,4 @@ +#include #include /* MKR1000, MKR WiFi 1010 */ @@ -6,8 +7,8 @@ #define SECRET_PASS "YOUR_WIFI_PASSWORD" #endif -/* ESP8266 */ -#if defined(BOARD_ESP8266) +/* ESP8266 ESP32*/ +#if defined(BOARD_ESP) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index 4eda5314a..aaebcb8f7 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -13,7 +13,7 @@ #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" void initProperties() { -#if defined(BOARD_ESP8266) +#if defined(BOARD_ESP) ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif diff --git a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h index fc0b0661e..7adeb4426 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h @@ -1,3 +1,4 @@ +#include #include /* MKR1000, MKR WiFi 1010 */ @@ -6,8 +7,8 @@ #define SECRET_PASS "YOUR_WIFI_PASSWORD" #endif -/* ESP8266 */ -#if defined(BOARD_ESP8266) +/* ESP8266 ESP32*/ +#if defined(BOARD_ESP) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index 2f84ea4f3..ac3128cb4 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -16,7 +16,7 @@ void onLedChange(); bool led; void initProperties() { -#if defined(BOARD_ESP8266) +#if defined(BOARD_ESP) ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif diff --git a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h index fc0b0661e..7adeb4426 100644 --- a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h @@ -1,3 +1,4 @@ +#include #include /* MKR1000, MKR WiFi 1010 */ @@ -6,8 +7,8 @@ #define SECRET_PASS "YOUR_WIFI_PASSWORD" #endif -/* ESP8266 */ -#if defined(BOARD_ESP8266) +/* ESP8266 ESP32*/ +#if defined(BOARD_ESP) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 63231a700..6e868527f 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -15,7 +15,7 @@ CloudSchedule monthly; CloudSchedule yearly; void initProperties() { -#if defined(BOARD_ESP8266) +#if defined(BOARD_ESP) ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h index 020482cfc..7adeb4426 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h @@ -1,3 +1,4 @@ +#include #include /* MKR1000, MKR WiFi 1010 */ @@ -6,6 +7,11 @@ #define SECRET_PASS "YOUR_WIFI_PASSWORD" #endif +/* ESP8266 ESP32*/ +#if defined(BOARD_ESP) + #define SECRET_DEVICE_KEY "my-device-password" +#endif + /* MKR GSM 1400 */ #if defined(BOARD_HAS_GSM) #define SECRET_PIN "" diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index c21820265..5ef88ea40 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -13,6 +13,13 @@ #error "Arduino IoT Cloud currently only supports MKR1000, MKR WiFi 1010, MKR WAN 1300/1310, MKR NB 1500 and MKR GSM 1400" #endif +/****************************************************************************** + DEFINES + ******************************************************************************/ + +#define THING_ID "ARDUINO_IOT_CLOUD_THING_ID" +#define BOARD_ID "ARDUINO_IOT_CLOUD_BOARD_ID" + /****************************************************************************** GLOBAL CONSTANTS ******************************************************************************/ @@ -72,7 +79,10 @@ void onStringPropertyChange(); ******************************************************************************/ #if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined (BOARD_HAS_NB) void initProperties() { - +#if defined(BOARD_ESP) + ArduinoCloud.setBoardId(BOARD_ID); + ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); +#endif ArduinoCloud.addProperty(bool_property_1, READWRITE, 1 * SECONDS); ArduinoCloud.addProperty(int_property_1, READ, 2 * MINUTES); ArduinoCloud.addProperty(float_property_1, WRITE, 3 * HOURS); From c9219f14045e043fed3e3d7beed183c1f9094c3f Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 1 Aug 2022 14:34:03 +0200 Subject: [PATCH 335/780] Use link to README.md insteaf of an hardcoded list of boards with WiFi --- examples/ArduinoIoTCloud-Advanced/arduino_secrets.h | 4 +++- examples/ArduinoIoTCloud-Basic/arduino_secrets.h | 5 ++++- examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h | 4 +++- examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h | 4 +++- examples/ArduinoIoTCloud-Schedule/arduino_secrets.h | 4 +++- examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h | 4 +++- 6 files changed, 19 insertions(+), 6 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h index 7adeb4426..b47db48fc 100644 --- a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h @@ -1,7 +1,9 @@ #include #include -/* MKR1000, MKR WiFi 1010 */ +/* A complete list of supported boards with WiFi is available here: + * https://github.com/arduino-libraries/ArduinoIoTCloud/#what + */ #if defined(BOARD_HAS_WIFI) #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" #define SECRET_PASS "YOUR_WIFI_PASSWORD" diff --git a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h index 66ec8d9ad..56df949db 100644 --- a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h @@ -1,6 +1,9 @@ +#include #include -/* MKR1000, MKR WiFi 1010 */ +/* A complete list of supported boards with WiFi is available here: + * https://github.com/arduino-libraries/ArduinoIoTCloud/#what + */ #if defined(BOARD_HAS_WIFI) #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" #define SECRET_PASS "YOUR_WIFI_PASSWORD" diff --git a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h index 7adeb4426..b47db48fc 100644 --- a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h @@ -1,7 +1,9 @@ #include #include -/* MKR1000, MKR WiFi 1010 */ +/* A complete list of supported boards with WiFi is available here: + * https://github.com/arduino-libraries/ArduinoIoTCloud/#what + */ #if defined(BOARD_HAS_WIFI) #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" #define SECRET_PASS "YOUR_WIFI_PASSWORD" diff --git a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h index 7adeb4426..b47db48fc 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h @@ -1,7 +1,9 @@ #include #include -/* MKR1000, MKR WiFi 1010 */ +/* A complete list of supported boards with WiFi is available here: + * https://github.com/arduino-libraries/ArduinoIoTCloud/#what + */ #if defined(BOARD_HAS_WIFI) #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" #define SECRET_PASS "YOUR_WIFI_PASSWORD" diff --git a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h index 7adeb4426..b47db48fc 100644 --- a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h @@ -1,7 +1,9 @@ #include #include -/* MKR1000, MKR WiFi 1010 */ +/* A complete list of supported boards with WiFi is available here: + * https://github.com/arduino-libraries/ArduinoIoTCloud/#what + */ #if defined(BOARD_HAS_WIFI) #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" #define SECRET_PASS "YOUR_WIFI_PASSWORD" diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h index 7adeb4426..b47db48fc 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h @@ -1,7 +1,9 @@ #include #include -/* MKR1000, MKR WiFi 1010 */ +/* A complete list of supported boards with WiFi is available here: + * https://github.com/arduino-libraries/ArduinoIoTCloud/#what + */ #if defined(BOARD_HAS_WIFI) #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" #define SECRET_PASS "YOUR_WIFI_PASSWORD" From 0552d79fcd555ed6b67abf6bdbcdb819584904e9 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 1 Aug 2022 15:16:12 +0200 Subject: [PATCH 336/780] Show supported board list url when building for unsupported board --- examples/ArduinoIoTCloud-Advanced/thingProperties.h | 8 ++++++++ examples/ArduinoIoTCloud-Basic/thingProperties.h | 2 +- examples/ArduinoIoTCloud-Callbacks/thingProperties.h | 2 +- examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h | 2 +- examples/ArduinoIoTCloud-Schedule/thingProperties.h | 8 ++++++++ .../utility/ArduinoIoTCloud_Travis_CI/thingProperties.h | 2 +- 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index b723c7bb1..2cabfa557 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -1,6 +1,14 @@ #include #include +#if defined(BOARD_HAS_WIFI) +#elif defined(BOARD_HAS_GSM) +#elif defined(BOARD_HAS_LORA) +#elif defined(BOARD_HAS_NB) +#else + #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" +#endif + #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" void onSwitchButtonChange(); diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index 5ff715d8f..ed4b0c18d 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -6,7 +6,7 @@ #elif defined(BOARD_HAS_LORA) #elif defined(BOARD_HAS_NB) #else - #error "Arduino IoT Cloud currently only supports MKR1000, MKR WiFi 1010, MKR WAN 1300/1310, MKR NB 1500 and MKR GSM 1400" + #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index aaebcb8f7..615251d47 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -6,7 +6,7 @@ #elif defined(BOARD_HAS_LORA) #elif defined(BOARD_HAS_NB) #else - #error "Arduino IoT Cloud currently only supports MKR1000, MKR WiFi 1010, MKR WAN 1300/1310, MKR NB 1500 and MKR GSM 1400" + #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif /* BOARD_ID is only required if you are using an ESP8266 */ diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index ac3128cb4..34f63725f 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -6,7 +6,7 @@ #elif defined(BOARD_HAS_LORA) #elif defined(BOARD_HAS_NB) #else - #error "Arduino IoT Cloud currently only supports MKR1000, MKR WiFi 1010, MKR WAN 1300/1310, MKR NB 1500 and MKR GSM 1400" + #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 6e868527f..864068979 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -1,6 +1,14 @@ #include #include +#if defined(BOARD_HAS_WIFI) +#elif defined(BOARD_HAS_GSM) +#elif defined(BOARD_HAS_LORA) +#elif defined(BOARD_HAS_NB) +#else + #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" +#endif + #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" void onSwitchButtonChange(); diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index 5ef88ea40..7705e3d10 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -10,7 +10,7 @@ #elif defined(BOARD_HAS_LORA) #elif defined(BOARD_HAS_NB) #else - #error "Arduino IoT Cloud currently only supports MKR1000, MKR WiFi 1010, MKR WAN 1300/1310, MKR NB 1500 and MKR GSM 1400" + #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif /****************************************************************************** From 4bad038f4760fd5e9cb06efc571352babfd51241 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 3 Nov 2022 12:06:23 +0100 Subject: [PATCH 337/780] Remove includes from thingProperties.h --- examples/ArduinoIoTCloud-Advanced/thingProperties.h | 3 --- examples/ArduinoIoTCloud-Basic/thingProperties.h | 3 --- examples/ArduinoIoTCloud-Callbacks/thingProperties.h | 3 --- examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h | 3 --- examples/ArduinoIoTCloud-Schedule/thingProperties.h | 3 --- .../utility/ArduinoIoTCloud_Travis_CI/thingProperties.h | 7 ------- 6 files changed, 22 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index 2cabfa557..0ce3c7eca 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -1,6 +1,3 @@ -#include -#include - #if defined(BOARD_HAS_WIFI) #elif defined(BOARD_HAS_GSM) #elif defined(BOARD_HAS_LORA) diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index ed4b0c18d..dd25617bf 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -1,6 +1,3 @@ -#include -#include - #if defined(BOARD_HAS_WIFI) #elif defined(BOARD_HAS_GSM) #elif defined(BOARD_HAS_LORA) diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index 615251d47..66ada9342 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -1,6 +1,3 @@ -#include -#include - #if defined(BOARD_HAS_WIFI) #elif defined(BOARD_HAS_GSM) #elif defined(BOARD_HAS_LORA) diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index 34f63725f..0282a5505 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -1,6 +1,3 @@ -#include -#include - #if defined(BOARD_HAS_WIFI) #elif defined(BOARD_HAS_GSM) #elif defined(BOARD_HAS_LORA) diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 864068979..70758d826 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -1,6 +1,3 @@ -#include -#include - #if defined(BOARD_HAS_WIFI) #elif defined(BOARD_HAS_GSM) #elif defined(BOARD_HAS_LORA) diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index 7705e3d10..d137fd214 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -1,10 +1,3 @@ -/****************************************************************************** - INCLUDE - ******************************************************************************/ - -#include -#include - #if defined(BOARD_HAS_WIFI) #elif defined(BOARD_HAS_GSM) #elif defined(BOARD_HAS_LORA) From c1582252cfc8cb117bfb18293f06da91f79d9b69 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 3 Nov 2022 12:11:14 +0100 Subject: [PATCH 338/780] Remove thing_id leftover --- examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index d137fd214..eed3d0f87 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -10,7 +10,6 @@ DEFINES ******************************************************************************/ -#define THING_ID "ARDUINO_IOT_CLOUD_THING_ID" #define BOARD_ID "ARDUINO_IOT_CLOUD_BOARD_ID" /****************************************************************************** From dfb452afa1836ef171874a792020fd24db2caf82 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 3 Nov 2022 12:18:56 +0100 Subject: [PATCH 339/780] Define BOARD_ID only for ESP boards --- examples/ArduinoIoTCloud-Advanced/thingProperties.h | 4 +++- examples/ArduinoIoTCloud-Basic/thingProperties.h | 4 +++- examples/ArduinoIoTCloud-Callbacks/thingProperties.h | 5 +++-- examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h | 4 +++- examples/ArduinoIoTCloud-Schedule/thingProperties.h | 4 +++- examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h | 4 +++- 6 files changed, 18 insertions(+), 7 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index 0ce3c7eca..425ce073b 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -6,7 +6,9 @@ #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif -#define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#if defined(BOARD_ESP) + #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#endif void onSwitchButtonChange(); void onColorChange(); diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index dd25617bf..8d9eea34b 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -6,7 +6,9 @@ #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif -#define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#if defined(BOARD_ESP) + #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#endif void onLedChange(); diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index 66ada9342..d739e85d2 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -6,8 +6,9 @@ #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif -/* BOARD_ID is only required if you are using an ESP8266 */ -#define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#if defined(BOARD_ESP) + #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#endif void initProperties() { #if defined(BOARD_ESP) diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index 0282a5505..8b68b1bdc 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -6,7 +6,9 @@ #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif -#define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#if defined(BOARD_ESP) + #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#endif void onLedChange(); diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 70758d826..5ef3bf6c1 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -6,7 +6,9 @@ #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif -#define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#if defined(BOARD_ESP) + #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#endif void onSwitchButtonChange(); diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index eed3d0f87..89bfada2f 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -10,7 +10,9 @@ DEFINES ******************************************************************************/ -#define BOARD_ID "ARDUINO_IOT_CLOUD_BOARD_ID" +#if defined(BOARD_ESP) + #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#endif /****************************************************************************** GLOBAL CONSTANTS From e0dc2457c486f0388230a3450ad4d1aff006febb Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 22 Jul 2022 17:01:17 +0200 Subject: [PATCH 340/780] OTA: Use connection handler network adapter type to select between Ethernet and WiFi --- src/ArduinoIoTCloudTCP.cpp | 3 ++- src/utility/ota/OTA-portenta-h7.cpp | 13 +++++++++++-- src/utility/ota/OTA.h | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index f33f09c5e..af422522b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -830,7 +830,8 @@ void ArduinoIoTCloudTCP::onOTARequest() #endif #ifdef BOARD_STM32H7 - _ota_error = portenta_h7_onOTARequest(_ota_url.c_str()); + bool const use_ethernet = _connection->getInterface() == NetworkAdapter::ETHERNET ? true : false; + _ota_error = portenta_h7_onOTARequest(_ota_url.c_str(), use_ethernet); #endif } #endif diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index 4b0c635da..23bde618c 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -28,13 +28,16 @@ #include #include +#include +#include + #include "../watchdog/Watchdog.h" /****************************************************************************** * FUNCTION DEFINITION ******************************************************************************/ -int portenta_h7_onOTARequest(char const * ota_url) +int portenta_h7_onOTARequest(char const * ota_url, bool use_ethernet) { watchdog_reset(); @@ -63,7 +66,13 @@ int portenta_h7_onOTARequest(char const * ota_url) watchdog_reset(); /* Download the OTA file from the web storage location. */ - int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download(ota_url, true /* is_https */); + MbedSocketClass * download_socket = static_cast(&WiFi); +#if defined (ARDUINO_PORTENTA_H7_M7) + if(use_ethernet) { + download_socket = static_cast(&Ethernet); + } +#endif + int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download(ota_url, true /* is_https */, download_socket); DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::download(%s) returns %d", ota_url, ota_portenta_qspi_download_ret_code); watchdog_reset(); diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index ce47a3ad2..513ef53b5 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -63,7 +63,7 @@ int rp2040_connect_onOTARequest(char const * ota_url); #endif #ifdef BOARD_STM32H7 -int portenta_h7_onOTARequest(char const * ota_url); +int portenta_h7_onOTARequest(char const * ota_url, bool use_ethernet); #endif #endif /* ARDUINO_OTA_LOGIC_H_ */ From e1d9da0e5f2e12d332ec330570c97b007dabd777 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 25 Jul 2022 11:40:37 +0200 Subject: [PATCH 341/780] Watchdog: Enable feed function for Ethernet The implementation is done as for WiFi so we can reuse the same define ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC Move watchdog network feed configuration into Watchdog module --- src/ArduinoIoTCloudTCP.cpp | 3 ++- src/utility/watchdog/Watchdog.cpp | 34 +++++++++++++++++++++++++++++++ src/utility/watchdog/Watchdog.h | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index af422522b..a94934a1b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -308,7 +308,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, if (enable_watchdog) { watchdog_enable(); #if defined (WIFI_HAS_FEED_WATCHDOG_FUNC) || defined (ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC) - WiFi.setFeedWatchdogFunc(watchdog_reset); + bool const use_ethernet = _connection->getInterface() == NetworkAdapter::ETHERNET ? true : false; + watchdog_enable_network_feed(use_ethernet); #endif } #endif diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index d639d30a7..d41ef333e 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -29,11 +29,14 @@ #ifdef ARDUINO_ARCH_SAMD # include +# include # define SAMD_WATCHDOG_MAX_TIME_ms (16 * 1000) #endif /* ARDUINO_ARCH_SAMD */ #ifdef ARDUINO_ARCH_MBED # include +# include +# include # define PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms (32760) # define NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms (8389) #endif /* ARDUINO_ARCH_MBED */ @@ -63,6 +66,13 @@ static void samd_watchdog_reset() } } +#if defined (WIFI_HAS_FEED_WATCHDOG_FUNC) +static void samd_watchdog_enable_network_feed() +{ + WiFi.setFeedWatchdogFunc(watchdog_reset); +} +#endif + /* This function is called within the WiFiNINA library when invoking * the method 'connectBearSSL' in order to prevent a premature bite * of the watchdog (max timeout on SAMD is 16 s). wifi_nina_feed... @@ -114,6 +124,19 @@ static void mbed_watchdog_reset() } } +#if defined (ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC) +static void mbed_watchdog_enable_network_feed(const bool use_ethernet) +{ + if(use_ethernet) { +#if defined(ARDUINO_PORTENTA_H7_M7) + Ethernet.setFeedWatchdogFunc(watchdog_reset); +#endif + } else { + WiFi.setFeedWatchdogFunc(watchdog_reset); + } +} +#endif + void mbed_watchdog_trigger_reset() { watchdog_config_t cfg; @@ -154,4 +177,15 @@ void watchdog_reset() mbed_watchdog_reset(); #endif } + +#if defined (WIFI_HAS_FEED_WATCHDOG_FUNC) || defined (ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC) +void watchdog_enable_network_feed(const bool use_ethernet) +{ +#ifdef ARDUINO_ARCH_SAMD + samd_watchdog_enable_network_feed(); +#else + mbed_watchdog_enable_network_feed(use_ethernet); +#endif +} +#endif #endif /* (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) */ diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index 879317684..b973e5a30 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -25,6 +25,7 @@ #if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) void watchdog_enable(); void watchdog_reset(); +void watchdog_enable_network_feed(bool use_ethernet); #endif /* (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) */ #ifdef ARDUINO_ARCH_MBED From f4afd119558ad351066d7520ac56bef21f2670f6 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 28 Jul 2022 10:47:16 +0200 Subject: [PATCH 342/780] Add const qualifier to use_ethernet function argument --- src/utility/ota/OTA-portenta-h7.cpp | 2 +- src/utility/ota/OTA.h | 2 +- src/utility/watchdog/Watchdog.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index 23bde618c..b4d7ddd7b 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -37,7 +37,7 @@ * FUNCTION DEFINITION ******************************************************************************/ -int portenta_h7_onOTARequest(char const * ota_url, bool use_ethernet) +int portenta_h7_onOTARequest(char const * ota_url, const bool use_ethernet) { watchdog_reset(); diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 513ef53b5..c1d3f79a0 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -63,7 +63,7 @@ int rp2040_connect_onOTARequest(char const * ota_url); #endif #ifdef BOARD_STM32H7 -int portenta_h7_onOTARequest(char const * ota_url, bool use_ethernet); +int portenta_h7_onOTARequest(char const * ota_url, const bool use_ethernet); #endif #endif /* ARDUINO_OTA_LOGIC_H_ */ diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index b973e5a30..dbaf2abd6 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -25,7 +25,7 @@ #if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) void watchdog_enable(); void watchdog_reset(); -void watchdog_enable_network_feed(bool use_ethernet); +void watchdog_enable_network_feed(const bool use_ethernet); #endif /* (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) */ #ifdef ARDUINO_ARCH_MBED From 174132070e9a3c43742a1a8ec395fb4d024f3b5c Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 19 Sep 2022 15:28:10 +0200 Subject: [PATCH 343/780] Watchdog: include Arduino_ConnectionHandler.h instead of Wifi/Ethernet.h In this way we can also use the more meaningful define BOARD_HAS_ETHERNET --- src/utility/watchdog/Watchdog.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index d41ef333e..eed2ce578 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -29,18 +29,17 @@ #ifdef ARDUINO_ARCH_SAMD # include -# include # define SAMD_WATCHDOG_MAX_TIME_ms (16 * 1000) #endif /* ARDUINO_ARCH_SAMD */ #ifdef ARDUINO_ARCH_MBED # include -# include -# include # define PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms (32760) # define NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms (8389) #endif /* ARDUINO_ARCH_MBED */ +#include + /****************************************************************************** * GLOBAL VARIABLES ******************************************************************************/ @@ -127,13 +126,13 @@ static void mbed_watchdog_reset() #if defined (ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC) static void mbed_watchdog_enable_network_feed(const bool use_ethernet) { +#if defined(BOARD_HAS_ETHERNET) if(use_ethernet) { -#if defined(ARDUINO_PORTENTA_H7_M7) Ethernet.setFeedWatchdogFunc(watchdog_reset); + } else #endif - } else { WiFi.setFeedWatchdogFunc(watchdog_reset); - } + } #endif From f39194793cb197756a594d0b37c57ecf48e32451 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 19 Sep 2022 15:28:19 +0200 Subject: [PATCH 344/780] Portenta OTA: include Arduino_ConnectionHandler.h instead of Wifi/Ethernet.h In this way we can also use the more meaningful define BOARD_HAS_ETHERNET --- src/utility/ota/OTA-portenta-h7.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index b4d7ddd7b..784f71969 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -27,9 +27,7 @@ #include #include - -#include -#include +#include #include "../watchdog/Watchdog.h" @@ -67,7 +65,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 (ARDUINO_PORTENTA_H7_M7) +#if defined (BOARD_HAS_ETHERNET) if(use_ethernet) { download_socket = static_cast(&Ethernet); } From fdaac0f5f8de2dcbcb529f35757ca659bd440e71 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 20 Sep 2022 15:20:43 +0200 Subject: [PATCH 345/780] Fix build for Nano RP2040 connect This board is an mbed platform + WiFiNINA so needs special handling for watchdog network feed. --- src/ArduinoIoTCloudTCP.cpp | 2 -- src/utility/watchdog/Watchdog.cpp | 17 +++++------------ 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index a94934a1b..f34da15af 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -307,10 +307,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) if (enable_watchdog) { watchdog_enable(); -#if defined (WIFI_HAS_FEED_WATCHDOG_FUNC) || defined (ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC) bool const use_ethernet = _connection->getInterface() == NetworkAdapter::ETHERNET ? true : false; watchdog_enable_network_feed(use_ethernet); -#endif } #endif diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index eed2ce578..a45f02d4e 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -65,13 +65,6 @@ static void samd_watchdog_reset() } } -#if defined (WIFI_HAS_FEED_WATCHDOG_FUNC) -static void samd_watchdog_enable_network_feed() -{ - WiFi.setFeedWatchdogFunc(watchdog_reset); -} -#endif - /* This function is called within the WiFiNINA library when invoking * the method 'connectBearSSL' in order to prevent a premature bite * of the watchdog (max timeout on SAMD is 16 s). wifi_nina_feed... @@ -177,14 +170,14 @@ void watchdog_reset() #endif } -#if defined (WIFI_HAS_FEED_WATCHDOG_FUNC) || defined (ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC) void watchdog_enable_network_feed(const bool use_ethernet) { -#ifdef ARDUINO_ARCH_SAMD - samd_watchdog_enable_network_feed(); -#else +#ifdef WIFI_HAS_FEED_WATCHDOG_FUNC + WiFi.setFeedWatchdogFunc(watchdog_reset); +#endif + +#ifdef ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC mbed_watchdog_enable_network_feed(use_ethernet); #endif } -#endif #endif /* (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) */ From 9c6d5d741ea936009f0e538deb33bfc655ca02e3 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 7 Nov 2022 10:44:05 +0100 Subject: [PATCH 346/780] Release v1.8.0 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index e15d45ab0..02d484f81 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.7.0 +version=1.8.0 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index e92d9647e..56c90697b 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -162,6 +162,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.7.0" +#define AIOT_CONFIG_LIB_VERSION "1.8.0" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From e7e9a836b89d1abb12e5b8ed45c22ab79f2a2aad Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 7 Nov 2022 12:26:56 +0100 Subject: [PATCH 347/780] Add EthernetConnectionHandler in library examples --- examples/ArduinoIoTCloud-Advanced/arduino_secrets.h | 8 ++++++++ examples/ArduinoIoTCloud-Advanced/thingProperties.h | 6 ++++++ examples/ArduinoIoTCloud-Basic/arduino_secrets.h | 10 +++++++++- examples/ArduinoIoTCloud-Basic/thingProperties.h | 10 ++++++++-- examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h | 8 ++++++++ examples/ArduinoIoTCloud-Callbacks/thingProperties.h | 6 ++++++ examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h | 8 ++++++++ examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h | 8 +++++++- examples/ArduinoIoTCloud-Schedule/arduino_secrets.h | 8 ++++++++ examples/ArduinoIoTCloud-Schedule/thingProperties.h | 8 +++++++- .../ArduinoIoTCloud_Travis_CI/arduino_secrets.h | 8 ++++++++ .../ArduinoIoTCloud_Travis_CI/thingProperties.h | 6 ++++++ 12 files changed, 89 insertions(+), 5 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h index b47db48fc..d1615135f 100644 --- a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h @@ -35,3 +35,11 @@ #define SECRET_LOGIN "" #define SECRET_PASS "" #endif + +/* Portenta H7 + Ethernet shield */ +#if defined(BOARD_HAS_ETHERNET) + #define SECRET_OPTIONAL_IP "" + #define SECRET_OPTIONAL_DNS "" + #define SECRET_OPTIONAL_GATEWAY "" + #define SECRET_OPTIONAL_NETMASK "" +#endif diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index 425ce073b..f8d7bb506 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -2,6 +2,7 @@ #elif defined(BOARD_HAS_GSM) #elif defined(BOARD_HAS_LORA) #elif defined(BOARD_HAS_NB) +#elif defined(BOARD_HAS_ETHERNET) #else #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif @@ -41,4 +42,9 @@ void initProperties() { LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_ETHERNET) + /* DHCP mode */ + //EthernetConnectionHandler ArduinoIoTPreferredConnection; + /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ + EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_OPTIONAL_IP, SECRET_OPTIONAL_DNS, SECRET_OPTIONAL_GATEWAY, SECRET_OPTIONAL_NETMASK); #endif diff --git a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h index 56df949db..d1615135f 100644 --- a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h @@ -9,7 +9,7 @@ #define SECRET_PASS "YOUR_WIFI_PASSWORD" #endif -/* ESP8266 */ +/* ESP8266 ESP32*/ #if defined(BOARD_ESP) #define SECRET_DEVICE_KEY "my-device-password" #endif @@ -35,3 +35,11 @@ #define SECRET_LOGIN "" #define SECRET_PASS "" #endif + +/* Portenta H7 + Ethernet shield */ +#if defined(BOARD_HAS_ETHERNET) + #define SECRET_OPTIONAL_IP "" + #define SECRET_OPTIONAL_DNS "" + #define SECRET_OPTIONAL_GATEWAY "" + #define SECRET_OPTIONAL_NETMASK "" +#endif diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index 8d9eea34b..e11eaf81f 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -2,6 +2,7 @@ #elif defined(BOARD_HAS_GSM) #elif defined(BOARD_HAS_LORA) #elif defined(BOARD_HAS_NB) +#elif defined(BOARD_HAS_ETHERNET) #else #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif @@ -21,7 +22,7 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif -#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) +#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) ArduinoCloud.addProperty(led, Permission::Write).onUpdate(onLedChange); ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10); ArduinoCloud.addProperty(seconds, Permission::Read).publishOnChange(1); @@ -32,7 +33,12 @@ void initProperties() { #endif } -#if defined(BOARD_HAS_WIFI) +#if defined(BOARD_HAS_ETHERNET) + /* DHCP mode */ + //EthernetConnectionHandler ArduinoIoTPreferredConnection; + /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ + EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_OPTIONAL_IP, SECRET_OPTIONAL_DNS, SECRET_OPTIONAL_GATEWAY, SECRET_OPTIONAL_NETMASK); +#elif defined(BOARD_HAS_WIFI) WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_PASS); #elif defined(BOARD_HAS_GSM) GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); diff --git a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h index b47db48fc..d1615135f 100644 --- a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h @@ -35,3 +35,11 @@ #define SECRET_LOGIN "" #define SECRET_PASS "" #endif + +/* Portenta H7 + Ethernet shield */ +#if defined(BOARD_HAS_ETHERNET) + #define SECRET_OPTIONAL_IP "" + #define SECRET_OPTIONAL_DNS "" + #define SECRET_OPTIONAL_GATEWAY "" + #define SECRET_OPTIONAL_NETMASK "" +#endif diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index d739e85d2..d92788f98 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -2,6 +2,7 @@ #elif defined(BOARD_HAS_GSM) #elif defined(BOARD_HAS_LORA) #elif defined(BOARD_HAS_NB) +#elif defined(BOARD_HAS_ETHERNET) #else #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif @@ -25,4 +26,9 @@ void initProperties() { LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_ETHERNET) + /* DHCP mode */ + //EthernetConnectionHandler ArduinoIoTPreferredConnection; + /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ + EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_OPTIONAL_IP, SECRET_OPTIONAL_DNS, SECRET_OPTIONAL_GATEWAY, SECRET_OPTIONAL_NETMASK); #endif diff --git a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h index b47db48fc..d1615135f 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h @@ -35,3 +35,11 @@ #define SECRET_LOGIN "" #define SECRET_PASS "" #endif + +/* Portenta H7 + Ethernet shield */ +#if defined(BOARD_HAS_ETHERNET) + #define SECRET_OPTIONAL_IP "" + #define SECRET_OPTIONAL_DNS "" + #define SECRET_OPTIONAL_GATEWAY "" + #define SECRET_OPTIONAL_NETMASK "" +#endif diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index 8b68b1bdc..94b3b0ece 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -2,6 +2,7 @@ #elif defined(BOARD_HAS_GSM) #elif defined(BOARD_HAS_LORA) #elif defined(BOARD_HAS_NB) +#elif defined(BOARD_HAS_ETHERNET) #else #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif @@ -19,7 +20,7 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif -#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) +#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) ArduinoCloud.addProperty(led, Permission::Write).onUpdate(onLedChange); #elif defined(BOARD_HAS_LORA) ArduinoCloud.addProperty(led, 1, READWRITE, ON_CHANGE, onLedChange); @@ -34,4 +35,9 @@ void initProperties() { LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_ETHERNET) + /* DHCP mode */ + //EthernetConnectionHandler ArduinoIoTPreferredConnection; + /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ + EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_OPTIONAL_IP, SECRET_OPTIONAL_DNS, SECRET_OPTIONAL_GATEWAY, SECRET_OPTIONAL_NETMASK); #endif diff --git a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h index b47db48fc..d1615135f 100644 --- a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h @@ -35,3 +35,11 @@ #define SECRET_LOGIN "" #define SECRET_PASS "" #endif + +/* Portenta H7 + Ethernet shield */ +#if defined(BOARD_HAS_ETHERNET) + #define SECRET_OPTIONAL_IP "" + #define SECRET_OPTIONAL_DNS "" + #define SECRET_OPTIONAL_GATEWAY "" + #define SECRET_OPTIONAL_NETMASK "" +#endif diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 5ef3bf6c1..940cb5c26 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -2,6 +2,7 @@ #elif defined(BOARD_HAS_GSM) #elif defined(BOARD_HAS_LORA) #elif defined(BOARD_HAS_NB) +#elif defined(BOARD_HAS_ETHERNET) #else #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif @@ -26,7 +27,7 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif -#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) +#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) ArduinoCloud.addProperty(switchButton, WRITE, ON_CHANGE); ArduinoCloud.addProperty(oneShot, READWRITE, ON_CHANGE); ArduinoCloud.addProperty(minute, READWRITE, ON_CHANGE); @@ -48,4 +49,9 @@ void initProperties() { LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_ETHERNET) + /* DHCP mode */ + //EthernetConnectionHandler ArduinoIoTPreferredConnection; + /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ + EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_OPTIONAL_IP, SECRET_OPTIONAL_DNS, SECRET_OPTIONAL_GATEWAY, SECRET_OPTIONAL_NETMASK); #endif diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h index b47db48fc..d1615135f 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h @@ -35,3 +35,11 @@ #define SECRET_LOGIN "" #define SECRET_PASS "" #endif + +/* Portenta H7 + Ethernet shield */ +#if defined(BOARD_HAS_ETHERNET) + #define SECRET_OPTIONAL_IP "" + #define SECRET_OPTIONAL_DNS "" + #define SECRET_OPTIONAL_GATEWAY "" + #define SECRET_OPTIONAL_NETMASK "" +#endif diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index 89bfada2f..eff3035bd 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -2,6 +2,7 @@ #elif defined(BOARD_HAS_GSM) #elif defined(BOARD_HAS_LORA) #elif defined(BOARD_HAS_NB) +#elif defined(BOARD_HAS_ETHERNET) #else #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif @@ -57,6 +58,11 @@ String str_property_8; LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, EU868); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_ETHERNET) + /* DHCP mode */ + //EthernetConnectionHandler ArduinoIoTPreferredConnection; + /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ + EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_OPTIONAL_IP, SECRET_OPTIONAL_DNS, SECRET_OPTIONAL_GATEWAY, SECRET_OPTIONAL_NETMASK); #endif /****************************************************************************** From 0802445d458a84cebdb9ac306beae4cd0395544a Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 7 Nov 2022 12:33:22 +0100 Subject: [PATCH 348/780] Define LED_BUILTIN is not defined in the core --- examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino index d772c2d83..853093fda 100644 --- a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino +++ b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino @@ -17,7 +17,7 @@ #include "arduino_secrets.h" #include "thingProperties.h" -#if defined(ESP32) +#if !defined(LED_BUILTIN) static int const LED_BUILTIN = 2; #endif From 7c4eb0938a463446974629938c3efc52bdfde5b9 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 7 Nov 2022 15:13:30 +0100 Subject: [PATCH 349/780] Align example sketches description header --- .../ArduinoIoTCloud-Advanced.ino | 7 ++++++- examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino | 4 ++-- .../ArduinoIoTCloud-Callbacks.ino | 4 ++-- .../ArduinoIoTCloud-DeferredOTA.ino | 5 ++++- .../ArduinoIoTCloud-Schedule.ino | 5 +++-- .../ArduinoIoTCloud_Travis_CI.ino | 9 +++++++-- 6 files changed, 24 insertions(+), 10 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino index 22ba8c295..a026d6297 100644 --- a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino +++ b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino @@ -1,7 +1,12 @@ /* This sketch demonstrates how to use more complex cloud data types such as a colour or coordinates. - This sketch is compatible with: + IMPORTANT: + This sketch works with WiFi, GSM, NB, Ethernet and Lora enabled boards supported by Arduino IoT Cloud. + On a LoRa board, if it is configured as a class A device (default and preferred option), values from Cloud dashboard are received + only after a value is sent to Cloud. + + The full list of compatible boards can be found here: - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ diff --git a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino index 853093fda..a32644941 100644 --- a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino +++ b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino @@ -6,11 +6,11 @@ * When you flip the switch in the Cloud dashboard the onboard LED lights gets turned ON or OFF. IMPORTANT: - This sketch works with WiFi, GSM, NB and Lora enabled boards supported by Arduino IoT Cloud. + This sketch works with WiFi, GSM, NB, Ethernet and Lora enabled boards supported by Arduino IoT Cloud. On a LoRa board, if it is configured as a class A device (default and preferred option), values from Cloud dashboard are received only after a value is sent to Cloud. - This sketch is compatible with: + The full list of compatible boards can be found here: - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ diff --git a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino index dcd7f2fa5..634464716 100644 --- a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino +++ b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino @@ -18,11 +18,11 @@ One function per event can be assigned. IMPORTANT: - This sketch works with WiFi, GSM, NB and Lora enabled boards supported by Arduino IoT Cloud. + This sketch works with WiFi, GSM, NB, Ethernet and Lora enabled boards supported by Arduino IoT Cloud. On a LoRa board, if it is configured as a class A device (default and preferred option), values from Cloud dashboard are received only after a value is sent to Cloud. - This sketch is compatible with: + The full list of compatible boards can be found here: - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ diff --git a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino index 7aa206637..fd5ab7977 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino +++ b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino @@ -9,7 +9,10 @@ * always_allow callback will immediately apply the OTA update * ask_user_via_serial callback will read user input from serial to apply or postpone OTA update - This sketch is compatible with: + IMPORTANT: + This sketch works with WiFi and Ethernet enabled boards supported by Arduino IoT Cloud. + + The full list of compatible boards can be found here: - https://github.com/arduino-libraries/ArduinoIoTCloud/#ota */ diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index 1897481de..7b82394ac 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -1,8 +1,9 @@ /* This sketch demonstrates how to use the cloud schedule variable type. - This sketch is compatible with the following boards: - - https://github.com/arduino-libraries/ArduinoIoTCloud#what + IMPORTANT: + This sketch works with WiFi, GSM, NB and Ethernet enabled boards supported by Arduino IoT Cloud. + */ #include "arduino_secrets.h" diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino b/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino index 729cc9098..6a971f629 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino @@ -3,8 +3,13 @@ unintentional breaking changes are made to the user facing Arduino IoT Cloud API. - This sketch is compatible with: - - https://github.com/arduino-libraries/ArduinoIoTCloud#what + IMPORTANT: + This sketch works with WiFi, GSM, NB, Ethernet and Lora enabled boards supported by Arduino IoT Cloud. + On a LoRa board, if it is configured as a class A device (default and preferred option), values from Cloud dashboard are received + only after a value is sent to Cloud. + + The full list of compatible boards can be found here: + - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ #include "arduino_secrets.h" From d4b1340961dfff69105ae09ec7674ee67b502612 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 7 Nov 2022 15:16:35 +0100 Subject: [PATCH 350/780] README: Add Ethernet boards list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cde81db0b..6440194e2 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ The `ArduinoIoTCloud` library is the central element of the firmware enabling ce * **GSM**: [`MKR GSM 1400`](https://store.arduino.cc/arduino-mkr-gsm-1400-1415) * **5G**: [`MKR NB 1500`](https://store.arduino.cc/arduino-mkr-nb-1500-1413) * **LoRa**: [`MKR WAN 1300/1310`](https://store.arduino.cc/mkr-wan-1310) +* **Ethernet**: [`Portenta H7`](https://store.arduino.cc/products/portenta-h7) + [`Vision Shield Ethernet`](https://store.arduino.cc/products/arduino-portenta-vision-shield-ethernet), [`Max Carrier`](https://store.arduino.cc/products/portenta-max-carrier), [`Breakout`](https://store.arduino.cc/products/arduino-portenta-breakout), [`Portenta Machine Control`](https://store.arduino.cc/products/arduino-portenta-machine-control) ### How? 1) Register your Arduino IoT Cloud capable board via [Arduino IoT Cloud](https://create.arduino.cc/iot) (Devices Section). From a0566e5958f7cedc2ab8dfc9644284817ecb6b37 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 11 Nov 2022 16:19:07 +0100 Subject: [PATCH 351/780] Remove unnecessary methods from public access label --- src/ArduinoIoTCloud.h | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 8be318b25..a17525e37 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -130,20 +130,6 @@ class ArduinoIoTCloudClass Property& addPropertyReal(unsigned int& property, String name, Permission const permission); Property& addPropertyReal(String& property, String name, Permission const permission); - Property& addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); - Property& addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); - Property& addPropertyReal(float& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); - Property& addPropertyReal(int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); - Property& addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); - Property& addPropertyReal(String& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); - - Property& addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, Permission const permission); - Property& addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, Permission const permission); - Property& addPropertyReal(float& property, PropertyContainer &prop_cont, String name, Permission const permission); - Property& addPropertyReal(int& property, PropertyContainer &prop_cont, String name, Permission const permission); - Property& addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, Permission const permission); - Property& addPropertyReal(String& property, PropertyContainer &prop_cont, String name, Permission const permission); - /* The following methods are for MKR WAN 1300/1310 LoRa boards since * they use a number to identify a given property within a CBOR message. * This approach reduces the required amount of data which is of great @@ -178,11 +164,26 @@ class ArduinoIoTCloudClass void execCloudEventCallback(ArduinoIoTCloudEvent const event); + /* The following methods are used to handle hidden thing and device properties */ + Property& addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, Permission const permission); + Property& addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, Permission const permission); + Property& addPropertyReal(float& property, PropertyContainer &prop_cont, String name, Permission const permission); + Property& addPropertyReal(int& property, PropertyContainer &prop_cont, String name, Permission const permission); + Property& addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, Permission const permission); + Property& addPropertyReal(String& property, PropertyContainer &prop_cont, String name, Permission const permission); + private: String _device_id; OnCloudEventCallback _cloud_event_callback[3]; bool _thing_id_outdated; + + Property& addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); + Property& addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); + Property& addPropertyReal(float& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); + Property& addPropertyReal(int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); + Property& addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); + Property& addPropertyReal(String& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); }; #ifdef HAS_TCP From 0773524ea96bdc0749f9960bdaeb20a1320a1cd4 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 11 Nov 2022 16:26:21 +0100 Subject: [PATCH 352/780] Reorder methods to make more clear calls dependency --- src/ArduinoIoTCloud.cpp | 238 ++++++++++++++++++---------------------- 1 file changed, 109 insertions(+), 129 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 0d9102d67..2b291d245 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -66,222 +66,202 @@ void ArduinoIoTCloudClass::addCallback(ArduinoIoTCloudEvent const event, OnCloud _cloud_event_callback[static_cast(event)] = callback; } -void ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +/* The following methods are used for non-LoRa boards */ +Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, Permission const permission) { - addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); + return addPropertyReal(property, _thing_property_container, name, -1, permission); } - -void ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +Property& ArduinoIoTCloudClass::addPropertyReal(float& property, String name, Permission const permission) { - Permission permission = Permission::ReadWrite; - if (permission_type == READ) { - permission = Permission::Read; - } else if (permission_type == WRITE) { - permission = Permission::Write; - } else { - permission = Permission::ReadWrite; - } - - if (seconds == ON_CHANGE) { - addPropertyToContainer(_thing_property_container, property, name, permission, tag).publishOnChange(minDelta, Property::DEFAULT_MIN_TIME_BETWEEN_UPDATES_MILLIS).onUpdate(fn).onSync(synFn); - } else { - addPropertyToContainer(_thing_property_container, property, name, permission, tag).publishEvery(seconds).onUpdate(fn).onSync(synFn); - } + return addPropertyReal(property, _thing_property_container, name, -1, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(int& property, String name, Permission const permission) { - return addPropertyToContainer(_thing_property_container, property, name, permission); + return addPropertyReal(property, _thing_property_container, name, -1, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, int tag, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, Permission const permission) { - return addPropertyToContainer(_thing_property_container, property, name, permission, tag); + return addPropertyReal(property, _thing_property_container, name, -1, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(String& property, String name, Permission const permission) { - return addPropertyToContainer(prop_cont, property, name, permission, -1); + return addPropertyReal(property, _thing_property_container, name, -1, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, Permission const permission) { - return addPropertyToContainer(prop_cont, property, name, permission, tag); + return addPropertyReal(property, _thing_property_container, name, -1, permission); } -void ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +/* The following methods are used for LoRa boards */ +Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, int tag, Permission const permission) { - addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); + return addPropertyReal(property, _thing_property_container, name, tag, permission); } - -void ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +Property& ArduinoIoTCloudClass::addPropertyReal(float& property, String name, int tag, Permission const permission) { - Property* p = new CloudWrapperBool(property); - addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); + return addPropertyReal(property, _thing_property_container, name, tag, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(int& property, String name, int tag, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, -1, permission); + return addPropertyReal(property, _thing_property_container, name, tag, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, int tag, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, int tag, Permission const permission) { return addPropertyReal(property, _thing_property_container, name, tag, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(String& property, String name, int tag, Permission const permission) { - return addPropertyReal(property, prop_cont, name, -1, permission); + return addPropertyReal(property, _thing_property_container, name, tag, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, int tag, Permission const permission) { - Property* p = new CloudWrapperBool(property); - return addPropertyToContainer(prop_cont, *p, name, permission, tag); + return addPropertyReal(property, _thing_property_container, name, tag, permission); } +/* The following methods are deprecated but still used for non-LoRa boards */ +void ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +{ + addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); +} void ArduinoIoTCloudClass::addPropertyReal(float& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); } - -void ArduinoIoTCloudClass::addPropertyReal(float& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +void ArduinoIoTCloudClass::addPropertyReal(int& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - Property* p = new CloudWrapperFloat(property); - addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); + addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); } - -Property& ArduinoIoTCloudClass::addPropertyReal(float& property, String name, Permission const permission) +void ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - return addPropertyReal(property, _thing_property_container, name, -1, permission); + addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); } - -Property& ArduinoIoTCloudClass::addPropertyReal(float& property, String name, int tag, Permission const permission) +void ArduinoIoTCloudClass::addPropertyReal(String& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - return addPropertyReal(property, _thing_property_container, name, tag, permission); + addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); } - -Property& ArduinoIoTCloudClass::addPropertyReal(float& property, PropertyContainer &prop_cont, String name, Permission const permission) +void ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - return addPropertyReal(property, prop_cont, name, -1, permission); + addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); } -Property& ArduinoIoTCloudClass::addPropertyReal(float& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) +/* The following methods are deprecated but still used for both LoRa and non-LoRa boards */ +void ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - Property* p = new CloudWrapperFloat(property); - return addPropertyToContainer(prop_cont, *p, name, permission, tag); + Property* p = new CloudWrapperBool(property); + addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); } - -void ArduinoIoTCloudClass::addPropertyReal(int& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +void ArduinoIoTCloudClass::addPropertyReal(float& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); + Property* p = new CloudWrapperFloat(property); + addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); } - void ArduinoIoTCloudClass::addPropertyReal(int& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { Property* p = new CloudWrapperInt(property); addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); } - -Property& ArduinoIoTCloudClass::addPropertyReal(int& property, String name, Permission const permission) +void ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - return addPropertyReal(property, _thing_property_container, name, -1, permission); + Property* p = new CloudWrapperUnsignedInt(property); + addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); } - -Property& ArduinoIoTCloudClass::addPropertyReal(int& property, String name, int tag, Permission const permission) +void ArduinoIoTCloudClass::addPropertyReal(String& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - return addPropertyReal(property, _thing_property_container, name, tag, permission); + Property* p = new CloudWrapperString(property); + addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); } - -Property& ArduinoIoTCloudClass::addPropertyReal(int& property, PropertyContainer &prop_cont, String name, Permission const permission) +void ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - return addPropertyReal(property, prop_cont, name, -1, permission); + Permission permission = Permission::ReadWrite; + if (permission_type == READ) { + permission = Permission::Read; + } else if (permission_type == WRITE) { + permission = Permission::Write; + } else { + permission = Permission::ReadWrite; + } + + if (seconds == ON_CHANGE) { + addPropertyToContainer(_thing_property_container, property, name, permission, tag).publishOnChange(minDelta, Property::DEFAULT_MIN_TIME_BETWEEN_UPDATES_MILLIS).onUpdate(fn).onSync(synFn); + } else { + addPropertyToContainer(_thing_property_container, property, name, permission, tag).publishEvery(seconds).onUpdate(fn).onSync(synFn); + } } -Property& ArduinoIoTCloudClass::addPropertyReal(int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) +/****************************************************************************** + * PROTECTED MEMBER FUNCTIONS + ******************************************************************************/ + +void ArduinoIoTCloudClass::execCloudEventCallback(ArduinoIoTCloudEvent const event) { - Property* p = new CloudWrapperInt(property); - return addPropertyToContainer(prop_cont, *p, name, permission, tag); + OnCloudEventCallback callback = _cloud_event_callback[static_cast(event)]; + if (callback) { + (*callback)(); + } } -void ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +__attribute__((weak)) void setDebugMessageLevel(int const /* level */) { - addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); + /* do nothing */ } -void ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +/* The following methods are used internally to handle hidden thing and device properties */ +Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, Permission const permission) { - Property* p = new CloudWrapperUnsignedInt(property); - addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); + return addPropertyReal(property, prop_cont, name, -1, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(float& property, PropertyContainer &prop_cont, String name, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, -1, permission); + return addPropertyReal(property, prop_cont, name, -1, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, int tag, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(int& property, PropertyContainer &prop_cont, String name, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, tag, permission); + return addPropertyReal(property, prop_cont, name, -1, permission); } - Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, Permission const permission) { return addPropertyReal(property, prop_cont, name, -1, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(String& property, PropertyContainer &prop_cont, String name, Permission const permission) { - Property* p = new CloudWrapperUnsignedInt(property); - return addPropertyToContainer(prop_cont, *p, name, permission, tag); + return addPropertyReal(property, prop_cont, name, -1, permission); } - -void ArduinoIoTCloudClass::addPropertyReal(String& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, Permission const permission) { - addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); + return addPropertyReal(property, prop_cont, name, -1, permission); } -void ArduinoIoTCloudClass::addPropertyReal(String& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +/****************************************************************************** + * PRIVATE MEMBER FUNCTIONS + ******************************************************************************/ + +/* The following methods are used for both LoRa and non-LoRa boards */ +Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) { - Property* p = new CloudWrapperString(property); - addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); + Property* p = new CloudWrapperBool(property); + return addPropertyReal(*p, prop_cont, name, tag, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(String& property, String name, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(float& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, -1, permission); + Property* p = new CloudWrapperFloat(property); + return addPropertyReal(*p, prop_cont, name, tag, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(String& property, String name, int tag, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, tag, permission); + Property* p = new CloudWrapperInt(property); + return addPropertyReal(*p, prop_cont, name, tag, permission); } - -Property& ArduinoIoTCloudClass::addPropertyReal(String& property, PropertyContainer &prop_cont, String name, Permission const permission) +Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) { - return addPropertyReal(property, prop_cont, name, -1, permission); + Property* p = new CloudWrapperUnsignedInt(property); + return addPropertyReal(*p, prop_cont, name, tag, permission); } - Property& ArduinoIoTCloudClass::addPropertyReal(String& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) { Property* p = new CloudWrapperString(property); - return addPropertyToContainer(prop_cont, *p, name, permission, tag); + return addPropertyReal(*p, prop_cont, name, tag, permission); } - -/****************************************************************************** - * PROTECTED MEMBER FUNCTIONS - ******************************************************************************/ - -void ArduinoIoTCloudClass::execCloudEventCallback(ArduinoIoTCloudEvent const event) -{ - OnCloudEventCallback callback = _cloud_event_callback[static_cast(event)]; - if (callback) { - (*callback)(); - } -} - -__attribute__((weak)) void setDebugMessageLevel(int const /* level */) +Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) { - /* do nothing */ -} + return addPropertyToContainer(prop_cont, property, name, permission, tag); +} \ No newline at end of file From ba9eb7ea820c3a957d449d7b2973431f0135ca4e Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 10 Nov 2022 17:06:54 +0100 Subject: [PATCH 353/780] Fix -Wwrite-strings warning --- src/utility/time/NTPUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility/time/NTPUtils.h b/src/utility/time/NTPUtils.h index 91cec89af..6337015a5 100644 --- a/src/utility/time/NTPUtils.h +++ b/src/utility/time/NTPUtils.h @@ -54,7 +54,7 @@ class NTPUtils static int const MAX_NTP_PORT = 65535; #endif static unsigned long const NTP_TIMEOUT_MS = 1000; - static char constexpr * NTP_TIME_SERVER = "time.arduino.cc"; + static constexpr const char * NTP_TIME_SERVER = "time.arduino.cc"; static void sendNTPpacket(UDP & udp); }; From 519d7f1659e0823a792d30b6e35f96085ee2efc9 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 10 Nov 2022 17:08:25 +0100 Subject: [PATCH 354/780] Fix -Wreorder warning --- src/tls/utility/Cert.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tls/utility/Cert.h b/src/tls/utility/Cert.h index 45f531869..9a74ea35b 100644 --- a/src/tls/utility/Cert.h +++ b/src/tls/utility/Cert.h @@ -147,12 +147,12 @@ class ArduinoIoTCloudCertClass { byte data[CERT_COMPRESSED_CERT_SLOT_LENGTH + CERT_SERIAL_NUMBER_LENGTH + CERT_AUTHORITY_KEY_ID_LENGTH]; } _compressedCert; - /* only raw EC X Y values 64 byte */ - const byte * _publicKey; - byte * _certBuffer; int _certBufferLen; + /* only raw EC X Y values 64 byte */ + const byte * _publicKey; + int versionLength(); int issuerOrSubjectLength(const CertInfo& issuerOrSubjectData); int sequenceHeaderLength(int length); From ffc600970293242534c18762d0887b006057e507 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 10 Nov 2022 17:10:08 +0100 Subject: [PATCH 355/780] Fix -Wunused-variable warning --- src/tls/profile/aiotc_profile.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tls/profile/aiotc_profile.c b/src/tls/profile/aiotc_profile.c index 2e2fa7372..e546b7577 100644 --- a/src/tls/profile/aiotc_profile.c +++ b/src/tls/profile/aiotc_profile.c @@ -51,8 +51,6 @@ void aiotc_client_profile_init(br_ssl_client_context *cc, br_x509_minimal_contex BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 }; - int id; - /* * Reset client context and set supported versions from TLS-1.0 * to TLS-1.2 (inclusive). From ced65621b455cb89dc9e91bc226a34b76c8b37a8 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 10 Nov 2022 17:12:39 +0100 Subject: [PATCH 356/780] Fix -Wreorder warning --- src/tls/BearSSLClient.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tls/BearSSLClient.h b/src/tls/BearSSLClient.h index ff60214db..457ef92f0 100644 --- a/src/tls/BearSSLClient.h +++ b/src/tls/BearSSLClient.h @@ -90,9 +90,8 @@ class BearSSLClient : public Client { Client* _client; const br_x509_trust_anchor* _TAs; int _numTAs; - GetTimeCallbackFunc _get_time_func; - bool _noSNI; + GetTimeCallbackFunc _get_time_func; br_ec_private_key _ecKey; br_x509_certificate _ecCert; From bee1cc56329fae15adba9cbc5530f784684ac68d Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 14 Nov 2022 13:42:42 +0100 Subject: [PATCH 357/780] Suppress -Wunused-variable warning --- src/utility/watchdog/Watchdog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index a45f02d4e..21cf7374c 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -173,6 +173,7 @@ void watchdog_reset() void watchdog_enable_network_feed(const bool use_ethernet) { #ifdef WIFI_HAS_FEED_WATCHDOG_FUNC + (void)use_ethernet; WiFi.setFeedWatchdogFunc(watchdog_reset); #endif From 9030adc260726610a242af153a24ea90499e9121 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 14 Nov 2022 14:27:23 +0100 Subject: [PATCH 358/780] Fix -Wreturn-type warning --- src/utility/ota/OTA-samd.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utility/ota/OTA-samd.cpp b/src/utility/ota/OTA-samd.cpp index dc5e1cc1f..03cc24bbd 100644 --- a/src/utility/ota/OTA-samd.cpp +++ b/src/utility/ota/OTA-samd.cpp @@ -57,6 +57,8 @@ int samd_onOTARequest(char const * ota_url) /* Perform the reset to reboot to SxU. */ NVIC_SystemReset(); + + return static_cast(OTAError::None); #endif /* OTA_STORAGE_SNU */ } From f976d3e5159b75a6620af8959bb1506f2ed06ce5 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 14 Nov 2022 14:28:34 +0100 Subject: [PATCH 359/780] Suppress -Wunused-variable warning --- src/utility/ota/OTA-samd.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utility/ota/OTA-samd.cpp b/src/utility/ota/OTA-samd.cpp index 03cc24bbd..941e56627 100644 --- a/src/utility/ota/OTA-samd.cpp +++ b/src/utility/ota/OTA-samd.cpp @@ -60,6 +60,8 @@ int samd_onOTARequest(char const * ota_url) return static_cast(OTAError::None); #endif /* OTA_STORAGE_SNU */ + + (void)ota_url; } #endif /* ARDUINO_ARCH_SAMD */ From 5ab7d897c9d723fc4c9c6839a5211b176c6e292c Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 14 Nov 2022 14:29:48 +0100 Subject: [PATCH 360/780] Fix -Wreturn-type warning --- src/utility/ota/OTA-samd.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utility/ota/OTA-samd.cpp b/src/utility/ota/OTA-samd.cpp index 941e56627..da4a98e27 100644 --- a/src/utility/ota/OTA-samd.cpp +++ b/src/utility/ota/OTA-samd.cpp @@ -62,6 +62,7 @@ int samd_onOTARequest(char const * ota_url) #endif /* OTA_STORAGE_SNU */ (void)ota_url; + return static_cast(OTAError::DownloadFailed); } #endif /* ARDUINO_ARCH_SAMD */ From fa9e6eec1314a75fbbab1595b0f0af7dea599151 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 11 Nov 2022 17:49:28 +0100 Subject: [PATCH 361/780] Remove no more needed protected methods --- src/ArduinoIoTCloud.cpp | 26 -------------------------- src/ArduinoIoTCloud.h | 8 -------- 2 files changed, 34 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 2b291d245..3df5363fa 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -205,32 +205,6 @@ __attribute__((weak)) void setDebugMessageLevel(int const /* level */) /* do nothing */ } -/* The following methods are used internally to handle hidden thing and device properties */ -Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, Permission const permission) -{ - return addPropertyReal(property, prop_cont, name, -1, permission); -} -Property& ArduinoIoTCloudClass::addPropertyReal(float& property, PropertyContainer &prop_cont, String name, Permission const permission) -{ - return addPropertyReal(property, prop_cont, name, -1, permission); -} -Property& ArduinoIoTCloudClass::addPropertyReal(int& property, PropertyContainer &prop_cont, String name, Permission const permission) -{ - return addPropertyReal(property, prop_cont, name, -1, permission); -} -Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, Permission const permission) -{ - return addPropertyReal(property, prop_cont, name, -1, permission); -} -Property& ArduinoIoTCloudClass::addPropertyReal(String& property, PropertyContainer &prop_cont, String name, Permission const permission) -{ - return addPropertyReal(property, prop_cont, name, -1, permission); -} -Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, Permission const permission) -{ - return addPropertyReal(property, prop_cont, name, -1, permission); -} - /****************************************************************************** * PRIVATE MEMBER FUNCTIONS ******************************************************************************/ diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index a17525e37..2be126f2c 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -164,14 +164,6 @@ class ArduinoIoTCloudClass void execCloudEventCallback(ArduinoIoTCloudEvent const event); - /* The following methods are used to handle hidden thing and device properties */ - Property& addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, Permission const permission); - Property& addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, Permission const permission); - Property& addPropertyReal(float& property, PropertyContainer &prop_cont, String name, Permission const permission); - Property& addPropertyReal(int& property, PropertyContainer &prop_cont, String name, Permission const permission); - Property& addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, Permission const permission); - Property& addPropertyReal(String& property, PropertyContainer &prop_cont, String name, Permission const permission); - private: String _device_id; From 74b3ff2b81631e5f689d791fcd0f9015f581bc94 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 11 Nov 2022 17:58:13 +0100 Subject: [PATCH 362/780] Simplify addPropertyReal logic and remove no more needed private methods --- src/ArduinoIoTCloud.cpp | 65 ++++++++++++----------------------------- src/ArduinoIoTCloud.h | 7 ----- 2 files changed, 18 insertions(+), 54 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 3df5363fa..7763dd1f5 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -69,53 +69,58 @@ void ArduinoIoTCloudClass::addCallback(ArduinoIoTCloudEvent const event, OnCloud /* The following methods are used for non-LoRa boards */ Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, -1, permission); + return addPropertyReal(property, name, -1, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(float& property, String name, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, -1, permission); + return addPropertyReal(property, name, -1, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(int& property, String name, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, -1, permission); + return addPropertyReal(property, name, -1, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, -1, permission); + return addPropertyReal(property, name, -1, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(String& property, String name, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, -1, permission); + return addPropertyReal(property, name, -1, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, -1, permission); + return addPropertyReal(property, name, -1, permission); } -/* The following methods are used for LoRa boards */ +/* The following methods are used for both LoRa and non-Lora boards */ Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, int tag, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, tag, permission); + Property* p = new CloudWrapperBool(property); + return addPropertyReal(*p, name, tag, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(float& property, String name, int tag, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, tag, permission); + Property* p = new CloudWrapperFloat(property); + return addPropertyReal(*p, name, tag, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(int& property, String name, int tag, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, tag, permission); + Property* p = new CloudWrapperInt(property); + return addPropertyReal(*p, name, tag, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, int tag, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, tag, permission); + Property* p = new CloudWrapperUnsignedInt(property); + return addPropertyReal(*p, name, tag, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(String& property, String name, int tag, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, tag, permission); + Property* p = new CloudWrapperString(property); + return addPropertyReal(*p, name, tag, permission); } Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, int tag, Permission const permission) { - return addPropertyReal(property, _thing_property_container, name, tag, permission); + return addPropertyToContainer(_thing_property_container, property, name, permission, tag); } /* The following methods are deprecated but still used for non-LoRa boards */ @@ -205,37 +210,3 @@ __attribute__((weak)) void setDebugMessageLevel(int const /* level */) /* do nothing */ } -/****************************************************************************** - * PRIVATE MEMBER FUNCTIONS - ******************************************************************************/ - -/* The following methods are used for both LoRa and non-LoRa boards */ -Property& ArduinoIoTCloudClass::addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) -{ - Property* p = new CloudWrapperBool(property); - return addPropertyReal(*p, prop_cont, name, tag, permission); -} -Property& ArduinoIoTCloudClass::addPropertyReal(float& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) -{ - Property* p = new CloudWrapperFloat(property); - return addPropertyReal(*p, prop_cont, name, tag, permission); -} -Property& ArduinoIoTCloudClass::addPropertyReal(int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) -{ - Property* p = new CloudWrapperInt(property); - return addPropertyReal(*p, prop_cont, name, tag, permission); -} -Property& ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) -{ - Property* p = new CloudWrapperUnsignedInt(property); - return addPropertyReal(*p, prop_cont, name, tag, permission); -} -Property& ArduinoIoTCloudClass::addPropertyReal(String& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) -{ - Property* p = new CloudWrapperString(property); - return addPropertyReal(*p, prop_cont, name, tag, permission); -} -Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission) -{ - return addPropertyToContainer(prop_cont, property, name, permission, tag); -} \ No newline at end of file diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 2be126f2c..717bce0fa 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -169,13 +169,6 @@ class ArduinoIoTCloudClass String _device_id; OnCloudEventCallback _cloud_event_callback[3]; bool _thing_id_outdated; - - Property& addPropertyReal(Property& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); - Property& addPropertyReal(bool& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); - Property& addPropertyReal(float& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); - Property& addPropertyReal(int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); - Property& addPropertyReal(unsigned int& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); - Property& addPropertyReal(String& property, PropertyContainer &prop_cont, String name, int tag, Permission const permission); }; #ifdef HAS_TCP From f1370560ba37a20d1fc197a451ca288e62e890cf Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 14 Nov 2022 13:32:59 +0100 Subject: [PATCH 363/780] Manually wrap and add hidden properties into the _device_property_container --- src/ArduinoIoTCloudTCP.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index f34da15af..3c11dea8f 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -250,18 +250,26 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _deviceTopicOut = getTopic_deviceout(); _deviceTopicIn = getTopic_devicein(); - addPropertyReal(_lib_version, _device_property_container, "LIB_VERSION", Permission::Read); + Property* p; + p = new CloudWrapperString(_lib_version); + addPropertyToContainer(_device_property_container, *p, "LIB_VERSION", Permission::Read, -1); #if OTA_ENABLED - addPropertyReal(_ota_cap, _device_property_container, "OTA_CAP", Permission::Read); - addPropertyReal(_ota_error, _device_property_container, "OTA_ERROR", Permission::Read); - addPropertyReal(_ota_img_sha256, _device_property_container, "OTA_SHA256", Permission::Read); - addPropertyReal(_ota_url, _device_property_container, "OTA_URL", Permission::ReadWrite); - addPropertyReal(_ota_req, _device_property_container, "OTA_REQ", Permission::ReadWrite); + p = new CloudWrapperBool(_ota_cap); + addPropertyToContainer(_device_property_container, *p, "OTA_CAP", Permission::Read, -1); + p = new CloudWrapperInt(_ota_error); + addPropertyToContainer(_device_property_container, *p, "OTA_ERROR", Permission::Read, -1); + p = new CloudWrapperString(_ota_img_sha256); + addPropertyToContainer(_device_property_container, *p, "OTA_SHA256", Permission::Read, -1); + p = new CloudWrapperString(_ota_url); + addPropertyToContainer(_device_property_container, *p, "OTA_URL", Permission::ReadWrite, -1); + p = new CloudWrapperBool(_ota_req); + addPropertyToContainer(_device_property_container, *p, "OTA_REQ", Permission::ReadWrite, -1); #endif /* OTA_ENABLED */ + p = new CloudWrapperString(_thing_id); + addPropertyToContainer(_device_property_container, *p, "thing_id", Permission::ReadWrite, -1).onUpdate(setThingIdOutdated); - addPropertyReal(_tz_offset, _thing_property_container, "tz_offset", Permission::ReadWrite).onSync(CLOUD_WINS).onUpdate(updateTimezoneInfo); - addPropertyReal(_tz_dst_until, _thing_property_container, "tz_dst_until", Permission::ReadWrite).onSync(CLOUD_WINS).onUpdate(updateTimezoneInfo); - addPropertyReal(_thing_id, _device_property_container, "thing_id", Permission::ReadWrite).onUpdate(setThingIdOutdated); + 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) From 9facaecb6d01c41ccd20257ed0bf820c58048916 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 1 Dec 2022 09:34:47 +0100 Subject: [PATCH 364/780] Remove No RTC available message --- src/property/Property.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index 833d9c68d..c6c3db9e4 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -21,10 +21,6 @@ #undef min #include -#if !defined ARDUINO_ARCH_SAMD && !defined ARDUINO_ARCH_MBED - #pragma message "No RTC available on this architecture - ArduinoIoTCloud will not keep track of local change timestamps ." -#endif - /****************************************************************************** CTOR/DTOR ******************************************************************************/ From 5b6ef6d95ec97852cf73d992b3aaa3d2ffe8ae69 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 1 Dec 2022 10:32:45 +0100 Subject: [PATCH 365/780] Unit tests: update catch to v2.13.10 --- extras/test/CMakeLists.txt | 2 +- .../{v2.12.1 => v2.13.10}/include/catch.hpp | 978 +++++++++++------- 2 files changed, 629 insertions(+), 351 deletions(-) rename extras/test/external/catch/{v2.12.1 => v2.13.10}/include/catch.hpp (95%) diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index b707b5254..8e5148905 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -13,7 +13,7 @@ include_directories(../../src) include_directories(../../src/cbor) include_directories(../../src/property) include_directories(../../src/utility/time) -include_directories(external/catch/v2.12.1/include) +include_directories(external/catch/v2.13.10/include) include_directories(external/fakeit/v2.0.5/include) ########################################################################## diff --git a/extras/test/external/catch/v2.12.1/include/catch.hpp b/extras/test/external/catch/v2.13.10/include/catch.hpp similarity index 95% rename from extras/test/external/catch/v2.12.1/include/catch.hpp rename to extras/test/external/catch/v2.13.10/include/catch.hpp index 1d2c9bb64..9b309bddc 100644 --- a/extras/test/external/catch/v2.12.1/include/catch.hpp +++ b/extras/test/external/catch/v2.13.10/include/catch.hpp @@ -1,9 +1,9 @@ /* - * Catch v2.12.1 - * Generated: 2020-04-21 19:29:20.964532 + * Catch v2.13.10 + * Generated: 2022-10-16 11:01:23.452308 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. + * Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -14,8 +14,8 @@ #define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 12 -#define CATCH_VERSION_PATCH 1 +#define CATCH_VERSION_MINOR 13 +#define CATCH_VERSION_PATCH 10 #ifdef __clang__ # pragma clang system_header @@ -66,13 +66,16 @@ #if !defined(CATCH_CONFIG_IMPL_ONLY) // start catch_platform.h +// See e.g.: +// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html #ifdef __APPLE__ -# include -# if TARGET_OS_OSX == 1 -# define CATCH_PLATFORM_MAC -# elif TARGET_OS_IPHONE == 1 -# define CATCH_PLATFORM_IPHONE -# endif +# include +# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ + (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) +# define CATCH_PLATFORM_MAC +# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) +# define CATCH_PLATFORM_IPHONE +# endif #elif defined(linux) || defined(__linux) || defined(__linux__) # define CATCH_PLATFORM_LINUX @@ -132,13 +135,9 @@ namespace Catch { #endif -#if defined(__cpp_lib_uncaught_exceptions) -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif - -// We have to avoid both ICC and Clang, because they try to mask themselves -// as gcc, and we want only GCC in this block -#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) +// Only GCC compiler should be used in this block, so other compilers trying to +// mask themselves as GCC should be ignored. +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) @@ -162,8 +161,8 @@ namespace Catch { // ``` // // Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. -# if !defined(__ibmxl__) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg) */ +# if !defined(__ibmxl__) && !defined(__CUDACC__) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ # endif # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ @@ -241,13 +240,6 @@ namespace Catch { // Visual C++ #if defined(_MSC_VER) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) - -# if _MSC_VER >= 1900 // Visual Studio 2015 or newer -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -# endif - // Universal Windows platform does not support SEH // Or console colours (or console at all...) # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) @@ -256,13 +248,18 @@ namespace Catch { # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH # endif +# if !defined(__clang__) // Handle Clang masquerading for msvc + // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ // _MSVC_TRADITIONAL == 0 means new conformant preprocessor // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(__clang__) // Handle Clang masquerading for msvc # if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) # define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR # endif // MSVC_TRADITIONAL + +// Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop` +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) # endif // __clang__ #endif // _MSC_VER @@ -330,7 +327,10 @@ namespace Catch { // Check if byte is available and usable # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # include + # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) // Check if variant is available and usable @@ -373,10 +373,6 @@ namespace Catch { # define CATCH_CONFIG_CPP17_OPTIONAL #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) -# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif - #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) # define CATCH_CONFIG_CPP17_STRING_VIEW #endif @@ -775,7 +771,7 @@ constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) n #define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) #define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) #define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) -#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) #define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) #define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) #define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) @@ -944,13 +940,13 @@ namespace Catch { #if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is - // replaced with std::invoke_result here. Also *_t format is preferred over - // typename *::type format. - template - using FunctionReturnType = std::remove_reference_t>>; + // replaced with std::invoke_result here. + template + using FunctionReturnType = std::remove_reference_t>>; #else - template - using FunctionReturnType = typename std::remove_reference::type>::type>::type; + // Keep ::type here because we still support C++11 + template + using FunctionReturnType = typename std::remove_reference::type>::type>::type; #endif } // namespace Catch @@ -1016,34 +1012,34 @@ struct AutoReg : NonCopyable { #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) #endif #endif @@ -1056,7 +1052,7 @@ struct AutoReg : NonCopyable { CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ static void TestName() #define INTERNAL_CATCH_TESTCASE( ... ) \ - INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ @@ -1078,7 +1074,7 @@ struct AutoReg : NonCopyable { CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ void TestName::test() #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ - INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), ClassName, __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ @@ -1105,7 +1101,7 @@ struct AutoReg : NonCopyable { int index = 0; \ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ using expander = int[];\ - (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \ + (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ }\ };\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ @@ -1119,18 +1115,18 @@ struct AutoReg : NonCopyable { #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) ) #endif #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \ @@ -1151,7 +1147,7 @@ struct AutoReg : NonCopyable { constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ - (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */\ + (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */\ } \ }; \ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ @@ -1168,18 +1164,18 @@ struct AutoReg : NonCopyable { #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T,__VA_ARGS__) + INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T,__VA_ARGS__) #else #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T, __VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__) + INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__) #else #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) ) #endif #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\ @@ -1195,7 +1191,7 @@ struct AutoReg : NonCopyable { void reg_tests() { \ int index = 0; \ using expander = int[]; \ - (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++, 0)... };/* NOLINT */\ + (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\ } \ };\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ @@ -1210,7 +1206,7 @@ struct AutoReg : NonCopyable { static void TestFunc() #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \ - INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, TmplList ) + INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, TmplList ) #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ @@ -1229,7 +1225,7 @@ struct AutoReg : NonCopyable { int index = 0; \ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ using expander = int[];\ - (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \ + (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ }\ };\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ @@ -1243,18 +1239,18 @@ struct AutoReg : NonCopyable { #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) #endif #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\ @@ -1278,7 +1274,7 @@ struct AutoReg : NonCopyable { constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ - (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */ \ + (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */ \ }\ };\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ @@ -1295,18 +1291,18 @@ struct AutoReg : NonCopyable { #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) ) #endif #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \ @@ -1325,7 +1321,7 @@ struct AutoReg : NonCopyable { void reg_tests(){\ int index = 0;\ using expander = int[];\ - (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++, 0)... };/* NOLINT */ \ + (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \ }\ };\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ @@ -1340,7 +1336,7 @@ struct AutoReg : NonCopyable { void TestName::test() #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \ - INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, TmplList ) + INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, TmplList ) // end catch_test_registry.h // start catch_capture.hpp @@ -1829,8 +1825,8 @@ namespace Catch { #endif namespace Detail { - template - std::string rangeToString(InputIterator first, InputIterator last) { + template + std::string rangeToString(InputIterator first, Sentinel last) { ReusableStringStream rss; rss << "{ "; if (first != last) { @@ -1988,20 +1984,27 @@ namespace Catch { #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER namespace Catch { - struct not_this_one {}; // Tag type for detecting which begin/ end are being selected - - // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace + // Import begin/ end from std here using std::begin; using std::end; - not_this_one begin( ... ); - not_this_one end( ... ); + namespace detail { + template + struct void_type { + using type = void; + }; + + template + struct is_range_impl : std::false_type { + }; + + template + struct is_range_impl()))>::type> : std::true_type { + }; + } // namespace detail template - struct is_range { - static const bool value = - !std::is_same())), not_this_one>::value && - !std::is_same())), not_this_one>::value; + struct is_range : detail::is_range_impl { }; #if defined(_MANAGED) // Managed types are never ranges @@ -2206,7 +2209,7 @@ namespace Catch { m_result( result ) {} - // We don't actually need a virtual destructor, but many static analyzers + // We don't actually need a virtual destructor, but many static analysers // complain if it's not here :-( virtual ~ITransientExpression(); @@ -2461,7 +2464,7 @@ namespace Catch { virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; - virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; + virtual auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) virtual void benchmarkPreparing( std::string const& name ) = 0; @@ -3090,7 +3093,7 @@ namespace Detail { Approx operator-() const; template ::value>::type> - Approx operator()( T const& value ) { + Approx operator()( T const& value ) const { Approx approx( static_cast(value) ); approx.m_epsilon = m_epsilon; approx.m_margin = m_margin; @@ -3714,8 +3717,6 @@ namespace Matchers { struct UnorderedEqualsMatcher : MatcherBase> { UnorderedEqualsMatcher(std::vector const& target) : m_target(target) {} bool match(std::vector const& vec) const override { - // Note: This is a reimplementation of std::is_permutation, - // because I don't want to include inside the common path if (m_target.size() != vec.size()) { return false; } @@ -3847,7 +3848,7 @@ namespace Catch { virtual ~GeneratorUntypedBase(); // Attempts to move the generator to the next element // - // Returns true if the move succeeded (and a valid element + // Returns true iff the move succeeded (and a valid element // can be retrieved). virtual bool next() = 0; }; @@ -4075,16 +4076,16 @@ namespace Generators { return makeGenerators( value( T( std::forward( val ) ) ), std::forward( moreGenerators )... ); } - auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; + auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; template // Note: The type after -> is weird, because VS2015 cannot parse // the expression used in the typedef inside, when it is in // return type. Yeah. - auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval().get()) { + auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval().get()) { using UnderlyingType = typename decltype(generatorExpression())::type; - IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo ); + IGeneratorTracker& tracker = acquireGeneratorTracker( generatorName, lineInfo ); if (!tracker.hasGenerator()) { tracker.setGenerator(pf::make_unique>(generatorExpression())); } @@ -4097,11 +4098,17 @@ namespace Generators { } // namespace Catch #define GENERATE( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) + Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ + CATCH_INTERNAL_LINEINFO, \ + [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) #define GENERATE_COPY( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) + Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ + CATCH_INTERNAL_LINEINFO, \ + [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) #define GENERATE_REF( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) + Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ + CATCH_INTERNAL_LINEINFO, \ + [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) // end catch_generators.hpp // start catch_generators_generic.hpp @@ -4158,7 +4165,7 @@ namespace Generators { if (!m_predicate(m_generator.get())) { // It might happen that there are no values that pass the // filter. In that case we throw an exception. - auto has_initial_value = next(); + auto has_initial_value = nextImpl(); if (!has_initial_value) { Catch::throw_exception(GeneratorException("No valid value found in filtered generator")); } @@ -4170,6 +4177,11 @@ namespace Generators { } bool next() override { + return nextImpl(); + } + + private: + bool nextImpl() { bool success = m_generator.next(); if (!success) { return false; @@ -4511,6 +4523,7 @@ namespace Catch { virtual int abortAfter() const = 0; virtual bool showInvisibles() const = 0; virtual ShowDurations::OrNot showDurations() const = 0; + virtual double minDuration() const = 0; virtual TestSpec const& testSpec() const = 0; virtual bool hasTestFilters() const = 0; virtual std::vector const& getTestsOrTags() const = 0; @@ -5283,6 +5296,7 @@ namespace Catch { Verbosity verbosity = Verbosity::Normal; WarnAbout::What warnings = WarnAbout::Nothing; ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; + double minDuration = -1; RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; UseColour::YesOrNo useColour = UseColour::Auto; WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; @@ -5333,6 +5347,7 @@ namespace Catch { bool warnAboutMissingAssertions() const override; bool warnAboutNoTests() const override; ShowDurations::OrNot showDurations() const override; + double minDuration() const override; RunTests::InWhatOrder runOrder() const override; unsigned int rngSeed() const override; UseColour::YesOrNo useColour() const override; @@ -5450,6 +5465,8 @@ namespace Catch { } // namespace Catch // end catch_outlier_classification.hpp + +#include #endif // CATCH_CONFIG_ENABLE_BENCHMARKING #include @@ -5710,6 +5727,9 @@ namespace Catch { // Returns double formatted as %.3f (format expected on output) std::string getFormattedDuration( double duration ); + //! Should the reporter show + bool shouldShowDuration( IConfig const& config, double duration ); + std::string serializeFilters( std::vector const& container ); template @@ -6103,8 +6123,6 @@ namespace Catch { static std::string getDescription(); - ReporterPreferences getPreferences() const override; - void noMatchingTestCases(std::string const& spec) override; void assertionStarting(AssertionInfo const&) override; @@ -6333,9 +6351,10 @@ namespace Catch { void writeTestCase(TestCaseNode const& testCaseNode); - void writeSection(std::string const& className, - std::string const& rootName, - SectionNode const& sectionNode); + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode, + bool testOkToFail ); void writeAssertions(SectionNode const& sectionNode); void writeAssertion(AssertionStats const& stats); @@ -6552,20 +6571,18 @@ namespace Catch { return {}; } }; - template - using ResultOf_t = typename std::result_of::type; // invoke and not return void :( template - CompleteType_t> complete_invoke(Fun&& fun, Args&&... args) { - return CompleteInvoker>::invoke(std::forward(fun), std::forward(args)...); + CompleteType_t> complete_invoke(Fun&& fun, Args&&... args) { + return CompleteInvoker>::invoke(std::forward(fun), std::forward(args)...); } const std::string benchmarkErrorMsg = "a benchmark failed to run successfully"; } // namespace Detail template - Detail::CompleteType_t> user_code(Fun&& fun) { + Detail::CompleteType_t> user_code(Fun&& fun) { CATCH_TRY{ return Detail::complete_invoke(std::forward(fun)); } CATCH_CATCH_ALL{ @@ -6810,8 +6827,8 @@ namespace Catch { Result result; int iterations; }; - template - using TimingOf = Timing, Detail::CompleteType_t>>; + template + using TimingOf = Timing, Detail::CompleteType_t>>; } // namespace Benchmark } // namespace Catch @@ -6822,7 +6839,7 @@ namespace Catch { namespace Benchmark { namespace Detail { template - TimingOf measure(Fun&& fun, Args&&... args) { + TimingOf measure(Fun&& fun, Args&&... args) { auto start = Clock::now(); auto&& r = Detail::complete_invoke(fun, std::forward(args)...); auto end = Clock::now(); @@ -6841,11 +6858,11 @@ namespace Catch { namespace Benchmark { namespace Detail { template - TimingOf measure_one(Fun&& fun, int iters, std::false_type) { + TimingOf measure_one(Fun&& fun, int iters, std::false_type) { return Detail::measure(fun, iters); } template - TimingOf measure_one(Fun&& fun, int iters, std::true_type) { + TimingOf measure_one(Fun&& fun, int iters, std::true_type) { Detail::ChronometerModel meter; auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters)); @@ -6862,7 +6879,7 @@ namespace Catch { }; template - TimingOf)> run_for_at_least(ClockDuration how_long, int seed, Fun&& fun) { + TimingOf> run_for_at_least(ClockDuration how_long, int seed, Fun&& fun) { auto iters = seed; while (iters < (1 << 30)) { auto&& Timing = measure_one(fun, iters, is_callable()); @@ -6872,7 +6889,7 @@ namespace Catch { } iters *= 2; } - throw optimized_away_error{}; + Catch::throw_exception(optimized_away_error{}); } } // namespace Detail } // namespace Benchmark @@ -6880,6 +6897,7 @@ namespace Catch { // end catch_run_for_at_least.hpp #include +#include namespace Catch { namespace Benchmark { @@ -7050,8 +7068,8 @@ namespace Catch { double b2 = bias - z1; double a1 = a(b1); double a2 = a(b2); - auto lo = std::max(cumn(a1), 0); - auto hi = std::min(cumn(a2), n - 1); + auto lo = (std::max)(cumn(a1), 0); + auto hi = (std::min)(cumn(a2), n - 1); return { point, resample[lo], resample[hi], confidence_level }; } @@ -7120,7 +7138,9 @@ namespace Catch { } template EnvironmentEstimate> estimate_clock_cost(FloatDuration resolution) { - auto time_limit = std::min(resolution * clock_cost_estimation_tick_limit, FloatDuration(clock_cost_estimation_time_limit)); + auto time_limit = (std::min)( + resolution * clock_cost_estimation_tick_limit, + FloatDuration(clock_cost_estimation_time_limit)); auto time_clock = [](int k) { return Detail::measure([k] { for (int i = 0; i < k; ++i) { @@ -7375,8 +7395,6 @@ namespace Catch { template struct ObjectStorage { - using TStorage = typename std::aligned_storage::value>::type; - ObjectStorage() : data() {} ObjectStorage(const ObjectStorage& other) @@ -7419,7 +7437,7 @@ namespace Catch { return *static_cast(static_cast(&data)); } - TStorage data; + struct { alignas(T) unsigned char data[sizeof(T)]; } data; }; } @@ -7460,23 +7478,37 @@ namespace TestCaseTracking { SourceLineInfo location; NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); + friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) { + return lhs.name == rhs.name + && lhs.location == rhs.location; + } }; - struct ITracker; + class ITracker; using ITrackerPtr = std::shared_ptr; - struct ITracker { - virtual ~ITracker(); + class ITracker { + NameAndLocation m_nameAndLocation; + + public: + ITracker(NameAndLocation const& nameAndLoc) : + m_nameAndLocation(nameAndLoc) + {} // static queries - virtual NameAndLocation const& nameAndLocation() const = 0; + NameAndLocation const& nameAndLocation() const { + return m_nameAndLocation; + } + + virtual ~ITracker(); // dynamic queries virtual bool isComplete() const = 0; // Successfully completed or failed virtual bool isSuccessfullyCompleted() const = 0; virtual bool isOpen() const = 0; // Started but not complete virtual bool hasChildren() const = 0; + virtual bool hasStarted() const = 0; virtual ITracker& parent() = 0; @@ -7531,7 +7563,6 @@ namespace TestCaseTracking { }; using Children = std::vector; - NameAndLocation m_nameAndLocation; TrackerContext& m_ctx; ITracker* m_parent; Children m_children; @@ -7540,11 +7571,13 @@ namespace TestCaseTracking { public: TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); - NameAndLocation const& nameAndLocation() const override; bool isComplete() const override; bool isSuccessfullyCompleted() const override; bool isOpen() const override; bool hasChildren() const override; + bool hasStarted() const override { + return m_runState != NotStarted; + } void addChild( ITrackerPtr const& child ) override; @@ -7583,6 +7616,10 @@ namespace TestCaseTracking { void addInitialFilters( std::vector const& filters ); void addNextFilters( std::vector const& filters ); + //! Returns filters active in this tracker + std::vector const& getFilters() const; + //! Returns whitespace-trimmed name of the tracked section + std::string const& trimmedName() const; }; } // namespace TestCaseTracking @@ -7748,7 +7785,7 @@ namespace Catch { double sb = stddev.point; double mn = mean.point / n; double mg_min = mn / 2.; - double sg = std::min(mg_min / 4., sb / std::sqrt(n)); + double sg = (std::min)(mg_min / 4., sb / std::sqrt(n)); double sg2 = sg * sg; double sb2 = sb * sb; @@ -7767,7 +7804,7 @@ namespace Catch { return (nc / n) * (sb2 - nc * sg2); }; - return std::min(var_out(1), var_out(std::min(c_max(0.), c_max(mg_min)))) / sb2; + return (std::min)(var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / sb2; } bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector::iterator first, std::vector::iterator last) { @@ -7907,7 +7944,11 @@ namespace Catch { #ifdef CATCH_PLATFORM_MAC - #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ + #if defined(__i386__) || defined(__x86_64__) + #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ + #elif defined(__aarch64__) + #define CATCH_TRAP() __asm__(".inst 0xd43e0000") + #endif #elif defined(CATCH_PLATFORM_IPHONE) @@ -7953,86 +7994,58 @@ namespace Catch { // start catch_fatal_condition.h -// start catch_windows_h_proxy.h - - -#if defined(CATCH_PLATFORM_WINDOWS) - -#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -# define CATCH_DEFINED_NOMINMAX -# define NOMINMAX -#endif -#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif - -#ifdef __AFXDLL -#include -#else -#include -#endif - -#ifdef CATCH_DEFINED_NOMINMAX -# undef NOMINMAX -#endif -#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# undef WIN32_LEAN_AND_MEAN -#endif - -#endif // defined(CATCH_PLATFORM_WINDOWS) - -// end catch_windows_h_proxy.h -#if defined( CATCH_CONFIG_WINDOWS_SEH ) +#include namespace Catch { - struct FatalConditionHandler { - - static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); + // Wrapper for platform-specific fatal error (signals/SEH) handlers + // + // Tries to be cooperative with other handlers, and not step over + // other handlers. This means that unknown structured exceptions + // are passed on, previous signal handlers are called, and so on. + // + // Can only be instantiated once, and assumes that once a signal + // is caught, the binary will end up terminating. Thus, there + class FatalConditionHandler { + bool m_started = false; + + // Install/disengage implementation for specific platform. + // Should be if-defed to work on current platform, can assume + // engage-disengage 1:1 pairing. + void engage_platform(); + void disengage_platform(); + public: + // Should also have platform-specific implementations as needed FatalConditionHandler(); - static void reset(); ~FatalConditionHandler(); - private: - static bool isSet; - static ULONG guaranteeSize; - static PVOID exceptionHandlerHandle; - }; - -} // namespace Catch - -#elif defined ( CATCH_CONFIG_POSIX_SIGNALS ) - -#include - -namespace Catch { - - struct FatalConditionHandler { - - static bool isSet; - static struct sigaction oldSigActions[]; - static stack_t oldSigStack; - static char altStackMem[]; - - static void handleSignal( int sig ); + void engage() { + assert(!m_started && "Handler cannot be installed twice."); + m_started = true; + engage_platform(); + } - FatalConditionHandler(); - ~FatalConditionHandler(); - static void reset(); + void disengage() { + assert(m_started && "Handler cannot be uninstalled without being installed first"); + m_started = false; + disengage_platform(); + } }; -} // namespace Catch - -#else - -namespace Catch { - struct FatalConditionHandler { - void reset(); + //! Simple RAII guard for (dis)engaging the FatalConditionHandler + class FatalConditionHandlerGuard { + FatalConditionHandler* m_handler; + public: + FatalConditionHandlerGuard(FatalConditionHandler* handler): + m_handler(handler) { + m_handler->engage(); + } + ~FatalConditionHandlerGuard() { + m_handler->disengage(); + } }; -} -#endif +} // end namespace Catch // end catch_fatal_condition.h #include @@ -8092,7 +8105,7 @@ namespace Catch { void sectionEnded( SectionEndInfo const& endInfo ) override; void sectionEndedEarly( SectionEndInfo const& endInfo ) override; - auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override; + auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override; #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) void benchmarkPreparing( std::string const& name ) override; @@ -8158,6 +8171,7 @@ namespace Catch { std::vector m_unfinishedSections; std::vector m_activeSections; TrackerContext m_trackerContext; + FatalConditionHandler m_fatalConditionhandler; bool m_lastAssertionPassed = false; bool m_shouldReportUnexpected = true; bool m_includeSuccessfulResults; @@ -9068,7 +9082,7 @@ namespace detail { } inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { std::string srcLC = source; - std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast( std::tolower(c) ); } ); + std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( unsigned char c ) { return static_cast( std::tolower(c) ); } ); if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") target = true; else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") @@ -9837,6 +9851,9 @@ namespace Catch { | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) ["-d"]["--durations"] ( "show test durations" ) + | Opt( config.minDuration, "seconds" ) + ["-D"]["--min-duration"] + ( "show test durations for tests taking at least the given number of seconds" ) | Opt( loadTestNamesFromFile, "filename" ) ["-f"]["--input-file"] ( "load test names to run from a file" ) @@ -9984,6 +10001,7 @@ namespace Catch { bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); } bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); } ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } + double Config::minDuration() const { return m_data.minDuration; } RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } unsigned int Config::rngSeed() const { return m_data.rngSeed; } UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } @@ -10026,6 +10044,36 @@ namespace Catch { } // end catch_errno_guard.h +// start catch_windows_h_proxy.h + + +#if defined(CATCH_PLATFORM_WINDOWS) + +#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) +# define CATCH_DEFINED_NOMINMAX +# define NOMINMAX +#endif +#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) +# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +#ifdef CATCH_DEFINED_NOMINMAX +# undef NOMINMAX +#endif +#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +#endif + +#endif // defined(CATCH_PLATFORM_WINDOWS) + +// end catch_windows_h_proxy.h #include namespace Catch { @@ -10704,25 +10752,47 @@ namespace Catch { // end catch_exception_translator_registry.cpp // start catch_fatal_condition.cpp -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif +#include + +#if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS ) + +namespace Catch { + + // If neither SEH nor signal handling is required, the handler impls + // do not have to do anything, and can be empty. + void FatalConditionHandler::engage_platform() {} + void FatalConditionHandler::disengage_platform() {} + FatalConditionHandler::FatalConditionHandler() = default; + FatalConditionHandler::~FatalConditionHandler() = default; + +} // end namespace Catch + +#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS + +#if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS ) +#error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time" +#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) namespace { - // Report the error condition + //! Signals fatal error message to the run context void reportFatal( char const * const message ) { Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); } -} -#endif // signals/SEH handling + //! Minimal size Catch2 needs for its own fatal error handling. + //! Picked anecdotally, so it might not be sufficient on all + //! platforms, and for all configurations. + constexpr std::size_t minStackSizeForErrors = 32 * 1024; +} // end unnamed namespace + +#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS #if defined( CATCH_CONFIG_WINDOWS_SEH ) namespace Catch { + struct SignalDefs { DWORD id; const char* name; }; // There is no 1-1 mapping between signals and windows exceptions. @@ -10735,7 +10805,7 @@ namespace Catch { { static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" }, }; - LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { + static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { for (auto const& def : signalDefs) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { reportFatal(def.name); @@ -10746,38 +10816,50 @@ namespace Catch { return EXCEPTION_CONTINUE_SEARCH; } + // Since we do not support multiple instantiations, we put these + // into global variables and rely on cleaning them up in outlined + // constructors/destructors + static PVOID exceptionHandlerHandle = nullptr; + + // For MSVC, we reserve part of the stack memory for handling + // memory overflow structured exception. FatalConditionHandler::FatalConditionHandler() { - isSet = true; - // 32k seems enough for Catch to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - exceptionHandlerHandle = nullptr; + ULONG guaranteeSize = static_cast(minStackSizeForErrors); + if (!SetThreadStackGuarantee(&guaranteeSize)) { + // We do not want to fully error out, because needing + // the stack reserve should be rare enough anyway. + Catch::cerr() + << "Failed to reserve piece of stack." + << " Stack overflows will not be reported successfully."; + } + } + + // We do not attempt to unset the stack guarantee, because + // Windows does not support lowering the stack size guarantee. + FatalConditionHandler::~FatalConditionHandler() = default; + + void FatalConditionHandler::engage_platform() { // Register as first handler in current chain exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); + if (!exceptionHandlerHandle) { + CATCH_RUNTIME_ERROR("Could not register vectored exception handler"); + } } - void FatalConditionHandler::reset() { - if (isSet) { - RemoveVectoredExceptionHandler(exceptionHandlerHandle); - SetThreadStackGuarantee(&guaranteeSize); - exceptionHandlerHandle = nullptr; - isSet = false; + void FatalConditionHandler::disengage_platform() { + if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) { + CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler"); } + exceptionHandlerHandle = nullptr; } - FatalConditionHandler::~FatalConditionHandler() { - reset(); - } +} // end namespace Catch -bool FatalConditionHandler::isSet = false; -ULONG FatalConditionHandler::guaranteeSize = 0; -PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; +#endif // CATCH_CONFIG_WINDOWS_SEH -} // namespace Catch +#if defined( CATCH_CONFIG_POSIX_SIGNALS ) -#elif defined( CATCH_CONFIG_POSIX_SIGNALS ) +#include namespace Catch { @@ -10786,10 +10868,6 @@ namespace Catch { const char* name; }; - // 32kb for the alternate stack seems to be sufficient. However, this value - // is experimentally determined, so that's not guaranteed. - static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; - static SignalDefs signalDefs[] = { { SIGINT, "SIGINT - Terminal interrupt signal" }, { SIGILL, "SIGILL - Illegal instruction signal" }, @@ -10799,7 +10877,32 @@ namespace Catch { { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } }; - void FatalConditionHandler::handleSignal( int sig ) { +// Older GCCs trigger -Wmissing-field-initializers for T foo = {} +// which is zero initialization, but not explicit. We want to avoid +// that. +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + + static char* altStackMem = nullptr; + static std::size_t altStackSize = 0; + static stack_t oldSigStack{}; + static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{}; + + static void restorePreviousSignalHandlers() { + // We set signal handlers back to the previous ones. Hopefully + // nobody overwrote them in the meantime, and doesn't expect + // their signal handlers to live past ours given that they + // installed them after ours.. + for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); + } + // Return the old stack + sigaltstack(&oldSigStack, nullptr); + } + + static void handleSignal( int sig ) { char const * name = ""; for (auto const& def : signalDefs) { if (sig == def.id) { @@ -10807,16 +10910,33 @@ namespace Catch { break; } } - reset(); - reportFatal(name); + // We need to restore previous signal handlers and let them do + // their thing, so that the users can have the debugger break + // when a signal is raised, and so on. + restorePreviousSignalHandlers(); + reportFatal( name ); raise( sig ); } FatalConditionHandler::FatalConditionHandler() { - isSet = true; + assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists"); + if (altStackSize == 0) { + altStackSize = std::max(static_cast(SIGSTKSZ), minStackSizeForErrors); + } + altStackMem = new char[altStackSize](); + } + + FatalConditionHandler::~FatalConditionHandler() { + delete[] altStackMem; + // We signal that another instance can be constructed by zeroing + // out the pointer. + altStackMem = nullptr; + } + + void FatalConditionHandler::engage_platform() { stack_t sigStack; sigStack.ss_sp = altStackMem; - sigStack.ss_size = sigStackSize; + sigStack.ss_size = altStackSize; sigStack.ss_flags = 0; sigaltstack(&sigStack, &oldSigStack); struct sigaction sa = { }; @@ -10828,40 +10948,17 @@ namespace Catch { } } - FatalConditionHandler::~FatalConditionHandler() { - reset(); - } +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#endif - void FatalConditionHandler::reset() { - if( isSet ) { - // Set signals back to previous values -- hopefully nobody overwrote them in the meantime - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { - sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); - } - // Return the old stack - sigaltstack(&oldSigStack, nullptr); - isSet = false; - } + void FatalConditionHandler::disengage_platform() { + restorePreviousSignalHandlers(); } - bool FatalConditionHandler::isSet = false; - struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - char FatalConditionHandler::altStackMem[sigStackSize] = {}; - -} // namespace Catch - -#else - -namespace Catch { - void FatalConditionHandler::reset() {} -} - -#endif // signals/SEH handling +} // end namespace Catch -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#endif +#endif // CATCH_CONFIG_POSIX_SIGNALS // end catch_fatal_condition.cpp // start catch_generators.cpp @@ -10880,8 +10977,8 @@ namespace Generators { GeneratorUntypedBase::~GeneratorUntypedBase() {} - auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { - return getResultCapture().acquireGeneratorTracker( lineInfo ); + auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { + return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo ); } } // namespace Generators @@ -11416,7 +11513,8 @@ namespace { return lhs == rhs; } - auto ulpDiff = std::abs(lc - rc); + // static cast as a workaround for IBM XLC + auto ulpDiff = std::abs(static_cast(lc - rc)); return static_cast(ulpDiff) <= maxUlpDiff; } @@ -11590,7 +11688,6 @@ Floating::WithinRelMatcher WithinRel(float target) { } // namespace Matchers } // namespace Catch - // end catch_matchers_floating.cpp // start catch_matchers_generic.cpp @@ -11768,10 +11865,10 @@ namespace Catch { Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) { auto trimmed = [&] (size_t start, size_t end) { - while (names[start] == ',' || isspace(names[start])) { + while (names[start] == ',' || isspace(static_cast(names[start]))) { ++start; } - while (names[end] == ',' || isspace(names[end])) { + while (names[end] == ',' || isspace(static_cast(names[end]))) { --end; } return names.substr(start, end - start + 1); @@ -12006,7 +12103,7 @@ namespace Catch { if (tmpnam_s(m_buffer)) { CATCH_RUNTIME_ERROR("Could not get a temp filename"); } - if (fopen_s(&m_file, m_buffer, "w")) { + if (fopen_s(&m_file, m_buffer, "w+")) { char buffer[100]; if (strerror_s(buffer, errno)) { CATCH_RUNTIME_ERROR("Could not translate errno to a string"); @@ -12301,11 +12398,13 @@ namespace Catch { namespace Catch { class StartupExceptionRegistry { +#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) public: void add(std::exception_ptr const& exception) noexcept; std::vector const& getExceptions() const noexcept; private: std::vector m_exceptions; +#endif }; } // end namespace Catch @@ -12388,7 +12487,11 @@ namespace Catch { m_tagAliasRegistry.add( alias, tag, lineInfo ); } void registerStartupException() noexcept override { +#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) m_exceptionRegistry.add(std::current_exception()); +#else + CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); +#endif } IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override { return m_enumValuesRegistry; @@ -12492,17 +12595,32 @@ namespace Catch { std::shared_ptr tracker; ITracker& currentTracker = ctx.currentTracker(); - if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { + // Under specific circumstances, the generator we want + // to acquire is also the current tracker. If this is + // the case, we have to avoid looking through current + // tracker's children, and instead return the current + // tracker. + // A case where this check is important is e.g. + // for (int i = 0; i < 5; ++i) { + // int n = GENERATE(1, 2); + // } + // + // without it, the code above creates 5 nested generators. + if (currentTracker.nameAndLocation() == nameAndLocation) { + auto thisTracker = currentTracker.parent().findChild(nameAndLocation); + assert(thisTracker); + assert(thisTracker->isGeneratorTracker()); + tracker = std::static_pointer_cast(thisTracker); + } else if ( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { assert( childTracker ); assert( childTracker->isGeneratorTracker() ); tracker = std::static_pointer_cast( childTracker ); - } - else { + } else { tracker = std::make_shared( nameAndLocation, ctx, ¤tTracker ); currentTracker.addChild( tracker ); } - if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( !tracker->isComplete() ) { tracker->open(); } @@ -12516,8 +12634,68 @@ namespace Catch { } void close() override { TrackerBase::close(); - // Generator interface only finds out if it has another item on atual move - if (m_runState == CompletedSuccessfully && m_generator->next()) { + // If a generator has a child (it is followed by a section) + // and none of its children have started, then we must wait + // until later to start consuming its values. + // This catches cases where `GENERATE` is placed between two + // `SECTION`s. + // **The check for m_children.empty cannot be removed**. + // doing so would break `GENERATE` _not_ followed by `SECTION`s. + const bool should_wait_for_child = [&]() { + // No children -> nobody to wait for + if ( m_children.empty() ) { + return false; + } + // If at least one child started executing, don't wait + if ( std::find_if( + m_children.begin(), + m_children.end(), + []( TestCaseTracking::ITrackerPtr tracker ) { + return tracker->hasStarted(); + } ) != m_children.end() ) { + return false; + } + + // No children have started. We need to check if they _can_ + // start, and thus we should wait for them, or they cannot + // start (due to filters), and we shouldn't wait for them + auto* parent = m_parent; + // This is safe: there is always at least one section + // tracker in a test case tracking tree + while ( !parent->isSectionTracker() ) { + parent = &( parent->parent() ); + } + assert( parent && + "Missing root (test case) level section" ); + + auto const& parentSection = + static_cast( *parent ); + auto const& filters = parentSection.getFilters(); + // No filters -> no restrictions on running sections + if ( filters.empty() ) { + return true; + } + + for ( auto const& child : m_children ) { + if ( child->isSectionTracker() && + std::find( filters.begin(), + filters.end(), + static_cast( *child ) + .trimmedName() ) != + filters.end() ) { + return true; + } + } + return false; + }(); + + // This check is a bit tricky, because m_generator->next() + // has a side-effect, where it consumes generator's current + // value, but we do not want to invoke the side-effect if + // this generator is still waiting for any child to start. + if ( should_wait_for_child || + ( m_runState == CompletedSuccessfully && + m_generator->next() ) ) { m_children.clear(); m_runState = Executing; } @@ -12653,10 +12831,10 @@ namespace Catch { return true; } - auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { + auto RunContext::acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { using namespace Generators; - GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) ); - assert( tracker.isOpen() ); + GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext, + TestCaseTracking::NameAndLocation( static_cast(generatorName), lineInfo ) ); m_lastAssertionInfo.lineInfo = lineInfo; return tracker; } @@ -12699,17 +12877,17 @@ namespace Catch { #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) void RunContext::benchmarkPreparing(std::string const& name) { - m_reporter->benchmarkPreparing(name); - } + m_reporter->benchmarkPreparing(name); + } void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { m_reporter->benchmarkStarting( info ); } void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) { m_reporter->benchmarkEnded( stats ); } - void RunContext::benchmarkFailed(std::string const & error) { - m_reporter->benchmarkFailed(error); - } + void RunContext::benchmarkFailed(std::string const & error) { + m_reporter->benchmarkFailed(error); + } #endif // CATCH_CONFIG_ENABLE_BENCHMARKING void RunContext::pushScopedMessage(MessageInfo const & message) { @@ -12843,9 +13021,8 @@ namespace Catch { } void RunContext::invokeActiveTestCase() { - FatalConditionHandler fatalConditionHandler; // Handle signals + FatalConditionHandlerGuard _(&m_fatalConditionhandler); m_activeTestCase->invoke(); - fatalConditionHandler.reset(); } void RunContext::handleUnfinishedSections() { @@ -13213,6 +13390,10 @@ namespace Catch { filename.erase(0, lastSlash); filename[0] = '#'; } + else + { + filename.insert(0, "#"); + } auto lastDot = filename.find_last_of('.'); if (lastDot != std::string::npos) { @@ -13375,7 +13556,7 @@ namespace Catch { // Handle list request if( Option listed = list( m_config ) ) - return static_cast( *listed ); + return (std::min) (MaxExitCode, static_cast(*listed)); TestGroup tests { m_config }; auto const totals = tests.execute(); @@ -13430,6 +13611,7 @@ namespace Catch { // end catch_singletons.cpp // start catch_startup_exception_registry.cpp +#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) namespace Catch { void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { CATCH_TRY { @@ -13445,6 +13627,7 @@ void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexce } } // end namespace Catch +#endif // end catch_startup_exception_registry.cpp // start catch_stream.cpp @@ -13629,7 +13812,7 @@ namespace Catch { namespace { char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); + return static_cast( std::tolower( static_cast(c) ) ); } } @@ -14012,24 +14195,28 @@ namespace Catch { namespace { struct TestHasher { - explicit TestHasher(Catch::SimplePcg32& rng) { - basis = rng(); - basis <<= 32; - basis |= rng(); - } + using hash_t = uint64_t; - uint64_t basis; + explicit TestHasher( hash_t hashSuffix ): + m_hashSuffix{ hashSuffix } {} - uint64_t operator()(TestCase const& t) const { - // Modified FNV-1a hash - static constexpr uint64_t prime = 1099511628211; - uint64_t hash = basis; - for (const char c : t.name) { + uint32_t operator()( TestCase const& t ) const { + // FNV-1a hash with multiplication fold. + const hash_t prime = 1099511628211u; + hash_t hash = 14695981039346656037u; + for ( const char c : t.name ) { hash ^= c; hash *= prime; } - return hash; + hash ^= m_hashSuffix; + hash *= prime; + const uint32_t low{ static_cast( hash ) }; + const uint32_t high{ static_cast( hash >> 32 ) }; + return low * high; } + + private: + hash_t m_hashSuffix; }; } // end unnamed namespace @@ -14047,9 +14234,9 @@ namespace Catch { case RunTests::InRandomOrder: { seedRng( config ); - TestHasher h( rng() ); + TestHasher h{ config.rngSeed() }; - using hashedTest = std::pair; + using hashedTest = std::pair; std::vector indexed_tests; indexed_tests.reserve( unsortedTestCases.size() ); @@ -14212,15 +14399,12 @@ namespace TestCaseTracking { m_currentTracker = tracker; } - TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : m_nameAndLocation( nameAndLocation ), + TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ): + ITracker(nameAndLocation), m_ctx( ctx ), m_parent( parent ) {} - NameAndLocation const& TrackerBase::nameAndLocation() const { - return m_nameAndLocation; - } bool TrackerBase::isComplete() const { return m_runState == CompletedSuccessfully || m_runState == Failed; } @@ -14336,7 +14520,8 @@ namespace TestCaseTracking { bool SectionTracker::isComplete() const { bool complete = true; - if ((m_filters.empty() || m_filters[0] == "") + if (m_filters.empty() + || m_filters[0] == "" || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) { complete = TrackerBase::isComplete(); } @@ -14381,6 +14566,14 @@ namespace TestCaseTracking { m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() ); } + std::vector const& SectionTracker::getFilters() const { + return m_filters; + } + + std::string const& SectionTracker::trimmedName() const { + return m_trimmed_name; + } + } // namespace TestCaseTracking using TestCaseTracking::ITracker; @@ -15115,11 +15308,48 @@ namespace Catch { // end catch_totals.cpp // start catch_uncaught_exceptions.cpp +// start catch_config_uncaught_exceptions.hpp + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 + +#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP +#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP + +#if defined(_MSC_VER) +# if _MSC_VER >= 1900 // Visual Studio 2015 or newer +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +# endif +#endif + +#include + +#if defined(__cpp_lib_uncaught_exceptions) \ + && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) + +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif // __cpp_lib_uncaught_exceptions + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \ + && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \ + && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) + +# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP +// end catch_config_uncaught_exceptions.hpp #include namespace Catch { bool uncaught_exceptions() { -#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) + return false; +#elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) return std::uncaught_exceptions() > 0; #else return std::uncaught_exception(); @@ -15159,7 +15389,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 12, 1, "", 0 ); + static Version version( 2, 13, 10, "", 0 ); return version; } @@ -15561,6 +15791,17 @@ namespace Catch { return std::string(buffer); } + bool shouldShowDuration( IConfig const& config, double duration ) { + if ( config.showDurations() == ShowDurations::Always ) { + return true; + } + if ( config.showDurations() == ShowDurations::Never ) { + return false; + } + const double min = config.minDuration(); + return min >= 0 && duration >= min; + } + std::string serializeFilters( std::vector const& container ) { ReusableStringStream oss; bool first = true; @@ -15827,10 +16068,6 @@ class AssertionPrinter { return "Reports test results on a single line, suitable for IDEs"; } - ReporterPreferences CompactReporter::getPreferences() const { - return m_reporterPrefs; - } - void CompactReporter::noMatchingTestCases( std::string const& spec ) { stream << "No test cases matched '" << spec << '\'' << std::endl; } @@ -15857,8 +16094,9 @@ class AssertionPrinter { } void CompactReporter::sectionEnded(SectionStats const& _sectionStats) { - if (m_config->showDurations() == ShowDurations::Always) { - stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; + double dur = _sectionStats.durationInSeconds; + if ( shouldShowDuration( *m_config, dur ) ) { + stream << getFormattedDuration( dur ) << " s: " << _sectionStats.sectionInfo.name << std::endl; } } @@ -16278,8 +16516,9 @@ void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) { stream << "\nNo assertions in test case"; stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; } - if (m_config->showDurations() == ShowDurations::Always) { - stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; + double dur = _sectionStats.durationInSeconds; + if (shouldShowDuration(*m_config, dur)) { + stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << std::endl; } if (m_headerPrinted) { m_headerPrinted = false; @@ -16563,6 +16802,7 @@ CATCH_REGISTER_REPORTER("console", ConsoleReporter) #include #include #include +#include namespace Catch { @@ -16590,7 +16830,7 @@ namespace Catch { #else std::strftime(timeStamp, timeStampSize, fmt, timeInfo); #endif - return std::string(timeStamp); + return std::string(timeStamp, timeStampSize-1); } std::string fileNameTag(const std::vector &tags) { @@ -16601,6 +16841,17 @@ namespace Catch { return it->substr(1); return std::string(); } + + // Formats the duration in seconds to 3 decimal places. + // This is done because some genius defined Maven Surefire schema + // in a way that only accepts 3 decimal places, and tools like + // Jenkins use that schema for validation JUnit reporter output. + std::string formatDuration( double seconds ) { + ReusableStringStream rss; + rss << std::fixed << std::setprecision( 3 ) << seconds; + return rss.str(); + } + } // anonymous namespace JunitReporter::JunitReporter( ReporterConfig const& _config ) @@ -16670,7 +16921,7 @@ namespace Catch { if( m_config->showDurations() == ShowDurations::Never ) xml.writeAttribute( "time", "" ); else - xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "time", formatDuration( suiteTime ) ); xml.writeAttribute( "timestamp", getCurrentTimestamp() ); // Write properties if there are any @@ -16715,12 +16966,13 @@ namespace Catch { if ( !m_config->name().empty() ) className = m_config->name() + "." + className; - writeSection( className, "", rootSection ); + writeSection( className, "", rootSection, stats.testInfo.okToFail() ); } - void JunitReporter::writeSection( std::string const& className, - std::string const& rootName, - SectionNode const& sectionNode ) { + void JunitReporter::writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode, + bool testOkToFail) { std::string name = trim( sectionNode.stats.sectionInfo.name ); if( !rootName.empty() ) name = rootName + '/' + name; @@ -16737,7 +16989,17 @@ namespace Catch { xml.writeAttribute( "classname", className ); xml.writeAttribute( "name", name ); } - xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) ); + xml.writeAttribute( "time", formatDuration( sectionNode.stats.durationInSeconds ) ); + // This is not ideal, but it should be enough to mimic gtest's + // junit output. + // Ideally the JUnit reporter would also handle `skipTest` + // events and write those out appropriately. + xml.writeAttribute( "status", "run" ); + + if (sectionNode.stats.assertions.failedButOk) { + xml.scopedElement("skipped") + .writeAttribute("message", "TEST_CASE tagged with !mayfail"); + } writeAssertions( sectionNode ); @@ -16748,9 +17010,9 @@ namespace Catch { } for( auto const& childNode : sectionNode.childSections ) if( className.empty() ) - writeSection( name, "", *childNode ); + writeSection( name, "", *childNode, testOkToFail ); else - writeSection( className, name, *childNode ); + writeSection( className, name, *childNode, testOkToFail ); } void JunitReporter::writeAssertions( SectionNode const& sectionNode ) { @@ -17172,6 +17434,10 @@ namespace Catch { .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.scopedElement( "OverallResultsCases") + .writeAttribute( "successes", testGroupStats.totals.testCases.passed ) + .writeAttribute( "failures", testGroupStats.totals.testCases.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.testCases.failedButOk ); m_xml.endElement(); } @@ -17181,6 +17447,10 @@ namespace Catch { .writeAttribute( "successes", testRunStats.totals.assertions.passed ) .writeAttribute( "failures", testRunStats.totals.assertions.failed ) .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.scopedElement( "OverallResultsCases") + .writeAttribute( "successes", testRunStats.totals.testCases.passed ) + .writeAttribute( "failures", testRunStats.totals.testCases.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.testCases.failedButOk ); m_xml.endElement(); } @@ -17254,12 +17524,20 @@ namespace Catch { #ifndef __OBJC__ +#ifndef CATCH_INTERNAL_CDECL +#ifdef _MSC_VER +#define CATCH_INTERNAL_CDECL __cdecl +#else +#define CATCH_INTERNAL_CDECL +#endif +#endif + #if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) // Standard C/C++ Win32 Unicode wmain entry point -extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { +extern "C" int CATCH_INTERNAL_CDECL wmain (int argc, wchar_t * argv[], wchar_t * []) { #else // Standard C/C++ main entry point -int main (int argc, char * argv[]) { +int CATCH_INTERNAL_CDECL main (int argc, char * argv[]) { #endif return Catch::Session().run( argc, argv ); @@ -17387,9 +17665,9 @@ int main (int argc, char * const argv[]) { #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #define CATCH_BENCHMARK(...) \ - INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) + INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) #define CATCH_BENCHMARK_ADVANCED(name) \ - INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) + INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name) #endif // CATCH_CONFIG_ENABLE_BENCHMARKING // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required @@ -17491,9 +17769,9 @@ int main (int argc, char * const argv[]) { #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #define BENCHMARK(...) \ - INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) + INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) #define BENCHMARK_ADVANCED(name) \ - INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) + INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name) #endif // CATCH_CONFIG_ENABLE_BENCHMARKING using Catch::Detail::Approx; @@ -17540,8 +17818,8 @@ using Catch::Detail::Approx; #define CATCH_WARN( msg ) (void)(0) #define CATCH_CAPTURE( msg ) (void)(0) -#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) +#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) #define CATCH_METHOD_AS_TEST_CASE( method, ... ) #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) #define CATCH_SECTION( ... ) @@ -17550,7 +17828,7 @@ using Catch::Detail::Approx; #define CATCH_FAIL_CHECK( ... ) (void)(0) #define CATCH_SUCCEED( ... ) (void)(0) -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) @@ -17573,8 +17851,8 @@ using Catch::Detail::Approx; #endif // "BDD-style" convenience wrappers -#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) +#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), className ) #define CATCH_GIVEN( desc ) #define CATCH_AND_GIVEN( desc ) #define CATCH_WHEN( desc ) @@ -17622,10 +17900,10 @@ using Catch::Detail::Approx; #define INFO( msg ) (void)(0) #define UNSCOPED_INFO( msg ) (void)(0) #define WARN( msg ) (void)(0) -#define CAPTURE( msg ) (void)(0) +#define CAPTURE( ... ) (void)(0) -#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) +#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) #define METHOD_AS_TEST_CASE( method, ... ) #define REGISTER_TEST_CASE( Function, ... ) (void)(0) #define SECTION( ... ) @@ -17633,7 +17911,7 @@ using Catch::Detail::Approx; #define FAIL( ... ) (void)(0) #define FAIL_CHECK( ... ) (void)(0) #define SUCCEED( ... ) (void)(0) -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) @@ -17663,8 +17941,8 @@ using Catch::Detail::Approx; #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) // "BDD-style" convenience wrappers -#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) -#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) +#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ) ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), className ) #define GIVEN( desc ) #define AND_GIVEN( desc ) From 3b72f69a6a476794955a604675893d9e0fc1f19d Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 21 Oct 2022 08:53:46 +0200 Subject: [PATCH 366/780] Use Property::appendAttributeReal Property::setAttributeReal instead of macros --- src/property/types/CloudBool.h | 4 ++-- src/property/types/CloudColor.h | 12 +++++----- src/property/types/CloudFloat.h | 4 ++-- src/property/types/CloudInt.h | 4 ++-- src/property/types/CloudLocation.h | 8 +++---- src/property/types/CloudSchedule.h | 16 ++++++------- src/property/types/CloudString.h | 4 ++-- src/property/types/CloudUnsignedInt.h | 4 ++-- src/property/types/CloudWrapperBool.h | 4 ++-- src/property/types/CloudWrapperFloat.h | 4 ++-- src/property/types/CloudWrapperInt.h | 4 ++-- src/property/types/CloudWrapperString.h | 4 ++-- src/property/types/CloudWrapperUnsignedInt.h | 4 ++-- .../types/automation/CloudColoredLight.h | 16 ++++++------- .../types/automation/CloudDimmedLight.h | 8 +++---- .../types/automation/CloudTelevision.h | 24 +++++++++---------- 16 files changed, 62 insertions(+), 62 deletions(-) diff --git a/src/property/types/CloudBool.h b/src/property/types/CloudBool.h index e0b9f1f30..495729d14 100644 --- a/src/property/types/CloudBool.h +++ b/src/property/types/CloudBool.h @@ -53,10 +53,10 @@ class CloudBool : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - return appendAttribute(_value); + return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value); + setAttributeReal(_cloud_value, ""); } //modifiers CloudBool& operator=(bool v) { diff --git a/src/property/types/CloudColor.h b/src/property/types/CloudColor.h index 294a2bb8d..0e2acaa0d 100644 --- a/src/property/types/CloudColor.h +++ b/src/property/types/CloudColor.h @@ -189,15 +189,15 @@ class CloudColor : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - CHECK_CBOR_MULTI(appendAttribute(_value.hue)); - CHECK_CBOR_MULTI(appendAttribute(_value.sat)); - CHECK_CBOR_MULTI(appendAttribute(_value.bri)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.hue, "hue", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.sat, "sat", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.bri, "bri", encoder)); return CborNoError; } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value.hue); - setAttribute(_cloud_value.sat); - setAttribute(_cloud_value.bri); + setAttributeReal(_cloud_value.hue, "hue"); + setAttributeReal(_cloud_value.sat, "sat"); + setAttributeReal(_cloud_value.bri, "bri"); } }; diff --git a/src/property/types/CloudFloat.h b/src/property/types/CloudFloat.h index b68fe70fe..69e601d6a 100644 --- a/src/property/types/CloudFloat.h +++ b/src/property/types/CloudFloat.h @@ -55,10 +55,10 @@ class CloudFloat : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - return appendAttribute(_value); + return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value); + setAttributeReal(_cloud_value, ""); } //modifiers CloudFloat& operator=(float v) { diff --git a/src/property/types/CloudInt.h b/src/property/types/CloudInt.h index 0ce65777a..1d3a15039 100644 --- a/src/property/types/CloudInt.h +++ b/src/property/types/CloudInt.h @@ -53,10 +53,10 @@ class CloudInt : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - return appendAttribute(_value); + return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value); + setAttributeReal(_cloud_value, ""); } //modifiers CloudInt& operator=(int v) { diff --git a/src/property/types/CloudLocation.h b/src/property/types/CloudLocation.h index 25636cd97..16607be6b 100644 --- a/src/property/types/CloudLocation.h +++ b/src/property/types/CloudLocation.h @@ -90,13 +90,13 @@ class CloudLocation : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - CHECK_CBOR_MULTI(appendAttribute(_value.lat)); - CHECK_CBOR_MULTI(appendAttribute(_value.lon)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.lat, "lat", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.lon, "lon", encoder)); return CborNoError; } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value.lat); - setAttribute(_cloud_value.lon); + setAttributeReal(_cloud_value.lat, "lat"); + setAttributeReal(_cloud_value.lon, "lon"); } }; diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index 47827c59c..f7018a94d 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -418,17 +418,17 @@ class CloudSchedule : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - CHECK_CBOR_MULTI(appendAttribute(_value.frm)); - CHECK_CBOR_MULTI(appendAttribute(_value.to)); - CHECK_CBOR_MULTI(appendAttribute(_value.len)); - CHECK_CBOR_MULTI(appendAttribute(_value.msk)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.frm, "frm", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.to, "to", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.len, "len", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.msk, "msk", encoder)); return CborNoError; } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value.frm); - setAttribute(_cloud_value.to); - setAttribute(_cloud_value.len); - setAttribute(_cloud_value.msk); + setAttributeReal(_cloud_value.frm, "frm"); + setAttributeReal(_cloud_value.to, "to"); + setAttributeReal(_cloud_value.len, "len"); + setAttributeReal(_cloud_value.msk, "msk"); } }; diff --git a/src/property/types/CloudString.h b/src/property/types/CloudString.h index f07f59ccf..18d3c6d76 100644 --- a/src/property/types/CloudString.h +++ b/src/property/types/CloudString.h @@ -59,10 +59,10 @@ class CloudString : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - return appendAttribute(_value); + return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value); + setAttributeReal(_cloud_value, ""); } //modifiers CloudString& operator=(String v) { diff --git a/src/property/types/CloudUnsignedInt.h b/src/property/types/CloudUnsignedInt.h index 37ec2d1cb..3aa08418c 100644 --- a/src/property/types/CloudUnsignedInt.h +++ b/src/property/types/CloudUnsignedInt.h @@ -53,10 +53,10 @@ class CloudUnsignedInt : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - return appendAttribute(_value); + return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value); + setAttributeReal(_cloud_value, ""); } //modifiers CloudUnsignedInt& operator=(unsigned int v) { diff --git a/src/property/types/CloudWrapperBool.h b/src/property/types/CloudWrapperBool.h index 701e7c87d..5990ac8e8 100644 --- a/src/property/types/CloudWrapperBool.h +++ b/src/property/types/CloudWrapperBool.h @@ -46,10 +46,10 @@ class CloudWrapperBool : public CloudWrapperBase { _cloud_value = _primitive_value; } virtual CborError appendAttributesToCloud() { - return appendAttribute(_primitive_value); + return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value); + setAttributeReal(_cloud_value, ""); } virtual bool isPrimitive() { return true; diff --git a/src/property/types/CloudWrapperFloat.h b/src/property/types/CloudWrapperFloat.h index db0f640cf..d477c4ed5 100644 --- a/src/property/types/CloudWrapperFloat.h +++ b/src/property/types/CloudWrapperFloat.h @@ -48,10 +48,10 @@ class CloudWrapperFloat : public CloudWrapperBase { _cloud_value = _primitive_value; } virtual CborError appendAttributesToCloud() { - return appendAttribute(_primitive_value); + return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value); + setAttributeReal(_cloud_value, ""); } virtual bool isPrimitive() { return true; diff --git a/src/property/types/CloudWrapperInt.h b/src/property/types/CloudWrapperInt.h index 261c72d46..a1984767d 100644 --- a/src/property/types/CloudWrapperInt.h +++ b/src/property/types/CloudWrapperInt.h @@ -46,10 +46,10 @@ class CloudWrapperInt : public CloudWrapperBase { _cloud_value = _primitive_value; } virtual CborError appendAttributesToCloud() { - return appendAttribute(_primitive_value); + return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value); + setAttributeReal(_cloud_value, ""); } virtual bool isPrimitive() { return true; diff --git a/src/property/types/CloudWrapperString.h b/src/property/types/CloudWrapperString.h index 3e1c0a3e3..eefd3ed0f 100644 --- a/src/property/types/CloudWrapperString.h +++ b/src/property/types/CloudWrapperString.h @@ -50,10 +50,10 @@ class CloudWrapperString : public CloudWrapperBase { _cloud_value = _primitive_value; } virtual CborError appendAttributesToCloud() { - return appendAttribute(_primitive_value); + return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value); + setAttributeReal(_cloud_value, ""); } virtual bool isPrimitive() { return true; diff --git a/src/property/types/CloudWrapperUnsignedInt.h b/src/property/types/CloudWrapperUnsignedInt.h index d722f585f..d14f0d18c 100644 --- a/src/property/types/CloudWrapperUnsignedInt.h +++ b/src/property/types/CloudWrapperUnsignedInt.h @@ -46,10 +46,10 @@ class CloudWrapperUnsignedInt : public CloudWrapperBase { _cloud_value = _primitive_value; } virtual CborError appendAttributesToCloud() { - return appendAttribute(_primitive_value); + return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value); + setAttributeReal(_cloud_value, ""); } virtual bool isPrimitive() { return true; diff --git a/src/property/types/automation/CloudColoredLight.h b/src/property/types/automation/CloudColoredLight.h index f38b8354a..9a61f13f3 100644 --- a/src/property/types/automation/CloudColoredLight.h +++ b/src/property/types/automation/CloudColoredLight.h @@ -119,17 +119,17 @@ class CloudColoredLight : public CloudColor { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - CHECK_CBOR_MULTI(appendAttribute(_value.swi)); - CHECK_CBOR_MULTI(appendAttribute(_value.hue)); - CHECK_CBOR_MULTI(appendAttribute(_value.sat)); - CHECK_CBOR_MULTI(appendAttribute(_value.bri)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.swi, "swi", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.hue, "hue", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.sat, "sat", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.bri, "bri", encoder)); return CborNoError; } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value.swi); - setAttribute(_cloud_value.hue); - setAttribute(_cloud_value.sat); - setAttribute(_cloud_value.bri); + setAttributeReal(_cloud_value.swi, "swi"); + setAttributeReal(_cloud_value.hue, "hue"); + setAttributeReal(_cloud_value.sat, "sat"); + setAttributeReal(_cloud_value.bri, "bri"); } }; diff --git a/src/property/types/automation/CloudDimmedLight.h b/src/property/types/automation/CloudDimmedLight.h index e14da0f75..650646f4e 100644 --- a/src/property/types/automation/CloudDimmedLight.h +++ b/src/property/types/automation/CloudDimmedLight.h @@ -99,14 +99,14 @@ class CloudDimmedLight : public Property { } virtual CborError appendAttributesToCloud() { - CHECK_CBOR_MULTI(appendAttribute(_value.swi)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.swi, "swi", encoder)); // To allow visualization through color widget // Start float hue = 0; float sat = 0; CHECK_CBOR_MULTI(appendAttributeReal(hue, getAttributeName(".hue", '.'), encoder)); CHECK_CBOR_MULTI(appendAttributeReal(sat, getAttributeName(".sat", '.'), encoder)); - CHECK_CBOR_MULTI(appendAttribute(_value.bri)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.bri, "bri", encoder)); // should be only: // appendAttribute(_value.bri); // end @@ -114,8 +114,8 @@ class CloudDimmedLight : public Property { } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value.swi); - setAttribute(_cloud_value.bri); + setAttributeReal(_cloud_value.swi, "swi"); + setAttributeReal(_cloud_value.bri, "bri"); } }; diff --git a/src/property/types/automation/CloudTelevision.h b/src/property/types/automation/CloudTelevision.h index 921f1ea56..914a4b07c 100644 --- a/src/property/types/automation/CloudTelevision.h +++ b/src/property/types/automation/CloudTelevision.h @@ -214,21 +214,21 @@ class CloudTelevision : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud() { - CHECK_CBOR_MULTI(appendAttribute(_value.swi)); - CHECK_CBOR_MULTI(appendAttribute(_value.vol)); - CHECK_CBOR_MULTI(appendAttribute(_value.mut)); - CHECK_CBOR_MULTI(appendAttribute((int)_value.pbc)); - CHECK_CBOR_MULTI(appendAttribute((int)_value.inp)); - CHECK_CBOR_MULTI(appendAttribute(_value.cha)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.swi, "swi", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.vol, "vol", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.mut, "mut", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal((int)_value.pbc, "pbc", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal((int)_value.inp, "inp", encoder)); + CHECK_CBOR_MULTI(appendAttributeReal(_value.cha, "cha", encoder)); return CborNoError; } virtual void setAttributesFromCloud() { - setAttribute(_cloud_value.swi); - setAttribute(_cloud_value.vol); - setAttribute(_cloud_value.mut); - setAttribute((int&)_cloud_value.pbc); - setAttribute((int&)_cloud_value.inp); - setAttribute(_cloud_value.cha); + setAttributeReal(_cloud_value.swi, "swi"); + setAttributeReal(_cloud_value.vol, "vol"); + setAttributeReal(_cloud_value.mut, "mut"); + setAttributeReal((int&)_cloud_value.pbc, "pbc"); + setAttributeReal((int&)_cloud_value.inp, "inp"); + setAttributeReal(_cloud_value.cha, "cha"); } }; From 753245a5bd25df7439e4ea9e935a40a70609c210 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 21 Oct 2022 08:56:04 +0200 Subject: [PATCH 367/780] Remove setAttribute and appendAttribute --- src/property/Property.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/property/Property.h b/src/property/Property.h index 6571bf625..6d14ec0e6 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -48,8 +48,6 @@ ******************************************************************************/ #define appendAttributesToCloud() appendAttributesToCloudReal(CborEncoder *encoder) -#define appendAttribute(x) appendAttributeReal(x, getAttributeName(#x, '.'), encoder) -#define setAttribute(x) setAttributeReal(x, getAttributeName(#x, '.')) /****************************************************************************** CONST From 5dd3ee280cc7238ab0c96cc3d5bb4d50874835c7 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 21 Oct 2022 09:13:06 +0200 Subject: [PATCH 368/780] Use Property::appendAttributesToCloudReal(...) instead of appendAttributesToCloud() macro --- src/property/types/CloudBool.h | 2 +- src/property/types/CloudColor.h | 2 +- src/property/types/CloudFloat.h | 2 +- src/property/types/CloudInt.h | 2 +- src/property/types/CloudLocation.h | 2 +- src/property/types/CloudSchedule.h | 2 +- src/property/types/CloudString.h | 2 +- src/property/types/CloudUnsignedInt.h | 2 +- src/property/types/CloudWrapperBool.h | 2 +- src/property/types/CloudWrapperFloat.h | 2 +- src/property/types/CloudWrapperInt.h | 2 +- src/property/types/CloudWrapperString.h | 2 +- src/property/types/CloudWrapperUnsignedInt.h | 2 +- src/property/types/automation/CloudColoredLight.h | 2 +- src/property/types/automation/CloudDimmedLight.h | 2 +- src/property/types/automation/CloudTelevision.h | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/property/types/CloudBool.h b/src/property/types/CloudBool.h index 495729d14..6c50b80a0 100644 --- a/src/property/types/CloudBool.h +++ b/src/property/types/CloudBool.h @@ -52,7 +52,7 @@ class CloudBool : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudColor.h b/src/property/types/CloudColor.h index 0e2acaa0d..a7ee0311d 100644 --- a/src/property/types/CloudColor.h +++ b/src/property/types/CloudColor.h @@ -188,7 +188,7 @@ class CloudColor : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttributeReal(_value.hue, "hue", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.sat, "sat", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.bri, "bri", encoder)); diff --git a/src/property/types/CloudFloat.h b/src/property/types/CloudFloat.h index 69e601d6a..86bb0ead8 100644 --- a/src/property/types/CloudFloat.h +++ b/src/property/types/CloudFloat.h @@ -54,7 +54,7 @@ class CloudFloat : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudInt.h b/src/property/types/CloudInt.h index 1d3a15039..722dd2ab9 100644 --- a/src/property/types/CloudInt.h +++ b/src/property/types/CloudInt.h @@ -52,7 +52,7 @@ class CloudInt : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudLocation.h b/src/property/types/CloudLocation.h index 16607be6b..f660da682 100644 --- a/src/property/types/CloudLocation.h +++ b/src/property/types/CloudLocation.h @@ -89,7 +89,7 @@ class CloudLocation : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttributeReal(_value.lat, "lat", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.lon, "lon", encoder)); return CborNoError; diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index f7018a94d..e74d3a179 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -417,7 +417,7 @@ class CloudSchedule : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttributeReal(_value.frm, "frm", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.to, "to", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.len, "len", encoder)); diff --git a/src/property/types/CloudString.h b/src/property/types/CloudString.h index 18d3c6d76..46c64642d 100644 --- a/src/property/types/CloudString.h +++ b/src/property/types/CloudString.h @@ -58,7 +58,7 @@ class CloudString : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudUnsignedInt.h b/src/property/types/CloudUnsignedInt.h index 3aa08418c..0245d0a58 100644 --- a/src/property/types/CloudUnsignedInt.h +++ b/src/property/types/CloudUnsignedInt.h @@ -52,7 +52,7 @@ class CloudUnsignedInt : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudWrapperBool.h b/src/property/types/CloudWrapperBool.h index 5990ac8e8..0ad79fe1e 100644 --- a/src/property/types/CloudWrapperBool.h +++ b/src/property/types/CloudWrapperBool.h @@ -45,7 +45,7 @@ class CloudWrapperBool : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudWrapperFloat.h b/src/property/types/CloudWrapperFloat.h index d477c4ed5..5496c4de0 100644 --- a/src/property/types/CloudWrapperFloat.h +++ b/src/property/types/CloudWrapperFloat.h @@ -47,7 +47,7 @@ class CloudWrapperFloat : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudWrapperInt.h b/src/property/types/CloudWrapperInt.h index a1984767d..f2ddaa219 100644 --- a/src/property/types/CloudWrapperInt.h +++ b/src/property/types/CloudWrapperInt.h @@ -45,7 +45,7 @@ class CloudWrapperInt : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudWrapperString.h b/src/property/types/CloudWrapperString.h index eefd3ed0f..f52b59859 100644 --- a/src/property/types/CloudWrapperString.h +++ b/src/property/types/CloudWrapperString.h @@ -49,7 +49,7 @@ class CloudWrapperString : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudWrapperUnsignedInt.h b/src/property/types/CloudWrapperUnsignedInt.h index d14f0d18c..3834d3eb3 100644 --- a/src/property/types/CloudWrapperUnsignedInt.h +++ b/src/property/types/CloudWrapperUnsignedInt.h @@ -45,7 +45,7 @@ class CloudWrapperUnsignedInt : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/automation/CloudColoredLight.h b/src/property/types/automation/CloudColoredLight.h index 9a61f13f3..44ac2bdd1 100644 --- a/src/property/types/automation/CloudColoredLight.h +++ b/src/property/types/automation/CloudColoredLight.h @@ -118,7 +118,7 @@ class CloudColoredLight : public CloudColor { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttributeReal(_value.swi, "swi", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.hue, "hue", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.sat, "sat", encoder)); diff --git a/src/property/types/automation/CloudDimmedLight.h b/src/property/types/automation/CloudDimmedLight.h index 650646f4e..cfb11f12a 100644 --- a/src/property/types/automation/CloudDimmedLight.h +++ b/src/property/types/automation/CloudDimmedLight.h @@ -98,7 +98,7 @@ class CloudDimmedLight : public Property { _cloud_value = _value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttributeReal(_value.swi, "swi", encoder)); // To allow visualization through color widget // Start diff --git a/src/property/types/automation/CloudTelevision.h b/src/property/types/automation/CloudTelevision.h index 914a4b07c..c71d127b8 100644 --- a/src/property/types/automation/CloudTelevision.h +++ b/src/property/types/automation/CloudTelevision.h @@ -213,7 +213,7 @@ class CloudTelevision : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloud() { + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttributeReal(_value.swi, "swi", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.vol, "vol", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.mut, "mut", encoder)); From 6b44c92fa8f71df6fd65021799dbdb3cfdfb1bc9 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 21 Oct 2022 09:15:19 +0200 Subject: [PATCH 369/780] Remove appendAttributesToCloud() macro --- src/property/Property.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/property/Property.h b/src/property/Property.h index 6d14ec0e6..16ce5a764 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -43,12 +43,6 @@ #include "../cbor/lib/tinycbor/cbor-lib.h" -/****************************************************************************** - DEFINE - ******************************************************************************/ - -#define appendAttributesToCloud() appendAttributesToCloudReal(CborEncoder *encoder) - /****************************************************************************** CONST ******************************************************************************/ From b5f3a19b5b3d76f51c96de474c1900dd75996df4 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 21 Oct 2022 09:18:36 +0200 Subject: [PATCH 370/780] Remove Property::getAttributeName(...) --- src/property/Property.cpp | 7 ------- src/property/Property.h | 1 - src/property/types/automation/CloudDimmedLight.h | 4 ++-- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index c6c3db9e4..6c65ab869 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -354,13 +354,6 @@ void Property::setAttributeReal(String attributeName, std::function Date: Fri, 21 Oct 2022 09:20:53 +0200 Subject: [PATCH 371/780] Rename appendAttributesToCloudReal to appendAttributesToCloud --- src/property/Property.cpp | 2 +- src/property/Property.h | 2 +- src/property/types/CloudBool.h | 2 +- src/property/types/CloudColor.h | 2 +- src/property/types/CloudFloat.h | 2 +- src/property/types/CloudInt.h | 2 +- src/property/types/CloudLocation.h | 2 +- src/property/types/CloudSchedule.h | 2 +- src/property/types/CloudString.h | 2 +- src/property/types/CloudUnsignedInt.h | 2 +- src/property/types/CloudWrapperBool.h | 2 +- src/property/types/CloudWrapperFloat.h | 2 +- src/property/types/CloudWrapperInt.h | 2 +- src/property/types/CloudWrapperString.h | 2 +- src/property/types/CloudWrapperUnsignedInt.h | 2 +- src/property/types/automation/CloudColoredLight.h | 2 +- src/property/types/automation/CloudDimmedLight.h | 2 +- src/property/types/automation/CloudTelevision.h | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index 6c65ab869..98472b372 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -170,7 +170,7 @@ void Property::execCallbackOnSync() { CborError Property::append(CborEncoder *encoder, bool lightPayload) { _lightPayload = lightPayload; _attributeIdentifier = 0; - CHECK_CBOR(appendAttributesToCloudReal(encoder)); + CHECK_CBOR(appendAttributesToCloud(encoder)); fromLocalToCloud(); _has_been_updated_once = true; _has_been_modified_in_callback = false; diff --git a/src/property/Property.h b/src/property/Property.h index 685d9d840..950b5bb55 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -208,7 +208,7 @@ class Property virtual bool isDifferentFromCloud() = 0; virtual void fromCloudToLocal() = 0; virtual void fromLocalToCloud() = 0; - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) = 0; + virtual CborError appendAttributesToCloud(CborEncoder *encoder) = 0; virtual void setAttributesFromCloud() = 0; virtual bool isPrimitive() { return false; diff --git a/src/property/types/CloudBool.h b/src/property/types/CloudBool.h index 6c50b80a0..654683b8f 100644 --- a/src/property/types/CloudBool.h +++ b/src/property/types/CloudBool.h @@ -52,7 +52,7 @@ class CloudBool : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudColor.h b/src/property/types/CloudColor.h index a7ee0311d..d09022453 100644 --- a/src/property/types/CloudColor.h +++ b/src/property/types/CloudColor.h @@ -188,7 +188,7 @@ class CloudColor : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttributeReal(_value.hue, "hue", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.sat, "sat", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.bri, "bri", encoder)); diff --git a/src/property/types/CloudFloat.h b/src/property/types/CloudFloat.h index 86bb0ead8..01e006b63 100644 --- a/src/property/types/CloudFloat.h +++ b/src/property/types/CloudFloat.h @@ -54,7 +54,7 @@ class CloudFloat : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudInt.h b/src/property/types/CloudInt.h index 722dd2ab9..7f1cd8006 100644 --- a/src/property/types/CloudInt.h +++ b/src/property/types/CloudInt.h @@ -52,7 +52,7 @@ class CloudInt : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudLocation.h b/src/property/types/CloudLocation.h index f660da682..50caa9275 100644 --- a/src/property/types/CloudLocation.h +++ b/src/property/types/CloudLocation.h @@ -89,7 +89,7 @@ class CloudLocation : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttributeReal(_value.lat, "lat", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.lon, "lon", encoder)); return CborNoError; diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index e74d3a179..95e26b584 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -417,7 +417,7 @@ class CloudSchedule : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttributeReal(_value.frm, "frm", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.to, "to", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.len, "len", encoder)); diff --git a/src/property/types/CloudString.h b/src/property/types/CloudString.h index 46c64642d..70cefb3d2 100644 --- a/src/property/types/CloudString.h +++ b/src/property/types/CloudString.h @@ -58,7 +58,7 @@ class CloudString : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudUnsignedInt.h b/src/property/types/CloudUnsignedInt.h index 0245d0a58..b7c20078a 100644 --- a/src/property/types/CloudUnsignedInt.h +++ b/src/property/types/CloudUnsignedInt.h @@ -52,7 +52,7 @@ class CloudUnsignedInt : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { return appendAttributeReal(_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudWrapperBool.h b/src/property/types/CloudWrapperBool.h index 0ad79fe1e..f60f374e8 100644 --- a/src/property/types/CloudWrapperBool.h +++ b/src/property/types/CloudWrapperBool.h @@ -45,7 +45,7 @@ class CloudWrapperBool : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudWrapperFloat.h b/src/property/types/CloudWrapperFloat.h index 5496c4de0..a888fdb1e 100644 --- a/src/property/types/CloudWrapperFloat.h +++ b/src/property/types/CloudWrapperFloat.h @@ -47,7 +47,7 @@ class CloudWrapperFloat : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudWrapperInt.h b/src/property/types/CloudWrapperInt.h index f2ddaa219..e151cfa16 100644 --- a/src/property/types/CloudWrapperInt.h +++ b/src/property/types/CloudWrapperInt.h @@ -45,7 +45,7 @@ class CloudWrapperInt : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudWrapperString.h b/src/property/types/CloudWrapperString.h index f52b59859..b7b125236 100644 --- a/src/property/types/CloudWrapperString.h +++ b/src/property/types/CloudWrapperString.h @@ -49,7 +49,7 @@ class CloudWrapperString : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudWrapperUnsignedInt.h b/src/property/types/CloudWrapperUnsignedInt.h index 3834d3eb3..50d7f6b1f 100644 --- a/src/property/types/CloudWrapperUnsignedInt.h +++ b/src/property/types/CloudWrapperUnsignedInt.h @@ -45,7 +45,7 @@ class CloudWrapperUnsignedInt : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { return appendAttributeReal(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { diff --git a/src/property/types/automation/CloudColoredLight.h b/src/property/types/automation/CloudColoredLight.h index 44ac2bdd1..8f24f1e94 100644 --- a/src/property/types/automation/CloudColoredLight.h +++ b/src/property/types/automation/CloudColoredLight.h @@ -118,7 +118,7 @@ class CloudColoredLight : public CloudColor { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttributeReal(_value.swi, "swi", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.hue, "hue", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.sat, "sat", encoder)); diff --git a/src/property/types/automation/CloudDimmedLight.h b/src/property/types/automation/CloudDimmedLight.h index b0f88793e..6cfec0596 100644 --- a/src/property/types/automation/CloudDimmedLight.h +++ b/src/property/types/automation/CloudDimmedLight.h @@ -98,7 +98,7 @@ class CloudDimmedLight : public Property { _cloud_value = _value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttributeReal(_value.swi, "swi", encoder)); // To allow visualization through color widget // Start diff --git a/src/property/types/automation/CloudTelevision.h b/src/property/types/automation/CloudTelevision.h index c71d127b8..c1eec054d 100644 --- a/src/property/types/automation/CloudTelevision.h +++ b/src/property/types/automation/CloudTelevision.h @@ -213,7 +213,7 @@ class CloudTelevision : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) { + virtual CborError appendAttributesToCloud(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttributeReal(_value.swi, "swi", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.vol, "vol", encoder)); CHECK_CBOR_MULTI(appendAttributeReal(_value.mut, "mut", encoder)); From de7e25c939b4f1a3bb2608e570116e95c9ec3ee5 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 21 Oct 2022 09:22:39 +0200 Subject: [PATCH 372/780] Rename appendAttributeReal to appendAttribute --- src/property/Property.cpp | 10 +++++----- src/property/Property.h | 10 +++++----- src/property/types/CloudBool.h | 2 +- src/property/types/CloudColor.h | 6 +++--- src/property/types/CloudFloat.h | 2 +- src/property/types/CloudInt.h | 2 +- src/property/types/CloudLocation.h | 4 ++-- src/property/types/CloudSchedule.h | 8 ++++---- src/property/types/CloudString.h | 2 +- src/property/types/CloudUnsignedInt.h | 2 +- src/property/types/CloudWrapperBool.h | 2 +- src/property/types/CloudWrapperFloat.h | 2 +- src/property/types/CloudWrapperInt.h | 2 +- src/property/types/CloudWrapperString.h | 2 +- src/property/types/CloudWrapperUnsignedInt.h | 2 +- src/property/types/automation/CloudColoredLight.h | 8 ++++---- src/property/types/automation/CloudDimmedLight.h | 8 ++++---- src/property/types/automation/CloudTelevision.h | 12 ++++++------ 18 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index 98472b372..f395ea2b3 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -181,7 +181,7 @@ CborError Property::append(CborEncoder *encoder, bool lightPayload) { return CborNoError; } -CborError Property::appendAttributeReal(bool value, String attributeName, CborEncoder *encoder) { +CborError Property::appendAttribute(bool value, String attributeName, CborEncoder *encoder) { return appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) { CHECK_CBOR(cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::BooleanValue))); @@ -190,7 +190,7 @@ CborError Property::appendAttributeReal(bool value, String attributeName, CborEn }, encoder); } -CborError Property::appendAttributeReal(int value, String attributeName, CborEncoder *encoder) { +CborError Property::appendAttribute(int value, String attributeName, CborEncoder *encoder) { return appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) { CHECK_CBOR(cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Value))); @@ -199,7 +199,7 @@ CborError Property::appendAttributeReal(int value, String attributeName, CborEnc }, encoder); } -CborError Property::appendAttributeReal(unsigned int value, String attributeName, CborEncoder *encoder) { +CborError Property::appendAttribute(unsigned int value, String attributeName, CborEncoder *encoder) { return appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) { CHECK_CBOR(cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Value))); @@ -208,7 +208,7 @@ CborError Property::appendAttributeReal(unsigned int value, String attributeName }, encoder); } -CborError Property::appendAttributeReal(float value, String attributeName, CborEncoder *encoder) { +CborError Property::appendAttribute(float value, String attributeName, CborEncoder *encoder) { return appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) { CHECK_CBOR(cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Value))); @@ -217,7 +217,7 @@ CborError Property::appendAttributeReal(float value, String attributeName, CborE }, encoder); } -CborError Property::appendAttributeReal(String value, String attributeName, CborEncoder *encoder) { +CborError Property::appendAttribute(String value, String attributeName, CborEncoder *encoder) { return appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) { CHECK_CBOR(cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::StringValue))); diff --git a/src/property/Property.h b/src/property/Property.h index 950b5bb55..180bb04e7 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -186,11 +186,11 @@ class Property void updateLocalTimestamp(); CborError append(CborEncoder * encoder, bool lightPayload); - CborError appendAttributeReal(bool value, String attributeName = "", CborEncoder *encoder = nullptr); - CborError appendAttributeReal(int value, String attributeName = "", CborEncoder *encoder = nullptr); - CborError appendAttributeReal(unsigned int value, String attributeName = "", CborEncoder *encoder = nullptr); - CborError appendAttributeReal(float value, String attributeName = "", CborEncoder *encoder = nullptr); - CborError appendAttributeReal(String value, String attributeName = "", CborEncoder *encoder = nullptr); + CborError appendAttribute(bool value, String attributeName = "", CborEncoder *encoder = nullptr); + CborError appendAttribute(int value, String attributeName = "", CborEncoder *encoder = nullptr); + CborError appendAttribute(unsigned int value, String attributeName = "", CborEncoder *encoder = nullptr); + CborError appendAttribute(float value, String attributeName = "", CborEncoder *encoder = nullptr); + CborError appendAttribute(String value, String attributeName = "", CborEncoder *encoder = nullptr); #ifndef __AVR__ CborError appendAttributeName(String attributeName, std::functionf, CborEncoder *encoder); void setAttributeReal(String attributeName, std::functionsetValue); diff --git a/src/property/types/CloudBool.h b/src/property/types/CloudBool.h index 654683b8f..1cb4bea6e 100644 --- a/src/property/types/CloudBool.h +++ b/src/property/types/CloudBool.h @@ -53,7 +53,7 @@ class CloudBool : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - return appendAttributeReal(_value, "", encoder); + return appendAttribute(_value, "", encoder); } virtual void setAttributesFromCloud() { setAttributeReal(_cloud_value, ""); diff --git a/src/property/types/CloudColor.h b/src/property/types/CloudColor.h index d09022453..27d581c40 100644 --- a/src/property/types/CloudColor.h +++ b/src/property/types/CloudColor.h @@ -189,9 +189,9 @@ class CloudColor : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - CHECK_CBOR_MULTI(appendAttributeReal(_value.hue, "hue", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.sat, "sat", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.bri, "bri", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.hue, "hue", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.sat, "sat", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.bri, "bri", encoder)); return CborNoError; } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudFloat.h b/src/property/types/CloudFloat.h index 01e006b63..02032d3cb 100644 --- a/src/property/types/CloudFloat.h +++ b/src/property/types/CloudFloat.h @@ -55,7 +55,7 @@ class CloudFloat : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - return appendAttributeReal(_value, "", encoder); + return appendAttribute(_value, "", encoder); } virtual void setAttributesFromCloud() { setAttributeReal(_cloud_value, ""); diff --git a/src/property/types/CloudInt.h b/src/property/types/CloudInt.h index 7f1cd8006..81dbf6c24 100644 --- a/src/property/types/CloudInt.h +++ b/src/property/types/CloudInt.h @@ -53,7 +53,7 @@ class CloudInt : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - return appendAttributeReal(_value, "", encoder); + return appendAttribute(_value, "", encoder); } virtual void setAttributesFromCloud() { setAttributeReal(_cloud_value, ""); diff --git a/src/property/types/CloudLocation.h b/src/property/types/CloudLocation.h index 50caa9275..e5fae7e67 100644 --- a/src/property/types/CloudLocation.h +++ b/src/property/types/CloudLocation.h @@ -90,8 +90,8 @@ class CloudLocation : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - CHECK_CBOR_MULTI(appendAttributeReal(_value.lat, "lat", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.lon, "lon", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.lat, "lat", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.lon, "lon", encoder)); return CborNoError; } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index 95e26b584..d5b9261ca 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -418,10 +418,10 @@ class CloudSchedule : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - CHECK_CBOR_MULTI(appendAttributeReal(_value.frm, "frm", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.to, "to", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.len, "len", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.msk, "msk", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.frm, "frm", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.to, "to", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.len, "len", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.msk, "msk", encoder)); return CborNoError; } virtual void setAttributesFromCloud() { diff --git a/src/property/types/CloudString.h b/src/property/types/CloudString.h index 70cefb3d2..2fae996e5 100644 --- a/src/property/types/CloudString.h +++ b/src/property/types/CloudString.h @@ -59,7 +59,7 @@ class CloudString : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - return appendAttributeReal(_value, "", encoder); + return appendAttribute(_value, "", encoder); } virtual void setAttributesFromCloud() { setAttributeReal(_cloud_value, ""); diff --git a/src/property/types/CloudUnsignedInt.h b/src/property/types/CloudUnsignedInt.h index b7c20078a..9dfc0970f 100644 --- a/src/property/types/CloudUnsignedInt.h +++ b/src/property/types/CloudUnsignedInt.h @@ -53,7 +53,7 @@ class CloudUnsignedInt : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - return appendAttributeReal(_value, "", encoder); + return appendAttribute(_value, "", encoder); } virtual void setAttributesFromCloud() { setAttributeReal(_cloud_value, ""); diff --git a/src/property/types/CloudWrapperBool.h b/src/property/types/CloudWrapperBool.h index f60f374e8..72a37a121 100644 --- a/src/property/types/CloudWrapperBool.h +++ b/src/property/types/CloudWrapperBool.h @@ -46,7 +46,7 @@ class CloudWrapperBool : public CloudWrapperBase { _cloud_value = _primitive_value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - return appendAttributeReal(_primitive_value, "", encoder); + return appendAttribute(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { setAttributeReal(_cloud_value, ""); diff --git a/src/property/types/CloudWrapperFloat.h b/src/property/types/CloudWrapperFloat.h index a888fdb1e..5d0276747 100644 --- a/src/property/types/CloudWrapperFloat.h +++ b/src/property/types/CloudWrapperFloat.h @@ -48,7 +48,7 @@ class CloudWrapperFloat : public CloudWrapperBase { _cloud_value = _primitive_value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - return appendAttributeReal(_primitive_value, "", encoder); + return appendAttribute(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { setAttributeReal(_cloud_value, ""); diff --git a/src/property/types/CloudWrapperInt.h b/src/property/types/CloudWrapperInt.h index e151cfa16..997a4c842 100644 --- a/src/property/types/CloudWrapperInt.h +++ b/src/property/types/CloudWrapperInt.h @@ -46,7 +46,7 @@ class CloudWrapperInt : public CloudWrapperBase { _cloud_value = _primitive_value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - return appendAttributeReal(_primitive_value, "", encoder); + return appendAttribute(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { setAttributeReal(_cloud_value, ""); diff --git a/src/property/types/CloudWrapperString.h b/src/property/types/CloudWrapperString.h index b7b125236..59b7d3926 100644 --- a/src/property/types/CloudWrapperString.h +++ b/src/property/types/CloudWrapperString.h @@ -50,7 +50,7 @@ class CloudWrapperString : public CloudWrapperBase { _cloud_value = _primitive_value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - return appendAttributeReal(_primitive_value, "", encoder); + return appendAttribute(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { setAttributeReal(_cloud_value, ""); diff --git a/src/property/types/CloudWrapperUnsignedInt.h b/src/property/types/CloudWrapperUnsignedInt.h index 50d7f6b1f..62a0cdf20 100644 --- a/src/property/types/CloudWrapperUnsignedInt.h +++ b/src/property/types/CloudWrapperUnsignedInt.h @@ -46,7 +46,7 @@ class CloudWrapperUnsignedInt : public CloudWrapperBase { _cloud_value = _primitive_value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - return appendAttributeReal(_primitive_value, "", encoder); + return appendAttribute(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { setAttributeReal(_cloud_value, ""); diff --git a/src/property/types/automation/CloudColoredLight.h b/src/property/types/automation/CloudColoredLight.h index 8f24f1e94..03c237ae7 100644 --- a/src/property/types/automation/CloudColoredLight.h +++ b/src/property/types/automation/CloudColoredLight.h @@ -119,10 +119,10 @@ class CloudColoredLight : public CloudColor { _cloud_value = _value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - CHECK_CBOR_MULTI(appendAttributeReal(_value.swi, "swi", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.hue, "hue", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.sat, "sat", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.bri, "bri", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.swi, "swi", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.hue, "hue", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.sat, "sat", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.bri, "bri", encoder)); return CborNoError; } virtual void setAttributesFromCloud() { diff --git a/src/property/types/automation/CloudDimmedLight.h b/src/property/types/automation/CloudDimmedLight.h index 6cfec0596..e8d863ab0 100644 --- a/src/property/types/automation/CloudDimmedLight.h +++ b/src/property/types/automation/CloudDimmedLight.h @@ -99,14 +99,14 @@ class CloudDimmedLight : public Property { } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - CHECK_CBOR_MULTI(appendAttributeReal(_value.swi, "swi", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.swi, "swi", encoder)); // To allow visualization through color widget // Start float hue = 0; float sat = 0; - CHECK_CBOR_MULTI(appendAttributeReal(hue, "hue", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(sat, "sat", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.bri, "bri", encoder)); + CHECK_CBOR_MULTI(appendAttribute(hue, "hue", encoder)); + CHECK_CBOR_MULTI(appendAttribute(sat, "sat", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.bri, "bri", encoder)); // should be only: // appendAttribute(_value.bri); // end diff --git a/src/property/types/automation/CloudTelevision.h b/src/property/types/automation/CloudTelevision.h index c1eec054d..720e00730 100644 --- a/src/property/types/automation/CloudTelevision.h +++ b/src/property/types/automation/CloudTelevision.h @@ -214,12 +214,12 @@ class CloudTelevision : public Property { _cloud_value = _value; } virtual CborError appendAttributesToCloud(CborEncoder *encoder) { - CHECK_CBOR_MULTI(appendAttributeReal(_value.swi, "swi", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.vol, "vol", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.mut, "mut", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal((int)_value.pbc, "pbc", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal((int)_value.inp, "inp", encoder)); - CHECK_CBOR_MULTI(appendAttributeReal(_value.cha, "cha", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.swi, "swi", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.vol, "vol", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.mut, "mut", encoder)); + CHECK_CBOR_MULTI(appendAttribute((int)_value.pbc, "pbc", encoder)); + CHECK_CBOR_MULTI(appendAttribute((int)_value.inp, "inp", encoder)); + CHECK_CBOR_MULTI(appendAttribute(_value.cha, "cha", encoder)); return CborNoError; } virtual void setAttributesFromCloud() { From 7d5221c051c572a58e4aa532af9a852cd5d42a39 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 21 Oct 2022 09:23:53 +0200 Subject: [PATCH 373/780] Rename setAttributeReal to setAttribute --- src/property/Property.cpp | 24 +++++++++---------- src/property/Property.h | 14 +++++------ src/property/types/CloudBool.h | 2 +- src/property/types/CloudColor.h | 6 ++--- src/property/types/CloudFloat.h | 2 +- src/property/types/CloudInt.h | 2 +- src/property/types/CloudLocation.h | 4 ++-- src/property/types/CloudSchedule.h | 8 +++---- src/property/types/CloudString.h | 2 +- src/property/types/CloudUnsignedInt.h | 2 +- src/property/types/CloudWrapperBool.h | 2 +- src/property/types/CloudWrapperFloat.h | 2 +- src/property/types/CloudWrapperInt.h | 2 +- src/property/types/CloudWrapperString.h | 2 +- src/property/types/CloudWrapperUnsignedInt.h | 2 +- .../types/automation/CloudColoredLight.h | 8 +++---- .../types/automation/CloudDimmedLight.h | 4 ++-- .../types/automation/CloudTelevision.h | 12 +++++----- 18 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index f395ea2b3..326e25584 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -278,8 +278,8 @@ void Property::setAttributesFromCloud(std::list * map_data_list) { setAttributesFromCloud(); } -void Property::setAttributeReal(bool& value, String attributeName) { - setAttributeReal(attributeName, [&value](CborMapData & md) { +void Property::setAttribute(bool& value, String attributeName) { + setAttribute(attributeName, [&value](CborMapData & md) { // Manage the case to have boolean values received as integers 0/1 if (md.bool_val.isSet()) { value = md.bool_val.get(); @@ -295,34 +295,34 @@ void Property::setAttributeReal(bool& value, String attributeName) { }); } -void Property::setAttributeReal(int& value, String attributeName) { - setAttributeReal(attributeName, [&value](CborMapData & md) { +void Property::setAttribute(int& value, String attributeName) { + setAttribute(attributeName, [&value](CborMapData & md) { value = md.val.get(); }); } -void Property::setAttributeReal(unsigned int& value, String attributeName) { - setAttributeReal(attributeName, [&value](CborMapData & md) { +void Property::setAttribute(unsigned int& value, String attributeName) { + setAttribute(attributeName, [&value](CborMapData & md) { value = md.val.get(); }); } -void Property::setAttributeReal(float& value, String attributeName) { - setAttributeReal(attributeName, [&value](CborMapData & md) { +void Property::setAttribute(float& value, String attributeName) { + setAttribute(attributeName, [&value](CborMapData & md) { value = md.val.get(); }); } -void Property::setAttributeReal(String& value, String attributeName) { - setAttributeReal(attributeName, [&value](CborMapData & md) { +void Property::setAttribute(String& value, String attributeName) { + setAttribute(attributeName, [&value](CborMapData & md) { value = md.str_val.get(); }); } #ifdef __AVR__ -void Property::setAttributeReal(String attributeName, nonstd::functionsetValue) +void Property::setAttribute(String attributeName, nonstd::functionsetValue) #else -void Property::setAttributeReal(String attributeName, std::functionsetValue) +void Property::setAttribute(String attributeName, std::functionsetValue) #endif { if (attributeName != "") { diff --git a/src/property/Property.h b/src/property/Property.h index 180bb04e7..b0e6ada06 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -193,17 +193,17 @@ class Property CborError appendAttribute(String value, String attributeName = "", CborEncoder *encoder = nullptr); #ifndef __AVR__ CborError appendAttributeName(String attributeName, std::functionf, CborEncoder *encoder); - void setAttributeReal(String attributeName, std::functionsetValue); + void setAttribute(String attributeName, std::functionsetValue); #else CborError appendAttributeName(String attributeName, nonstd::functionf, CborEncoder *encoder); - void setAttributeReal(String attributeName, nonstd::functionsetValue); + void setAttribute(String attributeName, nonstd::functionsetValue); #endif void setAttributesFromCloud(std::list * map_data_list); - void setAttributeReal(bool& value, String attributeName = ""); - void setAttributeReal(int& value, String attributeName = ""); - void setAttributeReal(unsigned int& value, String attributeName = ""); - void setAttributeReal(float& value, String attributeName = ""); - void setAttributeReal(String& value, String attributeName = ""); + void setAttribute(bool& value, String attributeName = ""); + void setAttribute(int& value, String attributeName = ""); + void setAttribute(unsigned int& value, String attributeName = ""); + void setAttribute(float& value, String attributeName = ""); + void setAttribute(String& value, String attributeName = ""); virtual bool isDifferentFromCloud() = 0; virtual void fromCloudToLocal() = 0; diff --git a/src/property/types/CloudBool.h b/src/property/types/CloudBool.h index 1cb4bea6e..3434656fc 100644 --- a/src/property/types/CloudBool.h +++ b/src/property/types/CloudBool.h @@ -56,7 +56,7 @@ class CloudBool : public Property { return appendAttribute(_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value, ""); + setAttribute(_cloud_value, ""); } //modifiers CloudBool& operator=(bool v) { diff --git a/src/property/types/CloudColor.h b/src/property/types/CloudColor.h index 27d581c40..54cb4f30f 100644 --- a/src/property/types/CloudColor.h +++ b/src/property/types/CloudColor.h @@ -195,9 +195,9 @@ class CloudColor : public Property { return CborNoError; } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value.hue, "hue"); - setAttributeReal(_cloud_value.sat, "sat"); - setAttributeReal(_cloud_value.bri, "bri"); + setAttribute(_cloud_value.hue, "hue"); + setAttribute(_cloud_value.sat, "sat"); + setAttribute(_cloud_value.bri, "bri"); } }; diff --git a/src/property/types/CloudFloat.h b/src/property/types/CloudFloat.h index 02032d3cb..514df7866 100644 --- a/src/property/types/CloudFloat.h +++ b/src/property/types/CloudFloat.h @@ -58,7 +58,7 @@ class CloudFloat : public Property { return appendAttribute(_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value, ""); + setAttribute(_cloud_value, ""); } //modifiers CloudFloat& operator=(float v) { diff --git a/src/property/types/CloudInt.h b/src/property/types/CloudInt.h index 81dbf6c24..37e4d3cae 100644 --- a/src/property/types/CloudInt.h +++ b/src/property/types/CloudInt.h @@ -56,7 +56,7 @@ class CloudInt : public Property { return appendAttribute(_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value, ""); + setAttribute(_cloud_value, ""); } //modifiers CloudInt& operator=(int v) { diff --git a/src/property/types/CloudLocation.h b/src/property/types/CloudLocation.h index e5fae7e67..cd4f0dc67 100644 --- a/src/property/types/CloudLocation.h +++ b/src/property/types/CloudLocation.h @@ -95,8 +95,8 @@ class CloudLocation : public Property { return CborNoError; } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value.lat, "lat"); - setAttributeReal(_cloud_value.lon, "lon"); + setAttribute(_cloud_value.lat, "lat"); + setAttribute(_cloud_value.lon, "lon"); } }; diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index d5b9261ca..ecf6345ec 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -425,10 +425,10 @@ class CloudSchedule : public Property { return CborNoError; } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value.frm, "frm"); - setAttributeReal(_cloud_value.to, "to"); - setAttributeReal(_cloud_value.len, "len"); - setAttributeReal(_cloud_value.msk, "msk"); + setAttribute(_cloud_value.frm, "frm"); + setAttribute(_cloud_value.to, "to"); + setAttribute(_cloud_value.len, "len"); + setAttribute(_cloud_value.msk, "msk"); } }; diff --git a/src/property/types/CloudString.h b/src/property/types/CloudString.h index 2fae996e5..f884720c0 100644 --- a/src/property/types/CloudString.h +++ b/src/property/types/CloudString.h @@ -62,7 +62,7 @@ class CloudString : public Property { return appendAttribute(_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value, ""); + setAttribute(_cloud_value, ""); } //modifiers CloudString& operator=(String v) { diff --git a/src/property/types/CloudUnsignedInt.h b/src/property/types/CloudUnsignedInt.h index 9dfc0970f..40bed697a 100644 --- a/src/property/types/CloudUnsignedInt.h +++ b/src/property/types/CloudUnsignedInt.h @@ -56,7 +56,7 @@ class CloudUnsignedInt : public Property { return appendAttribute(_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value, ""); + setAttribute(_cloud_value, ""); } //modifiers CloudUnsignedInt& operator=(unsigned int v) { diff --git a/src/property/types/CloudWrapperBool.h b/src/property/types/CloudWrapperBool.h index 72a37a121..8fffd4209 100644 --- a/src/property/types/CloudWrapperBool.h +++ b/src/property/types/CloudWrapperBool.h @@ -49,7 +49,7 @@ class CloudWrapperBool : public CloudWrapperBase { return appendAttribute(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value, ""); + setAttribute(_cloud_value, ""); } virtual bool isPrimitive() { return true; diff --git a/src/property/types/CloudWrapperFloat.h b/src/property/types/CloudWrapperFloat.h index 5d0276747..7ce857c85 100644 --- a/src/property/types/CloudWrapperFloat.h +++ b/src/property/types/CloudWrapperFloat.h @@ -51,7 +51,7 @@ class CloudWrapperFloat : public CloudWrapperBase { return appendAttribute(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value, ""); + setAttribute(_cloud_value, ""); } virtual bool isPrimitive() { return true; diff --git a/src/property/types/CloudWrapperInt.h b/src/property/types/CloudWrapperInt.h index 997a4c842..73623abfc 100644 --- a/src/property/types/CloudWrapperInt.h +++ b/src/property/types/CloudWrapperInt.h @@ -49,7 +49,7 @@ class CloudWrapperInt : public CloudWrapperBase { return appendAttribute(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value, ""); + setAttribute(_cloud_value, ""); } virtual bool isPrimitive() { return true; diff --git a/src/property/types/CloudWrapperString.h b/src/property/types/CloudWrapperString.h index 59b7d3926..7c75db0db 100644 --- a/src/property/types/CloudWrapperString.h +++ b/src/property/types/CloudWrapperString.h @@ -53,7 +53,7 @@ class CloudWrapperString : public CloudWrapperBase { return appendAttribute(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value, ""); + setAttribute(_cloud_value, ""); } virtual bool isPrimitive() { return true; diff --git a/src/property/types/CloudWrapperUnsignedInt.h b/src/property/types/CloudWrapperUnsignedInt.h index 62a0cdf20..34ed01ef3 100644 --- a/src/property/types/CloudWrapperUnsignedInt.h +++ b/src/property/types/CloudWrapperUnsignedInt.h @@ -49,7 +49,7 @@ class CloudWrapperUnsignedInt : public CloudWrapperBase { return appendAttribute(_primitive_value, "", encoder); } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value, ""); + setAttribute(_cloud_value, ""); } virtual bool isPrimitive() { return true; diff --git a/src/property/types/automation/CloudColoredLight.h b/src/property/types/automation/CloudColoredLight.h index 03c237ae7..031590a39 100644 --- a/src/property/types/automation/CloudColoredLight.h +++ b/src/property/types/automation/CloudColoredLight.h @@ -126,10 +126,10 @@ class CloudColoredLight : public CloudColor { return CborNoError; } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value.swi, "swi"); - setAttributeReal(_cloud_value.hue, "hue"); - setAttributeReal(_cloud_value.sat, "sat"); - setAttributeReal(_cloud_value.bri, "bri"); + setAttribute(_cloud_value.swi, "swi"); + setAttribute(_cloud_value.hue, "hue"); + setAttribute(_cloud_value.sat, "sat"); + setAttribute(_cloud_value.bri, "bri"); } }; diff --git a/src/property/types/automation/CloudDimmedLight.h b/src/property/types/automation/CloudDimmedLight.h index e8d863ab0..8e0c0b39f 100644 --- a/src/property/types/automation/CloudDimmedLight.h +++ b/src/property/types/automation/CloudDimmedLight.h @@ -114,8 +114,8 @@ class CloudDimmedLight : public Property { } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value.swi, "swi"); - setAttributeReal(_cloud_value.bri, "bri"); + setAttribute(_cloud_value.swi, "swi"); + setAttribute(_cloud_value.bri, "bri"); } }; diff --git a/src/property/types/automation/CloudTelevision.h b/src/property/types/automation/CloudTelevision.h index 720e00730..75967dd4f 100644 --- a/src/property/types/automation/CloudTelevision.h +++ b/src/property/types/automation/CloudTelevision.h @@ -223,12 +223,12 @@ class CloudTelevision : public Property { return CborNoError; } virtual void setAttributesFromCloud() { - setAttributeReal(_cloud_value.swi, "swi"); - setAttributeReal(_cloud_value.vol, "vol"); - setAttributeReal(_cloud_value.mut, "mut"); - setAttributeReal((int&)_cloud_value.pbc, "pbc"); - setAttributeReal((int&)_cloud_value.inp, "inp"); - setAttributeReal(_cloud_value.cha, "cha"); + setAttribute(_cloud_value.swi, "swi"); + setAttribute(_cloud_value.vol, "vol"); + setAttribute(_cloud_value.mut, "mut"); + setAttribute((int&)_cloud_value.pbc, "pbc"); + setAttribute((int&)_cloud_value.inp, "inp"); + setAttribute(_cloud_value.cha, "cha"); } }; From adfc649aa3d3e2f5e9035db5947f9746ef887ee7 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 21 Oct 2022 12:43:52 +0200 Subject: [PATCH 374/780] CloudDimmedLight: Remove fake variables from cbor message - Is not possible to associate a color widget to a CloudDimmedLight variable --- src/property/types/automation/CloudDimmedLight.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/property/types/automation/CloudDimmedLight.h b/src/property/types/automation/CloudDimmedLight.h index 8e0c0b39f..5da30821b 100644 --- a/src/property/types/automation/CloudDimmedLight.h +++ b/src/property/types/automation/CloudDimmedLight.h @@ -100,16 +100,7 @@ class CloudDimmedLight : public Property { virtual CborError appendAttributesToCloud(CborEncoder *encoder) { CHECK_CBOR_MULTI(appendAttribute(_value.swi, "swi", encoder)); - // To allow visualization through color widget - // Start - float hue = 0; - float sat = 0; - CHECK_CBOR_MULTI(appendAttribute(hue, "hue", encoder)); - CHECK_CBOR_MULTI(appendAttribute(sat, "sat", encoder)); CHECK_CBOR_MULTI(appendAttribute(_value.bri, "bri", encoder)); - // should be only: - // appendAttribute(_value.bri); - // end return CborNoError; } From 078f62fe1fdf6cf0379c1d3335aefd3b24686883 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 24 Oct 2022 13:58:44 +0200 Subject: [PATCH 375/780] Fix encoding test for DimmedLight property --- extras/test/src/test_encode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/test/src/test_encode.cpp b/extras/test/src/test_encode.cpp index 4c702cffc..ecb3c54ee 100644 --- a/extras/test/src/test_encode.cpp +++ b/extras/test/src/test_encode.cpp @@ -196,8 +196,8 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode-1]" CloudDimmedLight color_test = CloudDimmedLight(true, 2.0); addPropertyToContainer(property_container, color_test, "test", Permission::ReadWrite); - /* [{0: "test:swi", 4: true},{0: "test:hue", 2: 0.0},{0: "test:sat", 2: 0.0},{0: "test:bri", 2: 2.0}] = 9F A2 00 68 74 65 73 74 3A 73 77 69 04 F5 A2 00 68 74 65 73 74 3A 68 75 65 02 FA 00 00 00 00 A2 00 68 74 65 73 74 3A 73 61 74 02 FA 00 00 00 00 A2 00 68 74 65 73 74 3A 62 72 69 02 FA 40 00 00 00 FF*/ - std::vector const expected = {0x9F, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x73, 0x77, 0x69, 0x04, 0xF5, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x68, 0x75, 0x65, 0x02, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x73, 0x61, 0x74, 0x02, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x62, 0x72, 0x69, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xFF }; + /* [{0: "test:swi", 4: true},{0: "test:bri", 2: 2.0}] = 9F A2 00 68 74 65 73 74 3A 73 77 69 04 F5 A2 00 68 74 65 73 74 3A 62 72 69 02 FA 40 00 00 00 FF*/ + std::vector const expected = {0x9F, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x73, 0x77, 0x69, 0x04, 0xF5, 0xA2, 0x00, 0x68, 0x74, 0x65, 0x73, 0x74, 0x3A, 0x62, 0x72, 0x69, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xFF }; std::vector const actual = cbor::encode(property_container); REQUIRE(actual == expected); } From f0720541301efec1ee3713c72741ef7f573e38d9 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 2 Aug 2022 09:34:46 +0200 Subject: [PATCH 376/780] Add support for opta board --- library.properties | 2 +- src/AIoTC_Config.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library.properties b/library.properties index 02d484f81..885e30881 100644 --- a/library.properties +++ b/library.properties @@ -6,6 +6,6 @@ sentence=This library allows connecting to the Arduino IoT Cloud service. paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKR GSM, MKR1000 and WiFi101. category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud -architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32 +architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta includes=ArduinoIoTCloud.h depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 56c90697b..bf4367714 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -102,7 +102,7 @@ #define OTA_STORAGE_SSU (0) #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_OPTA) #define OTA_STORAGE_PORTENTA_QSPI (1) #else #define OTA_STORAGE_PORTENTA_QSPI (0) @@ -116,7 +116,7 @@ #if defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKR1000) || \ defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_PORTENTA_H7_M7) || \ - defined (ARDUINO_NANO_RP2040_CONNECT) + defined (ARDUINO_NANO_RP2040_CONNECT) || defined(ARDUINO_OPTA) #define BOARD_HAS_ECCX08 #define HAS_TCP #endif @@ -141,7 +141,7 @@ #define HAS_TCP #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_OPTA) #define BOARD_STM32H7 #endif From f86fea35d44b9351f0ec550ccb8b075048318742 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 19 Dec 2022 11:40:47 +0100 Subject: [PATCH 377/780] Add opta compile example workflow --- .github/workflows/compile-examples.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 99e1f0bf8..7559fcd14 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -58,6 +58,8 @@ jobs: type: nina - fqbn: arduino:mbed_nicla:nicla_vision type: mbed_nicla + - fqbn: arduino:mbed_opta:opta + type: mbed_opta # make board type-specific customizations to the matrix jobs include: @@ -148,6 +150,16 @@ jobs: - name: Arduino_Portenta_OTA sketch-paths: | - examples/utility/Provisioning + # Opta + - board: + type: mbed_opta + platforms: | + # Install mbed_opta platform via Boards Manager + - name: arduino:mbed_opta + libraries: | + - name: Arduino_Portenta_OTA + sketch-paths: | + - examples/utility/Provisioning # ESP8266 boards - board: type: esp8266 From 5dc5b5d8b25cc69448535318bd3dd38e77741888 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 28 Dec 2022 06:54:04 +0100 Subject: [PATCH 378/780] CI build: add dependency for ArduinoECCX08 library. --- .github/workflows/compile-examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 7559fcd14..8660f5707 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -157,6 +157,7 @@ jobs: # Install mbed_opta platform via Boards Manager - name: arduino:mbed_opta libraries: | + - name: ArduinoECCX08 - name: Arduino_Portenta_OTA sketch-paths: | - examples/utility/Provisioning From 5776c7fae64d86c5e95cc0c416aaf132097df8ea Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 9 Jan 2023 14:55:49 +0100 Subject: [PATCH 379/780] Release v1.9.0 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 885e30881..47282d739 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.8.0 +version=1.9.0 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index bf4367714..36ece27bd 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -162,6 +162,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.8.0" +#define AIOT_CONFIG_LIB_VERSION "1.9.0" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From f69faa1ce6cb905ae8cfafca8da20a4e75222ba8 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 19 Jan 2023 10:59:06 +0100 Subject: [PATCH 380/780] bin2ota Add missing boards --- extras/tools/bin2ota.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/extras/tools/bin2ota.py b/extras/tools/bin2ota.py index ffb21a856..a99130ebe 100755 --- a/extras/tools/bin2ota.py +++ b/extras/tools/bin2ota.py @@ -5,7 +5,7 @@ if len(sys.argv) != 4: print ("Usage: bin2ota.py BOARD sketch.bin sketch.ota") - print (" BOARD = [MKR_WIFI_1010 | NANO_33_IOT]") + print (" BOARD = [MKR_WIFI_1010 | NANO_33_IOT | PORTENTA_H7_M7 | NANO_RP2040_CONNECT | NICLA_VISION | OPTA ]") sys.exit() board = sys.argv[1] @@ -26,6 +26,10 @@ magic_number = 0x2341025B.to_bytes(4,byteorder='little') elif board == "NANO_RP2040_CONNECT": magic_number = 0x2341005E.to_bytes(4,byteorder='little') +elif board == "NICLA_VISION" + magic_number = 0x2341025F.to_bytes(4,byteorder='little') +elif board == "OPTA": + magic_number = 0x23410064.to_bytes(4,byteorder='little') else: print ("Error,", board, "is not a supported board type") sys.exit() From 0545ef561394732dc05a21006e61666c8a315be4 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 16 Nov 2022 15:42:31 +0100 Subject: [PATCH 381/780] Add OTA support for ESP32 boards --- src/AIoTC_Config.h | 6 +++- src/ArduinoIoTCloudTCP.cpp | 29 +++++++++++++-- src/utility/ota/OTA-esp32.cpp | 67 +++++++++++++++++++++++++++++++++++ src/utility/ota/OTA.h | 4 +++ 4 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 src/utility/ota/OTA-esp32.cpp diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 36ece27bd..b1ba04082 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -108,7 +108,11 @@ #define OTA_STORAGE_PORTENTA_QSPI (0) #endif -#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU || OTA_STORAGE_PORTENTA_QSPI) && !defined(ARDUINO_AVR_UNO_WIFI_REV2) +#if defined(ARDUINO_ARCH_ESP32) + #define OTA_STORAGE_ESP (1) +#endif + +#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU || OTA_STORAGE_PORTENTA_QSPI || OTA_STORAGE_ESP) && !defined(ARDUINO_AVR_UNO_WIFI_REV2) #define OTA_ENABLED (1) #else #define OTA_ENABLED (0) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 3c11dea8f..511ecf2a9 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -44,14 +44,27 @@ # include #endif -#include "utility/ota/OTA.h" +#if defined (ARDUINO_ARCH_ESP32) && OTA_ENABLED +# include "tls/utility/SHA256.h" +#include "esp_spi_flash.h" +#include "esp_ota_ops.h" +#include "esp_image_format.h" +#endif + +#if defined (ARDUINO_NANO_RP2040_CONNECT) || \ + (defined (ARDUINO_ARCH_SAMD) && OTA_ENABLED) #include "utility/ota/FlashSHA256.h" +#endif + +#if OTA_ENABLED +#include "utility/ota/OTA.h" +#endif + #include #include "cbor/CBOREncoder.h" #include "utility/watchdog/Watchdog.h" - /****************************************************************************** * EXTERN ******************************************************************************/ @@ -201,6 +214,9 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, * 1024 bytes or 0x100'000 bytes). */ String const sha256_str = FlashSHA256::calc(XIP_BASE, 0x100000); +#elif defined(ARDUINO_ARCH_ESP32) +# warning "Compute image SHA256" +String const sha256_str; #else # error "No method for SHA256 checksum calculation over application image defined for this architecture." #endif @@ -300,6 +316,11 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _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; +#endif + #ifdef BOARD_HAS_OFFLOADED_ECCX08 if (String(WiFi.firmwareVersion()) < String("1.4.4")) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, NINA firmware needs to be >= 1.4.4, current %s", __FUNCTION__, WiFi.firmwareVersion()); @@ -840,6 +861,10 @@ void ArduinoIoTCloudTCP::onOTARequest() 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 } #endif diff --git a/src/utility/ota/OTA-esp32.cpp b/src/utility/ota/OTA-esp32.cpp new file mode 100644 index 000000000..53068a5c3 --- /dev/null +++ b/src/utility/ota/OTA-esp32.cpp @@ -0,0 +1,67 @@ +/* + 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 defined ARDUINO_ARCH_ESP32 && OTA_ENABLED +#include "OTA.h" +#include +#include + +/****************************************************************************** + * FUNCTION DEFINITION + ******************************************************************************/ + +int esp32_onOTARequest(char const * ota_url) +{ + Arduino_ESP32_OTA::Error ota_err = Arduino_ESP32_OTA::Error::None; + Arduino_ESP32_OTA ota; + + /* Initialize the board for OTA handling. */ + if ((ota_err = ota.begin()) != Arduino_ESP32_OTA::Error::None) + { + DEBUG_ERROR("Arduino_ESP32_OTA::begin() failed with %d", static_cast(ota_err)); + return static_cast(ota_err); + } + + /* Download the OTA file from the web storage location. */ + int const ota_download = ota.download(ota_url); + if (ota_download <= 0) + { + DEBUG_ERROR("Arduino_ESP_OTA::download() failed with %d", ota_download); + return ota_download; + } + DEBUG_VERBOSE("Arduino_ESP_OTA::download() %d bytes downloaded", static_cast(ota_download)); + + /* Verify update integrity and apply */ + if ((ota_err = ota.update()) != Arduino_ESP32_OTA::Error::None) + { + DEBUG_ERROR("Arduino_ESP_OTA::update() failed with %d", static_cast(ota_err)); + return static_cast(ota_err); + } + + /* Perform the reset to reboot */ + ota.reset(); + + return static_cast(OTAError::None); +} + +#endif /* ARDUINO_ARCH_ESP32 */ diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index c1d3f79a0..dbf4ae4cc 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -66,4 +66,8 @@ int rp2040_connect_onOTARequest(char const * ota_url); int portenta_h7_onOTARequest(char const * ota_url, const bool use_ethernet); #endif +#ifdef ARDUINO_ARCH_ESP32 +int esp32_onOTARequest(char const * ota_url); +#endif + #endif /* ARDUINO_OTA_LOGIC_H_ */ From 7a3dfb3f9147e3cbd6feb5d1475e4761885bee17 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 28 Nov 2022 18:16:04 +0100 Subject: [PATCH 382/780] Compute sketch SHA256 --- src/ArduinoIoTCloudTCP.cpp | 40 +++++++++++++++++++++++++++++++++++-- src/tls/bearssl/dec32be.c | 2 +- src/tls/bearssl/enc32be.c | 2 +- src/tls/bearssl/sha2small.c | 2 +- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 511ecf2a9..261de542c 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -215,8 +215,44 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, */ String const sha256_str = FlashSHA256::calc(XIP_BASE, 0x100000); #elif defined(ARDUINO_ARCH_ESP32) -# warning "Compute image SHA256" -String const sha256_str; + SHA256 sha256; + + uint32_t lengthLeft = ESP.getSketchSize(); + + const esp_partition_t *running = esp_ota_get_running_partition(); + if (!running) { + DEBUG_ERROR("Partition could not be found"); + } + const size_t bufSize = SPI_FLASH_SEC_SIZE; + std::unique_ptr buf(new uint8_t[bufSize]); + uint32_t offset = 0; + if(!buf.get()) { + DEBUG_ERROR("Not enough memory to allocate buffer"); + } + + sha256.begin(); + while( lengthLeft > 0) { + size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize; + if (!ESP.flashRead(running->address + offset, reinterpret_cast(buf.get()), (readBytes + 3) & ~3)) { + DEBUG_ERROR("Could not read buffer from flash"); + } + sha256.update(buf.get(), readBytes); + lengthLeft -= readBytes; + offset += readBytes; + } + /* Retrieve the final hash string. */ + uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; + sha256.finalize(sha256_hash); + String sha256_str; + std::for_each(sha256_hash, + sha256_hash + SHA256::HASH_SIZE, + [&sha256_str](uint8_t const elem) + { + char buf[4]; + snprintf(buf, 4, "%02X", elem); + sha256_str += buf; + }); + DEBUG_VERBOSE("SHA256: %d bytes (of %d) read", ESP.getSketchSize() - lengthLeft, ESP.getSketchSize()); #else # error "No method for SHA256 checksum calculation over application image defined for this architecture." #endif diff --git a/src/tls/bearssl/dec32be.c b/src/tls/bearssl/dec32be.c index 064f9bf98..0b8b05a5e 100644 --- a/src/tls/bearssl/dec32be.c +++ b/src/tls/bearssl/dec32be.c @@ -23,7 +23,7 @@ */ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) || defined(ARDUINO_ARCH_ESP32) #include "inner.h" diff --git a/src/tls/bearssl/enc32be.c b/src/tls/bearssl/enc32be.c index b6be4e13f..a00d96123 100644 --- a/src/tls/bearssl/enc32be.c +++ b/src/tls/bearssl/enc32be.c @@ -23,7 +23,7 @@ */ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) || defined(ARDUINO_ARCH_ESP32) #include "inner.h" diff --git a/src/tls/bearssl/sha2small.c b/src/tls/bearssl/sha2small.c index 789623de0..02283f05c 100644 --- a/src/tls/bearssl/sha2small.c +++ b/src/tls/bearssl/sha2small.c @@ -23,7 +23,7 @@ */ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) || defined(ARDUINO_ARCH_ESP32) #include "inner.h" From 30e0f5cd127fa1adf62dde549e39eb9e65b59a35 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 13 Dec 2022 15:53:03 +0100 Subject: [PATCH 383/780] Add ESP32 support to bin2ota.py --- extras/tools/bin2ota.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extras/tools/bin2ota.py b/extras/tools/bin2ota.py index a99130ebe..7ec4c6846 100755 --- a/extras/tools/bin2ota.py +++ b/extras/tools/bin2ota.py @@ -30,6 +30,9 @@ magic_number = 0x2341025F.to_bytes(4,byteorder='little') elif board == "OPTA": magic_number = 0x23410064.to_bytes(4,byteorder='little') +# Magic number for all ESP32 boards not related to (VID/PID) +elif board == "ESP32": + magic_number = 0x45535033.to_bytes(4,byteorder='little') else: print ("Error,", board, "is not a supported board type") sys.exit() From 1ab8b3f23a3993038254e571e785ffe26f6f2195 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 18 Jan 2023 10:50:06 +0100 Subject: [PATCH 384/780] Move SHA256 code into OTA files --- src/ArduinoIoTCloudTCP.cpp | 145 ++++------------------------ src/ArduinoIoTCloudTCP.h | 1 + src/utility/ota/OTA-esp32.cpp | 49 +++++++++- src/utility/ota/OTA-nano-rp2040.cpp | 9 ++ src/utility/ota/OTA-portenta-h7.cpp | 47 +++++++++ src/utility/ota/OTA-samd.cpp | 24 ++++- src/utility/ota/OTA.h | 5 + 7 files changed, 151 insertions(+), 129 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 261de542c..62d2d7025 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -23,6 +23,7 @@ #ifdef HAS_TCP #include + #ifdef BOARD_HAS_ECCX08 #include "tls/BearSSLTrustAnchors.h" #include "tls/utility/CryptoUtil.h" @@ -34,45 +35,18 @@ #endif #ifdef BOARD_HAS_OFFLOADED_ECCX08 -#include -#include "tls/utility/CryptoUtil.h" -#endif - -#ifdef BOARD_STM32H7 -# include "tls/utility/SHA256.h" -# include -# include -#endif - -#if defined (ARDUINO_ARCH_ESP32) && OTA_ENABLED -# include "tls/utility/SHA256.h" -#include "esp_spi_flash.h" -#include "esp_ota_ops.h" -#include "esp_image_format.h" -#endif - -#if defined (ARDUINO_NANO_RP2040_CONNECT) || \ - (defined (ARDUINO_ARCH_SAMD) && OTA_ENABLED) -#include "utility/ota/FlashSHA256.h" + #include + #include "tls/utility/CryptoUtil.h" #endif #if OTA_ENABLED -#include "utility/ota/OTA.h" + #include "utility/ota/OTA.h" #endif #include #include "cbor/CBOREncoder.h" - #include "utility/watchdog/Watchdog.h" -/****************************************************************************** - * EXTERN - ******************************************************************************/ - -#ifdef BOARD_STM32H7 -extern RTC_HandleTypeDef RTCHandle; -#endif - /****************************************************************************** LOCAL MODULE FUNCTIONS ******************************************************************************/ @@ -164,100 +138,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #endif /* AVR */ #if OTA_ENABLED && !defined(__AVR__) -#if defined(BOARD_STM32H7) - /* The length of the application can be retrieved the same way it was - * communicated to the bootloader, that is by writing to the non-volatile - * storage registers of the RTC. - */ - SHA256 sha256; - uint32_t const app_start = 0x8040000; - uint32_t const app_size = HAL_RTCEx_BKUPRead(&RTCHandle, RTC_BKP_DR3); - - sha256.begin(); - uint32_t b = 0; - uint32_t bytes_read = 0; for(uint32_t a = app_start; - bytes_read < app_size; - bytes_read += sizeof(b), a += sizeof(b)) - { - /* Read the next chunk of memory. */ - memcpy(&b, reinterpret_cast(a), sizeof(b)); - /* Feed it to SHA256. */ - sha256.update(reinterpret_cast(&b), sizeof(b)); - } - /* Retrieve the final hash string. */ - uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; - sha256.finalize(sha256_hash); - String sha256_str; - std::for_each(sha256_hash, - sha256_hash + SHA256::HASH_SIZE, - [&sha256_str](uint8_t const elem) - { - char buf[4]; - snprintf(buf, 4, "%02X", elem); - sha256_str += buf; - }); - DEBUG_VERBOSE("SHA256: %d bytes (of %d) read", bytes_read, app_size); -#elif defined(ARDUINO_ARCH_SAMD) - /* Calculate the SHA256 checksum over the firmware stored in the flash of the - * MCU. Note: As we don't know the length per-se we read chunks of the flash - * until we detect one containing only 0xFF (= flash erased). This only works - * for firmware updated via OTA and second stage bootloaders (SxU family) - * because only those erase the complete flash before performing an update. - * Since the SHA256 firmware image is only required for the cloud servers to - * perform a version check after the OTA update this is a acceptable trade off. - * The bootloader is excluded from the calculation and occupies flash address - * range 0 to 0x2000, total flash size of 0x40000 bytes (256 kByte). - */ - String const sha256_str = FlashSHA256::calc(0x2000, 0x40000 - 0x2000); -#elif defined(ARDUINO_NANO_RP2040_CONNECT) - /* The maximum size of a RP2040 OTA update image is 1 MByte (that is 1024 * - * 1024 bytes or 0x100'000 bytes). - */ - String const sha256_str = FlashSHA256::calc(XIP_BASE, 0x100000); -#elif defined(ARDUINO_ARCH_ESP32) - SHA256 sha256; - - uint32_t lengthLeft = ESP.getSketchSize(); - - const esp_partition_t *running = esp_ota_get_running_partition(); - if (!running) { - DEBUG_ERROR("Partition could not be found"); - } - const size_t bufSize = SPI_FLASH_SEC_SIZE; - std::unique_ptr buf(new uint8_t[bufSize]); - uint32_t offset = 0; - if(!buf.get()) { - DEBUG_ERROR("Not enough memory to allocate buffer"); - } - - sha256.begin(); - while( lengthLeft > 0) { - size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize; - if (!ESP.flashRead(running->address + offset, reinterpret_cast(buf.get()), (readBytes + 3) & ~3)) { - DEBUG_ERROR("Could not read buffer from flash"); - } - sha256.update(buf.get(), readBytes); - lengthLeft -= readBytes; - offset += readBytes; - } - /* Retrieve the final hash string. */ - uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; - sha256.finalize(sha256_hash); - String sha256_str; - std::for_each(sha256_hash, - sha256_hash + SHA256::HASH_SIZE, - [&sha256_str](uint8_t const elem) - { - char buf[4]; - snprintf(buf, 4, "%02X", elem); - sha256_str += buf; - }); - DEBUG_VERBOSE("SHA256: %d bytes (of %d) read", ESP.getSketchSize() - lengthLeft, ESP.getSketchSize()); -#else -# error "No method for SHA256 checksum calculation over application image defined for this architecture." -#endif - DEBUG_VERBOSE("SHA256: HASH(%d) = %s", strlen(sha256_str.c_str()), sha256_str.c_str()); - _ota_img_sha256 = sha256_str; + _ota_img_sha256 = getOTAImageSHA256(); + DEBUG_VERBOSE("SHA256: HASH(%d) = %s", strlen(_ota_img_sha256.c_str()), _ota_img_sha256.c_str()); #endif /* OTA_ENABLED */ #if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) @@ -902,6 +784,21 @@ void ArduinoIoTCloudTCP::onOTARequest() _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() diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 28c6315be..3b7d431da 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -202,6 +202,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #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 53068a5c3..29cf3621b 100644 --- a/src/utility/ota/OTA-esp32.cpp +++ b/src/utility/ota/OTA-esp32.cpp @@ -22,9 +22,13 @@ #include #if defined ARDUINO_ARCH_ESP32 && OTA_ENABLED + #include "OTA.h" #include -#include +#include +#include "tls/utility/SHA256.h" + +#include /****************************************************************************** * FUNCTION DEFINITION @@ -64,4 +68,47 @@ int esp32_onOTARequest(char const * ota_url) return static_cast(OTAError::None); } +String esp32_getOTAImageSHA256() +{ + SHA256 sha256; + + uint32_t lengthLeft = ESP.getSketchSize(); + + const esp_partition_t *running = esp_ota_get_running_partition(); + if (!running) { + DEBUG_ERROR("Partition could not be found"); + } + const size_t bufSize = SPI_FLASH_SEC_SIZE; + std::unique_ptr buf(new uint8_t[bufSize]); + uint32_t offset = 0; + if(!buf.get()) { + DEBUG_ERROR("Not enough memory to allocate buffer"); + } + + sha256.begin(); + while( lengthLeft > 0) { + size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize; + if (!ESP.flashRead(running->address + offset, reinterpret_cast(buf.get()), (readBytes + 3) & ~3)) { + DEBUG_ERROR("Could not read buffer from flash"); + } + sha256.update(buf.get(), readBytes); + lengthLeft -= readBytes; + offset += readBytes; + } + /* Retrieve the final hash string. */ + uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; + sha256.finalize(sha256_hash); + String sha256_str; + std::for_each(sha256_hash, + sha256_hash + SHA256::HASH_SIZE, + [&sha256_str](uint8_t const elem) + { + char buf[4]; + snprintf(buf, 4, "%02X", elem); + sha256_str += buf; + }); + DEBUG_VERBOSE("SHA256: %d bytes (of %d) read", ESP.getSketchSize() - lengthLeft, ESP.getSketchSize()); + return sha256_str; +} + #endif /* ARDUINO_ARCH_ESP32 */ diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTA-nano-rp2040.cpp index 48071be7c..acdf6e8ec 100644 --- a/src/utility/ota/OTA-nano-rp2040.cpp +++ b/src/utility/ota/OTA-nano-rp2040.cpp @@ -32,6 +32,7 @@ #include "mbed.h" #include "FATFileSystem.h" #include "FlashIAPBlockDevice.h" +#include "utility/ota/FlashSHA256.h" /****************************************************************************** * FUNCTION DEFINITION @@ -249,4 +250,12 @@ int rp2040_connect_onOTARequest(char const * ota_url) return static_cast(OTAError::None); } +String rp2040_connect_getOTAImageSHA256() +{ + /* The maximum size of a RP2040 OTA update image is 1 MByte (that is 1024 * + * 1024 bytes or 0x100'000 bytes). + */ + return FlashSHA256::calc(XIP_BASE, 0x100000); +} + #endif /* ARDUINO_NANO_RP2040_CONNECT */ diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index 784f71969..12481a7ed 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -29,8 +29,18 @@ #include #include +#include + +#include "tls/utility/SHA256.h" + #include "../watchdog/Watchdog.h" +/****************************************************************************** + * EXTERN + ******************************************************************************/ + +extern RTC_HandleTypeDef RTCHandle; + /****************************************************************************** * FUNCTION DEFINITION ******************************************************************************/ @@ -96,4 +106,41 @@ int portenta_h7_onOTARequest(char const * ota_url, const bool use_ethernet) NVIC_SystemReset(); } +String portenta_h7_getOTAImageSHA256() +{ + /* The length of the application can be retrieved the same way it was + * communicated to the bootloader, that is by writing to the non-volatile + * storage registers of the RTC. + */ + SHA256 sha256; + uint32_t const app_start = 0x8040000; + uint32_t const app_size = HAL_RTCEx_BKUPRead(&RTCHandle, RTC_BKP_DR3); + + sha256.begin(); + uint32_t b = 0; + uint32_t bytes_read = 0; for(uint32_t a = app_start; + bytes_read < app_size; + bytes_read += sizeof(b), a += sizeof(b)) + { + /* Read the next chunk of memory. */ + memcpy(&b, reinterpret_cast(a), sizeof(b)); + /* Feed it to SHA256. */ + sha256.update(reinterpret_cast(&b), sizeof(b)); + } + /* Retrieve the final hash string. */ + uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; + sha256.finalize(sha256_hash); + String sha256_str; + std::for_each(sha256_hash, + sha256_hash + SHA256::HASH_SIZE, + [&sha256_str](uint8_t const elem) + { + char buf[4]; + snprintf(buf, 4, "%02X", elem); + sha256_str += buf; + }); + DEBUG_VERBOSE("SHA256: %d bytes (of %d) read", bytes_read, app_size); + return sha256_str; +} + #endif /* BOARD_STM32H7 */ diff --git a/src/utility/ota/OTA-samd.cpp b/src/utility/ota/OTA-samd.cpp index da4a98e27..fa62bb359 100644 --- a/src/utility/ota/OTA-samd.cpp +++ b/src/utility/ota/OTA-samd.cpp @@ -15,17 +15,18 @@ a commercial license, send an email to license@arduino.cc. */ -#ifdef ARDUINO_ARCH_SAMD - /****************************************************************************** * INCLUDE ******************************************************************************/ -#include "OTA.h" +#include -#include +#if defined (ARDUINO_ARCH_SAMD) && OTA_ENABLED +#include "OTA.h" +#include #include "../watchdog/Watchdog.h" +#include "utility/ota/FlashSHA256.h" #if OTA_STORAGE_SNU # include @@ -65,4 +66,19 @@ int samd_onOTARequest(char const * ota_url) return static_cast(OTAError::DownloadFailed); } +String samd_getOTAImageSHA256() +{ + /* Calculate the SHA256 checksum over the firmware stored in the flash of the + * MCU. Note: As we don't know the length per-se we read chunks of the flash + * until we detect one containing only 0xFF (= flash erased). This only works + * for firmware updated via OTA and second stage bootloaders (SxU family) + * because only those erase the complete flash before performing an update. + * Since the SHA256 firmware image is only required for the cloud servers to + * perform a version check after the OTA update this is a acceptable trade off. + * The bootloader is excluded from the calculation and occupies flash address + * range 0 to 0x2000, total flash size of 0x40000 bytes (256 kByte). + */ + return FlashSHA256::calc(0x2000, 0x40000 - 0x2000); +} + #endif /* ARDUINO_ARCH_SAMD */ diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index dbf4ae4cc..26139d46d 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -23,6 +23,7 @@ ******************************************************************************/ #include +#include /****************************************************************************** * DEFINES @@ -56,18 +57,22 @@ enum class OTAError : int #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 #endif /* ARDUINO_OTA_LOGIC_H_ */ From fce00185583dd26b6399d3c2c57bca65ab5de9a5 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 18 Jan 2023 14:02:55 +0100 Subject: [PATCH 385/780] esp32_getOTAImageSHA256: simplify beautify and align style --- src/utility/ota/OTA-esp32.cpp | 45 +++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/utility/ota/OTA-esp32.cpp b/src/utility/ota/OTA-esp32.cpp index 29cf3621b..97da4041c 100644 --- a/src/utility/ota/OTA-esp32.cpp +++ b/src/utility/ota/OTA-esp32.cpp @@ -70,31 +70,40 @@ int esp32_onOTARequest(char const * ota_url) String esp32_getOTAImageSHA256() { - SHA256 sha256; - - uint32_t lengthLeft = ESP.getSketchSize(); - const esp_partition_t *running = esp_ota_get_running_partition(); if (!running) { - DEBUG_ERROR("Partition could not be found"); + DEBUG_ERROR("ESP32::SHA256 Running partition could not be found"); + return String(); } - const size_t bufSize = SPI_FLASH_SEC_SIZE; - std::unique_ptr buf(new uint8_t[bufSize]); - uint32_t offset = 0; - if(!buf.get()) { - DEBUG_ERROR("Not enough memory to allocate buffer"); + + uint8_t *b = (uint8_t*)malloc(SPI_FLASH_SEC_SIZE); + if(b == nullptr) { + DEBUG_ERROR("ESP32::SHA256 Not enough memory to allocate buffer"); + return String(); } + SHA256 sha256; + uint32_t const app_start = running->address; + uint32_t const app_size = ESP.getSketchSize(); + uint32_t read_bytes = 0; + sha256.begin(); - while( lengthLeft > 0) { - size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize; - if (!ESP.flashRead(running->address + offset, reinterpret_cast(buf.get()), (readBytes + 3) & ~3)) { - DEBUG_ERROR("Could not read buffer from flash"); + for(uint32_t a = app_start; read_bytes < app_size; ) + { + /* Check if we are reading last sector and compute used size */ + uint32_t const read_size = read_bytes + SPI_FLASH_SEC_SIZE < app_size ? SPI_FLASH_SEC_SIZE : app_size - read_bytes; + + /* Use always 4 bytes aligned reads */ + if (!ESP.flashRead(a, reinterpret_cast(b), (read_size + 3) & ~3)) { + DEBUG_ERROR("ESP32::SHA256 Could not read data from flash"); + return String(); } - sha256.update(buf.get(), readBytes); - lengthLeft -= readBytes; - offset += readBytes; + sha256.update(b, read_size); + a += read_size; + read_bytes += read_size; } + free(b); + /* Retrieve the final hash string. */ uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; sha256.finalize(sha256_hash); @@ -107,7 +116,7 @@ String esp32_getOTAImageSHA256() snprintf(buf, 4, "%02X", elem); sha256_str += buf; }); - DEBUG_VERBOSE("SHA256: %d bytes (of %d) read", ESP.getSketchSize() - lengthLeft, ESP.getSketchSize()); + DEBUG_VERBOSE("SHA256: %d bytes (of %d) read", read_bytes, app_size); return sha256_str; } From e824e4ce19da4caa4cbeee64088e2f156c01a2dd Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 19 Jan 2023 12:55:31 +0100 Subject: [PATCH 386/780] CI: add Arduino_ESP32_OTA library dependency --- .github/workflows/compile-examples.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 8660f5707..8a24fdce9 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -179,7 +179,8 @@ jobs: # Install ESP32 platform via Boards Manager - name: esp32:esp32 source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - libraries: + libraries: | + - name: Arduino_ESP32_OTA sketch-paths: steps: From 86520bf6c6b00df513d4a01881f721c73af0bf0a Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Thu, 19 Jan 2023 15:01:57 +0100 Subject: [PATCH 387/780] Release v1.10.0 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 47282d739..6a7bdfb00 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.9.0 +version=1.10.0 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index b1ba04082..e734ecf2c 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -166,6 +166,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.9.0" +#define AIOT_CONFIG_LIB_VERSION "1.10.0" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 7c217e5043f483f86054a7070d52b12e19cf7d58 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 19 Jan 2023 12:54:35 +0100 Subject: [PATCH 388/780] Move OTA functions in newly added OTA.cpp file --- src/ArduinoIoTCloudTCP.cpp | 47 ++---------- src/ArduinoIoTCloudTCP.h | 2 - src/utility/ota/OTA-portenta-h7.cpp | 15 +++- src/utility/ota/OTA.cpp | 108 ++++++++++++++++++++++++++++ src/utility/ota/OTA.h | 35 ++++----- 5 files changed, 142 insertions(+), 65 deletions(-) create mode 100644 src/utility/ota/OTA.cpp diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 62d2d7025..e012b9f74 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 */ @@ -239,6 +239,10 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _ota_cap = true; #endif +#if OTA_ENABLED + OTA::setNetworkAdapter(_connection->getInterface()); +#endif + #ifdef BOARD_HAS_OFFLOADED_ECCX08 if (String(WiFi.firmwareVersion()) < String("1.4.4")) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, NINA firmware needs to be >= 1.4.4, current %s", __FUNCTION__, WiFi.firmwareVersion()); @@ -609,7 +613,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); /* If something fails send the OTA error to the cloud */ sendDevicePropertyToCloud("OTA_ERROR"); } @@ -762,45 +766,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-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index 12481a7ed..461058897 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -35,6 +35,12 @@ #include "../watchdog/Watchdog.h" +/****************************************************************************** + * LOCAL VARIABLES + ******************************************************************************/ + +static NetworkAdapter _ota_adapter = NetworkAdapter::WIFI; + /****************************************************************************** * EXTERN ******************************************************************************/ @@ -45,7 +51,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) { watchdog_reset(); @@ -76,7 +82,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(_ota_adapter == NetworkAdapter::ETHERNET) { download_socket = static_cast(&Ethernet); } #endif @@ -143,4 +149,9 @@ String portenta_h7_getOTAImageSHA256() return sha256_str; } +void portenta_h7_setNetworkAdapter(NetworkAdapter iface) +{ + _ota_adapter = iface; +} + #endif /* BOARD_STM32H7 */ diff --git a/src/utility/ota/OTA.cpp b/src/utility/ota/OTA.cpp new file mode 100644 index 000000000..e6cfb7146 --- /dev/null +++ b/src/utility/ota/OTA.cpp @@ -0,0 +1,108 @@ +/* + 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 DEFINITION + ******************************************************************************/ + +#ifdef ARDUINO_ARCH_SAMD +int samd_onOTARequest(char const * url); +String samd_getOTAImageSHA256(); +#endif + +#ifdef ARDUINO_NANO_RP2040_CONNECT +int rp2040_connect_onOTARequest(char const * url); +String rp2040_connect_getOTAImageSHA256(); +#endif + +#ifdef BOARD_STM32H7 +int portenta_h7_onOTARequest(char const * url); +String portenta_h7_getOTAImageSHA256(); +void portenta_h7_setNetworkAdapter(NetworkAdapter iface); +#endif + +#ifdef ARDUINO_ARCH_ESP32 +int esp32_onOTARequest(char const * url); +String esp32_getOTAImageSHA256(); +#endif + +/****************************************************************************** + * PUBLIC MEMBER FUNCTIONS + ******************************************************************************/ + + +int OTA::onRequest(String url) +{ + DEBUG_INFO("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, url.c_str()); + +#if defined (ARDUINO_ARCH_SAMD) + return samd_onOTARequest(url.c_str()); +#elif defined (ARDUINO_NANO_RP2040_CONNECT) + return rp2040_connect_onOTARequest(url.c_str()); +#elif defined (BOARD_STM32H7) + return portenta_h7_onOTARequest(url.c_str()); +#elif defined (ARDUINO_ARCH_ESP32) + 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 +} + + +void OTA::setNetworkAdapter(NetworkAdapter iface) +{ +#if defined (ARDUINO_ARCH_SAMD) + /* Only WiFi available */ +#elif defined (ARDUINO_NANO_RP2040_CONNECT) + /* Only WiFi available */ +#elif defined (BOARD_STM32H7) + portenta_h7_setNetworkAdapter(iface); +#elif defined (ARDUINO_ARCH_ESP32) + /* Only WiFi available */ +#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..23fb50b0b 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); + static String getImageSHA256(); + static void setNetworkAdapter(NetworkAdapter iface); + +}; + +#endif /* OTA_ENABLED */ #endif /* ARDUINO_OTA_LOGIC_H_ */ From d0346cbd88fbb81240eef419ea1dfba7fccee9f6 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 19 Jan 2023 16:09:45 +0100 Subject: [PATCH 389/780] Create OTA::isCapable and move code from ArduinoIoTCloudTCP --- src/ArduinoIoTCloudTCP.cpp | 34 ++--------------------------- src/utility/ota/OTA-esp32.cpp | 6 +++++ src/utility/ota/OTA-nano-rp2040.cpp | 5 +++++ src/utility/ota/OTA-portenta-h7.cpp | 5 +++++ src/utility/ota/OTA-samd.cpp | 13 +++++++++++ src/utility/ota/OTA.cpp | 22 ++++++++++++++++--- src/utility/ota/OTA.h | 1 + 7 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e012b9f74..5ae47c0a3 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -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 #if OTA_ENABLED 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 461058897..2a6653f47 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -149,6 +149,11 @@ String portenta_h7_getOTAImageSHA256() return sha256_str; } +bool portenta_h7_isOTACapable() +{ + return Arduino_Portenta_OTA::isOtaCapable(); +} + void portenta_h7_setNetworkAdapter(NetworkAdapter iface) { _ota_adapter = iface; 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 index e6cfb7146..0c3ad7178 100644 --- a/src/utility/ota/OTA.cpp +++ b/src/utility/ota/OTA.cpp @@ -27,35 +27,38 @@ #include /****************************************************************************** - * FUNCTION DEFINITION + * 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); 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) { DEBUG_INFO("ArduinoIoTCloudTCP::%s _ota_url = %s", __FUNCTION__, url.c_str()); @@ -88,6 +91,20 @@ String OTA::getImageSHA256() #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 +} void OTA::setNetworkAdapter(NetworkAdapter iface) { @@ -105,4 +122,3 @@ void OTA::setNetworkAdapter(NetworkAdapter iface) } #endif /* OTA_ENABLED */ - diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h index 23fb50b0b..57a22ad73 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -65,6 +65,7 @@ class OTA static int onRequest(String url); static String getImageSHA256(); static void setNetworkAdapter(NetworkAdapter iface); + static bool isCapable(); }; From 6bcac2a21e1caae31ce3705160c58de997195287 Mon Sep 17 00:00:00 2001 From: Jorgetrujilloroman <124149761+Jorgetrujilloroman@users.noreply.github.com> Date: Fri, 10 Feb 2023 17:05:19 +0100 Subject: [PATCH 390/780] bin2ota Fix: Add missing colon Adding missing colon on line 29 --- extras/tools/bin2ota.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/tools/bin2ota.py b/extras/tools/bin2ota.py index 7ec4c6846..32c3bfe1d 100755 --- a/extras/tools/bin2ota.py +++ b/extras/tools/bin2ota.py @@ -26,7 +26,7 @@ magic_number = 0x2341025B.to_bytes(4,byteorder='little') elif board == "NANO_RP2040_CONNECT": magic_number = 0x2341005E.to_bytes(4,byteorder='little') -elif board == "NICLA_VISION" +elif board == "NICLA_VISION": magic_number = 0x2341025F.to_bytes(4,byteorder='little') elif board == "OPTA": magic_number = 0x23410064.to_bytes(4,byteorder='little') From ddcfdecb09f938cd8099c7362129ecc620365e86 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 14 Feb 2023 17:23:24 +0100 Subject: [PATCH 391/780] Remove OTA::setNetworkAdapter Add iface parameter to OTA::onRequest --- src/ArduinoIoTCloudTCP.cpp | 6 +----- src/utility/ota/OTA-portenta-h7.cpp | 15 ++------------- src/utility/ota/OTA.cpp | 24 ++++++------------------ src/utility/ota/OTA.h | 3 +-- 4 files changed, 10 insertions(+), 38 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 5ae47c0a3..5d0dd8f57 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -209,10 +209,6 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _ota_cap = OTA::isCapable(); #endif -#if OTA_ENABLED - OTA::setNetworkAdapter(_connection->getInterface()); -#endif - #ifdef BOARD_HAS_OFFLOADED_ECCX08 if (String(WiFi.firmwareVersion()) < String("1.4.4")) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, NINA firmware needs to be >= 1.4.4, current %s", __FUNCTION__, WiFi.firmwareVersion()); @@ -583,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. */ - _ota_error = OTA::onRequest(_ota_url); + _ota_error = OTA::onRequest(_ota_url, _connection->getInterface()); /* If something fails send the OTA error to the cloud */ sendDevicePropertyToCloud("OTA_ERROR"); } diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index 2a6653f47..bd95f6a6b 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -35,12 +35,6 @@ #include "../watchdog/Watchdog.h" -/****************************************************************************** - * LOCAL VARIABLES - ******************************************************************************/ - -static NetworkAdapter _ota_adapter = NetworkAdapter::WIFI; - /****************************************************************************** * EXTERN ******************************************************************************/ @@ -51,7 +45,7 @@ extern RTC_HandleTypeDef RTCHandle; * FUNCTION DEFINITION ******************************************************************************/ -int portenta_h7_onOTARequest(char const * ota_url) +int portenta_h7_onOTARequest(char const * ota_url, NetworkAdapter iface) { watchdog_reset(); @@ -82,7 +76,7 @@ int portenta_h7_onOTARequest(char const * ota_url) /* Download the OTA file from the web storage location. */ MbedSocketClass * download_socket = static_cast(&WiFi); #if defined (BOARD_HAS_ETHERNET) - if(_ota_adapter == NetworkAdapter::ETHERNET) { + if(iface == NetworkAdapter::ETHERNET) { download_socket = static_cast(&Ethernet); } #endif @@ -154,9 +148,4 @@ bool portenta_h7_isOTACapable() return Arduino_Portenta_OTA::isOtaCapable(); } -void portenta_h7_setNetworkAdapter(NetworkAdapter iface) -{ - _ota_adapter = iface; -} - #endif /* BOARD_STM32H7 */ diff --git a/src/utility/ota/OTA.cpp b/src/utility/ota/OTA.cpp index 0c3ad7178..bac388b59 100644 --- a/src/utility/ota/OTA.cpp +++ b/src/utility/ota/OTA.cpp @@ -43,7 +43,7 @@ bool rp2040_connect_isOTACapable(); #endif #ifdef BOARD_STM32H7 -int portenta_h7_onOTARequest(char const * url); +int portenta_h7_onOTARequest(char const * url, NetworkAdapter iface); String portenta_h7_getOTAImageSHA256(); void portenta_h7_setNetworkAdapter(NetworkAdapter iface); bool portenta_h7_isOTACapable(); @@ -59,17 +59,20 @@ bool esp32_isOTACapable(); * PUBLIC MEMBER FUNCTIONS ******************************************************************************/ -int OTA::onRequest(String url) +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()); + 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" @@ -106,19 +109,4 @@ bool OTA::isCapable() #endif } -void OTA::setNetworkAdapter(NetworkAdapter iface) -{ -#if defined (ARDUINO_ARCH_SAMD) - /* Only WiFi available */ -#elif defined (ARDUINO_NANO_RP2040_CONNECT) - /* Only WiFi available */ -#elif defined (BOARD_STM32H7) - portenta_h7_setNetworkAdapter(iface); -#elif defined (ARDUINO_ARCH_ESP32) - /* Only WiFi available */ -#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 57a22ad73..88c7229b9 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -62,9 +62,8 @@ class OTA { public: - static int onRequest(String url); + static int onRequest(String url, NetworkAdapter iface); static String getImageSHA256(); - static void setNetworkAdapter(NetworkAdapter iface); static bool isCapable(); }; From b3ab0f9ee8ea1024394a6086e6a86c36b7dd6b1c Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 20 Jan 2023 10:05:39 +0100 Subject: [PATCH 392/780] Add private and arch specific functions to init/get/set RTC --- src/utility/time/TimeService.cpp | 167 +++++++++++++++++++++++++++++++ src/utility/time/TimeService.h | 3 + 2 files changed, 170 insertions(+) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index dc90048ad..9bb5811ac 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -39,6 +39,36 @@ RTCZero rtc; time_t cvt_time(char const * time); +#ifdef ARDUINO_ARCH_SAMD +void samd_initRTC(); +void samd_setRTC(unsigned long time); +unsigned long samd_getRTC(); +#endif + +#ifdef ARDUINO_NANO_RP2040_CONNECT +void rp2040_connect_initRTC(); +void rp2040_connect_setRTC(unsigned long time); +unsigned long rp2040_connect_getRTC(); +#endif + +#ifdef BOARD_STM32H7 +void stm32h7_initRTC(); +void stm32h7_setRTC(unsigned long time); +unsigned long stm32h7_getRTC(); +#endif + +#ifdef ARDUINO_ARCH_ESP32 +void esp32_initRTC(); +void esp32_setRTC(unsigned long time); +unsigned long esp32_getRTC(); +#endif + +#ifdef ARDUINO_ARCH_ESP8266 +void esp8266_initRTC(); +void esp8266_setRTC(unsigned long time); +unsigned long esp8266_getRTC(); +#endif + /************************************************************************************** * CONSTANTS **************************************************************************************/ @@ -277,6 +307,57 @@ bool TimeService::isTimeValid(unsigned long const time) return (time >= EPOCH_AT_COMPILE_TIME); } +void TimeService::initRTC() +{ +#if defined (ARDUINO_ARCH_SAMD) + samd_initRTC(); +#elif defined (ARDUINO_NANO_RP2040_CONNECT) + rp2040_connect_initRTC(); +#elif defined (BOARD_STM32H7) + stm32h7_initRTC(); +#elif defined (ARDUINO_ARCH_ESP32) + esp32_initRTC(); +#elif ARDUINO_ARCH_ESP8266 + esp8266_initRTC(); +#else + #error "RTC not available for this architecture" +#endif +} + +void TimeService::setRTC(unsigned long time) +{ +#if defined (ARDUINO_ARCH_SAMD) + samd_setRTC(time); +#elif defined (ARDUINO_NANO_RP2040_CONNECT) + rp2040_connect_setRTC(time); +#elif defined (BOARD_STM32H7) + stm32h7_setRTC(time); +#elif defined (ARDUINO_ARCH_ESP32) + esp32_setRTC(time); +#elif ARDUINO_ARCH_ESP8266 + esp8266_setRTC(time); +#else + #error "RTC not available for this architecture" +#endif +} + +unsigned long TimeService::getRTC() +{ +#if defined (ARDUINO_ARCH_SAMD) + return samd_getRTC(); +#elif defined (ARDUINO_NANO_RP2040_CONNECT) + return rp2040_connect_getRTC(); +#elif defined (BOARD_STM32H7) + return stm32h7_getRTC(); +#elif defined (ARDUINO_ARCH_ESP32) + return esp32_getRTC(); +#elif ARDUINO_ARCH_ESP8266 + return esp8266_getRTC(); +#else + #error "RTC not available for this architecture" +#endif +} + /************************************************************************************** * INTERNAL FUNCTION DEFINITION **************************************************************************************/ @@ -311,6 +392,92 @@ time_t cvt_time(char const * time) return mktime(&t); } +#ifdef ARDUINO_ARCH_SAMD +void samd_initRTC() +{ + rtc.begin(); +} + +void samd_setRTC(unsigned long time) +{ + rtc.setEpoch(time); +} + +unsigned long samd_getRTC() +{ + return rtc.getEpoch(); +} +#endif + +#ifdef ARDUINO_NANO_RP2040_CONNECT +void rp2040_connect_initRTC() +{ + /* Nothing to do */ +} + +void rp2040_connect_setRTC(unsigned long time) +{ + set_time(time); +} + +unsigned long rp2040_connect_getRTC() +{ + return time(NULL); +} +#endif + +#ifdef BOARD_STM32H7 +void stm32h7_initRTC() +{ + /* Nothing to do */ +} + +void stm32h7_setRTC(unsigned long time) +{ + set_time(time); +} + +unsigned long stm32h7_getRTC() +{ + return time(NULL); +} +#endif + +#ifdef ARDUINO_ARCH_ESP32 +void esp32_initRTC() +{ + //configTime(0, 0, "time.arduino.cc", "pool.ntp.org", "time.nist.gov"); +} + +void esp32_setRTC(unsigned long time) +{ + const timeval epoch = {(time_t)time, 0}; + settimeofday(&epoch, 0); +} + +unsigned long esp32_getRTC() +{ + return time(NULL); +} +#endif + +#ifdef ARDUINO_ARCH_ESP8266 +void esp8266_initRTC() +{ + /* Nothing to do */ +} + +void esp8266_setRTC(unsigned long time) +{ + /* TODO */ +} + +unsigned long esp8266_getRTC() +{ + /* TODO */ +} +#endif + TimeService & ArduinoIoTCloudTimeService() { static TimeService _timeService_instance; return _timeService_instance; diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index bf8eef1a1..04d62ffc3 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -69,6 +69,9 @@ class TimeService unsigned long getRemoteTime(); bool connected(); static bool isTimeValid(unsigned long const time); + void initRTC(); + void setRTC(unsigned long time); + unsigned long getRTC(); }; From ec338dd77ce4a9356585aa070417c61f37ebc875 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 20 Jan 2023 15:15:31 +0100 Subject: [PATCH 393/780] Add RTC implementation based on millis for ESP8266 --- src/utility/time/RTCMillis.cpp | 63 ++++++++++++++++++++++++++++++++++ src/utility/time/RTCMillis.h | 50 +++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 src/utility/time/RTCMillis.cpp create mode 100644 src/utility/time/RTCMillis.h diff --git a/src/utility/time/RTCMillis.cpp b/src/utility/time/RTCMillis.cpp new file mode 100644 index 000000000..ae17487ef --- /dev/null +++ b/src/utility/time/RTCMillis.cpp @@ -0,0 +1,63 @@ +/* + 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. +*/ + +#ifdef ARDUINO_ARCH_ESP8266 + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include +#include "RTCMillis.h" + +/************************************************************************************** + * CTOR/DTOR + **************************************************************************************/ + +RTCMillis::RTCMillis() +: _last_rtc_update_tick(0) +, _last_rtc_update_value(0) +{ + +} + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +void RTCMillis::begin() +{ + +} + +void RTCMillis::set(unsigned long time) +{ + _last_rtc_update_tick = millis(); + _last_rtc_update_value = time; +} + +unsigned long RTCMillis::get() +{ + unsigned long current_tick = millis(); + unsigned long const elapsed_s = (current_tick - _last_rtc_update_tick) / 1000; + if(elapsed_s) { + set(_last_rtc_update_value + elapsed_s); + } + return _last_rtc_update_value; +} + +#endif /* ARDUINO_ARCH_ESP8266 */ diff --git a/src/utility/time/RTCMillis.h b/src/utility/time/RTCMillis.h new file mode 100644 index 000000000..1fa7e0f4a --- /dev/null +++ b/src/utility/time/RTCMillis.h @@ -0,0 +1,50 @@ +/* + 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_IOT_CLOUD_RTC_MILLIS_H_ +#define ARDUINO_IOT_CLOUD_RTC_MILLIS_H_ + +#ifdef ARDUINO_ARCH_ESP8266 + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class RTCMillis +{ + +public: + + RTCMillis(); + + void begin(); + void set(unsigned long time); + unsigned long get(); + +private: + unsigned long _last_rtc_update_tick; + unsigned long _last_rtc_update_value; + +}; + +#endif /* ARDUINO_ARCH_ESP8266 */ + +#endif /* ARDUINO_IOT_CLOUD_RTC_MILLIS_H_ */ From bfde58c5ff440ecd7d3ddc67e0e924c079fe433b Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 20 Jan 2023 15:21:53 +0100 Subject: [PATCH 394/780] getTimeFromSting cosmetic changes --- src/utility/time/TimeService.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 9bb5811ac..e8eac6887 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -214,16 +214,14 @@ unsigned long TimeService::getTimeFromString(const String& input) static const int expected_length = 20; static const int expected_parameters = 6; - if(input == nullptr || input.length() != expected_length) - { + if(input == nullptr || input.length() != expected_length) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s invalid input length", __FUNCTION__); return 0; } int scanned_parameters = sscanf(input.c_str(), "%d %s %d %d:%d:%d", &year, s_month, &day, &hour, &min, &sec); - if(scanned_parameters != expected_parameters) - { + if(scanned_parameters != expected_parameters) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s invalid input parameters number", __FUNCTION__); return 0; } From 01cc7773c0aff2d0936858518cd780c3f8d93212 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 20 Jan 2023 15:25:29 +0100 Subject: [PATCH 395/780] Avoid to store EPOCH_AT_COMPILE_TIME inside RTC register --- src/utility/time/TimeService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index e8eac6887..816b115c7 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -302,7 +302,7 @@ unsigned long TimeService::getRemoteTime() bool TimeService::isTimeValid(unsigned long const time) { - return (time >= EPOCH_AT_COMPILE_TIME); + return (time > EPOCH_AT_COMPILE_TIME); } void TimeService::initRTC() From e7120b4ddfc4ea4a22c54558272bf13ce8102ec6 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 20 Jan 2023 15:26:23 +0100 Subject: [PATCH 396/780] Add sync method --- src/utility/time/TimeService.cpp | 14 ++++++++++++++ src/utility/time/TimeService.h | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 816b115c7..f8b4ba369 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -170,6 +170,20 @@ unsigned long TimeService::getTime() #endif } +bool TimeService::sync() +{ + _is_rtc_configured = false; + unsigned long utc = getRemoteTime(); + + if(isTimeValid(utc)) { + DEBUG_DEBUG("TimeServiceClass::%s Drift: %d RTC value: %u", __FUNCTION__, getRTC() - utc, utc); + setRTC(utc); + _last_ntp_sync_tick = millis(); + _is_rtc_configured = true; + } + return _is_rtc_configured; +} + void TimeService::setTimeZoneData(long offset, unsigned long dst_until) { if(_timezone_offset != offset) diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 04d62ffc3..c41523e07 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -43,11 +43,11 @@ class TimeService TimeService(); - void begin (ConnectionHandler * con_hdl); unsigned long getTime(); unsigned long getLocalTime(); void setTimeZoneData(long offset, unsigned long valid_until); + bool sync(); /* Helper function to convert an input String into a UNIX timestamp. * The input String format must be as follow "2021 Nov 01 17:00:00" */ From c862434964d0bba947e4c494a7b6ade74b421569 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 16 Feb 2023 10:13:29 +0100 Subject: [PATCH 397/780] Declare and use RTC for ESP8266 --- src/utility/time/TimeService.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index f8b4ba369..4029af5c9 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -25,6 +25,10 @@ #include "NTPUtils.h" +#ifdef ARDUINO_ARCH_ESP8266 + #include "RTCMillis.h" +#endif + /************************************************************************************** * GLOBAL VARIABLES **************************************************************************************/ @@ -33,6 +37,10 @@ RTCZero rtc; #endif +#ifdef ARDUINO_ARCH_ESP8266 +RTCMillis rtc; +#endif + /************************************************************************************** * INTERNAL FUNCTION DECLARATION **************************************************************************************/ @@ -476,17 +484,17 @@ unsigned long esp32_getRTC() #ifdef ARDUINO_ARCH_ESP8266 void esp8266_initRTC() { - /* Nothing to do */ + rtc.begin(); } void esp8266_setRTC(unsigned long time) { - /* TODO */ + rtc.set(time); } unsigned long esp8266_getRTC() { - /* TODO */ + return rtc.get(); } #endif From 2e48a0e0810866e76ef4666f9547dea64d91f9f5 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 16 Feb 2023 10:19:00 +0100 Subject: [PATCH 398/780] Move includes on top of file --- src/utility/time/TimeService.cpp | 14 ++++++++++---- src/utility/time/TimeService.h | 8 -------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 4029af5c9..7346ca5f9 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -19,12 +19,20 @@ * INCLUDE **************************************************************************************/ -#include "TimeService.h" +#include #include - +#include "TimeService.h" #include "NTPUtils.h" +#ifdef ARDUINO_ARCH_SAMD + #include +#endif + +#ifdef ARDUINO_ARCH_MBED + #include +#endif + #ifdef ARDUINO_ARCH_ESP8266 #include "RTCMillis.h" #endif @@ -288,9 +296,7 @@ bool TimeService::connected() unsigned long TimeService::getRemoteTime() { -#include "../../AIoTC_Config.h" #ifndef HAS_LORA - if(connected()) { /* At first try to see if a valid time can be obtained * using the network time available via the connection diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index c41523e07..593669702 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -24,14 +24,6 @@ #include -#ifdef ARDUINO_ARCH_SAMD - #include -#endif - -#ifdef ARDUINO_ARCH_MBED - #include -#endif - /************************************************************************************** * CLASS DECLARATION **************************************************************************************/ From 82699bbd8941b337957a131ce94ae3c032749352 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 16 Feb 2023 10:21:32 +0100 Subject: [PATCH 399/780] Extend NTP synch to all platforms --- src/utility/time/TimeService.cpp | 10 +++------- src/utility/time/TimeService.h | 4 ---- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 7346ca5f9..9c3fe8ec9 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -89,9 +89,9 @@ unsigned long esp8266_getRTC(); * CONSTANTS **************************************************************************************/ -#ifdef ARDUINO_ARCH_ESP8266 -static unsigned long const AIOT_TIMESERVICE_ESP8266_NTP_SYNC_TIMEOUT_ms = 86400000; -#endif +/* Default NTP synch is scheduled each 24 hours from startup */ +static unsigned long const AIOT_TIMESERVICE_NTP_SYNC_TIMEOUT_ms = 86400000; + static time_t const EPOCH_AT_COMPILE_TIME = cvt_time(__DATE__); static time_t const EPOCH = 0; @@ -105,11 +105,7 @@ TimeService::TimeService() , _is_tz_configured(false) , _timezone_offset(0) , _timezone_dst_until(0) -#ifdef ARDUINO_ARCH_ESP8266 , _last_ntp_sync_tick(0) -, _last_rtc_update_tick(0) -, _rtc(0) -#endif { } diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 593669702..70ca0ea73 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -52,11 +52,7 @@ class TimeService bool _is_tz_configured; long _timezone_offset; unsigned long _timezone_dst_until; -#ifdef ARDUINO_ARCH_ESP8266 unsigned long _last_ntp_sync_tick; - unsigned long _last_rtc_update_tick; - unsigned long _rtc; -#endif unsigned long getRemoteTime(); bool connected(); From 9471ee0d2cac38ee175755bc1f46c0d83d3b39a8 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 16 Feb 2023 10:23:17 +0100 Subject: [PATCH 400/780] Make use of initRTC and sync functions --- src/utility/time/TimeService.cpp | 68 +++++--------------------------- 1 file changed, 10 insertions(+), 58 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 9c3fe8ec9..75d994091 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -117,69 +117,21 @@ TimeService::TimeService() void TimeService::begin(ConnectionHandler * con_hdl) { _con_hdl = con_hdl; -#ifdef ARDUINO_ARCH_SAMD - rtc.begin(); -#endif + initRTC(); } unsigned long TimeService::getTime() { -#ifdef ARDUINO_ARCH_SAMD - if(!_is_rtc_configured) - { - unsigned long utc = getRemoteTime(); - if(EPOCH_AT_COMPILE_TIME != utc) - { - rtc.setEpoch(utc); - _is_rtc_configured = true; - } - return utc; + /* Check if it's time to sync */ + unsigned long const current_tick = millis(); + bool const is_ntp_sync_timeout = (current_tick - _last_ntp_sync_tick) > AIOT_TIMESERVICE_NTP_SYNC_TIMEOUT_ms; + if(!_is_rtc_configured || is_ntp_sync_timeout) { + sync(); } - return rtc.getEpoch(); -#elif ARDUINO_ARCH_MBED - if(!_is_rtc_configured) - { - unsigned long utc = getRemoteTime(); - if(EPOCH_AT_COMPILE_TIME != utc) - { - set_time(utc); - _is_rtc_configured = true; - } - return utc; - } - return time(NULL); -#elif ARDUINO_ARCH_ESP32 - if(!_is_rtc_configured) - { - configTime(0, 0, "time.arduino.cc", "pool.ntp.org", "time.nist.gov"); - _is_rtc_configured = true; - } - return time(NULL); -#elif ARDUINO_ARCH_ESP8266 - unsigned long const now = millis(); - bool const is_ntp_sync_timeout = (now - _last_ntp_sync_tick) > AIOT_TIMESERVICE_ESP8266_NTP_SYNC_TIMEOUT_ms; - if(!_is_rtc_configured || is_ntp_sync_timeout) - { - _is_rtc_configured = false; - unsigned long utc = getRemoteTime(); - if(EPOCH_AT_COMPILE_TIME != utc) - { - _rtc = utc; - _last_ntp_sync_tick = now; - _last_rtc_update_tick = now; - _is_rtc_configured = true; - } - return utc; - } - unsigned long const elapsed_s = (now - _last_rtc_update_tick) / 1000; - if(elapsed_s) { - _rtc += elapsed_s; - _last_rtc_update_tick = now; - } - return _rtc; -#else - return getRemoteTime(); -#endif + + /* Read time from RTC */ + unsigned long utc = getRTC(); + return isTimeValid(utc) ? utc : EPOCH_AT_COMPILE_TIME; } bool TimeService::sync() From ada180c0c628b9459033494e229810d108aa5ab7 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 20 Jan 2023 16:19:12 +0100 Subject: [PATCH 401/780] Make sync interval configurable --- src/utility/time/TimeService.cpp | 12 +++++++++--- src/utility/time/TimeService.h | 3 +++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 75d994091..d0153c262 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -24,6 +24,7 @@ #include #include "TimeService.h" #include "NTPUtils.h" +#include "AIoTC_Const.h" #ifdef ARDUINO_ARCH_SAMD #include @@ -90,8 +91,7 @@ unsigned long esp8266_getRTC(); **************************************************************************************/ /* Default NTP synch is scheduled each 24 hours from startup */ -static unsigned long const AIOT_TIMESERVICE_NTP_SYNC_TIMEOUT_ms = 86400000; - +static time_t const TIMESERVICE_NTP_SYNC_TIMEOUT_ms = DAYS * 1000; static time_t const EPOCH_AT_COMPILE_TIME = cvt_time(__DATE__); static time_t const EPOCH = 0; @@ -106,6 +106,7 @@ TimeService::TimeService() , _timezone_offset(0) , _timezone_dst_until(0) , _last_ntp_sync_tick(0) +, _ntp_sync_interval_ms(TIMESERVICE_NTP_SYNC_TIMEOUT_ms) { } @@ -124,7 +125,7 @@ unsigned long TimeService::getTime() { /* Check if it's time to sync */ unsigned long const current_tick = millis(); - bool const is_ntp_sync_timeout = (current_tick - _last_ntp_sync_tick) > AIOT_TIMESERVICE_NTP_SYNC_TIMEOUT_ms; + bool const is_ntp_sync_timeout = (current_tick - _last_ntp_sync_tick) > _ntp_sync_interval_ms; if(!_is_rtc_configured || is_ntp_sync_timeout) { sync(); } @@ -148,6 +149,11 @@ bool TimeService::sync() return _is_rtc_configured; } +void TimeService::setSyncInterval(unsigned long seconds) +{ + _ntp_sync_interval_ms = seconds * 1000; +} + void TimeService::setTimeZoneData(long offset, unsigned long dst_until) { if(_timezone_offset != offset) diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 70ca0ea73..43fa2d4a8 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -40,6 +40,8 @@ class TimeService unsigned long getLocalTime(); void setTimeZoneData(long offset, unsigned long valid_until); bool sync(); + void setSyncInterval(unsigned long seconds); + /* Helper function to convert an input String into a UNIX timestamp. * The input String format must be as follow "2021 Nov 01 17:00:00" */ @@ -53,6 +55,7 @@ class TimeService long _timezone_offset; unsigned long _timezone_dst_until; unsigned long _last_ntp_sync_tick; + unsigned long _ntp_sync_interval_ms; unsigned long getRemoteTime(); bool connected(); From 8439b010658dd86efe7b4280bade2a1f3816e5b7 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 3 Feb 2022 16:02:29 +0100 Subject: [PATCH 402/780] setTimeZoneData cosmetic changes --- src/utility/time/TimeService.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index d0153c262..4e6647582 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -156,15 +156,12 @@ void TimeService::setSyncInterval(unsigned long seconds) void TimeService::setTimeZoneData(long offset, unsigned long dst_until) { - if(_timezone_offset != offset) - DEBUG_DEBUG("ArduinoIoTCloudTCP::%s tz_offset: [%d]", __FUNCTION__, offset); - _timezone_offset = offset; - - if(_timezone_dst_until != dst_until) - DEBUG_DEBUG("ArduinoIoTCloudTCP::%s tz_dst_unitl: [%ul]", __FUNCTION__, dst_until); - _timezone_dst_until = dst_until; - - _is_tz_configured = true; + if(_timezone_offset != offset || _timezone_dst_until != dst_until) { + DEBUG_DEBUG("ArduinoIoTCloudTCP::%s offset: %d dst_unitl %ul", __FUNCTION__, offset, dst_until); + _timezone_offset = offset; + _timezone_dst_until = dst_until; + _is_tz_configured = true; + } } unsigned long TimeService::getLocalTime() From 1836f23342bf01aa2a5d6dcfeb31cd2611e757c6 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 20 Jan 2023 16:38:51 +0100 Subject: [PATCH 403/780] Fix debug prints reporting the wrong class name --- src/utility/time/TimeService.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 4e6647582..8341b09ee 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -157,7 +157,7 @@ void TimeService::setSyncInterval(unsigned long seconds) void TimeService::setTimeZoneData(long offset, unsigned long dst_until) { if(_timezone_offset != offset || _timezone_dst_until != dst_until) { - DEBUG_DEBUG("ArduinoIoTCloudTCP::%s offset: %d dst_unitl %ul", __FUNCTION__, offset, dst_until); + DEBUG_DEBUG("TimeService::%s offset: %d dst_unitl %ul", __FUNCTION__, offset, dst_until); _timezone_offset = offset; _timezone_dst_until = dst_until; _is_tz_configured = true; @@ -196,21 +196,21 @@ unsigned long TimeService::getTimeFromString(const String& input) static const int expected_parameters = 6; if(input == nullptr || input.length() != expected_length) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s invalid input length", __FUNCTION__); + DEBUG_ERROR("TimeService::%s invalid input length", __FUNCTION__); return 0; } int scanned_parameters = sscanf(input.c_str(), "%d %s %d %d:%d:%d", &year, s_month, &day, &hour, &min, &sec); if(scanned_parameters != expected_parameters) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s invalid input parameters number", __FUNCTION__); + DEBUG_ERROR("TimeService::%s invalid input parameters number", __FUNCTION__); return 0; } char * s_month_position = strstr(month_names, s_month); if(s_month_position == nullptr || strlen(s_month) != 3) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s invalid month name, use %s", __FUNCTION__, month_names); + DEBUG_ERROR("TimeService::%s invalid month name, use %s", __FUNCTION__, month_names); return 0; } @@ -218,7 +218,7 @@ unsigned long TimeService::getTimeFromString(const String& input) if(month < 0 || month > 11 || day < 1 || day > 31 || year < 1900 || hour < 0 || hour > 24 || min < 0 || min > 60 || sec < 0 || sec > 60) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s invalid date values", __FUNCTION__); + DEBUG_ERROR("TimeService::%s invalid date values", __FUNCTION__); return 0; } From 56de2c15f0f39ec467a98e17c34db9ba6bdeebe4 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 20 Jan 2023 17:15:58 +0100 Subject: [PATCH 404/780] Do not build code not compatible with LORA devices --- src/utility/time/TimeService.cpp | 14 +++++++++++--- src/utility/time/TimeService.h | 8 +++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 8341b09ee..ea9bc8275 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -105,8 +105,10 @@ TimeService::TimeService() , _is_tz_configured(false) , _timezone_offset(0) , _timezone_dst_until(0) +#ifdef HAS_TCP , _last_ntp_sync_tick(0) , _ntp_sync_interval_ms(TIMESERVICE_NTP_SYNC_TIMEOUT_ms) +#endif { } @@ -123,6 +125,7 @@ void TimeService::begin(ConnectionHandler * con_hdl) unsigned long TimeService::getTime() { +#ifdef HAS_TCP /* Check if it's time to sync */ unsigned long const current_tick = millis(); bool const is_ntp_sync_timeout = (current_tick - _last_ntp_sync_tick) > _ntp_sync_interval_ms; @@ -133,8 +136,12 @@ unsigned long TimeService::getTime() /* Read time from RTC */ unsigned long utc = getRTC(); return isTimeValid(utc) ? utc : EPOCH_AT_COMPILE_TIME; +#else + return EPOCH_AT_COMPILE_TIME; +#endif } +#ifdef HAS_TCP bool TimeService::sync() { _is_rtc_configured = false; @@ -153,6 +160,7 @@ void TimeService::setSyncInterval(unsigned long seconds) { _ntp_sync_interval_ms = seconds * 1000; } +#endif void TimeService::setTimeZoneData(long offset, unsigned long dst_until) { @@ -236,6 +244,7 @@ unsigned long TimeService::getTimeFromString(const String& input) * PRIVATE MEMBER FUNCTIONS **************************************************************************************/ +#ifdef HAS_TCP bool TimeService::connected() { if(_con_hdl == nullptr) { @@ -247,7 +256,6 @@ bool TimeService::connected() unsigned long TimeService::getRemoteTime() { -#ifndef HAS_LORA if(connected()) { /* At first try to see if a valid time can be obtained * using the network time available via the connection @@ -269,8 +277,6 @@ unsigned long TimeService::getRemoteTime() #endif } -#endif /* ifndef HAS_LORA */ - /* Return the epoch timestamp at compile time as a last * line of defense. Otherwise the certificate expiration * date is wrong and we'll be unable to establish a connection @@ -279,6 +285,8 @@ unsigned long TimeService::getRemoteTime() return EPOCH_AT_COMPILE_TIME; } +#endif /* HAS_TCP */ + bool TimeService::isTimeValid(unsigned long const time) { return (time > EPOCH_AT_COMPILE_TIME); diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 43fa2d4a8..149ff1c83 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -22,6 +22,7 @@ * INCLUDE **************************************************************************************/ +#include #include /************************************************************************************** @@ -39,7 +40,9 @@ class TimeService unsigned long getTime(); unsigned long getLocalTime(); void setTimeZoneData(long offset, unsigned long valid_until); +#ifdef HAS_TCP bool sync(); +#endif void setSyncInterval(unsigned long seconds); /* Helper function to convert an input String into a UNIX timestamp. @@ -54,12 +57,15 @@ class TimeService bool _is_tz_configured; long _timezone_offset; unsigned long _timezone_dst_until; +#ifdef HAS_TCP unsigned long _last_ntp_sync_tick; unsigned long _ntp_sync_interval_ms; +#endif +#ifdef HAS_TCP unsigned long getRemoteTime(); bool connected(); - static bool isTimeValid(unsigned long const time); +#endif void initRTC(); void setRTC(unsigned long time); unsigned long getRTC(); From 7cd0f63a58081447ff9d331c0fce9481a9f0ac11 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 20 Jan 2023 17:20:31 +0100 Subject: [PATCH 405/780] Config RTC for LoRa devices using EPOCH_AT_COMPILE_TIME --- src/utility/time/TimeService.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index ea9bc8275..a0784e785 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -121,11 +121,13 @@ void TimeService::begin(ConnectionHandler * con_hdl) { _con_hdl = con_hdl; initRTC(); +#ifdef HAS_LORA + setRTC(EPOCH_AT_COMPILE_TIME); +#endif } unsigned long TimeService::getTime() { -#ifdef HAS_TCP /* Check if it's time to sync */ unsigned long const current_tick = millis(); bool const is_ntp_sync_timeout = (current_tick - _last_ntp_sync_tick) > _ntp_sync_interval_ms; @@ -136,16 +138,25 @@ unsigned long TimeService::getTime() /* Read time from RTC */ unsigned long utc = getRTC(); return isTimeValid(utc) ? utc : EPOCH_AT_COMPILE_TIME; -#else - return EPOCH_AT_COMPILE_TIME; -#endif } #ifdef HAS_TCP bool TimeService::sync() { _is_rtc_configured = false; - unsigned long utc = getRemoteTime(); + + unsigned long utc = EPOCH_AT_COMPILE_TIME; + if(_sync_func) { + utc = _sync_func(); + } else { +#ifdef HAS_TCP + utc = getRemoteTime(); +#endif +#ifdef HAS_LORA + /* Just keep incrementing stored RTC value*/ + utc = getRTC(); +#endif + } if(isTimeValid(utc)) { DEBUG_DEBUG("TimeServiceClass::%s Drift: %d RTC value: %u", __FUNCTION__, getRTC() - utc, utc); From a51b2d5c6a252d2a6111c96a39f3ee232044b5b0 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 20 Jan 2023 17:22:32 +0100 Subject: [PATCH 406/780] Add function to set internal time --- src/utility/time/TimeService.cpp | 5 +++++ src/utility/time/TimeService.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index a0784e785..26920d458 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -140,6 +140,11 @@ unsigned long TimeService::getTime() return isTimeValid(utc) ? utc : EPOCH_AT_COMPILE_TIME; } +void TimeService::setTime(unsigned long time) +{ + setRTC(time); +} + #ifdef HAS_TCP bool TimeService::sync() { diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 149ff1c83..743500ac2 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -38,6 +38,7 @@ class TimeService void begin (ConnectionHandler * con_hdl); unsigned long getTime(); + void setTime(unsigned long time); unsigned long getLocalTime(); void setTimeZoneData(long offset, unsigned long valid_until); #ifdef HAS_TCP From c9cfdbe79907f9903bdb83586f41db351504278e Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 20 Jan 2023 17:45:24 +0100 Subject: [PATCH 407/780] Add possibility to configure a custom time sync function --- src/utility/time/TimeService.cpp | 22 +++++++++++++--------- src/utility/time/TimeService.h | 16 ++++++++++------ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 26920d458..c54a14d31 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -105,10 +105,9 @@ TimeService::TimeService() , _is_tz_configured(false) , _timezone_offset(0) , _timezone_dst_until(0) -#ifdef HAS_TCP -, _last_ntp_sync_tick(0) -, _ntp_sync_interval_ms(TIMESERVICE_NTP_SYNC_TIMEOUT_ms) -#endif +, _last_sync_tick(0) +, _sync_interval_ms(TIMESERVICE_NTP_SYNC_TIMEOUT_ms) +, _sync_func(nullptr) { } @@ -130,7 +129,7 @@ unsigned long TimeService::getTime() { /* Check if it's time to sync */ unsigned long const current_tick = millis(); - bool const is_ntp_sync_timeout = (current_tick - _last_ntp_sync_tick) > _ntp_sync_interval_ms; + bool const is_ntp_sync_timeout = (current_tick - _last_sync_tick) > _sync_interval_ms; if(!_is_rtc_configured || is_ntp_sync_timeout) { sync(); } @@ -145,7 +144,6 @@ void TimeService::setTime(unsigned long time) setRTC(time); } -#ifdef HAS_TCP bool TimeService::sync() { _is_rtc_configured = false; @@ -166,7 +164,7 @@ bool TimeService::sync() if(isTimeValid(utc)) { DEBUG_DEBUG("TimeServiceClass::%s Drift: %d RTC value: %u", __FUNCTION__, getRTC() - utc, utc); setRTC(utc); - _last_ntp_sync_tick = millis(); + _last_sync_tick = millis(); _is_rtc_configured = true; } return _is_rtc_configured; @@ -174,9 +172,15 @@ bool TimeService::sync() void TimeService::setSyncInterval(unsigned long seconds) { - _ntp_sync_interval_ms = seconds * 1000; + _sync_interval_ms = seconds * 1000; +} + +void TimeService::setSyncFunction(syncTimeFunctionPtr sync_func) +{ + if(sync_func) { + _sync_func = sync_func; + } } -#endif void TimeService::setTimeZoneData(long offset, unsigned long dst_until) { diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 743500ac2..b48019a6e 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -25,6 +25,12 @@ #include #include +/****************************************************************************** + * TYPEDEF + ******************************************************************************/ + +typedef unsigned long(*syncTimeFunctionPtr)(void); + /************************************************************************************** * CLASS DECLARATION **************************************************************************************/ @@ -41,10 +47,9 @@ class TimeService void setTime(unsigned long time); unsigned long getLocalTime(); void setTimeZoneData(long offset, unsigned long valid_until); -#ifdef HAS_TCP bool sync(); -#endif void setSyncInterval(unsigned long seconds); + void setSyncFunction(syncTimeFunctionPtr sync_func); /* Helper function to convert an input String into a UNIX timestamp. * The input String format must be as follow "2021 Nov 01 17:00:00" @@ -58,10 +63,9 @@ class TimeService bool _is_tz_configured; long _timezone_offset; unsigned long _timezone_dst_until; -#ifdef HAS_TCP - unsigned long _last_ntp_sync_tick; - unsigned long _ntp_sync_interval_ms; -#endif + unsigned long _last_sync_tick; + unsigned long _sync_interval_ms; + syncTimeFunctionPtr _sync_func; #ifdef HAS_TCP unsigned long getRemoteTime(); From fa22ff8372440f078361730664e0dab4be1060b5 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 7 Feb 2023 17:06:32 +0100 Subject: [PATCH 408/780] Switch to TimeServiceClass Rename TimeService into TimeServiceClass and use a more standard way to instantiate it. --- extras/test/src/test_CloudSchedule.cpp | 14 +++++-- extras/test/src/util/PropertyTestUtil.cpp | 5 --- src/ArduinoIoTCloud.cpp | 2 +- src/ArduinoIoTCloud.h | 2 +- src/property/types/CloudSchedule.h | 3 +- src/utility/time/TimeService.cpp | 51 ++++++++++++----------- src/utility/time/TimeService.h | 10 +++-- 7 files changed, 46 insertions(+), 41 deletions(-) diff --git a/extras/test/src/test_CloudSchedule.cpp b/extras/test/src/test_CloudSchedule.cpp index 88acad6ab..b8c3c0999 100644 --- a/extras/test/src/test_CloudSchedule.cpp +++ b/extras/test/src/test_CloudSchedule.cpp @@ -13,16 +13,22 @@ unsigned long time_now = 1; /************************************************************************************** - * TimeService Fake CTOR/DTOR + * TimeServiceClass Fake CTOR **************************************************************************************/ -TimeService::TimeService() {} +TimeServiceClass::TimeServiceClass() {} /************************************************************************************** - * TimeService Fake Methods + * TimeServiceClass Fake Methods **************************************************************************************/ -unsigned long TimeService::getLocalTime() {return time_now;} +unsigned long TimeServiceClass::getLocalTime() {return time_now;} + +/************************************************************************************** + * TimeService Fake local instance + **************************************************************************************/ + +TimeServiceClass TimeService; /************************************************************************************** TEST CODE diff --git a/extras/test/src/util/PropertyTestUtil.cpp b/extras/test/src/util/PropertyTestUtil.cpp index ca71cd765..1bf41c437 100644 --- a/extras/test/src/util/PropertyTestUtil.cpp +++ b/extras/test/src/util/PropertyTestUtil.cpp @@ -18,8 +18,3 @@ unsigned long getTime() { return 0; } - -TimeService & ArduinoIoTCloudTimeService() { - static TimeService _timeService_instance; - return _timeService_instance; -} diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 7763dd1f5..4997ec9b3 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -28,7 +28,7 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() : _connection{nullptr} , _last_checked_property_index{0} -, _time_service(ArduinoIoTCloudTimeService()) +, _time_service(TimeService) , _tz_offset{0} , _tz_dst_until{0} , _thing_id{""} diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 717bce0fa..bce662eb6 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -156,7 +156,7 @@ class ArduinoIoTCloudClass PropertyContainer _device_property_container; PropertyContainer _thing_property_container; unsigned int _last_checked_property_index; - TimeService & _time_service; + TimeServiceClass & _time_service; int _tz_offset; unsigned int _tz_dst_until; String _thing_id; diff --git a/src/property/types/CloudSchedule.h b/src/property/types/CloudSchedule.h index ecf6345ec..9a9222968 100644 --- a/src/property/types/CloudSchedule.h +++ b/src/property/types/CloudSchedule.h @@ -115,7 +115,7 @@ class Schedule { bool isActive() { - ScheduleTimeType now = _schedule_time_service.getLocalTime(); + ScheduleTimeType now = TimeService.getLocalTime(); if(checkTimeValid(now)) { /* We have to wait RTC configuration and Timezone setting from the cloud */ @@ -201,7 +201,6 @@ class Schedule { return !(operator==(aSchedule)); } private: - TimeService & _schedule_time_service = ArduinoIoTCloudTimeService(); ScheduleUnit getScheduleUnit(ScheduleConfigurationType msk) { return static_cast((msk & SCHEDULE_UNIT_MASK) >> SCHEDULE_UNIT_SHIFT); diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index c54a14d31..24856c14f 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -99,7 +99,7 @@ static time_t const EPOCH = 0; * CTOR/DTOR **************************************************************************************/ -TimeService::TimeService() +TimeServiceClass::TimeServiceClass() : _con_hdl(nullptr) , _is_rtc_configured(false) , _is_tz_configured(false) @@ -116,7 +116,7 @@ TimeService::TimeService() * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -void TimeService::begin(ConnectionHandler * con_hdl) +void TimeServiceClass::begin(ConnectionHandler * con_hdl) { _con_hdl = con_hdl; initRTC(); @@ -125,7 +125,7 @@ void TimeService::begin(ConnectionHandler * con_hdl) #endif } -unsigned long TimeService::getTime() +unsigned long TimeServiceClass::getTime() { /* Check if it's time to sync */ unsigned long const current_tick = millis(); @@ -139,12 +139,12 @@ unsigned long TimeService::getTime() return isTimeValid(utc) ? utc : EPOCH_AT_COMPILE_TIME; } -void TimeService::setTime(unsigned long time) +void TimeServiceClass::setTime(unsigned long time) { setRTC(time); } -bool TimeService::sync() +bool TimeServiceClass::sync() { _is_rtc_configured = false; @@ -170,29 +170,29 @@ bool TimeService::sync() return _is_rtc_configured; } -void TimeService::setSyncInterval(unsigned long seconds) +void TimeServiceClass::setSyncInterval(unsigned long seconds) { _sync_interval_ms = seconds * 1000; } -void TimeService::setSyncFunction(syncTimeFunctionPtr sync_func) +void TimeServiceClass::setSyncFunction(syncTimeFunctionPtr sync_func) { if(sync_func) { _sync_func = sync_func; } } -void TimeService::setTimeZoneData(long offset, unsigned long dst_until) +void TimeServiceClass::setTimeZoneData(long offset, unsigned long dst_until) { if(_timezone_offset != offset || _timezone_dst_until != dst_until) { - DEBUG_DEBUG("TimeService::%s offset: %d dst_unitl %ul", __FUNCTION__, offset, dst_until); + DEBUG_DEBUG("TimeServiceClass::%s offset: %d dst_unitl %ul", __FUNCTION__, offset, dst_until); _timezone_offset = offset; _timezone_dst_until = dst_until; _is_tz_configured = true; } } -unsigned long TimeService::getLocalTime() +unsigned long TimeServiceClass::getLocalTime() { unsigned long utc = getTime(); if(_is_tz_configured) { @@ -202,7 +202,7 @@ unsigned long TimeService::getLocalTime() } } -unsigned long TimeService::getTimeFromString(const String& input) +unsigned long TimeServiceClass::getTimeFromString(const String& input) { struct tm t = { @@ -224,21 +224,21 @@ unsigned long TimeService::getTimeFromString(const String& input) static const int expected_parameters = 6; if(input == nullptr || input.length() != expected_length) { - DEBUG_ERROR("TimeService::%s invalid input length", __FUNCTION__); + DEBUG_ERROR("TimeServiceClass::%s invalid input length", __FUNCTION__); return 0; } int scanned_parameters = sscanf(input.c_str(), "%d %s %d %d:%d:%d", &year, s_month, &day, &hour, &min, &sec); if(scanned_parameters != expected_parameters) { - DEBUG_ERROR("TimeService::%s invalid input parameters number", __FUNCTION__); + DEBUG_ERROR("TimeServiceClass::%s invalid input parameters number", __FUNCTION__); return 0; } char * s_month_position = strstr(month_names, s_month); if(s_month_position == nullptr || strlen(s_month) != 3) { - DEBUG_ERROR("TimeService::%s invalid month name, use %s", __FUNCTION__, month_names); + DEBUG_ERROR("TimeServiceClass::%s invalid month name, use %s", __FUNCTION__, month_names); return 0; } @@ -246,7 +246,7 @@ unsigned long TimeService::getTimeFromString(const String& input) if(month < 0 || month > 11 || day < 1 || day > 31 || year < 1900 || hour < 0 || hour > 24 || min < 0 || min > 60 || sec < 0 || sec > 60) { - DEBUG_ERROR("TimeService::%s invalid date values", __FUNCTION__); + DEBUG_ERROR("TimeServiceClass::%s invalid date values", __FUNCTION__); return 0; } @@ -265,7 +265,7 @@ unsigned long TimeService::getTimeFromString(const String& input) **************************************************************************************/ #ifdef HAS_TCP -bool TimeService::connected() +bool TimeServiceClass::connected() { if(_con_hdl == nullptr) { return false; @@ -274,7 +274,7 @@ bool TimeService::connected() } } -unsigned long TimeService::getRemoteTime() +unsigned long TimeServiceClass::getRemoteTime() { if(connected()) { /* At first try to see if a valid time can be obtained @@ -307,12 +307,12 @@ unsigned long TimeService::getRemoteTime() #endif /* HAS_TCP */ -bool TimeService::isTimeValid(unsigned long const time) +bool TimeServiceClass::isTimeValid(unsigned long const time) { return (time > EPOCH_AT_COMPILE_TIME); } -void TimeService::initRTC() +void TimeServiceClass::initRTC() { #if defined (ARDUINO_ARCH_SAMD) samd_initRTC(); @@ -329,7 +329,7 @@ void TimeService::initRTC() #endif } -void TimeService::setRTC(unsigned long time) +void TimeServiceClass::setRTC(unsigned long time) { #if defined (ARDUINO_ARCH_SAMD) samd_setRTC(time); @@ -346,7 +346,7 @@ void TimeService::setRTC(unsigned long time) #endif } -unsigned long TimeService::getRTC() +unsigned long TimeServiceClass::getRTC() { #if defined (ARDUINO_ARCH_SAMD) return samd_getRTC(); @@ -483,7 +483,8 @@ unsigned long esp8266_getRTC() } #endif -TimeService & ArduinoIoTCloudTimeService() { - static TimeService _timeService_instance; - return _timeService_instance; -} +/****************************************************************************** + * EXTERN DEFINITION + ******************************************************************************/ + +TimeServiceClass TimeService; diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index b48019a6e..7f6529ecf 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -35,12 +35,12 @@ typedef unsigned long(*syncTimeFunctionPtr)(void); * CLASS DECLARATION **************************************************************************************/ -class TimeService +class TimeServiceClass { public: - TimeService(); + TimeServiceClass(); void begin (ConnectionHandler * con_hdl); unsigned long getTime(); @@ -77,6 +77,10 @@ class TimeService }; -TimeService & ArduinoIoTCloudTimeService(); +/****************************************************************************** + * EXTERN DECLARATION + ******************************************************************************/ + +extern TimeServiceClass TimeService; #endif /* ARDUINO_IOT_CLOUD_TIME_SERVICE_H_ */ From 3c069770354fe3d737174bc9b54b875668580d2e Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 8 Feb 2023 14:29:13 +0100 Subject: [PATCH 409/780] Check Timezone offset boundaries --- src/utility/time/TimeService.cpp | 20 ++++++++++++++------ src/utility/time/TimeService.h | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 24856c14f..0b0b982fc 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -103,7 +103,7 @@ TimeServiceClass::TimeServiceClass() : _con_hdl(nullptr) , _is_rtc_configured(false) , _is_tz_configured(false) -, _timezone_offset(0) +, _timezone_offset(24 * 60 * 60) , _timezone_dst_until(0) , _last_sync_tick(0) , _sync_interval_ms(TIMESERVICE_NTP_SYNC_TIMEOUT_ms) @@ -184,11 +184,13 @@ void TimeServiceClass::setSyncFunction(syncTimeFunctionPtr sync_func) void TimeServiceClass::setTimeZoneData(long offset, unsigned long dst_until) { - if(_timezone_offset != offset || _timezone_dst_until != dst_until) { - DEBUG_DEBUG("TimeServiceClass::%s offset: %d dst_unitl %ul", __FUNCTION__, offset, dst_until); - _timezone_offset = offset; - _timezone_dst_until = dst_until; - _is_tz_configured = true; + if(isTimeZoneOffsetValid(offset) && isTimeValid(dst_until)) { + if(_timezone_offset != offset || _timezone_dst_until != dst_until) { + DEBUG_DEBUG("TimeServiceClass::%s offset: %d dst_unitl %u", __FUNCTION__, offset, dst_until); + _timezone_offset = offset; + _timezone_dst_until = dst_until; + _is_tz_configured = true; + } } } @@ -312,6 +314,12 @@ bool TimeServiceClass::isTimeValid(unsigned long const time) return (time > EPOCH_AT_COMPILE_TIME); } +bool TimeServiceClass::isTimeZoneOffsetValid(long const offset) +{ + /* UTC offset can go from +14 to -12 hours */ + return ((offset < (14 * 60 * 60)) && (offset > (-12 * 60 * 60))); +} + void TimeServiceClass::initRTC() { #if defined (ARDUINO_ARCH_SAMD) diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 7f6529ecf..6e6af6bb5 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -74,6 +74,8 @@ class TimeServiceClass void initRTC(); void setRTC(unsigned long time); unsigned long getRTC(); + static bool isTimeValid(unsigned long const time); + static bool isTimeZoneOffsetValid(long const offset); }; From 77ea16daf1a7152ba07d73f51be79856f8b483ba Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 17 Feb 2023 10:49:03 +0100 Subject: [PATCH 410/780] NTPUtils use hardware random number generator for ESP boards --- src/utility/time/NTPUtils.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/utility/time/NTPUtils.cpp b/src/utility/time/NTPUtils.cpp index 9ce276c8c..24c626a73 100644 --- a/src/utility/time/NTPUtils.cpp +++ b/src/utility/time/NTPUtils.cpp @@ -92,8 +92,11 @@ void NTPUtils::sendNTPpacket(UDP & udp) int NTPUtils::getRandomPort(int const min_port, int const max_port) { -#ifdef BOARD_HAS_ECCX08 +#if defined (BOARD_HAS_ECCX08) return ECCX08.random(min_port, max_port); +#elif defined (ARDUINO_ARCH_ESP8266) || (ARDUINO_ARCH_ESP32) + /* Uses HW Random Number Generator */ + return random(min_port, max_port); #else randomSeed(analogRead(0)); return random(min_port, max_port); From d3db39e3b7b158cfe43ceac6fc5d97b1585170e6 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 26 Feb 2023 12:40:38 +0100 Subject: [PATCH 411/780] Add Arduino_ESP32_OTA to library dependencies --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 6a7bdfb00..158bdc59d 100644 --- a/library.properties +++ b/library.properties @@ -8,4 +8,4 @@ category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta includes=ArduinoIoTCloud.h -depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library +depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,Arduino_ESP32_OTA From b9bfb27eb26fdca32676e4f535e359f029a1ff90 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Tue, 28 Feb 2023 10:36:51 +0100 Subject: [PATCH 412/780] Add Arduino_Portenta_OTA to library dependencies --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 158bdc59d..128232682 100644 --- a/library.properties +++ b/library.properties @@ -8,4 +8,4 @@ category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta includes=ArduinoIoTCloud.h -depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,Arduino_ESP32_OTA +depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,Arduino_ESP32_OTA,Arduino_Portenta_OTA From 91e9d26e9170c3bf688418da540e08bb8bd9207e Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 6 Jul 2022 16:51:58 +0200 Subject: [PATCH 413/780] Use NTP as primary time source and connection handler as fallback --- src/utility/time/TimeService.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 0b0b982fc..a9536caa0 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -279,24 +279,24 @@ bool TimeServiceClass::connected() unsigned long TimeServiceClass::getRemoteTime() { if(connected()) { - /* At first try to see if a valid time can be obtained - * using the network time available via the connection - * handler. - */ - unsigned long const connection_time = _con_hdl->getTime(); - if(isTimeValid(connection_time)) { - return connection_time; - } - #ifndef __AVR__ - /* If no valid network time is available try to obtain the - * time via NTP next. + /* At first try to obtain a valid time via NTP. + * This is the most reliable time source and it will + * ensure a correct behaviour of the library. */ unsigned long const ntp_time = NTPUtils::getTime(_con_hdl->getUDP()); if(isTimeValid(ntp_time)) { return ntp_time; } #endif + + /* As fallback if NTP request fails try to obtain the + * network time using the connection handler. + */ + unsigned long const connection_time = _con_hdl->getTime(); + if(isTimeValid(connection_time)) { + return connection_time; + } } /* Return the epoch timestamp at compile time as a last From 11e875b5c20981723dd40d6e9b117c47fbc2d7af Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 20 Dec 2022 15:00:32 +0100 Subject: [PATCH 414/780] Add support for giga board --- extras/tools/bin2ota.py | 4 +++- library.properties | 2 +- src/AIoTC_Config.h | 7 ++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/extras/tools/bin2ota.py b/extras/tools/bin2ota.py index 32c3bfe1d..651a51740 100755 --- a/extras/tools/bin2ota.py +++ b/extras/tools/bin2ota.py @@ -5,7 +5,7 @@ if len(sys.argv) != 4: print ("Usage: bin2ota.py BOARD sketch.bin sketch.ota") - print (" BOARD = [MKR_WIFI_1010 | NANO_33_IOT | PORTENTA_H7_M7 | NANO_RP2040_CONNECT | NICLA_VISION | OPTA ]") + print (" BOARD = [ MKR_WIFI_1010 | NANO_33_IOT | PORTENTA_H7_M7 | NANO_RP2040_CONNECT | NICLA_VISION | OPTA | GIGA ]") sys.exit() board = sys.argv[1] @@ -30,6 +30,8 @@ magic_number = 0x2341025F.to_bytes(4,byteorder='little') elif board == "OPTA": magic_number = 0x23410064.to_bytes(4,byteorder='little') +elif board == "GIGA": + magic_number = 0x23410266.to_bytes(4,byteorder='little') # Magic number for all ESP32 boards not related to (VID/PID) elif board == "ESP32": magic_number = 0x45535033.to_bytes(4,byteorder='little') diff --git a/library.properties b/library.properties index 128232682..26369e2d2 100644 --- a/library.properties +++ b/library.properties @@ -6,6 +6,6 @@ sentence=This library allows connecting to the Arduino IoT Cloud service. paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKR GSM, MKR1000 and WiFi101. category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud -architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta +architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta,mbed_giga includes=ArduinoIoTCloud.h depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,Arduino_ESP32_OTA,Arduino_Portenta_OTA diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index e734ecf2c..02194f5d3 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -102,7 +102,7 @@ #define OTA_STORAGE_SSU (0) #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_OPTA) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_OPTA) || defined(ARDUINO_GIGA) #define OTA_STORAGE_PORTENTA_QSPI (1) #else #define OTA_STORAGE_PORTENTA_QSPI (0) @@ -120,7 +120,8 @@ #if defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKR1000) || \ defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_PORTENTA_H7_M7) || \ - defined (ARDUINO_NANO_RP2040_CONNECT) || defined(ARDUINO_OPTA) + defined (ARDUINO_NANO_RP2040_CONNECT) || defined(ARDUINO_OPTA) || \ + defined(ARDUINO_GIGA) #define BOARD_HAS_ECCX08 #define HAS_TCP #endif @@ -145,7 +146,7 @@ #define HAS_TCP #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_OPTA) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_OPTA) || defined(ARDUINO_GIGA) #define BOARD_STM32H7 #endif From 6d02b1939d0516e31d7ff2f34aaebb9c892aefbf Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 3 Mar 2023 10:19:45 +0100 Subject: [PATCH 415/780] Enable CI for GIGA --- .github/workflows/compile-examples.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 8a24fdce9..2477ab652 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -60,6 +60,9 @@ jobs: type: mbed_nicla - fqbn: arduino:mbed_opta:opta type: mbed_opta + - fqbn: arduino:mbed_giga:giga + type: mbed_giga + # make board type-specific customizations to the matrix jobs include: @@ -161,6 +164,17 @@ jobs: - name: Arduino_Portenta_OTA sketch-paths: | - examples/utility/Provisioning + # GIGA + - board: + type: mbed_giga + platforms: | + # Install mbed_giga platform via Boards Manager + - name: arduino:mbed_giga + libraries: | + - name: ArduinoECCX08 + - name: Arduino_Portenta_OTA + sketch-paths: | + - examples/utility/Provisioning # ESP8266 boards - board: type: esp8266 From 89d3c92c86ecfef63868ac8d8e161e4fe4543001 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 6 Mar 2023 09:09:14 +0100 Subject: [PATCH 416/780] Release v1.11.0 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 26369e2d2..5204938ca 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.10.0 +version=1.11.0 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 02194f5d3..41abcb7d9 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -167,6 +167,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.10.0" +#define AIOT_CONFIG_LIB_VERSION "1.11.0" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 068107a53476a7e028f8d8749635e201874a794e Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 27 Apr 2023 09:26:30 +0200 Subject: [PATCH 417/780] TimeService: Fix esp8266 time drift --- src/utility/time/RTCMillis.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/utility/time/RTCMillis.cpp b/src/utility/time/RTCMillis.cpp index ae17487ef..419236d16 100644 --- a/src/utility/time/RTCMillis.cpp +++ b/src/utility/time/RTCMillis.cpp @@ -54,9 +54,8 @@ unsigned long RTCMillis::get() { unsigned long current_tick = millis(); unsigned long const elapsed_s = (current_tick - _last_rtc_update_tick) / 1000; - if(elapsed_s) { - set(_last_rtc_update_value + elapsed_s); - } + _last_rtc_update_value += elapsed_s; + _last_rtc_update_tick += elapsed_s * 1000; return _last_rtc_update_value; } From dc80f9e2e5c41bd103c31730408ce0af73422499 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 15 May 2023 09:35:56 +0200 Subject: [PATCH 418/780] Release v1.11.1 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 5204938ca..3b15b8af5 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.11.0 +version=1.11.1 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 41abcb7d9..f169ecbd3 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -167,6 +167,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.11.0" +#define AIOT_CONFIG_LIB_VERSION "1.11.1" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 1194620ddee61a03763482bcaed3fa1d3e9fe8e7 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 May 2023 09:51:36 +0200 Subject: [PATCH 419/780] Substitute BOARD_ESP with BOARD_HAS_SECRET_KEY --- examples/ArduinoIoTCloud-Advanced/arduino_secrets.h | 2 +- examples/ArduinoIoTCloud-Advanced/thingProperties.h | 4 ++-- examples/ArduinoIoTCloud-Basic/arduino_secrets.h | 2 +- examples/ArduinoIoTCloud-Basic/thingProperties.h | 4 ++-- examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h | 2 +- examples/ArduinoIoTCloud-Callbacks/thingProperties.h | 4 ++-- examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h | 2 +- examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h | 4 ++-- examples/ArduinoIoTCloud-Schedule/arduino_secrets.h | 2 +- examples/ArduinoIoTCloud-Schedule/thingProperties.h | 4 ++-- .../utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h | 2 +- .../utility/ArduinoIoTCloud_Travis_CI/thingProperties.h | 4 ++-- src/AIoTC_Config.h | 2 +- src/ArduinoIoTCloudTCP.cpp | 6 +++--- src/ArduinoIoTCloudTCP.h | 6 +++--- 15 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h index d1615135f..09ea8323a 100644 --- a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h @@ -10,7 +10,7 @@ #endif /* ESP8266 ESP32*/ -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index f8d7bb506..fd4b2ce69 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -7,7 +7,7 @@ #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #endif @@ -19,7 +19,7 @@ CloudLocation location; CloudColor color; void initProperties() { -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif diff --git a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h index d1615135f..09ea8323a 100644 --- a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h @@ -10,7 +10,7 @@ #endif /* ESP8266 ESP32*/ -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index e11eaf81f..b10ac85fc 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -7,7 +7,7 @@ #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #endif @@ -18,7 +18,7 @@ int potentiometer; int seconds; void initProperties() { -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif diff --git a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h index d1615135f..09ea8323a 100644 --- a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h @@ -10,7 +10,7 @@ #endif /* ESP8266 ESP32*/ -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index d92788f98..f3de1a2ed 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -7,12 +7,12 @@ #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #endif void initProperties() { -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif diff --git a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h index d1615135f..09ea8323a 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h @@ -10,7 +10,7 @@ #endif /* ESP8266 ESP32*/ -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index 94b3b0ece..1570e4a1b 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -7,7 +7,7 @@ #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #endif @@ -16,7 +16,7 @@ void onLedChange(); bool led; void initProperties() { -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif diff --git a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h index d1615135f..09ea8323a 100644 --- a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h @@ -10,7 +10,7 @@ #endif /* ESP8266 ESP32*/ -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 940cb5c26..22a185b9c 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -7,7 +7,7 @@ #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #endif @@ -23,7 +23,7 @@ CloudSchedule monthly; CloudSchedule yearly; void initProperties() { -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h index d1615135f..09ea8323a 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h @@ -10,7 +10,7 @@ #endif /* ESP8266 ESP32*/ -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index eff3035bd..8a9ed4a28 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -11,7 +11,7 @@ DEFINES ******************************************************************************/ -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #endif @@ -79,7 +79,7 @@ void onStringPropertyChange(); ******************************************************************************/ #if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined (BOARD_HAS_NB) void initProperties() { -#if defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 41abcb7d9..3cf486063 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -142,7 +142,7 @@ #endif #if defined(ARDUINO_ESP8266_ESP12) || defined(ARDUINO_ARCH_ESP32) || defined(ESP8266) || defined(ESP32) - #define BOARD_ESP + #define BOARD_HAS_SECRET_KEY #define HAS_TCP #endif diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 5d0dd8f57..7feeb308e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -86,7 +86,7 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() #ifdef BOARD_HAS_ECCX08 , _sslClient(nullptr, ArduinoIoTCloudTrustAnchor, ArduinoIoTCloudTrustAnchor_NUM, getTime) #endif - #ifdef BOARD_ESP + #ifdef BOARD_HAS_SECRET_KEY , _password("") #endif , _mqttClient{nullptr} @@ -168,12 +168,12 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _sslClient.setClient(_connection->getClient()); #elif defined(BOARD_HAS_SE050) _sslClient.appendCustomCACert(AIoTSSCert); -#elif defined(BOARD_ESP) +#elif defined(BOARD_HAS_SECRET_KEY) _sslClient.setInsecure(); #endif _mqttClient.setClient(_sslClient); -#ifdef BOARD_ESP +#ifdef BOARD_HAS_SECRET_KEY _mqttClient.setUsernamePassword(getDeviceId(), _password); #endif _mqttClient.onMessage(ArduinoIoTCloudTCP::onMessage); diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index e8218c9e1..adc5c17e1 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -29,7 +29,7 @@ #ifdef BOARD_HAS_ECCX08 #include "tls/BearSSLClient.h" #include "tls/utility/CryptoUtil.h" -#elif defined(BOARD_ESP) +#elif defined(BOARD_HAS_SECRET_KEY) #include #elif defined(BOARD_HAS_SE050) #include "tls/utility/CryptoUtil.h" @@ -81,7 +81,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #endif int begin(bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH); - #ifdef BOARD_ESP + #ifdef BOARD_HAS_SECRET_KEY inline void setBoardId (String const device_id) { setDeviceId(device_id); } inline void setSecretDeviceKey(String const password) { _password = password; } #endif @@ -143,7 +143,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass ArduinoIoTCloudCertClass _cert; WiFiBearSSLClient _sslClient; CryptoUtil _crypto; - #elif defined(BOARD_ESP) + #elif defined(BOARD_HAS_SECRET_KEY) WiFiClientSecure _sslClient; String _password; #elif defined(BOARD_HAS_SE050) From ee8b8bfa9960fa381f16d4359717d9eaac952b1d Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 May 2023 09:53:45 +0200 Subject: [PATCH 420/780] Remove redundant ESP arch defines --- src/AIoTC_Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index f169ecbd3..d23269e18 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -141,7 +141,7 @@ #define HAS_LORA #endif -#if defined(ARDUINO_ESP8266_ESP12) || defined(ARDUINO_ARCH_ESP32) || defined(ESP8266) || defined(ESP32) +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) #define BOARD_ESP #define HAS_TCP #endif From 3df9d32d959c226550cd57f695db477d23ddc609 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 7 Jun 2023 09:33:15 +0200 Subject: [PATCH 421/780] Restore BOARD_ESP to handle board specific configurations --- src/AIoTC_Config.h | 1 + src/ArduinoIoTCloudTCP.cpp | 2 +- src/ArduinoIoTCloudTCP.h | 9 ++++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 3cf486063..f7f28931f 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -142,6 +142,7 @@ #endif #if defined(ARDUINO_ESP8266_ESP12) || defined(ARDUINO_ARCH_ESP32) || defined(ESP8266) || defined(ESP32) + #define BOARD_ESP #define BOARD_HAS_SECRET_KEY #define HAS_TCP #endif diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 7feeb308e..402dbf4e6 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -168,7 +168,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _sslClient.setClient(_connection->getClient()); #elif defined(BOARD_HAS_SE050) _sslClient.appendCustomCACert(AIoTSSCert); -#elif defined(BOARD_HAS_SECRET_KEY) +#elif defined(BOARD_ESP) _sslClient.setInsecure(); #endif diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index adc5c17e1..8f6337b36 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -29,7 +29,7 @@ #ifdef BOARD_HAS_ECCX08 #include "tls/BearSSLClient.h" #include "tls/utility/CryptoUtil.h" -#elif defined(BOARD_HAS_SECRET_KEY) +#elif defined(BOARD_ESP) #include #elif defined(BOARD_HAS_SE050) #include "tls/utility/CryptoUtil.h" @@ -143,15 +143,18 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass ArduinoIoTCloudCertClass _cert; WiFiBearSSLClient _sslClient; CryptoUtil _crypto; - #elif defined(BOARD_HAS_SECRET_KEY) + #elif defined(BOARD_ESP) WiFiClientSecure _sslClient; - String _password; #elif defined(BOARD_HAS_SE050) ArduinoIoTCloudCertClass _cert; WiFiSSLSE050Client _sslClient; CryptoUtil _crypto; #endif + #if defined (BOARD_HAS_SECRET_KEY) + String _password; + #endif + MqttClient _mqttClient; String _deviceTopicOut; From a34ce91e7a7087190a43c218fda122a2381b04ca Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 4 May 2023 08:55:18 +0200 Subject: [PATCH 422/780] Initial: Basic support for Portenta C33 RTC support and OTA support missing --- src/AIoTC_Config.h | 2 +- src/ArduinoIoTCloudTCP.cpp | 3 +++ src/ArduinoIoTCloudTCP.h | 7 +++++++ src/utility/time/TimeService.cpp | 9 ++++++--- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index f169ecbd3..4ae83767d 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -126,7 +126,7 @@ #define HAS_TCP #endif -#if defined(ARDUINO_NICLA_VISION) +#if defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_PORTENTA_C33) #define BOARD_HAS_SE050 #define HAS_TCP #endif diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 5d0dd8f57..2e8b1bea8 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -166,6 +166,9 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #if defined(BOARD_HAS_ECCX08) _sslClient.setClient(_connection->getClient()); +#elif defined(ARDUINO_PORTENTA_C33) + _sslClient.setClient(_connection->getClient()); + _sslClient.setCACert(AIoTSSCert); #elif defined(BOARD_HAS_SE050) _sslClient.appendCustomCACert(AIoTSSCert); #elif defined(BOARD_ESP) diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index e8218c9e1..54b0d34f4 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -31,6 +31,9 @@ #include "tls/utility/CryptoUtil.h" #elif defined(BOARD_ESP) #include +#elif defined(ARDUINO_PORTENTA_C33) + #include "tls/utility/CryptoUtil.h" + #include #elif defined(BOARD_HAS_SE050) #include "tls/utility/CryptoUtil.h" #include @@ -146,6 +149,10 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #elif defined(BOARD_ESP) WiFiClientSecure _sslClient; String _password; + #elif defined(ARDUINO_PORTENTA_C33) + ArduinoIoTCloudCertClass _cert; + SSLClient _sslClient; + CryptoUtil _crypto; #elif defined(BOARD_HAS_SE050) ArduinoIoTCloudCertClass _cert; WiFiSSLSE050Client _sslClient; diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index a9536caa0..3cae3eca1 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -330,8 +330,9 @@ void TimeServiceClass::initRTC() stm32h7_initRTC(); #elif defined (ARDUINO_ARCH_ESP32) esp32_initRTC(); -#elif ARDUINO_ARCH_ESP8266 +#elif defined (ARDUINO_ARCH_ESP8266) esp8266_initRTC(); +#elif defined (ARDUINO_PORTENTA_C33) #else #error "RTC not available for this architecture" #endif @@ -347,8 +348,9 @@ void TimeServiceClass::setRTC(unsigned long time) stm32h7_setRTC(time); #elif defined (ARDUINO_ARCH_ESP32) esp32_setRTC(time); -#elif ARDUINO_ARCH_ESP8266 +#elif defined (ARDUINO_ARCH_ESP8266) esp8266_setRTC(time); +#elif defined (ARDUINO_PORTENTA_C33) #else #error "RTC not available for this architecture" #endif @@ -364,8 +366,9 @@ unsigned long TimeServiceClass::getRTC() return stm32h7_getRTC(); #elif defined (ARDUINO_ARCH_ESP32) return esp32_getRTC(); -#elif ARDUINO_ARCH_ESP8266 +#elif defined (ARDUINO_ARCH_ESP8266) return esp8266_getRTC(); +#elif defined (ARDUINO_PORTENTA_C33) #else #error "RTC not available for this architecture" #endif From d85a55c1181cf20576ee3eaf24dcfc81280f28f5 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 12 Jun 2023 10:02:21 +0200 Subject: [PATCH 423/780] Portenta C33: Add RTC support --- src/utility/time/TimeService.cpp | 39 +++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 3cae3eca1..eeab3245d 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -38,6 +38,10 @@ #include "RTCMillis.h" #endif +#ifdef ARDUINO_ARCH_RENESAS + #include "RTC.h" +#endif + /************************************************************************************** * GLOBAL VARIABLES **************************************************************************************/ @@ -86,6 +90,12 @@ void esp8266_setRTC(unsigned long time); unsigned long esp8266_getRTC(); #endif +#ifdef ARDUINO_ARCH_RENESAS +void renesas_initRTC(); +void renesas_setRTC(unsigned long time); +unsigned long renesas_getRTC(); +#endif + /************************************************************************************** * CONSTANTS **************************************************************************************/ @@ -332,7 +342,8 @@ void TimeServiceClass::initRTC() esp32_initRTC(); #elif defined (ARDUINO_ARCH_ESP8266) esp8266_initRTC(); -#elif defined (ARDUINO_PORTENTA_C33) +#elif defined (ARDUINO_ARCH_RENESAS) + renesas_initRTC(); #else #error "RTC not available for this architecture" #endif @@ -350,7 +361,8 @@ void TimeServiceClass::setRTC(unsigned long time) esp32_setRTC(time); #elif defined (ARDUINO_ARCH_ESP8266) esp8266_setRTC(time); -#elif defined (ARDUINO_PORTENTA_C33) +#elif defined (ARDUINO_ARCH_RENESAS) + renesas_setRTC(time); #else #error "RTC not available for this architecture" #endif @@ -368,7 +380,8 @@ unsigned long TimeServiceClass::getRTC() return esp32_getRTC(); #elif defined (ARDUINO_ARCH_ESP8266) return esp8266_getRTC(); -#elif defined (ARDUINO_PORTENTA_C33) +#elif defined (ARDUINO_ARCH_RENESAS) + return renesas_getRTC(); #else #error "RTC not available for this architecture" #endif @@ -494,6 +507,26 @@ unsigned long esp8266_getRTC() } #endif +#ifdef ARDUINO_ARCH_RENESAS +void renesas_initRTC() +{ + RTC.begin(); +} + +void renesas_setRTC(unsigned long time) +{ + RTCTime t(time); + RTC.setTime(t); +} + +unsigned long renesas_getRTC() +{ + RTCTime t; + RTC.getTime(t); + return t.getUnixTime(); +} +#endif + /****************************************************************************** * EXTERN DEFINITION ******************************************************************************/ From 1b6b2a7abba9a266d737fba3500a50b5a8ae62d8 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 22 Jun 2023 17:05:38 +0200 Subject: [PATCH 424/780] Release v1.11.2 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 3b15b8af5..a9a450042 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.11.1 +version=1.11.2 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. From 080e1bcd0103671e1c7931b097af187a19daf5ae Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 28 Jun 2023 10:25:10 +0200 Subject: [PATCH 425/780] Add renesas_portenta architecture --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index a9a450042..243450928 100644 --- a/library.properties +++ b/library.properties @@ -6,6 +6,6 @@ sentence=This library allows connecting to the Arduino IoT Cloud service. paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKR GSM, MKR1000 and WiFi101. category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud -architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta,mbed_giga +architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta,mbed_giga,renesas_portenta includes=ArduinoIoTCloud.h depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,Arduino_ESP32_OTA,Arduino_Portenta_OTA From e48f8008cf841c4b00ac91dd1ac6da97dbdc3b97 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 28 Jun 2023 10:37:39 +0200 Subject: [PATCH 426/780] Enable compile example workflow for Portenta C33 --- .github/workflows/compile-examples.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 2477ab652..f5a039cbb 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -62,6 +62,8 @@ jobs: type: mbed_opta - fqbn: arduino:mbed_giga:giga type: mbed_giga + - fqbn: arduino:renesas_portenta:portenta_c33 + type: renesas_portenta # make board type-specific customizations to the matrix jobs @@ -175,6 +177,14 @@ jobs: - name: Arduino_Portenta_OTA sketch-paths: | - examples/utility/Provisioning + # Portneta C33 + - board: + type: renesas_portenta + platforms: | + # Install renesas_portenta platform via Boards Manager + - name: arduino:renesas_portenta + sketch-paths: | + - examples/utility/Provisioning # ESP8266 boards - board: type: esp8266 From 433e641af5a7b14e2a8ab12c4299de6b0521d519 Mon Sep 17 00:00:00 2001 From: per1234 Date: Wed, 28 Jun 2023 08:58:48 -0700 Subject: [PATCH 427/780] Bump `codecov/codecov-action` dependency to v3 The "Unit Test" GitHub Actions workflow uses the "codecov/codecov-action" GitHub Actions action to upload coverage data to Codecov. Previously the workflow specified the "v1" version ref for the action dependency. That pinned the dependency to the major version 1 series. Several major version bumps have been made in the action since that time so the use of the v1 ref caused the workflow to use a significantly outdated and deprecated version of the action. Bumping the action to the latest "v3" ref will avoid the potential for the step to stop working entirely (the action docs claim v1 was sunset 1.5 years ago) and allow the workflow to benefit from the enhancements and fixes from ongoing development work in the action until such time as a breaking change in the action triggers them to make another major version bump. At that time it will be necessary for the project maintainers to evaluate whether the breaking change requires any modifications to the workflow before manually bumping the ref again (i.e., `uses: codecov/codecov-action@v3` -> `uses: codecov/codecov-action@v4`). --- .github/workflows/unit-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index f3b66c2c8..13460c6a4 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -36,7 +36,7 @@ jobs: coverage-data-path: ${{ env.COVERAGE_DATA_PATH }} - name: Upload coverage report to Codecov - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v3 with: file: "${{ env.COVERAGE_DATA_PATH }}" fail_ci_if_error: true From 4b112e8bdcb016ed1de9bd4b111feffef602d613 Mon Sep 17 00:00:00 2001 From: per1234 Date: Wed, 28 Jun 2023 09:06:35 -0700 Subject: [PATCH 428/780] Use token when uploading unit test code coverage data to Codecov from workflow Codecov claims a token is not needed when using the codecov/codecov-action GitHub Actions action in workflows of a public repository: https://github.com/codecov/codecov-action#usage > For public repositories, no token is needed However, experience shows that that step of the workflow is subject to intermittent spurious failures caused by a 404 error during the upload attempt: ``` [2023-06-26T09:18:51.453Z] ['error'] There was an error running the uploader: Error uploading to https://codecov.io: Error: There was an error fetching the storage URL during POST: 404 - {'detail': ErrorDetail(string='Unable to locate build via Github Actions API. Please upload with the Codecov repository upload token to resolve issue.', code='not_found')} ``` It is suggested that this can be avoided by providing the upload token: https://community.codecov.com/t/upload-issues-unable-to-locate-build-via-github-actions-api/3954 It should be noted that PRs from forks do not have access to repository secrets, so the approach suggested there of using an encrypted repository secret for the token would mean that PRs from forks (the workflow runs for which don't have access to secrets) would still be subject to the same intermittent spurious workflow run failures. The alternative approach is to add the token in plaintext directly in the workflow. The security implications of that approach are described here: https://community.codecov.com/t/upload-issues-unable-to-locate-build-via-github-actions-api/3954 > Public repositories that rely on PRs via forks will find that they cannot effectively use Codecov if the token is > stored as a GitHub secret. The scope of the Codecov token is only to confirm that the coverage uploaded comes from a > specific repository, not to pull down source code or make any code changes. > > For this reason, we recommend that teams with public repositories that rely on PRs via forks consider the security > ramifications of making the Codecov token available as opposed to being in a secret. > > A malicious actor would be able to upload incorrect or misleading coverage reports to a specific repository if they > have access to your upload token, but would not be able to pull down source code or make any code changes. We have evaluated the risks of exposing the token and are intentionally choosing to accept the possibility of it being used by a malicious actor to upload incorrect coverage data for this project to Codecov. --- .github/workflows/unit-tests.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 13460c6a4..2b4283747 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -35,8 +35,23 @@ jobs: - '*/src/cbor/lib/*' coverage-data-path: ${{ env.COVERAGE_DATA_PATH }} + # A token is used to avoid intermittent spurious job failures caused by rate limiting. + - name: Set up Codecov upload token + run: | + if [[ "${{ github.repository }}" == "arduino-libraries/ArduinoIoTCloud" ]]; then + # In order to avoid uploads of data from forks, only use the token for runs in the parent repo. + # Token is intentionally exposed. + # See: https://community.codecov.com/t/upload-issues-unable-to-locate-build-via-github-actions-api/3954 + CODECOV_TOKEN="47827969-3fda-4ba1-9506-e8d0834ed88c" + else + # codecov/codecov-action does unauthenticated upload if empty string is passed via the `token` input. + CODECOV_TOKEN="" + fi + echo "CODECOV_TOKEN=$CODECOV_TOKEN" >> "$GITHUB_ENV" + - name: Upload coverage report to Codecov uses: codecov/codecov-action@v3 with: file: "${{ env.COVERAGE_DATA_PATH }}" fail_ci_if_error: true + token: ${{ env.CODECOV_TOKEN }} From 5784098c599b55463cce02e7dc8e926a883f9c59 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 28 Jun 2023 09:03:11 +0200 Subject: [PATCH 429/780] Add UNO R4 WiFi basic support --- src/AIoTC_Config.h | 5 +++++ src/ArduinoIoTCloudTCP.h | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 29bfb61f7..95ef1a93d 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -151,6 +151,11 @@ #define BOARD_STM32H7 #endif +#if defined(ARDUINO_UNOR4_WIFI) + #define BOARD_HAS_SECRET_KEY + #define HAS_TCP +#endif + /****************************************************************************** * CONSTANTS ******************************************************************************/ diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 4b4a186cc..f15f019da 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -31,6 +31,8 @@ #include "tls/utility/CryptoUtil.h" #elif defined(BOARD_ESP) #include +#elif defined(ARDUINO_UNOR4_WIFI) + #include #elif defined(ARDUINO_PORTENTA_C33) #include "tls/utility/CryptoUtil.h" #include @@ -148,6 +150,8 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass CryptoUtil _crypto; #elif defined(BOARD_ESP) WiFiClientSecure _sslClient; + #elif defined(ARDUINO_UNOR4_WIFI) + WiFiSSLClient _sslClient; #elif defined(ARDUINO_PORTENTA_C33) ArduinoIoTCloudCertClass _cert; SSLClient _sslClient; From 79f2adb9bf3007edfa9c38f22b338d0d150b1da5 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 28 Jun 2023 09:04:43 +0200 Subject: [PATCH 430/780] Fix crash at startup --- src/utility/time/TimeService.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index eeab3245d..23d13767f 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -96,13 +96,18 @@ void renesas_setRTC(unsigned long time); unsigned long renesas_getRTC(); #endif +/************************************************************************************** + * DEFINES + **************************************************************************************/ + +#define EPOCH_AT_COMPILE_TIME cvt_time(__DATE__) + /************************************************************************************** * CONSTANTS **************************************************************************************/ /* Default NTP synch is scheduled each 24 hours from startup */ static time_t const TIMESERVICE_NTP_SYNC_TIMEOUT_ms = DAYS * 1000; -static time_t const EPOCH_AT_COMPILE_TIME = cvt_time(__DATE__); static time_t const EPOCH = 0; /************************************************************************************** From 176c2cae5a99006bc1c9fa1c9939974b9179be5f Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 28 Jun 2023 09:06:21 +0200 Subject: [PATCH 431/780] Compute EPOCH_AT_COMPILE_TIME only once --- src/utility/time/TimeService.cpp | 56 ++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 23d13767f..23ab0a663 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -398,32 +398,38 @@ unsigned long TimeServiceClass::getRTC() time_t cvt_time(char const * time) { - char s_month[5]; - int month, day, year; - struct tm t = - { - 0 /* tm_sec */, - 0 /* tm_min */, - 0 /* tm_hour */, - 0 /* tm_mday */, - 0 /* tm_mon */, - 0 /* tm_year */, - 0 /* tm_wday */, - 0 /* tm_yday */, - 0 /* tm_isdst */ - }; - static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; - - sscanf(time, "%s %d %d", s_month, &day, &year); - - month = (strstr(month_names, s_month) - month_names) / 3; - - t.tm_mon = month; - t.tm_mday = day; - t.tm_year = year - 1900; - t.tm_isdst = -1; + static time_t build_time = 0; + + if (!build_time) { + char s_month[5]; + int month, day, year; + struct tm t = + { + 0 /* tm_sec */, + 0 /* tm_min */, + 0 /* tm_hour */, + 0 /* tm_mday */, + 0 /* tm_mon */, + 0 /* tm_year */, + 0 /* tm_wday */, + 0 /* tm_yday */, + 0 /* tm_isdst */ + }; + static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + + sscanf(time, "%s %d %d", s_month, &day, &year); + + month = (strstr(month_names, s_month) - month_names) / 3; + + t.tm_mon = month; + t.tm_mday = day; + t.tm_year = year - 1900; + t.tm_isdst = -1; + + build_time = mktime(&t); + } - return mktime(&t); + return build_time; } #ifdef ARDUINO_ARCH_SAMD From dac5ce9173c47bd49104f90da81abbeff1979afe Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 28 Jun 2023 09:08:48 +0200 Subject: [PATCH 432/780] Add renesas_uno architecture --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 243450928..c67a30bd0 100644 --- a/library.properties +++ b/library.properties @@ -6,6 +6,6 @@ sentence=This library allows connecting to the Arduino IoT Cloud service. paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKR GSM, MKR1000 and WiFi101. category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud -architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta,mbed_giga,renesas_portenta +architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta,mbed_giga,renesas_portenta,renesas_uno includes=ArduinoIoTCloud.h depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,Arduino_ESP32_OTA,Arduino_Portenta_OTA From 0d635ef93d8eadd1b116c40b7bc3d23e08358c87 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 28 Jun 2023 09:12:39 +0200 Subject: [PATCH 433/780] Enable compile example workflow for UNO R4 WiFi --- .github/workflows/compile-examples.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index f5a039cbb..67382b479 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -64,6 +64,8 @@ jobs: type: mbed_giga - fqbn: arduino:renesas_portenta:portenta_c33 type: renesas_portenta + - fqbn: arduino:renesas_uno:unor4wifi + type: renesas_uno # make board type-specific customizations to the matrix jobs @@ -177,7 +179,7 @@ jobs: - name: Arduino_Portenta_OTA sketch-paths: | - examples/utility/Provisioning - # Portneta C33 + # Portenta C33 - board: type: renesas_portenta platforms: | @@ -185,6 +187,12 @@ jobs: - name: arduino:renesas_portenta sketch-paths: | - examples/utility/Provisioning + # UNO R4 WiFi + - board: + type: renesas_uno + platforms: | + # Install renesas_uno platform via Boards Manager + - name: arduino:renesas_uno # ESP8266 boards - board: type: esp8266 From 44f92b0bcc89a1d9119da7a7881c573ebdc35329 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 4 Jul 2023 00:56:32 +0200 Subject: [PATCH 434/780] Add WiFi firmware version check --- src/ArduinoIoTCloudTCP.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 11ffff1a2..12fbc6135 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -327,6 +327,12 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() reconnection_retry_delay = min(reconnection_retry_delay, static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms)); _next_connection_attempt_tick = millis() + reconnection_retry_delay; +#if defined(ARDUINO_UNOWIFIR4) + if (String(WiFi.firmwareVersion()) < String("0.2.0")) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, WiFI firmware needs to be >= 0.2.0, current %s", __FUNCTION__, WiFi.firmwareVersion()); + } +#endif + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); DEBUG_ERROR("ArduinoIoTCloudTCP::%s %d connection attempt at tick time %d", __FUNCTION__, _last_connection_attempt_cnt, _next_connection_attempt_tick); return State::ConnectPhy; From 2cbe1e82c39cb175abbb62d10db34d215ce553d4 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 7 Jul 2023 08:18:56 +0200 Subject: [PATCH 435/780] Fix typo --- src/ArduinoIoTCloudTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 12fbc6135..81273a322 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -329,7 +329,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() #if defined(ARDUINO_UNOWIFIR4) if (String(WiFi.firmwareVersion()) < String("0.2.0")) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, WiFI firmware needs to be >= 0.2.0, current %s", __FUNCTION__, WiFi.firmwareVersion()); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, WiFi firmware needs to be >= 0.2.0, current %s", __FUNCTION__, WiFi.firmwareVersion()); } #endif From 32f80194f5712f334352bbe3f6823a8815cdea13 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Fri, 7 Jul 2023 08:34:35 +0200 Subject: [PATCH 436/780] Release v1.11.3 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index c67a30bd0..d041e843c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.11.2 +version=1.11.3 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 95ef1a93d..750d44ec0 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -173,6 +173,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.11.1" +#define AIOT_CONFIG_LIB_VERSION "1.11.3" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 1e78257849230637ab4091c768d656c3c2e1a06c Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 7 Jun 2023 08:42:39 +0200 Subject: [PATCH 437/780] ESP32: enable TLS and add server cert --- src/ArduinoIoTCloudTCP.cpp | 8 +++++ src/tls/AIoTCUPCert.h | 64 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/tls/AIoTCUPCert.h diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 81273a322..9858cd75b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -39,6 +39,10 @@ #include "tls/utility/CryptoUtil.h" #endif +#ifdef BOARD_HAS_SECRET_KEY + #include "tls/AIoTCUPCert.h" +#endif + #if OTA_ENABLED #include "utility/ota/OTA.h" #endif @@ -172,7 +176,11 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #elif defined(BOARD_HAS_SE050) _sslClient.appendCustomCACert(AIoTSSCert); #elif defined(BOARD_ESP) + #if defined(ARDUINO_ARCH_ESP8266) _sslClient.setInsecure(); + #else + _sslClient.setCACert(AAIoTUPCert); + #endif #endif _mqttClient.setClient(_sslClient); diff --git a/src/tls/AIoTCUPCert.h b/src/tls/AIoTCUPCert.h new file mode 100644 index 000000000..8f10f4d9d --- /dev/null +++ b/src/tls/AIoTCUPCert.h @@ -0,0 +1,64 @@ +/* + This file is part of ArduinoIoTBearSSL. + + Copyright 2019 ARDUINO SA (http://www.arduino.cc/) + + This software is released under the GNU General Public License version 3, + which covers the main part of ArduinoIoTBearSSL. + 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 _AIOTC_UP_CERT_H_ +#define _AIOTC_UP_CERT_H_ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include +#ifdef BOARD_HAS_SECRET_KEY + +/****************************************************************************** + * CONSTANTS + ******************************************************************************/ + +//https://www.amazontrust.com/repository/Amazon-RSA-2048-M01.pem +static const char AAIoTUPCert[] = +"-----BEGIN CERTIFICATE-----\n" +"MIIEXjCCA0agAwIBAgITB3MSOAudZoijOx7Zv5zNpo4ODzANBgkqhkiG9w0BAQsF\n" +"ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" +"b24gUm9vdCBDQSAxMB4XDTIyMDgyMzIyMjEyOFoXDTMwMDgyMzIyMjEyOFowPDEL\n" +"MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEcMBoGA1UEAxMTQW1hem9uIFJT\n" +"QSAyMDQ4IE0wMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOtxLKnL\n" +"H4gokjIwr4pXD3i3NyWVVYesZ1yX0yLI2qIUZ2t88Gfa4gMqs1YSXca1R/lnCKeT\n" +"epWSGA+0+fkQNpp/L4C2T7oTTsddUx7g3ZYzByDTlrwS5HRQQqEFE3O1T5tEJP4t\n" +"f+28IoXsNiEzl3UGzicYgtzj2cWCB41eJgEmJmcf2T8TzzK6a614ZPyq/w4CPAff\n" +"nAV4coz96nW3AyiE2uhuB4zQUIXvgVSycW7sbWLvj5TDXunEpNCRwC4kkZjK7rol\n" +"jtT2cbb7W2s4Bkg3R42G3PLqBvt2N32e/0JOTViCk8/iccJ4sXqrS1uUN4iB5Nmv\n" +"JK74csVl+0u0UecCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYD\n" +"VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNV\n" +"HQ4EFgQUgbgOY4qJEhjl+js7UJWf5uWQE4UwHwYDVR0jBBgwFoAUhBjMhTTsvAyU\n" +"lC4IWZzHshBOCggwewYIKwYBBQUHAQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8v\n" +"b2NzcC5yb290Y2ExLmFtYXpvbnRydXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDov\n" +"L2NydC5yb290Y2ExLmFtYXpvbnRydXN0LmNvbS9yb290Y2ExLmNlcjA/BgNVHR8E\n" +"ODA2MDSgMqAwhi5odHRwOi8vY3JsLnJvb3RjYTEuYW1hem9udHJ1c3QuY29tL3Jv\n" +"b3RjYTEuY3JsMBMGA1UdIAQMMAowCAYGZ4EMAQIBMA0GCSqGSIb3DQEBCwUAA4IB\n" +"AQCtAN4CBSMuBjJitGuxlBbkEUDeK/pZwTXv4KqPK0G50fOHOQAd8j21p0cMBgbG\n" +"kfMHVwLU7b0XwZCav0h1ogdPMN1KakK1DT0VwA/+hFvGPJnMV1Kx2G4S1ZaSk0uU\n" +"5QfoiYIIano01J5k4T2HapKQmmOhS/iPtuo00wW+IMLeBuKMn3OLn005hcrOGTad\n" +"hcmeyfhQP7Z+iKHvyoQGi1C0ClymHETx/chhQGDyYSWqB/THwnN15AwLQo0E5V9E\n" +"SJlbe4mBlqeInUsNYugExNf+tOiybcrswBy8OFsd34XOW3rjSUtsuafd9AWySa3h\n" +"xRRrwszrzX/WWGm6wyB+f7C4\n" +"-----END CERTIFICATE-----\n"; + +#endif /* #ifdef BOARD_HAS_SECRET_KEY */ + +#endif /* _AIOTC_UP_CERT_H_ */ From 730d462eb132bf1bc8b6b6722261b8d17c23d996 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 19 Jul 2023 11:28:54 +0200 Subject: [PATCH 438/780] Examples: fix Schedule example build --- .../ArduinoIoTCloud-Schedule.ino | 23 +++++++++---------- .../thingProperties.h | 2 +- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index 7b82394ac..170a5f15a 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -58,7 +58,7 @@ void setup() { */ void setupOneShotSchedule() { - ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); + ScheduleTimeType startingFrom = TimeServiceClass::getTimeFromString("2021 Nov 01 17:00:00"); ScheduleTimeType until = startingFrom + ( DAYS * 1 ); ScheduleTimeType activePeriod = MINUTES * 5; @@ -74,7 +74,7 @@ void setupOneShotSchedule() { */ void setupMinuteSchedule() { - ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); + ScheduleTimeType startingFrom = TimeServiceClass::getTimeFromString("2021 Nov 01 17:00:00"); ScheduleTimeType until = startingFrom + ( DAYS * 1 ); ScheduleTimeType activePeriod = SECONDS * 15; unsigned int repetitionPeriod = 1; @@ -91,8 +91,8 @@ void setupMinuteSchedule() { */ void setupHourlySchedule() { - ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); - ScheduleTimeType until = TimeService::getTimeFromString("2021 Nov 15 13:00:00"); + ScheduleTimeType startingFrom = TimeServiceClass::getTimeFromString("2021 Nov 01 17:00:00"); + ScheduleTimeType until = TimeServiceClass::getTimeFromString("2021 Nov 15 13:00:00"); ScheduleTimeType activePeriod = MINUTES * 20; unsigned int repetitionPeriod = 1; @@ -108,8 +108,8 @@ void setupHourlySchedule() { */ void setupDailySchedule() { - ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); - ScheduleTimeType until = TimeService::getTimeFromString("2021 Nov 15 13:00:00"); + ScheduleTimeType startingFrom = TimeServiceClass::getTimeFromString("2021 Nov 01 17:00:00"); + ScheduleTimeType until = TimeServiceClass::getTimeFromString("2021 Nov 15 13:00:00"); ScheduleTimeType activePeriod = HOURS * 2; unsigned int repetitionPeriod = 1; @@ -133,7 +133,7 @@ void setupDailySchedule() { */ void setupWeeklySchedule() { - unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); + unsigned int startingFrom = TimeServiceClass::getTimeFromString("2021 Nov 01 17:00:00"); unsigned int until = startingFrom + ( DAYS * 30 ); unsigned int executionPeriod = MINUTES * 3; @@ -158,8 +158,8 @@ void setupWeeklySchedule() { */ void setupMonthlySchedule() { - ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00"); - ScheduleTimeType until = TimeService::getTimeFromString("2021 Nov 15 13:00:00"); + ScheduleTimeType startingFrom = TimeServiceClass::getTimeFromString("2021 Nov 01 17:00:00"); + ScheduleTimeType until = TimeServiceClass::getTimeFromString("2021 Nov 15 13:00:00"); ScheduleTimeType activePeriod = DAYS * 1; int dayOfMonth = 3; @@ -175,8 +175,8 @@ void setupMonthlySchedule() { */ void setupYearlySchedule() { - ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 06 17:00:00"); - ScheduleTimeType until = TimeService::getTimeFromString("2041 Nov 06 13:00:00"); + ScheduleTimeType startingFrom = TimeServiceClass::getTimeFromString("2021 Nov 06 17:00:00"); + ScheduleTimeType until = TimeServiceClass::getTimeFromString("2041 Nov 06 13:00:00"); ScheduleTimeType activePeriod = DAYS * 2; int dayOfMonth = 6; @@ -222,4 +222,3 @@ void loop() { } } - diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 22a185b9c..5949d8900 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -37,7 +37,7 @@ void initProperties() { ArduinoCloud.addProperty(monthly, READWRITE, ON_CHANGE); ArduinoCloud.addProperty(yearly, READWRITE, ON_CHANGE); #elif defined(BOARD_HAS_LORA) - ArduinoCloud.addProperty(switchButton, 1, WRITE, ON_CHANGE; + ArduinoCloud.addProperty(switchButton, 1, WRITE, ON_CHANGE); #endif } From c4c650598da7b90c929fd4ba3d0d875af840ffd5 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 18 Jul 2023 17:17:53 +0200 Subject: [PATCH 439/780] Nano ESP32: enable compile examples workflow --- .github/workflows/compile-examples.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 67382b479..7cc56c845 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -66,6 +66,8 @@ jobs: type: renesas_portenta - fqbn: arduino:renesas_uno:unor4wifi type: renesas_uno + - fqbn: arduino:esp32:nano_nora + type: arduino_esp32 # make board type-specific customizations to the matrix jobs @@ -193,6 +195,16 @@ jobs: platforms: | # Install renesas_uno platform via Boards Manager - name: arduino:renesas_uno + # Nano ESP32 + - board: + type: arduino_esp32 + platforms: | + # Install arduino_esp32 platform via Boards Manager + - name: arduino:esp32 + libraries: | + - name: Arduino_ESP32_OTA + sketch-paths: | + - examples/ArduinoIoTCloud-DeferredOTA # ESP8266 boards - board: type: esp8266 From dabc9b01a1a75995bb2a8a37f31b18ebe990f026 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 19 Jul 2023 11:14:32 +0200 Subject: [PATCH 440/780] Examples: fix build for Arduino NANO ESP32 --- examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino | 2 +- .../ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino | 2 +- examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino index a32644941..ba4162baf 100644 --- a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino +++ b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino @@ -17,7 +17,7 @@ #include "arduino_secrets.h" #include "thingProperties.h" -#if !defined(LED_BUILTIN) +#if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) static int const LED_BUILTIN = 2; #endif diff --git a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino index fd5ab7977..b39439b4a 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino +++ b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino @@ -19,7 +19,7 @@ #include "arduino_secrets.h" #include "thingProperties.h" -#if defined(ESP32) +#if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) static int const LED_BUILTIN = 2; #endif diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index 7b82394ac..21e62f11d 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -9,7 +9,7 @@ #include "arduino_secrets.h" #include "thingProperties.h" -#if defined(ESP32) +#if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) static int const LED_BUILTIN = 2; #endif From 9cd67c109268bbbe0e650cd70f89345593af5638 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 19 Jul 2023 11:13:54 +0200 Subject: [PATCH 441/780] CI: Add missing examples --- .github/workflows/compile-examples.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 67382b479..821dea446 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -28,6 +28,8 @@ jobs: UNIVERSAL_SKETCH_PATHS: | - examples/ArduinoIoTCloud-Advanced - examples/ArduinoIoTCloud-Basic + - examples/ArduinoIoTCloud-Callbacks + - examples/ArduinoIoTCloud-Schedule - examples/utility/ArduinoIoTCloud_Travis_CI SKETCHES_REPORTS_PATH: sketches-reports @@ -97,6 +99,7 @@ jobs: - name: Arduino_JSON - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | + - examples/ArduinoIoTCloud-DeferredOTA - examples/utility/Provisioning - examples/utility/SelfProvisioning - board: @@ -146,6 +149,7 @@ jobs: - name: ArduinoECCX08 - name: Arduino_Portenta_OTA sketch-paths: | + - examples/ArduinoIoTCloud-DeferredOTA - examples/utility/Provisioning # Nicla Vision - board: @@ -156,6 +160,7 @@ jobs: libraries: | - name: Arduino_Portenta_OTA sketch-paths: | + - examples/ArduinoIoTCloud-DeferredOTA - examples/utility/Provisioning # Opta - board: @@ -167,6 +172,7 @@ jobs: - name: ArduinoECCX08 - name: Arduino_Portenta_OTA sketch-paths: | + - examples/ArduinoIoTCloud-DeferredOTA - examples/utility/Provisioning # GIGA - board: @@ -178,6 +184,7 @@ jobs: - name: ArduinoECCX08 - name: Arduino_Portenta_OTA sketch-paths: | + - examples/ArduinoIoTCloud-DeferredOTA - examples/utility/Provisioning # Portenta C33 - board: @@ -213,7 +220,8 @@ jobs: source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json libraries: | - name: Arduino_ESP32_OTA - sketch-paths: + sketch-paths: | + - examples/ArduinoIoTCloud-DeferredOTA steps: - name: Checkout From fdf04d49c3803f62fde0b349da7f50f89ad9484a Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 24 Jul 2023 16:41:40 +0300 Subject: [PATCH 442/780] Release v1.12.0 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index d041e843c..5d78ac4e9 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.11.3 +version=1.12.0 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 750d44ec0..b6f5fff80 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -173,6 +173,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.11.3" +#define AIOT_CONFIG_LIB_VERSION "1.12.0" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From d44e21c88c3bd359a396f219619b69b28ebcb016 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 25 Jul 2023 13:23:49 +0200 Subject: [PATCH 443/780] bin2ota: add Arduino NANO ESP32 --- extras/tools/bin2ota.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extras/tools/bin2ota.py b/extras/tools/bin2ota.py index 651a51740..5ec788d95 100755 --- a/extras/tools/bin2ota.py +++ b/extras/tools/bin2ota.py @@ -5,7 +5,7 @@ if len(sys.argv) != 4: print ("Usage: bin2ota.py BOARD sketch.bin sketch.ota") - print (" BOARD = [ MKR_WIFI_1010 | NANO_33_IOT | PORTENTA_H7_M7 | NANO_RP2040_CONNECT | NICLA_VISION | OPTA | GIGA ]") + print (" BOARD = [ MKR_WIFI_1010 | NANO_33_IOT | PORTENTA_H7_M7 | NANO_RP2040_CONNECT | NICLA_VISION | OPTA | GIGA | NANO_ESP32 ]") sys.exit() board = sys.argv[1] @@ -32,6 +32,8 @@ magic_number = 0x23410064.to_bytes(4,byteorder='little') elif board == "GIGA": magic_number = 0x23410266.to_bytes(4,byteorder='little') +elif board == "NANO_ESP32": + magic_number = 0x23410070.to_bytes(4,byteorder='little') # Magic number for all ESP32 boards not related to (VID/PID) elif board == "ESP32": magic_number = 0x45535033.to_bytes(4,byteorder='little') From d1192ebecd81dd50857c2f7c5dde314661affb4c Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 25 Jul 2023 15:05:43 +0200 Subject: [PATCH 444/780] README: Add new boards --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 07151347c..fd3e6d9f2 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ ### What? The `ArduinoIoTCloud` library is the central element of the firmware enabling certain Arduino boards to connect to the [Arduino IoT Cloud](https://www.arduino.cc/en/IoT/HomePage). The following boards are supported: -* **WiFi**: [`MKR 1000`](https://store.arduino.cc/arduino-mkr1000-wifi), [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`Nano RP2040 Connect`](https://store.arduino.cc/products/arduino-nano-rp2040-connect), [`Nicla Vision`](https://store.arduino.cc/products/nicla-vision), [`ESP8266`](https://github.com/esp8266/Arduino/releases/tag/2.5.0), [`ESP32`](https://github.com/espressif/arduino-esp32/releases/tag/1.0.6) +* **WiFi**: [`MKR 1000`](https://store.arduino.cc/arduino-mkr1000-wifi), [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`Nano RP2040 Connect`](https://store.arduino.cc/products/arduino-nano-rp2040-connect), [`Nicla Vision`](https://store.arduino.cc/products/nicla-vision), [`OPTA WiFi`](https://store.arduino.cc/products/opta-wifi), [`GIGA R1 WiFi`](https://store.arduino.cc/products/giga-r1-wifi), [`Portenta C33`](https://store.arduino.cc/products/portenta-c33), [`UNO R4 WiFi`](https://store.arduino.cc/products/uno-r4-wifi), [`Nano ESP32`](https://store.arduino.cc/products/nano-esp32), [`ESP8266`](https://github.com/esp8266/Arduino/releases/tag/2.5.0), [`ESP32`](https://github.com/espressif/arduino-esp32/releases/tag/2.0.5) * **GSM**: [`MKR GSM 1400`](https://store.arduino.cc/arduino-mkr-gsm-1400-1415) * **5G**: [`MKR NB 1500`](https://store.arduino.cc/arduino-mkr-nb-1500-1413) * **LoRa**: [`MKR WAN 1300/1310`](https://store.arduino.cc/mkr-wan-1310) -* **Ethernet**: [`Portenta H7`](https://store.arduino.cc/products/portenta-h7) + [`Vision Shield Ethernet`](https://store.arduino.cc/products/arduino-portenta-vision-shield-ethernet), [`Max Carrier`](https://store.arduino.cc/products/portenta-max-carrier), [`Breakout`](https://store.arduino.cc/products/arduino-portenta-breakout), [`Portenta Machine Control`](https://store.arduino.cc/products/arduino-portenta-machine-control) +* **Ethernet**: [`Portenta H7`](https://store.arduino.cc/products/portenta-h7) + [`Vision Shield Ethernet`](https://store.arduino.cc/products/arduino-portenta-vision-shield-ethernet), [`Max Carrier`](https://store.arduino.cc/products/portenta-max-carrier), [`Breakout`](https://store.arduino.cc/products/arduino-portenta-breakout), [`Portenta Machine Control`](https://store.arduino.cc/products/arduino-portenta-machine-control), [`OPTA WiFi`](https://store.arduino.cc/products/opta-wifi), [`OPTA RS485`](https://store.arduino.cc/products/opta-rs485), [`OPTA Lite`](https://store.arduino.cc/products/opta-lite), [`Portenta C33`](https://store.arduino.cc/products/portenta-c33) + [`Vision Shield Ethernet`](https://store.arduino.cc/products/arduino-portenta-vision-shield-ethernet) ### How? 1) Register your Arduino IoT Cloud capable board via [Arduino IoT Cloud](https://create.arduino.cc/iot) (Devices Section). From 105c5eca43e2e40473529b31038feb1e67c74354 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 25 Jul 2023 15:07:04 +0200 Subject: [PATCH 445/780] README: Add list of boards with watchdog support --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index fd3e6d9f2..94f116eb8 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,8 @@ The [1.0.0](https://github.com/arduino-libraries/ArduinoIoTCloud/releases/tag/1. ArduinoCloud.begin(ArduinoIoTPreferredConnection, false). ``` +Whatchdog is enabled by default using the following boards: [`MKR 1000`](https://store.arduino.cc/arduino-mkr1000-wifi), [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`MKR GSM 1400`](https://store.arduino.cc/arduino-mkr-gsm-1400-1415), [`MKR NB 1500`](https://store.arduino.cc/arduino-mkr-nb-1500-1413), [`MKR WAN 1300/1310`](https://store.arduino.cc/mkr-wan-1310), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`Nano RP2040 Connect`](https://store.arduino.cc/products/arduino-nano-rp2040-connect), [`Nicla Vision`](https://store.arduino.cc/products/nicla-vision), [`OPTA WiFi`](https://store.arduino.cc/products/opta-wifi), [`OPTA RS485`](https://store.arduino.cc/products/opta-rs485), [`OPTA Lite`](https://store.arduino.cc/products/opta-lite), [`GIGA R1 WiFi`](https://store.arduino.cc/products/giga-r1-wifi) + #### Device can not subscribe to `THING_ID` ``` ArduinoIoTCloudTCP::handle_SubscribeMqttTopics could not subscribe to /a/t/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/e/i From b836c89be2f62b73fac8c81a71f3deee3308d95c Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 25 Jul 2023 15:08:06 +0200 Subject: [PATCH 446/780] README: Update list of board with OTA support --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 94f116eb8..093cce28a 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ In this case either the device has not been associated with the thing within the #### OTA OTA is supported by the following boards: -[`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`Nano RP2040 Connect`](https://store.arduino.cc/products/arduino-nano-rp2040-connect), [`Nicla Vision`](https://store.arduino.cc/products/nicla-vision) +[`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`Nano RP2040 Connect`](https://store.arduino.cc/products/arduino-nano-rp2040-connect), [`Nicla Vision`](https://store.arduino.cc/products/nicla-vision), [`OPTA WiFi`](https://store.arduino.cc/products/opta-wifi), [`OPTA RS485`](https://store.arduino.cc/products/opta-rs485), [`OPTA Lite`](https://store.arduino.cc/products/opta-lite), [`GIGA R1 WiFi`](https://store.arduino.cc/products/giga-r1-wifi), [`Nano ESP32`](https://store.arduino.cc/products/nano-esp32), [`ESP32`](https://github.com/espressif/arduino-esp32/releases/tag/2.0.5) #### ESP Boards Support for ESP boards is obtained through a third-party core with some differences and limitations compared to Arduino boards. From 6b6cb9355a1c933e1f89592a2dbf7ff0ba25e8e5 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 25 Jul 2023 15:13:33 +0200 Subject: [PATCH 447/780] README: remove section about ESP Boards --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index 093cce28a..33c40c61a 100644 --- a/README.md +++ b/README.md @@ -87,9 +87,3 @@ In this case either the device has not been associated with the thing within the OTA is supported by the following boards: [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`Nano RP2040 Connect`](https://store.arduino.cc/products/arduino-nano-rp2040-connect), [`Nicla Vision`](https://store.arduino.cc/products/nicla-vision), [`OPTA WiFi`](https://store.arduino.cc/products/opta-wifi), [`OPTA RS485`](https://store.arduino.cc/products/opta-rs485), [`OPTA Lite`](https://store.arduino.cc/products/opta-lite), [`GIGA R1 WiFi`](https://store.arduino.cc/products/giga-r1-wifi), [`Nano ESP32`](https://store.arduino.cc/products/nano-esp32), [`ESP32`](https://github.com/espressif/arduino-esp32/releases/tag/2.0.5) -#### ESP Boards -Support for ESP boards is obtained through a third-party core with some differences and limitations compared to Arduino boards. - -- **Authentication scheme**: Board authentication is done through `DEVICE_LOGIN_NAME` and `DEVICE_KEY`, both values are included in the `thingProperties.h` file. -- **Watchdog**: Watchdog support is not included. -- **OTA**: OTA support is not included From 93d337ef393534caa3482f013230e09af633e232 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 25 Jul 2023 15:14:11 +0200 Subject: [PATCH 448/780] README: Add section about authentication --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 33c40c61a..83a7e70cb 100644 --- a/README.md +++ b/README.md @@ -87,3 +87,13 @@ In this case either the device has not been associated with the thing within the OTA is supported by the following boards: [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`Nano RP2040 Connect`](https://store.arduino.cc/products/arduino-nano-rp2040-connect), [`Nicla Vision`](https://store.arduino.cc/products/nicla-vision), [`OPTA WiFi`](https://store.arduino.cc/products/opta-wifi), [`OPTA RS485`](https://store.arduino.cc/products/opta-rs485), [`OPTA Lite`](https://store.arduino.cc/products/opta-lite), [`GIGA R1 WiFi`](https://store.arduino.cc/products/giga-r1-wifi), [`Nano ESP32`](https://store.arduino.cc/products/nano-esp32), [`ESP32`](https://github.com/espressif/arduino-esp32/releases/tag/2.0.5) +#### Authentication +Boards can authenticate to the ArduinoIoTCloud servers using 3 methods: + + * `DEVICE_LOGIN_NAME` and `DEVICE_KEY`. This values are defined in the `thingProperties.h` file and included in the Sketch. Boards that are using this method are: [`UNO R4 WiFi`](https://store.arduino.cc/products/uno-r4-wifi), [`Nano ESP32`](https://store.arduino.cc/products/nano-esp32), [`ESP8266`](https://github.com/esp8266/Arduino/releases/tag/2.5.0), [`ESP32`](https://github.com/espressif/arduino-esp32/releases/tag/2.0.5) + + * `DEVICE_CERTIFICATE` and `PRIVATE_KEY`. This values are stored inside the board secure element during the device provisioning phase. Boards that are using this method are: [`MKR 1000`](https://store.arduino.cc/arduino-mkr1000-wifi), [`MKR WiFi 1010`](https://store.arduino.cc/arduino-mkr-wifi-1010), [`MKR GSM 1400`](https://store.arduino.cc/arduino-mkr-gsm-1400-1415), [`MKR NB 1500`](https://store.arduino.cc/arduino-mkr-nb-1500-1413), [`Nano 33 IoT`](https://store.arduino.cc/arduino-nano-33-iot), [`Portenta H7`](https://store.arduino.cc/portenta-h7), [`Nano RP2040 Connect`](https://store.arduino.cc/products/arduino-nano-rp2040-connect), [`Nicla Vision`](https://store.arduino.cc/products/nicla-vision), [`OPTA WiFi`](https://store.arduino.cc/products/opta-wifi), [`OPTA RS485`](https://store.arduino.cc/products/opta-rs485), [`OPTA Lite`](https://store.arduino.cc/products/opta-lite), [`GIGA R1 WiFi`](https://store.arduino.cc/products/giga-r1-wifi), [`Portenta C33`](https://store.arduino.cc/products/portenta-c33) + + * `APP_EUI` and `APP_KEY`. This values are defined in the `thingProperties.h` file and included in the Sketch. Boards that are using this method are: [`MKR WAN 1300/1310`](https://store.arduino.cc/mkr-wan-1310) + + \ No newline at end of file From 9540706f2e57103a86cd19fd5470b792846a8fbe Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 18 Aug 2023 10:22:36 +0200 Subject: [PATCH 449/780] bin2ota: add Uno R4 WiFi --- extras/tools/bin2ota.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extras/tools/bin2ota.py b/extras/tools/bin2ota.py index 5ec788d95..57e3f47f2 100755 --- a/extras/tools/bin2ota.py +++ b/extras/tools/bin2ota.py @@ -5,7 +5,7 @@ if len(sys.argv) != 4: print ("Usage: bin2ota.py BOARD sketch.bin sketch.ota") - print (" BOARD = [ MKR_WIFI_1010 | NANO_33_IOT | PORTENTA_H7_M7 | NANO_RP2040_CONNECT | NICLA_VISION | OPTA | GIGA | NANO_ESP32 ]") + print (" BOARD = [ MKR_WIFI_1010 | NANO_33_IOT | PORTENTA_H7_M7 | NANO_RP2040_CONNECT | NICLA_VISION | OPTA | GIGA | NANO_ESP32 | ESP32 | UNOR4WIFI]") sys.exit() board = sys.argv[1] @@ -37,6 +37,8 @@ # Magic number for all ESP32 boards not related to (VID/PID) elif board == "ESP32": magic_number = 0x45535033.to_bytes(4,byteorder='little') +elif board == "UNOR4WIFI": + magic_number = 0x23411002.to_bytes(4,byteorder='little') else: print ("Error,", board, "is not a supported board type") sys.exit() From 98e42013210e03f274004bd8c3a7dd521e462629 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 18 Aug 2023 10:25:49 +0200 Subject: [PATCH 450/780] Uno R4 WiFi: add OTA support --- src/AIoTC_Config.h | 2 +- src/tls/bearssl/dec32be.c | 4 +- src/tls/bearssl/enc32be.c | 4 +- src/tls/bearssl/sha2small.c | 4 +- src/utility/ota/OTA-unor4.cpp | 187 ++++++++++++++++++++++++++++++++++ src/utility/ota/OTA.cpp | 13 +++ 6 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 src/utility/ota/OTA-unor4.cpp diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index b6f5fff80..6e65e1be3 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -108,7 +108,7 @@ #define OTA_STORAGE_PORTENTA_QSPI (0) #endif -#if defined(ARDUINO_ARCH_ESP32) +#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_UNOR4_WIFI) #define OTA_STORAGE_ESP (1) #endif diff --git a/src/tls/bearssl/dec32be.c b/src/tls/bearssl/dec32be.c index 0b8b05a5e..733381229 100644 --- a/src/tls/bearssl/dec32be.c +++ b/src/tls/bearssl/dec32be.c @@ -23,7 +23,9 @@ */ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) || defined(ARDUINO_ARCH_ESP32) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || \ + defined(BOARD_HAS_SE050) || defined(ARDUINO_ARCH_ESP32) || \ + defined(ARDUINO_UNOR4_WIFI) #include "inner.h" diff --git a/src/tls/bearssl/enc32be.c b/src/tls/bearssl/enc32be.c index a00d96123..26fa3cee1 100644 --- a/src/tls/bearssl/enc32be.c +++ b/src/tls/bearssl/enc32be.c @@ -23,7 +23,9 @@ */ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) || defined(ARDUINO_ARCH_ESP32) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || \ + defined(BOARD_HAS_SE050) || defined(ARDUINO_ARCH_ESP32) || \ + defined(ARDUINO_UNOR4_WIFI) #include "inner.h" diff --git a/src/tls/bearssl/sha2small.c b/src/tls/bearssl/sha2small.c index 02283f05c..04cc71f81 100644 --- a/src/tls/bearssl/sha2small.c +++ b/src/tls/bearssl/sha2small.c @@ -23,7 +23,9 @@ */ #include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) || defined(ARDUINO_ARCH_ESP32) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || \ + defined(BOARD_HAS_SE050) || defined(ARDUINO_ARCH_ESP32) || \ + defined(ARDUINO_UNOR4_WIFI) #include "inner.h" diff --git a/src/utility/ota/OTA-unor4.cpp b/src/utility/ota/OTA-unor4.cpp new file mode 100644 index 000000000..34c417b02 --- /dev/null +++ b/src/utility/ota/OTA-unor4.cpp @@ -0,0 +1,187 @@ +/* + 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 defined ARDUINO_UNOR4_WIFI && OTA_ENABLED + +#include "OTAUpdate.h" +#include +#include "tls/utility/SHA256.h" +#include "fsp_common_api.h" +#include "r_flash_lp.h" +#include "WiFiS3.h" + +/****************************************************************************** + * DEFINES + ******************************************************************************/ + +/* Key code for writing PRCR register. */ +#define BSP_PRV_PRCR_KEY (0xA500U) +#define BSP_PRV_PRCR_PRC1_UNLOCK ((BSP_PRV_PRCR_KEY) | 0x2U) +#define BSP_PRV_PRCR_LOCK ((BSP_PRV_PRCR_KEY) | 0x0U) + +#define OTA_MAGIC (*((volatile uint16_t *) &R_SYSTEM->VBTBKR[4])) +#define OTA_SIZE (*((volatile uint32_t *) &R_SYSTEM->VBTBKR[6])) + +/****************************************************************************** + * FUNCTION DEFINITION + ******************************************************************************/ + +static void unor4_setOTASize(uint32_t size) +{ + R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_PRC1_UNLOCK; + OTA_MAGIC = 0x07AA; + OTA_SIZE = size; + R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_LOCK; +} + +static uint32_t unor4_getOTASize() +{ + if (OTA_MAGIC == 0x07AA) + { + return OTA_SIZE; + } + return 0; +} + +static int unor4_codeFlashOpen(flash_lp_instance_ctrl_t * ctrl) +{ + flash_cfg_t cfg; + + cfg.data_flash_bgo = false; + cfg.p_callback = nullptr; + cfg.p_context = nullptr; + cfg.p_extend = nullptr; + cfg.ipl = (BSP_IRQ_DISABLED); + cfg.irq = FSP_INVALID_VECTOR; + cfg.err_ipl = (BSP_IRQ_DISABLED); + cfg.err_irq = FSP_INVALID_VECTOR; + + fsp_err_t rv = FSP_ERR_UNSUPPORTED; + + rv = R_FLASH_LP_Open(ctrl,&cfg); + return rv; +} + +static int unor4_codeFlashClose(flash_lp_instance_ctrl_t * ctrl) +{ + fsp_err_t rv = FSP_ERR_UNSUPPORTED; + + rv = R_FLASH_LP_Close(ctrl); + return rv; +} + +int unor4_onOTARequest(char const * ota_url) +{ + OTAUpdate::Error ota_err = OTAUpdate::Error::None; + OTAUpdate ota; + + /* Initialize the board for OTA handling. */ + if ((ota_err = ota.begin("/update.bin")) != OTAUpdate::Error::None) + { + DEBUG_ERROR("OTAUpdate::begin() failed with %d", static_cast(ota_err)); + return static_cast(ota_err); + } + + /* Download the OTA file from the web storage location. */ + int const ota_download = ota.download(ota_url,"/update.bin"); + if (ota_download <= 0) + { + DEBUG_ERROR("OTAUpdate::download() failed with %d", ota_download); + return ota_download; + } + DEBUG_VERBOSE("OTAUpdate::download() %d bytes downloaded", static_cast(ota_download)); + + /* Verify update integrity */ + if ((ota_err = ota.verify()) != OTAUpdate::Error::None) + { + DEBUG_ERROR("OTAUpdate::verify() failed with %d", static_cast(ota_err)); + return static_cast(ota_err); + } + + /* Store update size and write OTA magin number */ + unor4_setOTASize(ota_download); + + /* Flash new firmware */ + if ((ota_err = ota.update("/update.bin")) != OTAUpdate::Error::None) + { + DEBUG_ERROR("OTAUpdate::update() failed with %d", static_cast(ota_err)); + return static_cast(ota_err); + } + + return static_cast(OTAUpdate::Error::None); +} + +String unor4_getOTAImageSHA256() +{ + /* The length of the application can be retrieved the same way it was + * communicated to the bootloader, that is by writing to the non-volatile + * storage registers of the RTC. + */ + SHA256 sha256; + uint32_t const app_start = 0x4000; + uint32_t const app_size = unor4_getOTASize(); + + flash_lp_instance_ctrl_t ctrl; + unor4_codeFlashOpen(&ctrl); + + sha256.begin(); + uint32_t b = 0; + uint32_t bytes_read = 0; for(uint32_t a = app_start; + bytes_read < app_size; + bytes_read += sizeof(b), a += sizeof(b)) + { + /* Read the next chunk of memory. */ + memcpy(&b, reinterpret_cast(a), sizeof(b)); + /* Feed it to SHA256. */ + sha256.update(reinterpret_cast(&b), sizeof(b)); + } + + unor4_codeFlashClose(&ctrl); + + /* Retrieve the final hash string. */ + uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; + sha256.finalize(sha256_hash); + String sha256_str; + std::for_each(sha256_hash, + sha256_hash + SHA256::HASH_SIZE, + [&sha256_str](uint8_t const elem) + { + char buf[4]; + snprintf(buf, 4, "%02X", elem); + sha256_str += buf; + }); + DEBUG_ERROR("SHA256: %d bytes (of %d) read", bytes_read, app_size); + return sha256_str; +} + +bool unor4_isOTACapable() +{ + /* check firmware version */ + String const fv = WiFi.firmwareVersion(); + if (fv < String("0.3.0")) { + return false; + } + return true; +} + +#endif /* ARDUINO_UNOR4_WIFI */ diff --git a/src/utility/ota/OTA.cpp b/src/utility/ota/OTA.cpp index bac388b59..e71aac5a2 100644 --- a/src/utility/ota/OTA.cpp +++ b/src/utility/ota/OTA.cpp @@ -55,6 +55,12 @@ String esp32_getOTAImageSHA256(); bool esp32_isOTACapable(); #endif +#ifdef ARDUINO_UNOR4_WIFI +int unor4_onOTARequest(char const * url); +String unor4_getOTAImageSHA256(); +bool unor4_isOTACapable(); +#endif + /****************************************************************************** * PUBLIC MEMBER FUNCTIONS ******************************************************************************/ @@ -74,6 +80,9 @@ int OTA::onRequest(String url, NetworkAdapter iface) #elif defined (ARDUINO_ARCH_ESP32) (void)iface; return esp32_onOTARequest(url.c_str()); +#elif defined (ARDUINO_UNOR4_WIFI) + (void)iface; + return unor4_onOTARequest(url.c_str()); #else #error "OTA not supported for this architecture" #endif @@ -89,6 +98,8 @@ String OTA::getImageSHA256() return portenta_h7_getOTAImageSHA256(); #elif defined (ARDUINO_ARCH_ESP32) return esp32_getOTAImageSHA256(); +#elif defined (ARDUINO_UNOR4_WIFI) + return unor4_getOTAImageSHA256(); #else #error "No method for SHA256 checksum calculation over application image defined for this architecture." #endif @@ -104,6 +115,8 @@ bool OTA::isCapable() return portenta_h7_isOTACapable(); #elif defined (ARDUINO_ARCH_ESP32) return esp32_isOTACapable(); +#elif defined (ARDUINO_UNOR4_WIFI) + return unor4_isOTACapable(); #else #error "OTA not supported for this architecture" #endif From b4f527553aecf5a8eabf93b4a10ca0e081a51e49 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 11 Sep 2023 12:33:00 +0200 Subject: [PATCH 451/780] Release v1.12.1 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 5d78ac4e9..19389967f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.12.0 +version=1.12.1 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 6e65e1be3..a3003133d 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -173,6 +173,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.12.0" +#define AIOT_CONFIG_LIB_VERSION "1.12.1" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From a4d0fbc5d0421236fdc135bba30d23bb7d29d9d9 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 20 Sep 2023 12:43:40 +0200 Subject: [PATCH 452/780] Avoid calling onchange callback on sync event if property isn't changed --- src/property/Property.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index 326e25584..89bbf0734 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -394,8 +394,10 @@ void onAutoSync(Property & property) { } void onForceCloudSync(Property & property) { - property.fromCloudToLocal(); - property.execCallbackOnChange(); + if (property.isDifferentFromCloud()) { + property.fromCloudToLocal(); + property.execCallbackOnChange(); + } } void onForceDeviceSync(Property & /* property */) { From 81b0b114f9e1b9f3f2193f7ee7d13c2f2bf1d47d Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 26 Sep 2023 15:54:32 +0200 Subject: [PATCH 453/780] ESP32: Use certificate bundle Add missing root certificates --- src/ArduinoIoTCloudTCP.cpp | 4 +- src/tls/AIoTCUPCert.h | 228 ++++++++++++++++++++++++++++++++----- 2 files changed, 200 insertions(+), 32 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 9858cd75b..97a15de6d 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -39,7 +39,7 @@ #include "tls/utility/CryptoUtil.h" #endif -#ifdef BOARD_HAS_SECRET_KEY +#ifdef ARDUINO_ARCH_ESP32 #include "tls/AIoTCUPCert.h" #endif @@ -179,7 +179,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #if defined(ARDUINO_ARCH_ESP8266) _sslClient.setInsecure(); #else - _sslClient.setCACert(AAIoTUPCert); + _sslClient.setCACertBundle(x509_crt_bundle); #endif #endif diff --git a/src/tls/AIoTCUPCert.h b/src/tls/AIoTCUPCert.h index 8f10f4d9d..58a01737d 100644 --- a/src/tls/AIoTCUPCert.h +++ b/src/tls/AIoTCUPCert.h @@ -24,41 +24,209 @@ ******************************************************************************/ #include -#ifdef BOARD_HAS_SECRET_KEY +#ifdef ARDUINO_ARCH_ESP32 /****************************************************************************** * CONSTANTS ******************************************************************************/ -//https://www.amazontrust.com/repository/Amazon-RSA-2048-M01.pem -static const char AAIoTUPCert[] = -"-----BEGIN CERTIFICATE-----\n" -"MIIEXjCCA0agAwIBAgITB3MSOAudZoijOx7Zv5zNpo4ODzANBgkqhkiG9w0BAQsF\n" -"ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" -"b24gUm9vdCBDQSAxMB4XDTIyMDgyMzIyMjEyOFoXDTMwMDgyMzIyMjEyOFowPDEL\n" -"MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEcMBoGA1UEAxMTQW1hem9uIFJT\n" -"QSAyMDQ4IE0wMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOtxLKnL\n" -"H4gokjIwr4pXD3i3NyWVVYesZ1yX0yLI2qIUZ2t88Gfa4gMqs1YSXca1R/lnCKeT\n" -"epWSGA+0+fkQNpp/L4C2T7oTTsddUx7g3ZYzByDTlrwS5HRQQqEFE3O1T5tEJP4t\n" -"f+28IoXsNiEzl3UGzicYgtzj2cWCB41eJgEmJmcf2T8TzzK6a614ZPyq/w4CPAff\n" -"nAV4coz96nW3AyiE2uhuB4zQUIXvgVSycW7sbWLvj5TDXunEpNCRwC4kkZjK7rol\n" -"jtT2cbb7W2s4Bkg3R42G3PLqBvt2N32e/0JOTViCk8/iccJ4sXqrS1uUN4iB5Nmv\n" -"JK74csVl+0u0UecCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYD\n" -"VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNV\n" -"HQ4EFgQUgbgOY4qJEhjl+js7UJWf5uWQE4UwHwYDVR0jBBgwFoAUhBjMhTTsvAyU\n" -"lC4IWZzHshBOCggwewYIKwYBBQUHAQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8v\n" -"b2NzcC5yb290Y2ExLmFtYXpvbnRydXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDov\n" -"L2NydC5yb290Y2ExLmFtYXpvbnRydXN0LmNvbS9yb290Y2ExLmNlcjA/BgNVHR8E\n" -"ODA2MDSgMqAwhi5odHRwOi8vY3JsLnJvb3RjYTEuYW1hem9udHJ1c3QuY29tL3Jv\n" -"b3RjYTEuY3JsMBMGA1UdIAQMMAowCAYGZ4EMAQIBMA0GCSqGSIb3DQEBCwUAA4IB\n" -"AQCtAN4CBSMuBjJitGuxlBbkEUDeK/pZwTXv4KqPK0G50fOHOQAd8j21p0cMBgbG\n" -"kfMHVwLU7b0XwZCav0h1ogdPMN1KakK1DT0VwA/+hFvGPJnMV1Kx2G4S1ZaSk0uU\n" -"5QfoiYIIano01J5k4T2HapKQmmOhS/iPtuo00wW+IMLeBuKMn3OLn005hcrOGTad\n" -"hcmeyfhQP7Z+iKHvyoQGi1C0ClymHETx/chhQGDyYSWqB/THwnN15AwLQo0E5V9E\n" -"SJlbe4mBlqeInUsNYugExNf+tOiybcrswBy8OFsd34XOW3rjSUtsuafd9AWySa3h\n" -"xRRrwszrzX/WWGm6wyB+f7C4\n" -"-----END CERTIFICATE-----\n"; +/* This certificate bundle is created using the following certificates: -#endif /* #ifdef BOARD_HAS_SECRET_KEY */ + * https://www.amazontrust.com/repository/AmazonRootCA1.pem + * https://www.amazontrust.com/repository/AmazonRootCA2.pem + * https://www.amazontrust.com/repository/AmazonRootCA3.pem + * https://www.amazontrust.com/repository/AmazonRootCA4.pem + * https://www.amazontrust.com/repository/SFSRootCAG2.pem + * https://certs.secureserver.net/repository/sf-class2-root.crt + + */ + +static const unsigned char x509_crt_bundle[] = { + 0x00, 0x06, 0x00, 0x3b, 0x01, 0x26, 0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, + 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x06, 0x41, 0x6d, 0x61, 0x7a, + 0x6f, 0x6e, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x10, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, + 0x20, 0x43, 0x41, 0x20, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xb2, 0x78, 0x80, 0x71, 0xca, 0x78, 0xd5, 0xe3, 0x71, 0xaf, + 0x47, 0x80, 0x50, 0x74, 0x7d, 0x6e, 0xd8, 0xd7, 0x88, 0x76, 0xf4, 0x99, + 0x68, 0xf7, 0x58, 0x21, 0x60, 0xf9, 0x74, 0x84, 0x01, 0x2f, 0xac, 0x02, + 0x2d, 0x86, 0xd3, 0xa0, 0x43, 0x7a, 0x4e, 0xb2, 0xa4, 0xd0, 0x36, 0xba, + 0x01, 0xbe, 0x8d, 0xdb, 0x48, 0xc8, 0x07, 0x17, 0x36, 0x4c, 0xf4, 0xee, + 0x88, 0x23, 0xc7, 0x3e, 0xeb, 0x37, 0xf5, 0xb5, 0x19, 0xf8, 0x49, 0x68, + 0xb0, 0xde, 0xd7, 0xb9, 0x76, 0x38, 0x1d, 0x61, 0x9e, 0xa4, 0xfe, 0x82, + 0x36, 0xa5, 0xe5, 0x4a, 0x56, 0xe4, 0x45, 0xe1, 0xf9, 0xfd, 0xb4, 0x16, + 0xfa, 0x74, 0xda, 0x9c, 0x9b, 0x35, 0x39, 0x2f, 0xfa, 0xb0, 0x20, 0x50, + 0x06, 0x6c, 0x7a, 0xd0, 0x80, 0xb2, 0xa6, 0xf9, 0xaf, 0xec, 0x47, 0x19, + 0x8f, 0x50, 0x38, 0x07, 0xdc, 0xa2, 0x87, 0x39, 0x58, 0xf8, 0xba, 0xd5, + 0xa9, 0xf9, 0x48, 0x67, 0x30, 0x96, 0xee, 0x94, 0x78, 0x5e, 0x6f, 0x89, + 0xa3, 0x51, 0xc0, 0x30, 0x86, 0x66, 0xa1, 0x45, 0x66, 0xba, 0x54, 0xeb, + 0xa3, 0xc3, 0x91, 0xf9, 0x48, 0xdc, 0xff, 0xd1, 0xe8, 0x30, 0x2d, 0x7d, + 0x2d, 0x74, 0x70, 0x35, 0xd7, 0x88, 0x24, 0xf7, 0x9e, 0xc4, 0x59, 0x6e, + 0xbb, 0x73, 0x87, 0x17, 0xf2, 0x32, 0x46, 0x28, 0xb8, 0x43, 0xfa, 0xb7, + 0x1d, 0xaa, 0xca, 0xb4, 0xf2, 0x9f, 0x24, 0x0e, 0x2d, 0x4b, 0xf7, 0x71, + 0x5c, 0x5e, 0x69, 0xff, 0xea, 0x95, 0x02, 0xcb, 0x38, 0x8a, 0xae, 0x50, + 0x38, 0x6f, 0xdb, 0xfb, 0x2d, 0x62, 0x1b, 0xc5, 0xc7, 0x1e, 0x54, 0xe1, + 0x77, 0xe0, 0x67, 0xc8, 0x0f, 0x9c, 0x87, 0x23, 0xd6, 0x3f, 0x40, 0x20, + 0x7f, 0x20, 0x80, 0xc4, 0x80, 0x4c, 0x3e, 0x3b, 0x24, 0x26, 0x8e, 0x04, + 0xae, 0x6c, 0x9a, 0xc8, 0xaa, 0x0d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x00, + 0x3b, 0x02, 0x26, 0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x13, 0x06, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x31, + 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6d, + 0x61, 0x7a, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, + 0x20, 0x32, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, + 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xad, + 0x96, 0x9f, 0x2d, 0x9c, 0x4a, 0x4c, 0x4a, 0x81, 0x79, 0x51, 0x99, 0xec, + 0x8a, 0xcb, 0x6b, 0x60, 0x51, 0x13, 0xbc, 0x4d, 0x6d, 0x06, 0xfc, 0xb0, + 0x08, 0x8d, 0xdd, 0x19, 0x10, 0x6a, 0xc7, 0x26, 0x0c, 0x35, 0xd8, 0xc0, + 0x6f, 0x20, 0x84, 0xe9, 0x94, 0xb1, 0x9b, 0x85, 0x03, 0xc3, 0x5b, 0xdb, + 0x4a, 0xe8, 0xc8, 0xf8, 0x90, 0x76, 0xd9, 0x5b, 0x4f, 0xe3, 0x4c, 0xe8, + 0x06, 0x36, 0x4d, 0xcc, 0x9a, 0xac, 0x3d, 0x0c, 0x90, 0x2b, 0x92, 0xd4, + 0x06, 0x19, 0x60, 0xac, 0x37, 0x44, 0x79, 0x85, 0x81, 0x82, 0xad, 0x5a, + 0x37, 0xe0, 0x0d, 0xcc, 0x9d, 0xa6, 0x4c, 0x52, 0x76, 0xea, 0x43, 0x9d, + 0xb7, 0x04, 0xd1, 0x50, 0xf6, 0x55, 0xe0, 0xd5, 0xd2, 0xa6, 0x49, 0x85, + 0xe9, 0x37, 0xe9, 0xca, 0x7e, 0xae, 0x5c, 0x95, 0x4d, 0x48, 0x9a, 0x3f, + 0xae, 0x20, 0x5a, 0x6d, 0x88, 0x95, 0xd9, 0x34, 0xb8, 0x52, 0x1a, 0x43, + 0x90, 0xb0, 0xbf, 0x6c, 0x05, 0xb9, 0xb6, 0x78, 0xb7, 0xea, 0xd0, 0xe4, + 0x3a, 0x3c, 0x12, 0x53, 0x62, 0xff, 0x4a, 0xf2, 0x7b, 0xbe, 0x35, 0x05, + 0xa9, 0x12, 0x34, 0xe3, 0xf3, 0x64, 0x74, 0x62, 0x2c, 0x3d, 0x00, 0x49, + 0x5a, 0x28, 0xfe, 0x32, 0x44, 0xbb, 0x87, 0xdd, 0x65, 0x27, 0x02, 0x71, + 0x3b, 0xda, 0x4a, 0xf7, 0x1f, 0xda, 0xcd, 0xf7, 0x21, 0x55, 0x90, 0x4f, + 0x0f, 0xec, 0xae, 0x82, 0xe1, 0x9f, 0x6b, 0xd9, 0x45, 0xd3, 0xbb, 0xf0, + 0x5f, 0x87, 0xed, 0x3c, 0x2c, 0x39, 0x86, 0xda, 0x3f, 0xde, 0xec, 0x72, + 0x55, 0xeb, 0x79, 0xa3, 0xad, 0xdb, 0xdd, 0x7c, 0xb0, 0xba, 0x1c, 0xce, + 0xfc, 0xde, 0x4f, 0x35, 0x76, 0xcf, 0x0f, 0xf8, 0x78, 0x1f, 0x6a, 0x36, + 0x51, 0x46, 0x27, 0x61, 0x5b, 0xe9, 0x9e, 0xcf, 0xf0, 0xa2, 0x55, 0x7d, + 0x7c, 0x25, 0x8a, 0x6f, 0x2f, 0xb4, 0xc5, 0xcf, 0x84, 0x2e, 0x2b, 0xfd, + 0x0d, 0x51, 0x10, 0x6c, 0xfb, 0x5f, 0x1b, 0xbc, 0x1b, 0x7e, 0xc5, 0xae, + 0x3b, 0x98, 0x01, 0x31, 0x92, 0xff, 0x0b, 0x57, 0xf4, 0x9a, 0xb2, 0xb9, + 0x57, 0xe9, 0xab, 0xef, 0x0d, 0x76, 0xd1, 0xf0, 0xee, 0xf4, 0xce, 0x86, + 0xa7, 0xe0, 0x6e, 0xe9, 0xb4, 0x69, 0xa1, 0xdf, 0x69, 0xf6, 0x33, 0xc6, + 0x69, 0x2e, 0x97, 0x13, 0x9e, 0xa5, 0x87, 0xb0, 0x57, 0x10, 0x81, 0x37, + 0xc9, 0x53, 0xb3, 0xbb, 0x7f, 0xf6, 0x92, 0xd1, 0x9c, 0xd0, 0x18, 0xf4, + 0x92, 0x6e, 0xda, 0x83, 0x4f, 0xa6, 0x63, 0x99, 0x4c, 0xa5, 0xfb, 0x5e, + 0xef, 0x21, 0x64, 0x7a, 0x20, 0x5f, 0x6c, 0x64, 0x85, 0x15, 0xcb, 0x37, + 0xe9, 0x62, 0x0c, 0x0b, 0x2a, 0x16, 0xdc, 0x01, 0x2e, 0x32, 0xda, 0x3e, + 0x4b, 0xf5, 0x9e, 0x3a, 0xf6, 0x17, 0x40, 0x94, 0xef, 0x9e, 0x91, 0x08, + 0x86, 0xfa, 0xbe, 0x63, 0xa8, 0x5a, 0x33, 0xec, 0xcb, 0x74, 0x43, 0x95, + 0xf9, 0x6c, 0x69, 0x52, 0x36, 0xc7, 0x29, 0x6f, 0xfc, 0x55, 0x03, 0x5c, + 0x1f, 0xfb, 0x9f, 0xbd, 0x47, 0xeb, 0xe7, 0x49, 0x47, 0x95, 0x0b, 0x4e, + 0x89, 0x22, 0x09, 0x49, 0xe0, 0xf5, 0x61, 0x1e, 0xf1, 0xbf, 0x2e, 0x8a, + 0x72, 0x6e, 0x80, 0x59, 0xff, 0x57, 0x3a, 0xf9, 0x75, 0x32, 0xa3, 0x4e, + 0x5f, 0xec, 0xed, 0x28, 0x62, 0xd9, 0x4d, 0x73, 0xf2, 0xcc, 0x81, 0x17, + 0x60, 0xed, 0xcd, 0xeb, 0xdc, 0xdb, 0xa7, 0xca, 0xc5, 0x7e, 0x02, 0xbd, + 0xf2, 0x54, 0x08, 0x54, 0xfd, 0xb4, 0x2d, 0x09, 0x2c, 0x17, 0x54, 0x4a, + 0x98, 0xd1, 0x54, 0xe1, 0x51, 0x67, 0x08, 0xd2, 0xed, 0x6e, 0x7e, 0x6f, + 0x3f, 0xd2, 0x2d, 0x81, 0x59, 0x29, 0x66, 0xcb, 0x90, 0x39, 0x95, 0x11, + 0x1e, 0x74, 0x27, 0xfe, 0xdd, 0xeb, 0xaf, 0x02, 0x03, 0x01, 0x00, 0x01, + 0x00, 0x3b, 0x00, 0x5b, 0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, 0x0d, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x06, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, + 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, + 0x41, 0x20, 0x33, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, + 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x29, 0x97, 0xa7, 0xc6, 0x41, 0x7f, + 0xc0, 0x0d, 0x9b, 0xe8, 0x01, 0x1b, 0x56, 0xc6, 0xf2, 0x52, 0xa5, 0xba, + 0x2d, 0xb2, 0x12, 0xe8, 0xd2, 0x2e, 0xd7, 0xfa, 0xc9, 0xc5, 0xd8, 0xaa, + 0x6d, 0x1f, 0x73, 0x81, 0x3b, 0x3b, 0x98, 0x6b, 0x39, 0x7c, 0x33, 0xa5, + 0xc5, 0x4e, 0x86, 0x8e, 0x80, 0x17, 0x68, 0x62, 0x45, 0x57, 0x7d, 0x44, + 0x58, 0x1d, 0xb3, 0x37, 0xe5, 0x67, 0x08, 0xeb, 0x66, 0xde, 0x00, 0x3b, + 0x00, 0x78, 0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x06, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6d, 0x61, + 0x7a, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x34, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, + 0x04, 0xd2, 0xab, 0x8a, 0x37, 0x4f, 0xa3, 0x53, 0x0d, 0xfe, 0xc1, 0x8a, + 0x7b, 0x4b, 0xa8, 0x7b, 0x46, 0x4b, 0x63, 0xb0, 0x62, 0xf6, 0x2d, 0x1b, + 0xdb, 0x08, 0x71, 0x21, 0xd2, 0x00, 0xe8, 0x63, 0xbd, 0x9a, 0x27, 0xfb, + 0xf0, 0x39, 0x6e, 0x5d, 0xea, 0x3d, 0xa5, 0xc9, 0x81, 0xaa, 0xa3, 0x5b, + 0x20, 0x98, 0x45, 0x5d, 0x16, 0xdb, 0xfd, 0xe8, 0x10, 0x6d, 0xe3, 0x9c, + 0xe0, 0xe3, 0xbd, 0x5f, 0x84, 0x62, 0xf3, 0x70, 0x64, 0x33, 0xa0, 0xcb, + 0x24, 0x2f, 0x70, 0xba, 0x88, 0xa1, 0x2a, 0xa0, 0x75, 0xf8, 0x81, 0xae, + 0x62, 0x06, 0xc4, 0x81, 0xdb, 0x39, 0x6e, 0x29, 0xb0, 0x1e, 0xfa, 0x2e, + 0x5c, 0x00, 0x6a, 0x01, 0x24, 0x30, 0x68, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, + 0x6f, 0x67, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, + 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x29, 0x53, 0x74, + 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x43, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x20, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x0d, 0x00, 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xb7, 0x32, 0xc8, 0xfe, 0xe9, 0x71, 0xa6, 0x04, 0x85, 0xad, 0x0c, 0x11, + 0x64, 0xdf, 0xce, 0x4d, 0xef, 0xc8, 0x03, 0x18, 0x87, 0x3f, 0xa1, 0xab, + 0xfb, 0x3c, 0xa6, 0x9f, 0xf0, 0xc3, 0xa1, 0xda, 0xd4, 0xd8, 0x6e, 0x2b, + 0x53, 0x90, 0xfb, 0x24, 0xa4, 0x3e, 0x84, 0xf0, 0x9e, 0xe8, 0x5f, 0xec, + 0xe5, 0x27, 0x44, 0xf5, 0x28, 0xa6, 0x3f, 0x7b, 0xde, 0xe0, 0x2a, 0xf0, + 0xc8, 0xaf, 0x53, 0x2f, 0x9e, 0xca, 0x05, 0x01, 0x93, 0x1e, 0x8f, 0x66, + 0x1c, 0x39, 0xa7, 0x4d, 0xfa, 0x5a, 0xb6, 0x73, 0x04, 0x25, 0x66, 0xeb, + 0x77, 0x7f, 0xe7, 0x59, 0xc6, 0x4a, 0x99, 0x25, 0x14, 0x54, 0xeb, 0x26, + 0xc7, 0xf3, 0x7f, 0x19, 0xd5, 0x30, 0x70, 0x8f, 0xaf, 0xb0, 0x46, 0x2a, + 0xff, 0xad, 0xeb, 0x29, 0xed, 0xd7, 0x9f, 0xaa, 0x04, 0x87, 0xa3, 0xd4, + 0xf9, 0x89, 0xa5, 0x34, 0x5f, 0xdb, 0x43, 0x91, 0x82, 0x36, 0xd9, 0x66, + 0x3c, 0xb1, 0xb8, 0xb9, 0x82, 0xfd, 0x9c, 0x3a, 0x3e, 0x10, 0xc8, 0x3b, + 0xef, 0x06, 0x65, 0x66, 0x7a, 0x9b, 0x19, 0x18, 0x3d, 0xff, 0x71, 0x51, + 0x3c, 0x30, 0x2e, 0x5f, 0xbe, 0x3d, 0x77, 0x73, 0xb2, 0x5d, 0x06, 0x6c, + 0xc3, 0x23, 0x56, 0x9a, 0x2b, 0x85, 0x26, 0x92, 0x1c, 0xa7, 0x02, 0xb3, + 0xe4, 0x3f, 0x0d, 0xaf, 0x08, 0x79, 0x82, 0xb8, 0x36, 0x3d, 0xea, 0x9c, + 0xd3, 0x35, 0xb3, 0xbc, 0x69, 0xca, 0xf5, 0xcc, 0x9d, 0xe8, 0xfd, 0x64, + 0x8d, 0x17, 0x80, 0x33, 0x6e, 0x5e, 0x4a, 0x5d, 0x99, 0xc9, 0x1e, 0x87, + 0xb4, 0x9d, 0x1a, 0xc0, 0xd5, 0x6e, 0x13, 0x35, 0x23, 0x5e, 0xdf, 0x9b, + 0x5f, 0x3d, 0xef, 0xd6, 0xf7, 0x76, 0xc2, 0xea, 0x3e, 0xbb, 0x78, 0x0d, + 0x1c, 0x42, 0x67, 0x6b, 0x04, 0xd8, 0xf8, 0xd6, 0xda, 0x6f, 0x8b, 0xf2, + 0x44, 0xa0, 0x01, 0xab, 0x02, 0x01, 0x03, 0x00, 0x9b, 0x01, 0x26, 0x30, + 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74, + 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, + 0x69, 0x65, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x3b, 0x30, + 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, 0x72, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, 0x82, + 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, + 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd5, 0x0c, 0x3a, 0xc4, 0x2a, + 0xf9, 0x4e, 0xe2, 0xf5, 0xbe, 0x19, 0x97, 0x5f, 0x8e, 0x88, 0x53, 0xb1, + 0x1f, 0x3f, 0xcb, 0xcf, 0x9f, 0x20, 0x13, 0x6d, 0x29, 0x3a, 0xc8, 0x0f, + 0x7d, 0x3c, 0xf7, 0x6b, 0x76, 0x38, 0x63, 0xd9, 0x36, 0x60, 0xa8, 0x9b, + 0x5e, 0x5c, 0x00, 0x80, 0xb2, 0x2f, 0x59, 0x7f, 0xf6, 0x87, 0xf9, 0x25, + 0x43, 0x86, 0xe7, 0x69, 0x1b, 0x52, 0x9a, 0x90, 0xe1, 0x71, 0xe3, 0xd8, + 0x2d, 0x0d, 0x4e, 0x6f, 0xf6, 0xc8, 0x49, 0xd9, 0xb6, 0xf3, 0x1a, 0x56, + 0xae, 0x2b, 0xb6, 0x74, 0x14, 0xeb, 0xcf, 0xfb, 0x26, 0xe3, 0x1a, 0xba, + 0x1d, 0x96, 0x2e, 0x6a, 0x3b, 0x58, 0x94, 0x89, 0x47, 0x56, 0xff, 0x25, + 0xa0, 0x93, 0x70, 0x53, 0x83, 0xda, 0x84, 0x74, 0x14, 0xc3, 0x67, 0x9e, + 0x04, 0x68, 0x3a, 0xdf, 0x8e, 0x40, 0x5a, 0x1d, 0x4a, 0x4e, 0xcf, 0x43, + 0x91, 0x3b, 0xe7, 0x56, 0xd6, 0x00, 0x70, 0xcb, 0x52, 0xee, 0x7b, 0x7d, + 0xae, 0x3a, 0xe7, 0xbc, 0x31, 0xf9, 0x45, 0xf6, 0xc2, 0x60, 0xcf, 0x13, + 0x59, 0x02, 0x2b, 0x80, 0xcc, 0x34, 0x47, 0xdf, 0xb9, 0xde, 0x90, 0x65, + 0x6d, 0x02, 0xcf, 0x2c, 0x91, 0xa6, 0xa6, 0xe7, 0xde, 0x85, 0x18, 0x49, + 0x7c, 0x66, 0x4e, 0xa3, 0x3a, 0x6d, 0xa9, 0xb5, 0xee, 0x34, 0x2e, 0xba, + 0x0d, 0x03, 0xb8, 0x33, 0xdf, 0x47, 0xeb, 0xb1, 0x6b, 0x8d, 0x25, 0xd9, + 0x9b, 0xce, 0x81, 0xd1, 0x45, 0x46, 0x32, 0x96, 0x70, 0x87, 0xde, 0x02, + 0x0e, 0x49, 0x43, 0x85, 0xb6, 0x6c, 0x73, 0xbb, 0x64, 0xea, 0x61, 0x41, + 0xac, 0xc9, 0xd4, 0x54, 0xdf, 0x87, 0x2f, 0xc7, 0x22, 0xb2, 0x26, 0xcc, + 0x9f, 0x59, 0x54, 0x68, 0x9f, 0xfc, 0xbe, 0x2a, 0x2f, 0xc4, 0x55, 0x1c, + 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, 0x39, 0x8b, 0x7f, 0x05, 0x02, + 0x03, 0x01, 0x00, 0x01 +}; +unsigned int x509_crt_bundle_len = 2164; + + +#endif /* #ifdef ARDUINO_ARCH_ESP32 */ #endif /* _AIOTC_UP_CERT_H_ */ From 967290694df358e8f6ee0325392229f0689e4c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20S=C3=B6derby?= <35461661+karlsoderby@users.noreply.github.com> Date: Wed, 27 Sep 2023 11:05:50 +0200 Subject: [PATCH 454/780] IoT Cloud Docs --- docs/api.md | 531 +++++++++++++++++++++++++++++++++++++++++++++++++ docs/readme.md | 23 +++ 2 files changed, 554 insertions(+) create mode 100644 docs/api.md create mode 100644 docs/readme.md diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 000000000..913319fac --- /dev/null +++ b/docs/api.md @@ -0,0 +1,531 @@ +## ArduinoCloud Class (Base) + +### `ArduinoCloud (Class)` + +#### Description + +`ArduinoIoTCloud` is a class for interfacing with the Arduino IoT Cloud. It provides an interface for managing IoT Cloud connectivity, updating data, and handling events. + +Depending on what type of connection is used (TCP/LPWAN), either the `ArduinoIoTCloudTCP` or `ArduinoIoTCloudLPWAN` base classes are initialized. This specification is done in the Arduino IoT Cloud's "Thing" interface, and is reflected in the automatically generated `thingProperties.h` file. + +The above classes are inherited from the `ArduinoIoTCloudClass` base class, with methods used depending on what connection is used. + +#### Syntax + +``` +ArduinoCloud.method() +``` + +### `push()` + +#### Description + +Pushes data to the IoT Cloud. + +#### Syntax + +``` +ArduinoCloud.push() +``` + +#### Parameters + +None. + +#### Returns + +Nothing. + +### `setTimestamp()` + +Sets a timestamp for a cloud variable. + +#### Syntax + +``` +ArduinoCloud.setTimestamp(cloudVariable, timestamp) +``` + +#### Parameters + +- `String` - property name +- `unsigned long const` - timestamp + +### `setThingId()` + +Sets the Thing ID. + +#### Syntax + +``` +ArduinoCloud.setThingId(thingId) +``` + +#### Parameters +- `String` - your Thing's ID. Obtainable in the IoT Cloud interface. + +### `String & getThingId()` + +Gets the Thing ID. + +#### Syntax + +#### Parameters + +### `setDeviceId()` + +Sets the Device ID. + +#### Syntax + +``` +ArduinoCloud.setDeviceId(deviceId) +``` + +#### Parameters + +- `String` - Device ID. + +### `getDeviceId()` + +Gets the Device ID. + +#### Syntax + +``` +ArduinoCloud.getDeviceId() +``` + +#### Parameters + +None + +#### Returns + +- `String` - Device ID. + +### `setThingIdOutdatedFlag()` + +Sets a flag indicating that the Thing ID is outdated. + +#### Syntax + +``` +ArduinoCloud.setThingIdOutdatedFlag() +``` + +#### Parameters +None. + +#### Returns +Nothing. + +### `clrThingIdOutdatedFlag()` + +Clears the flag indicating that the Thing ID is outdated. + +#### Syntax + +``` +ArduinoCloud.clrThingIdOutdatedFlag() +``` + +#### Parameters +None. + +#### Returns +Nothing. + +### `getThingIdOutdatedFlag()` + +Gets the flag indicating whether the Thing ID is outdated. + +#### Syntax + +``` +ArduinoCloud.getThingOutdatedFlag() +``` + +#### Parameters +None. + +#### Returns +- Boolean (true/false) + +### `deviceNotAttached()` + +Checks if the device is not attached. + +#### Syntax + +``` +ArduinoCloud.deviceNotAttached() +``` + +#### Parameters +None. + +#### Returns + +- Boolean (true/false) + +### `getConnection()` + +Gets the connection handler used. + +#### Syntax + +``` +ArduinoCloud.getConnection() +``` + +#### Parameters + +### `getInternalTime()` + +Gets the internal time. + +#### Syntax + +``` +ArduinoCloud.getInternalTime() +``` + +#### Parameters +None. + +#### Returns +- `unsigned long` - internal time + +### `getLocalTime()` + +Gets the local time (based on your time zone). + +#### Syntax + +``` +ArduinoCloud.getLocalTime() +``` + +#### Parameters +None + +#### Returns +- `unsigned long` - local time + + +### `updateInternalTimezoneInfo()` + +Updates the internal timezone information. + +#### Syntax + +#### Parameters + +### `addCallback(ArduinoIoTCloudEvent const event, OnCloudEventCallback callback)` + +Adds a callback function for IoT Cloud events. + +#### Syntax + +``` +ArduinoCloud.addCallback(ArduinoIoTCloudEvent::CONNECT, doThisOnConnect); +ArduinoCloud.addCallback(ArduinoIoTCloudEvent::SYNC, doThisOnSync); +ArduinoCloud.addCallback(ArduinoIoTCloudEvent::DISCONNECT, doThisOnDisconnect); +``` + +#### Parameters +- Event (CONNECT, SYNC, DISCONNECT) +- Callback function + +#### Example + +See the [ArduinoIoTCloud-Callbacks](https://github.com/arduino-libraries/ArduinoIoTCloud/blob/master/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino) example. + + + +## ArduinoCloud Class (TCP) + +### `begin()` (TCP) + +#### Description + +Initialises the library with the connection handler specified in `thingProperties.h`. This is automatically generated based on the type of device. + +#### Syntax + +``` +ArduinoCloud.begin() +``` + +#### Parameters + +The `ArduinoIoTPreferredConnection` object is created automatically inside a `thingProperties.h` file when configuring a Thing and depends on what type of device you use. The connection handler classes are not part of the Arduino IoT Cloud, but exists inside the [Arduino_ConnectionHandler](https://github.com/arduino-libraries/Arduino_ConnectionHandler) library (listed as a dependency). + +For example, using the `WiFiConnectionHandler`, we use the `SSID`, `PASS` parameters which are defined in the `arduino_secrets.h` file, also generated based on what you input in the Arduino IoT Cloud interface. + +``` +WiFiConnectionHandler ArduinoIoTPreferredConnection(SSID, PASS); +``` + +#### Returns +Nothing. + +### `update()` (TCP) + +#### Description + +**Note:** for LoRa devices, the `update()` function is implemented differently. See + +Responsible for updating the IoT Cloud connection. +- First it feeds a watchdog timer, making sure it is not stuck anywhere, +- then sends variable updates to the IoT Cloud (via MQTT client) +- finally, it checks for new data from the IoT Cloud (via the MQTT client) + +Any IoT Cloud sketch needs to continuously call the `update()` function, as it will otherwise time out and reset. The `update()` is by default placed inside of the `loop()`. + +**Note:** do not use the `delay()` function in the sketch, as the watchdog timer will cause the board to reset and attempt to reconnect. + +#### Syntax + +``` +ArduinoCloud.update() +``` + +#### Parameters +None. + +#### Returns +Nothing. + + +### `connected()` (TCP) + +#### Description + +Checks the connection status and returns an integer the connection status (int). + +#### Syntax + +``` +ArduinoCloud.connected() +``` + +#### Parameters +None. + +#### Returns +- `int` - status of connection + +### `printDebugInfo()` (TCP) + +#### Description + +Print any available debug information. + +#### Parameters +None + +#### Returns +Nothing. + +### `setBoardId()` + +#### Description + +This method is only enabled if you are using an ESP32/ESP8266 board, and sets the board/device id. + +#### Syntax + +``` +ArduinoCloud.setBoardId(DEVICE_LOGIN_NAME); +``` + +### `setSecretDeviceKey()` + +#### Description + +This method is only enabled if you are using an ESP32/ESP8266 based board, and sets the secret device key for the device. The secret key is only obtainable from the Arduino IoT Cloud during device configuration. + +#### Syntax + +``` +ArduinoCloud.setSecretDeviceKey(DEVICE_KEY); +``` + +### `getBrokerAddress()` + +#### Description + +Get the MQTT broker address used. + +#### Syntax + +``` +ArduinoCloud.getBrokerAddress() +``` + +#### Parameters +None. + +#### Return +- `String` - the MQTT broker address. + +### `getBrokerPort()` + +#### Description + +Get the MQTT broker port used. + +#### Syntax + +``` +ArduinoCloud.getBrokerPort() +``` + +#### Parameters +None. + +#### Return +- `int` - the MQTT broker port. + + + +## ArduinoCloud Class (LPWAN) + +### `begin()` (LPWAN) + +### Description +This function initializes the ArduinoIoTCloudLPWAN library with the specified connection handler and retry settings. + +#### Parameters +- `ConnectionHandler` - object containing `APPEUI`, `APPKEY` and frequency band (e.g. `_lora_band::EU868`) +- `bool` - a boolean value that decides whether retry functionality is enabled (`true`) or disabled (`false`) + +#### Returns + +- `int` - returns `1` on successful initialization. + +### `update()` (LPWAN) + +#### Description + +**Note:** for TCP devices, the `update()` function is implemented differently. See [ArduinoCloud Class (TCP)](). + +Responsible for updating the IoT Cloud connection. +- First it feeds a watchdog timer, making sure it is not stuck anywhere, +- then sends variable updates to the IoT Cloud (via MQTT client) +- finally, it checks for new data from the IoT Cloud (via the MQTT client) + +Any IoT Cloud sketch needs to continuously call the `update()` function, as it will otherwise time out and reset. The `update()` is by default placed inside of the `loop()`. + +**Note:** do not use the `delay()` function in the sketch, as the watchdog timer will cause the board to reset and attempt to reconnect. + +#### Syntax + +``` +ArduinoCloud.update() +``` + +#### Parameters +None. + +#### Returns +Nothing. + + +### `connected()` (LPWAN) + +#### Description + +Checks the connection status and returns an integer the connection status (int). + +#### Syntax + +``` +ArduinoCloud.connected() +``` + +#### Parameters +None. + +#### Returns +- `int` - status of connection + +### `printDebugInfo()` (LPWAN) + +#### Description + +Print any available debug information. + +#### Parameters +None. + +#### Returns +Nothing. + +## `isRetryEnabled()` + +#### Description +This method is used to check whether retry functionality is enabled. + +#### Parameters +None. + +#### Returns +- `bool` - returns `true` if retry functionality is enabled, otherwise returns `false`. + + +### `getMaxRetry()` + +#### Description +This method is used to retrieve the maximum number of retry attempts. + +#### Parameters +None. + +#### Returns +- `int` - returns the maximum number of retry attempts as an integer. + +### `getIntervalRetry()` + +#### Description +This method is used to retrieve the interval in milliseconds between the retry attempts. + +#### Parameters +None. + +#### Returns +- `long` - returns the interval between retry attempts in milliseconds. + +### `enableRetry()` + +#### Description +This method is used to enable or disable retry functionality. + +#### Parameters +- `bool` - if `true`, retry functionality is enabled; if `false`, retry functionality is disabled. + +#### Returns +Nothing. + +### `setMaxRetry()` + +Used to set the maximum number of retry attempts. + +#### Parameters +- `int` - the maximum number of retry attempts to set. + +#### Returns +Nothing. + +### `setIntervalRetry()` + +#### Description +Sets the interval in milliseconds between retry attempts. + +#### Parameters +- `long` - the interval between retry attempts in milliseconds to set. + +#### Returns +Nothing. \ No newline at end of file diff --git a/docs/readme.md b/docs/readme.md new file mode 100644 index 000000000..b4c95612f --- /dev/null +++ b/docs/readme.md @@ -0,0 +1,23 @@ +# ArduinoIoTCloud + +The ArduinoIoTCloud library is the central element of the firmware enabling certain Arduino boards to connect to the [Arduino IoT Cloud](https://create.arduino.cc/iot/). + +- To get started, check out the [official documentation](https://docs.arduino.cc/arduino-cloud/) +- For source code, check out the [GitHub repository](https://github.com/arduino-libraries/ArduinoIoTCloud) + + +## TCP / LPWAN + +Depending on what type of connection is used (TCP/LPWAN), either the `ArduinoIoTCloudTCP` or `ArduinoIoTCloudLPWAN` base classes are initialized. This specification is done in the Arduino IoT Cloud's "Thing" interface, and is reflected in the automatically generated `thingProperties.h` file. + +- If a board is configured as a **TCP** device, it will automatically include the `ArduinoIoTCloudTCP.h` file, and methods of the `ArduinoIoTCloudTCP` class will be made available. This is the most common option. +- If a board is configured as an **LPWAN** device, it will instead include the `ArduinoIoTCloudLPWAN.h` file, and methods of the `ArduinoIoTCloudLPWAN` class will be made available. + +As a result, functions such as `begin()`, `update()`, `connected()` and `printDebugInfo()` are documented under each corresponding class. + +## Connection Handler Library + +When the library is initalized via the `begin()` function, it will choose the specified **connection handler**, which is automatically added to your `thingProperties.h` file when configuring a Thing. + +The connection handler is done via another library, [Arduino_ConnectionHandler](https://github.com/arduino-libraries/Arduino_ConnectionHandler), which supports Wi-Fi®, GSM, NB-IoT, LoRa® & Ethernet. + From 9f3cd5a4fba87c278296c135431a0c4c1944abef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20S=C3=B6derby?= <35461661+karlsoderby@users.noreply.github.com> Date: Wed, 27 Sep 2023 11:08:11 +0200 Subject: [PATCH 455/780] Update readme.md --- docs/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/readme.md b/docs/readme.md index b4c95612f..b14ec789e 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -17,7 +17,7 @@ As a result, functions such as `begin()`, `update()`, `connected()` and `printDe ## Connection Handler Library -When the library is initalized via the `begin()` function, it will choose the specified **connection handler**, which is automatically added to your `thingProperties.h` file when configuring a Thing. +When the library is initialized via the `begin()` function, it will choose the specified **connection handler**, which is automatically added to your `thingProperties.h` file when configuring a Thing. The connection handler is done via another library, [Arduino_ConnectionHandler](https://github.com/arduino-libraries/Arduino_ConnectionHandler), which supports Wi-Fi®, GSM, NB-IoT, LoRa® & Ethernet. From 0bc469f4ec6c1ecf5030da5d79d9c0b36148fe7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20S=C3=B6derby?= <35461661+karlsoderby@users.noreply.github.com> Date: Wed, 27 Sep 2023 14:38:33 +0200 Subject: [PATCH 456/780] Added addProperty method --- docs/api.md | 43 ++++++++++++++++++++++++++++++++++++++++++- docs/readme.md | 13 +++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/docs/api.md b/docs/api.md index 913319fac..ad4dc29ff 100644 --- a/docs/api.md +++ b/docs/api.md @@ -222,7 +222,7 @@ Updates the internal timezone information. #### Parameters -### `addCallback(ArduinoIoTCloudEvent const event, OnCloudEventCallback callback)` +### `addCallback()` Adds a callback function for IoT Cloud events. @@ -329,6 +329,26 @@ None #### Returns Nothing. +### `addProperty()` (TCP) + +#### Description + +Adds a variable/property with a set of parameters. + +#### Syntax +``` +ArduinoCloud.addProperty(cloudVariable, tag, permission, policy, callbackFunction) +``` + +#### Parameters +- `cloudVariable` - name of the variable/property. +- `permission` - can either be `READ` / `WRITE` or `READWRITE` +- `policy` - `ON_CHANGE` (whenever variable data changes) or ` * SECONDS`. `` is specified in the Thing configuration. +- `callBackFunction` - by default, a callback function is added to a variable with **WRITE** permissions. A variable called `test` will automatically be added as `onTestChange` which also is added to your sketch. + +#### Returns +Nothing. + ### `setBoardId()` #### Description @@ -464,6 +484,27 @@ None. #### Returns Nothing. +### `addProperty()` (LPWAN) + +#### Description + +Adds a variable/property with a set of parameters. + +#### Syntax +``` +ArduinoCloud.addProperty(cloudVariable, tag, permission, policy, callbackFunction) +``` + +#### Parameters +- `cloudVariable` - name of the variable/property. +- `permission` - can either be `READ` / `WRITE` or `READWRITE` +- `tag` - matches the cloud and local variables with a number. E.g. adding a second variable will have the tag `2`. +- `policy` - `ON_CHANGE` (whenever variable data changes) or ` * SECONDS`. `` is specified in the Thing configuration. +- `callBackFunction` - by default, a callback function is added to a variable with **WRITE** permissions. A variable called `test` will automatically be added as `onTestChange` which also is added to your sketch. + +#### Returns +Nothing. + ## `isRetryEnabled()` #### Description diff --git a/docs/readme.md b/docs/readme.md index b14ec789e..16c3cea7b 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -5,6 +5,19 @@ The ArduinoIoTCloud library is the central element of the firmware enabling cert - To get started, check out the [official documentation](https://docs.arduino.cc/arduino-cloud/) - For source code, check out the [GitHub repository](https://github.com/arduino-libraries/ArduinoIoTCloud) +## thingProperties.h + +When you are create and configure a Thing in the [Arduino IoT Cloud interface](https://create.arduino.cc/iot/), the `thingProperties.h` file is generated automatically. + +This file adds all the variable/properties along with its specifications (e.g. update policy, read/write permissions), and the type of connection handler depending on what device you have attached. + +Methods such as `addProperty()` and `setThingId()` are implemented here, so there's no need for manually entering anything. + +We recommend that **you do not edit this file** as it is automatically updating whenever you make changes in the Arduino IoT Cloud. + +### Offline Editing + +If you have set up your sketch in an offline environment, make sure that whatever changes you make are reflected in this file, as it will be updated in the online environment. ## TCP / LPWAN From 732c2d9fbbcae19af72818bab04298a5ee77ec5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20S=C3=B6derby?= <35461661+karlsoderby@users.noreply.github.com> Date: Wed, 27 Sep 2023 14:55:44 +0200 Subject: [PATCH 457/780] Update based on feedback removed a number of methods that are not going to be public soon, and general revised some of the other methods --- docs/api.md | 57 +++++++++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/docs/api.md b/docs/api.md index ad4dc29ff..40aa89f6d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -51,26 +51,22 @@ ArduinoCloud.setTimestamp(cloudVariable, timestamp) - `String` - property name - `unsigned long const` - timestamp -### `setThingId()` -Sets the Thing ID. +### `getThingId()` + +Gets the Thing ID. #### Syntax ``` -ArduinoCloud.setThingId(thingId) +ArduinoCloud.getThingId() ``` #### Parameters -- `String` - your Thing's ID. Obtainable in the IoT Cloud interface. - -### `String & getThingId()` - -Gets the Thing ID. - -#### Syntax +None. -#### Parameters +#### Returns +- `String` - Thing ID. ### `setDeviceId()` @@ -214,14 +210,6 @@ None - `unsigned long` - local time -### `updateInternalTimezoneInfo()` - -Updates the internal timezone information. - -#### Syntax - -#### Parameters - ### `addCallback()` Adds a callback function for IoT Cloud events. @@ -355,6 +343,10 @@ Nothing. This method is only enabled if you are using an ESP32/ESP8266 board, and sets the board/device id. +Currently, the following official Arduino boards uses this method: +- [Arduino UNO R4 WiFi](https://store.arduino.cc/products/uno-r4-wifi) +- [Arduino Nano ESP32](https://store.arduino.cc/products/nano-esp32) + #### Syntax ``` @@ -430,16 +422,7 @@ This function initializes the ArduinoIoTCloudLPWAN library with the specified co #### Description -**Note:** for TCP devices, the `update()` function is implemented differently. See [ArduinoCloud Class (TCP)](). - -Responsible for updating the IoT Cloud connection. -- First it feeds a watchdog timer, making sure it is not stuck anywhere, -- then sends variable updates to the IoT Cloud (via MQTT client) -- finally, it checks for new data from the IoT Cloud (via the MQTT client) - -Any IoT Cloud sketch needs to continuously call the `update()` function, as it will otherwise time out and reset. The `update()` is by default placed inside of the `loop()`. - -**Note:** do not use the `delay()` function in the sketch, as the watchdog timer will cause the board to reset and attempt to reconnect. +This method handles the update between the board and the IoT Cloud. #### Syntax @@ -505,7 +488,21 @@ ArduinoCloud.addProperty(cloudVariable, tag, permission, policy, callbackFunctio #### Returns Nothing. -## `isRetryEnabled()` +### `setThingId()` + +Sets the Thing ID. + +#### Syntax + +``` +ArduinoCloud.setThingId(thingId) +``` + +#### Parameters +- `String` - your Thing's ID. Obtainable in the IoT Cloud interface. + + +### `isRetryEnabled()` #### Description This method is used to check whether retry functionality is enabled. From 7e66828df26bcdad2eb0fb0b466ea30526562b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20S=C3=B6derby?= <35461661+karlsoderby@users.noreply.github.com> Date: Wed, 27 Sep 2023 15:03:16 +0200 Subject: [PATCH 458/780] Update api.md --- docs/api.md | 65 ----------------------------------------------------- 1 file changed, 65 deletions(-) diff --git a/docs/api.md b/docs/api.md index 40aa89f6d..e4825e2d6 100644 --- a/docs/api.md +++ b/docs/api.md @@ -100,71 +100,6 @@ None - `String` - Device ID. -### `setThingIdOutdatedFlag()` - -Sets a flag indicating that the Thing ID is outdated. - -#### Syntax - -``` -ArduinoCloud.setThingIdOutdatedFlag() -``` - -#### Parameters -None. - -#### Returns -Nothing. - -### `clrThingIdOutdatedFlag()` - -Clears the flag indicating that the Thing ID is outdated. - -#### Syntax - -``` -ArduinoCloud.clrThingIdOutdatedFlag() -``` - -#### Parameters -None. - -#### Returns -Nothing. - -### `getThingIdOutdatedFlag()` - -Gets the flag indicating whether the Thing ID is outdated. - -#### Syntax - -``` -ArduinoCloud.getThingOutdatedFlag() -``` - -#### Parameters -None. - -#### Returns -- Boolean (true/false) - -### `deviceNotAttached()` - -Checks if the device is not attached. - -#### Syntax - -``` -ArduinoCloud.deviceNotAttached() -``` - -#### Parameters -None. - -#### Returns - -- Boolean (true/false) - ### `getConnection()` Gets the connection handler used. From 4929d5be5e03a66438feeb7e6b8b61c7432222f6 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Thu, 28 Sep 2023 10:07:59 +0200 Subject: [PATCH 459/780] Release v1.12.2 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 19389967f..81d8a2440 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.12.1 +version=1.12.2 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index a3003133d..c22609ee9 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -173,6 +173,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.12.1" +#define AIOT_CONFIG_LIB_VERSION "1.12.2" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From debfe4f529adbc6bba69f93c7a2591cb4318887b Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 9 Oct 2023 15:27:18 +0200 Subject: [PATCH 460/780] Fix typo in comments --- src/utility/ota/FlashSHA256.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility/ota/FlashSHA256.cpp b/src/utility/ota/FlashSHA256.cpp index cac4db619..85a1b4ebe 100644 --- a/src/utility/ota/FlashSHA256.cpp +++ b/src/utility/ota/FlashSHA256.cpp @@ -81,7 +81,7 @@ String FlashSHA256::calc(uint32_t const start_addr, uint32_t const max_flash_siz } /* We've read a normal segment with the next segment not containing - * any erased elements, just update the SHA256 hash calcultion. + * any erased elements, just update the SHA256 hash calculation. */ sha256.update(chunk, FLASH_READ_CHUNK_SIZE); bytes_read += FLASH_READ_CHUNK_SIZE; From 8373e9014b05fffb92ba95b1a3414965347edbd9 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 9 Mar 2022 15:13:40 +0100 Subject: [PATCH 461/780] Remove __AVR__ compile options to improve code clarity --- src/ArduinoIoTCloudTCP.cpp | 15 +- src/cbor/CBORDecoder.h | 4 - src/cbor/CBOREncoder.h | 4 - src/cbor/lib/tinycbor/src/cbor.h | 5 - src/cbor/lib/tinycbor/src/cborpretty.c | 4 - src/cbor/lib/tinycbor/src/cbortojson.c | 4 - src/cbor/lib/tinycbor/src/open_memstream.c | 4 - src/nonstd/nonstd.h | 235 --------------------- src/property/Property.cpp | 8 - src/property/Property.h | 15 -- src/property/PropertyContainer.h | 4 - src/utility/ota/FlashSHA256.cpp | 2 +- src/utility/time/TimeService.cpp | 2 - 13 files changed, 2 insertions(+), 304 deletions(-) delete mode 100644 src/nonstd/nonstd.h diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 97a15de6d..1efbf3f33 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -132,16 +132,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _brokerAddress = brokerAddress; _brokerPort = brokerPort; -#if defined(__AVR__) - String const nina_fw_version = WiFi.firmwareVersion(); - if (nina_fw_version < "1.4.2") - { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s NINA firmware needs to be >= 1.4.2 to support cloud on Uno WiFi Rev. 2, current %s", __FUNCTION__, nina_fw_version.c_str()); - return 0; - } -#endif /* AVR */ - -#if OTA_ENABLED && !defined(__AVR__) +#if OTA_ENABLED _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 */ @@ -483,18 +474,14 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() if (!_mqttClient.subscribe(_dataTopicIn)) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); -#if !defined(__AVR__) DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); -#endif return State::SubscribeThingTopics; } if (!_mqttClient.subscribe(_shadowTopicIn)) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); -#if !defined(__AVR__) DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); -#endif return State::SubscribeThingTopics; } diff --git a/src/cbor/CBORDecoder.h b/src/cbor/CBORDecoder.h index d1bf91ca0..5e9496b2a 100644 --- a/src/cbor/CBORDecoder.h +++ b/src/cbor/CBORDecoder.h @@ -24,10 +24,6 @@ #include -#ifdef __AVR__ -# include -#endif - #undef max #undef min #include diff --git a/src/cbor/CBOREncoder.h b/src/cbor/CBOREncoder.h index fa68d2200..cbba5522d 100644 --- a/src/cbor/CBOREncoder.h +++ b/src/cbor/CBOREncoder.h @@ -24,10 +24,6 @@ #include -#ifdef __AVR__ -# include -#endif - #undef max #undef min #include diff --git a/src/cbor/lib/tinycbor/src/cbor.h b/src/cbor/lib/tinycbor/src/cbor.h index 93d448daf..27a4fe4a8 100644 --- a/src/cbor/lib/tinycbor/src/cbor.h +++ b/src/cbor/lib/tinycbor/src/cbor.h @@ -25,11 +25,6 @@ #ifndef CBOR_H #define CBOR_H -#ifdef __AVR__ -#define FP_NAN NAN -#define FP_INFINITE INFINITY -#endif - #ifndef assert #include #endif diff --git a/src/cbor/lib/tinycbor/src/cborpretty.c b/src/cbor/lib/tinycbor/src/cborpretty.c index b82b985ac..2db4b253a 100644 --- a/src/cbor/lib/tinycbor/src/cborpretty.c +++ b/src/cbor/lib/tinycbor/src/cborpretty.c @@ -28,8 +28,6 @@ # define __STDC_LIMIT_MACROS 1 #endif -#ifndef __AVR__ - #include "cbor.h" #include "cborinternal_p.h" #include "compilersupport_p.h" @@ -582,6 +580,4 @@ CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *t #pragma GCC diagnostic pop -#endif // __AVR__ - /** @} */ diff --git a/src/cbor/lib/tinycbor/src/cbortojson.c b/src/cbor/lib/tinycbor/src/cbortojson.c index 0e669f27e..ed6a16666 100644 --- a/src/cbor/lib/tinycbor/src/cbortojson.c +++ b/src/cbor/lib/tinycbor/src/cbortojson.c @@ -30,8 +30,6 @@ # define __STDC_LIMIT_MACROS 1 #endif -#ifndef __AVR__ - #include "cbor.h" #include "cborjson.h" #include "cborinternal_p.h" @@ -703,6 +701,4 @@ CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags) #pragma GCC diagnostic pop -#endif // __AVR__ - /** @} */ diff --git a/src/cbor/lib/tinycbor/src/open_memstream.c b/src/cbor/lib/tinycbor/src/open_memstream.c index 4d79a726e..b3e624d47 100644 --- a/src/cbor/lib/tinycbor/src/open_memstream.c +++ b/src/cbor/lib/tinycbor/src/open_memstream.c @@ -34,10 +34,6 @@ #include -#ifdef __AVR__ -typedef size_t ssize_t; -#endif - typedef ssize_t RetType; typedef size_t LenType; diff --git a/src/nonstd/nonstd.h b/src/nonstd/nonstd.h deleted file mode 100644 index b591919c6..000000000 --- a/src/nonstd/nonstd.h +++ /dev/null @@ -1,235 +0,0 @@ -#pragma once -#ifdef __AVR__ -#include -extern void * operator new(size_t size, void * ptr); -namespace nonstd{ - - templatestruct tag{using type=T;}; - templateusing type_t=typename Tag::type; - - using size_t=decltype(sizeof(int)); - - //move - - template - T&& move(T&t){return static_cast(t);} - - //forward - - template - struct remove_reference:tag{}; - template - struct remove_reference:tag{}; - templateusing remove_reference_t=type_t>; - - template - T&& forward( remove_reference_t& t ) { - return static_cast(t); - } - template - T&& forward( remove_reference_t&& t ) { - return static_cast(t); - } - - //decay - - template - struct remove_const:tag{}; - template - struct remove_const:tag{}; - - template - struct remove_volatile:tag{}; - template - struct remove_volatile:tag{}; - - template - struct remove_cv:remove_const>>{}; - - - template - struct decay3:remove_cv{}; - template - struct decay3:tag{}; - template - struct decay2:decay3{}; - template - struct decay2:tag{}; - - template - struct decay:decay2>{}; - - template - using decay_t=type_t>; - - //is_convertible - - template - T declval(); // no implementation - - template - struct integral_constant{ - static constexpr T value=t; - constexpr integral_constant() {}; - constexpr operator T()const{ return value; } - constexpr T operator()()const{ return value; } - }; - template - using bool_t=integral_constant; - using true_type=bool_t; - using false_type=bool_t; - - templatestruct voider:tag{}; - templateusing void_t=type_t>; - - namespace details { - templateclass Z, class, class...Ts> - struct can_apply:false_type{}; - templateclass Z, class...Ts> - struct can_apply>, Ts...>:true_type{}; - } - templateclass Z, class...Ts> - using can_apply = details::can_apply; - - namespace details { - template - using try_convert = decltype( To{declval()} ); - } - template - struct is_convertible : can_apply< details::try_convert, From, To > {}; - template<> - struct is_convertible:true_type{}; - - //enable_if - - template - struct enable_if {}; - template - struct enable_if:tag{}; - template - using enable_if_t=type_t>; - - //res_of - - namespace details { - template - using invoke_t = decltype( declval()(declval()...) ); - - template - struct res_of {}; - template - struct res_of>>: - tag> - {}; - } - template - using res_of = details::res_of; - template - using res_of_t=type_t>; - - //aligned_storage - - template - struct alignas(align) aligned_storage_t { - char buff[size]; - }; - - //is_same - - template - struct is_same:false_type{}; - template - struct is_same:true_type{}; - - template - struct small_task; - - template - struct small_task{ - struct vtable_t { - void(*mover)(void* src, void* dest); - void(*destroyer)(void*); - R(*invoke)(void const* t, Args&&...args); - template - static vtable_t const* get() { - static const vtable_t table = { - [](void* src, void*dest) { - new(dest) T(move(*static_cast(src))); - }, - [](void* t){ static_cast(t)->~T(); }, - [](void const* t, Args&&...args)->R { - return (*static_cast(t))(forward(args)...); - } - }; - return &table; - } - }; - vtable_t const* table = nullptr; - aligned_storage_t data; - template, - enable_if_t{}>* = nullptr, - enable_if_t, R >{}>* = nullptr - > - small_task( F&& f ): - table( vtable_t::template get() ) - { - static_assert( sizeof(dF) <= sz, "object too large" ); - static_assert( alignof(dF) <= algn, "object too aligned" ); - new(&data) dF(forward(f)); - } - ~small_task() { - if (table) - table->destroyer(&data); - } - small_task(const small_task& o): - table(o.table) - { - data = o.data; - } - small_task(small_task&& o): - table(o.table) - { - if (table) - table->mover(&o.data, &data); - } - small_task(){} - small_task& operator=(const small_task& o){ - this->~small_task(); - new(this) small_task( move(o) ); - return *this; - } - small_task& operator=(small_task&& o){ - this->~small_task(); - new(this) small_task( move(o) ); - return *this; - } - explicit operator bool()const{return table;} - R operator()(Args...args)const{ - return table->invoke(&data, forward(args)...); - } - }; - - template - inline bool operator==(const small_task& __f, nullptr_t) - { return !static_cast(__f); } - - /// @overload - template - inline bool operator==(nullptr_t, const small_task& __f) - { return !static_cast(__f); } - - template - inline bool operator!=(const small_task& __f, nullptr_t) - { return static_cast(__f); } - - /// @overload - template - inline bool operator!=(nullptr_t, const small_task& __f) - { return static_cast(__f); } - - template - using function = small_task; -} - -#endif \ No newline at end of file diff --git a/src/property/Property.cpp b/src/property/Property.cpp index 326e25584..4d4258b28 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -226,11 +226,7 @@ CborError Property::appendAttribute(String value, String attributeName, CborEnco }, encoder); } -#ifdef __AVR__ -CborError Property::appendAttributeName(String attributeName, nonstd::functionappendValue, CborEncoder *encoder) -#else CborError Property::appendAttributeName(String attributeName, std::functionappendValue, CborEncoder *encoder) -#endif { if (attributeName != "") { // when the attribute name string is not empty, the attribute identifier is incremented in order to be encoded in the message if the _lightPayload flag is set @@ -319,11 +315,7 @@ void Property::setAttribute(String& value, String attributeName) { }); } -#ifdef __AVR__ -void Property::setAttribute(String attributeName, nonstd::functionsetValue) -#else void Property::setAttribute(String attributeName, std::functionsetValue) -#endif { if (attributeName != "") { _attributeIdentifier++; diff --git a/src/property/Property.h b/src/property/Property.h index b0e6ada06..90848b64a 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -32,13 +32,7 @@ #undef max #undef min -#ifdef __AVR__ -# include -# include -#else # include -#endif - #include #include "../cbor/lib/tinycbor/cbor-lib.h" @@ -140,10 +134,6 @@ typedef void(*OnSyncCallbackFunc)(Property &); CLASS DECLARATION ******************************************************************************/ -#ifdef __AVR__ -#include "nonstd/nonstd.h" -#endif - class Property { public: @@ -191,13 +181,8 @@ class Property CborError appendAttribute(unsigned int value, String attributeName = "", CborEncoder *encoder = nullptr); CborError appendAttribute(float value, String attributeName = "", CborEncoder *encoder = nullptr); CborError appendAttribute(String value, String attributeName = "", CborEncoder *encoder = nullptr); -#ifndef __AVR__ CborError appendAttributeName(String attributeName, std::functionf, CborEncoder *encoder); void setAttribute(String attributeName, std::functionsetValue); -#else - CborError appendAttributeName(String attributeName, nonstd::functionf, CborEncoder *encoder); - void setAttribute(String attributeName, nonstd::functionsetValue); -#endif void setAttributesFromCloud(std::list * map_data_list); void setAttribute(bool& value, String attributeName = ""); void setAttribute(int& value, String attributeName = ""); diff --git a/src/property/PropertyContainer.h b/src/property/PropertyContainer.h index 8c254875e..9dc3c86cd 100644 --- a/src/property/PropertyContainer.h +++ b/src/property/PropertyContainer.h @@ -26,10 +26,6 @@ #include "Property.h" -#ifdef __AVR__ -# include -#endif - #undef max #undef min #include diff --git a/src/utility/ota/FlashSHA256.cpp b/src/utility/ota/FlashSHA256.cpp index 85a1b4ebe..d0fc3d532 100644 --- a/src/utility/ota/FlashSHA256.cpp +++ b/src/utility/ota/FlashSHA256.cpp @@ -20,7 +20,7 @@ ******************************************************************************/ #include -#if OTA_ENABLED && !defined(__AVR__) +#if OTA_ENABLED #include "FlashSHA256.h" diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 23ab0a663..ac0a5eb02 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -294,7 +294,6 @@ bool TimeServiceClass::connected() unsigned long TimeServiceClass::getRemoteTime() { if(connected()) { -#ifndef __AVR__ /* At first try to obtain a valid time via NTP. * This is the most reliable time source and it will * ensure a correct behaviour of the library. @@ -303,7 +302,6 @@ unsigned long TimeServiceClass::getRemoteTime() if(isTimeValid(ntp_time)) { return ntp_time; } -#endif /* As fallback if NTP request fails try to obtain the * network time using the connection handler. From 4a4a174d7e9abdb6cc816144b9461119121ad48e Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 10 Oct 2023 08:53:40 +0200 Subject: [PATCH 462/780] UNO R4 WiFi: move firmware check inside begin function --- src/ArduinoIoTCloudTCP.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 1efbf3f33..2ebd373f0 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -218,6 +218,12 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, } #endif /* BOARD_HAS_OFFLOADED_ECCX08 */ +#if defined(ARDUINO_UNOWIFIR4) + if (String(WiFi.firmwareVersion()) < String("0.2.0")) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, WiFi firmware needs to be >= 0.2.0, current %s", __FUNCTION__, WiFi.firmwareVersion()); + } +#endif + /* Since we do not control what code the user inserts * between ArduinoIoTCloudTCP::begin() and the first * call to ArduinoIoTCloudTCP::update() it is wise to @@ -326,12 +332,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() reconnection_retry_delay = min(reconnection_retry_delay, static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms)); _next_connection_attempt_tick = millis() + reconnection_retry_delay; -#if defined(ARDUINO_UNOWIFIR4) - if (String(WiFi.firmwareVersion()) < String("0.2.0")) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, WiFi firmware needs to be >= 0.2.0, current %s", __FUNCTION__, WiFi.firmwareVersion()); - } -#endif - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); DEBUG_ERROR("ArduinoIoTCloudTCP::%s %d connection attempt at tick time %d", __FUNCTION__, _last_connection_attempt_cnt, _next_connection_attempt_tick); return State::ConnectPhy; From c04d01652d1e10d2f16d6d140b543dfeb9da1c4f Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 13 Nov 2023 10:21:34 +0100 Subject: [PATCH 463/780] TimeService: RTC use generic ARDUINO_ARCH_MBED and rename functions --- src/utility/time/TimeService.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index ac0a5eb02..777f73d48 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -72,10 +72,10 @@ void rp2040_connect_setRTC(unsigned long time); unsigned long rp2040_connect_getRTC(); #endif -#ifdef BOARD_STM32H7 -void stm32h7_initRTC(); -void stm32h7_setRTC(unsigned long time); -unsigned long stm32h7_getRTC(); +#ifdef ARDUINO_ARCH_MBED +void mbed_initRTC(); +void mbed_setRTC(unsigned long time); +unsigned long mbed_getRTC(); #endif #ifdef ARDUINO_ARCH_ESP32 @@ -339,8 +339,8 @@ void TimeServiceClass::initRTC() samd_initRTC(); #elif defined (ARDUINO_NANO_RP2040_CONNECT) rp2040_connect_initRTC(); -#elif defined (BOARD_STM32H7) - stm32h7_initRTC(); +#elif defined (ARDUINO_ARCH_MBED) + mbed_initRTC(); #elif defined (ARDUINO_ARCH_ESP32) esp32_initRTC(); #elif defined (ARDUINO_ARCH_ESP8266) @@ -358,8 +358,8 @@ void TimeServiceClass::setRTC(unsigned long time) samd_setRTC(time); #elif defined (ARDUINO_NANO_RP2040_CONNECT) rp2040_connect_setRTC(time); -#elif defined (BOARD_STM32H7) - stm32h7_setRTC(time); +#elif defined (ARDUINO_ARCH_MBED) + mbed_setRTC(time); #elif defined (ARDUINO_ARCH_ESP32) esp32_setRTC(time); #elif defined (ARDUINO_ARCH_ESP8266) @@ -377,8 +377,8 @@ unsigned long TimeServiceClass::getRTC() return samd_getRTC(); #elif defined (ARDUINO_NANO_RP2040_CONNECT) return rp2040_connect_getRTC(); -#elif defined (BOARD_STM32H7) - return stm32h7_getRTC(); +#elif defined (ARDUINO_ARCH_MBED) + return mbed_getRTC(); #elif defined (ARDUINO_ARCH_ESP32) return esp32_getRTC(); #elif defined (ARDUINO_ARCH_ESP8266) @@ -464,18 +464,18 @@ unsigned long rp2040_connect_getRTC() } #endif -#ifdef BOARD_STM32H7 -void stm32h7_initRTC() +#ifdef ARDUINO_ARCH_MBED +void mbed_initRTC() { /* Nothing to do */ } -void stm32h7_setRTC(unsigned long time) +void mbed_setRTC(unsigned long time) { set_time(time); } -unsigned long stm32h7_getRTC() +unsigned long mbed_getRTC() { return time(NULL); } From 4b0ef290f159da563156fe47212b8d895c9ff553 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 13 Nov 2023 10:24:25 +0100 Subject: [PATCH 464/780] TimeService: remove RP2040 functions --- src/utility/time/TimeService.cpp | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 777f73d48..cc3872150 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -66,12 +66,6 @@ void samd_setRTC(unsigned long time); unsigned long samd_getRTC(); #endif -#ifdef ARDUINO_NANO_RP2040_CONNECT -void rp2040_connect_initRTC(); -void rp2040_connect_setRTC(unsigned long time); -unsigned long rp2040_connect_getRTC(); -#endif - #ifdef ARDUINO_ARCH_MBED void mbed_initRTC(); void mbed_setRTC(unsigned long time); @@ -337,8 +331,6 @@ void TimeServiceClass::initRTC() { #if defined (ARDUINO_ARCH_SAMD) samd_initRTC(); -#elif defined (ARDUINO_NANO_RP2040_CONNECT) - rp2040_connect_initRTC(); #elif defined (ARDUINO_ARCH_MBED) mbed_initRTC(); #elif defined (ARDUINO_ARCH_ESP32) @@ -356,8 +348,6 @@ void TimeServiceClass::setRTC(unsigned long time) { #if defined (ARDUINO_ARCH_SAMD) samd_setRTC(time); -#elif defined (ARDUINO_NANO_RP2040_CONNECT) - rp2040_connect_setRTC(time); #elif defined (ARDUINO_ARCH_MBED) mbed_setRTC(time); #elif defined (ARDUINO_ARCH_ESP32) @@ -375,8 +365,6 @@ unsigned long TimeServiceClass::getRTC() { #if defined (ARDUINO_ARCH_SAMD) return samd_getRTC(); -#elif defined (ARDUINO_NANO_RP2040_CONNECT) - return rp2040_connect_getRTC(); #elif defined (ARDUINO_ARCH_MBED) return mbed_getRTC(); #elif defined (ARDUINO_ARCH_ESP32) @@ -447,23 +435,6 @@ unsigned long samd_getRTC() } #endif -#ifdef ARDUINO_NANO_RP2040_CONNECT -void rp2040_connect_initRTC() -{ - /* Nothing to do */ -} - -void rp2040_connect_setRTC(unsigned long time) -{ - set_time(time); -} - -unsigned long rp2040_connect_getRTC() -{ - return time(NULL); -} -#endif - #ifdef ARDUINO_ARCH_MBED void mbed_initRTC() { From 98ffe0e5d15f05351e53a7ec6add8a29a99de113 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 22 Nov 2023 13:59:14 +0100 Subject: [PATCH 465/780] ESP32 OTA: check if device partition table is OTA compatible --- src/utility/ota/OTA-esp32.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utility/ota/OTA-esp32.cpp b/src/utility/ota/OTA-esp32.cpp index 443187c7d..51065d1ba 100644 --- a/src/utility/ota/OTA-esp32.cpp +++ b/src/utility/ota/OTA-esp32.cpp @@ -122,8 +122,7 @@ String esp32_getOTAImageSHA256() bool esp32_isOTACapable() { - /* NOTE: here is possible to check if current partition scheme is OTA compatible */ - return true; + return Arduino_ESP32_OTA::isCapable(); } #endif /* ARDUINO_ARCH_ESP32 */ From 60e8a885e0e99c247ca1fc5b1841252545185931 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 24 Nov 2023 14:34:15 +0100 Subject: [PATCH 466/780] Edge Control: add board support --- .github/workflows/compile-examples.yml | 8 ++ library.properties | 2 +- src/AIoTC_Config.h | 2 +- src/ArduinoIoTCloudTCP.cpp | 4 +- src/ArduinoIoTCloudTCP.h | 2 + src/tls/AIoTCUPCert.h | 110 +++++++++++++++++++++++++ src/utility/watchdog/Watchdog.cpp | 13 ++- 7 files changed, 130 insertions(+), 11 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 7040b20bd..48e3bbf7f 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -70,6 +70,8 @@ jobs: type: renesas_uno - fqbn: arduino:esp32:nano_nora type: arduino_esp32 + - fqbn: arduino:mbed_edge:edge_control + type: mbed_edge # make board type-specific customizations to the matrix jobs @@ -212,6 +214,12 @@ jobs: - name: Arduino_ESP32_OTA sketch-paths: | - examples/ArduinoIoTCloud-DeferredOTA + # Edge Control + - board: + type: mbed_edge + platforms: | + # Install mbed_edge platform via Boards Manager + - name: arduino:mbed_edge # ESP8266 boards - board: type: esp8266 diff --git a/library.properties b/library.properties index 81d8a2440..5a1f0c3ec 100644 --- a/library.properties +++ b/library.properties @@ -6,6 +6,6 @@ sentence=This library allows connecting to the Arduino IoT Cloud service. paragraph=It provides a ConnectionManager to handle connection/disconnection, property-change updates and events callbacks. The supported boards are MKR GSM, MKR1000 and WiFi101. category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud -architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta,mbed_giga,renesas_portenta,renesas_uno +architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta,mbed_giga,renesas_portenta,renesas_uno,mbed_edge includes=ArduinoIoTCloud.h depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,Arduino_ESP32_OTA,Arduino_Portenta_OTA diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index c22609ee9..e62b1617e 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -151,7 +151,7 @@ #define BOARD_STM32H7 #endif -#if defined(ARDUINO_UNOR4_WIFI) +#if defined(ARDUINO_UNOR4_WIFI) || defined(ARDUINO_EDGE_CONTROL) #define BOARD_HAS_SECRET_KEY #define HAS_TCP #endif diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 2ebd373f0..9e018d600 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -39,7 +39,7 @@ #include "tls/utility/CryptoUtil.h" #endif -#ifdef ARDUINO_ARCH_ESP32 +#ifdef BOARD_HAS_SECRET_KEY #include "tls/AIoTCUPCert.h" #endif @@ -172,6 +172,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #else _sslClient.setCACertBundle(x509_crt_bundle); #endif +#elif defined(ARDUINO_EDGE_CONTROL) + _sslClient.appendCustomCACert(AIoTUPCert); #endif _mqttClient.setClient(_sslClient); diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index f15f019da..e50f9a076 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -152,6 +152,8 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass WiFiClientSecure _sslClient; #elif defined(ARDUINO_UNOR4_WIFI) WiFiSSLClient _sslClient; + #elif defined(ARDUINO_EDGE_CONTROL) + GSMSSLClient _sslClient; #elif defined(ARDUINO_PORTENTA_C33) ArduinoIoTCloudCertClass _cert; SSLClient _sslClient; diff --git a/src/tls/AIoTCUPCert.h b/src/tls/AIoTCUPCert.h index 58a01737d..ac3daa707 100644 --- a/src/tls/AIoTCUPCert.h +++ b/src/tls/AIoTCUPCert.h @@ -226,6 +226,116 @@ static const unsigned char x509_crt_bundle[] = { }; unsigned int x509_crt_bundle_len = 2164; +#elif defined (ARDUINO_EDGE_CONTROL) + /* + * https://www.amazontrust.com/repository/AmazonRootCA1.pem + * https://www.amazontrust.com/repository/AmazonRootCA2.pem + * https://www.amazontrust.com/repository/AmazonRootCA3.pem + * https://www.amazontrust.com/repository/AmazonRootCA4.pem + * https://www.amazontrust.com/repository/SFSRootCAG2.pem + */ +static const char AIoTUPCert[] = +"-----BEGIN CERTIFICATE-----\n" +"MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF\n" +"ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" +"b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL\n" +"MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n" +"b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\n" +"ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\n" +"9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\n" +"IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\n" +"VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\n" +"93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\n" +"jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n" +"AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA\n" +"A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI\n" +"U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs\n" +"N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv\n" +"o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\n" +"5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\n" +"rqXRfboQnoZsG4q5WTP468SQvvG5\n" +"-----END CERTIFICATE-----\n" +"-----BEGIN CERTIFICATE-----\n" +"MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF\n" +"ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" +"b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL\n" +"MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n" +"b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK\n" +"gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ\n" +"W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg\n" +"1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K\n" +"8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r\n" +"2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me\n" +"z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR\n" +"8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj\n" +"mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz\n" +"7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6\n" +"+XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI\n" +"0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB\n" +"Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm\n" +"UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2\n" +"LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY\n" +"+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS\n" +"k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl\n" +"7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm\n" +"btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl\n" +"urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+\n" +"fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63\n" +"n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE\n" +"76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H\n" +"9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT\n" +"4PsJYGw=\n" +"-----END CERTIFICATE-----\n" +"-----BEGIN CERTIFICATE-----\n" +"MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5\n" +"MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" +"Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n" +"A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n" +"Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl\n" +"ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j\n" +"QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr\n" +"ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr\n" +"BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM\n" +"YyRIHN8wfdVoOw==\n" +"-----END CERTIFICATE-----\n" +"-----BEGIN CERTIFICATE-----\n" +"MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5\n" +"MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" +"Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n" +"A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n" +"Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi\n" +"9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk\n" +"M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB\n" +"/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB\n" +"MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw\n" +"CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW\n" +"1KyLa2tJElMzrdfkviT8tQp21KW8EA==\n" +"-----END CERTIFICATE-----\n" +"-----BEGIN CERTIFICATE-----\n" +"MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx\n" +"EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT\n" +"HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs\n" +"ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5\n" +"MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD\n" +"VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy\n" +"ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy\n" +"dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI\n" +"hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p\n" +"OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2\n" +"8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K\n" +"Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe\n" +"hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk\n" +"6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw\n" +"DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q\n" +"AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI\n" +"bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB\n" +"ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z\n" +"qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd\n" +"iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn\n" +"0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN\n" +"sSi6\n" +"-----END CERTIFICATE-----\n"; +#else #endif /* #ifdef ARDUINO_ARCH_ESP32 */ diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 21cf7374c..9e499a29c 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -34,8 +34,9 @@ #ifdef ARDUINO_ARCH_MBED # include -# define PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms (32760) -# define NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms (8389) +# define PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms (32760) +# define NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms (8389) +# define EDGE_CONTROL_WATCHDOG_MAX_TIMEOUT_ms (32760) #endif /* ARDUINO_ARCH_MBED */ #include @@ -97,6 +98,8 @@ static void mbed_watchdog_enable() cfg.timeout_ms = PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms; #elif defined(ARDUINO_NANO_RP2040_CONNECT) cfg.timeout_ms = NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms; +#elif defined(ARDUINO_EDGE_CONTROL) + cfg.timeout_ms = EDGE_CONTROL_WATCHDOG_MAX_TIMEOUT_ms; #else # error "You need to define the maximum possible timeout for this architecture." #endif @@ -132,13 +135,7 @@ static void mbed_watchdog_enable_network_feed(const bool use_ethernet) void mbed_watchdog_trigger_reset() { watchdog_config_t cfg; -#if defined(BOARD_STM32H7) - cfg.timeout_ms = 1; -#elif defined(ARDUINO_NANO_RP2040_CONNECT) cfg.timeout_ms = 1; -#else -# error "You need to define the maximum possible timeout for this architecture." -#endif if (hal_watchdog_init(&cfg) == WATCHDOG_STATUS_OK) { is_watchdog_enabled = true; From bb22b877bafb0890cc5ccc4f677dd8befdda6a9e Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 27 Nov 2023 14:45:22 +0100 Subject: [PATCH 467/780] Edge Control: fix compile example workflow --- .../arduino_secrets.h | 12 ++-------- .../thingProperties.h | 12 +++++----- .../ArduinoIoTCloud-Basic/arduino_secrets.h | 12 ++-------- .../ArduinoIoTCloud-Basic/thingProperties.h | 12 +++++----- .../arduino_secrets.h | 12 ++-------- .../thingProperties.h | 10 ++++----- .../arduino_secrets.h | 22 ------------------- .../thingProperties.h | 18 ++------------- .../arduino_secrets.h | 12 ++-------- .../thingProperties.h | 12 +++++----- .../arduino_secrets.h | 12 ++-------- .../thingProperties.h | 12 +++++----- 12 files changed, 36 insertions(+), 122 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h index 09ea8323a..fc43514f9 100644 --- a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h @@ -14,8 +14,8 @@ #define SECRET_DEVICE_KEY "my-device-password" #endif -/* MKR GSM 1400 */ -#if defined(BOARD_HAS_GSM) +/* MKR GSM 1400 */ /* MKR NB 1500 */ /* Portenta CAT.M1/NB IoT GNSS Shield */ +#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_CATM1_NBIOT) #define SECRET_PIN "" #define SECRET_APN "" #define SECRET_LOGIN "" @@ -28,14 +28,6 @@ #define SECRET_APP_KEY "" #endif -/* MKR NB 1500 */ -#if defined(BOARD_HAS_NB) - #define SECRET_PIN "" - #define SECRET_APN "" - #define SECRET_LOGIN "" - #define SECRET_PASS "" -#endif - /* Portenta H7 + Ethernet shield */ #if defined(BOARD_HAS_ETHERNET) #define SECRET_OPTIONAL_IP "" diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index fd4b2ce69..97ffee9d6 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -1,9 +1,5 @@ -#if defined(BOARD_HAS_WIFI) -#elif defined(BOARD_HAS_GSM) -#elif defined(BOARD_HAS_LORA) -#elif defined(BOARD_HAS_NB) -#elif defined(BOARD_HAS_ETHERNET) -#else +#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ + defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif @@ -23,7 +19,7 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif -#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) +#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT) ArduinoCloud.addProperty(switchButton, WRITE, ON_CHANGE, onSwitchButtonChange); ArduinoCloud.addProperty(location, READ, ON_CHANGE); ArduinoCloud.addProperty(color, READWRITE, ON_CHANGE, onColorChange); @@ -42,6 +38,8 @@ void initProperties() { LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_CATM1_NBIOT) + CatM1ConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_ETHERNET) /* DHCP mode */ //EthernetConnectionHandler ArduinoIoTPreferredConnection; diff --git a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h index 09ea8323a..fc43514f9 100644 --- a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h @@ -14,8 +14,8 @@ #define SECRET_DEVICE_KEY "my-device-password" #endif -/* MKR GSM 1400 */ -#if defined(BOARD_HAS_GSM) +/* MKR GSM 1400 */ /* MKR NB 1500 */ /* Portenta CAT.M1/NB IoT GNSS Shield */ +#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_CATM1_NBIOT) #define SECRET_PIN "" #define SECRET_APN "" #define SECRET_LOGIN "" @@ -28,14 +28,6 @@ #define SECRET_APP_KEY "" #endif -/* MKR NB 1500 */ -#if defined(BOARD_HAS_NB) - #define SECRET_PIN "" - #define SECRET_APN "" - #define SECRET_LOGIN "" - #define SECRET_PASS "" -#endif - /* Portenta H7 + Ethernet shield */ #if defined(BOARD_HAS_ETHERNET) #define SECRET_OPTIONAL_IP "" diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index b10ac85fc..31d49b656 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -1,9 +1,5 @@ -#if defined(BOARD_HAS_WIFI) -#elif defined(BOARD_HAS_GSM) -#elif defined(BOARD_HAS_LORA) -#elif defined(BOARD_HAS_NB) -#elif defined(BOARD_HAS_ETHERNET) -#else +#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ + defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif @@ -22,7 +18,7 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif -#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) +#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT) ArduinoCloud.addProperty(led, Permission::Write).onUpdate(onLedChange); ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10); ArduinoCloud.addProperty(seconds, Permission::Read).publishOnChange(1); @@ -46,4 +42,6 @@ void initProperties() { LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_CATM1_NBIOT) + CatM1ConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #endif diff --git a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h index 09ea8323a..fc43514f9 100644 --- a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h @@ -14,8 +14,8 @@ #define SECRET_DEVICE_KEY "my-device-password" #endif -/* MKR GSM 1400 */ -#if defined(BOARD_HAS_GSM) +/* MKR GSM 1400 */ /* MKR NB 1500 */ /* Portenta CAT.M1/NB IoT GNSS Shield */ +#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_CATM1_NBIOT) #define SECRET_PIN "" #define SECRET_APN "" #define SECRET_LOGIN "" @@ -28,14 +28,6 @@ #define SECRET_APP_KEY "" #endif -/* MKR NB 1500 */ -#if defined(BOARD_HAS_NB) - #define SECRET_PIN "" - #define SECRET_APN "" - #define SECRET_LOGIN "" - #define SECRET_PASS "" -#endif - /* Portenta H7 + Ethernet shield */ #if defined(BOARD_HAS_ETHERNET) #define SECRET_OPTIONAL_IP "" diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index f3de1a2ed..59eff5857 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -1,9 +1,5 @@ -#if defined(BOARD_HAS_WIFI) -#elif defined(BOARD_HAS_GSM) -#elif defined(BOARD_HAS_LORA) -#elif defined(BOARD_HAS_NB) -#elif defined(BOARD_HAS_ETHERNET) -#else +#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ + defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif @@ -26,6 +22,8 @@ void initProperties() { LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_CATM1_NBIOT) + CatM1ConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_ETHERNET) /* DHCP mode */ //EthernetConnectionHandler ArduinoIoTPreferredConnection; diff --git a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h index 09ea8323a..1b0bb7fcb 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h @@ -14,28 +14,6 @@ #define SECRET_DEVICE_KEY "my-device-password" #endif -/* MKR GSM 1400 */ -#if defined(BOARD_HAS_GSM) - #define SECRET_PIN "" - #define SECRET_APN "" - #define SECRET_LOGIN "" - #define SECRET_PASS "" -#endif - -/* MKR WAN 1300/1310 */ -#if defined(BOARD_HAS_LORA) - #define SECRET_APP_EUI "" - #define SECRET_APP_KEY "" -#endif - -/* MKR NB 1500 */ -#if defined(BOARD_HAS_NB) - #define SECRET_PIN "" - #define SECRET_APN "" - #define SECRET_LOGIN "" - #define SECRET_PASS "" -#endif - /* Portenta H7 + Ethernet shield */ #if defined(BOARD_HAS_ETHERNET) #define SECRET_OPTIONAL_IP "" diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index 1570e4a1b..525de5aa4 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -1,9 +1,4 @@ -#if defined(BOARD_HAS_WIFI) -#elif defined(BOARD_HAS_GSM) -#elif defined(BOARD_HAS_LORA) -#elif defined(BOARD_HAS_NB) -#elif defined(BOARD_HAS_ETHERNET) -#else +#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_ETHERNET)) #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif @@ -20,21 +15,12 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif -#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) + ArduinoCloud.addProperty(led, Permission::Write).onUpdate(onLedChange); -#elif defined(BOARD_HAS_LORA) - ArduinoCloud.addProperty(led, 1, READWRITE, ON_CHANGE, onLedChange); -#endif } #if defined(BOARD_HAS_WIFI) WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_PASS); -#elif defined(BOARD_HAS_GSM) - GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); -#elif defined(BOARD_HAS_LORA) - LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); -#elif defined(BOARD_HAS_NB) - NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_ETHERNET) /* DHCP mode */ //EthernetConnectionHandler ArduinoIoTPreferredConnection; diff --git a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h index 09ea8323a..fc43514f9 100644 --- a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h @@ -14,8 +14,8 @@ #define SECRET_DEVICE_KEY "my-device-password" #endif -/* MKR GSM 1400 */ -#if defined(BOARD_HAS_GSM) +/* MKR GSM 1400 */ /* MKR NB 1500 */ /* Portenta CAT.M1/NB IoT GNSS Shield */ +#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_CATM1_NBIOT) #define SECRET_PIN "" #define SECRET_APN "" #define SECRET_LOGIN "" @@ -28,14 +28,6 @@ #define SECRET_APP_KEY "" #endif -/* MKR NB 1500 */ -#if defined(BOARD_HAS_NB) - #define SECRET_PIN "" - #define SECRET_APN "" - #define SECRET_LOGIN "" - #define SECRET_PASS "" -#endif - /* Portenta H7 + Ethernet shield */ #if defined(BOARD_HAS_ETHERNET) #define SECRET_OPTIONAL_IP "" diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 5949d8900..4f03c20ce 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -1,9 +1,5 @@ -#if defined(BOARD_HAS_WIFI) -#elif defined(BOARD_HAS_GSM) -#elif defined(BOARD_HAS_LORA) -#elif defined(BOARD_HAS_NB) -#elif defined(BOARD_HAS_ETHERNET) -#else +#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ + defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif @@ -27,7 +23,7 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif -#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) +#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT) ArduinoCloud.addProperty(switchButton, WRITE, ON_CHANGE); ArduinoCloud.addProperty(oneShot, READWRITE, ON_CHANGE); ArduinoCloud.addProperty(minute, READWRITE, ON_CHANGE); @@ -49,6 +45,8 @@ void initProperties() { LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_CATM1_NBIOT) + CatM1ConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_ETHERNET) /* DHCP mode */ //EthernetConnectionHandler ArduinoIoTPreferredConnection; diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h index 09ea8323a..fc43514f9 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h @@ -14,8 +14,8 @@ #define SECRET_DEVICE_KEY "my-device-password" #endif -/* MKR GSM 1400 */ -#if defined(BOARD_HAS_GSM) +/* MKR GSM 1400 */ /* MKR NB 1500 */ /* Portenta CAT.M1/NB IoT GNSS Shield */ +#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_CATM1_NBIOT) #define SECRET_PIN "" #define SECRET_APN "" #define SECRET_LOGIN "" @@ -28,14 +28,6 @@ #define SECRET_APP_KEY "" #endif -/* MKR NB 1500 */ -#if defined(BOARD_HAS_NB) - #define SECRET_PIN "" - #define SECRET_APN "" - #define SECRET_LOGIN "" - #define SECRET_PASS "" -#endif - /* Portenta H7 + Ethernet shield */ #if defined(BOARD_HAS_ETHERNET) #define SECRET_OPTIONAL_IP "" diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index 8a9ed4a28..a93e83052 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -1,9 +1,5 @@ -#if defined(BOARD_HAS_WIFI) -#elif defined(BOARD_HAS_GSM) -#elif defined(BOARD_HAS_LORA) -#elif defined(BOARD_HAS_NB) -#elif defined(BOARD_HAS_ETHERNET) -#else +#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ + defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif @@ -58,6 +54,8 @@ String str_property_8; LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, EU868); #elif defined(BOARD_HAS_NB) NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_CATM1_NBIOT) + CatM1ConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_ETHERNET) /* DHCP mode */ //EthernetConnectionHandler ArduinoIoTPreferredConnection; @@ -77,7 +75,7 @@ void onStringPropertyChange(); /****************************************************************************** FUNCTIONS ******************************************************************************/ -#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined (BOARD_HAS_NB) +#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined (BOARD_HAS_NB) || defined (BOARD_HAS_CATM1_NBIOT) void initProperties() { #if defined(BOARD_HAS_SECRET_KEY) ArduinoCloud.setBoardId(BOARD_ID); From 73450d2b8f05c1ee9da72be8587bf32f03cd0cba Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 27 Nov 2023 14:37:27 +0100 Subject: [PATCH 468/780] EdgeControl: use long watchdog timeout to allow connection --- src/utility/watchdog/Watchdog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 9e499a29c..aeb27abdc 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -36,7 +36,7 @@ # include # define PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms (32760) # define NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms (8389) -# define EDGE_CONTROL_WATCHDOG_MAX_TIMEOUT_ms (32760) +# define EDGE_CONTROL_WATCHDOG_MAX_TIMEOUT_ms (65536) #endif /* ARDUINO_ARCH_MBED */ #include From 095d4543a5cd796ba20ed557a4bbb39305e4819c Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 27 Nov 2023 15:10:38 +0100 Subject: [PATCH 469/780] Portenta H7: allow watchdog feed during CAT.M1 connection process --- src/ArduinoIoTCloudTCP.cpp | 5 ++-- src/utility/watchdog/Watchdog.cpp | 48 ++++++++++++++++--------------- src/utility/watchdog/Watchdog.h | 8 +++++- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 9e018d600..fe2c473e0 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -233,9 +233,10 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, */ #if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) if (enable_watchdog) { + /* Initialize watchdog hardware */ watchdog_enable(); - bool const use_ethernet = _connection->getInterface() == NetworkAdapter::ETHERNET ? true : false; - watchdog_enable_network_feed(use_ethernet); + /* Setup callbacks to feed the watchdog during offloaded network operations (connection/download)*/ + watchdog_enable_network_feed(_connection->getInterface()); } #endif diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index aeb27abdc..942b569f1 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -39,8 +39,6 @@ # define EDGE_CONTROL_WATCHDOG_MAX_TIMEOUT_ms (65536) #endif /* ARDUINO_ARCH_MBED */ -#include - /****************************************************************************** * GLOBAL VARIABLES ******************************************************************************/ @@ -66,24 +64,18 @@ static void samd_watchdog_reset() } } -/* This function is called within the WiFiNINA library when invoking - * the method 'connectBearSSL' in order to prevent a premature bite - * of the watchdog (max timeout on SAMD is 16 s). wifi_nina_feed... +/* This function is called within the GSMConnectionHandler. mkr_gsm_feed... * is defined a weak function there and overwritten by this "strong" * function here. */ -#ifndef WIFI_HAS_FEED_WATCHDOG_FUNC -void wifi_nina_feed_watchdog() -{ - samd_watchdog_reset(); -} -#endif - void mkr_gsm_feed_watchdog() { samd_watchdog_reset(); } - +/* This function is called within the GSMConnectionHandler. mkr_nb_feed... + * is defined a weak function there and overwritten by this "strong" + * function here. + */ void mkr_nb_feed_watchdog() { samd_watchdog_reset(); @@ -119,18 +111,26 @@ static void mbed_watchdog_reset() } } -#if defined (ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC) -static void mbed_watchdog_enable_network_feed(const bool use_ethernet) +static void mbed_watchdog_enable_network_feed(NetworkAdapter ni) { + if (ni == NetworkAdapter::ETHERNET) { #if defined(BOARD_HAS_ETHERNET) - if(use_ethernet) { Ethernet.setFeedWatchdogFunc(watchdog_reset); - } else #endif + } + + if (ni == NetworkAdapter::WIFI) { +#if defined(ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC) && defined(BOARD_HAS_WIFI) WiFi.setFeedWatchdogFunc(watchdog_reset); +#endif + } -} + if (ni == NetworkAdapter::CATM1) { +#if defined(BOARD_HAS_CATM1_NBIOT) + GSM.setFeedWatchdogFunc(watchdog_reset); #endif + } +} void mbed_watchdog_trigger_reset() { @@ -167,15 +167,17 @@ void watchdog_reset() #endif } -void watchdog_enable_network_feed(const bool use_ethernet) +void watchdog_enable_network_feed(NetworkAdapter ni) { -#ifdef WIFI_HAS_FEED_WATCHDOG_FUNC - (void)use_ethernet; + /* Setup WiFi NINA watchdog feed callback function */ +#if defined(ARDUINO_ARCH_SAMD) && defined(WIFI_HAS_FEED_WATCHDOG_FUNC) + (void)ni; WiFi.setFeedWatchdogFunc(watchdog_reset); #endif -#ifdef ARDUINO_PORTENTA_H7_WIFI_HAS_FEED_WATCHDOG_FUNC - mbed_watchdog_enable_network_feed(use_ethernet); + /* Setup mbed sockets watchdog feed callback function */ +#if defined(ARDUINO_ARCH_MBED) + mbed_watchdog_enable_network_feed(ni); #endif } #endif /* (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) */ diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index dbaf2abd6..3bfd35453 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -18,6 +18,12 @@ #ifndef ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ #define ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include + /****************************************************************************** * FUNCTION DECLARATION ******************************************************************************/ @@ -25,7 +31,7 @@ #if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) void watchdog_enable(); void watchdog_reset(); -void watchdog_enable_network_feed(const bool use_ethernet); +void watchdog_enable_network_feed(NetworkAdapter ni); #endif /* (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) */ #ifdef ARDUINO_ARCH_MBED From d436b80f099be3bbc9132248aae24c3042836446 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Tue, 28 Nov 2023 08:26:57 +0100 Subject: [PATCH 470/780] Release v1.13.0 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 5a1f0c3ec..48a0e5b37 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.12.2 +version=1.13.0 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index e62b1617e..eb2750b49 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -173,6 +173,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.12.2" +#define AIOT_CONFIG_LIB_VERSION "1.13.0" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From d1e2fc8c13d4c0179d0905e4491f8591bfd9fd07 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 10 Jan 2024 21:30:30 +0100 Subject: [PATCH 471/780] Use DEFAULT_MIN_TIME_BETWEEN_UPDATES_MILLIS as default period for publishOnChange --- src/property/Property.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/property/Property.h b/src/property/Property.h index 90848b64a..7393da192 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -143,7 +143,7 @@ class Property /* Composable configuration of the Property class */ Property & onUpdate(UpdateCallbackFunc func); Property & onSync(OnSyncCallbackFunc func); - Property & publishOnChange(float const min_delta_property, unsigned long const min_time_between_updates_millis = 0); + Property & publishOnChange(float const min_delta_property, unsigned long const min_time_between_updates_millis = DEFAULT_MIN_TIME_BETWEEN_UPDATES_MILLIS); Property & publishEvery(unsigned long const seconds); Property & publishOnDemand(); Property & encodeTimestamp(); From 349ae46b1f97710a4160c6c098373be65e233a9a Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 10 Jan 2024 21:35:32 +0100 Subject: [PATCH 472/780] Unit tests: force publishOnChange interval to 0 - The test was intended to run with a default interval of 0, changing the default we need to manually force interval to 0 --- extras/test/src/test_publishOnChange.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/test/src/test_publishOnChange.cpp b/extras/test/src/test_publishOnChange.cpp index 8d5f3f533..2896e00b7 100644 --- a/extras/test/src/test_publishOnChange.cpp +++ b/extras/test/src/test_publishOnChange.cpp @@ -21,7 +21,7 @@ SCENARIO("An Arduino cloud property is published on value change", "[ArduinoClou CloudInt test = 10; int const DELTA = 6; - addPropertyToContainer(property_container, test, "test", Permission::ReadWrite).publishOnChange(DELTA); + addPropertyToContainer(property_container, test, "test", Permission::ReadWrite).publishOnChange(DELTA,0); WHEN("test = 10, delta = 6, the property is encoded for the 1st time") { THEN("The property should be encoded") { From eb39dbe6b64657391a68119ce38a63bbd8bfdb10 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 12 Jan 2024 15:12:16 +0100 Subject: [PATCH 473/780] Avoid library to call deprecated functions itself --- src/ArduinoIoTCloud.cpp | 32 +++++++++++++++++++++----------- src/ArduinoIoTCloud.h | 2 ++ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 4997ec9b3..580521047 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -126,56 +126,66 @@ Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, /* The following methods are deprecated but still used for non-LoRa boards */ void ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); + Property* p = new CloudWrapperBool(property); + addPropertyRealInternal(*p, name, -1, permission_type, seconds, fn, minDelta, synFn); } void ArduinoIoTCloudClass::addPropertyReal(float& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); + Property* p = new CloudWrapperFloat(property); + addPropertyRealInternal(*p, name, -1, permission_type, seconds, fn, minDelta, synFn); } void ArduinoIoTCloudClass::addPropertyReal(int& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); + Property* p = new CloudWrapperInt(property); + addPropertyRealInternal(*p, name, -1, permission_type, seconds, fn, minDelta, synFn); } void ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); + Property* p = new CloudWrapperUnsignedInt(property); + addPropertyRealInternal(*p, name, -1, permission_type, seconds, fn, minDelta, synFn); } void ArduinoIoTCloudClass::addPropertyReal(String& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); + Property* p = new CloudWrapperString(property); + addPropertyRealInternal(*p, name, -1, permission_type, seconds, fn, minDelta, synFn); } void ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { - addPropertyReal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); + addPropertyRealInternal(property, name, -1, permission_type, seconds, fn, minDelta, synFn); } /* The following methods are deprecated but still used for both LoRa and non-LoRa boards */ void ArduinoIoTCloudClass::addPropertyReal(bool& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { Property* p = new CloudWrapperBool(property); - addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); + addPropertyRealInternal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); } void ArduinoIoTCloudClass::addPropertyReal(float& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { Property* p = new CloudWrapperFloat(property); - addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); + addPropertyRealInternal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); } void ArduinoIoTCloudClass::addPropertyReal(int& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { Property* p = new CloudWrapperInt(property); - addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); + addPropertyRealInternal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); } void ArduinoIoTCloudClass::addPropertyReal(unsigned int& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { Property* p = new CloudWrapperUnsignedInt(property); - addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); + addPropertyRealInternal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); } void ArduinoIoTCloudClass::addPropertyReal(String& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { Property* p = new CloudWrapperString(property); - addPropertyReal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); + addPropertyRealInternal(*p, name, tag, permission_type, seconds, fn, minDelta, synFn); } void ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) +{ + addPropertyRealInternal(property, name, tag, permission_type, seconds, fn, minDelta, synFn); +} + +void ArduinoIoTCloudClass::addPropertyRealInternal(Property& property, String name, int tag, permissionType permission_type, long seconds, void(*fn)(void), float minDelta, void(*synFn)(Property & property)) { Permission permission = Permission::ReadWrite; if (permission_type == READ) { diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index bce662eb6..6154f25e9 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -166,6 +166,8 @@ class ArduinoIoTCloudClass private: + void addPropertyRealInternal(Property& property, String name, int tag, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0f, void(*synFn)(Property & property) = CLOUD_WINS); + String _device_id; OnCloudEventCallback _cloud_event_callback[3]; bool _thing_id_outdated; From d34c500984fbeffeb390ea4502f755210c75b57f Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 31 Jan 2024 10:18:46 +0100 Subject: [PATCH 474/780] Examples: make examples build on cloud web editor --- .../ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino | 1 - examples/ArduinoIoTCloud-Advanced/arduino_secrets.h | 3 --- examples/ArduinoIoTCloud-Advanced/thingProperties.h | 4 ++++ examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino | 1 - examples/ArduinoIoTCloud-Basic/arduino_secrets.h | 3 --- examples/ArduinoIoTCloud-Basic/thingProperties.h | 4 ++++ .../ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino | 1 - examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h | 3 --- examples/ArduinoIoTCloud-Callbacks/thingProperties.h | 4 ++++ .../ArduinoIoTCloud-DeferredOTA.ino | 1 - examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h | 3 --- examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h | 4 ++++ .../ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino | 1 - examples/ArduinoIoTCloud-Schedule/arduino_secrets.h | 3 --- examples/ArduinoIoTCloud-Schedule/thingProperties.h | 4 ++++ 15 files changed, 20 insertions(+), 20 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino index a026d6297..e958594c2 100644 --- a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino +++ b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino @@ -10,7 +10,6 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ -#include "arduino_secrets.h" #include "thingProperties.h" void setup() { diff --git a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h index fc43514f9..3d464a477 100644 --- a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h @@ -1,6 +1,3 @@ -#include -#include - /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index 97ffee9d6..09f965452 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -1,3 +1,7 @@ +#include +#include +#include "arduino_secrets.h" + #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" diff --git a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino index ba4162baf..426c4da5a 100644 --- a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino +++ b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino @@ -14,7 +14,6 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ -#include "arduino_secrets.h" #include "thingProperties.h" #if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) diff --git a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h index fc43514f9..3d464a477 100644 --- a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h @@ -1,6 +1,3 @@ -#include -#include - /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index 31d49b656..b6025d89f 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -1,3 +1,7 @@ +#include +#include +#include "arduino_secrets.h" + #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" diff --git a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino index 634464716..20b37f291 100644 --- a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino +++ b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino @@ -26,7 +26,6 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ -#include "arduino_secrets.h" #include "thingProperties.h" void setup() { diff --git a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h index fc43514f9..3d464a477 100644 --- a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h @@ -1,6 +1,3 @@ -#include -#include - /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index 59eff5857..daed69097 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -1,3 +1,7 @@ +#include +#include +#include "arduino_secrets.h" + #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" diff --git a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino index b39439b4a..bbe58c373 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino +++ b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino @@ -16,7 +16,6 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud/#ota */ -#include "arduino_secrets.h" #include "thingProperties.h" #if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) diff --git a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h index 1b0bb7fcb..412b7db13 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h @@ -1,6 +1,3 @@ -#include -#include - /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index 525de5aa4..1aa4b1be3 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -1,3 +1,7 @@ +#include +#include +#include "arduino_secrets.h" + #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_ETHERNET)) #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index 484548037..9adb83378 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -6,7 +6,6 @@ */ -#include "arduino_secrets.h" #include "thingProperties.h" #if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) diff --git a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h index fc43514f9..3d464a477 100644 --- a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h @@ -1,6 +1,3 @@ -#include -#include - /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 4f03c20ce..69a47186e 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -1,3 +1,7 @@ +#include +#include +#include "arduino_secrets.h" + #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" From fd69bce0cf845fa0b5834e55620cde876096a718 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 1 Feb 2024 14:47:35 +0100 Subject: [PATCH 475/780] Examples: restore Arduino_ConnectionHandler.h include in the arduino_secrets.h files The reason is that this makes it easier for the user to understand the origin of the BOARD_HAS_* macros referenced in the file. --- examples/ArduinoIoTCloud-Advanced/arduino_secrets.h | 2 ++ examples/ArduinoIoTCloud-Basic/arduino_secrets.h | 2 ++ examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h | 2 ++ examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h | 2 ++ examples/ArduinoIoTCloud-Schedule/arduino_secrets.h | 2 ++ 5 files changed, 10 insertions(+) diff --git a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h index 3d464a477..2f6069225 100644 --- a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h @@ -1,3 +1,5 @@ +#include + /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ diff --git a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h index 3d464a477..2f6069225 100644 --- a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h @@ -1,3 +1,5 @@ +#include + /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ diff --git a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h index 3d464a477..2f6069225 100644 --- a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h @@ -1,3 +1,5 @@ +#include + /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ diff --git a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h index 412b7db13..b745cf215 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h @@ -1,3 +1,5 @@ +#include + /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ diff --git a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h index 3d464a477..2f6069225 100644 --- a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h @@ -1,3 +1,5 @@ +#include + /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ From 03f46d2078ed04a19cae0fc1fd2a6d1a21ba717f Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 1 Feb 2024 14:50:43 +0100 Subject: [PATCH 476/780] Examples: fix ArduinoIoTCloud_Travis_CI following the same pattern --- .../ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino | 1 - examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h | 1 - examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h | 4 ++++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino b/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino index 6a971f629..8995da36f 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino @@ -12,7 +12,6 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ -#include "arduino_secrets.h" #include "thingProperties.h" void setup() { diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h index fc43514f9..2f6069225 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h @@ -1,4 +1,3 @@ -#include #include /* A complete list of supported boards with WiFi is available here: diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index a93e83052..3410978bd 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -1,3 +1,7 @@ +#include +#include +#include "arduino_secrets.h" + #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" From 2f4a7568d7b84960ca85f1aa81ae1ace78695a74 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 1 Feb 2024 15:01:11 +0100 Subject: [PATCH 477/780] Examples: add newline to improve formatting --- .../ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino | 4 ++-- examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino | 4 ++-- .../ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino | 4 ++-- .../ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino index e958594c2..4f45a395d 100644 --- a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino +++ b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino @@ -3,8 +3,8 @@ IMPORTANT: This sketch works with WiFi, GSM, NB, Ethernet and Lora enabled boards supported by Arduino IoT Cloud. - On a LoRa board, if it is configured as a class A device (default and preferred option), values from Cloud dashboard are received - only after a value is sent to Cloud. + On a LoRa board, if it is configured as a class A device (default and preferred option), + values from Cloud dashboard are received only after a value is sent to Cloud. The full list of compatible boards can be found here: - https://github.com/arduino-libraries/ArduinoIoTCloud#what diff --git a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino index 426c4da5a..cb146900d 100644 --- a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino +++ b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino @@ -7,8 +7,8 @@ IMPORTANT: This sketch works with WiFi, GSM, NB, Ethernet and Lora enabled boards supported by Arduino IoT Cloud. - On a LoRa board, if it is configured as a class A device (default and preferred option), values from Cloud dashboard are received - only after a value is sent to Cloud. + On a LoRa board, if it is configured as a class A device (default and preferred option), + values from Cloud dashboard are received only after a value is sent to Cloud. The full list of compatible boards can be found here: - https://github.com/arduino-libraries/ArduinoIoTCloud#what diff --git a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino index 20b37f291..c01153d9b 100644 --- a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino +++ b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino @@ -19,8 +19,8 @@ IMPORTANT: This sketch works with WiFi, GSM, NB, Ethernet and Lora enabled boards supported by Arduino IoT Cloud. - On a LoRa board, if it is configured as a class A device (default and preferred option), values from Cloud dashboard are received - only after a value is sent to Cloud. + On a LoRa board, if it is configured as a class A device (default and preferred option), + values from Cloud dashboard are received only after a value is sent to Cloud. The full list of compatible boards can be found here: - https://github.com/arduino-libraries/ArduinoIoTCloud#what diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino b/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino index 8995da36f..575b55f49 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino @@ -5,8 +5,8 @@ IMPORTANT: This sketch works with WiFi, GSM, NB, Ethernet and Lora enabled boards supported by Arduino IoT Cloud. - On a LoRa board, if it is configured as a class A device (default and preferred option), values from Cloud dashboard are received - only after a value is sent to Cloud. + On a LoRa board, if it is configured as a class A device (default and preferred option), + values from Cloud dashboard are received only after a value is sent to Cloud. The full list of compatible boards can be found here: - https://github.com/arduino-libraries/ArduinoIoTCloud#what From 094453cfa560e3572217fa45451512616cc5141c Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 2 Feb 2024 16:26:21 +0100 Subject: [PATCH 478/780] Remove remaining ARDUINO_AVR_UNO_WIFI_REV2 configuration defines --- src/AIoTC_Config.h | 51 ++++++++-------------------------------------- 1 file changed, 8 insertions(+), 43 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index eb2750b49..64f0a33ad 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -27,64 +27,30 @@ #endif #ifndef DEBUG_ERROR -# if defined(ARDUINO_AVR_UNO_WIFI_REV2) -# define DEBUG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) -# else -# define DEBUG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) -# endif + #define DEBUG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__) #endif #ifndef DEBUG_WARNING -# if defined(ARDUINO_AVR_UNO_WIFI_REV2) -# define DEBUG_WARNING(fmt, ...) -# else -# define DEBUG_WARNING(fmt, ...) Debug.print(DBG_WARNING, fmt, ## __VA_ARGS__) -# endif + #define DEBUG_WARNING(fmt, ...) Debug.print(DBG_WARNING, fmt, ## __VA_ARGS__) #endif #ifndef DEBUG_INFO -# if defined(ARDUINO_AVR_UNO_WIFI_REV2) -# define DEBUG_INFO(fmt, ...) -# else -# define DEBUG_INFO(fmt, ...) Debug.print(DBG_INFO, fmt, ## __VA_ARGS__) -# endif + #define DEBUG_INFO(fmt, ...) Debug.print(DBG_INFO, fmt, ## __VA_ARGS__) #endif #ifndef DEBUG_DEBUG -# if defined(ARDUINO_AVR_UNO_WIFI_REV2) -# define DEBUG_DEBUG(fmt, ...) -# else -# define DEBUG_DEBUG(fmt, ...) Debug.print(DBG_DEBUG, fmt, ## __VA_ARGS__) -# endif + #define DEBUG_DEBUG(fmt, ...) Debug.print(DBG_DEBUG, fmt, ## __VA_ARGS__) #endif #ifndef DEBUG_VERBOSE -# if defined(ARDUINO_AVR_UNO_WIFI_REV2) -# define DEBUG_VERBOSE(fmt, ...) -# else -# define DEBUG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) -# endif -#endif - -#if defined(ARDUINO_AVR_UNO_WIFI_REV2) && !(defined(DEBUG_ERROR) || defined(DEBUG_WARNING) || defined(DEBUG_INFO) || defined(DEBUG_DEBUG) || defined(DEBUG_VERBOSE)) -/* Provide defines for constants provided within Arduino_DebugUtils - * in order to allow older sketches using those constants to still - * compile. - */ -# define DBG_NONE -1 -# define DBG_ERROR 0 -# define DBG_WARNING 1 -# define DBG_INFO 2 -# define DBG_DEBUG 3 -# define DBG_VERBOSE 4 + #define DEBUG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) #endif /****************************************************************************** * AUTOMATICALLY CONFIGURED DEFINES ******************************************************************************/ -#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || \ - defined(ARDUINO_AVR_UNO_WIFI_REV2) +#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) #define OTA_STORAGE_SNU (1) #else #define OTA_STORAGE_SNU (0) @@ -112,7 +78,7 @@ #define OTA_STORAGE_ESP (1) #endif -#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU || OTA_STORAGE_PORTENTA_QSPI || OTA_STORAGE_ESP) && !defined(ARDUINO_AVR_UNO_WIFI_REV2) +#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU || OTA_STORAGE_PORTENTA_QSPI || OTA_STORAGE_ESP) #define OTA_ENABLED (1) #else #define OTA_ENABLED (0) @@ -131,8 +97,7 @@ #define HAS_TCP #endif -#if defined(ARDUINO_AVR_UNO_WIFI_REV2) || \ - defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) +#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) #define BOARD_HAS_OFFLOADED_ECCX08 #define HAS_TCP #endif From 42f62d30f306d675f2212acf9b89c532f0b22505 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 10 Jan 2024 22:18:21 +0100 Subject: [PATCH 479/780] Add build configuration file for ECCX08 --- src/AIoTC_Config.h | 2 ++ src/ArduinoECCX08Config.h | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/ArduinoECCX08Config.h diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index eb2750b49..62d62e34d 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -18,6 +18,8 @@ #ifndef ARDUINO_AIOTC_CONFIG_H_ #define ARDUINO_AIOTC_CONFIG_H_ +#include + /****************************************************************************** * USER CONFIGURABLE DEFINES ******************************************************************************/ diff --git a/src/ArduinoECCX08Config.h b/src/ArduinoECCX08Config.h new file mode 100644 index 000000000..41edf9708 --- /dev/null +++ b/src/ArduinoECCX08Config.h @@ -0,0 +1,27 @@ +/* + 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_ECCX08_CONFIG_H +#define ARDUINO_ECCX08_CONFIG_H + +#define ECCX08_DISABLE_ASN1 +#define ECCX08_DISABLE_CSR +#define ECCX08_DISABLE_JWS +#define ECCX08_DISABLE_SSC +#define ECCX08_DISABLE_PEM + +#endif /* ARDUINO_ECCX08_CONFIG_H */ From 2d9ee71b814a6d47e73eb1b5cbc0c954cb8c0927 Mon Sep 17 00:00:00 2001 From: Giampaolo Mancini Date: Fri, 22 Dec 2023 11:48:25 +0100 Subject: [PATCH 480/780] Make lzss.dylib Universal (fat dylib for x64 and arm64) --- extras/tools/lzss.dylib | Bin 17604 -> 83648 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/extras/tools/lzss.dylib b/extras/tools/lzss.dylib index 77e1d515351946dcb01b5fb52c73760a83d1c8e3..3747d1ca01c7ea7b349435468a40b641c28ad31c 100755 GIT binary patch delta 5283 zcmbtY3vg4%6}_t`+0T}-4aodLEI~_<`PC3UCIk?%DGoFN95UlhTT}=(78o3ZO#l;~ zGA;ya=vWnPXp@2<$sqCR&_JegX9%WtN$AklbQ%I_N}!!EG7QtCowimwMm=}m%7{Nq z*RyZ;?%uthvv==m-M&?{ZnqWw_WG~hBO;3+N=K^^<)SHR$0rM8S!hxGs3%+T$v$$z z){%3#z2u1Q>dHBi>-s$BNQZ5Keas)eymlSTSVEMB%2IS2(I(j=8VGs|X1(48Gs_nQ zFNwY`4~9~U$0V?bxLN~?hUaa2+#K9tH(RDHfuBt&a7{M{O3j9twx~Wgx>XuYS;6^Y zcwUv__9zZX2fxtz2j3E3%?qp9ay84eC3wR2NU%!`9GF~lTN@l39hmX zomwP4Et#=kMsggjU-dnzy@dw!3_oeXA=>b~B)3&DGi}vJ{A#IAK zusL`|n>Dai4SH0o=+?C0Z0jI{tsQ_WcS~_puV1}-%#wB0zQtn}ty(d0yc#BS{8CFR z(M}9v10=l@vp5d6w29%0#r7Z zjp6brD$}8M$g&&}u0&7FzLafrHyn?2YZL%OGlixGKDW>g7x~LRMVp+1#KR+nr)31% z(hN_FF6<*pGpNOlG5uxH*DVNRR2xg*JxJGR60CK&!Asyp+oA8FfDoSeS;$08j%B_r zB>4=-#YEz@bd?hR>(qSo8gJ$5Cz;B6lcEfh7;jd&3iW0xQ8|5XpbRAk0p-x z{!c^LW1SHZmfBeV-GizucSmAJ(g5QI6pmfWfO~nJXrwdU4I;O~h<|L%qv5hx2V z)VC_V1mSyFF}+e2OIM21m159$RLt`!idnBOkuap-M$e;GA4SdlhDgN3DQud{4*$LI;`bKr4fz!(c{JWrXh_BqY-Uk6!0%+r%L;& zc)*wu!6dv|?gs3V;Uff$GK9xsPHMqj<_LqCc_k0V*h5C8)9Go66g#8GHD|N{c_Y%6 z558Sd-RCO`!?`f8u~BU*Dv@F(XWwpPP%O=~CJ8YwjKFiL2&bdemOMs)woyUb=#55- zu}#XOusUicYToF6%yf>06kmS?FFZn70ES-eiLnj9PFLkFJ8oOLP?C_ z1RZHpmcGAxP)wm>!t8`+fE(WO+GJH*BE3B+x5V^522_*l-9U-gh2Uhifhfgq4#4Y; zB6If%L!ro^+F>es*#HTl$gqbS0WH(T(kOelINzK*HoZ2s55bylB6U+B3zrPQmk*aGA!S4`WP2(1#%sLFTiW5wG7N;-3?U z_?rXXke5X-AkY)>+OFtTEpz{JY{da6yi@dFhEc3=4%#=bCthC44BYRQxcU*t@4PuRZv4|hdzNbpLsi`+zDnLFgOuF5i`ZpIGx1amQ{9|MI`z;~fwBNXuUo7}FXg0ErT4};h6Jo3n`^TRQJyjUf%V&oSC zNu&Uf%dCVX5msIRdR#cjWMIP4v=_ht{gkgL1{7}gz!Tr}5Dv&=3Yjv|!4Tt9b(Hp@ z?QVD~l4w(RzQ)(27U>2p;o@5oM=S{)Vk92YoL!f4xb=2HaPyEY(*j-?gR41?pQ&*j z!HwA!hF)dKWi_-7CC=-kFaMn%Xo;cnoYKKs$X9j9< zB%!HedrwCUcy$*~Mn9Y<(h(ff2XbT_;zK&Z=O5Xx#}jyYS5NRG{&21ZC|R6mWj`&Y zpPACnPU-ha>Gw1HbL;C~tgmxbtXfsGD)>F;ylQ?>dXO)vK zEW`W4Z;s~r`H91{e4(HFg;p0Qwut$K+IE9Rl%c*zHK zk803K?fm3PEt2-&Quo{#<#hs<3H-DY`KY5%pFk}o3VyR>lp$G#mp))lD{X-rcssK* zmc{jzl@+TfW5uG?%PGf7Avx-+^HQEUGt5fO7}Mz727HdbB)pZr>I#~!QF8+Zx~kQ{ zJdL(3g}{|B)GVo>=NWxkq|s>~X$FPsp)eF;wPAcUiY~+F;BxSfr6#-sn*~{<+)VG?_clSW-cimDTmDtGtV0y>hF5 zX+_;)pHWBaeJiDSqXyD@68C+_>rRZEmk7OEKb94$iD2P`{ zmrs)VK`>A66}SW>4YMT}x+n zZ>$*l{h1dWzE~{2;J>rn&uqWEdCe~_{O9ezeD=?6edoV^?S2X#VBWZ=2O@vY?_aSl zw7q{}`}|#v<>%Wce|+V46FuI3o7;>%V;;$R00sAyf5@0|ZwO}}8(F`4+@g);e;)d$ d!P$>*8GWwIy7%iXX-|K0u6N~E&ho#K{s)47=&k?& delta 10 RcmX@m%X*}fag)Fi7XTUp1Zw~Q From c097292b12a05ab863a776fd08c6d2d74cab6b81 Mon Sep 17 00:00:00 2001 From: Giampaolo Mancini Date: Fri, 2 Feb 2024 17:25:05 +0100 Subject: [PATCH 481/780] Fix python tools' shebang --- extras/tools/bin2ota.py | 2 +- extras/tools/lzss.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/tools/bin2ota.py b/extras/tools/bin2ota.py index 57e3f47f2..6a51268a4 100755 --- a/extras/tools/bin2ota.py +++ b/extras/tools/bin2ota.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 import sys import crccheck diff --git a/extras/tools/lzss.py b/extras/tools/lzss.py index 931870788..d65ad0fe5 100755 --- a/extras/tools/lzss.py +++ b/extras/tools/lzss.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 import platform import sys From 0a183f74dee7a0952d8cd8aea7ca813edcd025dc Mon Sep 17 00:00:00 2001 From: Giampaolo Mancini Date: Fri, 2 Feb 2024 17:56:52 +0100 Subject: [PATCH 482/780] Remove MacOS stuff --- extras/.DS_Store | Bin 0 -> 6148 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 extras/.DS_Store diff --git a/extras/.DS_Store b/extras/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2bf60533173cb0027117c9b7d98faa167d25091e GIT binary patch literal 6148 zcmeHKIS#@=4752UBpOP}{Q^H&A$S2Fpg^KQLE@@Y@h+am_-LXi9TcE(S-46wBSQFbozdA5@3jmxT?1s7b62M{sU`=cT z5rJt?fkD-5F*N9im&~h)ZD7zvv-!|`vu1~){&t*SJYBQ~a-;%OpsT<*mJ6%@Tlhf# z-z9NH1*pJZDWH?hZnMTGWo_+!oYmR_-@`5E1vkUoDHyyQ1HBw$VdZ$~Ns(7Hq)$ literal 0 HcmV?d00001 From c27e49526fa18c787db2b931f0cac72fcea36c84 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 16 Feb 2024 08:34:52 +0100 Subject: [PATCH 483/780] Configure Dependabot to check for outdated actions used in workflows (#417) Dependabot will periodically check the versions of all actions used in the repository's workflows. If any are found to be outdated, it will submit a pull request to update them. NOTE: Dependabot's PRs will occasionally propose to pin to the patch version of the action (e.g., updating to ). When the action author has provided a major version ref, use that instead (e.g., ). Dependabot will automatically close its PR once the workflow has been updated. More information: https://docs.github.com/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot --- .github/dependabot.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..03b0e93f9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +# See: https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#about-the-dependabotyml-file +version: 2 + +updates: + # Configure check for outdated GitHub Actions actions in workflows. + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/dependabot/README.md + # See: https://docs.github.com/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot + - package-ecosystem: github-actions + directory: /.github/workflows/ + schedule: + interval: daily + labels: + - "topic: infrastructure" From beaba783ab05fc23660908cf25993033fce87c0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Feb 2024 08:40:13 +0100 Subject: [PATCH 484/780] Bump actions/upload-artifact from 2 to 4 in /.github/workflows (#419) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/compile-examples.yml | 2 +- .github/workflows/sync-labels.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 48e3bbf7f..fd1359292 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -277,7 +277,7 @@ jobs: - name: Save memory usage change report as artifact if: github.event_name == 'pull_request' - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: ${{ env.SKETCHES_REPORTS_PATH }} path: ${{ env.SKETCHES_REPORTS_PATH }} diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 3ee6febdc..93adc5e94 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -70,7 +70,7 @@ jobs: file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} - name: Pass configuration files to next job via workflow artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: path: | *.yaml From 24f601ea0c0187c42ef14c58f3ba84524287a01c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Feb 2024 08:40:34 +0100 Subject: [PATCH 485/780] Bump actions/download-artifact from 2 to 4 in /.github/workflows (#420) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 2 to 4. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/sync-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 93adc5e94..781ac624d 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -108,7 +108,7 @@ jobs: uses: actions/checkout@v2 - name: Download configuration files artifact - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: ${{ env.CONFIGURATIONS_ARTIFACT }} path: ${{ env.CONFIGURATIONS_FOLDER }} From d5e6e70c725cc2d44cdf62d195ece39db6cb60fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Feb 2024 08:41:10 +0100 Subject: [PATCH 486/780] Bump actions/checkout from 2 to 4 in /.github/workflows (#421) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-arduino.yml | 2 +- .github/workflows/compile-examples.yml | 2 +- .github/workflows/spell-check.yml | 2 +- .github/workflows/sync-labels.yml | 4 ++-- .github/workflows/unit-tests.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/check-arduino.yml b/.github/workflows/check-arduino.yml index 15f7c2e73..19bd32ded 100644 --- a/.github/workflows/check-arduino.yml +++ b/.github/workflows/check-arduino.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Arduino Lint uses: arduino/arduino-lint-action@v1 diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index fd1359292..46cb41c79 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -245,7 +245,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install ESP32 platform dependencies if: matrix.board.type == 'esp32' diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml index b96e8e9d8..4253ed878 100644 --- a/.github/workflows/spell-check.yml +++ b/.github/workflows/spell-check.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Spell check uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 781ac624d..c66887432 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -27,7 +27,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Download JSON schema for labels configuration file id: download-schema @@ -105,7 +105,7 @@ jobs: echo "::set-output name=flag::--dry-run" - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Download configuration files artifact uses: actions/download-artifact@v4 diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 2b4283747..10d06cf27 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - uses: arduino/cpp-test-action@main with: From 88fd69531eb67166f63e887125e594a4c1eccbd3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Feb 2024 08:41:29 +0100 Subject: [PATCH 487/780] Bump geekyeggo/delete-artifact from 1 to 4 in /.github/workflows (#422) Bumps [geekyeggo/delete-artifact](https://github.com/geekyeggo/delete-artifact) from 1 to 4. - [Release notes](https://github.com/geekyeggo/delete-artifact/releases) - [Changelog](https://github.com/GeekyEggo/delete-artifact/blob/main/CHANGELOG.md) - [Commits](https://github.com/geekyeggo/delete-artifact/compare/v1...v4) --- updated-dependencies: - dependency-name: geekyeggo/delete-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/sync-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index c66887432..d93984812 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -114,7 +114,7 @@ jobs: path: ${{ env.CONFIGURATIONS_FOLDER }} - name: Remove unneeded artifact - uses: geekyeggo/delete-artifact@v1 + uses: geekyeggo/delete-artifact@v4 with: name: ${{ env.CONFIGURATIONS_ARTIFACT }} From dfd03781c109c4bdc2988ce1297e151e022fa340 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Sat, 17 Feb 2024 06:07:06 +0100 Subject: [PATCH 488/780] Fix regression re report-size-deltas after updating actions/upload-artifact. (#423) For more information see https://github.com/arduino/report-size-deltas/blob/main/docs/FAQ.md#size-deltas-report-workflow-triggered-by-schedule-event . --- .github/workflows/compile-examples.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 46cb41c79..46837b40d 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -40,38 +40,55 @@ jobs: board: - fqbn: arduino:samd:mkr1000 type: mkr1000 + artifact-name-suffix: arduino-samd-mkr1000 - fqbn: arduino:samd:mkrwifi1010 type: nina + artifact-name-suffix: arduino-samd-mkrwifi1010 - fqbn: arduino:samd:nano_33_iot type: nina + artifact-name-suffix: arduino-samd-nano_33_iot - fqbn: arduino:samd:mkrwan1300 type: wan + artifact-name-suffix: arduino-samd-mkrwan1300 - fqbn: arduino:samd:mkrgsm1400 type: gsm + artifact-name-suffix: arduino-samd-mkrgsm1400 - fqbn: arduino:samd:mkrnb1500 type: nb + artifact-name-suffix: arduino-samd-mkrnb1500 - fqbn: arduino:mbed_portenta:envie_m7 type: mbed_portenta + artifact-name-suffix: arduino-mbed_portenta-envie_m7 - fqbn: esp8266:esp8266:huzzah type: esp8266 + artifact-name-suffix: esp8266-esp8266-huzzah - fqbn: esp32:esp32:esp32 type: esp32 + artifact-name-suffix: esp32-esp32-esp32 - fqbn: arduino:mbed_nano:nanorp2040connect type: nina + artifact-name-suffix: arduino-mbed_nano-nanorp2040connect - fqbn: arduino:mbed_nicla:nicla_vision type: mbed_nicla + artifact-name-suffix: arduino-mbed_nicla-nicla_vision - fqbn: arduino:mbed_opta:opta type: mbed_opta + artifact-name-suffix: arduino-mbed_opta-opta - fqbn: arduino:mbed_giga:giga type: mbed_giga + artifact-name-suffix: arduino-mbed_giga-giga - fqbn: arduino:renesas_portenta:portenta_c33 type: renesas_portenta + artifact-name-suffix: arduino-renesas_portenta-portenta_c33 - fqbn: arduino:renesas_uno:unor4wifi type: renesas_uno + artifact-name-suffix: arduino-renesas_uno-unor4wifi - fqbn: arduino:esp32:nano_nora type: arduino_esp32 + artifact-name-suffix: arduino-esp32-nano_nora - fqbn: arduino:mbed_edge:edge_control type: mbed_edge + artifact-name-suffix: arduino-mbed_edge-edge_control # make board type-specific customizations to the matrix jobs @@ -279,5 +296,5 @@ jobs: if: github.event_name == 'pull_request' uses: actions/upload-artifact@v4 with: - name: ${{ env.SKETCHES_REPORTS_PATH }} + name: sketches-report-${{ matrix.board.artifact-name-suffix }} path: ${{ env.SKETCHES_REPORTS_PATH }} From 836771a7a4a2d49758bf7e977f68fa2b124a5941 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 21 Feb 2024 06:41:49 +0100 Subject: [PATCH 489/780] Fix regression: report size delta size on PR. (#429) The necessary steps have in fact been documented here: https://github.com/arduino/report-size-deltas/blob/main/docs/FAQ.md#workflow-triggered-by-pull_request-event but I have overlooked them when I fixed the upload issue. With this PR the size deltas are - once again - reported within the PR. --- .github/workflows/compile-examples.yml | 26 ++++++++++++++++++++++-- .github/workflows/report-size-deltas.yml | 14 ------------- .gitignore | 1 + 3 files changed, 25 insertions(+), 16 deletions(-) delete mode 100644 .github/workflows/report-size-deltas.yml diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 46837b40d..e482cfecb 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -12,8 +12,12 @@ on: - "examples/**" - "src/**" +env: + # It's convenient to set variables for values used multiple times in the workflow. + SKETCHES_REPORTS_PATH: sketches-reports + jobs: - build: + compile: runs-on: ubuntu-latest env: @@ -31,7 +35,6 @@ jobs: - examples/ArduinoIoTCloud-Callbacks - examples/ArduinoIoTCloud-Schedule - examples/utility/ArduinoIoTCloud_Travis_CI - SKETCHES_REPORTS_PATH: sketches-reports strategy: fail-fast: false @@ -292,9 +295,28 @@ jobs: google-key-file: ${{ secrets.GOOGLE_KEY_FILE }} spreadsheet-id: 1I6NZkpZpf8KugBkE92adB1Z3_b7ZepOpCdYTOigJpN4 + # This step is needed to pass the size data to the report job. - name: Save memory usage change report as artifact if: github.event_name == 'pull_request' uses: actions/upload-artifact@v4 with: name: sketches-report-${{ matrix.board.artifact-name-suffix }} path: ${{ env.SKETCHES_REPORTS_PATH }} + + # When using a matrix to compile for multiple boards, it's necessary to use a separate job for the deltas report + report: + needs: compile # Wait for the compile job to finish to get the data for the report + if: github.event_name == 'pull_request' # Only run the job when the workflow is triggered by a pull request + runs-on: ubuntu-latest + + steps: + # This step is needed to get the size data produced by the compile jobs + - name: Download sketches reports artifacts + uses: actions/download-artifact@v4 + with: + # All workflow artifacts will be downloaded to this location. + path: ${{ env.SKETCHES_REPORTS_PATH }} + + - uses: arduino/report-size-deltas@v1 + with: + sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }} diff --git a/.github/workflows/report-size-deltas.yml b/.github/workflows/report-size-deltas.yml deleted file mode 100644 index 9b0f2cdb5..000000000 --- a/.github/workflows/report-size-deltas.yml +++ /dev/null @@ -1,14 +0,0 @@ -on: - schedule: - - cron: '*/5 * * * *' - -jobs: - report: - runs-on: ubuntu-latest - - steps: - - name: Comment size deltas reports to PRs - uses: arduino/report-size-deltas@v1 - with: - # The name of the workflow artifact created by the "Compile Examples" workflow - sketches-reports-source: sketches-reports diff --git a/.gitignore b/.gitignore index 16e30d984..7704f8888 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ *.orig .vs build +.idea/ From 9278f817d28c78bf9b5aa2e0aaa41fd2a66a1aa6 Mon Sep 17 00:00:00 2001 From: per1234 Date: Wed, 21 Feb 2024 06:08:25 -0800 Subject: [PATCH 490/780] Revert "Fix regression: report size delta size on PR. (#429)" This partially reverts commit 836771a7a4a2d49758bf7e977f68fa2b124a5941. The repository infrastructure uses the "arduino/report-size-deltas" action to generate a report of the changes in memory usage of the example sketches that would result from merging a pull request. There are two use patterns for the "arduino/report-size-deltas" action: * Run from a workflow triggered by a `schedule` event. * Run from the same workflow as the "arduino/compile-sketches" action when triggered by a `pull_request` event. The latter use pattern is only suitable for private repositories. The reason is that, when a pull request is submitted from a fork, the permissions of the access token used by the "arduino/report-size-deltas" action are downgraded to read-only in workflows triggered by a `pull_request` event, which means it is unable to make the report comment. The reverted commit migrated the size deltas report infrastructure from the first use pattern to the second, which caused the "Compile Examples" workflow runs to fail on pull requests submitted from forks: Error: HTTPError: HTTP Error 403: Forbidden For this reason, the infrastructure must be reverted back to using the first use pattern. --- .github/workflows/compile-examples.yml | 26 ++---------------------- .github/workflows/report-size-deltas.yml | 14 +++++++++++++ 2 files changed, 16 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/report-size-deltas.yml diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index e482cfecb..46837b40d 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -12,12 +12,8 @@ on: - "examples/**" - "src/**" -env: - # It's convenient to set variables for values used multiple times in the workflow. - SKETCHES_REPORTS_PATH: sketches-reports - jobs: - compile: + build: runs-on: ubuntu-latest env: @@ -35,6 +31,7 @@ jobs: - examples/ArduinoIoTCloud-Callbacks - examples/ArduinoIoTCloud-Schedule - examples/utility/ArduinoIoTCloud_Travis_CI + SKETCHES_REPORTS_PATH: sketches-reports strategy: fail-fast: false @@ -295,28 +292,9 @@ jobs: google-key-file: ${{ secrets.GOOGLE_KEY_FILE }} spreadsheet-id: 1I6NZkpZpf8KugBkE92adB1Z3_b7ZepOpCdYTOigJpN4 - # This step is needed to pass the size data to the report job. - name: Save memory usage change report as artifact if: github.event_name == 'pull_request' uses: actions/upload-artifact@v4 with: name: sketches-report-${{ matrix.board.artifact-name-suffix }} path: ${{ env.SKETCHES_REPORTS_PATH }} - - # When using a matrix to compile for multiple boards, it's necessary to use a separate job for the deltas report - report: - needs: compile # Wait for the compile job to finish to get the data for the report - if: github.event_name == 'pull_request' # Only run the job when the workflow is triggered by a pull request - runs-on: ubuntu-latest - - steps: - # This step is needed to get the size data produced by the compile jobs - - name: Download sketches reports artifacts - uses: actions/download-artifact@v4 - with: - # All workflow artifacts will be downloaded to this location. - path: ${{ env.SKETCHES_REPORTS_PATH }} - - - uses: arduino/report-size-deltas@v1 - with: - sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }} diff --git a/.github/workflows/report-size-deltas.yml b/.github/workflows/report-size-deltas.yml new file mode 100644 index 000000000..9b0f2cdb5 --- /dev/null +++ b/.github/workflows/report-size-deltas.yml @@ -0,0 +1,14 @@ +on: + schedule: + - cron: '*/5 * * * *' + +jobs: + report: + runs-on: ubuntu-latest + + steps: + - name: Comment size deltas reports to PRs + uses: arduino/report-size-deltas@v1 + with: + # The name of the workflow artifact created by the "Compile Examples" workflow + sketches-reports-source: sketches-reports From ce9fc413feb9bb393cfc0341a12e6f4068331a10 Mon Sep 17 00:00:00 2001 From: per1234 Date: Wed, 21 Feb 2024 07:05:01 -0800 Subject: [PATCH 491/780] Correct workflow artifact name pattern in size deltas report workflow The "sketches-reports-source" input of the "arduino/report-size-deltas" GitHub Actions action defines the regular expression that matches the names of the sketches report workflow artifacts produced by the "Compile Examples" workflow. The key string in the names of these artifacts was set to "sketches-report" when the "Compile Examples" workflow was adjusted for compatibility with the breaking changes introduced by updating to version 4.x of the workflow's "actions/upload-artifact" GitHub Actions action dependency. The pattern set in the size deltas report workflow was "sketches-reports". The "s" at the end of that pattern caused it to no longer match against the key string in the artifact names after that adjustment of the "Compile Examples" workflow, resulting in size deltas reports no longer being generated by the workflow. Although a minimal fix would be to simply remove the "s" from the end of the pattern, the decision was made to use a more strict regular expression. This will make it easier for maintainers and contributors to understand that this value is a regular expression and the exact nature of how that regular expression functions (which is less clear when relying on the "arduino/report-size-deltas" action's partial pattern matching behavior). --- .github/workflows/report-size-deltas.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/report-size-deltas.yml b/.github/workflows/report-size-deltas.yml index 9b0f2cdb5..ae4c69abd 100644 --- a/.github/workflows/report-size-deltas.yml +++ b/.github/workflows/report-size-deltas.yml @@ -10,5 +10,5 @@ jobs: - name: Comment size deltas reports to PRs uses: arduino/report-size-deltas@v1 with: - # The name of the workflow artifact created by the "Compile Examples" workflow - sketches-reports-source: sketches-reports + # Regex matching the names of the workflow artifacts created by the "Compile Examples" workflow + sketches-reports-source: ^sketches-report-.+ From 98effa4923b1c28194fd3dc0914d52a7f1c24706 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 19 Feb 2024 13:02:07 +0100 Subject: [PATCH 492/780] UNO R4 WiFi OTA: adapt code to handle new and old return values from OTAUpdate core library --- src/utility/ota/OTA-unor4.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/utility/ota/OTA-unor4.cpp b/src/utility/ota/OTA-unor4.cpp index 34c417b02..d446476c3 100644 --- a/src/utility/ota/OTA-unor4.cpp +++ b/src/utility/ota/OTA-unor4.cpp @@ -92,14 +92,14 @@ static int unor4_codeFlashClose(flash_lp_instance_ctrl_t * ctrl) int unor4_onOTARequest(char const * ota_url) { - OTAUpdate::Error ota_err = OTAUpdate::Error::None; + int ota_err = static_cast(OTAUpdate::Error::None); OTAUpdate ota; /* Initialize the board for OTA handling. */ - if ((ota_err = ota.begin("/update.bin")) != OTAUpdate::Error::None) + if ((ota_err = static_cast(ota.begin("/update.bin"))) != static_cast(OTAUpdate::Error::None)) { - DEBUG_ERROR("OTAUpdate::begin() failed with %d", static_cast(ota_err)); - return static_cast(ota_err); + DEBUG_ERROR("OTAUpdate::begin() failed with %d", ota_err); + return ota_err; } /* Download the OTA file from the web storage location. */ @@ -109,23 +109,23 @@ int unor4_onOTARequest(char const * ota_url) DEBUG_ERROR("OTAUpdate::download() failed with %d", ota_download); return ota_download; } - DEBUG_VERBOSE("OTAUpdate::download() %d bytes downloaded", static_cast(ota_download)); + DEBUG_VERBOSE("OTAUpdate::download() %d bytes downloaded", ota_download); /* Verify update integrity */ - if ((ota_err = ota.verify()) != OTAUpdate::Error::None) + if ((ota_err = static_cast(ota.verify())) != static_cast(OTAUpdate::Error::None)) { - DEBUG_ERROR("OTAUpdate::verify() failed with %d", static_cast(ota_err)); - return static_cast(ota_err); + DEBUG_ERROR("OTAUpdate::verify() failed with %d", ota_err); + return ota_err; } /* Store update size and write OTA magin number */ unor4_setOTASize(ota_download); /* Flash new firmware */ - if ((ota_err = ota.update("/update.bin")) != OTAUpdate::Error::None) + if ((ota_err = static_cast(ota.update("/update.bin"))) != static_cast(OTAUpdate::Error::None)) { - DEBUG_ERROR("OTAUpdate::update() failed with %d", static_cast(ota_err)); - return static_cast(ota_err); + DEBUG_ERROR("OTAUpdate::update() failed with %d", ota_err); + return ota_err; } return static_cast(OTAUpdate::Error::None); From 08b1221345008f300ecc33c5306b5066502c6a16 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 22 Feb 2024 14:24:18 +0100 Subject: [PATCH 493/780] Update report-size-deltas workflow to wake him up --- .github/workflows/report-size-deltas.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/report-size-deltas.yml b/.github/workflows/report-size-deltas.yml index ae4c69abd..39e2a0ad2 100644 --- a/.github/workflows/report-size-deltas.yml +++ b/.github/workflows/report-size-deltas.yml @@ -1,11 +1,21 @@ +name: Report Size Deltas + +# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows on: + push: + paths: + - ".github/workflows/report-size-deltas.yml" schedule: - - cron: '*/5 * * * *' + # Run at the minimum interval allowed by GitHub Actions. + # Note: GitHub Actions periodically has outages which result in workflow failures. + # In this event, the workflows will start passing again once the service recovers. + - cron: "*/5 * * * *" + workflow_dispatch: + repository_dispatch: jobs: report: runs-on: ubuntu-latest - steps: - name: Comment size deltas reports to PRs uses: arduino/report-size-deltas@v1 From 75804b45893c6f07007cb8a52a562be01a7b889d Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 22 Feb 2024 14:34:53 +0100 Subject: [PATCH 494/780] Add whitespace after if --- src/ArduinoIoTCloudTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index fe2c473e0..ca6d793ab 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -564,7 +564,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() /* Retransmit data in case there was a lost transaction due * to phy layer or MQTT connectivity loss. */ - if(_mqtt_data_request_retransmit && (_mqtt_data_len > 0)) { + if (_mqtt_data_request_retransmit && (_mqtt_data_len > 0)) { write(_dataTopicOut, _mqtt_data_buf, _mqtt_data_len); _mqtt_data_request_retransmit = false; } From dca9968d1d5f6a5bc61bb0b416b8349c9be5258f Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 15 Jan 2024 10:26:06 +0100 Subject: [PATCH 495/780] checking _ota_req when the FSM state is between SubscribeDeviceTopic and Connected --- src/ArduinoIoTCloudTCP.cpp | 67 +++++++++++++++++++++----------------- src/ArduinoIoTCloudTCP.h | 2 ++ 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index ca6d793ab..5d284d671 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -271,6 +271,12 @@ void ArduinoIoTCloudTCP::update() } _state = next_state; +#if OTA_ENABLED + if (_state > State::SubscribeDeviceTopic && _state <= State::Connected) { + handle_OTARequest(); + } +#endif /* OTA_ENABLED */ + /* This watchdog feed is actually needed only by the RP2040 Connect because its * maximum watchdog window is 8389 ms; despite this we feed it for all * supported ARCH to keep code aligned. @@ -569,36 +575,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() _mqtt_data_request_retransmit = false; } -#if OTA_ENABLED - /* Request a OTA download if the hidden property - * OTA request has been set. - */ - - if (_ota_req) - { - bool const ota_execution_allowed_by_user = (_get_ota_confirmation != nullptr && _get_ota_confirmation()); - bool const perform_ota_now = ota_execution_allowed_by_user || !_ask_user_before_executing_ota; - if (perform_ota_now) { - /* Clear the error flag. */ - _ota_error = static_cast(OTAError::None); - /* Clear the request flag. */ - _ota_req = false; - /* Transmit the cleared request flags to the cloud. */ - sendDevicePropertyToCloud("OTA_REQ"); - /* Call member function to handle OTA request. */ - _ota_error = OTA::onRequest(_ota_url, _connection->getInterface()); - /* If something fails send the OTA error to the cloud */ - sendDevicePropertyToCloud("OTA_ERROR"); - } - } - - /* Check if we have received the OTA_URL property and provide - * echo to the cloud. - */ - sendDevicePropertyToCloud("OTA_URL"); - -#endif /* OTA_ENABLED */ - /* Check if any properties need encoding and send them to * the cloud if necessary. */ @@ -613,6 +589,37 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() } } +#if OTA_ENABLED +void ArduinoIoTCloudTCP::handle_OTARequest() { + /* Request a OTA download if the hidden property + * OTA request has been set. + */ + + if (_ota_req) + { + bool const ota_execution_allowed_by_user = (_get_ota_confirmation != nullptr && _get_ota_confirmation()); + bool const perform_ota_now = ota_execution_allowed_by_user || !_ask_user_before_executing_ota; + if (perform_ota_now) { + /* Clear the error flag. */ + _ota_error = static_cast(OTAError::None); + /* Clear the request flag. */ + _ota_req = false; + /* Transmit the cleared request flags to the cloud. */ + sendDevicePropertyToCloud("OTA_REQ"); + /* Call member function to handle OTA request. */ + _ota_error = OTA::onRequest(_ota_url, _connection->getInterface()); + /* If something fails send the OTA error to the cloud */ + sendDevicePropertyToCloud("OTA_ERROR"); + } + } + + /* Check if we have received the OTA_URL property and provide + * echo to the cloud. + */ + sendDevicePropertyToCloud("OTA_URL"); +} +#endif /* OTA_ENABLED */ + ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect() { DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index e50f9a076..30ce1e27f 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -103,6 +103,8 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass _get_ota_confirmation = cb; _ask_user_before_executing_ota = true; } + + void handle_OTARequest(); #endif private: From 24c33dea6c37a13a446b2e9bdad64c499cf3a0bc Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 15 Jan 2024 17:04:41 +0100 Subject: [PATCH 496/780] changing download to downloadAndDecompress for mbed core --- src/utility/ota/OTA-portenta-h7.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTA-portenta-h7.cpp index bd95f6a6b..1d7ecf3a7 100644 --- a/src/utility/ota/OTA-portenta-h7.cpp +++ b/src/utility/ota/OTA-portenta-h7.cpp @@ -80,22 +80,11 @@ int portenta_h7_onOTARequest(char const * ota_url, NetworkAdapter iface) download_socket = static_cast(&Ethernet); } #endif - int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.download(ota_url, true /* is_https */, download_socket); + int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.downloadAndDecompress(ota_url, true /* is_https */, download_socket); DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::download(%s) returns %d", ota_url, ota_portenta_qspi_download_ret_code); watchdog_reset(); - /* Decompress the LZSS compressed OTA file. */ - int const ota_portenta_qspi_decompress_ret_code = ota_portenta_qspi.decompress(); - DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::decompress() returns %d", ota_portenta_qspi_decompress_ret_code); - if (ota_portenta_qspi_decompress_ret_code < 0) - { - DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::decompress() failed with %d", ota_portenta_qspi_decompress_ret_code); - return ota_portenta_qspi_decompress_ret_code; - } - - watchdog_reset(); - /* Schedule the firmware update. */ if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) { DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::update() failed with %d", static_cast(ota_portenta_err)); From c95f278220a22a2c2d26780e5a8e081c35758818 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 26 Feb 2024 08:40:20 +0100 Subject: [PATCH 497/780] Release v1.14.0 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 48a0e5b37..7011c0cc0 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.13.0 +version=1.14.0 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 50a13bbd7..3238c0952 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -140,6 +140,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.13.0" +#define AIOT_CONFIG_LIB_VERSION "1.14.0" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 2f6cf5073c2933598b7920e1e386b5c9049a4a10 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 2 Feb 2024 16:12:07 +0100 Subject: [PATCH 498/780] Switch to Arduino_SecureElement library --- .../utility/Provisioning/ECCX08TLSConfig.h | 105 -- src/AIoTC_Config.h | 7 +- src/ArduinoIoTCloudTCP.cpp | 58 +- src/ArduinoIoTCloudTCP.h | 93 +- src/tls/AIoTCSSCert.h | 4 +- src/tls/utility/Cert.cpp | 918 ------------------ src/tls/utility/Cert.h | 187 ---- src/tls/utility/CryptoUtil.cpp | 211 ---- src/tls/utility/CryptoUtil.h | 91 -- 9 files changed, 86 insertions(+), 1588 deletions(-) delete mode 100644 examples/utility/Provisioning/ECCX08TLSConfig.h delete mode 100644 src/tls/utility/Cert.cpp delete mode 100644 src/tls/utility/Cert.h delete mode 100644 src/tls/utility/CryptoUtil.cpp delete mode 100644 src/tls/utility/CryptoUtil.h diff --git a/examples/utility/Provisioning/ECCX08TLSConfig.h b/examples/utility/Provisioning/ECCX08TLSConfig.h deleted file mode 100644 index 9126b3666..000000000 --- a/examples/utility/Provisioning/ECCX08TLSConfig.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2019 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 _ECCX08_TLS_CONFIG_H_ -#define _ECCX08_TLS_CONFIG_H_ - -const byte DEFAULT_ECCX08_TLS_CONFIG[128] = { - // Read only - start - // SN[0:3] - 0x01, 0x23, 0x00, 0x00, - // RevNum - 0x00, 0x00, 0x50, 0x00, - // SN[4:8] - 0x00, 0x00, 0x00, 0x00, 0x00, - // Reserved - 0xC0, - // I2C_Enable - 0x71, - // Reserved - 0x00, - // Read only - end - // I2C_Address - 0xC0, - // Reserved - 0x00, - // OTPmode - 0x55, - // ChipMode - 0x00, - // SlotConfig - 0x83, 0x20, // External Signatures | Internal Signatures | IsSecret | Write Configure Never, Default: 0x83, 0x20, - 0x87, 0x20, // External Signatures | Internal Signatures | ECDH | IsSecret | Write Configure Never, Default: 0x87, 0x20, - 0x87, 0x20, // External Signatures | Internal Signatures | ECDH | IsSecret | Write Configure Never, Default: 0x8F, 0x20, - 0x87, 0x2F, // External Signatures | Internal Signatures | ECDH | IsSecret | WriteKey all slots | Write Configure Never, Default: 0xC4, 0x8F, - 0x87, 0x2F, // External Signatures | Internal Signatures | ECDH | IsSecret | WriteKey all slots | Write Configure Never, Default: 0x8F, 0x8F, - 0x8F, 0x8F, - 0x9F, 0x8F, - 0xAF, 0x8F, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0xAF, 0x8F, - // Counter[0] - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - // Counter[1] - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - // LastKeyUse - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - // Write via commands only - start - // UserExtra - 0x00, - // Selector - 0x00, - // LockValue - 0x55, - // LockConfig - 0x55, - // SlotLocked - 0xFF, 0xFF, - // Write via commands only - end - // RFU - 0x00, 0x00, - // X509format - 0x00, 0x00, 0x00, 0x00, - // KeyConfig - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x33, 0x00, - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x33, 0x00, - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x33, 0x00, - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x1C, 0x00, - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x1C, 0x00, - 0x1C, 0x00, - 0x1C, 0x00, - 0x1C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x1C, 0x00 -}; - -#endif /* _ECCX08_TLS_CONFIG_H_ */ diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 3238c0952..7692e2f46 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -118,11 +118,16 @@ #define BOARD_STM32H7 #endif -#if defined(ARDUINO_UNOR4_WIFI) || defined(ARDUINO_EDGE_CONTROL) +#if defined(ARDUINO_EDGE_CONTROL) #define BOARD_HAS_SECRET_KEY #define HAS_TCP #endif +#if defined(ARDUINO_UNOR4_WIFI) + #define BOARD_HAS_SOFTSE + #define HAS_TCP +#endif + /****************************************************************************** * CONSTANTS ******************************************************************************/ diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 5d284d671..e307efaa9 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -24,23 +24,16 @@ #ifdef HAS_TCP #include +#ifdef BOARD_HAS_SECRET_KEY + #include "tls/AIoTCUPCert.h" +#endif + #ifdef BOARD_HAS_ECCX08 #include "tls/BearSSLTrustAnchors.h" - #include "tls/utility/CryptoUtil.h" #endif -#ifdef BOARD_HAS_SE050 +#if defined(BOARD_HAS_SE050) || defined(BOARD_HAS_SOFTSE) #include "tls/AIoTCSSCert.h" - #include "tls/utility/CryptoUtil.h" -#endif - -#ifdef BOARD_HAS_OFFLOADED_ECCX08 - #include - #include "tls/utility/CryptoUtil.h" -#endif - -#ifdef BOARD_HAS_SECRET_KEY - #include "tls/AIoTCUPCert.h" #endif #if OTA_ENABLED @@ -90,9 +83,9 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() #ifdef BOARD_HAS_ECCX08 , _sslClient(nullptr, ArduinoIoTCloudTrustAnchor, ArduinoIoTCloudTrustAnchor_NUM, getTime) #endif - #ifdef BOARD_HAS_SECRET_KEY +#ifdef BOARD_HAS_SECRET_KEY , _password("") - #endif +#endif , _mqttClient{nullptr} , _deviceTopicOut("") , _deviceTopicIn("") @@ -137,43 +130,50 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, DEBUG_VERBOSE("SHA256: HASH(%d) = %s", strlen(_ota_img_sha256.c_str()), _ota_img_sha256.c_str()); #endif /* OTA_ENABLED */ -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) +#if !defined(BOARD_HAS_SECRET_KEY) if (!_crypto.begin()) { DEBUG_ERROR("_crypto.begin() failed."); return 0; } - if (!_crypto.readDeviceId(getDeviceId(), CryptoSlot::DeviceId)) + if (!SElementArduinoCloudDeviceId::read(_crypto, getDeviceId(), SElementArduinoCloudSlot::DeviceId)) { DEBUG_ERROR("_crypto.readDeviceId(...) failed."); return 0; } #endif -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_SE050) - if (!_crypto.readCert(_cert, CryptoSlot::CompressedCertificate)) +#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_SE050) || defined(BOARD_HAS_SOFTSE) + if (!SElementArduinoCloudCertificate::read(_crypto, _cert, SElementArduinoCloudSlot::CompressedCertificate)) { DEBUG_ERROR("Cryptography certificate reconstruction failure."); return 0; } - _sslClient.setEccSlot(static_cast(CryptoSlot::Key), _cert.bytes(), _cert.length()); + _sslClient.setEccSlot(static_cast(SElementArduinoCloudSlot::Key), _cert.bytes(), _cert.length()); #endif -#if defined(BOARD_HAS_ECCX08) + +#if defined(BOARD_HAS_SECRET_KEY) + #if defined(ARDUINO_EDGE_CONTROL) + _sslClient.appendCustomCACert(AIoTUPCert); + #elif defined(ARDUINO_ARCH_ESP32) + _sslClient.setCACertBundle(x509_crt_bundle); + #else + _sslClient.setInsecure(); + #endif +#else + #if defined(BOARD_HAS_ECCX08) _sslClient.setClient(_connection->getClient()); -#elif defined(ARDUINO_PORTENTA_C33) + #elif defined(BOARD_HAS_SE050) + #if defined(ARDUINO_PORTENTA_C33) _sslClient.setClient(_connection->getClient()); _sslClient.setCACert(AIoTSSCert); -#elif defined(BOARD_HAS_SE050) + #else _sslClient.appendCustomCACert(AIoTSSCert); -#elif defined(BOARD_ESP) - #if defined(ARDUINO_ARCH_ESP8266) - _sslClient.setInsecure(); - #else - _sslClient.setCACertBundle(x509_crt_bundle); + #endif + #elif defined(BOARD_HAS_SOFTSE) + _sslClient.setCACert(AIoTSSCert, strlen(AIoTSSCert)); #endif -#elif defined(ARDUINO_EDGE_CONTROL) - _sslClient.appendCustomCACert(AIoTUPCert); #endif _mqttClient.setClient(_sslClient); diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 30ce1e27f..a36abfef3 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -23,31 +23,37 @@ ******************************************************************************/ #include - #include +#include -#ifdef BOARD_HAS_ECCX08 - #include "tls/BearSSLClient.h" - #include "tls/utility/CryptoUtil.h" -#elif defined(BOARD_ESP) - #include -#elif defined(ARDUINO_UNOR4_WIFI) - #include -#elif defined(ARDUINO_PORTENTA_C33) - #include "tls/utility/CryptoUtil.h" - #include -#elif defined(BOARD_HAS_SE050) - #include "tls/utility/CryptoUtil.h" - #include -#endif - -#ifdef BOARD_HAS_OFFLOADED_ECCX08 -#include "tls/utility/CryptoUtil.h" -#include +#if defined(BOARD_HAS_SECRET_KEY) + #if defined(BOARD_ESP) + #include + #elif defined(ARDUINO_EDGE_CONTROL) + #include + #endif +#else + #include + #include + #if defined(BOARD_HAS_OFFLOADED_ECCX08) + #else + #include + #ifdef BOARD_HAS_ECCX08 + #include "tls/BearSSLClient.h" + #elif defined(BOARD_HAS_OFFLOADED_ECCX08) + #include + #elif defined(BOARD_HAS_SE050) + #if defined(ARDUINO_PORTENTA_C33) + #include + #else + #include + #endif + #elif defined(BOARD_HAS_SOFTSE) + #include + #endif + #endif #endif -#include - /****************************************************************************** CONSTANTS ******************************************************************************/ @@ -79,7 +85,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass virtual int connected () override; virtual void printDebugInfo() override; - #if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) + #if !defined(BOARD_HAS_SECRET_KEY) int begin(ConnectionHandler & connection, bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH); #else int begin(ConnectionHandler & connection, bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_USER_PASS_AUTH); @@ -142,33 +148,32 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass int _mqtt_data_len; bool _mqtt_data_request_retransmit; - #if defined(BOARD_HAS_ECCX08) - ArduinoIoTCloudCertClass _cert; - BearSSLClient _sslClient; - CryptoUtil _crypto; - #elif defined(BOARD_HAS_OFFLOADED_ECCX08) - ArduinoIoTCloudCertClass _cert; - WiFiBearSSLClient _sslClient; - CryptoUtil _crypto; - #elif defined(BOARD_ESP) +#if defined(BOARD_HAS_SECRET_KEY) + String _password; + #if defined(BOARD_ESP) WiFiClientSecure _sslClient; - #elif defined(ARDUINO_UNOR4_WIFI) - WiFiSSLClient _sslClient; - #elif defined(ARDUINO_EDGE_CONTROL) + #elif defined(ARDUINO_EDGE_CONTROL) GSMSSLClient _sslClient; - #elif defined(ARDUINO_PORTENTA_C33) - ArduinoIoTCloudCertClass _cert; - SSLClient _sslClient; - CryptoUtil _crypto; + #endif +#else + SecureElement _crypto; + #if defined(BOARD_HAS_OFFLOADED_ECCX08) + WiFiBearSSLClient _sslClient; + #else + ECP256Certificate _cert; + #if defined(BOARD_HAS_ECCX08) + BearSSLClient _sslClient; #elif defined(BOARD_HAS_SE050) - ArduinoIoTCloudCertClass _cert; + #if defined(ARDUINO_PORTENTA_C33) + SSLClient _sslClient; + #else WiFiSSLSE050Client _sslClient; - CryptoUtil _crypto; - #endif - - #if defined (BOARD_HAS_SECRET_KEY) - String _password; + #endif + #elif defined(BOARD_HAS_SOFTSE) + WiFiSSLClient _sslClient; #endif + #endif +#endif MqttClient _mqttClient; diff --git a/src/tls/AIoTCSSCert.h b/src/tls/AIoTCSSCert.h index 1dc8206d9..29d71223b 100644 --- a/src/tls/AIoTCSSCert.h +++ b/src/tls/AIoTCSSCert.h @@ -24,7 +24,7 @@ ******************************************************************************/ #include -#ifdef BOARD_HAS_SE050 +#if defined(BOARD_HAS_SE050) || defined(BOARD_HAS_SOFTSE) /****************************************************************************** * CONSTANTS @@ -43,6 +43,6 @@ static const char AIoTSSCert[] = "AiEA6tnZ2lrNElKXCajtZg/hjWRE/+giFzBP8riar8qOz2w=\n" "-----END CERTIFICATE-----\n"; -#endif /* #ifdef BOARD_HAS_SE050 */ +#endif /* #if defined(BOARD_HAS_SE050) || defined(BOARD_HAS_SOFTSE) */ #endif /* _AIOTC_SS_CERT_H_ */ diff --git a/src/tls/utility/Cert.cpp b/src/tls/utility/Cert.cpp deleted file mode 100644 index f4ce3b42b..000000000 --- a/src/tls/utility/Cert.cpp +++ /dev/null @@ -1,918 +0,0 @@ -/* - This file is part of the ArduinoECCX08 library. - Copyright (c) 2019 Arduino SA. All rights reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include - -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) - -#include "Cert.h" - -/****************************************************************************** - * DEFINE - ******************************************************************************/ - -#define ASN1_INTEGER 0x02 -#define ASN1_BIT_STRING 0x03 -#define ASN1_NULL 0x05 -#define ASN1_OBJECT_IDENTIFIER 0x06 -#define ASN1_PRINTABLE_STRING 0x13 -#define ASN1_SEQUENCE 0x30 -#define ASN1_SET 0x31 - -/****************************************************************************** - * LOCAL MODULE FUNCTIONS - ******************************************************************************/ - -static String base64Encode(const byte in[], unsigned int length, const char* prefix, const char* suffix) { - static const char* CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - - int b; - String out; - - int reserveLength = 4 * ((length + 2) / 3) + ((length / 3 * 4) / 76) + strlen(prefix) + strlen(suffix); - out.reserve(reserveLength); - - if (prefix) { - out += prefix; - } - - for (unsigned int i = 0; i < length; i += 3) { - if (i > 0 && (i / 3 * 4) % 76 == 0) { - out += '\n'; - } - - b = (in[i] & 0xFC) >> 2; - out += CODES[b]; - - b = (in[i] & 0x03) << 4; - if (i + 1 < length) { - b |= (in[i + 1] & 0xF0) >> 4; - out += CODES[b]; - b = (in[i + 1] & 0x0F) << 2; - if (i + 2 < length) { - b |= (in[i + 2] & 0xC0) >> 6; - out += CODES[b]; - b = in[i + 2] & 0x3F; - out += CODES[b]; - } else { - out += CODES[b]; - out += '='; - } - } else { - out += CODES[b]; - out += "=="; - } - } - - if (suffix) { - out += suffix; - } - - return out; -} - -/****************************************************************************** - * CTOR/DTOR - ******************************************************************************/ - -ArduinoIoTCloudCertClass::ArduinoIoTCloudCertClass() -: _certBuffer(nullptr) -, _certBufferLen(0) -, _publicKey(nullptr) -{ - -} - -ArduinoIoTCloudCertClass::~ArduinoIoTCloudCertClass() -{ - if (_certBuffer) { - free(_certBuffer); - _certBuffer = nullptr; - } -} - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -int ArduinoIoTCloudCertClass::begin() -{ - memset(_compressedCert.data, 0x00, CERT_COMPRESSED_CERT_LENGTH); - return 1; -} - -int ArduinoIoTCloudCertClass::buildCSR() -{ - int csrInfoLen = CSRInfoLength(); - int subjectLen = issuerOrSubjectLength(_subjectData); - - _certBufferLen = getCSRSize(); - _certBuffer = (byte*)malloc(_certBufferLen); - - if (_certBuffer == nullptr) { - return 0; - } - - byte* out = _certBuffer; - - // header - out += appendSequenceHeader(csrInfoLen, out); - - // version - out += appendVersion(0x00, out); - - // subject - out += appendSequenceHeader(subjectLen, out); - out += appendIssuerOrSubject(_subjectData, out); - - // public key - if (_publicKey == nullptr) { - return 0; - } - out += appendPublicKey(_publicKey, out); - - // terminator - *out++ = 0xa0; - *out++ = 0x00; - - return 1; -} - -int ArduinoIoTCloudCertClass::signCSR(byte * signature) -{ - /* copy old certbuffer in a temp buffer */ - byte* tempBuffer = (byte*)malloc(_certBufferLen); - - if (tempBuffer == nullptr) { - return 0; - } - - memcpy(tempBuffer, _certBuffer, _certBufferLen); - - _certBufferLen = getCSRSignedSize(signature); - _certBuffer = (byte*)realloc(_certBuffer, _certBufferLen); - - if (_certBuffer == nullptr) { - return 0; - } - - byte* out = _certBuffer; - - // header - out += appendSequenceHeader(getCSRSize() + signatureLength(signature), out); - - // info - memcpy(out, tempBuffer, getCSRSize()); - free(tempBuffer); - out += getCSRSize(); - - // signature - out += appendSignature(signature, out); - - return 1; -} - -String ArduinoIoTCloudCertClass::getCSRPEM() -{ - return base64Encode(_certBuffer, _certBufferLen, "-----BEGIN CERTIFICATE REQUEST-----\n", "\n-----END CERTIFICATE REQUEST-----\n"); -} - -int ArduinoIoTCloudCertClass::buildCert() -{ - _certBufferLen = getCertSize(); - _certBuffer = (byte*)malloc(_certBufferLen); - - if (_certBuffer == nullptr) { - return 0; - } - - uint8_t* out = _certBuffer; - - int certInfoLen = certInfoLength(); - - // header - out += appendSequenceHeader(certInfoLen, out); - - // version - *out++ = 0xA0; - *out++ = 0x03; - *out++ = 0x02; - *out++ = 0x01; - *out++ = 0x02; - - // serial number - out += appendSerialNumber(_compressedCert.slot.two.values.serialNumber, CERT_SERIAL_NUMBER_LENGTH, out); - - // signature type - out += appendEcdsaWithSHA256(out); - - // issuer - int issuerDataLen = issuerOrSubjectLength(_issuerData); - out += appendSequenceHeader(issuerDataLen, out); - out += appendIssuerOrSubject(_issuerData, out); - - // dates - DateInfo dateData; - getDateFromCompressedData(dateData); - - *out++ = ASN1_SEQUENCE; - *out++ = 30 + ((dateData.issueYear > 2049) ? 2 : 0) + (((dateData.issueYear + dateData.expireYears) > 2049) ? 2 : 0); - out += appendDate(dateData.issueYear, dateData.issueMonth, dateData.issueDay, dateData.issueHour, 0, 0, out); - out += appendDate(dateData.issueYear + dateData.expireYears, dateData.issueMonth, dateData.issueDay, dateData.issueHour, 0, 0, out); - - // subject - int subjectDataLen = issuerOrSubjectLength(_subjectData); - out += appendSequenceHeader(subjectDataLen, out); - out += appendIssuerOrSubject(_subjectData, out); - - // public key - if (_publicKey == nullptr) { - return 0; - } - out += appendPublicKey(_publicKey, out); - - int authorityKeyIdLen = authorityKeyIdLength(_compressedCert.slot.two.values.authorityKeyId, CERT_AUTHORITY_KEY_ID_LENGTH); - if (authorityKeyIdLen) - { - out += appendAuthorityKeyId(_compressedCert.slot.two.values.authorityKeyId, CERT_AUTHORITY_KEY_ID_LENGTH, out); - } - else - { - // null sequence - *out++ = 0xA3; - *out++ = 0x02; - *out++ = 0x30; - *out++ = 0x00; - } - - return 1; -} - -int ArduinoIoTCloudCertClass::signCert(const byte * signature) -{ - /* copy old certbuffer in a temp buffer */ - byte* tempBuffer = (byte*)malloc(_certBufferLen); - - if (tempBuffer == nullptr) { - return 0; - } - - memcpy(tempBuffer, _certBuffer, _certBufferLen); - - _certBufferLen = getCertSignedSize(signature); - _certBuffer = (byte*)realloc(_certBuffer, _certBufferLen); - - if (_certBuffer == nullptr) { - return 0; - } - - byte* out = _certBuffer; - - // header - out +=appendSequenceHeader(getCertSize() + signatureLength(signature), out); - - // info - memcpy(out, tempBuffer, getCertSize()); - free(tempBuffer); - out += getCertSize(); - - // signature - out += appendSignature(signature, out); - - return 1; -} - -int ArduinoIoTCloudCertClass::importCert(const byte certDER[], size_t derLen) -{ - _certBufferLen = derLen; - _certBuffer = (byte*)malloc(_certBufferLen); - - if (_certBuffer == nullptr) { - return 0; - } - - memcpy(_certBuffer, certDER, _certBufferLen); - - return 1; -} - -int ArduinoIoTCloudCertClass::signCert() -{ - return signCert(_compressedCert.slot.one.values.signature); -} - -String ArduinoIoTCloudCertClass::getCertPEM() -{ - return base64Encode(_certBuffer, _certBufferLen, "-----BEGIN CERTIFICATE-----\n", "\n-----END CERTIFICATE-----\n"); -} - -void ArduinoIoTCloudCertClass::getDateFromCompressedData(DateInfo& date) { - date.issueYear = (_compressedCert.slot.one.values.dates[0] >> 3) + 2000; - date.issueMonth = ((_compressedCert.slot.one.values.dates[0] & 0x07) << 1) | (_compressedCert.slot.one.values.dates[1] >> 7); - date.issueDay = (_compressedCert.slot.one.values.dates[1] & 0x7c) >> 2; - date.issueHour = ((_compressedCert.slot.one.values.dates[1] & 0x03) << 3) | (_compressedCert.slot.one.values.dates[2] >> 5); - date.expireYears = (_compressedCert.slot.one.values.dates[2] & 0x1f); -} - -void ArduinoIoTCloudCertClass::setIssueYear(int issueYear) { - _compressedCert.slot.one.values.dates[0] &= 0x07; - _compressedCert.slot.one.values.dates[0] |= (issueYear - 2000) << 3; -} - -void ArduinoIoTCloudCertClass::setIssueMonth(int issueMonth) { - _compressedCert.slot.one.values.dates[0] &= 0xf8; - _compressedCert.slot.one.values.dates[0] |= issueMonth >> 1; - - _compressedCert.slot.one.values.dates[1] &= 0x7f; - _compressedCert.slot.one.values.dates[1] |= issueMonth << 7; -} - -void ArduinoIoTCloudCertClass::setIssueDay(int issueDay) { - _compressedCert.slot.one.values.dates[1] &= 0x83; - _compressedCert.slot.one.values.dates[1] |= issueDay << 2; -} - -void ArduinoIoTCloudCertClass::setIssueHour(int issueHour) { - _compressedCert.slot.one.values.dates[2] &= 0x1f; - _compressedCert.slot.one.values.dates[2] |= issueHour << 5; - - _compressedCert.slot.one.values.dates[1] &= 0xfc; - _compressedCert.slot.one.values.dates[1] |= issueHour >> 3; -} - -void ArduinoIoTCloudCertClass::setExpireYears(int expireYears) { - _compressedCert.slot.one.values.dates[2] &= 0xe0; - _compressedCert.slot.one.values.dates[2] |= expireYears; -} - -int ArduinoIoTCloudCertClass::setSerialNumber(const uint8_t serialNumber[], int serialNumberLen) { - if (serialNumberLen == CERT_SERIAL_NUMBER_LENGTH) { - memcpy(_compressedCert.slot.two.values.serialNumber, serialNumber, CERT_SERIAL_NUMBER_LENGTH); - return 1; - } - return 0; -} - -int ArduinoIoTCloudCertClass::setAuthorityKeyId(const uint8_t authorityKeyId[], int authorityKeyIdLen) { - if (authorityKeyIdLen == CERT_AUTHORITY_KEY_ID_LENGTH) { - memcpy(_compressedCert.slot.two.values.authorityKeyId, authorityKeyId, CERT_AUTHORITY_KEY_ID_LENGTH); - return 1; - } - return 0; -} - -int ArduinoIoTCloudCertClass::setPublicKey(const byte* publicKey, int publicKeyLen) { - if (publicKeyLen == CERT_PUBLIC_KEY_LENGTH) { - _publicKey = publicKey; - return 1; - } - return 0; -} - -int ArduinoIoTCloudCertClass::setSignature(const byte* signature, int signatureLen) { - if (signatureLen == CERT_SIGNATURE_LENGTH) { - memcpy(_compressedCert.slot.one.values.signature, signature, CERT_SIGNATURE_LENGTH); - return 1; - } - return 0; -} - -/****************************************************************************** - * PRIVATE MEMBER FUNCTIONS - ******************************************************************************/ - -int ArduinoIoTCloudCertClass::versionLength() -{ - return 3; -} - -int ArduinoIoTCloudCertClass::issuerOrSubjectLength(const CertInfo& issuerOrSubjectData) -{ - int length = 0; - int countryNameLength = issuerOrSubjectData.countryName.length(); - int stateProvinceNameLength = issuerOrSubjectData.stateProvinceName.length(); - int localityNameLength = issuerOrSubjectData.localityName.length(); - int organizationNameLength = issuerOrSubjectData.organizationName.length(); - int organizationalUnitNameLength = issuerOrSubjectData.organizationalUnitName.length(); - int commonNameLength = issuerOrSubjectData.commonName.length(); - - if (countryNameLength) { - length += (11 + countryNameLength); - } - - if (stateProvinceNameLength) { - length += (11 + stateProvinceNameLength); - } - - if (localityNameLength) { - length += (11 + localityNameLength); - } - - if (organizationNameLength) { - length += (11 + organizationNameLength); - } - - if (organizationalUnitNameLength) { - length += (11 + organizationalUnitNameLength); - } - - if (commonNameLength) { - length += (11 + commonNameLength); - } - - return length; -} - -int ArduinoIoTCloudCertClass::sequenceHeaderLength(int length) -{ - if (length > 255) { - return 4; - } else if (length > 127) { - return 3; - } else { - return 2; - } -} - -int ArduinoIoTCloudCertClass::publicKeyLength() -{ - return (2 + 2 + 9 + 10 + 4 + 64); -} - -int ArduinoIoTCloudCertClass::signatureLength(const byte signature[]) -{ - const byte* r = &signature[0]; - const byte* s = &signature[32]; - - int rLength = 32; - int sLength = 32; - - while (*r == 0x00 && rLength) { - r++; - rLength--; - } - - if (*r & 0x80) { - rLength++; - } - - while (*s == 0x00 && sLength) { - s++; - sLength--; - } - - if (*s & 0x80) { - sLength++; - } - - return (21 + rLength + sLength); -} - -int ArduinoIoTCloudCertClass::serialNumberLength(const byte serialNumber[], int length) -{ - while (*serialNumber == 0 && length) { - serialNumber++; - length--; - } - - if (*serialNumber & 0x80) { - length++; - } - - return (2 + length); -} - -int ArduinoIoTCloudCertClass::authorityKeyIdLength(const byte authorityKeyId[], int length) { - bool set = false; - - // check if the authority key identifier is non-zero - for (int i = 0; i < length; i++) { - if (authorityKeyId[i] != 0) { - set = true; - break; - } - } - - return (set ? (length + 17) : 0); -} - -int ArduinoIoTCloudCertClass::CSRInfoLength() -{ - int versionLen = versionLength(); - int subjectLen = issuerOrSubjectLength(_subjectData); - int subjectHeaderLen = sequenceHeaderLength(subjectLen); - int publicKeyLen = publicKeyLength(); - - int csrInfoLen = versionLen + subjectHeaderLen + subjectLen + publicKeyLen + 2; - - return csrInfoLen; -} - -int ArduinoIoTCloudCertClass::getCSRSize() -{ - int csrInfoLen = CSRInfoLength(); - int csrInfoHeaderLen = sequenceHeaderLength(csrInfoLen); - - return (csrInfoLen + csrInfoHeaderLen); -} - -int ArduinoIoTCloudCertClass::getCSRSignedSize(byte * signature) -{ - int signatureLen = signatureLength(signature); - int csrLen = getCSRSize() + signatureLen; - return sequenceHeaderLength(csrLen) + csrLen; -} - -int ArduinoIoTCloudCertClass::certInfoLength() -{ - int datesSizeLen = 30; - DateInfo dates; - - getDateFromCompressedData(dates); - - if (dates.issueYear > 2049) { - // two more bytes for GeneralizedTime - datesSizeLen += 2; - } - - if ((dates.issueYear + dates.expireYears) > 2049) { - // two more bytes for GeneralizedTime - datesSizeLen += 2; - } - - int serialNumberLen = serialNumberLength(_compressedCert.slot.two.values.serialNumber, CERT_SERIAL_NUMBER_LENGTH); - - int issuerLen = issuerOrSubjectLength(_issuerData); - - int issuerHeaderLen = sequenceHeaderLength(issuerLen); - - int subjectLen = issuerOrSubjectLength(_subjectData); - - int subjectHeaderLen = sequenceHeaderLength(subjectLen); - - int publicKeyLen = publicKeyLength(); - - int certInfoLen = 5 + serialNumberLen + 12 + issuerHeaderLen + issuerLen + (datesSizeLen + 2) + - subjectHeaderLen + subjectLen + publicKeyLen; - - int authorityKeyIdLen = authorityKeyIdLength(_compressedCert.slot.two.values.authorityKeyId, CERT_AUTHORITY_KEY_ID_LENGTH); - - if (authorityKeyIdLen) - { - certInfoLen += authorityKeyIdLen; - } - else - { - certInfoLen += 4; - } - - return certInfoLen; -} - -int ArduinoIoTCloudCertClass::getCertSize() -{ - int certInfoLen = certInfoLength(); - int certInfoHeaderLen = sequenceHeaderLength(certInfoLen); - - return (certInfoLen + certInfoHeaderLen); -} - -int ArduinoIoTCloudCertClass::getCertSignedSize(const byte * signature) -{ - int signatureLen = signatureLength(signature); - int certLen = getCertSize() + signatureLen; - return sequenceHeaderLength(certLen) + certLen; -} - -int ArduinoIoTCloudCertClass::appendSequenceHeader(int length, byte out[]) -{ - *out++ = ASN1_SEQUENCE; - if (length > 255) { - *out++ = 0x82; - *out++ = (length >> 8) & 0xff; - } else if (length > 127) { - *out++ = 0x81; - } - *out++ = (length) & 0xff; - - if (length > 255) { - return 4; - } else if (length > 127) { - return 3; - } else { - return 2; - } -} - -int ArduinoIoTCloudCertClass::appendVersion(int version, byte out[]) -{ - out[0] = ASN1_INTEGER; - out[1] = 0x01; - out[2] = version; - - return versionLength(); -} - -int ArduinoIoTCloudCertClass::appendName(const String& name, int type, byte out[]) -{ - int nameLength = name.length(); - - *out++ = ASN1_SET; - *out++ = nameLength + 9; - - *out++ = ASN1_SEQUENCE; - *out++ = nameLength + 7; - - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x03; - *out++ = 0x55; - *out++ = 0x04; - *out++ = type; - - *out++ = ASN1_PRINTABLE_STRING; - *out++ = nameLength; - memcpy(out, name.c_str(), nameLength); - - return (nameLength + 11); -} - -int ArduinoIoTCloudCertClass::appendIssuerOrSubject(const CertInfo& issuerOrSubjectData, byte out[]) -{ - if (issuerOrSubjectData.countryName.length() > 0) { - out += appendName(issuerOrSubjectData.countryName, 0x06, out); - } - - if (issuerOrSubjectData.stateProvinceName.length() > 0) { - out += appendName(issuerOrSubjectData.stateProvinceName, 0x08, out); - } - - if (issuerOrSubjectData.localityName.length() > 0) { - out += appendName(issuerOrSubjectData.localityName, 0x07, out); - } - - if (issuerOrSubjectData.organizationName.length() > 0) { - out += appendName(issuerOrSubjectData.organizationName, 0x0a, out); - } - - if (issuerOrSubjectData.organizationalUnitName.length() > 0) { - out += appendName(issuerOrSubjectData.organizationalUnitName, 0x0b, out); - } - - if (issuerOrSubjectData.commonName.length() > 0) { - out += appendName(issuerOrSubjectData.commonName, 0x03, out); - } - - return issuerOrSubjectLength(issuerOrSubjectData); -} - -int ArduinoIoTCloudCertClass::appendPublicKey(const byte publicKey[], byte out[]) -{ - int subjectPublicKeyDataLength = 2 + 9 + 10 + 4 + 64; - - // subject public key - *out++ = ASN1_SEQUENCE; - *out++ = (subjectPublicKeyDataLength) & 0xff; - - *out++ = ASN1_SEQUENCE; - *out++ = 0x13; - - // EC public key - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x07; - *out++ = 0x2a; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xce; - *out++ = 0x3d; - *out++ = 0x02; - *out++ = 0x01; - - // PRIME 256 v1 - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x08; - *out++ = 0x2a; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xce; - *out++ = 0x3d; - *out++ = 0x03; - *out++ = 0x01; - *out++ = 0x07; - - *out++ = 0x03; - *out++ = 0x42; - *out++ = 0x00; - *out++ = 0x04; - - memcpy(out, publicKey, 64); - - return publicKeyLength(); -} - -int ArduinoIoTCloudCertClass::appendSignature(const byte signature[], byte out[]) -{ - // signature algorithm - *out++ = ASN1_SEQUENCE; - *out++ = 0x0a; - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x08; - - // ECDSA with SHA256 - *out++ = 0x2a; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xce; - *out++ = 0x3d; - *out++ = 0x04; - *out++ = 0x03; - *out++ = 0x02; - - const byte* r = &signature[0]; - const byte* s = &signature[32]; - - int rLength = 32; - int sLength = 32; - - while (*r == 0 && rLength) { - r++; - rLength--; - } - - while (*s == 0 && sLength) { - s++; - sLength--; - } - - if (*r & 0x80) { - rLength++; - } - - if (*s & 0x80) { - sLength++; - } - - *out++ = ASN1_BIT_STRING; - *out++ = (rLength + sLength + 7); - *out++ = 0; - - *out++ = ASN1_SEQUENCE; - *out++ = (rLength + sLength + 4); - - *out++ = ASN1_INTEGER; - *out++ = rLength; - if ((*r & 0x80) && rLength) { - *out++ = 0; - rLength--; - } - memcpy(out, r, rLength); - out += rLength; - - *out++ = ASN1_INTEGER; - *out++ = sLength; - if ((*s & 0x80) && sLength) { - *out++ = 0; - sLength--; - } - memcpy(out, s, sLength); - out += rLength; - - return signatureLength(signature); -} - -int ArduinoIoTCloudCertClass::appendSerialNumber(const byte serialNumber[], int length, byte out[]) -{ - while (*serialNumber == 0 && length) { - serialNumber++; - length--; - } - - if (*serialNumber & 0x80) { - length++; - } - - *out++ = ASN1_INTEGER; - *out++ = length; - - if (*serialNumber & 0x80) { - *out++ = 0x00; - length--; - } - - memcpy(out, serialNumber, length); - - if (*serialNumber & 0x80) { - length++; - } - - return (2 + length); -} - -int ArduinoIoTCloudCertClass::appendDate(int year, int month, int day, int hour, int minute, int second, byte out[]) -{ - bool useGeneralizedTime = (year > 2049); - - if (useGeneralizedTime) { - *out++ = 0x18; - *out++ = 0x0f; - *out++ = '0' + (year / 1000); - *out++ = '0' + ((year % 1000) / 100); - *out++ = '0' + ((year % 100) / 10); - *out++ = '0' + (year % 10); - } else { - year -= 2000; - - *out++ = 0x17; - *out++ = 0x0d; - *out++ = '0' + (year / 10); - *out++ = '0' + (year % 10); - } - *out++ = '0' + (month / 10); - *out++ = '0' + (month % 10); - *out++ = '0' + (day / 10); - *out++ = '0' + (day % 10); - *out++ = '0' + (hour / 10); - *out++ = '0' + (hour % 10); - *out++ = '0' + (minute / 10); - *out++ = '0' + (minute % 10); - *out++ = '0' + (second / 10); - *out++ = '0' + (second % 10); - *out++ = 0x5a; // UTC - - return (useGeneralizedTime ? 17 : 15); -} - -int ArduinoIoTCloudCertClass::appendEcdsaWithSHA256(byte out[]) -{ - *out++ = ASN1_SEQUENCE; - *out++ = 0x0A; - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x08; - *out++ = 0x2A; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xCE; - *out++ = 0x3D; - *out++ = 0x04; - *out++ = 0x03; - *out++ = 0x02; - - return 12; -} - -int ArduinoIoTCloudCertClass::appendAuthorityKeyId(const byte authorityKeyId[], int length, byte out[]) { - // [3] - *out++ = 0xa3; - *out++ = 0x23; - - // sequence - *out++ = ASN1_SEQUENCE; - *out++ = 0x21; - - // sequence - *out++ = ASN1_SEQUENCE; - *out++ = 0x1f; - - // 2.5.29.35 authorityKeyIdentifier(X.509 extension) - *out++ = 0x06; - *out++ = 0x03; - *out++ = 0x55; - *out++ = 0x1d; - *out++ = 0x23; - - // octet string - *out++ = 0x04; - *out++ = 0x18; - - // sequence - *out++ = ASN1_SEQUENCE; - *out++ = 0x16; - - *out++ = 0x80; - *out++ = 0x14; - - memcpy(out, authorityKeyId, length); - - return length + 17; -} - -#endif /* (BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) */ diff --git a/src/tls/utility/Cert.h b/src/tls/utility/Cert.h deleted file mode 100644 index 9a74ea35b..000000000 --- a/src/tls/utility/Cert.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2019 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_IOT_CLOUD_CERT_H -#define ARDUINO_IOT_CLOUD_CERT_H - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include - -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) - -/****************************************************************************** - * DEFINE - ******************************************************************************/ - -#define CERT_SERIAL_NUMBER_LENGTH 16 -#define CERT_AUTHORITY_KEY_ID_LENGTH 20 -#define CERT_PUBLIC_KEY_LENGTH 64 -#define CERT_SIGNATURE_LENGTH 64 -#define CERT_DATES_LENGTH 3 -#define CERT_COMPRESSED_CERT_SLOT_LENGTH 72 -#define CERT_COMPRESSED_CERT_LENGTH CERT_COMPRESSED_CERT_SLOT_LENGTH + CERT_SERIAL_NUMBER_LENGTH + CERT_AUTHORITY_KEY_ID_LENGTH - -#include - -class ArduinoIoTCloudCertClass { -public: - ArduinoIoTCloudCertClass(); - virtual ~ArduinoIoTCloudCertClass(); - - int begin(); - int end(); - - /* APIs used only for Certificate generation*/ - void setIssueYear(int issueYear); - void setIssueMonth(int issueMonth); - void setIssueDay(int issueDay); - void setIssueHour(int issueHour); - void setExpireYears(int expireYears); - int setSerialNumber(const uint8_t serialNumber[], int serialNumberLen); - int setAuthorityKeyId(const uint8_t authorityKeyId[], int authorityKeyIdLen); - - inline void setIssuerCountryName(const String& countryName) { _issuerData.countryName = countryName; } - inline void setIssuerStateProvinceName(const String& stateProvinceName) { _issuerData.stateProvinceName = stateProvinceName; } - inline void setIssuerLocalityName(const String& localityName) { _issuerData.localityName = localityName; } - inline void setIssuerOrganizationName(const String& organizationName) { _issuerData.organizationName = organizationName; } - inline void setIssuerOrganizationalUnitName(const String& organizationalUnitName) { _issuerData.organizationalUnitName = organizationalUnitName; } - inline void setIssuerCommonName(const String& commonName) { _issuerData.commonName = commonName; } - - /* APIs used for both CSR and Certificate generation */ - inline void setSubjectCountryName(const String& countryName) { _subjectData.countryName = countryName; } - inline void setSubjectStateProvinceName(const String& stateProvinceName) { _subjectData.stateProvinceName = stateProvinceName; } - inline void setSubjectLocalityName(const String& localityName) { _subjectData.localityName = localityName; } - inline void setSubjectOrganizationName(const String& organizationName) { _subjectData.organizationName = organizationName; } - inline void setSubjectOrganizationalUnitName(const String& organizationalUnitName) { _subjectData.organizationalUnitName = organizationalUnitName; } - inline void setSubjectCommonName(const String& commonName) { _subjectData.commonName = commonName; } - - int setPublicKey(const byte* publicKey, int publicKeyLen); - int setSignature(const byte* signature, int signatureLen); - - /* Get Buffer */ - inline byte* bytes() { return _certBuffer; } - inline int length() { return _certBufferLen; } - -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) - /* Get Data to create ECCX08 compressed cert */ - inline byte* compressedCertBytes() { return _compressedCert.data; } - inline int compressedCertLenght() {return CERT_COMPRESSED_CERT_LENGTH; } - inline byte* compressedCertSignatureAndDatesBytes() { return _compressedCert.slot.one.data; } - inline int compressedCertSignatureAndDatesLength() {return CERT_COMPRESSED_CERT_SLOT_LENGTH; } - inline byte* compressedCertSerialAndAuthorityKeyIdBytes() { return _compressedCert.slot.two.data; } - inline int compressedCertSerialAndAuthorityKeyIdLenght() {return CERT_SERIAL_NUMBER_LENGTH + CERT_AUTHORITY_KEY_ID_LENGTH; } -#endif - - /* Build CSR */ - int buildCSR(); - int signCSR(byte signature[]); - String getCSRPEM(); - - /* Build Certificate */ - int buildCert(); - int signCert(const byte signature[]); - int signCert(); - String getCertPEM(); - - /* Import DER buffer into CertClass*/ - int importCert(const byte certDER[], size_t derLen); - -private: - - struct CertInfo { - String countryName; - String stateProvinceName; - String localityName; - String organizationName; - String organizationalUnitName; - String commonName; - }_issuerData, _subjectData; - - struct DateInfo { - int issueYear; - int issueMonth; - int issueDay; - int issueHour; - int expireYears; - }; - - union SignatureAndDateUType { - struct __attribute__((__packed__)) SignatureAndDateType { - byte signature[CERT_SIGNATURE_LENGTH]; - byte dates[CERT_DATES_LENGTH]; - byte unused[5]; - } values; - byte data[CERT_COMPRESSED_CERT_SLOT_LENGTH]; - }; - - union SerialNumberAndAuthorityKeyIdUType { - struct __attribute__((__packed__)) SerialNumberAndAuthorityKeyIdType { - byte serialNumber[CERT_SERIAL_NUMBER_LENGTH]; - byte authorityKeyId[CERT_AUTHORITY_KEY_ID_LENGTH]; - } values; - byte data[CERT_SERIAL_NUMBER_LENGTH + CERT_AUTHORITY_KEY_ID_LENGTH]; - }; - - union CompressedCertDataUType { - struct __attribute__((__packed__)) CompressedCertDataType { - SignatureAndDateUType one; - SerialNumberAndAuthorityKeyIdUType two; - }slot; - byte data[CERT_COMPRESSED_CERT_SLOT_LENGTH + CERT_SERIAL_NUMBER_LENGTH + CERT_AUTHORITY_KEY_ID_LENGTH]; - } _compressedCert; - - byte * _certBuffer; - int _certBufferLen; - - /* only raw EC X Y values 64 byte */ - const byte * _publicKey; - - int versionLength(); - int issuerOrSubjectLength(const CertInfo& issuerOrSubjectData); - int sequenceHeaderLength(int length); - int publicKeyLength(); - int signatureLength(const byte signature[]); - int serialNumberLength(const byte serialNumber[], int length); - int authorityKeyIdLength(const byte authorityKeyId[], int length); - int CSRInfoLength(); - int getCSRSize(); - int getCSRSignedSize(byte signature[]); - int certInfoLength(); - int getCertSize(); - int getCertSignedSize(const byte signature[]); - - void getDateFromCompressedData(DateInfo& date); - - int appendSequenceHeader(int length, byte out[]); - int appendVersion(int version, byte out[]); - int appendName(const String& name, int type, byte out[]); - int appendIssuerOrSubject(const CertInfo& issuerOrSubjectData, byte out[]); - int appendPublicKey(const byte publicKey[], byte out[]); - int appendSignature(const byte signature[], byte out[]); - int appendSerialNumber(const byte serialNumber[], int length, byte out[]); - int appendDate(int year, int month, int day, int hour, int minute, int second, byte out[]); - int appendEcdsaWithSHA256(byte out[]); - int appendAuthorityKeyId(const byte authorityKeyId[], int length, byte out[]); - -}; - -#endif /* BOARD_HAS_ECCX08 || BOARD_HAS_OFFLOADED_ECCX08 || BOARD_HAS_SE050*/ - -#endif /* ARDUINO_IOT_CLOUD_CERT_H */ diff --git a/src/tls/utility/CryptoUtil.cpp b/src/tls/utility/CryptoUtil.cpp deleted file mode 100644 index 24f03121d..000000000 --- a/src/tls/utility/CryptoUtil.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2019 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 defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) - -#include "CryptoUtil.h" -#include "SHA256.h" - -/****************************************************************************** - * DEFINE - ******************************************************************************/ -#define CRYPTO_SHA256_BUFFER_LENGTH 32 -#define CRYPTO_CERT_BUFFER_LENGTH 1024 - -/************************************************************************************** - * CTOR/DTOR - **************************************************************************************/ -CryptoUtil::CryptoUtil() -#if defined(BOARD_HAS_SE050) -: _crypto {SE05X} -#else -: _crypto {ECCX08} -#endif -{ - -} - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -int CryptoUtil::buildCSR(ArduinoIoTCloudCertClass & cert, const CryptoSlot keySlot, bool newPrivateKey) -{ - byte publicKey[CERT_PUBLIC_KEY_LENGTH]; - byte signature[CERT_SIGNATURE_LENGTH]; - - if (newPrivateKey) { - if (!_crypto.generatePrivateKey(static_cast(keySlot), publicKey)) { - return 0; - } - } else { - if (!_crypto.generatePublicKey(static_cast(keySlot), publicKey)) { - return 0; - } - } - - /* Store public key in csr */ - if (!cert.setPublicKey(publicKey, CERT_PUBLIC_KEY_LENGTH)) { - return 0; - } - - /* Build CSR */ - if (!cert.buildCSR()) { - return 0; - } - - /* compute CSR SHA256 */ - SHA256 sha256; - byte sha256buf[CRYPTO_SHA256_BUFFER_LENGTH]; - sha256.begin(); - sha256.update(cert.bytes(), cert.length()); - sha256.finalize(sha256buf); - - if (!_crypto.ecSign(static_cast(keySlot), sha256buf, signature)) { - return 0; - } - - /* sign CSR */ - return cert.signCSR(signature); -} - -int CryptoUtil::buildCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot keySlot) -{ - byte publicKey[CERT_PUBLIC_KEY_LENGTH]; - - if (!_crypto.generatePublicKey(static_cast(keySlot), publicKey)) { - return 0; - } - - /* Store public key in csr */ - if (!cert.setPublicKey(publicKey, CERT_PUBLIC_KEY_LENGTH)) { - return 0; - } - - /* Build CSR */ - if (!cert.buildCert()) { - return 0; - } - - /* sign CSR */ - return cert.signCert(); -} - -int CryptoUtil::readDeviceId(String & device_id, const CryptoSlot device_id_slot) -{ - byte device_id_bytes[CERT_COMPRESSED_CERT_SLOT_LENGTH] = {0}; - - if (!_crypto.readSlot(static_cast(device_id_slot), device_id_bytes, sizeof(device_id_bytes))) { - return 0; - } - - device_id = String(reinterpret_cast(device_id_bytes)); - return 1; -} - -int CryptoUtil::writeDeviceId(String & device_id, const CryptoSlot device_id_slot) -{ - byte device_id_bytes[CERT_COMPRESSED_CERT_SLOT_LENGTH] = {0}; - - device_id.getBytes(device_id_bytes, sizeof(device_id_bytes)); - - if (!_crypto.writeSlot(static_cast(device_id_slot), device_id_bytes, sizeof(device_id_bytes))) { - return 0; - } - return 1; -} - -int CryptoUtil::writeCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot certSlot) -{ -#if defined(BOARD_HAS_SE050) - if (!_crypto.writeSlot(static_cast(certSlot), cert.bytes(), cert.length())) { - return 0; - } -#else - if (!_crypto.writeSlot(static_cast(certSlot), cert.compressedCertSignatureAndDatesBytes(), cert.compressedCertSignatureAndDatesLength())) { - return 0; - } - - if (!_crypto.writeSlot(static_cast(certSlot) + 1, cert.compressedCertSerialAndAuthorityKeyIdBytes(), cert.compressedCertSerialAndAuthorityKeyIdLenght())) { - return 0; - } -#endif - return 1; -} - -int CryptoUtil::readCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot certSlot) -{ -#if defined(BOARD_HAS_SE050) - byte derBuffer[CRYPTO_CERT_BUFFER_LENGTH]; - size_t derLen; - if (!_crypto.readBinaryObject(static_cast(certSlot), derBuffer, sizeof(derBuffer), &derLen)) { - return 0; - } - - if (!cert.importCert(derBuffer, derLen)) { - return 0; - } -#else - String deviceId; - byte publicKey[CERT_PUBLIC_KEY_LENGTH]; - - cert.begin(); - - if (!readDeviceId(deviceId, CryptoSlot::DeviceId)) { - return 0; - } - - if (!_crypto.readSlot(static_cast(certSlot), cert.compressedCertSignatureAndDatesBytes(), cert.compressedCertSignatureAndDatesLength())) { - return 0; - } - - if (!_crypto.readSlot(static_cast(certSlot) + 1, cert.compressedCertSerialAndAuthorityKeyIdBytes(), cert.compressedCertSerialAndAuthorityKeyIdLenght())) { - return 0; - } - - if (!_crypto.generatePublicKey(static_cast(CryptoSlot::Key), publicKey)) { - return 0; - } - - cert.setSubjectCommonName(deviceId); - cert.setIssuerCountryName("US"); - cert.setIssuerOrganizationName("Arduino LLC US"); - cert.setIssuerOrganizationalUnitName("IT"); - cert.setIssuerCommonName("Arduino"); - - if (!cert.setPublicKey(publicKey, CERT_PUBLIC_KEY_LENGTH)) { - return 0; - } - - if (!cert.buildCert()) { - return 0; - } - - if (!cert.signCert()) { - return 0; - } -#endif - return 1; -} - -#endif /* (BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) */ diff --git a/src/tls/utility/CryptoUtil.h b/src/tls/utility/CryptoUtil.h deleted file mode 100644 index ba75f7021..000000000 --- a/src/tls/utility/CryptoUtil.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2019 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_IOT_CLOUD_UTILITY_CRYPTO_CRYPTO_UTIL_H_ -#define ARDUINO_IOT_CLOUD_UTILITY_CRYPTO_CRYPTO_UTIL_H_ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include - -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_SE050) -#include -#include "Cert.h" - -#if defined(BOARD_HAS_SE050) -#include -#else -#include -#endif - -/****************************************************************************** - * DEFINE - ******************************************************************************/ -#if defined(BOARD_HAS_SE050) -#define CRYPTO_SLOT_OFFSET 100 -#else -#define CRYPTO_SLOT_OFFSET 0 -#endif - -/****************************************************************************** - TYPEDEF - ******************************************************************************/ -enum class CryptoSlot : int -{ - Key = (0 + CRYPTO_SLOT_OFFSET), - CompressedCertificate = (10 + CRYPTO_SLOT_OFFSET), - SerialNumberAndAuthorityKeyIdentifier = (11 + CRYPTO_SLOT_OFFSET), - DeviceId = (12 + CRYPTO_SLOT_OFFSET) -}; - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class CryptoUtil -{ -public: - - CryptoUtil(); - - inline int begin() { return _crypto.begin(); } - inline int locked() { return _crypto.locked(); } - inline int writeConfiguration(const byte config[]) { return _crypto.writeConfiguration(config); } - inline int lock() { return _crypto.lock(); } - - int buildCSR(ArduinoIoTCloudCertClass & cert, const CryptoSlot keySlot, bool newPrivateKey); - int buildCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot keySlot); - - int readDeviceId(String & device_id, const CryptoSlot device_id_slot); - int writeDeviceId(String & device_id, const CryptoSlot device_id_slot); - int writeCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot certSlot); - int readCert(ArduinoIoTCloudCertClass & cert, const CryptoSlot certSlot); - -private: -#if defined(BOARD_HAS_SE050) - SE05XClass & _crypto; -#else - ECCX08Class & _crypto; -#endif - -}; - -#endif /* BOARD_HAS_ECCX08 || BOARD_HAS_OFFLOADED_ECCX08 || BOARD_HAS_SE050 */ - -#endif /* ARDUINO_IOT_CLOUD_UTILITY_CRYPTO_CRYPTO_UTIL_H_ */ From d1208626b7a6dbdc70907fe85096b8649bab88b5 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 2 Feb 2024 16:21:04 +0100 Subject: [PATCH 499/780] Examples: update provisioning sketch - Use Arduino_SecureElement library - Add WiFi version check - Align code to "Cloud version" provisioning sketch --- .../utility/Provisioning/Provisioning.ino | 134 ++++++++++++++---- 1 file changed, 103 insertions(+), 31 deletions(-) diff --git a/examples/utility/Provisioning/Provisioning.ino b/examples/utility/Provisioning/Provisioning.ino index 97394fc2c..ebde2218b 100644 --- a/examples/utility/Provisioning/Provisioning.ino +++ b/examples/utility/Provisioning/Provisioning.ino @@ -1,21 +1,37 @@ -#include -#include "ECCX08TLSConfig.h" - -const bool DEBUG = true; - -ArduinoIoTCloudCertClass Certificate; -CryptoUtil Crypto; +#include +#include +#include +#include +#include + +#ifdef ARDUINO_SAMD_MKR1000 +#include +#define LATEST_WIFI_FIRMWARE_VERSION WIFI_FIRMWARE_LATEST_MODEL_B +#endif +#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_NANO_RP2040_CONNECT) +#include +#define LATEST_WIFI_FIRMWARE_VERSION WIFI_FIRMWARE_LATEST_VERSION +#endif +#if defined(ARDUINO_UNOR4_WIFI) +#include +#define LATEST_WIFI_FIRMWARE_VERSION WIFI_FIRMWARE_LATEST_VERSION +#endif + +String promptAndReadLine(const char* prompt, const unsigned int timeout = 0); void setup() { Serial.begin(9600); while (!Serial); - if (!Crypto.begin()) { + SecureElement secureElement; + + if (!secureElement.begin()) { Serial.println("No crypto present!"); while (1); } - if (!Crypto.locked()) { + if (!secureElement.locked()) { + /* WARNING: This string is parsed from IoTCloud frontend */ String lockConfirm = promptAndReadLine("Your crypto is unlocked, would you like to lock it (y/N): "); lockConfirm.toLowerCase(); @@ -24,12 +40,14 @@ void setup() { while (1); } - if (!Crypto.writeConfiguration(DEFAULT_ECCX08_TLS_CONFIG)) { + if (!secureElement.writeConfiguration()) { + /* WARNING: This string is parsed from IoTCloud frontend */ Serial.println("Writing crypto configuration failed!"); while (1); } - if (!Crypto.lock()) { + if (!secureElement.lock()) { + /* WARNING: This string is parsed from IoTCloud frontend */ Serial.println("Locking crypto configuration failed!"); while (1); } @@ -38,7 +56,8 @@ void setup() { Serial.println(); } - String csrConfirm = promptAndReadLine("Would you like to generate a new private key and CSR (y/N): "); + /* WARNING: This string is parsed from IoTCloud frontend */ + String csrConfirm = promptAndReadLine("Would you like to generate a new private key and CSR (y/N): ", 5000); csrConfirm.toLowerCase(); if (csrConfirm != "y") { @@ -46,15 +65,19 @@ void setup() { while (1); } + ECP256Certificate Certificate; + if (!Certificate.begin()) { Serial.println("Error starting CSR generation!"); while (1); } - String deviceId = promptAndReadLine("Please enter the device ID: "); + /* WARNING: This string is parsed from IoTCloud frontend */ + String deviceId = promptAndReadLine("Please enter the device id: "); Certificate.setSubjectCommonName(deviceId); - if (!Crypto.buildCSR(Certificate, CryptoSlot::Key, true)) { + if (!SElementCSR::build(secureElement, Certificate, (int)SElementArduinoCloudSlot::Key, true)) { + /* WARNING: This string is parsed from IoTCloud frontend */ Serial.println("Error generating CSR!"); while (1); } @@ -62,12 +85,14 @@ void setup() { String csr = Certificate.getCSRPEM(); if (!csr) { + /* WARNING: This string is parsed from IoTCloud frontend */ Serial.println("Error generating CSR!"); while (1); } Serial.println("Generated CSR is:"); Serial.println(); + /* WARNING: This string is parsed from IoTCloud frontend */ Serial.println(csr); String issueYear = promptAndReadLine("Please enter the issue year of the certificate (2000 - 2031): "); @@ -79,20 +104,21 @@ void setup() { String authorityKeyIdentifier = promptAndReadLine("Please enter the certificates authority key identifier: "); String signature = promptAndReadLine("Please enter the certificates signature: "); - byte serialNumberBytes[CERT_SERIAL_NUMBER_LENGTH]; - byte authorityKeyIdentifierBytes[CERT_AUTHORITY_KEY_ID_LENGTH]; - byte signatureBytes[CERT_SIGNATURE_LENGTH]; + byte serialNumberBytes[ECP256_CERT_SERIAL_NUMBER_LENGTH]; + byte authorityKeyIdentifierBytes[ECP256_CERT_AUTHORITY_KEY_ID_LENGTH]; + byte signatureBytes[ECP256_CERT_SIGNATURE_LENGTH]; hexStringToBytes(serialNumber, serialNumberBytes, sizeof(serialNumberBytes)); hexStringToBytes(authorityKeyIdentifier, authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); hexStringToBytes(signature, signatureBytes, sizeof(signatureBytes)); - if (!Crypto.writeDeviceId(deviceId, CryptoSlot::DeviceId)) { + if (!SElementArduinoCloudDeviceId::write(secureElement, deviceId, SElementArduinoCloudSlot::DeviceId)) { Serial.println("Error storing device ID!"); while (1); } if (!Certificate.begin()) { + /* WARNING: This string is parsed from IoTCloud frontend */ Serial.println("Error starting crypto storage!"); while (1); } @@ -111,20 +137,17 @@ void setup() { Certificate.setIssueHour(issueHour.toInt()); Certificate.setExpireYears(expireYears.toInt()); - if (!Crypto.buildCert(Certificate, CryptoSlot::Key)) { + if (!SElementArduinoCloudCertificate::build(secureElement, Certificate, static_cast(SElementArduinoCloudSlot::Key))) { Serial.println("Error building cert!"); while (1); } - - if (!Crypto.writeCert(Certificate, CryptoSlot::CompressedCertificate)) { + + if (!SElementArduinoCloudCertificate::write(secureElement, Certificate, SElementArduinoCloudSlot::CompressedCertificate)) { Serial.println("Error storing cert!"); while (1); } - if (!DEBUG) { - return; - } - + /* WARNING: This string is parsed from IoTCloud frontend */ Serial.println("Compressed cert = "); const byte* certData = Certificate.bytes(); @@ -139,23 +162,72 @@ void setup() { Serial.print(b, HEX); } Serial.println(); + + + String cert = Certificate.getCertPEM(); + if (!cert) { + Serial.println("Error generating cert!"); + while (1); + } + Serial.println("Cert PEM = "); + Serial.println(); + Serial.println(cert); + + +#ifdef LATEST_WIFI_FIRMWARE_VERSION + Serial.println("Checking firmware of WiFi module..."); + Serial.println(); + String fv = WiFi.firmwareVersion(); + /* WARNING: This string is parsed from IoTCloud frontend */ + Serial.print("Current firmware version: "); + /* WARNING: This string is parsed from IoTCloud frontend */ + Serial.println(fv); + + String latestFv = LATEST_WIFI_FIRMWARE_VERSION; + if (fv >= latestFv) { + /* WARNING: This string is parsed from IoTCloud frontend */ + Serial.println("Latest firmware version correctly installed."); + } else { + /* WARNING: This string is parsed from IoTCloud frontend */ + String latestFvStr = "The firmware is not up to date. Latest version available: " + latestFv; + Serial.println(latestFvStr); + } +#else + Serial.println(); + /* WARNING: This string is parsed from IoTCloud frontend */ + Serial.println("Program finished."); +#endif } void loop() { } -String promptAndReadLine(const char* prompt) { - Serial.print(prompt); - String s = readLine(); +String promptAndReadLine(const char* prompt, const unsigned int timeout) { + String s = ""; + while(1) { + Serial.print(prompt); + s = readLine(timeout); + if (s.length() > 0) { + break; + } + } Serial.println(s); return s; } -String readLine() { - String line; +bool isExpired(const unsigned int start, const unsigned int timeout) { + if (timeout) { + return (millis() - start) > timeout; + } else { + return false; + } +} - while (1) { +String readLine(const unsigned int timeout) { + String line; + const unsigned int start = millis(); + while (!isExpired(start, timeout)) { if (Serial.available()) { char c = Serial.read(); From 6be3d18458eb926e01b703ab393e29d2488a815f Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 16 Feb 2024 13:47:36 +0100 Subject: [PATCH 500/780] Add common define for boards with secure element --- src/AIoTC_Config.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 7692e2f46..e7500120f 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -128,6 +128,10 @@ #define HAS_TCP #endif +#if defined(BOARD_HAS_SOFTSE) || defined(BOARD_HAS_OFFLOADED_ECCX08) || defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_SE050) + #define BOARD_HAS_SECURE_ELEMENT +#endif + /****************************************************************************** * CONSTANTS ******************************************************************************/ From f5564782031ff67d440cb6dca466f6c0099b91f2 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 16 Feb 2024 13:51:34 +0100 Subject: [PATCH 501/780] UNO R4 WiFi: allow both username/password and mTLS authentication --- src/AIoTC_Config.h | 1 + src/ArduinoIoTCloudTCP.cpp | 82 ++++++++++++++++++++---------------- src/ArduinoIoTCloudTCP.h | 86 ++++++++++++++++++-------------------- src/tls/AIoTCUPCert.h | 2 +- 4 files changed, 89 insertions(+), 82 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index e7500120f..eef6a764b 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -125,6 +125,7 @@ #if defined(ARDUINO_UNOR4_WIFI) #define BOARD_HAS_SOFTSE + #define BOARD_HAS_SECRET_KEY #define HAS_TCP #endif diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e307efaa9..e1a592452 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -24,7 +24,7 @@ #ifdef HAS_TCP #include -#ifdef BOARD_HAS_SECRET_KEY +#if defined(BOARD_HAS_SECRET_KEY) #include "tls/AIoTCUPCert.h" #endif @@ -114,8 +114,13 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_watchdog, String brokerAddress, uint16_t brokerPort) { _connection = &connection; +#ifdef BOARD_HAS_SECRET_KEY + _brokerAddress = _password.length() ? DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH : brokerAddress; + _brokerPort = _password.length() ? DEFAULT_BROKER_PORT_USER_PASS_AUTH : brokerPort; +#else _brokerAddress = brokerAddress; _brokerPort = brokerPort; +#endif _time_service.begin(&connection); return begin(enable_watchdog, _brokerAddress, _brokerPort); } @@ -130,55 +135,60 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, DEBUG_VERBOSE("SHA256: HASH(%d) = %s", strlen(_ota_img_sha256.c_str()), _ota_img_sha256.c_str()); #endif /* OTA_ENABLED */ -#if !defined(BOARD_HAS_SECRET_KEY) - if (!_crypto.begin()) - { - DEBUG_ERROR("_crypto.begin() failed."); - return 0; - } - if (!SElementArduinoCloudDeviceId::read(_crypto, getDeviceId(), SElementArduinoCloudSlot::DeviceId)) +#if defined(BOARD_HAS_SECRET_KEY) + /* If board is not configured for username and password login */ + if(!_password.length()) { - DEBUG_ERROR("_crypto.readDeviceId(...) failed."); - return 0; - } #endif - -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_SE050) || defined(BOARD_HAS_SOFTSE) - if (!SElementArduinoCloudCertificate::read(_crypto, _cert, SElementArduinoCloudSlot::CompressedCertificate)) - { - DEBUG_ERROR("Cryptography certificate reconstruction failure."); - return 0; +#if defined(BOARD_HAS_SECURE_ELEMENT) + if (!_crypto.begin()) + { + DEBUG_ERROR("_crypto.begin() failed."); + return 0; + } + if (!SElementArduinoCloudDeviceId::read(_crypto, getDeviceId(), SElementArduinoCloudSlot::DeviceId)) + { + DEBUG_ERROR("_crypto.readDeviceId(...) failed."); + return 0; + } + #if !defined(BOARD_HAS_OFFLOADED_ECCX08) + if (!SElementArduinoCloudCertificate::read(_crypto, _cert, SElementArduinoCloudSlot::CompressedCertificate)) + { + DEBUG_ERROR("Cryptography certificate reconstruction failure."); + return 0; + } + _sslClient.setEccSlot(static_cast(SElementArduinoCloudSlot::Key), _cert.bytes(), _cert.length()); + #endif +#endif +#if defined(BOARD_HAS_SECRET_KEY) } - _sslClient.setEccSlot(static_cast(SElementArduinoCloudSlot::Key), _cert.bytes(), _cert.length()); #endif +#if defined(BOARD_HAS_OFFLOADED_ECCX08) -#if defined(BOARD_HAS_SECRET_KEY) - #if defined(ARDUINO_EDGE_CONTROL) - _sslClient.appendCustomCACert(AIoTUPCert); - #elif defined(ARDUINO_ARCH_ESP32) - _sslClient.setCACertBundle(x509_crt_bundle); - #else - _sslClient.setInsecure(); - #endif -#else - #if defined(BOARD_HAS_ECCX08) +#elif defined(BOARD_HAS_ECCX08) _sslClient.setClient(_connection->getClient()); - #elif defined(BOARD_HAS_SE050) - #if defined(ARDUINO_PORTENTA_C33) +#elif defined(ARDUINO_PORTENTA_C33) _sslClient.setClient(_connection->getClient()); _sslClient.setCACert(AIoTSSCert); - #else +#elif defined(ARDUINO_NICLA_VISION) _sslClient.appendCustomCACert(AIoTSSCert); - #endif - #elif defined(BOARD_HAS_SOFTSE) - _sslClient.setCACert(AIoTSSCert, strlen(AIoTSSCert)); - #endif +#elif defined(ARDUINO_EDGE_CONTROL) + _sslClient.appendCustomCACert(AIoTUPCert); +#elif defined(ARDUINO_UNOR4_WIFI) + +#elif defined(ARDUINO_ARCH_ESP32) + _sslClient.setCACertBundle(x509_crt_bundle); +#elif defined(ARDUINO_ARCH_ESP8266) + _sslClient.setInsecure(); #endif _mqttClient.setClient(_sslClient); #ifdef BOARD_HAS_SECRET_KEY - _mqttClient.setUsernamePassword(getDeviceId(), _password); + if(_password.length()) + { + _mqttClient.setUsernamePassword(getDeviceId(), _password); + } #endif _mqttClient.onMessage(ArduinoIoTCloudTCP::onMessage); _mqttClient.setKeepAliveInterval(30 * 1000); diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index a36abfef3..b305b1b4e 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -26,42 +26,42 @@ #include #include -#if defined(BOARD_HAS_SECRET_KEY) - #if defined(BOARD_ESP) - #include - #elif defined(ARDUINO_EDGE_CONTROL) - #include - #endif -#else +#if defined(BOARD_HAS_SECURE_ELEMENT) #include #include - #if defined(BOARD_HAS_OFFLOADED_ECCX08) - #else + #if !defined(BOARD_HAS_OFFLOADED_ECCX08) #include - #ifdef BOARD_HAS_ECCX08 - #include "tls/BearSSLClient.h" - #elif defined(BOARD_HAS_OFFLOADED_ECCX08) - #include - #elif defined(BOARD_HAS_SE050) - #if defined(ARDUINO_PORTENTA_C33) - #include - #else - #include - #endif - #elif defined(BOARD_HAS_SOFTSE) - #include - #endif #endif #endif +#if defined(BOARD_HAS_OFFLOADED_ECCX08) + #include "WiFiSSLClient.h" +#elif defined(BOARD_HAS_ECCX08) + #include "tls/BearSSLClient.h" +#elif defined(ARDUINO_PORTENTA_C33) + #include +#elif defined(ARDUINO_NICLA_VISION) + #include +#elif defined(ARDUINO_EDGE_CONTROL) + #include +#elif defined(ARDUINO_UNOR4_WIFI) + #include +#elif defined(BOARD_ESP) + #include +#endif + /****************************************************************************** CONSTANTS ******************************************************************************/ - +#if defined(BOARD_HAS_SECURE_ELEMENT) static char const DEFAULT_BROKER_ADDRESS_SECURE_AUTH[] = "mqtts-sa.iot.arduino.cc"; static uint16_t const DEFAULT_BROKER_PORT_SECURE_AUTH = 8883; +#endif + +#if defined(BOARD_HAS_SECRET_KEY) static char const DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH[] = "mqtts-up.iot.arduino.cc"; static uint16_t const DEFAULT_BROKER_PORT_USER_PASS_AUTH = 8884; +#endif /****************************************************************************** * TYPEDEF @@ -85,11 +85,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass virtual int connected () override; virtual void printDebugInfo() override; - #if !defined(BOARD_HAS_SECRET_KEY) int begin(ConnectionHandler & connection, bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH); - #else - int begin(ConnectionHandler & connection, bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_USER_PASS_AUTH); - #endif int begin(bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS_SECURE_AUTH, uint16_t brokerPort = DEFAULT_BROKER_PORT_SECURE_AUTH); #ifdef BOARD_HAS_SECRET_KEY @@ -150,29 +146,29 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #if defined(BOARD_HAS_SECRET_KEY) String _password; - #if defined(BOARD_ESP) - WiFiClientSecure _sslClient; - #elif defined(ARDUINO_EDGE_CONTROL) - GSMSSLClient _sslClient; - #endif -#else +#endif + +#if defined(BOARD_HAS_SECURE_ELEMENT) SecureElement _crypto; - #if defined(BOARD_HAS_OFFLOADED_ECCX08) - WiFiBearSSLClient _sslClient; - #else - ECP256Certificate _cert; - #if defined(BOARD_HAS_ECCX08) + #if !defined(BOARD_HAS_OFFLOADED_ECCX08) + ECP256Certificate _cert; + #endif +#endif + +#if defined(BOARD_HAS_OFFLOADED_ECCX08) + WiFiSSLClient _sslClient; +#elif defined(BOARD_HAS_ECCX08) BearSSLClient _sslClient; - #elif defined(BOARD_HAS_SE050) - #if defined(ARDUINO_PORTENTA_C33) +#elif defined(ARDUINO_PORTENTA_C33) SSLClient _sslClient; - #else +#elif defined(ARDUINO_NICLA_VISION) WiFiSSLSE050Client _sslClient; - #endif - #elif defined(BOARD_HAS_SOFTSE) +#elif defined(ARDUINO_EDGE_CONTROL) + GSMSSLClient _sslClient; +#elif defined(ARDUINO_UNOR4_WIFI) WiFiSSLClient _sslClient; - #endif - #endif +#elif defined(BOARD_ESP) + WiFiClientSecure _sslClient; #endif MqttClient _mqttClient; diff --git a/src/tls/AIoTCUPCert.h b/src/tls/AIoTCUPCert.h index ac3daa707..330b8cb78 100644 --- a/src/tls/AIoTCUPCert.h +++ b/src/tls/AIoTCUPCert.h @@ -24,7 +24,7 @@ ******************************************************************************/ #include -#ifdef ARDUINO_ARCH_ESP32 +#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_UNOR4_WIFI) /****************************************************************************** * CONSTANTS From 8a1ab608524abdf95bcfb05ee48f2c0255151ffb Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 16 Feb 2024 13:56:51 +0100 Subject: [PATCH 502/780] Add Arduino_SecureElement to compile examples workflow --- .github/workflows/compile-examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 46837b40d..baf9a4b1e 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -24,6 +24,7 @@ jobs: - name: Arduino_ConnectionHandler - name: Arduino_DebugUtils - name: ArduinoMqttClient + - name: Arduino_SecureElement # sketch paths to compile (recursive) for all boards UNIVERSAL_SKETCH_PATHS: | - examples/ArduinoIoTCloud-Advanced From 37442d2b2d03e851a0182a560e7842a251359af6 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 16 Feb 2024 16:58:02 +0100 Subject: [PATCH 503/780] Use the same url for username/password and mTLS connection --- src/ArduinoIoTCloudTCP.cpp | 3 +-- src/ArduinoIoTCloudTCP.h | 10 ++-------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e1a592452..906cd2dcf 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -114,11 +114,10 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_watchdog, String brokerAddress, uint16_t brokerPort) { _connection = &connection; + _brokerAddress = brokerAddress; #ifdef BOARD_HAS_SECRET_KEY - _brokerAddress = _password.length() ? DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH : brokerAddress; _brokerPort = _password.length() ? DEFAULT_BROKER_PORT_USER_PASS_AUTH : brokerPort; #else - _brokerAddress = brokerAddress; _brokerPort = brokerPort; #endif _time_service.begin(&connection); diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index b305b1b4e..18b5541b4 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -53,15 +53,9 @@ /****************************************************************************** CONSTANTS ******************************************************************************/ -#if defined(BOARD_HAS_SECURE_ELEMENT) -static char const DEFAULT_BROKER_ADDRESS_SECURE_AUTH[] = "mqtts-sa.iot.arduino.cc"; +static char const DEFAULT_BROKER_ADDRESS_SECURE_AUTH[] = "iot.arduino.cc"; static uint16_t const DEFAULT_BROKER_PORT_SECURE_AUTH = 8883; -#endif - -#if defined(BOARD_HAS_SECRET_KEY) -static char const DEFAULT_BROKER_ADDRESS_USER_PASS_AUTH[] = "mqtts-up.iot.arduino.cc"; static uint16_t const DEFAULT_BROKER_PORT_USER_PASS_AUTH = 8884; -#endif /****************************************************************************** * TYPEDEF @@ -151,7 +145,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #if defined(BOARD_HAS_SECURE_ELEMENT) SecureElement _crypto; #if !defined(BOARD_HAS_OFFLOADED_ECCX08) - ECP256Certificate _cert; + ECP256Certificate _cert; #endif #endif From 27f536b4fa7d879b83046ad334d0b881185b1501 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 27 Feb 2024 11:45:09 +0100 Subject: [PATCH 504/780] UNO R4 WiFi: add error message about fw version and device certificate --- src/ArduinoIoTCloudTCP.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 906cd2dcf..d08051a23 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -143,6 +143,11 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, if (!_crypto.begin()) { DEBUG_ERROR("_crypto.begin() failed."); +#if defined(ARDUINO_UNOWIFIR4) + if (String(WiFi.firmwareVersion()) < String("0.4.1")) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to read device certificate, WiFi firmware needs to be >= 0.4.1, current %s", __FUNCTION__, WiFi.firmwareVersion()); + } +#endif return 0; } if (!SElementArduinoCloudDeviceId::read(_crypto, getDeviceId(), SElementArduinoCloudSlot::DeviceId)) From 863408476216c01820f67afe37b3fd3323996ebe Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 27 Feb 2024 11:49:42 +0100 Subject: [PATCH 505/780] Rename _crypto in _selement --- src/ArduinoIoTCloudTCP.cpp | 10 +++++----- src/ArduinoIoTCloudTCP.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index d08051a23..5c009c484 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -140,9 +140,9 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, { #endif #if defined(BOARD_HAS_SECURE_ELEMENT) - if (!_crypto.begin()) + if (!_selement.begin()) { - DEBUG_ERROR("_crypto.begin() failed."); + DEBUG_ERROR("_selement.begin() failed."); #if defined(ARDUINO_UNOWIFIR4) if (String(WiFi.firmwareVersion()) < String("0.4.1")) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to read device certificate, WiFi firmware needs to be >= 0.4.1, current %s", __FUNCTION__, WiFi.firmwareVersion()); @@ -150,13 +150,13 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #endif return 0; } - if (!SElementArduinoCloudDeviceId::read(_crypto, getDeviceId(), SElementArduinoCloudSlot::DeviceId)) + if (!SElementArduinoCloudDeviceId::read(_selement, getDeviceId(), SElementArduinoCloudSlot::DeviceId)) { - DEBUG_ERROR("_crypto.readDeviceId(...) failed."); + DEBUG_ERROR("_selement.readDeviceId(...) failed."); return 0; } #if !defined(BOARD_HAS_OFFLOADED_ECCX08) - if (!SElementArduinoCloudCertificate::read(_crypto, _cert, SElementArduinoCloudSlot::CompressedCertificate)) + if (!SElementArduinoCloudCertificate::read(_selement, _cert, SElementArduinoCloudSlot::CompressedCertificate)) { DEBUG_ERROR("Cryptography certificate reconstruction failure."); return 0; diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 18b5541b4..821fb9dda 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -143,7 +143,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #endif #if defined(BOARD_HAS_SECURE_ELEMENT) - SecureElement _crypto; + SecureElement _selement; #if !defined(BOARD_HAS_OFFLOADED_ECCX08) ECP256Certificate _cert; #endif From 6575af1764554a358fd1b41dde31b948b8e3f154 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 27 Feb 2024 11:53:09 +0100 Subject: [PATCH 506/780] Align style of secure element debug error prints --- src/ArduinoIoTCloudTCP.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 5c009c484..a78915031 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -142,7 +142,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #if defined(BOARD_HAS_SECURE_ELEMENT) if (!_selement.begin()) { - DEBUG_ERROR("_selement.begin() failed."); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not initialize secure element.", __FUNCTION__); #if defined(ARDUINO_UNOWIFIR4) if (String(WiFi.firmwareVersion()) < String("0.4.1")) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to read device certificate, WiFi firmware needs to be >= 0.4.1, current %s", __FUNCTION__, WiFi.firmwareVersion()); @@ -152,13 +152,13 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, } if (!SElementArduinoCloudDeviceId::read(_selement, getDeviceId(), SElementArduinoCloudSlot::DeviceId)) { - DEBUG_ERROR("_selement.readDeviceId(...) failed."); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not read device id.", __FUNCTION__); return 0; } #if !defined(BOARD_HAS_OFFLOADED_ECCX08) if (!SElementArduinoCloudCertificate::read(_selement, _cert, SElementArduinoCloudSlot::CompressedCertificate)) { - DEBUG_ERROR("Cryptography certificate reconstruction failure."); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not read device certificate.", __FUNCTION__); return 0; } _sslClient.setEccSlot(static_cast(SElementArduinoCloudSlot::Key), _cert.bytes(), _cert.length()); From ae996ce7f9003c8e8991f191566f17eb25abaa2a Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 5 Mar 2024 10:17:58 +0100 Subject: [PATCH 507/780] Fix: use WiFiBearSSLClient for boards with offloaded ECCX08 --- src/ArduinoIoTCloudTCP.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 821fb9dda..60b6649cc 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -150,7 +150,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #endif #if defined(BOARD_HAS_OFFLOADED_ECCX08) - WiFiSSLClient _sslClient; + WiFiBearSSLClient _sslClient; #elif defined(BOARD_HAS_ECCX08) BearSSLClient _sslClient; #elif defined(ARDUINO_PORTENTA_C33) From cf66030485abf764248c8eecf6659a7feff97893 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Tue, 5 Mar 2024 13:48:10 +0100 Subject: [PATCH 508/780] Release v1.15.0 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 7011c0cc0..de37c314a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.14.0 +version=1.15.0 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index eef6a764b..7bfd18c14 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -150,6 +150,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.14.0" +#define AIOT_CONFIG_LIB_VERSION "1.15.0" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From e1d9c8e0370faf1cb186e085e902f5ac13c1a7dc Mon Sep 17 00:00:00 2001 From: "Zachary J. Fields" Date: Tue, 12 Mar 2024 09:32:02 -0500 Subject: [PATCH 509/780] fix: Add dependency: `Arduino_SecureElement` Recent change relies on `Arduino_SecureElement`, but failed to include the dependency to library.properties. --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index de37c314a..59c4474d0 100644 --- a/library.properties +++ b/library.properties @@ -8,4 +8,4 @@ category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta,mbed_giga,renesas_portenta,renesas_uno,mbed_edge includes=ArduinoIoTCloud.h -depends=Arduino_ConnectionHandler,Arduino_DebugUtils,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,Arduino_ESP32_OTA,Arduino_Portenta_OTA +depends=Arduino_ConnectionHandler,Arduino_DebugUtils,Arduino_SecureElement,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,Arduino_ESP32_OTA,Arduino_Portenta_OTA From 50b512aaf4b9aa6dfcd763d7fcfc02d5bcfdb8b0 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Tue, 12 Mar 2024 16:04:47 +0100 Subject: [PATCH 510/780] Release v1.15.1 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 59c4474d0..c98825ea2 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.15.0 +version=1.15.1 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 7bfd18c14..e47a8ac2b 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -150,6 +150,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.15.0" +#define AIOT_CONFIG_LIB_VERSION "1.15.1" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From da8250035b574725929540ec4ac3a3f860e1dffc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 14:48:45 +0100 Subject: [PATCH 511/780] Bump geekyeggo/delete-artifact from 4 to 5 in /.github/workflows (#436) Bumps [geekyeggo/delete-artifact](https://github.com/geekyeggo/delete-artifact) from 4 to 5. - [Release notes](https://github.com/geekyeggo/delete-artifact/releases) - [Changelog](https://github.com/GeekyEggo/delete-artifact/blob/main/CHANGELOG.md) - [Commits](https://github.com/geekyeggo/delete-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: geekyeggo/delete-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/sync-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index d93984812..8c422de0f 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -114,7 +114,7 @@ jobs: path: ${{ env.CONFIGURATIONS_FOLDER }} - name: Remove unneeded artifact - uses: geekyeggo/delete-artifact@v4 + uses: geekyeggo/delete-artifact@v5 with: name: ${{ env.CONFIGURATIONS_ARTIFACT }} From 48df22a02ad38894f78eb1aadc766b51a03a41b2 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 28 Mar 2024 09:27:34 +0100 Subject: [PATCH 512/780] Add setThingId call in Travic_CI sketch to ensure checking function existance --- examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index 3410978bd..55b83771d 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -15,6 +15,10 @@ #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #endif +#if defined(BOARD_HAS_LORA) + #define THING_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" +#endif + /****************************************************************************** GLOBAL CONSTANTS ******************************************************************************/ @@ -114,6 +118,7 @@ void initProperties() { #elif defined(BOARD_HAS_LORA) void initProperties() { + ArduinoCloud.setThingId(THING_ID); ArduinoCloud.addProperty(bool_property_1, 1, READWRITE, 1 * SECONDS); ArduinoCloud.addProperty(int_property_1, 2, READ, 2 * MINUTES); From 2c7ba81b4bfa32965bdf65c16a3109bd6dc6012e Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 20 Feb 2024 15:46:30 +0100 Subject: [PATCH 513/780] Add Property write policy to manually handle local values update --- src/property/Property.cpp | 13 +++++++++++++ src/property/Property.h | 12 +++++++++++- src/property/PropertyContainer.cpp | 4 +++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/property/Property.cpp b/src/property/Property.cpp index b26494ed9..6297c09cb 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -29,6 +29,7 @@ Property::Property() , _min_delta_property{0.0f} , _min_time_between_updates_millis{DEFAULT_MIN_TIME_BETWEEN_UPDATES_MILLIS} , _permission{Permission::Read} +, _write_policy{WritePolicy::Auto} , _get_time_func{nullptr} , _update_callback_func{nullptr} , _on_sync_callback_func{nullptr} @@ -102,6 +103,18 @@ Property & Property::encodeTimestamp() return (*this); } +Property & Property::writeOnChange() +{ + _write_policy = WritePolicy::Auto; + return (*this); +} + +Property & Property::writeOnDemand() +{ + _write_policy = WritePolicy::Manual; + return (*this); +} + void Property::setTimestamp(unsigned long const timestamp) { _timestamp = timestamp; diff --git a/src/property/Property.h b/src/property/Property.h index 7393da192..71a8447c9 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -125,6 +125,10 @@ enum class UpdatePolicy { OnChange, TimeInterval, OnDemand }; +enum class WritePolicy { + Auto, Manual +}; + typedef void(*UpdateCallbackFunc)(void); typedef unsigned long(*GetTimeCallbackFunc)(); class Property; @@ -147,6 +151,8 @@ class Property Property & publishEvery(unsigned long const seconds); Property & publishOnDemand(); Property & encodeTimestamp(); + Property & writeOnChange(); + Property & writeOnDemand(); inline String name() const { return _name; @@ -160,6 +166,9 @@ class Property inline bool isWriteableByCloud() const { return (_permission == Permission::Write) || (_permission == Permission::ReadWrite); } + inline bool isWritableOnChange() const { + return _write_policy == WritePolicy::Auto; + } void setTimestamp(unsigned long const timestamp); bool shouldBeUpdated(); @@ -209,6 +218,7 @@ class Property private: Permission _permission; + WritePolicy _write_policy; GetTimeCallbackFunc _get_time_func; UpdateCallbackFunc _update_callback_func; OnSyncCallbackFunc _on_sync_callback_func; @@ -219,7 +229,7 @@ class Property _has_been_appended_but_not_sended; /* Variables used for UpdatePolicy::TimeInterval */ unsigned long _last_updated_millis, - _update_interval_millis; + _update_interval_millis; /* Variables used for reconnection sync*/ unsigned long _last_local_change_timestamp; unsigned long _last_cloud_change_timestamp; diff --git a/src/property/PropertyContainer.cpp b/src/property/PropertyContainer.cpp index 833250f02..77ae52a36 100644 --- a/src/property/PropertyContainer.cpp +++ b/src/property/PropertyContainer.cpp @@ -121,7 +121,9 @@ void updateProperty(PropertyContainer & prop_cont, String propertyName, unsigned if (is_sync_message) { property->execCallbackOnSync(); } else { - property->fromCloudToLocal(); + if (property->isWritableOnChange()) { + property->fromCloudToLocal(); + } property->execCallbackOnChange(); property->provideEcho(); } From af472ca354fdcbdaf1a194595ded22b5858a1b31 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 20 Feb 2024 15:48:07 +0100 Subject: [PATCH 514/780] Remove public functions to handle thing_id discovery protocol --- src/ArduinoIoTCloud.cpp | 1 + src/ArduinoIoTCloud.h | 7 +------ src/ArduinoIoTCloudTCP.cpp | 21 ++++++++------------- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 580521047..7d4676e57 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -32,6 +32,7 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() , _tz_offset{0} , _tz_dst_until{0} , _thing_id{""} +, _thing_id_property{nullptr} , _lib_version{AIOT_CONFIG_LIB_VERSION} , _device_id{""} , _cloud_event_callback{nullptr} diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 6154f25e9..bf1c6dc8c 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -96,12 +96,6 @@ class ArduinoIoTCloudClass inline void setDeviceId(String const device_id) { _device_id = device_id; }; inline String & getDeviceId() { return _device_id; }; - inline void setThingIdOutdatedFlag() { _thing_id_outdated = true ; } - inline void clrThingIdOutdatedFlag() { _thing_id_outdated = false ; } - inline bool getThingIdOutdatedFlag() { return _thing_id_outdated; } - - inline bool deviceNotAttached() { return _thing_id == ""; } - inline ConnectionHandler * getConnection() { return _connection; } inline unsigned long getInternalTime() { return _time_service.getTime(); } @@ -160,6 +154,7 @@ class ArduinoIoTCloudClass int _tz_offset; unsigned int _tz_dst_until; String _thing_id; + Property * _thing_id_property; String _lib_version; void execCloudEventCallback(ArduinoIoTCloudEvent const event); diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index a78915031..5200e1043 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -58,11 +58,6 @@ void updateTimezoneInfo() ArduinoCloud.updateInternalTimezoneInfo(); } -void setThingIdOutdated() -{ - ArduinoCloud.setThingIdOutdatedFlag(); -} - /****************************************************************************** CTOR/DTOR ******************************************************************************/ @@ -218,7 +213,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, addPropertyToContainer(_device_property_container, *p, "OTA_REQ", Permission::ReadWrite, -1); #endif /* OTA_ENABLED */ p = new CloudWrapperString(_thing_id); - addPropertyToContainer(_device_property_container, *p, "thing_id", Permission::ReadWrite, -1).onUpdate(setThingIdOutdated); + _thing_id_property = &addPropertyToContainer(_device_property_container, *p, "thing_id", Permission::ReadWrite, -1).writeOnDemand(); 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); @@ -409,7 +404,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() return State::Disconnect; } - if (getThingIdOutdatedFlag()) + if (_thing_id_property->isDifferentFromCloud()) { return State::CheckDeviceConfig; } @@ -445,7 +440,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() updateThingTopics(); - if (deviceNotAttached()) + if (_thing_id.length() == 0) { /* Configuration received but device not attached. Wait: 40s */ unsigned long attach_retry_delay = (1 << _last_device_attach_cnt) * AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms; @@ -468,7 +463,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() return State::Disconnect; } - if (getThingIdOutdatedFlag()) + if (_thing_id_property->isDifferentFromCloud()) { return State::CheckDeviceConfig; } @@ -524,7 +519,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() return State::Disconnect; } - if (getThingIdOutdatedFlag()) + if (_thing_id_property->isDifferentFromCloud()) { return State::CheckDeviceConfig; } @@ -567,7 +562,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() /* We are connected so let's to our stuff here. */ else { - if (getThingIdOutdatedFlag()) + if (_thing_id_property->isDifferentFromCloud()) { return State::CheckDeviceConfig; } @@ -762,12 +757,12 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l void ArduinoIoTCloudTCP::updateThingTopics() { + _thing_id_property->fromCloudToLocal(); + _shadowTopicOut = getTopic_shadowout(); _shadowTopicIn = getTopic_shadowin(); _dataTopicOut = getTopic_dataout(); _dataTopicIn = getTopic_datain(); - - clrThingIdOutdatedFlag(); } /****************************************************************************** From 896249be314b3fa80e93f92ec0580b3b30dad4a5 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 20 Feb 2024 16:14:40 +0100 Subject: [PATCH 515/780] Remove public functions to handle timezone changes --- src/ArduinoIoTCloud.cpp | 2 -- src/ArduinoIoTCloud.h | 3 --- src/ArduinoIoTCloudTCP.cpp | 28 +++++++++++++++++++--------- src/ArduinoIoTCloudTCP.h | 5 +++++ 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 7d4676e57..ce191eafd 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -29,8 +29,6 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() : _connection{nullptr} , _last_checked_property_index{0} , _time_service(TimeService) -, _tz_offset{0} -, _tz_dst_until{0} , _thing_id{""} , _thing_id_property{nullptr} , _lib_version{AIOT_CONFIG_LIB_VERSION} diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index bf1c6dc8c..9fa9d2963 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -100,7 +100,6 @@ class ArduinoIoTCloudClass inline unsigned long getInternalTime() { return _time_service.getTime(); } inline unsigned long getLocalTime() { return _time_service.getLocalTime(); } - inline void updateInternalTimezoneInfo() { _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); } void addCallback(ArduinoIoTCloudEvent const event, OnCloudEventCallback callback); @@ -151,8 +150,6 @@ class ArduinoIoTCloudClass PropertyContainer _thing_property_container; unsigned int _last_checked_property_index; TimeServiceClass & _time_service; - int _tz_offset; - unsigned int _tz_dst_until; String _thing_id; Property * _thing_id_property; String _lib_version; diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 5200e1043..87b1c555e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -53,17 +53,16 @@ unsigned long getTime() return ArduinoCloud.getInternalTime(); } -void updateTimezoneInfo() -{ - ArduinoCloud.updateInternalTimezoneInfo(); -} - /****************************************************************************** CTOR/DTOR ******************************************************************************/ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() : _state{State::ConnectPhy} +, _tz_offset{0} +, _tz_offset_property{nullptr} +, _tz_dst_until{0} +, _tz_dst_until_property{nullptr} , _next_connection_attempt_tick{0} , _last_connection_attempt_cnt{0} , _next_device_subscribe_attempt_tick{0} @@ -214,9 +213,10 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #endif /* OTA_ENABLED */ p = new CloudWrapperString(_thing_id); _thing_id_property = &addPropertyToContainer(_device_property_container, *p, "thing_id", Permission::ReadWrite, -1).writeOnDemand(); - - 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); + p = new CloudWrapperInt(_tz_offset); + _tz_offset_property = &addPropertyToContainer(_thing_property_container, *p, "tz_offset", Permission::ReadWrite, -1).writeOnDemand(); + p = new CloudWrapperUnsignedInt(_tz_dst_until); + _tz_dst_until_property = &addPropertyToContainer(_thing_property_container, *p, "tz_dst_until", Permission::ReadWrite, -1).writeOnDemand(); #if OTA_ENABLED _ota_cap = OTA::isCapable(); @@ -584,13 +584,23 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() _mqtt_data_request_retransmit = false; } + /* Configure Time service with timezone data: + * _tz_offset [offset + dst] + * _tz_dst_until [posix timestamp until _tz_offset is valid] + */ + if (_tz_offset_property->isDifferentFromCloud() || _tz_dst_until_property->isDifferentFromCloud()) { + _tz_offset_property->fromCloudToLocal(); + _tz_dst_until_property->fromCloudToLocal(); + _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); + } + /* Check if any properties need encoding and send them to * the cloud if necessary. */ sendThingPropertiesToCloud(); unsigned long const internal_posix_time = _time_service.getTime(); - if(internal_posix_time < _tz_dst_until) { + if (internal_posix_time < _tz_dst_until) { return State::Connected; } else { return State::RequestLastValues; diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 60b6649cc..d00bb0ca6 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -123,6 +123,11 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass State _state; + int _tz_offset; + Property * _tz_offset_property; + unsigned int _tz_dst_until; + Property * _tz_dst_until_property; + unsigned long _next_connection_attempt_tick; unsigned int _last_connection_attempt_cnt; unsigned long _next_device_subscribe_attempt_tick; From 50ade9196cf92d9b2fc383610a150f4173c8e697 Mon Sep 17 00:00:00 2001 From: "Zachary J. Fields" Date: Thu, 28 Mar 2024 23:58:10 -0500 Subject: [PATCH 516/780] fix: Await Serial Previous implementation was waiting while "Serial was NOT ready" AND "time passed is GREATER than 5 seconds". This can NEVER be true. Early logs were being missed and Serial had difficulty connecting during debugging. It should have instead been waiting while "Serial was NOT ready" AND "time passed is LESS THAN OR EQUAL TO 5 seconds". --- .../ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino | 2 +- examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino | 2 +- .../ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino | 4 ++-- .../ArduinoIoTCloud-DeferredOTA.ino | 4 ++-- .../ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino | 4 ++-- .../ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino index 4f45a395d..095850406 100644 --- a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino +++ b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino @@ -15,7 +15,7 @@ void setup() { /* Initialize serial and wait up to 5 seconds for port to open */ Serial.begin(9600); - for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime > 5000); ) { } + for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime <= 5000); ) { } /* This function takes care of connecting your sketch variables to the ArduinoIoTCloud object */ initProperties(); diff --git a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino index cb146900d..a37996b31 100644 --- a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino +++ b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino @@ -23,7 +23,7 @@ static int const LED_BUILTIN = 2; void setup() { /* Initialize serial and wait up to 5 seconds for port to open */ Serial.begin(9600); - for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime > 5000); ) { } + for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime <= 5000); ) { } /* Configure LED pin as an output */ pinMode(LED_BUILTIN, OUTPUT); diff --git a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino index c01153d9b..1d39a2f5a 100644 --- a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino +++ b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino @@ -8,7 +8,7 @@ You don't need any specific Properties to be created in order to demonstrate these functionalities. Simply create a new Thing and give it 1 arbitrary Property. - Remember that the Thing ID needs to be configured in thingProperties.h + Remember that the Thing ID needs to be configured in thingProperties.h These events can be very useful in particular cases, for instance to disable a peripheral or a connected sensor/actuator when no data connection is available, as well as to perform specific operations on connection or right after properties values are synchronised. @@ -31,7 +31,7 @@ void setup() { /* Initialize serial and wait up to 5 seconds for port to open */ Serial.begin(9600); - for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime > 5000); ) { } + for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime <= 5000); ) { } /* This function takes care of connecting your sketch variables to the ArduinoIoTCloud object */ initProperties(); diff --git a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino index bbe58c373..52fc87312 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino +++ b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino @@ -39,7 +39,7 @@ bool ask_user_via_serial() { if (Serial.available()) { char c = Serial.read(); if (c == 'y' || c == 'Y') { - return true; + return true; } } return false; @@ -56,7 +56,7 @@ bool onOTARequestCallback() void setup() { /* Initialize serial and wait up to 5 seconds for port to open */ Serial.begin(9600); - for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime > 5000); ) { } + for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime <= 5000); ) { } /* Configure LED pin as an output */ pinMode(LED_BUILTIN, OUTPUT); diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index 9adb83378..1e8a30d0d 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -15,7 +15,7 @@ static int const LED_BUILTIN = 2; void setup() { /* Initialize the serial port and wait up to 5 seconds for a connection */ Serial.begin(9600); - for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime > 5000); ) { } + for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime <= 5000); ) { } /* Configure LED pin as an output */ pinMode(LED_BUILTIN, OUTPUT); @@ -206,7 +206,7 @@ void loop() { if(daily.isActive()) { Serial.println("Daily schedule is active"); } - + /* Activate LED when the weekly schedule is active */ digitalWrite(LED_BUILTIN, weekly.isActive()); diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino b/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino index 575b55f49..4d478e065 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/ArduinoIoTCloud_Travis_CI.ino @@ -18,7 +18,7 @@ void setup() { Serial.begin(9600); unsigned long serialBeginTime = millis(); - while (!Serial && (millis() - serialBeginTime > 5000)); + while (!Serial && (millis() - serialBeginTime <= 5000)); Serial.println("Starting Arduino IoT Cloud Example"); From ab43cf37e55aac8004217556f15acfba7d8495cf Mon Sep 17 00:00:00 2001 From: "Zachary J. Fields" Date: Sat, 17 Feb 2024 18:03:31 -0600 Subject: [PATCH 517/780] chore: clean examples - Remove/replace deprecated API calls - Minimize file inclusions - Fix whitespace --- .../ArduinoIoTCloud-Advanced.ino | 3 +++ .../arduino_secrets.h | 4 ++-- .../thingProperties.h | 13 +++++++------ .../ArduinoIoTCloud-Basic.ino | 3 +++ .../ArduinoIoTCloud-Basic/arduino_secrets.h | 4 ++-- .../ArduinoIoTCloud-Basic/thingProperties.h | 7 ++++--- .../ArduinoIoTCloud-Callbacks.ino | 3 +++ .../arduino_secrets.h | 4 ++-- .../thingProperties.h | 1 + .../ArduinoIoTCloud-DeferredOTA.ino | 5 ++++- .../arduino_secrets.h | 4 ++-- .../thingProperties.h | 1 + .../ArduinoIoTCloud-Schedule.ino | 6 ++++-- .../arduino_secrets.h | 4 ++-- .../thingProperties.h | 19 ++++++++++--------- 15 files changed, 50 insertions(+), 31 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino index 4f45a395d..c99e84c88 100644 --- a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino +++ b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino @@ -10,6 +10,9 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ +#include + +#include "arduino_secrets.h" #include "thingProperties.h" void setup() { diff --git a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h index 2f6069225..7cd2dd0dc 100644 --- a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h @@ -1,4 +1,4 @@ -#include +#include /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what @@ -8,7 +8,7 @@ #define SECRET_PASS "YOUR_WIFI_PASSWORD" #endif -/* ESP8266 ESP32*/ +/* ESP8266 ESP32 */ #if defined(BOARD_HAS_SECRET_KEY) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index 09f965452..a8853e904 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -1,5 +1,6 @@ #include #include + #include "arduino_secrets.h" #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ @@ -24,13 +25,13 @@ void initProperties() { ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif #if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT) - ArduinoCloud.addProperty(switchButton, WRITE, ON_CHANGE, onSwitchButtonChange); - ArduinoCloud.addProperty(location, READ, ON_CHANGE); - ArduinoCloud.addProperty(color, READWRITE, ON_CHANGE, onColorChange); + ArduinoCloud.addProperty(switchButton, Permission::Write).onUpdate(onSwitchButtonChange); + ArduinoCloud.addProperty(location, Permission::Read).publishOnChange(0.0f); + ArduinoCloud.addProperty(color, Permission::ReadWrite).onUpdate(onColorChange); #elif defined(BOARD_HAS_LORA) - ArduinoCloud.addProperty(switchButton, 1, WRITE, ON_CHANGE, onSwitchButtonChange); - ArduinoCloud.addProperty(location, 2, READ, ON_CHANGE); - ArduinoCloud.addProperty(color, 3, READWRITE, ON_CHANGE, onColorChange); + ArduinoCloud.addProperty(switchButton, 1, Permission::Write).onUpdate(onSwitchButtonChange); + ArduinoCloud.addProperty(location, 2, Permission::Read).publishOnChange(0.0f); + ArduinoCloud.addProperty(color, 3, Permission::ReadWrite).onUpdate(onColorChange); #endif } diff --git a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino index cb146900d..000200054 100644 --- a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino +++ b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino @@ -14,6 +14,9 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ +#include + +#include "arduino_secrets.h" #include "thingProperties.h" #if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) diff --git a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h index 2f6069225..7cd2dd0dc 100644 --- a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h @@ -1,4 +1,4 @@ -#include +#include /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what @@ -8,7 +8,7 @@ #define SECRET_PASS "YOUR_WIFI_PASSWORD" #endif -/* ESP8266 ESP32*/ +/* ESP8266 ESP32 */ #if defined(BOARD_HAS_SECRET_KEY) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index b6025d89f..101abbef4 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -1,5 +1,6 @@ #include #include + #include "arduino_secrets.h" #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ @@ -27,9 +28,9 @@ void initProperties() { ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10); ArduinoCloud.addProperty(seconds, Permission::Read).publishOnChange(1); #elif defined(BOARD_HAS_LORA) - ArduinoCloud.addProperty(led, 1, READWRITE, ON_CHANGE, onLedChange); - ArduinoCloud.addProperty(potentiometer, 2, READ, ON_CHANGE); - ArduinoCloud.addProperty(seconds, 3, READ, 5 * MINUTES); + ArduinoCloud.addProperty(led, 1, Permission::ReadWrite).onUpdate(onLedChange); + ArduinoCloud.addProperty(potentiometer, 2, Permission::Read).publishOnChange(10); + ArduinoCloud.addProperty(seconds, 3, Permission::Read).publishEvery(5 * MINUTES); #endif } diff --git a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino index c01153d9b..d410e2169 100644 --- a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino +++ b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino @@ -26,6 +26,9 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ +#include + +#include "arduino_secrets.h" #include "thingProperties.h" void setup() { diff --git a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h index 2f6069225..7cd2dd0dc 100644 --- a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h @@ -1,4 +1,4 @@ -#include +#include /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what @@ -8,7 +8,7 @@ #define SECRET_PASS "YOUR_WIFI_PASSWORD" #endif -/* ESP8266 ESP32*/ +/* ESP8266 ESP32 */ #if defined(BOARD_HAS_SECRET_KEY) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index daed69097..d84fd1e57 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -1,5 +1,6 @@ #include #include + #include "arduino_secrets.h" #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ diff --git a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino index bbe58c373..c4d179f62 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino +++ b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino @@ -16,6 +16,9 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud/#ota */ +#include + +#include "arduino_secrets.h" #include "thingProperties.h" #if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) @@ -39,7 +42,7 @@ bool ask_user_via_serial() { if (Serial.available()) { char c = Serial.read(); if (c == 'y' || c == 'Y') { - return true; + return true; } } return false; diff --git a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h index b745cf215..a065e92e8 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h @@ -1,4 +1,4 @@ -#include +#include /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what @@ -8,7 +8,7 @@ #define SECRET_PASS "YOUR_WIFI_PASSWORD" #endif -/* ESP8266 ESP32*/ +/* ESP8266 ESP32 */ #if defined(BOARD_HAS_SECRET_KEY) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index 1aa4b1be3..d2e523fbe 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -1,5 +1,6 @@ #include #include + #include "arduino_secrets.h" #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_ETHERNET)) diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index 9adb83378..76be35130 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -6,6 +6,9 @@ */ +#include + +#include "arduino_secrets.h" #include "thingProperties.h" #if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) @@ -206,7 +209,7 @@ void loop() { if(daily.isActive()) { Serial.println("Daily schedule is active"); } - + /* Activate LED when the weekly schedule is active */ digitalWrite(LED_BUILTIN, weekly.isActive()); @@ -219,5 +222,4 @@ void loop() { if(yearly.isActive()) { Serial.println("Yearly schedule is active"); } - } diff --git a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h index 2f6069225..7cd2dd0dc 100644 --- a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h @@ -1,4 +1,4 @@ -#include +#include /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what @@ -8,7 +8,7 @@ #define SECRET_PASS "YOUR_WIFI_PASSWORD" #endif -/* ESP8266 ESP32*/ +/* ESP8266 ESP32 */ #if defined(BOARD_HAS_SECRET_KEY) #define SECRET_DEVICE_KEY "my-device-password" #endif diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 69a47186e..2fe16af9a 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -1,5 +1,6 @@ #include #include + #include "arduino_secrets.h" #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ @@ -28,16 +29,16 @@ void initProperties() { ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif #if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT) - ArduinoCloud.addProperty(switchButton, WRITE, ON_CHANGE); - ArduinoCloud.addProperty(oneShot, READWRITE, ON_CHANGE); - ArduinoCloud.addProperty(minute, READWRITE, ON_CHANGE); - ArduinoCloud.addProperty(hourly, READWRITE, ON_CHANGE); - ArduinoCloud.addProperty(daily, READWRITE, ON_CHANGE); - ArduinoCloud.addProperty(weekly, READWRITE, ON_CHANGE); - ArduinoCloud.addProperty(monthly, READWRITE, ON_CHANGE); - ArduinoCloud.addProperty(yearly, READWRITE, ON_CHANGE); + ArduinoCloud.addProperty(switchButton, Permission::Write).onUpdate(nullptr); + ArduinoCloud.addProperty(oneShot, Permission::ReadWrite).onUpdate(nullptr); + ArduinoCloud.addProperty(minute, Permission::ReadWrite).onUpdate(nullptr); + ArduinoCloud.addProperty(hourly, Permission::ReadWrite).onUpdate(nullptr); + ArduinoCloud.addProperty(daily, Permission::ReadWrite).onUpdate(nullptr); + ArduinoCloud.addProperty(weekly, Permission::ReadWrite).onUpdate(nullptr); + ArduinoCloud.addProperty(monthly, Permission::ReadWrite).onUpdate(nullptr); + ArduinoCloud.addProperty(yearly, Permission::ReadWrite).onUpdate(nullptr); #elif defined(BOARD_HAS_LORA) - ArduinoCloud.addProperty(switchButton, 1, WRITE, ON_CHANGE); + ArduinoCloud.addProperty(switchButton, 1, Permission::Write).onUpdate(nullptr); #endif } From 8ae88fce78168ff3a640b2c8cdb30b7ed47a7186 Mon Sep 17 00:00:00 2001 From: "Zachary J. Fields" Date: Fri, 15 Mar 2024 08:00:17 -0500 Subject: [PATCH 518/780] Apply suggestions from code review Co-authored-by: Mattia Pennasilico --- .../ArduinoIoTCloud-Advanced.ino | 3 --- .../arduino_secrets.h | 2 +- .../thingProperties.h | 1 - .../ArduinoIoTCloud-Basic.ino | 3 --- .../ArduinoIoTCloud-Basic/arduino_secrets.h | 2 +- .../ArduinoIoTCloud-Basic/thingProperties.h | 1 - .../ArduinoIoTCloud-Callbacks.ino | 3 --- .../arduino_secrets.h | 2 +- .../thingProperties.h | 1 - .../ArduinoIoTCloud-DeferredOTA.ino | 3 --- .../arduino_secrets.h | 2 +- .../thingProperties.h | 1 - .../ArduinoIoTCloud-Schedule.ino | 3 --- .../arduino_secrets.h | 2 +- .../thingProperties.h | 19 +++++++++---------- 15 files changed, 14 insertions(+), 34 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino index c99e84c88..4f45a395d 100644 --- a/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino +++ b/examples/ArduinoIoTCloud-Advanced/ArduinoIoTCloud-Advanced.ino @@ -10,9 +10,6 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ -#include - -#include "arduino_secrets.h" #include "thingProperties.h" void setup() { diff --git a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h index 7cd2dd0dc..7e5face72 100644 --- a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h @@ -1,4 +1,4 @@ -#include +#include /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index a8853e904..8d8269307 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -1,6 +1,5 @@ #include #include - #include "arduino_secrets.h" #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ diff --git a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino index 000200054..cb146900d 100644 --- a/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino +++ b/examples/ArduinoIoTCloud-Basic/ArduinoIoTCloud-Basic.ino @@ -14,9 +14,6 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ -#include - -#include "arduino_secrets.h" #include "thingProperties.h" #if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) diff --git a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h index 7cd2dd0dc..7e5face72 100644 --- a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h @@ -1,4 +1,4 @@ -#include +#include /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index 101abbef4..2792236e2 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -1,6 +1,5 @@ #include #include - #include "arduino_secrets.h" #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ diff --git a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino index d410e2169..c01153d9b 100644 --- a/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino +++ b/examples/ArduinoIoTCloud-Callbacks/ArduinoIoTCloud-Callbacks.ino @@ -26,9 +26,6 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud#what */ -#include - -#include "arduino_secrets.h" #include "thingProperties.h" void setup() { diff --git a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h index 7cd2dd0dc..7e5face72 100644 --- a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h @@ -1,4 +1,4 @@ -#include +#include /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index d84fd1e57..daed69097 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -1,6 +1,5 @@ #include #include - #include "arduino_secrets.h" #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ diff --git a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino index c4d179f62..7d6b775c3 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino +++ b/examples/ArduinoIoTCloud-DeferredOTA/ArduinoIoTCloud-DeferredOTA.ino @@ -16,9 +16,6 @@ - https://github.com/arduino-libraries/ArduinoIoTCloud/#ota */ -#include - -#include "arduino_secrets.h" #include "thingProperties.h" #if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) diff --git a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h index a065e92e8..177e1770b 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h @@ -1,4 +1,4 @@ -#include +#include /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index d2e523fbe..1aa4b1be3 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -1,6 +1,5 @@ #include #include - #include "arduino_secrets.h" #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_ETHERNET)) diff --git a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino index 76be35130..d24569196 100644 --- a/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino +++ b/examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino @@ -6,9 +6,6 @@ */ -#include - -#include "arduino_secrets.h" #include "thingProperties.h" #if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) diff --git a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h index 7cd2dd0dc..7e5face72 100644 --- a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h @@ -1,4 +1,4 @@ -#include +#include /* A complete list of supported boards with WiFi is available here: * https://github.com/arduino-libraries/ArduinoIoTCloud/#what diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 2fe16af9a..b6c3abb05 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -1,6 +1,5 @@ #include #include - #include "arduino_secrets.h" #if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ @@ -29,16 +28,16 @@ void initProperties() { ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif #if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT) - ArduinoCloud.addProperty(switchButton, Permission::Write).onUpdate(nullptr); - ArduinoCloud.addProperty(oneShot, Permission::ReadWrite).onUpdate(nullptr); - ArduinoCloud.addProperty(minute, Permission::ReadWrite).onUpdate(nullptr); - ArduinoCloud.addProperty(hourly, Permission::ReadWrite).onUpdate(nullptr); - ArduinoCloud.addProperty(daily, Permission::ReadWrite).onUpdate(nullptr); - ArduinoCloud.addProperty(weekly, Permission::ReadWrite).onUpdate(nullptr); - ArduinoCloud.addProperty(monthly, Permission::ReadWrite).onUpdate(nullptr); - ArduinoCloud.addProperty(yearly, Permission::ReadWrite).onUpdate(nullptr); + ArduinoCloud.addProperty(switchButton, Permission::Write); + ArduinoCloud.addProperty(oneShot, Permission::ReadWrite); + ArduinoCloud.addProperty(minute, Permission::ReadWrite); + ArduinoCloud.addProperty(hourly, Permission::ReadWrite); + ArduinoCloud.addProperty(daily, Permission::ReadWrite); + ArduinoCloud.addProperty(weekly, Permission::ReadWrite); + ArduinoCloud.addProperty(monthly, Permission::ReadWrite); + ArduinoCloud.addProperty(yearly, Permission::ReadWrite); #elif defined(BOARD_HAS_LORA) - ArduinoCloud.addProperty(switchButton, 1, Permission::Write).onUpdate(nullptr); + ArduinoCloud.addProperty(switchButton, 1, Permission::Write); #endif } From e33ea924bfb324695eb5556d41a30f9f4b3a057c Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 12 Mar 2024 16:52:12 +0100 Subject: [PATCH 519/780] SelfProvisioning: remove dependency from ArduinoIoTCloud library --- .../utility/SelfProvisioning/ECCX08Cert.cpp | 939 ------------------ .../utility/SelfProvisioning/ECCX08Cert.h | 141 --- .../SelfProvisioning/ECCX08TLSConfig.h | 105 -- .../SelfProvisioning/SelfProvisioning.ino | 102 +- 4 files changed, 51 insertions(+), 1236 deletions(-) delete mode 100644 examples/utility/SelfProvisioning/ECCX08Cert.cpp delete mode 100644 examples/utility/SelfProvisioning/ECCX08Cert.h delete mode 100644 examples/utility/SelfProvisioning/ECCX08TLSConfig.h diff --git a/examples/utility/SelfProvisioning/ECCX08Cert.cpp b/examples/utility/SelfProvisioning/ECCX08Cert.cpp deleted file mode 100644 index db037d4e0..000000000 --- a/examples/utility/SelfProvisioning/ECCX08Cert.cpp +++ /dev/null @@ -1,939 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2019 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 -#include -#include "ECCX08Cert.h" -#include "tls/utility/SHA256.h" - -/****************************************************************************** - * DEFINE - ******************************************************************************/ - -#define ASN1_INTEGER 0x02 -#define ASN1_BIT_STRING 0x03 -#define ASN1_NULL 0x05 -#define ASN1_OBJECT_IDENTIFIER 0x06 -#define ASN1_PRINTABLE_STRING 0x13 -#define ASN1_SEQUENCE 0x30 -#define ASN1_SET 0x31 - -struct __attribute__((__packed__)) CompressedCert { - byte signature[64]; - byte dates[3]; - byte unused[5]; -}; - -#define SERIAL_NUMBER_LENGTH 16 -#define AUTHORITY_KEY_IDENTIFIER_LENGTH 20 - -struct __attribute__((__packed__)) SerialNumberAndAuthorityKeyIdentifier { - byte serialNumber[SERIAL_NUMBER_LENGTH]; - byte authorityKeyIdentifier[AUTHORITY_KEY_IDENTIFIER_LENGTH]; -}; - -/****************************************************************************** - * LOCAL MODULE FUNCTIONS - ******************************************************************************/ - -static String base64Encode(const byte in[], unsigned int length, const char* prefix, const char* suffix) { - static const char* CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - - int b; - String out; - - int reserveLength = 4 * ((length + 2) / 3) + ((length / 3 * 4) / 76) + strlen(prefix) + strlen(suffix); - out.reserve(reserveLength); - - if (prefix) { - out += prefix; - } - - for (unsigned int i = 0; i < length; i += 3) { - if (i > 0 && (i / 3 * 4) % 76 == 0) { - out += '\n'; - } - - b = (in[i] & 0xFC) >> 2; - out += CODES[b]; - - b = (in[i] & 0x03) << 4; - if (i + 1 < length) { - b |= (in[i + 1] & 0xF0) >> 4; - out += CODES[b]; - b = (in[i + 1] & 0x0F) << 2; - if (i + 2 < length) { - b |= (in[i + 2] & 0xC0) >> 6; - out += CODES[b]; - b = in[i + 2] & 0x3F; - out += CODES[b]; - } else { - out += CODES[b]; - out += '='; - } - } else { - out += CODES[b]; - out += "=="; - } - } - - if (suffix) { - out += suffix; - } - - return out; -} - -/****************************************************************************** - * CTOR/DTOR - ******************************************************************************/ - -ECCX08CertClass::ECCX08CertClass() : - _keySlot(-1), - _compressedCertSlot(-1), - _serialNumberAndAuthorityKeyIdentifierSlot(-1), - _bytes(NULL), - _length(0) { -} - -ECCX08CertClass::~ECCX08CertClass() { - if (_bytes) { - free(_bytes); - _bytes = NULL; - } -} - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -int ECCX08CertClass::beginCSR(int keySlot, bool newPrivateKey) { - if (keySlot < 0 || keySlot > 8) { - return 0; - } - - _keySlot = keySlot; - - if (newPrivateKey) { - if (!ECCX08.generatePrivateKey(_keySlot, _temp)) { - return 0; - } - } else { - if (!ECCX08.generatePublicKey(_keySlot, _temp)) { - return 0; - } - } - - return 1; -} - -String ECCX08CertClass::endCSR() { - int versionLen = versionLength(); - int subjectLen = issuerOrSubjectLength(_subjectCountryName, - _subjectStateProvinceName, - _subjectLocalityName, - _subjectOrganizationName, - _subjectOrganizationalUnitName, - _subjectCommonName); - int subjectHeaderLen = sequenceHeaderLength(subjectLen); - int publicKeyLen = publicKeyLength(); - - int csrInfoLen = versionLen + subjectHeaderLen + subjectLen + publicKeyLen + 2; - int csrInfoHeaderLen = sequenceHeaderLength(csrInfoLen); - - byte csrInfo[csrInfoHeaderLen + csrInfoLen]; - byte* out = csrInfo; - - appendSequenceHeader(csrInfoLen, out); - out += csrInfoHeaderLen; - - // version - appendVersion(0x00, out); - out += versionLen; - - // subject - appendSequenceHeader(subjectLen, out); - out += subjectHeaderLen; - appendIssuerOrSubject(_subjectCountryName, - _subjectStateProvinceName, - _subjectLocalityName, - _subjectOrganizationName, - _subjectOrganizationalUnitName, - _subjectCommonName, out); - out += subjectLen; - - // public key - appendPublicKey(_temp, out); - out += publicKeyLen; - - // terminator - *out++ = 0xa0; - *out++ = 0x00; - - SHA256 sha256; - byte csrInfoSha256[64]; - byte signature[64]; - - sha256.begin(); - sha256.update(csrInfo, csrInfoHeaderLen + csrInfoLen); - sha256.finalize(csrInfoSha256); - - if (!ECCX08.ecSign(_keySlot, csrInfoSha256, signature)) { - return ""; - } - - int signatureLen = signatureLength(signature); - int csrLen = csrInfoHeaderLen + csrInfoLen + signatureLen; - int csrHeaderLen = sequenceHeaderLength(csrLen); - - byte csr[csrLen + csrHeaderLen]; - out = csr; - - appendSequenceHeader(csrLen, out); - out += csrHeaderLen; - - // info - memcpy(out, csrInfo, csrInfoHeaderLen + csrInfoLen); - out += (csrInfoHeaderLen + csrInfoLen); - - // signature - appendSignature(signature, out); - out += signatureLen; - - return base64Encode(csr, csrLen + csrHeaderLen, "-----BEGIN CERTIFICATE REQUEST-----\n", "\n-----END CERTIFICATE REQUEST-----\n"); -} - -int ECCX08CertClass::beginStorage(int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot) { - if (compressedCertSlot < 8 || compressedCertSlot > 15) { - return 0; - } - - if (serialNumberAndAuthorityKeyIdentifierSlot < 8 || serialNumberAndAuthorityKeyIdentifierSlot > 15) { - return 0; - } - - _compressedCertSlot = compressedCertSlot; - _serialNumberAndAuthorityKeyIdentifierSlot = serialNumberAndAuthorityKeyIdentifierSlot; - - memset(_temp, 0x00, sizeof(_temp)); - - return 1; -} - -void ECCX08CertClass::setSignature(byte signature[]) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - memcpy(compressedCert->signature, signature, 64); -} - -void ECCX08CertClass::setIssueYear(int issueYear) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[0] &= 0x07; - compressedCert->dates[0] |= (issueYear - 2000) << 3; -} - -void ECCX08CertClass::setIssueMonth(int issueMonth) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[0] &= 0xf8; - compressedCert->dates[0] |= issueMonth >> 1; - - compressedCert->dates[1] &= 0x7f; - compressedCert->dates[1] |= issueMonth << 7; -} - -void ECCX08CertClass::setIssueDay(int issueDay) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[1] &= 0x83; - compressedCert->dates[1] |= issueDay << 2; -} - -void ECCX08CertClass::setIssueHour(int issueHour) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[2] &= 0x1f; - compressedCert->dates[2] |= issueHour << 5; - - compressedCert->dates[1] &= 0xfc; - compressedCert->dates[1] |= issueHour >> 3; -} - -void ECCX08CertClass::setExpireYears(int expireYears) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[2] &= 0xe0; - compressedCert->dates[2] |= expireYears; -} - -void ECCX08CertClass::setSerialNumber(const byte serialNumber[]) { - memcpy(&_temp[72], serialNumber, SERIAL_NUMBER_LENGTH); -} - -void ECCX08CertClass::setAuthorityKeyIdentifier(const byte authorityKeyIdentifier[]) { - memcpy(&_temp[88], authorityKeyIdentifier, AUTHORITY_KEY_IDENTIFIER_LENGTH); -} - -int ECCX08CertClass::endStorage() { - if (!ECCX08.writeSlot(_compressedCertSlot, &_temp[0], 72)) { - return 0; - } - - if (!ECCX08.writeSlot(_serialNumberAndAuthorityKeyIdentifierSlot, &_temp[72], SERIAL_NUMBER_LENGTH + AUTHORITY_KEY_IDENTIFIER_LENGTH)) { - return 0; - } - - return 1; -} - -int ECCX08CertClass::beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot) { - if (keySlot < 0 || keySlot > 8) { - return 0; - } - - if (compressedCertSlot < 8 || compressedCertSlot > 15) { - return 0; - } - - if (serialNumberAndAuthorityKeyIdentifierSlot < 8 || serialNumberAndAuthorityKeyIdentifierSlot > 15) { - return 0; - } - - _keySlot = keySlot; - _compressedCertSlot = compressedCertSlot; - _serialNumberAndAuthorityKeyIdentifierSlot = serialNumberAndAuthorityKeyIdentifierSlot; - - return 1; -} - -int ECCX08CertClass::endReconstruction() { - byte publicKey[64]; - struct CompressedCert compressedCert; - struct SerialNumberAndAuthorityKeyIdentifier serialNumberAndAuthorityKeyIdentifier; - - if (!ECCX08.generatePublicKey(_keySlot, publicKey)) { - return 0; - } - - if (!ECCX08.readSlot(_compressedCertSlot, (byte*)&compressedCert, sizeof(compressedCert))) { - return 0; - } - - if (!ECCX08.readSlot(_serialNumberAndAuthorityKeyIdentifierSlot, (byte*)&serialNumberAndAuthorityKeyIdentifier, sizeof(serialNumberAndAuthorityKeyIdentifier))) { - return 0; - } - - // dates - int year = (compressedCert.dates[0] >> 3) + 2000; - int month = ((compressedCert.dates[0] & 0x07) << 1) | (compressedCert.dates[1] >> 7); - int day = (compressedCert.dates[1] & 0x7c) >> 2; - int hour = ((compressedCert.dates[1] & 0x03) << 3) | (compressedCert.dates[2] >> 5); - int expireYears = (compressedCert.dates[2] & 0x1f); - - int datesSize = 30; - - if (year > 2049) { - // two more bytes for GeneralizedTime - datesSize += 2; - } - - if ((year + expireYears) > 2049) { - // two more bytes for GeneralizedTime - datesSize += 2; - } - - int serialNumberLen = serialNumberLength(serialNumberAndAuthorityKeyIdentifier.serialNumber); - - int issuerLen = issuerOrSubjectLength(_issuerCountryName, - _issuerStateProvinceName, - _issuerLocalityName, - _issuerOrganizationName, - _issuerOrganizationalUnitName, - _issuerCommonName); - - int issuerHeaderLen = sequenceHeaderLength(issuerLen); - - int subjectLen = issuerOrSubjectLength(_subjectCountryName, - _subjectStateProvinceName, - _subjectLocalityName, - _subjectOrganizationName, - _subjectOrganizationalUnitName, - _subjectCommonName); - - int subjectHeaderLen = sequenceHeaderLength(subjectLen); - - int publicKeyLen = publicKeyLength(); - - int authorityKeyIdentifierLen = authorityKeyIdentifierLength(serialNumberAndAuthorityKeyIdentifier.authorityKeyIdentifier); - - int signatureLen = signatureLength(compressedCert.signature); - - int certInfoLen = 5 + serialNumberLen + 12 + issuerHeaderLen + issuerLen + (datesSize + 2) + - subjectHeaderLen + subjectLen + publicKeyLen; - - if (authorityKeyIdentifierLen) { - certInfoLen += authorityKeyIdentifierLen; - } else { - certInfoLen += 4; - } - - int certInfoHeaderLen = sequenceHeaderLength(certInfoLen); - - int certDataLen = certInfoLen + certInfoHeaderLen + signatureLen; - int certDataHeaderLen = sequenceHeaderLength(certDataLen); - - _length = certDataLen + certDataHeaderLen; - _bytes = (byte*)realloc(_bytes, _length); - - if (!_bytes) { - _length = 0; - return 0; - } - - byte* out = _bytes; - - appendSequenceHeader(certDataLen, out); - out += certDataHeaderLen; - - appendSequenceHeader(certInfoLen, out); - out += certInfoHeaderLen; - - // version - *out++ = 0xA0; - *out++ = 0x03; - *out++ = 0x02; - *out++ = 0x01; - *out++ = 0x02; - - // serial number - appendSerialNumber(serialNumberAndAuthorityKeyIdentifier.serialNumber, out); - out += serialNumberLen; - - // ecdsaWithSHA256 - out += appendEcdsaWithSHA256(out); - - // issuer - appendSequenceHeader(issuerLen, out); - out += issuerHeaderLen; - appendIssuerOrSubject(_issuerCountryName, - _issuerStateProvinceName, - _issuerLocalityName, - _issuerOrganizationName, - _issuerOrganizationalUnitName, - _issuerCommonName, out); - out += issuerLen; - - *out++ = ASN1_SEQUENCE; - *out++ = datesSize; - out += appendDate(year, month, day, hour, 0, 0, out); - out += appendDate(year + expireYears, month, day, hour, 0, 0, out); - - // subject - appendSequenceHeader(subjectLen, out); - out += subjectHeaderLen; - appendIssuerOrSubject(_subjectCountryName, - _subjectStateProvinceName, - _subjectLocalityName, - _subjectOrganizationName, - _subjectOrganizationalUnitName, - _subjectCommonName, out); - out += subjectLen; - - // public key - appendPublicKey(publicKey, out); - out += publicKeyLen; - - if (authorityKeyIdentifierLen) { - appendAuthorityKeyIdentifier(serialNumberAndAuthorityKeyIdentifier.authorityKeyIdentifier, out); - out += authorityKeyIdentifierLen; - } else { - // null sequence - *out++ = 0xA3; - *out++ = 0x02; - *out++ = 0x30; - *out++ = 0x00; - } - - // signature - appendSignature(compressedCert.signature, out); - out += signatureLen; - - return 1; -} - -byte* ECCX08CertClass::bytes() { - return _bytes; -} - -int ECCX08CertClass::length() { - return _length; -} - -void ECCX08CertClass::setIssuerCountryName(const String& countryName) { - _issuerCountryName = countryName; -} - -void ECCX08CertClass::setIssuerStateProvinceName(const String& stateProvinceName) { - _issuerStateProvinceName = stateProvinceName; -} - -void ECCX08CertClass::setIssuerLocalityName(const String& localityName) { - _issuerLocalityName = localityName; -} - -void ECCX08CertClass::setIssuerOrganizationName(const String& organizationName) { - _issuerOrganizationName = organizationName; -} - -void ECCX08CertClass::setIssuerOrganizationalUnitName(const String& organizationalUnitName) { - _issuerOrganizationalUnitName = organizationalUnitName; -} - -void ECCX08CertClass::setIssuerCommonName(const String& commonName) { - _issuerCommonName = commonName; -} - -void ECCX08CertClass::setSubjectCountryName(const String& countryName) { - _subjectCountryName = countryName; -} - -void ECCX08CertClass::setSubjectStateProvinceName(const String& stateProvinceName) { - _subjectStateProvinceName = stateProvinceName; -} - -void ECCX08CertClass::setSubjectLocalityName(const String& localityName) { - _subjectLocalityName = localityName; -} - -void ECCX08CertClass::setSubjectOrganizationName(const String& organizationName) { - _subjectOrganizationName = organizationName; -} - -void ECCX08CertClass::setSubjectOrganizationalUnitName(const String& organizationalUnitName) { - _subjectOrganizationName = organizationalUnitName; -} - -void ECCX08CertClass::setSubjectCommonName(const String& commonName) { - _subjectCommonName = commonName; -} - -int ECCX08CertClass::versionLength() { - return 3; -} - -int ECCX08CertClass::issuerOrSubjectLength(const String& countryName, - const String& stateProvinceName, - const String& localityName, - const String& organizationName, - const String& organizationalUnitName, - const String& commonName) { - int length = 0; - int countryNameLength = countryName.length(); - int stateProvinceNameLength = stateProvinceName.length(); - int localityNameLength = localityName.length(); - int organizationNameLength = organizationName.length(); - int organizationalUnitNameLength = organizationalUnitName.length(); - int commonNameLength = commonName.length(); - - if (countryNameLength) { - length += (11 + countryNameLength); - } - - if (stateProvinceNameLength) { - length += (11 + stateProvinceNameLength); - } - - if (localityNameLength) { - length += (11 + localityNameLength); - } - - if (organizationNameLength) { - length += (11 + organizationNameLength); - } - - if (organizationalUnitNameLength) { - length += (11 + organizationalUnitNameLength); - } - - if (commonNameLength) { - length += (11 + commonNameLength); - } - - return length; -} - -int ECCX08CertClass::publicKeyLength() { - return (2 + 2 + 9 + 10 + 4 + 64); -} - -int ECCX08CertClass::authorityKeyIdentifierLength(const byte authorityKeyIdentifier[]) { - bool set = false; - - // check if the authority key identifier is non-zero - for (int i = 0; i < AUTHORITY_KEY_IDENTIFIER_LENGTH; i++) { - if (authorityKeyIdentifier[i] != 0) { - set = true; - break; - } - } - - return (set ? 37 : 0); -} - -int ECCX08CertClass::signatureLength(const byte signature[]) { - const byte* r = &signature[0]; - const byte* s = &signature[32]; - - int rLength = 32; - int sLength = 32; - - while (*r == 0x00 && rLength) { - r++; - rLength--; - } - - if (*r & 0x80) { - rLength++; - } - - while (*s == 0x00 && sLength) { - s++; - sLength--; - } - - if (*s & 0x80) { - sLength++; - } - - return (21 + rLength + sLength); -} - -int ECCX08CertClass::serialNumberLength(const byte serialNumber[]) { - int length = SERIAL_NUMBER_LENGTH; - - while (*serialNumber == 0 && length) { - serialNumber++; - length--; - } - - if (*serialNumber & 0x80) { - length++; - } - - return (2 + length); -} - -int ECCX08CertClass::sequenceHeaderLength(int length) { - if (length > 255) { - return 4; - } else if (length > 127) { - return 3; - } else { - return 2; - } -} - -void ECCX08CertClass::appendVersion(int version, byte out[]) { - out[0] = ASN1_INTEGER; - out[1] = 0x01; - out[2] = version; -} - -void ECCX08CertClass::appendIssuerOrSubject(const String& countryName, - const String& stateProvinceName, - const String& localityName, - const String& organizationName, - const String& organizationalUnitName, - const String& commonName, - byte out[]) { - if (countryName.length() > 0) { - out += appendName(countryName, 0x06, out); - } - - if (stateProvinceName.length() > 0) { - out += appendName(stateProvinceName, 0x08, out); - } - - if (localityName.length() > 0) { - out += appendName(localityName, 0x07, out); - } - - if (organizationName.length() > 0) { - out += appendName(organizationName, 0x0a, out); - } - - if (organizationalUnitName.length() > 0) { - out += appendName(organizationalUnitName, 0x0b, out); - } - - if (commonName.length() > 0) { - out += appendName(commonName, 0x03, out); - } -} - -void ECCX08CertClass::appendPublicKey(const byte publicKey[], byte out[]) { - int subjectPublicKeyDataLength = 2 + 9 + 10 + 4 + 64; - - // subject public key - *out++ = ASN1_SEQUENCE; - *out++ = (subjectPublicKeyDataLength) & 0xff; - - *out++ = ASN1_SEQUENCE; - *out++ = 0x13; - - // EC public key - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x07; - *out++ = 0x2a; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xce; - *out++ = 0x3d; - *out++ = 0x02; - *out++ = 0x01; - - // PRIME 256 v1 - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x08; - *out++ = 0x2a; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xce; - *out++ = 0x3d; - *out++ = 0x03; - *out++ = 0x01; - *out++ = 0x07; - - *out++ = 0x03; - *out++ = 0x42; - *out++ = 0x00; - *out++ = 0x04; - - memcpy(out, publicKey, 64); -} - -void ECCX08CertClass::appendAuthorityKeyIdentifier(const byte authorityKeyIdentifier[], byte out[]) { - // [3] - *out++ = 0xa3; - *out++ = 0x23; - - // sequence - *out++ = ASN1_SEQUENCE; - *out++ = 0x21; - - // sequence - *out++ = ASN1_SEQUENCE; - *out++ = 0x1f; - - // 2.5.29.35 authorityKeyIdentifier(X.509 extension) - *out++ = 0x06; - *out++ = 0x03; - *out++ = 0x55; - *out++ = 0x1d; - *out++ = 0x23; - - // octet string - *out++ = 0x04; - *out++ = 0x18; - - // sequence - *out++ = ASN1_SEQUENCE; - *out++ = 0x16; - - *out++ = 0x80; - *out++ = 0x14; - - memcpy(out, authorityKeyIdentifier, 20); -} - -void ECCX08CertClass::appendSignature(const byte signature[], byte out[]) { - // signature algorithm - *out++ = ASN1_SEQUENCE; - *out++ = 0x0a; - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x08; - - // ECDSA with SHA256 - *out++ = 0x2a; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xce; - *out++ = 0x3d; - *out++ = 0x04; - *out++ = 0x03; - *out++ = 0x02; - - const byte* r = &signature[0]; - const byte* s = &signature[32]; - - int rLength = 32; - int sLength = 32; - - while (*r == 0 && rLength) { - r++; - rLength--; - } - - while (*s == 0 && sLength) { - s++; - sLength--; - } - - if (*r & 0x80) { - rLength++; - } - - if (*s & 0x80) { - sLength++; - } - - *out++ = ASN1_BIT_STRING; - *out++ = (rLength + sLength + 7); - *out++ = 0; - - *out++ = ASN1_SEQUENCE; - *out++ = (rLength + sLength + 4); - - *out++ = ASN1_INTEGER; - *out++ = rLength; - if ((*r & 0x80) && rLength) { - *out++ = 0; - rLength--; - } - memcpy(out, r, rLength); - out += rLength; - - *out++ = ASN1_INTEGER; - *out++ = sLength; - if ((*s & 0x80) && sLength) { - *out++ = 0; - sLength--; - } - memcpy(out, s, sLength); - out += rLength; -} - -void ECCX08CertClass::appendSerialNumber(const byte serialNumber[], byte out[]) { - int length = SERIAL_NUMBER_LENGTH; - - while (*serialNumber == 0 && length) { - serialNumber++; - length--; - } - - if (*serialNumber & 0x80) { - length++; - } - - *out++ = ASN1_INTEGER; - *out++ = length; - - if (*serialNumber & 0x80) { - *out++ = 0x00; - length--; - } - - memcpy(out, serialNumber, length); -} - -int ECCX08CertClass::appendName(const String& name, int type, byte out[]) { - int nameLength = name.length(); - - *out++ = ASN1_SET; - *out++ = nameLength + 9; - - *out++ = ASN1_SEQUENCE; - *out++ = nameLength + 7; - - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x03; - *out++ = 0x55; - *out++ = 0x04; - *out++ = type; - - *out++ = ASN1_PRINTABLE_STRING; - *out++ = nameLength; - memcpy(out, name.c_str(), nameLength); - - return (nameLength + 11); -} - -void ECCX08CertClass::appendSequenceHeader(int length, byte out[]) { - *out++ = ASN1_SEQUENCE; - if (length > 255) { - *out++ = 0x82; - *out++ = (length >> 8) & 0xff; - } else if (length > 127) { - *out++ = 0x81; - } - *out++ = (length) & 0xff; -} - -int ECCX08CertClass::appendDate(int year, int month, int day, int hour, int minute, int second, byte out[]) { - bool useGeneralizedTime = (year > 2049); - - if (useGeneralizedTime) { - *out++ = 0x18; - *out++ = 0x0f; - *out++ = '0' + (year / 1000); - *out++ = '0' + ((year % 1000) / 100); - *out++ = '0' + ((year % 100) / 10); - *out++ = '0' + (year % 10); - } else { - year -= 2000; - - *out++ = 0x17; - *out++ = 0x0d; - *out++ = '0' + (year / 10); - *out++ = '0' + (year % 10); - } - *out++ = '0' + (month / 10); - *out++ = '0' + (month % 10); - *out++ = '0' + (day / 10); - *out++ = '0' + (day % 10); - *out++ = '0' + (hour / 10); - *out++ = '0' + (hour % 10); - *out++ = '0' + (minute / 10); - *out++ = '0' + (minute % 10); - *out++ = '0' + (second / 10); - *out++ = '0' + (second % 10); - *out++ = 0x5a; // UTC - - return (useGeneralizedTime ? 17 : 15); -} - -int ECCX08CertClass::appendEcdsaWithSHA256(byte out[]) { - *out++ = ASN1_SEQUENCE; - *out++ = 0x0A; - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x08; - *out++ = 0x2A; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xCE; - *out++ = 0x3D; - *out++ = 0x04; - *out++ = 0x03; - *out++ = 0x02; - - return 12; -} diff --git a/examples/utility/SelfProvisioning/ECCX08Cert.h b/examples/utility/SelfProvisioning/ECCX08Cert.h deleted file mode 100644 index d40d4cd02..000000000 --- a/examples/utility/SelfProvisioning/ECCX08Cert.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2019 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 _ECCX08_CERT_H_ -#define _ECCX08_CERT_H_ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class ECCX08CertClass { - - public: - ECCX08CertClass(); - virtual ~ECCX08CertClass(); - - int beginCSR(int keySlot, bool newPrivateKey = true); - String endCSR(); - - int beginStorage(int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot); - void setSignature(byte signature[]); - void setIssueYear(int issueYear); - void setIssueMonth(int issueMonth); - void setIssueDay(int issueDay); - void setIssueHour(int issueHour); - void setExpireYears(int expireYears); - void setSerialNumber(const byte serialNumber[]); - void setAuthorityKeyIdentifier(const byte authorityKeyIdentifier[]); - int endStorage(); - - int beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot); - int endReconstruction(); - - byte* bytes(); - int length(); - - void setIssuerCountryName(const String& countryName); - void setIssuerStateProvinceName(const String& stateProvinceName); - void setIssuerLocalityName(const String& localityName); - void setIssuerOrganizationName(const String& organizationName); - void setIssuerOrganizationalUnitName(const String& organizationalUnitName); - void setIssuerCommonName(const String& commonName); - - void setSubjectCountryName(const String& countryName); - void setSubjectStateProvinceName(const String& stateProvinceName); - void setSubjectLocalityName(const String& localityName); - void setSubjectOrganizationName(const String& organizationName); - void setSubjectOrganizationalUnitName(const String& organizationalUnitName); - void setSubjectCommonName(const String& commonName); - - private: - int versionLength(); - - int issuerOrSubjectLength(const String& countryName, - const String& stateProvinceName, - const String& localityName, - const String& organizationName, - const String& organizationalUnitName, - const String& commonName); - - int publicKeyLength(); - - int authorityKeyIdentifierLength(const byte authorityKeyIdentifier[]); - - int signatureLength(const byte signature[]); - - int serialNumberLength(const byte serialNumber[]); - - int sequenceHeaderLength(int length); - - void appendVersion(int version, byte out[]); - - void appendIssuerOrSubject(const String& countryName, - const String& stateProvinceName, - const String& localityName, - const String& organizationName, - const String& organizationalUnitName, - const String& commonName, - byte out[]); - - void appendPublicKey(const byte publicKey[], byte out[]); - - void appendAuthorityKeyIdentifier(const byte authorityKeyIdentifier[], byte out[]); - - void appendSignature(const byte signature[], byte out[]); - - void appendSerialNumber(const byte serialNumber[], byte out[]); - - int appendName(const String& name, int type, byte out[]); - - void appendSequenceHeader(int length, byte out[]); - - int appendDate(int year, int month, int day, int hour, int minute, int second, byte out[]); - - int appendEcdsaWithSHA256(byte out[]); - - private: - int _keySlot; - int _compressedCertSlot; - int _serialNumberAndAuthorityKeyIdentifierSlot; - - String _issuerCountryName; - String _issuerStateProvinceName; - String _issuerLocalityName; - String _issuerOrganizationName; - String _issuerOrganizationalUnitName; - String _issuerCommonName; - - String _subjectCountryName; - String _subjectStateProvinceName; - String _subjectLocalityName; - String _subjectOrganizationName; - String _subjectOrganizationalUnitName; - String _subjectCommonName; - - byte _temp[108]; - byte* _bytes; - int _length; -}; - -#endif /* _ECCX08_CERT_H_ */ diff --git a/examples/utility/SelfProvisioning/ECCX08TLSConfig.h b/examples/utility/SelfProvisioning/ECCX08TLSConfig.h deleted file mode 100644 index 9126b3666..000000000 --- a/examples/utility/SelfProvisioning/ECCX08TLSConfig.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2019 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 _ECCX08_TLS_CONFIG_H_ -#define _ECCX08_TLS_CONFIG_H_ - -const byte DEFAULT_ECCX08_TLS_CONFIG[128] = { - // Read only - start - // SN[0:3] - 0x01, 0x23, 0x00, 0x00, - // RevNum - 0x00, 0x00, 0x50, 0x00, - // SN[4:8] - 0x00, 0x00, 0x00, 0x00, 0x00, - // Reserved - 0xC0, - // I2C_Enable - 0x71, - // Reserved - 0x00, - // Read only - end - // I2C_Address - 0xC0, - // Reserved - 0x00, - // OTPmode - 0x55, - // ChipMode - 0x00, - // SlotConfig - 0x83, 0x20, // External Signatures | Internal Signatures | IsSecret | Write Configure Never, Default: 0x83, 0x20, - 0x87, 0x20, // External Signatures | Internal Signatures | ECDH | IsSecret | Write Configure Never, Default: 0x87, 0x20, - 0x87, 0x20, // External Signatures | Internal Signatures | ECDH | IsSecret | Write Configure Never, Default: 0x8F, 0x20, - 0x87, 0x2F, // External Signatures | Internal Signatures | ECDH | IsSecret | WriteKey all slots | Write Configure Never, Default: 0xC4, 0x8F, - 0x87, 0x2F, // External Signatures | Internal Signatures | ECDH | IsSecret | WriteKey all slots | Write Configure Never, Default: 0x8F, 0x8F, - 0x8F, 0x8F, - 0x9F, 0x8F, - 0xAF, 0x8F, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0xAF, 0x8F, - // Counter[0] - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - // Counter[1] - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - // LastKeyUse - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - // Write via commands only - start - // UserExtra - 0x00, - // Selector - 0x00, - // LockValue - 0x55, - // LockConfig - 0x55, - // SlotLocked - 0xFF, 0xFF, - // Write via commands only - end - // RFU - 0x00, 0x00, - // X509format - 0x00, 0x00, 0x00, 0x00, - // KeyConfig - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x33, 0x00, - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x33, 0x00, - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x33, 0x00, - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x1C, 0x00, - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x1C, 0x00, - 0x1C, 0x00, - 0x1C, 0x00, - 0x1C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x1C, 0x00 -}; - -#endif /* _ECCX08_TLS_CONFIG_H_ */ diff --git a/examples/utility/SelfProvisioning/SelfProvisioning.ino b/examples/utility/SelfProvisioning/SelfProvisioning.ino index a0c13724b..c7ab32edb 100644 --- a/examples/utility/SelfProvisioning/SelfProvisioning.ino +++ b/examples/utility/SelfProvisioning/SelfProvisioning.ino @@ -16,9 +16,10 @@ */ #include "arduino_secrets.h" -#include "ECCX08TLSConfig.h" -#include "ECCX08Cert.h" -#include +#include +#include +#include +#include #include #include @@ -29,10 +30,6 @@ #define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x0080A048) const bool DEBUG = true; -const int keySlot = 0; -const int compressedCertSlot = 10; -const int serialNumberAndAuthorityKeyIdentifierSlot = 11; -const int deviceIdSlot = 12; char ssid[] = SECRET_SSID; char pass[] = SECRET_PASS; @@ -67,7 +64,7 @@ char server[] = "api2.arduino.cc"; // server address WiFiSSLClient client; int status = WL_IDLE_STATUS; -ECCX08CertClass ECCX08Cert; +SecureElement secureElement; void setup() { Serial.begin(9600); @@ -94,31 +91,31 @@ void setup() { Serial.print("IP Address: "); Serial.println(ip); - while (!ECCX08.begin()) { - Serial.println("No ECCX08 present!"); + while (!secureElement.begin()) { + Serial.println("No secureElement present!"); delay(100); } - if (!ECCX08.locked()) { + if (!secureElement.locked()) { - if (!ECCX08.writeConfiguration(DEFAULT_ECCX08_TLS_CONFIG)) { - Serial.println("Writing ECCX08 configuration failed!"); + if (!secureElement.writeConfiguration()) { + Serial.println("Writing secureElement configuration failed!"); Serial.println("Stopping Provisioning"); while (1); } - if (!ECCX08.lock()) { - Serial.println("Locking ECCX08 configuration failed!"); + if (!secureElement.lock()) { + Serial.println("Locking secureElement configuration failed!"); Serial.println("Stopping Provisioning"); while (1); } - Serial.println("ECCX08 locked successfully"); + Serial.println("secureElement locked successfully"); Serial.println(); } //Random number for device name - board_name += String(ECCX08.random(65535)); + board_name += String(secureElement.random(65535)); uint32_t BoardUniqueID[4]; BoardUniqueID[0] = SERIAL_NUMBER_WORD_0; @@ -155,18 +152,26 @@ void setup() { delay(2000); - while (!ECCX08Cert.beginCSR(keySlot, true)) { + ECP256Certificate Certificate; + + while (!Certificate.begin()) { Serial.println("Error starting CSR generation!"); - delay(2000); + while (1); } - ECCX08Cert.setSubjectCommonName(deviceId); + Certificate.setSubjectCommonName(deviceId); + + if (!SElementCSR::build(secureElement, Certificate, static_cast(SElementArduinoCloudSlot::Key), true)) { + Serial.println("Error generating CSR!"); + while (1); + } - String csr = ECCX08Cert.endCSR(); + String csr = Certificate.getCSRPEM(); - while (!csr) { + if (!csr) { + /* WARNING: This string is parsed from IoTCloud frontend */ Serial.println("Error generating CSR!"); - delay(2000); + while (1); } Serial.println("Generated CSR is:"); @@ -206,42 +211,37 @@ void setup() { hexStringToBytes(authorityKeyIdentifier, authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); hexStringToBytes(signature, signatureBytes, sizeof(signatureBytes)); - if (!ECCX08.writeSlot(deviceIdSlot, deviceIdBytes, sizeof(deviceIdBytes))) { + if (!secureElement.writeSlot(static_cast(SElementArduinoCloudSlot::DeviceId), deviceIdBytes, sizeof(deviceIdBytes))) { Serial.println("Error storing device id!"); while (1); } - if (!ECCX08Cert.beginStorage(compressedCertSlot, serialNumberAndAuthorityKeyIdentifierSlot)) { - Serial.println("Error starting ECCX08 storage!"); + if (!Certificate.begin()) { + Serial.println("Error starting secureElement storage!"); while (1); } - ECCX08Cert.setSignature(signatureBytes); - ECCX08Cert.setAuthorityKeyIdentifier(authorityKeyIdentifierBytes); - ECCX08Cert.setSerialNumber(serialNumberBytes); - ECCX08Cert.setIssueYear(issueYear.toInt()); - ECCX08Cert.setIssueMonth(issueMonth.toInt()); - ECCX08Cert.setIssueDay(issueDay.toInt()); - ECCX08Cert.setIssueHour(issueHour.toInt()); - ECCX08Cert.setExpireYears(expireYears.toInt()); - - if (!ECCX08Cert.endStorage()) { - Serial.println("Error storing ECCX08 compressed cert!"); + Certificate.setSubjectCommonName(deviceId); + Certificate.setIssuerCountryName("US"); + Certificate.setIssuerOrganizationName("Arduino LLC US"); + Certificate.setIssuerOrganizationalUnitName("IT"); + Certificate.setIssuerCommonName("Arduino"); + Certificate.setSignature(signatureBytes, sizeof(signatureBytes)); + Certificate.setAuthorityKeyId(authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); + Certificate.setSerialNumber(serialNumberBytes, sizeof(serialNumberBytes)); + Certificate.setIssueYear(issueYear.toInt()); + Certificate.setIssueMonth(issueMonth.toInt()); + Certificate.setIssueDay(issueDay.toInt()); + Certificate.setIssueHour(issueHour.toInt()); + Certificate.setExpireYears(expireYears.toInt()); + + if (!SElementArduinoCloudCertificate::build(secureElement, Certificate, static_cast(SElementArduinoCloudSlot::Key))) { + Serial.println("Error building secureElement compressed cert!"); while (1); } - if (!ECCX08Cert.beginReconstruction(keySlot, compressedCertSlot, serialNumberAndAuthorityKeyIdentifierSlot)) { - Serial.println("Error starting ECCX08 cert reconstruction!"); - while (1); - } - - ECCX08Cert.setIssuerCountryName("US"); - ECCX08Cert.setIssuerOrganizationName("Arduino LLC US"); - ECCX08Cert.setIssuerOrganizationalUnitName("IT"); - ECCX08Cert.setIssuerCommonName("Arduino"); - - if (!ECCX08Cert.endReconstruction()) { - Serial.println("Error reconstructing ECCX08 compressed cert!"); + if (!SElementArduinoCloudCertificate::write(secureElement, Certificate, SElementArduinoCloudSlot::CompressedCertificate)) { + Serial.println("Error storing cert!"); while (1); } @@ -251,8 +251,8 @@ void setup() { Serial.println("Compressed cert = "); - const byte* certData = ECCX08Cert.bytes(); - int certLength = ECCX08Cert.length(); + const byte* certData = Certificate.bytes(); + int certLength = Certificate.length(); for (int i = 0; i < certLength; i++) { byte b = certData[i]; From 23f6545e0b070f0f82533edabfbcc368a837ee6f Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 12 Mar 2024 16:52:51 +0100 Subject: [PATCH 520/780] SelfProvisioning: reduce delay for WiFi connection --- examples/utility/SelfProvisioning/SelfProvisioning.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/utility/SelfProvisioning/SelfProvisioning.ino b/examples/utility/SelfProvisioning/SelfProvisioning.ino index c7ab32edb..3a2a9d46a 100644 --- a/examples/utility/SelfProvisioning/SelfProvisioning.ino +++ b/examples/utility/SelfProvisioning/SelfProvisioning.ino @@ -81,7 +81,7 @@ void setup() { // Connect to WPA/WPA2 network: status = WiFi.begin(ssid, pass); - delay(10000); + delay(3000); } Serial.print("SSID: "); From 9976166a9a1e5412695a9d0016296b746ab5d2ad Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 12 Mar 2024 16:54:06 +0100 Subject: [PATCH 521/780] SelfProvisioning: print error if certificate parsing fails --- .../SelfProvisioning/SelfProvisioning.ino | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/examples/utility/SelfProvisioning/SelfProvisioning.ino b/examples/utility/SelfProvisioning/SelfProvisioning.ino index 3a2a9d46a..a9dcf0955 100644 --- a/examples/utility/SelfProvisioning/SelfProvisioning.ino +++ b/examples/utility/SelfProvisioning/SelfProvisioning.ino @@ -466,19 +466,20 @@ void ArduinoCertificate(String user_token, String DeviceUuid, String csr) { JSONVar myObject = JSON.parse(certResponse); String certZip = JSON.stringify(myObject["compressed"]); JSONVar myCert = JSON.parse(certZip); - if (myCert.hasOwnProperty("not_before")) { + if (myCert.hasOwnProperty("not_before") && + myCert.hasOwnProperty("serial") && + myCert.hasOwnProperty("authority_key_identifier") && + myCert.hasOwnProperty("signature_asn1_x") && + myCert.hasOwnProperty("signature_asn1_x")) { not_before += (const char*) myCert["not_before"]; - } - if (myCert.hasOwnProperty("serial")) { serialNumber += (const char*) myCert["serial"]; - } - if (myCert.hasOwnProperty("authority_key_identifier")) { authorityKeyIdentifier += (const char*) myCert["authority_key_identifier"]; - } - if (myCert.hasOwnProperty("signature_asn1_x")) { signature += (const char*) myCert["signature_asn1_x"]; - } - if (myCert.hasOwnProperty("signature_asn1_y")) { signature += (const char*) myCert["signature_asn1_y"]; + } else { + Serial.println("Error parsing cloud certificate"); + while (1) { + ; + } } -} \ No newline at end of file +} From 7310e8a297902663262c1fe4114ea942c49f6ef8 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 12 Mar 2024 16:55:22 +0100 Subject: [PATCH 522/780] SelfProvisioning: fix certificate response parsing --- examples/utility/SelfProvisioning/SelfProvisioning.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/utility/SelfProvisioning/SelfProvisioning.ino b/examples/utility/SelfProvisioning/SelfProvisioning.ino index a9dcf0955..5167775b6 100644 --- a/examples/utility/SelfProvisioning/SelfProvisioning.ino +++ b/examples/utility/SelfProvisioning/SelfProvisioning.ino @@ -463,7 +463,8 @@ void ArduinoCertificate(String user_token, String DeviceUuid, String csr) { } intIndex++; } - JSONVar myObject = JSON.parse(certResponse); + char* p = strstr(certResponse, "{"); + JSONVar myObject = JSON.parse(p); String certZip = JSON.stringify(myObject["compressed"]); JSONVar myCert = JSON.parse(certZip); if (myCert.hasOwnProperty("not_before") && From 6ffb679586a00a4677f9f4515c2e4cabf86292ac Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 3 Apr 2024 10:29:09 +0200 Subject: [PATCH 523/780] Implement getUniqueSerialNumber as in mbed core --- .../SelfProvisioning/SelfProvisioning.ino | 71 +++++++++++-------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/examples/utility/SelfProvisioning/SelfProvisioning.ino b/examples/utility/SelfProvisioning/SelfProvisioning.ino index 5167775b6..49c091fd7 100644 --- a/examples/utility/SelfProvisioning/SelfProvisioning.ino +++ b/examples/utility/SelfProvisioning/SelfProvisioning.ino @@ -23,12 +23,6 @@ #include #include -// from section 10.3.3 of the SAMD datasheet -#define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x0080A00C) -#define SERIAL_NUMBER_WORD_1 *(volatile uint32_t*)(0x0080A040) -#define SERIAL_NUMBER_WORD_2 *(volatile uint32_t*)(0x0080A044) -#define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x0080A048) - const bool DEBUG = true; char ssid[] = SECRET_SSID; @@ -116,31 +110,12 @@ void setup() { //Random number for device name board_name += String(secureElement.random(65535)); - - uint32_t BoardUniqueID[4]; - BoardUniqueID[0] = SERIAL_NUMBER_WORD_0; - BoardUniqueID[1] = SERIAL_NUMBER_WORD_1; - BoardUniqueID[2] = SERIAL_NUMBER_WORD_2; - BoardUniqueID[3] = SERIAL_NUMBER_WORD_3; - uint8_t bid[32]; - for (int i = 0; i < 4; i++) - { - bid[i*4+0] = (uint8_t)(BoardUniqueID[i] >> 24); - bid[i*4+1] = (uint8_t)(BoardUniqueID[i] >> 16); - bid[i*4+2] = (uint8_t)(BoardUniqueID[i] >> 8); - bid[i*4+3] = (uint8_t)(BoardUniqueID[i] >> 0); - } - - for (size_t i = 0; i < 16; i++) { - if (bid[i] < 16) { - ArduinoID += String(0, HEX); - } - ArduinoID += String(bid[i], HEX); - } - ArduinoID.toUpperCase(); - Serial.print("Device Name: "); Serial.println(board_name); + //Board Serial Number + ArduinoID = ArduinoSerialNumber(); + Serial.print("SN: "); + Serial.println(ArduinoID); // Create Arduino Token ArduinoToken(client_id, secret_id); Serial.print("Bearer Token: "); @@ -314,6 +289,44 @@ void hexStringToBytes(String& in, byte out[], int length) { } } +#ifdef ARDUINO_ARCH_SAMD + +static void utox8(uint32_t val, uint8_t* s) { + for (int i = 0; i < 16; i=i+2) { + int d = val & 0XF; + val = (val >> 4); + + s[15 - i -1] = d > 9 ? 'A' + d - 10 : '0' + d; + s[15 - i] = '\0'; + } +} + +uint8_t getUniqueSerialNumber(uint8_t* name) { + utox8(*(volatile uint32_t*)(0x0080A00C), &name[0]); + utox8(*(volatile uint32_t*)(0x0080A040), &name[16]); + utox8(*(volatile uint32_t*)(0x0080A044), &name[32]); + utox8(*(volatile uint32_t*)(0x0080A048), &name[48]); + return 64; +} + +#endif + +String ArduinoSerialNumber() { + + uint8_t uniqueSerialNumber[64 + 1] = {0}; + char BoardUniqueID[32 + 1] = {0}; + + int uniqueSerialNumberLength = getUniqueSerialNumber(uniqueSerialNumber); + for(int i = 0, k = 0; i < uniqueSerialNumberLength; i = i+2, k++) { + BoardUniqueID[k] = uniqueSerialNumber[i]; + } + + String serialNumber = String(BoardUniqueID); + serialNumber.toUpperCase(); + return serialNumber; + +} + void ArduinoToken(String client_id, String client_secret) { Serial.println("Creating Bearer Token..."); String PostData = "grant_type=client_credentials&client_id="; From 91cba61ab33ed1ada333c2e57c2211c28d2e22cb Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 3 Apr 2024 15:27:39 +0200 Subject: [PATCH 524/780] Add API call to configure WiFi firmware version --- .../SelfProvisioning/SelfProvisioning.ino | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/examples/utility/SelfProvisioning/SelfProvisioning.ino b/examples/utility/SelfProvisioning/SelfProvisioning.ino index 49c091fd7..b10af1ca3 100644 --- a/examples/utility/SelfProvisioning/SelfProvisioning.ino +++ b/examples/utility/SelfProvisioning/SelfProvisioning.ino @@ -127,6 +127,12 @@ void setup() { delay(2000); + // Configure WiFi firmware version + String fv = WiFi.firmwareVersion(); + WiFiFirmwareVersion(fv, deviceId, Arduino_Token); + Serial.print("WiFi Firmware Version: "); + Serial.println(fv); + ECP256Certificate Certificate; while (!Certificate.begin()) { @@ -327,6 +333,28 @@ String ArduinoSerialNumber() { } +void WiFiFirmwareVersion(String fv, String deviceId, String token) { + Serial.println("Configuring WiFi firmware version..."); + String PostData = "{\"wifi_fw_version\":\""; + PostData += fv; + PostData += "\"}"; + + if (client.connect(server, 443)) { + client.print("POST /iot/v2/devices/"); + client.print(deviceId); + client.println(" HTTP/1.1"); + client.println("Host: api2.arduino.cc"); + client.println("Connection: close"); + client.println("Content-Type: application/json;charset=UTF-8"); + client.print("Authorization: Bearer "); + client.println(token); + client.print("Content-Length: "); + client.println(PostData.length()); + client.println(); + client.println(PostData); + } +} + void ArduinoToken(String client_id, String client_secret) { Serial.println("Creating Bearer Token..."); String PostData = "grant_type=client_credentials&client_id="; From acab564e4b7c08ffc7c7f71e06b0945c7d664640 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 3 Apr 2024 15:28:13 +0200 Subject: [PATCH 525/780] Add support for Nano RP2040 Connect --- examples/utility/SelfProvisioning/SelfProvisioning.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/utility/SelfProvisioning/SelfProvisioning.ino b/examples/utility/SelfProvisioning/SelfProvisioning.ino index b10af1ca3..8e21cf2e7 100644 --- a/examples/utility/SelfProvisioning/SelfProvisioning.ino +++ b/examples/utility/SelfProvisioning/SelfProvisioning.ino @@ -36,6 +36,9 @@ char secret_id[] = SECRET_SECRET_ID; #elif defined(ARDUINO_SAMD_MKRWIFI1010) char board_type[] = "mkrwifi1010"; // MKR WiFi 1010 char board_fqbn[] = "arduino:samd:mkrwifi1010"; // MKR WiFi 1010 +#elif defined(ARDUINO_NANO_RP2040_CONNECT) + char board_type[] = "nanorp2040connect"; // Nano RP2040 Connect + char board_fqbn[] = "arduino:mbed_nano:nanorp2040connect"; // Nano RP2040 Connect #else char board_type[] = "nonina"; // Not supported boards char board_fqbn[] = ""; From 7b90f4b598186813bb62359cf40a8665ef627c4f Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 5 Apr 2024 09:28:12 +0200 Subject: [PATCH 526/780] Add support for STM32H7 mbed boards --- .../SelfProvisioning/SelfProvisioning.ino | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/examples/utility/SelfProvisioning/SelfProvisioning.ino b/examples/utility/SelfProvisioning/SelfProvisioning.ino index 8e21cf2e7..61b30feb9 100644 --- a/examples/utility/SelfProvisioning/SelfProvisioning.ino +++ b/examples/utility/SelfProvisioning/SelfProvisioning.ino @@ -21,7 +21,6 @@ #include #include #include -#include const bool DEBUG = true; @@ -31,16 +30,35 @@ char client_id[] = SECRET_CLIENT_ID; char secret_id[] = SECRET_SECRET_ID; #if defined(ARDUINO_SAMD_NANO_33_IOT) + #include char board_type[] = "nano_33_iot"; // Nano 33 IoT char board_fqbn[] = "arduino:samd:nano_33_iot"; // Nano 33 IoT #elif defined(ARDUINO_SAMD_MKRWIFI1010) + #include char board_type[] = "mkrwifi1010"; // MKR WiFi 1010 char board_fqbn[] = "arduino:samd:mkrwifi1010"; // MKR WiFi 1010 #elif defined(ARDUINO_NANO_RP2040_CONNECT) + #include char board_type[] = "nanorp2040connect"; // Nano RP2040 Connect char board_fqbn[] = "arduino:mbed_nano:nanorp2040connect"; // Nano RP2040 Connect +#elif defined(ARDUINO_PORTENTA_H7_M7) + #include + char board_type[] = "envie_m7"; // Portenta H7 + char board_fqbn[] = "arduino:mbed_portenta:envie_m7"; // Portenta H7 +#elif defined(ARDUINO_NICLA_VISION) + #include + char board_type[] = "nicla_vision"; // Nicla Vision + char board_fqbn[] = "arduino:mbed_nicla:nicla_vision"; // Nicla Vision +#elif defined(ARDUINO_GIGA) + #include + char board_type[] = "giga"; // Giga R1 WiFi + char board_fqbn[] = "arduino:mbed_giga:giga"; // Giga R1 WiFi +#elif defined(ARDUINO_OPTA) + #include + char board_type[] = "opta"; // Opta + char board_fqbn[] = "arduino:mbed_opta:opta"; // Opta #else - char board_type[] = "nonina"; // Not supported boards + char board_type[] = "unsupported"; // Not supported boards char board_fqbn[] = ""; #endif @@ -67,7 +85,7 @@ void setup() { Serial.begin(9600); while (!Serial); - if (board_type == "nonina") { + if (board_type == "unsupported") { Serial.println("Sorry, this sketch only works on Nano 33 IoT and MKR 1010 WiFi"); while (1) { ; } } @@ -356,6 +374,7 @@ void WiFiFirmwareVersion(String fv, String deviceId, String token) { client.println(); client.println(PostData); } + client.stop(); } void ArduinoToken(String client_id, String client_secret) { @@ -398,12 +417,14 @@ void ArduinoToken(String client_id, String client_secret) { if (tokenResponse[intIndex] == -1) { break; } + delay(1); intIndex++; } JSONVar myObject = JSON.parse(tokenResponse); if (myObject.hasOwnProperty("access_token")) { Arduino_Token += (const char*) myObject["access_token"]; } + client.stop(); } void BoardUuid(String board_name, String board_type, String board_fqbn, String board_serial, String user_token) { @@ -432,7 +453,8 @@ void BoardUuid(String board_name, String board_type, String board_fqbn, String b } while (!client.available()) { - ; + Serial.println("No client"); + delay(2000); } char endOfHeaders[] = "\r\n\r\n"; @@ -451,12 +473,14 @@ void BoardUuid(String board_name, String board_type, String board_fqbn, String b if (deviceResponse[intIndex] == -1) { break; } + delay(1); intIndex++; } JSONVar myObject = JSON.parse(deviceResponse); if (myObject.hasOwnProperty("id")) { deviceId += (const char*) myObject["id"]; } + client.stop(); } void ArduinoCertificate(String user_token, String DeviceUuid, String csr) { @@ -505,6 +529,7 @@ void ArduinoCertificate(String user_token, String DeviceUuid, String csr) { if (certResponse[intIndex] == -1) { break; } + delay(1); intIndex++; } char* p = strstr(certResponse, "{"); From 3cb6e7366bce6bf8322e73a0c79a13a050bc71ec Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 5 Apr 2024 14:03:34 +0200 Subject: [PATCH 527/780] Add support for Renesas boards --- .../SelfProvisioning/SelfProvisioning.ino | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/examples/utility/SelfProvisioning/SelfProvisioning.ino b/examples/utility/SelfProvisioning/SelfProvisioning.ino index 61b30feb9..46bfcafef 100644 --- a/examples/utility/SelfProvisioning/SelfProvisioning.ino +++ b/examples/utility/SelfProvisioning/SelfProvisioning.ino @@ -57,6 +57,15 @@ char secret_id[] = SECRET_SECRET_ID; #include char board_type[] = "opta"; // Opta char board_fqbn[] = "arduino:mbed_opta:opta"; // Opta +#elif defined(ARDUINO_PORTENTA_C33) + #include + #include + char board_type[] = "portenta_c33"; // Portenta C33 + char board_fqbn[] = "arduino:renesas_portenta:portenta_c33"; // Portenta C33 +#elif defined(ARDUINO_UNOR4_WIFI) + #include + char board_type[] = "unor4wifi"; // UNO R4 WiFi + char board_fqbn[] = "arduino:renesas_uno:unor4wifi"; // UNO R4 WiFI #else char board_type[] = "unsupported"; // Not supported boards char board_fqbn[] = ""; @@ -316,7 +325,7 @@ void hexStringToBytes(String& in, byte out[], int length) { } } -#ifdef ARDUINO_ARCH_SAMD +#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_RENESAS) static void utox8(uint32_t val, uint8_t* s) { for (int i = 0; i < 16; i=i+2) { @@ -327,6 +336,9 @@ static void utox8(uint32_t val, uint8_t* s) { s[15 - i] = '\0'; } } +#endif + +#ifdef ARDUINO_ARCH_SAMD uint8_t getUniqueSerialNumber(uint8_t* name) { utox8(*(volatile uint32_t*)(0x0080A00C), &name[0]); @@ -338,6 +350,17 @@ uint8_t getUniqueSerialNumber(uint8_t* name) { #endif +#ifdef ARDUINO_ARCH_RENESAS +uint8_t getUniqueSerialNumber(uint8_t* name) { + const bsp_unique_id_t* t = R_BSP_UniqueIdGet(); + utox8(t->unique_id_words[0], &name[0]); + utox8(t->unique_id_words[1], &name[16]); + utox8(t->unique_id_words[2], &name[32]); + utox8(t->unique_id_words[3], &name[48]); + return 64; +} +#endif + String ArduinoSerialNumber() { uint8_t uniqueSerialNumber[64 + 1] = {0}; From 4cf7a3417dcf813d0423a5a45a6b5f114363d884 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 8 Apr 2024 17:12:04 +0200 Subject: [PATCH 528/780] Add writeOnDemand testcase --- extras/test/CMakeLists.txt | 1 + extras/test/src/test_writeOnDemand.cpp | 38 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 extras/test/src/test_writeOnDemand.cpp diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index 8e5148905..c330afd10 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -41,6 +41,7 @@ set(TEST_SRCS src/test_publishOnChangeRateLimit.cpp src/test_readOnly.cpp src/test_writeOnly.cpp + src/test_writeOnDemand.cpp ) set(TEST_UTIL_SRCS diff --git a/extras/test/src/test_writeOnDemand.cpp b/extras/test/src/test_writeOnDemand.cpp new file mode 100644 index 000000000..5bd0c3782 --- /dev/null +++ b/extras/test/src/test_writeOnDemand.cpp @@ -0,0 +1,38 @@ +/* + Copyright (c) 2019 Arduino. All rights reserved. +*/ + +/************************************************************************************** + INCLUDE + **************************************************************************************/ + +#include + +#include + +#include +#include + +/************************************************************************************** + TEST CODE + **************************************************************************************/ + +SCENARIO("An Arduino cloud property is marked 'write on demand'", "[ArduinoCloudThing::decode]") +{ + PropertyContainer property_container; + + CloudInt test = 0; + addPropertyToContainer(property_container, test, "test", Permission::ReadWrite).writeOnDemand(); + + /* [{0: "test", 2: 7}] = 81 A2 00 64 74 65 73 74 02 07 */ + uint8_t const payload[] = {0x81, 0xA2, 0x00, 0x64, 0x74, 0x65, 0x73, 0x74, 0x02, 0x07}; + int const payload_length = sizeof(payload) / sizeof(uint8_t); + CBORDecoder::decode(property_container, payload, payload_length); + + REQUIRE(test == 0); + + Property* p = getProperty(property_container, "test"); + p->fromCloudToLocal(); + + REQUIRE(test == 7); +} From 11e77ea8b9af8bbc8d1ad2c154167d5e7a12ffc0 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 9 Apr 2024 08:50:09 +0200 Subject: [PATCH 529/780] Add writeOnChange testcase --- extras/test/CMakeLists.txt | 1 + extras/test/src/test_writeOnChange.cpp | 33 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 extras/test/src/test_writeOnChange.cpp diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index c330afd10..2588c27c0 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -42,6 +42,7 @@ set(TEST_SRCS src/test_readOnly.cpp src/test_writeOnly.cpp src/test_writeOnDemand.cpp + src/test_writeOnChange.cpp ) set(TEST_UTIL_SRCS diff --git a/extras/test/src/test_writeOnChange.cpp b/extras/test/src/test_writeOnChange.cpp new file mode 100644 index 000000000..0896bbdfd --- /dev/null +++ b/extras/test/src/test_writeOnChange.cpp @@ -0,0 +1,33 @@ +/* + Copyright (c) 2019 Arduino. All rights reserved. +*/ + +/************************************************************************************** + INCLUDE + **************************************************************************************/ + +#include + +#include + +#include +#include + +/************************************************************************************** + TEST CODE + **************************************************************************************/ + +SCENARIO("An Arduino cloud property is marked 'write on change'", "[ArduinoCloudThing::decode]") +{ + PropertyContainer property_container; + + CloudInt test = 0; + addPropertyToContainer(property_container, test, "test", Permission::ReadWrite).writeOnChange(); + + /* [{0: "test", 2: 7}] = 81 A2 00 64 74 65 73 74 02 07 */ + uint8_t const payload[] = {0x81, 0xA2, 0x00, 0x64, 0x74, 0x65, 0x73, 0x74, 0x02, 0x07}; + int const payload_length = sizeof(payload) / sizeof(uint8_t); + CBORDecoder::decode(property_container, payload, payload_length); + + REQUIRE(test == 7); +} From b629c11e2d3bceb080c8101ca790759fe9d9dc4c Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 9 Apr 2024 14:49:59 +0200 Subject: [PATCH 530/780] ArduinoIoTCloudClass: Remove unused variable --- src/ArduinoIoTCloud.cpp | 1 - src/ArduinoIoTCloud.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index ce191eafd..84f08f780 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -34,7 +34,6 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() , _lib_version{AIOT_CONFIG_LIB_VERSION} , _device_id{""} , _cloud_event_callback{nullptr} -, _thing_id_outdated{false} { } diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 9fa9d2963..7436c0baf 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -162,7 +162,6 @@ class ArduinoIoTCloudClass String _device_id; OnCloudEventCallback _cloud_event_callback[3]; - bool _thing_id_outdated; }; #ifdef HAS_TCP From d8254d08500ed74625e257b7d7b60cf2f9401a08 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 3 Oct 2023 08:58:30 +0200 Subject: [PATCH 531/780] Add missing debug print --- src/ArduinoIoTCloudTCP.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 87b1c555e..5c89d2280 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -642,6 +642,7 @@ void ArduinoIoTCloudTCP::handle_OTARequest() { ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect() { DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); + DEBUG_INFO("Disconnected from Arduino IoT Cloud"); _mqttClient.stop(); execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); return State::ConnectPhy; From 16ad787993e43acc3f808d98fdfd4f9f7e6ea3d5 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 3 Oct 2023 17:50:32 +0200 Subject: [PATCH 532/780] Simplify Connect/Disconnect Attach/Detach logic --- src/ArduinoIoTCloudTCP.cpp | 40 +++++++++++++------------------------- src/ArduinoIoTCloudTCP.h | 2 -- 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 5c89d2280..0a19a3a89 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -87,7 +87,6 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _shadowTopicIn("") , _dataTopicOut("") , _dataTopicIn("") -, _deviceSubscribedToThing{false} #if OTA_ENABLED , _ota_cap{false} , _ota_error{static_cast(OTAError::None)} @@ -376,16 +375,13 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() if (!_mqttClient.subscribe(_deviceTopicIn)) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _deviceTopicIn.c_str()); - return State::SubscribeDeviceTopic; } if (_last_device_subscribe_cnt > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) { _last_device_subscribe_cnt = 0; _next_device_subscribe_attempt_tick = 0; - _mqttClient.stop(); - execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - return State::ConnectPhy; + return State::Disconnect; } /* No device configuration reply. Wait: 5s -> 10s -> 20s -> 30s */ @@ -428,16 +424,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() return State::Disconnect; } - if(_deviceSubscribedToThing == true) - { - /* Unsubscribe from old things topics and go on with a new subscription */ - _mqttClient.unsubscribe(_shadowTopicIn); - _mqttClient.unsubscribe(_dataTopicIn); - _deviceSubscribedToThing = false; - DEBUG_INFO("Disconnected from Arduino IoT Cloud"); - execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - } - updateThingTopics(); if (_thing_id.length() == 0) @@ -465,7 +451,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() if (_thing_id_property->isDifferentFromCloud()) { - return State::CheckDeviceConfig; + return State::Disconnect; } unsigned long const now = millis(); @@ -481,9 +467,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() { _last_subscribe_request_cnt = 0; _last_subscribe_request_tick = 0; - _mqttClient.stop(); - execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - return State::ConnectPhy; + return State::Disconnect; } _last_subscribe_request_tick = now; @@ -506,7 +490,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() DEBUG_INFO("Connected to Arduino IoT Cloud"); DEBUG_INFO("Thing ID: %s", getThingId().c_str()); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); - _deviceSubscribedToThing = true; /*Add retry wait time otherwise we are trying to reconnect every 250 ms...*/ return State::RequestLastValues; @@ -521,7 +504,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() if (_thing_id_property->isDifferentFromCloud()) { - return State::CheckDeviceConfig; + return State::Disconnect; } /* Check whether or not we need to send a new request. */ @@ -542,9 +525,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() { _last_sync_request_cnt = 0; _last_sync_request_tick = 0; - _mqttClient.stop(); - execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - return State::ConnectPhy; + return State::Disconnect; } } @@ -564,7 +545,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() { if (_thing_id_property->isDifferentFromCloud()) { - return State::CheckDeviceConfig; + return State::Disconnect; } /* Check if a primitive property wrapper is locally changed. @@ -641,9 +622,14 @@ void ArduinoIoTCloudTCP::handle_OTARequest() { ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect() { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); + if (!_mqttClient.connected()) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); + } else { + _mqttClient.unsubscribe(_shadowTopicIn); + _mqttClient.unsubscribe(_dataTopicIn); + _mqttClient.stop(); + } DEBUG_INFO("Disconnected from Arduino IoT Cloud"); - _mqttClient.stop(); execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); return State::ConnectPhy; } diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index d00bb0ca6..0be0bfcf0 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -179,8 +179,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass String _dataTopicOut; String _dataTopicIn; - bool _deviceSubscribedToThing; - #if OTA_ENABLED bool _ota_cap; int _ota_error; From 68e3d97202e8c22931adf1b8f3b66f5cec2f076c Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 4 Oct 2023 15:09:51 +0200 Subject: [PATCH 533/780] Simplify Attach/Detach timeout logic --- src/AIoTC_Config.h | 3 ++- src/ArduinoIoTCloudTCP.cpp | 32 ++++++++++++++++---------------- src/ArduinoIoTCloudTCP.h | 1 - 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index e47a8ac2b..b9301934f 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -139,10 +139,11 @@ #define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) #define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) -#define AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (5*1000UL) +#define AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (2000UL) #define AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (32000UL) #define AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_RETRY_DELAY_ms (1000UL) #define AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_MAX_RETRY_CNT (10UL) +#define AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (20000UL) #define AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (1280000UL) #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 0a19a3a89..d18b34e09 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -362,7 +362,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SendDeviceProperties() } sendDevicePropertiesToCloud(); - return State::SubscribeDeviceTopic; + return State::WaitDeviceConfig; } ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() @@ -384,11 +384,10 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() return State::Disconnect; } - /* No device configuration reply. Wait: 5s -> 10s -> 20s -> 30s */ + _last_device_subscribe_cnt++; unsigned long subscribe_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms; subscribe_retry_delay = min(subscribe_retry_delay, static_cast(AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms)); _next_device_subscribe_attempt_tick = millis() + subscribe_retry_delay; - _last_device_subscribe_cnt++; return State::WaitDeviceConfig; } @@ -400,20 +399,19 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() return State::Disconnect; } - if (_thing_id_property->isDifferentFromCloud()) - { - return State::CheckDeviceConfig; - } - - if (millis() > _next_device_subscribe_attempt_tick) + bool const is_retry_attempt = (_last_device_subscribe_cnt > 0); + if (is_retry_attempt && (millis() > _next_device_subscribe_attempt_tick)) { /* Configuration not received or device not attached to a valid thing. Try to resubscribe */ if (_mqttClient.unsubscribe(_deviceTopicIn)) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s device waiting for valid thing_id", __FUNCTION__); - return State::SubscribeDeviceTopic; } } + + if (!is_retry_attempt || (is_retry_attempt && (millis() > _next_device_subscribe_attempt_tick))) + return State::SubscribeDeviceTopic; + return State::WaitDeviceConfig; } @@ -428,16 +426,19 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() if (_thing_id.length() == 0) { - /* Configuration received but device not attached. Wait: 40s */ - unsigned long attach_retry_delay = (1 << _last_device_attach_cnt) * AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms; + /* Device configuration received, but invalid thing_id. Do not increase counter, but recompute delay. + * Device not attached. Wait: 40s -> 80s -> 160s -> 320s -> 640s -> 1280s -> 1280s ... + */ + unsigned long attach_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms; attach_retry_delay = min(attach_retry_delay, static_cast(AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms)); _next_device_subscribe_attempt_tick = millis() + attach_retry_delay; - _last_device_attach_cnt++; return State::WaitDeviceConfig; } DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s Device attached to a new valid Thing %s", __FUNCTION__, getThingId().c_str()); - _last_device_attach_cnt = 0; + + /* Received valid thing_id reset counters and go on */ + _last_device_subscribe_cnt = 0; return State::SubscribeThingTopics; } @@ -652,8 +653,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) /* Topic for OTA properties and device configuration */ if (_deviceTopicIn == topic) { CBORDecoder::decode(_device_property_container, (uint8_t*)bytes, length); - _last_device_subscribe_cnt = 0; - _next_device_subscribe_attempt_tick = 0; + _state = State::CheckDeviceConfig; } /* Topic for user input data */ diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 0be0bfcf0..cbe9e6fcc 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -132,7 +132,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass unsigned int _last_connection_attempt_cnt; unsigned long _next_device_subscribe_attempt_tick; unsigned int _last_device_subscribe_cnt; - unsigned int _last_device_attach_cnt; unsigned long _last_sync_request_tick; unsigned int _last_sync_request_cnt; unsigned long _last_subscribe_request_tick; From baf69e4581454d3c3f4941097d0e049caf951fdf Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 4 Oct 2023 15:11:31 +0200 Subject: [PATCH 534/780] Add comments and DEBUG --- src/ArduinoIoTCloudTCP.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index d18b34e09..07d25af3c 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -344,13 +344,15 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() return State::SendDeviceProperties; } + /* Can't connect to the broker. Wait: 2s -> 4s -> 8s -> 16s -> 32s -> 32s ... */ _last_connection_attempt_cnt++; unsigned long reconnection_retry_delay = (1 << _last_connection_attempt_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms; reconnection_retry_delay = min(reconnection_retry_delay, static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms)); _next_connection_attempt_tick = millis() + reconnection_retry_delay; DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); - DEBUG_ERROR("ArduinoIoTCloudTCP::%s %d connection attempt at tick time %d", __FUNCTION__, _last_connection_attempt_cnt, _next_connection_attempt_tick); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s %d next connection attempt in %d ms", __FUNCTION__, _last_connection_attempt_cnt, reconnection_retry_delay); + /* Go back to ConnectPhy and retry to get time from network (invalid time for SSL handshake?)*/ return State::ConnectPhy; } @@ -361,6 +363,8 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SendDeviceProperties() return State::Disconnect; } + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s announce device to the Cloud %d", __FUNCTION__, _time_service.getTime()); + /* TODO check if write fails */ sendDevicePropertiesToCloud(); return State::WaitDeviceConfig; } @@ -372,11 +376,17 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() return State::Disconnect; } + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s request device configuration %d", __FUNCTION__, _time_service.getTime()); + if (!_mqttClient.subscribe(_deviceTopicIn)) { + /* If device_id is wrong the board can't connect to the broker so this condition + * should never happen. + */ DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _deviceTopicIn.c_str()); } + /* Max retry than disconnect */ if (_last_device_subscribe_cnt > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) { _last_device_subscribe_cnt = 0; @@ -384,10 +394,12 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() return State::Disconnect; } + /* No device configuration received. Wait: 4s -> 8s -> 16s -> 32s -> 32s ...*/ _last_device_subscribe_cnt++; unsigned long subscribe_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms; subscribe_retry_delay = min(subscribe_retry_delay, static_cast(AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms)); _next_device_subscribe_attempt_tick = millis() + subscribe_retry_delay; + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s %d next configuration request in %d ms", __FUNCTION__, _last_device_subscribe_cnt, subscribe_retry_delay); return State::WaitDeviceConfig; } @@ -405,7 +417,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() /* Configuration not received or device not attached to a valid thing. Try to resubscribe */ if (_mqttClient.unsubscribe(_deviceTopicIn)) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s device waiting for valid thing_id", __FUNCTION__); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s device waiting for valid thing_id %d", __FUNCTION__, _time_service.getTime()); } } @@ -432,10 +444,12 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() unsigned long attach_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms; attach_retry_delay = min(attach_retry_delay, static_cast(AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms)); _next_device_subscribe_attempt_tick = millis() + attach_retry_delay; + + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s device not attached, next configuration request in %d ms", __FUNCTION__, attach_retry_delay); return State::WaitDeviceConfig; } - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s Device attached to a new valid Thing %s", __FUNCTION__, getThingId().c_str()); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s device attached to a new valid thing_id %s %d", __FUNCTION__, getThingId().c_str(), _time_service.getTime()); /* Received valid thing_id reset counters and go on */ _last_device_subscribe_cnt = 0; From 5c9db23034f7748605016084ba2d1e52f8d375e6 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 5 Oct 2023 09:04:41 +0200 Subject: [PATCH 535/780] Reorder functions implementation --- src/ArduinoIoTCloudTCP.cpp | 46 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 07d25af3c..cf416ff9d 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -369,6 +369,29 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SendDeviceProperties() return State::WaitDeviceConfig; } +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() +{ + if (!_mqttClient.connected()) + { + return State::Disconnect; + } + + bool const is_retry_attempt = (_last_device_subscribe_cnt > 0); + if (is_retry_attempt && (millis() > _next_device_subscribe_attempt_tick)) + { + /* Configuration not received or device not attached to a valid thing. Try to resubscribe */ + if (_mqttClient.unsubscribe(_deviceTopicIn)) + { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s device waiting for valid thing_id %d", __FUNCTION__, _time_service.getTime()); + } + } + + if (!is_retry_attempt || (is_retry_attempt && (millis() > _next_device_subscribe_attempt_tick))) + return State::SubscribeDeviceTopic; + + return State::WaitDeviceConfig; +} + ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() { if (!_mqttClient.connected()) @@ -404,29 +427,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() return State::WaitDeviceConfig; } -ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() -{ - if (!_mqttClient.connected()) - { - return State::Disconnect; - } - - bool const is_retry_attempt = (_last_device_subscribe_cnt > 0); - if (is_retry_attempt && (millis() > _next_device_subscribe_attempt_tick)) - { - /* Configuration not received or device not attached to a valid thing. Try to resubscribe */ - if (_mqttClient.unsubscribe(_deviceTopicIn)) - { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s device waiting for valid thing_id %d", __FUNCTION__, _time_service.getTime()); - } - } - - if (!is_retry_attempt || (is_retry_attempt && (millis() > _next_device_subscribe_attempt_tick))) - return State::SubscribeDeviceTopic; - - return State::WaitDeviceConfig; -} - ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() { if (!_mqttClient.connected()) From 3aeb4abdfce0b0f3ebbd7955b7c9a038fe5b42f8 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 5 Oct 2023 11:13:50 +0200 Subject: [PATCH 536/780] Unify naming and logic of thing susbscribe retry --- src/ArduinoIoTCloudTCP.cpp | 24 ++++++++---------------- src/ArduinoIoTCloudTCP.h | 4 ++-- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index cf416ff9d..c5e35905d 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -69,8 +69,8 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _last_device_subscribe_cnt{0} , _last_sync_request_tick{0} , _last_sync_request_cnt{0} -, _last_subscribe_request_tick{0} -, _last_subscribe_request_cnt{0} +, _next_thing_subscribe_attempt_tick{0} +, _last_thing_subscribe_attempt_cnt{0} , _mqtt_data_buf{0} , _mqtt_data_len{0} , _mqtt_data_request_retransmit{false} @@ -413,7 +413,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() if (_last_device_subscribe_cnt > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) { _last_device_subscribe_cnt = 0; - _next_device_subscribe_attempt_tick = 0; return State::Disconnect; } @@ -469,24 +468,18 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() return State::Disconnect; } - unsigned long const now = millis(); - bool const is_subscribe_retry_delay_expired = (now - _last_subscribe_request_tick) > AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_RETRY_DELAY_ms; - bool const is_first_subscribe_request = (_last_subscribe_request_cnt == 0); - - if (!is_first_subscribe_request && !is_subscribe_retry_delay_expired) - { + bool const is_retry_attempt = (_last_thing_subscribe_attempt_cnt > 0); + if (is_retry_attempt && (millis() < _next_thing_subscribe_attempt_tick)) return State::SubscribeThingTopics; - } - if (_last_subscribe_request_cnt > AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_MAX_RETRY_CNT) + if (_last_thing_subscribe_attempt_cnt > AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_MAX_RETRY_CNT) { - _last_subscribe_request_cnt = 0; - _last_subscribe_request_tick = 0; + _last_thing_subscribe_attempt_cnt = 0; return State::Disconnect; } - _last_subscribe_request_tick = now; - _last_subscribe_request_cnt++; + _next_thing_subscribe_attempt_tick = millis() + AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_RETRY_DELAY_ms; + _last_thing_subscribe_attempt_cnt++; if (!_mqttClient.subscribe(_dataTopicIn)) { @@ -506,7 +499,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() DEBUG_INFO("Thing ID: %s", getThingId().c_str()); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); - /*Add retry wait time otherwise we are trying to reconnect every 250 ms...*/ return State::RequestLastValues; } diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index cbe9e6fcc..88efca3f7 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -134,8 +134,8 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass unsigned int _last_device_subscribe_cnt; unsigned long _last_sync_request_tick; unsigned int _last_sync_request_cnt; - unsigned long _last_subscribe_request_tick; - unsigned int _last_subscribe_request_cnt; + unsigned long _next_thing_subscribe_attempt_tick; + unsigned int _last_thing_subscribe_attempt_cnt; String _brokerAddress; uint16_t _brokerPort; uint8_t _mqtt_data_buf[MQTT_TRANSMIT_BUFFER_SIZE]; From 0c21a29c7e3b4df2d8bff9db76eacdec798ccda2 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 6 Oct 2023 14:01:05 +0200 Subject: [PATCH 537/780] Reorder timeout variables declaration and initialization --- src/ArduinoIoTCloudTCP.cpp | 4 ++-- src/ArduinoIoTCloudTCP.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index c5e35905d..d2e8672be 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -67,10 +67,10 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _last_connection_attempt_cnt{0} , _next_device_subscribe_attempt_tick{0} , _last_device_subscribe_cnt{0} -, _last_sync_request_tick{0} -, _last_sync_request_cnt{0} , _next_thing_subscribe_attempt_tick{0} , _last_thing_subscribe_attempt_cnt{0} +, _last_sync_request_tick{0} +, _last_sync_request_cnt{0} , _mqtt_data_buf{0} , _mqtt_data_len{0} , _mqtt_data_request_retransmit{false} diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 88efca3f7..26a1b2ead 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -132,10 +132,10 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass unsigned int _last_connection_attempt_cnt; unsigned long _next_device_subscribe_attempt_tick; unsigned int _last_device_subscribe_cnt; - unsigned long _last_sync_request_tick; - unsigned int _last_sync_request_cnt; unsigned long _next_thing_subscribe_attempt_tick; unsigned int _last_thing_subscribe_attempt_cnt; + unsigned long _last_sync_request_tick; + unsigned int _last_sync_request_cnt; String _brokerAddress; uint16_t _brokerPort; uint8_t _mqtt_data_buf[MQTT_TRANSMIT_BUFFER_SIZE]; From 8d84dcd9657b877a6b3b3a2af638d7929345b4b4 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 6 Oct 2023 15:49:49 +0200 Subject: [PATCH 538/780] Unify naming and logic of last values request retry --- src/ArduinoIoTCloudTCP.cpp | 33 +++++++++++++++------------------ src/ArduinoIoTCloudTCP.h | 4 ++-- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index d2e8672be..409e7754f 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -69,8 +69,8 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _last_device_subscribe_cnt{0} , _next_thing_subscribe_attempt_tick{0} , _last_thing_subscribe_attempt_cnt{0} -, _last_sync_request_tick{0} -, _last_sync_request_cnt{0} +, _next_sync_attempt_tick{0} +, _last_sync_attempt_cnt{0} , _mqtt_data_buf{0} , _mqtt_data_len{0} , _mqtt_data_request_retransmit{false} @@ -515,27 +515,25 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() } /* Check whether or not we need to send a new request. */ - unsigned long const now = millis(); - bool const is_sync_request_timeout = (now - _last_sync_request_tick) > AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms; - bool const is_first_sync_request = (_last_sync_request_cnt == 0); - if (is_first_sync_request || is_sync_request_timeout) + bool const is_retry_attempt = (_last_sync_attempt_cnt > 0); + if (is_retry_attempt && (millis() < _next_sync_attempt_tick)) + return State::RequestLastValues; + + if (_last_sync_attempt_cnt > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) { - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, now); - requestLastValue(); - _last_sync_request_tick = now; /* Track the number of times a get-last-values request was sent to the cloud. * If no data is received within a certain number of retry-requests it's a better * strategy to disconnect and re-establish connection from the ground up. */ - _last_sync_request_cnt++; - if (_last_sync_request_cnt > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) - { - _last_sync_request_cnt = 0; - _last_sync_request_tick = 0; - return State::Disconnect; - } + _last_sync_attempt_cnt = 0; + return State::Disconnect; } + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, _time_service.getTime()); + requestLastValue(); + _next_sync_attempt_tick = millis() + AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms; + _last_sync_attempt_cnt++; + return State::RequestLastValues; } @@ -674,8 +672,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) CBORDecoder::decode(_thing_property_container, (uint8_t*)bytes, length, true); _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); - _last_sync_request_cnt = 0; - _last_sync_request_tick = 0; + _last_sync_attempt_cnt = 0; _state = State::Connected; } } diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 26a1b2ead..a200f5060 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -134,8 +134,8 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass unsigned int _last_device_subscribe_cnt; unsigned long _next_thing_subscribe_attempt_tick; unsigned int _last_thing_subscribe_attempt_cnt; - unsigned long _last_sync_request_tick; - unsigned int _last_sync_request_cnt; + unsigned long _next_sync_attempt_tick; + unsigned int _last_sync_attempt_cnt; String _brokerAddress; uint16_t _brokerPort; uint8_t _mqtt_data_buf[MQTT_TRANSMIT_BUFFER_SIZE]; From ca26344addc33bb558949ef949f2097186e8d44b Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 6 Oct 2023 17:00:17 +0200 Subject: [PATCH 539/780] Remove WaitDeviceConfig state --- src/ArduinoIoTCloudTCP.cpp | 28 +++++++++------------------- src/ArduinoIoTCloudTCP.h | 2 -- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 409e7754f..bb2e6705e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -270,7 +270,6 @@ void ArduinoIoTCloudTCP::update() case State::ConnectMqttBroker: next_state = handle_ConnectMqttBroker(); break; case State::SendDeviceProperties: next_state = handle_SendDeviceProperties(); break; case State::SubscribeDeviceTopic: next_state = handle_SubscribeDeviceTopic(); break; - case State::WaitDeviceConfig: next_state = handle_WaitDeviceConfig(); break; case State::CheckDeviceConfig: next_state = handle_CheckDeviceConfig(); break; case State::SubscribeThingTopics: next_state = handle_SubscribeThingTopics(); break; case State::RequestLastValues: next_state = handle_RequestLastValues(); break; @@ -366,10 +365,10 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SendDeviceProperties() DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s announce device to the Cloud %d", __FUNCTION__, _time_service.getTime()); /* TODO check if write fails */ sendDevicePropertiesToCloud(); - return State::WaitDeviceConfig; + return State::SubscribeDeviceTopic; } -ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() { if (!_mqttClient.connected()) { @@ -377,7 +376,10 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() } bool const is_retry_attempt = (_last_device_subscribe_cnt > 0); - if (is_retry_attempt && (millis() > _next_device_subscribe_attempt_tick)) + if (is_retry_attempt && (millis() < _next_device_subscribe_attempt_tick)) + return State::SubscribeDeviceTopic; + + if (is_retry_attempt) { /* Configuration not received or device not attached to a valid thing. Try to resubscribe */ if (_mqttClient.unsubscribe(_deviceTopicIn)) @@ -386,19 +388,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_WaitDeviceConfig() } } - if (!is_retry_attempt || (is_retry_attempt && (millis() > _next_device_subscribe_attempt_tick))) - return State::SubscribeDeviceTopic; - - return State::WaitDeviceConfig; -} - -ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() -{ - if (!_mqttClient.connected()) - { - return State::Disconnect; - } - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s request device configuration %d", __FUNCTION__, _time_service.getTime()); if (!_mqttClient.subscribe(_deviceTopicIn)) @@ -423,7 +412,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() _next_device_subscribe_attempt_tick = millis() + subscribe_retry_delay; DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s %d next configuration request in %d ms", __FUNCTION__, _last_device_subscribe_cnt, subscribe_retry_delay); - return State::WaitDeviceConfig; + return State::SubscribeDeviceTopic; } ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() @@ -445,7 +434,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() _next_device_subscribe_attempt_tick = millis() + attach_retry_delay; DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s device not attached, next configuration request in %d ms", __FUNCTION__, attach_retry_delay); - return State::WaitDeviceConfig; + return State::SubscribeDeviceTopic; } DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s device attached to a new valid thing_id %s %d", __FUNCTION__, getThingId().c_str(), _time_service.getTime()); @@ -657,6 +646,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) /* Topic for OTA properties and device configuration */ if (_deviceTopicIn == topic) { CBORDecoder::decode(_device_property_container, (uint8_t*)bytes, length); + _last_device_subscribe_cnt = 0; _state = State::CheckDeviceConfig; } diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index a200f5060..5815c86bf 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -113,7 +113,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass ConnectMqttBroker, SendDeviceProperties, SubscribeDeviceTopic, - WaitDeviceConfig, CheckDeviceConfig, SubscribeThingTopics, RequestLastValues, @@ -199,7 +198,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass State handle_SyncTime(); State handle_ConnectMqttBroker(); State handle_SendDeviceProperties(); - State handle_WaitDeviceConfig(); State handle_CheckDeviceConfig(); State handle_SubscribeDeviceTopic(); State handle_SubscribeThingTopics(); From 30dde27aff88ec55c7a0f0b5935b9ec5417793b1 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 6 Oct 2023 17:08:26 +0200 Subject: [PATCH 540/780] We can safely send another subscribe request without unsubscribe --- src/ArduinoIoTCloudTCP.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index bb2e6705e..e1ec6564f 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -382,10 +382,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() if (is_retry_attempt) { /* Configuration not received or device not attached to a valid thing. Try to resubscribe */ - if (_mqttClient.unsubscribe(_deviceTopicIn)) - { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s device waiting for valid thing_id %d", __FUNCTION__, _time_service.getTime()); - } + DEBUG_ERROR("ArduinoIoTCloudTCP::%s device waiting for valid thing_id %d", __FUNCTION__, _time_service.getTime()); } DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s request device configuration %d", __FUNCTION__, _time_service.getTime()); From 03e87ba69060897192d23c0746a79fd64caeaa5f Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 6 Oct 2023 17:10:04 +0200 Subject: [PATCH 541/780] Merge disconnect conditions --- src/ArduinoIoTCloudTCP.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e1ec6564f..a18485b25 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -444,12 +444,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() { - if (!_mqttClient.connected()) - { - return State::Disconnect; - } - - if (_thing_id_property->isDifferentFromCloud()) + if (!_mqttClient.connected() || _thing_id_property->isDifferentFromCloud()) { return State::Disconnect; } @@ -490,12 +485,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() { - if (!_mqttClient.connected()) - { - return State::Disconnect; - } - - if (_thing_id_property->isDifferentFromCloud()) + if (!_mqttClient.connected() || _thing_id_property->isDifferentFromCloud()) { return State::Disconnect; } From a7f05599c7075133ae6bcf76d2f353b90afbda47 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 9 Oct 2023 10:12:51 +0200 Subject: [PATCH 542/780] Reorder timeout and retry defines --- src/AIoTC_Config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index b9301934f..063f1af9b 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -141,10 +141,10 @@ #define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) #define AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (2000UL) #define AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (32000UL) -#define AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_RETRY_DELAY_ms (1000UL) -#define AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_MAX_RETRY_CNT (10UL) #define AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (20000UL) #define AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (1280000UL) +#define AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_RETRY_DELAY_ms (1000UL) +#define AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_MAX_RETRY_CNT (10UL) #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) From c9d808b7a0fb1321b014dc762abc5f85ef5d06b2 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 9 Oct 2023 10:14:10 +0200 Subject: [PATCH 543/780] Add specific define for max number of retry connecting to device topic --- src/AIoTC_Config.h | 1 + src/ArduinoIoTCloudTCP.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 063f1af9b..f4fbd2a6a 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -141,6 +141,7 @@ #define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) #define AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (2000UL) #define AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (32000UL) +#define AIOT_CONFIG_DEVICE_TOPIC_MAX_RETRY_CNT (10UL) #define AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (20000UL) #define AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (1280000UL) #define AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_RETRY_DELAY_ms (1000UL) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index a18485b25..d70dcfe88 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -396,7 +396,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() } /* Max retry than disconnect */ - if (_last_device_subscribe_cnt > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) + if (_last_device_subscribe_cnt > AIOT_CONFIG_DEVICE_TOPIC_MAX_RETRY_CNT) { _last_device_subscribe_cnt = 0; return State::Disconnect; From 5d9f39d6780e973423955a346328c8b6f859d01e Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 9 Oct 2023 15:13:55 +0200 Subject: [PATCH 544/780] Add Class to handle retries and state transitions --- src/ArduinoIoTCloudTCP.cpp | 103 ++++++++++++++---------------- src/ArduinoIoTCloudTCP.h | 10 +-- src/utility/time/TimedAttempt.cpp | 75 ++++++++++++++++++++++ src/utility/time/TimedAttempt.h | 40 ++++++++++++ 4 files changed, 166 insertions(+), 62 deletions(-) create mode 100644 src/utility/time/TimedAttempt.cpp create mode 100644 src/utility/time/TimedAttempt.h diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index d70dcfe88..2fe03df53 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -59,18 +59,11 @@ unsigned long getTime() ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() : _state{State::ConnectPhy} +, _connection_attempt(0,0) , _tz_offset{0} , _tz_offset_property{nullptr} , _tz_dst_until{0} , _tz_dst_until_property{nullptr} -, _next_connection_attempt_tick{0} -, _last_connection_attempt_cnt{0} -, _next_device_subscribe_attempt_tick{0} -, _last_device_subscribe_cnt{0} -, _next_thing_subscribe_attempt_tick{0} -, _last_thing_subscribe_attempt_cnt{0} -, _next_sync_attempt_tick{0} -, _last_sync_attempt_cnt{0} , _mqtt_data_buf{0} , _mqtt_data_len{0} , _mqtt_data_request_retransmit{false} @@ -113,7 +106,12 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_ #else _brokerPort = brokerPort; #endif + + /* Setup TimeService */ _time_service.begin(&connection); + + /* Setup retry timers */ + _connection_attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms); return begin(enable_watchdog, _brokerAddress, _brokerPort); } @@ -132,15 +130,16 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, if(!_password.length()) { #endif + #if defined(BOARD_HAS_SECURE_ELEMENT) if (!_selement.begin()) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not initialize secure element.", __FUNCTION__); -#if defined(ARDUINO_UNOWIFIR4) + #if defined(ARDUINO_UNOWIFIR4) if (String(WiFi.firmwareVersion()) < String("0.4.1")) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to read device certificate, WiFi firmware needs to be >= 0.4.1, current %s", __FUNCTION__, WiFi.firmwareVersion()); } -#endif + #endif return 0; } if (!SElementArduinoCloudDeviceId::read(_selement, getDeviceId(), SElementArduinoCloudSlot::DeviceId)) @@ -317,8 +316,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() { if (_connection->check() == NetworkConnectionState::CONNECTED) { - bool const is_retry_attempt = (_last_connection_attempt_cnt > 0); - if (!is_retry_attempt || (is_retry_attempt && (millis() > _next_connection_attempt_tick))) + if (!_connection_attempt.isRetry() || (_connection_attempt.isRetry() && _connection_attempt.isExpired())) return State::SyncTime; } @@ -339,18 +337,20 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() { if (_mqttClient.connect(_brokerAddress.c_str(), _brokerPort)) { - _last_connection_attempt_cnt = 0; + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s connected to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); + /* Reconfigure timers for next state */ + _connection_attempt.begin(AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms, AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms); return State::SendDeviceProperties; } /* Can't connect to the broker. Wait: 2s -> 4s -> 8s -> 16s -> 32s -> 32s ... */ - _last_connection_attempt_cnt++; - unsigned long reconnection_retry_delay = (1 << _last_connection_attempt_cnt) * AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms; - reconnection_retry_delay = min(reconnection_retry_delay, static_cast(AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms)); - _next_connection_attempt_tick = millis() + reconnection_retry_delay; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" + unsigned long const reconnection_retry_delay = _connection_attempt.retry(); +#pragma GCC diagnostic pop DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s %d next connection attempt in %d ms", __FUNCTION__, _last_connection_attempt_cnt, reconnection_retry_delay); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s %d next connection attempt in %d ms", __FUNCTION__, _connection_attempt.getRetryCount(), reconnection_retry_delay); /* Go back to ConnectPhy and retry to get time from network (invalid time for SSL handshake?)*/ return State::ConnectPhy; } @@ -375,11 +375,10 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() return State::Disconnect; } - bool const is_retry_attempt = (_last_device_subscribe_cnt > 0); - if (is_retry_attempt && (millis() < _next_device_subscribe_attempt_tick)) + if (_connection_attempt.isRetry() && !_connection_attempt.isExpired()) return State::SubscribeDeviceTopic; - if (is_retry_attempt) + if (_connection_attempt.isRetry()) { /* Configuration not received or device not attached to a valid thing. Try to resubscribe */ DEBUG_ERROR("ArduinoIoTCloudTCP::%s device waiting for valid thing_id %d", __FUNCTION__, _time_service.getTime()); @@ -396,18 +395,17 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() } /* Max retry than disconnect */ - if (_last_device_subscribe_cnt > AIOT_CONFIG_DEVICE_TOPIC_MAX_RETRY_CNT) + if (_connection_attempt.getRetryCount() > AIOT_CONFIG_DEVICE_TOPIC_MAX_RETRY_CNT) { - _last_device_subscribe_cnt = 0; return State::Disconnect; } /* No device configuration received. Wait: 4s -> 8s -> 16s -> 32s -> 32s ...*/ - _last_device_subscribe_cnt++; - unsigned long subscribe_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms; - subscribe_retry_delay = min(subscribe_retry_delay, static_cast(AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms)); - _next_device_subscribe_attempt_tick = millis() + subscribe_retry_delay; - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s %d next configuration request in %d ms", __FUNCTION__, _last_device_subscribe_cnt, subscribe_retry_delay); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" + unsigned long const subscribe_retry_delay = _connection_attempt.retry(); +#pragma GCC diagnostic pop + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s %d next configuration request in %d ms", __FUNCTION__, _connection_attempt.getRetryCount(), subscribe_retry_delay); return State::SubscribeDeviceTopic; } @@ -426,18 +424,18 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() /* Device configuration received, but invalid thing_id. Do not increase counter, but recompute delay. * Device not attached. Wait: 40s -> 80s -> 160s -> 320s -> 640s -> 1280s -> 1280s ... */ - unsigned long attach_retry_delay = (1 << _last_device_subscribe_cnt) * AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms; - attach_retry_delay = min(attach_retry_delay, static_cast(AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms)); - _next_device_subscribe_attempt_tick = millis() + attach_retry_delay; - +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" + unsigned long const attach_retry_delay = _connection_attempt.reconfigure(AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms, AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms); +#pragma GCC diagnostic pop DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s device not attached, next configuration request in %d ms", __FUNCTION__, attach_retry_delay); return State::SubscribeDeviceTopic; } DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s device attached to a new valid thing_id %s %d", __FUNCTION__, getThingId().c_str(), _time_service.getTime()); - /* Received valid thing_id reset counters and go on */ - _last_device_subscribe_cnt = 0; + /* Received valid thing_id, reconfigure timers for next state and go on */ + _connection_attempt.begin(AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_RETRY_DELAY_ms); return State::SubscribeThingTopics; } @@ -449,18 +447,15 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() return State::Disconnect; } - bool const is_retry_attempt = (_last_thing_subscribe_attempt_cnt > 0); - if (is_retry_attempt && (millis() < _next_thing_subscribe_attempt_tick)) + if (_connection_attempt.isRetry() && !_connection_attempt.isExpired()) return State::SubscribeThingTopics; - if (_last_thing_subscribe_attempt_cnt > AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_MAX_RETRY_CNT) + if (_connection_attempt.getRetryCount() > AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_MAX_RETRY_CNT) { - _last_thing_subscribe_attempt_cnt = 0; return State::Disconnect; } - _next_thing_subscribe_attempt_tick = millis() + AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_RETRY_DELAY_ms; - _last_thing_subscribe_attempt_cnt++; + _connection_attempt.retry(); if (!_mqttClient.subscribe(_dataTopicIn)) { @@ -480,6 +475,8 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() DEBUG_INFO("Thing ID: %s", getThingId().c_str()); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); + /* Successfully subscribed to thing topics, reconfigure timers for next state and go on */ + _connection_attempt.begin(AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms); return State::RequestLastValues; } @@ -491,25 +488,21 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() } /* Check whether or not we need to send a new request. */ - bool const is_retry_attempt = (_last_sync_attempt_cnt > 0); - if (is_retry_attempt && (millis() < _next_sync_attempt_tick)) + if (_connection_attempt.isRetry() && !_connection_attempt.isExpired()) return State::RequestLastValues; - if (_last_sync_attempt_cnt > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) + /* Track the number of times a get-last-values request was sent to the cloud. + * If no data is received within a certain number of retry-requests it's a better + * strategy to disconnect and re-establish connection from the ground up. + */ + if (_connection_attempt.getRetryCount() > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) { - /* Track the number of times a get-last-values request was sent to the cloud. - * If no data is received within a certain number of retry-requests it's a better - * strategy to disconnect and re-establish connection from the ground up. - */ - _last_sync_attempt_cnt = 0; return State::Disconnect; } - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, _time_service.getTime()); + _connection_attempt.retry(); requestLastValue(); - _next_sync_attempt_tick = millis() + AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms; - _last_sync_attempt_cnt++; - + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, _time_service.getTime()); return State::RequestLastValues; } @@ -608,10 +601,14 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect() } else { _mqttClient.unsubscribe(_shadowTopicIn); _mqttClient.unsubscribe(_dataTopicIn); + /* TODO add device topic */ _mqttClient.stop(); } DEBUG_INFO("Disconnected from Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + + /* Setup timer for broker connection and restart */ + _connection_attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms); return State::ConnectPhy; } @@ -633,7 +630,6 @@ void ArduinoIoTCloudTCP::handleMessage(int length) /* Topic for OTA properties and device configuration */ if (_deviceTopicIn == topic) { CBORDecoder::decode(_device_property_container, (uint8_t*)bytes, length); - _last_device_subscribe_cnt = 0; _state = State::CheckDeviceConfig; } @@ -649,7 +645,6 @@ void ArduinoIoTCloudTCP::handleMessage(int length) CBORDecoder::decode(_thing_property_container, (uint8_t*)bytes, length, true); _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); - _last_sync_attempt_cnt = 0; _state = State::Connected; } } diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 5815c86bf..9b5ffa6c0 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -25,6 +25,7 @@ #include #include #include +#include #if defined(BOARD_HAS_SECURE_ELEMENT) #include @@ -121,20 +122,13 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass }; State _state; + TimedAttempt _connection_attempt; int _tz_offset; Property * _tz_offset_property; unsigned int _tz_dst_until; Property * _tz_dst_until_property; - unsigned long _next_connection_attempt_tick; - unsigned int _last_connection_attempt_cnt; - unsigned long _next_device_subscribe_attempt_tick; - unsigned int _last_device_subscribe_cnt; - unsigned long _next_thing_subscribe_attempt_tick; - unsigned int _last_thing_subscribe_attempt_cnt; - unsigned long _next_sync_attempt_tick; - unsigned int _last_sync_attempt_cnt; String _brokerAddress; uint16_t _brokerPort; uint8_t _mqtt_data_buf[MQTT_TRANSMIT_BUFFER_SIZE]; diff --git a/src/utility/time/TimedAttempt.cpp b/src/utility/time/TimedAttempt.cpp new file mode 100644 index 000000000..97e39a833 --- /dev/null +++ b/src/utility/time/TimedAttempt.cpp @@ -0,0 +1,75 @@ +/* + This file is part of the Arduino_SecureElement library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include +#include "TimedAttempt.h" + +/****************************************************************************** + * CTOR/DTOR + ******************************************************************************/ + +TimedAttempt::TimedAttempt(unsigned long minDelay, unsigned long maxDelay) +: _minDelay(minDelay) +, _maxDelay(maxDelay) { +} + +/****************************************************************************** + * PUBLIC MEMBER FUNCTIONS + ******************************************************************************/ + +void TimedAttempt::begin(unsigned long delay) { + _retryCount = 0; + _minDelay = delay; + _maxDelay = delay; +} + +void TimedAttempt::begin(unsigned long minDelay, unsigned long maxDelay) { + _retryCount = 0; + _minDelay = minDelay; + _maxDelay = maxDelay; +} + +unsigned long TimedAttempt::reconfigure(unsigned long minDelay, unsigned long maxDelay) { + _minDelay = minDelay; + _maxDelay = maxDelay; + return reload(); +} + +unsigned long TimedAttempt::retry() { + _retryCount++; + return reload(); +} + +unsigned long TimedAttempt::reload() { + unsigned long retryDelay = (1 << _retryCount) * _minDelay; + retryDelay = min(retryDelay, _maxDelay); + _nextRetryTick = millis() + retryDelay; + return retryDelay; +} + +void TimedAttempt::reset() { + _retryCount = 0; +} + +bool TimedAttempt::isRetry() { + return _retryCount > 0; +} + +bool TimedAttempt::isExpired() { + return millis() > _nextRetryTick; +} + +unsigned int TimedAttempt::getRetryCount() { + return _retryCount; +} diff --git a/src/utility/time/TimedAttempt.h b/src/utility/time/TimedAttempt.h new file mode 100644 index 000000000..68cad47cf --- /dev/null +++ b/src/utility/time/TimedAttempt.h @@ -0,0 +1,40 @@ +/* + This file is part of the Arduino_SecureElement library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#ifndef TIMED_ATTEMPT_H +#define TIMED_ATTEMPT_H + +/****************************************************************************** + * CLASS DECLARATION + ******************************************************************************/ + +class TimedAttempt { + +public: + TimedAttempt(unsigned long minDelay, unsigned long maxDelay); + + void begin(unsigned long delay); + void begin(unsigned long minDelay, unsigned long maxDelay); + unsigned long reconfigure(unsigned long minDelay, unsigned long maxDelay); + unsigned long retry(); + unsigned long reload(); + void reset(); + bool isRetry(); + bool isExpired(); + unsigned int getRetryCount(); + +private: + unsigned long _minDelay; + unsigned long _maxDelay; + unsigned long _nextRetryTick; + unsigned int _retryCount; +}; + +#endif /* TIMED_ATTEMPT_H */ From 2f12cb9c802cff07fbbfdd1c4215a1d7ef76b0d8 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 14 Mar 2024 13:33:19 +0100 Subject: [PATCH 545/780] TimedAttempt: add variable to store next attempt wait time --- src/utility/time/TimedAttempt.cpp | 2 +- src/utility/time/TimedAttempt.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utility/time/TimedAttempt.cpp b/src/utility/time/TimedAttempt.cpp index 97e39a833..b3b63df56 100644 --- a/src/utility/time/TimedAttempt.cpp +++ b/src/utility/time/TimedAttempt.cpp @@ -53,7 +53,7 @@ unsigned long TimedAttempt::retry() { unsigned long TimedAttempt::reload() { unsigned long retryDelay = (1 << _retryCount) * _minDelay; - retryDelay = min(retryDelay, _maxDelay); + _retryDelay = min(retryDelay, _maxDelay); _nextRetryTick = millis() + retryDelay; return retryDelay; } diff --git a/src/utility/time/TimedAttempt.h b/src/utility/time/TimedAttempt.h index 68cad47cf..aed030a7f 100644 --- a/src/utility/time/TimedAttempt.h +++ b/src/utility/time/TimedAttempt.h @@ -34,6 +34,7 @@ class TimedAttempt { unsigned long _minDelay; unsigned long _maxDelay; unsigned long _nextRetryTick; + unsigned long _retryDelay; unsigned int _retryCount; }; From a7c28d7f4ee25da23f1dda9eab50e35606a63c22 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 14 Mar 2024 13:34:12 +0100 Subject: [PATCH 546/780] TimedAttempt: add getWaitTime() --- src/utility/time/TimedAttempt.cpp | 4 ++++ src/utility/time/TimedAttempt.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/utility/time/TimedAttempt.cpp b/src/utility/time/TimedAttempt.cpp index b3b63df56..01da506d7 100644 --- a/src/utility/time/TimedAttempt.cpp +++ b/src/utility/time/TimedAttempt.cpp @@ -73,3 +73,7 @@ bool TimedAttempt::isExpired() { unsigned int TimedAttempt::getRetryCount() { return _retryCount; } + +unsigned int TimedAttempt::getWaitTime() { + return _retryDelay; +} diff --git a/src/utility/time/TimedAttempt.h b/src/utility/time/TimedAttempt.h index aed030a7f..67a1931c0 100644 --- a/src/utility/time/TimedAttempt.h +++ b/src/utility/time/TimedAttempt.h @@ -29,6 +29,7 @@ class TimedAttempt { bool isRetry(); bool isExpired(); unsigned int getRetryCount(); + unsigned int getWaitTime(); private: unsigned long _minDelay; From 51710f377d2d49cc6d269aeafd1a0655449d3a29 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 14 Mar 2024 13:37:02 +0100 Subject: [PATCH 547/780] ArduinoIoTCloudTCP: use getWaitTime() for broker connection retry --- src/ArduinoIoTCloudTCP.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 2fe03df53..794be824c 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -344,13 +344,10 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() } /* Can't connect to the broker. Wait: 2s -> 4s -> 8s -> 16s -> 32s -> 32s ... */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" - unsigned long const reconnection_retry_delay = _connection_attempt.retry(); -#pragma GCC diagnostic pop + _connection_attempt.retry(); DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s %d next connection attempt in %d ms", __FUNCTION__, _connection_attempt.getRetryCount(), reconnection_retry_delay); + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s %d next connection attempt in %d ms", __FUNCTION__, _connection_attempt.getRetryCount(), _connection_attempt.getWaitTime()); /* Go back to ConnectPhy and retry to get time from network (invalid time for SSL handshake?)*/ return State::ConnectPhy; } From 0eb2b5a6afa24deb0a27a29363924fd7e9452517 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 22 Apr 2024 16:59:31 +0200 Subject: [PATCH 548/780] Examples: Avoid SECRET_PASS redefinition on Portenta H7 --- examples/ArduinoIoTCloud-Advanced/arduino_secrets.h | 4 ++-- examples/ArduinoIoTCloud-Advanced/thingProperties.h | 2 +- examples/ArduinoIoTCloud-Basic/arduino_secrets.h | 4 ++-- examples/ArduinoIoTCloud-Basic/thingProperties.h | 2 +- examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h | 4 ++-- examples/ArduinoIoTCloud-Callbacks/thingProperties.h | 2 +- examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h | 4 ++-- examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h | 2 +- examples/ArduinoIoTCloud-Schedule/arduino_secrets.h | 4 ++-- examples/ArduinoIoTCloud-Schedule/thingProperties.h | 2 +- examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h | 4 ++-- examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h | 2 +- 12 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h index 7e5face72..44a9e21d2 100644 --- a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h @@ -4,8 +4,8 @@ * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ #if defined(BOARD_HAS_WIFI) - #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" - #define SECRET_PASS "YOUR_WIFI_PASSWORD" + #define SECRET_WIFI_SSID "YOUR_WIFI_NETWORK_NAME" + #define SECRET_WIFI_PASS "YOUR_WIFI_PASSWORD" #endif /* ESP8266 ESP32 */ diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index 8d8269307..43187104d 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -35,7 +35,7 @@ void initProperties() { } #if defined(BOARD_HAS_WIFI) - WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_PASS); + WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_WIFI_SSID, SECRET_WIFI_PASS); #elif defined(BOARD_HAS_GSM) GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_LORA) diff --git a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h index 7e5face72..44a9e21d2 100644 --- a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h @@ -4,8 +4,8 @@ * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ #if defined(BOARD_HAS_WIFI) - #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" - #define SECRET_PASS "YOUR_WIFI_PASSWORD" + #define SECRET_WIFI_SSID "YOUR_WIFI_NETWORK_NAME" + #define SECRET_WIFI_PASS "YOUR_WIFI_PASSWORD" #endif /* ESP8266 ESP32 */ diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index 2792236e2..4193b440b 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -39,7 +39,7 @@ void initProperties() { /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_OPTIONAL_IP, SECRET_OPTIONAL_DNS, SECRET_OPTIONAL_GATEWAY, SECRET_OPTIONAL_NETMASK); #elif defined(BOARD_HAS_WIFI) - WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_PASS); + WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_WIFI_SSID, SECRET_WIFI_PASS); #elif defined(BOARD_HAS_GSM) GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_LORA) diff --git a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h index 7e5face72..44a9e21d2 100644 --- a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h @@ -4,8 +4,8 @@ * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ #if defined(BOARD_HAS_WIFI) - #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" - #define SECRET_PASS "YOUR_WIFI_PASSWORD" + #define SECRET_WIFI_SSID "YOUR_WIFI_NETWORK_NAME" + #define SECRET_WIFI_PASS "YOUR_WIFI_PASSWORD" #endif /* ESP8266 ESP32 */ diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index daed69097..8f2b5055e 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -19,7 +19,7 @@ void initProperties() { } #if defined(BOARD_HAS_WIFI) - WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_PASS); + WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_WIFI_SSID, SECRET_WIFI_PASS); #elif defined(BOARD_HAS_GSM) GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_LORA) diff --git a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h index 177e1770b..e784c4413 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/arduino_secrets.h @@ -4,8 +4,8 @@ * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ #if defined(BOARD_HAS_WIFI) - #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" - #define SECRET_PASS "YOUR_WIFI_PASSWORD" + #define SECRET_WIFI_SSID "YOUR_WIFI_NETWORK_NAME" + #define SECRET_WIFI_PASS "YOUR_WIFI_PASSWORD" #endif /* ESP8266 ESP32 */ diff --git a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h index 1aa4b1be3..cb89dabac 100644 --- a/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h +++ b/examples/ArduinoIoTCloud-DeferredOTA/thingProperties.h @@ -24,7 +24,7 @@ void initProperties() { } #if defined(BOARD_HAS_WIFI) - WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_PASS); + WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_WIFI_SSID, SECRET_WIFI_PASS); #elif defined(BOARD_HAS_ETHERNET) /* DHCP mode */ //EthernetConnectionHandler ArduinoIoTPreferredConnection; diff --git a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h index 7e5face72..44a9e21d2 100644 --- a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h @@ -4,8 +4,8 @@ * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ #if defined(BOARD_HAS_WIFI) - #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" - #define SECRET_PASS "YOUR_WIFI_PASSWORD" + #define SECRET_WIFI_SSID "YOUR_WIFI_NETWORK_NAME" + #define SECRET_WIFI_PASS "YOUR_WIFI_PASSWORD" #endif /* ESP8266 ESP32 */ diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index b6c3abb05..8d2d7dfc6 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -42,7 +42,7 @@ void initProperties() { } #if defined(BOARD_HAS_WIFI) - WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_PASS); + WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_WIFI_SSID, SECRET_WIFI_PASS); #elif defined(BOARD_HAS_GSM) GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_LORA) diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h index 2f6069225..2ae0cefa6 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h @@ -4,8 +4,8 @@ * https://github.com/arduino-libraries/ArduinoIoTCloud/#what */ #if defined(BOARD_HAS_WIFI) - #define SECRET_SSID "YOUR_WIFI_NETWORK_NAME" - #define SECRET_PASS "YOUR_WIFI_PASSWORD" + #define SECRET_WIFI_SSID "YOUR_WIFI_NETWORK_NAME" + #define SECRET_WIFI_PASS "YOUR_WIFI_PASSWORD" #endif /* ESP8266 ESP32*/ diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index 55b83771d..36604ebf7 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -55,7 +55,7 @@ String str_property_7; String str_property_8; #if defined(BOARD_HAS_WIFI) - WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_PASS); + WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_WIFI_SSID, SECRET_WIFI_PASS); #elif defined(BOARD_HAS_GSM) GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_LORA) From 4540401f46c37f9eb8b583ee5e106a27a6916ced Mon Sep 17 00:00:00 2001 From: "Zachary J. Fields" Date: Mon, 19 Feb 2024 07:54:29 -0600 Subject: [PATCH 549/780] chore: Switch LPWAN off deprecated method --- src/ArduinoIoTCloudLPWAN.cpp | 2 +- src/property/PropertyContainer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 0f96d36db..d6a062a7a 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -61,7 +61,7 @@ ArduinoIoTCloudLPWAN::ArduinoIoTCloudLPWAN() int ArduinoIoTCloudLPWAN::connected() { - return (_connection->getStatus() == NetworkConnectionState::CONNECTED) ? 1 : 0; + return (_connection->check() == NetworkConnectionState::CONNECTED) ? 1 : 0; } int ArduinoIoTCloudLPWAN::begin(ConnectionHandler& connection, bool retry) diff --git a/src/property/PropertyContainer.cpp b/src/property/PropertyContainer.cpp index 833250f02..3ab4e75e0 100644 --- a/src/property/PropertyContainer.cpp +++ b/src/property/PropertyContainer.cpp @@ -95,7 +95,7 @@ void requestUpdateForAllProperties(PropertyContainer & prop_cont) void updateTimestampOnLocallyChangedProperties(PropertyContainer & prop_cont) { - /* This function updates the timestamps on the primitive properties + /* This function updates the timestamps on the primitive properties * that have been modified locally since last cloud synchronization */ std::for_each(prop_cont.begin(), From 8d7c71616391ec05535389c11ca58134028b41e7 Mon Sep 17 00:00:00 2001 From: "Zachary J. Fields" Date: Mon, 19 Feb 2024 16:17:26 -0600 Subject: [PATCH 550/780] chore: increase LoRa retry interval --- src/ArduinoIoTCloudLPWAN.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index d6a062a7a..9a3d4ae18 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -50,7 +50,7 @@ ArduinoIoTCloudLPWAN::ArduinoIoTCloudLPWAN() : _state{State::ConnectPhy} , _retryEnable{false} , _maxNumRetry{5} -, _intervalRetry{1000} +, _intervalRetry{10000} { } @@ -105,8 +105,7 @@ ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_ConnectPhy() ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_SyncTime() { - unsigned long const internal_posix_time = _time_service.getTime(); - DEBUG_VERBOSE("ArduinoIoTCloudLPWAN::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); + DEBUG_VERBOSE("ArduinoIoTCloudLPWAN::%s internal clock configured to posix timestamp %lu", __FUNCTION__, _time_service.getTime()); DEBUG_INFO("Connected to Arduino IoT Cloud"); return State::Connected; } From 73fd2874f18c50486a8fd4f6c929f473c5ad5c21 Mon Sep 17 00:00:00 2001 From: "Zachary J. Fields" Date: Tue, 27 Feb 2024 12:42:38 -0600 Subject: [PATCH 551/780] chore: Address PR feedback --- src/AIoTC_Config.h | 1 + src/ArduinoIoTCloudLPWAN.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index e47a8ac2b..7828191f0 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -137,6 +137,7 @@ * CONSTANTS ******************************************************************************/ +#define AIOT_CONFIG_INTERVAL_RETRY_DELAY_ms (10000UL) #define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) #define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) #define AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (5*1000UL) diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 9a3d4ae18..e3f625fb7 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -50,7 +50,7 @@ ArduinoIoTCloudLPWAN::ArduinoIoTCloudLPWAN() : _state{State::ConnectPhy} , _retryEnable{false} , _maxNumRetry{5} -, _intervalRetry{10000} +, _intervalRetry{AIOT_CONFIG_INTERVAL_RETRY_DELAY_ms} { } From 459985383421246f210317f7b9af37d5aa91bc6a Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 9 Apr 2024 12:26:49 +0200 Subject: [PATCH 552/780] Move properties containers inside class implementation --- src/ArduinoIoTCloud.cpp | 11 +++++------ src/ArduinoIoTCloud.h | 8 +++----- src/ArduinoIoTCloudLPWAN.cpp | 2 ++ src/ArduinoIoTCloudLPWAN.h | 5 +++++ src/ArduinoIoTCloudTCP.cpp | 3 +++ src/ArduinoIoTCloudTCP.h | 5 +++++ 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 84f08f780..ec2d48267 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -27,7 +27,6 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() : _connection{nullptr} -, _last_checked_property_index{0} , _time_service(TimeService) , _thing_id{""} , _thing_id_property{nullptr} @@ -44,12 +43,12 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() void ArduinoIoTCloudClass::push() { - requestUpdateForAllProperties(_thing_property_container); + requestUpdateForAllProperties(getThingPropertyContainer()); } bool ArduinoIoTCloudClass::setTimestamp(String const & prop_name, unsigned long const timestamp) { - Property * p = getProperty(_thing_property_container, prop_name); + Property * p = getProperty(getThingPropertyContainer(), prop_name); if (p == nullptr) return false; @@ -118,7 +117,7 @@ Property& ArduinoIoTCloudClass::addPropertyReal(String& property, String name, i } Property& ArduinoIoTCloudClass::addPropertyReal(Property& property, String name, int tag, Permission const permission) { - return addPropertyToContainer(_thing_property_container, property, name, permission, tag); + return addPropertyToContainer(getThingPropertyContainer(), property, name, permission, tag); } /* The following methods are deprecated but still used for non-LoRa boards */ @@ -195,9 +194,9 @@ void ArduinoIoTCloudClass::addPropertyRealInternal(Property& property, String na } if (seconds == ON_CHANGE) { - addPropertyToContainer(_thing_property_container, property, name, permission, tag).publishOnChange(minDelta, Property::DEFAULT_MIN_TIME_BETWEEN_UPDATES_MILLIS).onUpdate(fn).onSync(synFn); + addPropertyToContainer(getThingPropertyContainer(), property, name, permission, tag).publishOnChange(minDelta, Property::DEFAULT_MIN_TIME_BETWEEN_UPDATES_MILLIS).onUpdate(fn).onSync(synFn); } else { - addPropertyToContainer(_thing_property_container, property, name, permission, tag).publishEvery(seconds).onUpdate(fn).onSync(synFn); + addPropertyToContainer(getThingPropertyContainer(), property, name, permission, tag).publishEvery(seconds).onUpdate(fn).onSync(synFn); } } diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 7436c0baf..2c5bc4fec 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -105,7 +105,7 @@ class ArduinoIoTCloudClass #define addProperty( v, ...) addPropertyReal(v, #v, __VA_ARGS__) - /* The following methods are used for non-LoRa boards which can use the + /* The following methods are used for non-LoRa boards which can use the * name of the property to identify a given property within a CBOR message. */ @@ -146,9 +146,6 @@ class ArduinoIoTCloudClass protected: ConnectionHandler * _connection; - PropertyContainer _device_property_container; - PropertyContainer _thing_property_container; - unsigned int _last_checked_property_index; TimeServiceClass & _time_service; String _thing_id; Property * _thing_id_property; @@ -158,8 +155,9 @@ class ArduinoIoTCloudClass private: - void addPropertyRealInternal(Property& property, String name, int tag, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0f, void(*synFn)(Property & property) = CLOUD_WINS); + virtual PropertyContainer &getThingPropertyContainer() = 0; + void addPropertyRealInternal(Property& property, String name, int tag, permissionType permission_type = READWRITE, long seconds = ON_CHANGE, void(*fn)(void) = NULL, float minDelta = 0.0f, void(*synFn)(Property & property) = CLOUD_WINS); String _device_id; OnCloudEventCallback _cloud_event_callback[3]; }; diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index e3f625fb7..22234f97c 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -51,6 +51,8 @@ ArduinoIoTCloudLPWAN::ArduinoIoTCloudLPWAN() , _retryEnable{false} , _maxNumRetry{5} , _intervalRetry{AIOT_CONFIG_INTERVAL_RETRY_DELAY_ms} +, _thing_property_container{0} +, _last_checked_property_index{0} { } diff --git a/src/ArduinoIoTCloudLPWAN.h b/src/ArduinoIoTCloudLPWAN.h index 8d1f42d28..46c9e242d 100644 --- a/src/ArduinoIoTCloudLPWAN.h +++ b/src/ArduinoIoTCloudLPWAN.h @@ -49,6 +49,8 @@ class ArduinoIoTCloudLPWAN : public ArduinoIoTCloudClass inline void setMaxRetry (int val) { _maxNumRetry = val; } inline void setIntervalRetry(long val) { _intervalRetry = val; } + inline PropertyContainer &getThingPropertyContainer() { return _thing_property_container; } + private: @@ -64,6 +66,9 @@ class ArduinoIoTCloudLPWAN : public ArduinoIoTCloudClass int _maxNumRetry; long _intervalRetry; + PropertyContainer _thing_property_container; + unsigned int _last_checked_property_index; + State handle_ConnectPhy(); State handle_SyncTime(); State handle_Connected(); diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 794be824c..7457eb8d0 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -60,6 +60,9 @@ unsigned long getTime() ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() : _state{State::ConnectPhy} , _connection_attempt(0,0) +, _device_property_container{0} +, _thing_property_container{0} +, _last_checked_property_index{0} , _tz_offset{0} , _tz_offset_property{nullptr} , _tz_dst_until{0} diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 9b5ffa6c0..bf8396b48 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -91,6 +91,8 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass inline String getBrokerAddress() const { return _brokerAddress; } inline uint16_t getBrokerPort () const { return _brokerPort; } + inline PropertyContainer &getThingPropertyContainer() { return _thing_property_container; } + #if OTA_ENABLED /* The callback is triggered when the OTA is initiated and it gets executed until _ota_req flag is cleared. * It should return true when the OTA can be applied or false otherwise. @@ -123,6 +125,9 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass State _state; TimedAttempt _connection_attempt; + PropertyContainer _device_property_container; + PropertyContainer _thing_property_container; + unsigned int _last_checked_property_index; int _tz_offset; Property * _tz_offset_property; From 864d50f2da13205f27b710f4fa6b29dd45390d14 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 5 Feb 2024 09:12:28 +0100 Subject: [PATCH 553/780] Add commands definitions --- src/message/Commands.h | 50 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/message/Commands.h diff --git a/src/message/Commands.h b/src/message/Commands.h new file mode 100644 index 000000000..0f9cdac20 --- /dev/null +++ b/src/message/Commands.h @@ -0,0 +1,50 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include +#include + +/****************************************************************************** + * TYPEDEF + ******************************************************************************/ + +enum CommandId : uint16_t { + + /* Device commands */ + DeviceBeginCmdId, + ThingBeginCmdId, + ThingUpdateCmdId, + DeviceRegisteredCmdId, + DeviceAttachedCmdId, + DeviceDetachedCmdId, + + /* Thing commands */ + LastValuesBeginCmdId, + LastValuesUpdateCmdId, + PropertiesUpdateCmdId, + + /* Generic commands */ + ResetCmdId, + + /* Unknown command id */ + UnknownCmdId +}; + +struct Command { + CommandId id; +}; + +typedef Command Message; From 4a9f01cf2e7bc1dbe5695569d1929006bb7460bb Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 7 Mar 2024 12:29:11 +0100 Subject: [PATCH 554/780] Add MessageStream interface --- src/interfaces/MessageStream.h | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/interfaces/MessageStream.h diff --git a/src/interfaces/MessageStream.h b/src/interfaces/MessageStream.h new file mode 100644 index 000000000..ac2b18ac9 --- /dev/null +++ b/src/interfaces/MessageStream.h @@ -0,0 +1,40 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include +#include + +using upstreamFunction = std::function; + +/****************************************************************************** + * CLASS DECLARATION + ******************************************************************************/ + +class MessageStream { +public: + MessageStream(upstreamFunction upstream): upstream(upstream) {} + + /** + * Send message upstream + * @param m: message to send + */ + virtual inline void sendUpstream(Message* m) { + upstream(m); + } + +private: + upstreamFunction upstream; +}; From ad40ac8dad78641846e12778b8814e8c5704dc92 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 7 Mar 2024 12:27:26 +0100 Subject: [PATCH 555/780] Add CloudProcess interface --- src/interfaces/CloudProcess.h | 56 +++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/interfaces/CloudProcess.h diff --git a/src/interfaces/CloudProcess.h b/src/interfaces/CloudProcess.h new file mode 100644 index 000000000..7462e867f --- /dev/null +++ b/src/interfaces/CloudProcess.h @@ -0,0 +1,56 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#ifndef ARDUINO_IOT_CLOUD_PROCESS +#define ARDUINO_IOT_CLOUD_PROCESS + +/****************************************************************************** + * INCLUDES + ******************************************************************************/ + +#include +#include +#include +#include + +/****************************************************************************** + * CLASS DECLARATION + ******************************************************************************/ + +class CloudProcess { +public: + CloudProcess(MessageStream* stream): stream(stream) {} + + /** + * Abstract method that is called whenever a message comes from Message stream + * @param m: the incoming message + */ + virtual void handleMessage(Message* m) = 0; + + /** + * Abstract method that is called to update the FSM of the CloudProcess + */ + virtual void update() = 0; + +protected: + /** + * Used by a derived class to send a message to the underlying messageStream + * @param msg: the message to send + */ + void deliver(Message* msg) { + assert(stream != nullptr); + stream->sendUpstream(msg); + } + +private: + MessageStream* stream; +}; + +#endif /* ARDUINO_IOT_CLOUD_PROCESS */ From 93322bba86d6aa175a0c2c8e10d5c9ddf1c1aadc Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 11 Apr 2024 10:25:54 +0200 Subject: [PATCH 556/780] Add ArduinoCloudThing --- src/ArduinoIoTCloudThing.cpp | 172 +++++++++++++++++++++++++++++++++++ src/ArduinoIoTCloudThing.h | 69 ++++++++++++++ 2 files changed, 241 insertions(+) create mode 100644 src/ArduinoIoTCloudThing.cpp create mode 100644 src/ArduinoIoTCloudThing.h diff --git a/src/ArduinoIoTCloudThing.cpp b/src/ArduinoIoTCloudThing.cpp new file mode 100644 index 000000000..6ea6dd904 --- /dev/null +++ b/src/ArduinoIoTCloudThing.cpp @@ -0,0 +1,172 @@ +/* + This file is part of the Arduino_SecureElement library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include + +#ifdef HAS_TCP + +#include "ArduinoIoTCloudThing.h" +#include "interfaces/CloudProcess.h" +#include "property/types/CloudWrapperInt.h" +#include "property/types/CloudWrapperUnsignedInt.h" + +/****************************************************************************** + * CTOR/DTOR + ******************************************************************************/ +ArduinoCloudThing::ArduinoCloudThing(MessageStream* ms) +: CloudProcess(ms), +_state{State::Init}, +_syncAttempt(0, 0), +_propertyContainer(0), +_propertyContainerIndex(0), +_utcOffset(0), +_utcOffsetProperty(nullptr), +_utcOffsetExpireTime(0), +_utcOffsetExpireTimeProperty(nullptr) { +} + +/****************************************************************************** + * PUBLIC MEMBER FUNCTIONS + ******************************************************************************/ + +void ArduinoCloudThing::begin() { + Property* property; + + property = new CloudWrapperInt(_utcOffset); + _utcOffsetProperty = &addPropertyToContainer(getPropertyContainer(), + *property, + "tz_offset", + Permission::ReadWrite, -1); + _utcOffsetProperty->writeOnDemand(); + property = new CloudWrapperUnsignedInt(_utcOffsetExpireTime); + _utcOffsetExpireTimeProperty = &addPropertyToContainer(getPropertyContainer(), + *property, + "tz_dst_until", + Permission::ReadWrite, -1); + _utcOffsetExpireTimeProperty->writeOnDemand(); +} + +void ArduinoCloudThing::update() { + /* Run through the state machine. */ + State nextState = _state; + switch (_state) { + case State::Init: nextState = handleInit(); break; + case State::RequestLastValues: nextState = handleRequestLastValues(); break; + case State::Connected: nextState = handleConnected(); break; + case State::Disconnect: nextState = handleDisconnect(); break; + } + + /* Handle external events */ + switch (_command) { + case LastValuesUpdateCmdId: + if (_state == State::RequestLastValues) { + DEBUG_VERBOSE("CloudThing::%s Thing is synced", __FUNCTION__); + nextState = State::Connected; + } + break; + + /* We have received a reset command */ + case ResetCmdId: + nextState = State::Init; + break; + + default: + break; + } + + _command = UnknownCmdId; + _state = nextState; +} + +int ArduinoCloudThing::connected() { + return _state > State::Disconnect ? 1 : 0; +} + +void ArduinoCloudThing::handleMessage(Message* m) { + _command = UnknownCmdId; + if (m != nullptr) { + _command = m->id; + } +} + +ArduinoCloudThing::State ArduinoCloudThing::handleInit() { + _syncAttempt.begin(AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms); + return State::RequestLastValues; +} + +ArduinoCloudThing::State ArduinoCloudThing::handleRequestLastValues() { + /* Check whether or not we need to send a new request. */ + if (_syncAttempt.isRetry() && !_syncAttempt.isExpired()) { + return State::RequestLastValues; + } + + /* Track the number of times a get-last-values request was sent to the cloud. + * If no data is received within a certain number of retry-requests it's a + * better strategy to disconnect and re-establish connection from the ground up. + */ + if (_syncAttempt.getRetryCount() > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) { + return State::Disconnect; + } + + _syncAttempt.retry(); + + /* Send message upstream to inform infrastructure we need to request thing + * last values + */ + DEBUG_VERBOSE("CloudThing::%s not int sync. %d next sync request in %d ms", + __FUNCTION__, _syncAttempt.getRetryCount(), _syncAttempt.getWaitTime()); + Message message = { LastValuesBeginCmdId }; + deliver(&message); + + return State::RequestLastValues; +} + +ArduinoCloudThing::State ArduinoCloudThing::handleConnected() { + /* Check if a primitive property wrapper is locally changed. + * This function requires an existing time service which in + * turn requires an established connection. Not having that + * leads to a wrong time set in the time service which inhibits + * the connection from being established due to a wrong data + * in the reconstructed certificate. + */ + updateTimestampOnLocallyChangedProperties(getPropertyContainer()); + + /* Configure Time service with timezone data: + * _utcOffset [offset + dst] + * _utcOffsetExpireTime [posix timestamp until _utcOffset is valid] + */ + if (_utcOffsetProperty->isDifferentFromCloud() || + _utcOffsetExpireTimeProperty->isDifferentFromCloud()) { + _utcOffsetProperty->fromCloudToLocal(); + _utcOffsetExpireTimeProperty->fromCloudToLocal(); + TimeService.setTimeZoneData(_utcOffset, _utcOffsetExpireTime); + } + + /* Check if any property needs encoding and send them to the cloud */ + Message message = { PropertiesUpdateCmdId }; + deliver(&message); + + if (getTime() > _utcOffsetExpireTime) { + return State::RequestLastValues; + } + + return State::Connected; +} + +ArduinoCloudThing::State ArduinoCloudThing::handleDisconnect() { + return State::Disconnect; +} + +#endif /* HAS_TCP */ diff --git a/src/ArduinoIoTCloudThing.h b/src/ArduinoIoTCloudThing.h new file mode 100644 index 000000000..de52bc002 --- /dev/null +++ b/src/ArduinoIoTCloudThing.h @@ -0,0 +1,69 @@ +/* + This file is part of the Arduino_SecureElement library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + + +#ifndef ARDUINO_IOT_CLOUD_THING_H +#define ARDUINO_IOT_CLOUD_THING_H + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include "interfaces/CloudProcess.h" +#include "utility/time/TimedAttempt.h" +#include "property/PropertyContainer.h" + +/****************************************************************************** + * CLASS DECLARATION + ******************************************************************************/ + +class ArduinoCloudThing : public CloudProcess { +public: + + ArduinoCloudThing(MessageStream *stream); + virtual void update() override; + virtual void handleMessage(Message *m) override; + + virtual void begin(); + virtual int connected(); + + inline PropertyContainer &getPropertyContainer() { + return _propertyContainer; + }; + inline unsigned int &getPropertyContainerIndex() { + return _propertyContainerIndex; + } + +private: + + enum class State { + Disconnect, + Init, + RequestLastValues, + Connected, + }; + + State _state; + CommandId _command; + TimedAttempt _syncAttempt; + PropertyContainer _propertyContainer; + unsigned int _propertyContainerIndex; + int _utcOffset; + Property *_utcOffsetProperty; + unsigned int _utcOffsetExpireTime; + Property *_utcOffsetExpireTimeProperty; + + State handleInit(); + State handleRequestLastValues(); + State handleConnected(); + State handleDisconnect(); +}; + +#endif /* ARDUINO_IOT_CLOUD_THING_H */ From 51682bd53fe9093ad876b90fef29b2ec6213cec1 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 28 Feb 2024 11:34:00 +0100 Subject: [PATCH 557/780] TimeService: make isTimeValid public --- src/utility/time/TimeService.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 6e6af6bb5..794ec344d 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -56,6 +56,8 @@ class TimeServiceClass */ static unsigned long getTimeFromString(const String& input); + static bool isTimeValid(unsigned long const time); + private: ConnectionHandler * _con_hdl; @@ -74,7 +76,6 @@ class TimeServiceClass void initRTC(); void setRTC(unsigned long time); unsigned long getRTC(); - static bool isTimeValid(unsigned long const time); static bool isTimeZoneOffsetValid(long const offset); }; From 21a5a405e2d868a021f4b75ebf2c86342702b75e Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 28 Feb 2024 12:23:03 +0100 Subject: [PATCH 558/780] ArduinoIoTCloudTCP: Use isTimeValid() to check NTP time --- src/ArduinoIoTCloudTCP.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 7457eb8d0..fead2f602 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -328,12 +328,13 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" - unsigned long const internal_posix_time = _time_service.getTime(); -#pragma GCC diagnostic pop - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); - return State::ConnectMqttBroker; + if (TimeServiceClass::isTimeValid(getTime())) + { + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d", __FUNCTION__, getTime()); + return State::ConnectMqttBroker; + } + + return State::ConnectPhy; } ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() From 3130afab294f2624b10542d207cffe13bca5f687 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 11 Apr 2024 10:26:07 +0200 Subject: [PATCH 559/780] ArduinoIoTCloudTCP: adapt state machine to use Thing process --- src/ArduinoIoTCloud.cpp | 1 - src/ArduinoIoTCloud.h | 1 - src/ArduinoIoTCloudTCP.cpp | 122 +++++++++++++------------------------ src/ArduinoIoTCloudTCP.h | 18 ++---- 4 files changed, 50 insertions(+), 92 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index ec2d48267..0603b6759 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -29,7 +29,6 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() : _connection{nullptr} , _time_service(TimeService) , _thing_id{""} -, _thing_id_property{nullptr} , _lib_version{AIOT_CONFIG_LIB_VERSION} , _device_id{""} , _cloud_event_callback{nullptr} diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 2c5bc4fec..7c0bcc5f9 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -148,7 +148,6 @@ class ArduinoIoTCloudClass ConnectionHandler * _connection; TimeServiceClass & _time_service; String _thing_id; - Property * _thing_id_property; String _lib_version; void execCloudEventCallback(ArduinoIoTCloudEvent const event); diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index fead2f602..e06e218b4 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -60,13 +60,10 @@ unsigned long getTime() ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() : _state{State::ConnectPhy} , _connection_attempt(0,0) +, _message_stream(std::bind(&ArduinoIoTCloudTCP::sendMessage, this, std::placeholders::_1)) +, _thing(&_message_stream) +, _thing_id_property{nullptr} , _device_property_container{0} -, _thing_property_container{0} -, _last_checked_property_index{0} -, _tz_offset{0} -, _tz_offset_property{nullptr} -, _tz_dst_until{0} -, _tz_dst_until_property{nullptr} , _mqtt_data_buf{0} , _mqtt_data_len{0} , _mqtt_data_request_retransmit{false} @@ -214,10 +211,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #endif /* OTA_ENABLED */ p = new CloudWrapperString(_thing_id); _thing_id_property = &addPropertyToContainer(_device_property_container, *p, "thing_id", Permission::ReadWrite, -1).writeOnDemand(); - p = new CloudWrapperInt(_tz_offset); - _tz_offset_property = &addPropertyToContainer(_thing_property_container, *p, "tz_offset", Permission::ReadWrite, -1).writeOnDemand(); - p = new CloudWrapperUnsignedInt(_tz_dst_until); - _tz_dst_until_property = &addPropertyToContainer(_thing_property_container, *p, "tz_dst_until", Permission::ReadWrite, -1).writeOnDemand(); + + _thing.begin(); #if OTA_ENABLED _ota_cap = OTA::isCapable(); @@ -274,7 +269,6 @@ void ArduinoIoTCloudTCP::update() case State::SubscribeDeviceTopic: next_state = handle_SubscribeDeviceTopic(); break; case State::CheckDeviceConfig: next_state = handle_CheckDeviceConfig(); break; case State::SubscribeThingTopics: next_state = handle_SubscribeThingTopics(); break; - case State::RequestLastValues: next_state = handle_RequestLastValues(); break; case State::Connected: next_state = handle_Connected(); break; case State::Disconnect: next_state = handle_Disconnect(); break; } @@ -478,38 +472,12 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() /* Successfully subscribed to thing topics, reconfigure timers for next state and go on */ _connection_attempt.begin(AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms); - return State::RequestLastValues; -} - -ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() -{ - if (!_mqttClient.connected() || _thing_id_property->isDifferentFromCloud()) - { - return State::Disconnect; - } - - /* Check whether or not we need to send a new request. */ - if (_connection_attempt.isRetry() && !_connection_attempt.isExpired()) - return State::RequestLastValues; - - /* Track the number of times a get-last-values request was sent to the cloud. - * If no data is received within a certain number of retry-requests it's a better - * strategy to disconnect and re-establish connection from the ground up. - */ - if (_connection_attempt.getRetryCount() > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT) - { - return State::Disconnect; - } - - _connection_attempt.retry(); - requestLastValue(); - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, _time_service.getTime()); - return State::RequestLastValues; + return State::Connected; } ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() { - if (!_mqttClient.connected()) + if (!_mqttClient.connected() || _thing_id_property->isDifferentFromCloud() || !_thing.connected()) { /* The last message was definitely lost, trigger a retransmit. */ _mqtt_data_request_retransmit = true; @@ -518,20 +486,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() /* We are connected so let's to our stuff here. */ else { - if (_thing_id_property->isDifferentFromCloud()) - { - return State::Disconnect; - } - - /* Check if a primitive property wrapper is locally changed. - * This function requires an existing time service which in - * turn requires an established connection. Not having that - * leads to a wrong time set in the time service which inhibits - * the connection from being established due to a wrong data - * in the reconstructed certificate. - */ - updateTimestampOnLocallyChangedProperties(_thing_property_container); - /* Retransmit data in case there was a lost transaction due * to phy layer or MQTT connectivity loss. */ @@ -540,27 +494,11 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() _mqtt_data_request_retransmit = false; } - /* Configure Time service with timezone data: - * _tz_offset [offset + dst] - * _tz_dst_until [posix timestamp until _tz_offset is valid] - */ - if (_tz_offset_property->isDifferentFromCloud() || _tz_dst_until_property->isDifferentFromCloud()) { - _tz_offset_property->fromCloudToLocal(); - _tz_dst_until_property->fromCloudToLocal(); - _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); - } + /* Call CloudThing process to synchronize properties */ + _thing.update(); - /* Check if any properties need encoding and send them to - * the cloud if necessary. - */ - sendThingPropertiesToCloud(); + return State::Connected; - unsigned long const internal_posix_time = _time_service.getTime(); - if (internal_posix_time < _tz_dst_until) { - return State::Connected; - } else { - return State::RequestLastValues; - } } } @@ -605,9 +543,15 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect() /* TODO add device topic */ _mqttClient.stop(); } + + Message message = { ResetCmdId }; + _thing.handleMessage(&message); + DEBUG_INFO("Disconnected from Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + updateThingTopics(); + /* Setup timer for broker connection and restart */ _connection_attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms); return State::ConnectPhy; @@ -631,25 +575,47 @@ void ArduinoIoTCloudTCP::handleMessage(int length) /* Topic for OTA properties and device configuration */ if (_deviceTopicIn == topic) { CBORDecoder::decode(_device_property_container, (uint8_t*)bytes, length); - _state = State::CheckDeviceConfig; + if (_thing_id_property->isDifferentFromCloud() && (_thing_id.length() != 0)) { + _state = State::Disconnect; + } else { + _state = State::CheckDeviceConfig; + } } /* Topic for user input data */ if (_dataTopicIn == topic) { - CBORDecoder::decode(_thing_property_container, (uint8_t*)bytes, length); + CBORDecoder::decode(_thing.getPropertyContainer(), (uint8_t*)bytes, length); } /* Topic for sync Thing last values on connect */ - if ((_shadowTopicIn == topic) && (_state == State::RequestLastValues)) + if (_shadowTopicIn == topic) { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); - CBORDecoder::decode(_thing_property_container, (uint8_t*)bytes, length, true); - _time_service.setTimeZoneData(_tz_offset, _tz_dst_until); + CBORDecoder::decode(_thing.getPropertyContainer(), (uint8_t*)bytes, length, true); + Message message = { LastValuesUpdateCmdId }; + _thing.handleMessage(&message); execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); _state = State::Connected; } } +void ArduinoIoTCloudTCP::sendMessage(Message * msg) +{ + switch (msg->id) + { + case PropertiesUpdateCmdId: + sendThingPropertiesToCloud(); + break; + + case LastValuesBeginCmdId: + requestLastValue(); + break; + + default: + break; + } +} + void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(String const topic, PropertyContainer & property_container, unsigned int & current_property_index) { int bytes_encoded = 0; @@ -670,7 +636,7 @@ void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(String const topic, Proper void ArduinoIoTCloudTCP::sendThingPropertiesToCloud() { - sendPropertyContainerToCloud(_dataTopicOut, _thing_property_container, _last_checked_property_index); + sendPropertyContainerToCloud(_dataTopicOut, _thing.getPropertyContainer(), _thing.getPropertyContainerIndex()); } void ArduinoIoTCloudTCP::sendDevicePropertiesToCloud() diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index bf8396b48..3d23e56a1 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #if defined(BOARD_HAS_SECURE_ELEMENT) #include @@ -75,7 +75,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass ArduinoIoTCloudTCP(); virtual ~ArduinoIoTCloudTCP() { } - virtual void update () override; virtual int connected () override; virtual void printDebugInfo() override; @@ -91,7 +90,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass inline String getBrokerAddress() const { return _brokerAddress; } inline uint16_t getBrokerPort () const { return _brokerPort; } - inline PropertyContainer &getThingPropertyContainer() { return _thing_property_container; } + inline PropertyContainer &getThingPropertyContainer() { return _thing.getPropertyContainer(); } #if OTA_ENABLED /* The callback is triggered when the OTA is initiated and it gets executed until _ota_req flag is cleared. @@ -118,21 +117,16 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass SubscribeDeviceTopic, CheckDeviceConfig, SubscribeThingTopics, - RequestLastValues, Connected, Disconnect, }; State _state; TimedAttempt _connection_attempt; + MessageStream _message_stream; + ArduinoCloudThing _thing; + Property * _thing_id_property; PropertyContainer _device_property_container; - PropertyContainer _thing_property_container; - unsigned int _last_checked_property_index; - - int _tz_offset; - Property * _tz_offset_property; - unsigned int _tz_dst_until; - Property * _tz_dst_until_property; String _brokerAddress; uint16_t _brokerPort; @@ -200,12 +194,12 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass State handle_CheckDeviceConfig(); State handle_SubscribeDeviceTopic(); State handle_SubscribeThingTopics(); - State handle_RequestLastValues(); State handle_Connected(); State handle_Disconnect(); static void onMessage(int length); void handleMessage(int length); + void sendMessage(Message * msg); void sendPropertyContainerToCloud(String const topic, PropertyContainer & property_container, unsigned int & current_property_index); void sendThingPropertiesToCloud(); void sendDevicePropertiesToCloud(); From f7d8ba73c2cdca25e9e7154d5ea403f98765ebb9 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 11 Apr 2024 17:27:55 +0200 Subject: [PATCH 560/780] Add ArduinoCloudDevice --- src/ArduinoIoTCloudDevice.cpp | 144 ++++++++++++++++++++++++++++++++++ src/ArduinoIoTCloudDevice.h | 70 +++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 src/ArduinoIoTCloudDevice.cpp create mode 100644 src/ArduinoIoTCloudDevice.h diff --git a/src/ArduinoIoTCloudDevice.cpp b/src/ArduinoIoTCloudDevice.cpp new file mode 100644 index 000000000..f72b65588 --- /dev/null +++ b/src/ArduinoIoTCloudDevice.cpp @@ -0,0 +1,144 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include + +#ifdef HAS_TCP + +#include "ArduinoIoTCloudDevice.h" +#include "interfaces/CloudProcess.h" + +/****************************************************************************** + CTOR/DTOR + ******************************************************************************/ +ArduinoCloudDevice::ArduinoCloudDevice(MessageStream *ms) +: CloudProcess(ms), +_state{State::Init}, +_attachAttempt(0, 0), +_attached(false), +_registered(false) { +} + +void ArduinoCloudDevice::begin() { + _attachAttempt.begin(AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms, + AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms); +} + +void ArduinoCloudDevice::update() { + /* Run through the state machine. */ + State nextState = _state; + switch (_state) { + case State::Init: nextState = handleInit(); break; + case State::SendCapabilities: nextState = handleSendCapabilities(); break; + case State::Connected: nextState = handleConnected(); break; + case State::Disconnected: nextState = handleDisconnected(); break; + } + + /* Handle external events */ + switch (_command) { + case DeviceAttachedCmdId: + _attached = true; + _registered = true; + DEBUG_VERBOSE("CloudDevice::%s Device is attached", __FUNCTION__); + nextState = State::Connected; + break; + + case DeviceDetachedCmdId: + _attached = false; + _registered = false; + nextState = State::Init; + break; + + case DeviceRegisteredCmdId: + _registered = true; + nextState = State::Connected; + break; + + /* We have received a reset command */ + case ResetCmdId: + nextState = State::Init; + break; + + default: + break; + } + + _command = UnknownCmdId; + _state = nextState; +} + +int ArduinoCloudDevice::connected() { + return _state != State::Disconnected ? 1 : 0; +} + +void ArduinoCloudDevice::handleMessage(Message *m) { + _command = UnknownCmdId; + if (m != nullptr) { + _command = m->id; + } +} + +ArduinoCloudDevice::State ArduinoCloudDevice::handleInit() { + /* Reset attempt struct for the nex retry after disconnection */ + _attachAttempt.begin(AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms, + AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms); + + _attached = false; + _registered = false; + + return State::SendCapabilities; +} + +ArduinoCloudDevice::State ArduinoCloudDevice::handleSendCapabilities() { + /* Sends device capabilities message */ + Message message = { DeviceBeginCmdId }; + deliver(&message); + + /* Subscribe to device topic to request */ + message = { ThingBeginCmdId }; + deliver(&message); + + /* No device configuration received. Wait: 4s -> 8s -> 16s -> 32s -> 32s ...*/ + _attachAttempt.retry(); + DEBUG_VERBOSE("CloudDevice::%s not attached. %d next configuration request in %d ms", + __FUNCTION__, _attachAttempt.getRetryCount(), _attachAttempt.getWaitTime()); + return State::Connected; +} + +ArduinoCloudDevice::State ArduinoCloudDevice::handleConnected() { + /* Max retry than disconnect */ + if (_attachAttempt.getRetryCount() > AIOT_CONFIG_DEVICE_TOPIC_MAX_RETRY_CNT) { + return State::Disconnected; + } + + if (!_attached && _attachAttempt.isExpired()) { + if (_registered) { + /* Device configuration received, but invalid thing_id. Do not increase + * counter, but recompute delay. + * Wait: 4s -> 80s -> 160s -> 320s -> 640s -> 1280s -> 1280s ... + */ + _attachAttempt.reconfigure(AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms, + AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms); + } + return State::SendCapabilities; + } + + return State::Connected; +} + +ArduinoCloudDevice::State ArduinoCloudDevice::handleDisconnected() { + return State::Disconnected; +} + +#endif /* HAS_TCP */ diff --git a/src/ArduinoIoTCloudDevice.h b/src/ArduinoIoTCloudDevice.h new file mode 100644 index 000000000..294acfde5 --- /dev/null +++ b/src/ArduinoIoTCloudDevice.h @@ -0,0 +1,70 @@ +/* + This file is part of the Arduino_SecureElement library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#ifndef ARDUINO_IOT_CLOUD_DEVICE_H +#define ARDUINO_IOT_CLOUD_DEVICE_H + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include "interfaces/CloudProcess.h" +#include "utility/time/TimedAttempt.h" +#include "property/PropertyContainer.h" + +/****************************************************************************** + * CLASS DECLARATION + ******************************************************************************/ + +class ArduinoCloudDevice : public CloudProcess { +public: + + ArduinoCloudDevice(MessageStream* stream); + virtual void update() override; + virtual void handleMessage(Message* m) override; + + virtual void begin(); + virtual int connected(); + + inline PropertyContainer &getPropertyContainer() { + return _propertyContainer; + }; + inline unsigned int &getPropertyContainerIndex() { + return _propertyContainerIndex; + } + inline bool isAttached() { + return _attached; + }; + + +private: + + enum class State { + Disconnected, + Init, + SendCapabilities, + Connected, + }; + + State _state; + CommandId _command; + TimedAttempt _attachAttempt; + PropertyContainer _propertyContainer; + unsigned int _propertyContainerIndex; + bool _attached; + bool _registered; + + State handleInit(); + State handleSendCapabilities(); + State handleConnected(); + State handleDisconnected(); +}; + +#endif /* ARDUINO_IOT_CLOUD_DEVICE_H */ From 9c881972253d1e01968fb8857f494623732e0599 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 16 Apr 2024 11:34:01 +0200 Subject: [PATCH 561/780] ArduinoIoTCloudTCP: adapt state machine to use Device process --- src/ArduinoIoTCloudTCP.cpp | 328 +++++++++++++++---------------------- src/ArduinoIoTCloudTCP.h | 22 ++- 2 files changed, 140 insertions(+), 210 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e06e218b4..e9ccd4a94 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -63,7 +63,7 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _message_stream(std::bind(&ArduinoIoTCloudTCP::sendMessage, this, std::placeholders::_1)) , _thing(&_message_stream) , _thing_id_property{nullptr} -, _device_property_container{0} +, _device(&_message_stream) , _mqtt_data_buf{0} , _mqtt_data_len{0} , _mqtt_data_request_retransmit{false} @@ -120,11 +120,6 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _brokerAddress = brokerAddress; _brokerPort = brokerPort; -#if OTA_ENABLED - _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 */ - #if defined(BOARD_HAS_SECRET_KEY) /* If board is not configured for username and password login */ if(!_password.length()) @@ -196,27 +191,30 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, Property* p; p = new CloudWrapperString(_lib_version); - addPropertyToContainer(_device_property_container, *p, "LIB_VERSION", Permission::Read, -1); -#if OTA_ENABLED + addPropertyToContainer(_device.getPropertyContainer(), *p, "LIB_VERSION", Permission::Read, -1); + p = new CloudWrapperString(_thing_id); + _thing_id_property = &addPropertyToContainer(_device.getPropertyContainer(), *p, "thing_id", Permission::ReadWrite, -1).writeOnDemand(); + + _thing.begin(); + _device.begin(); + +#if OTA_ENABLED p = new CloudWrapperBool(_ota_cap); - addPropertyToContainer(_device_property_container, *p, "OTA_CAP", Permission::Read, -1); + addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_CAP", Permission::Read, -1); p = new CloudWrapperInt(_ota_error); - addPropertyToContainer(_device_property_container, *p, "OTA_ERROR", Permission::Read, -1); + addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_ERROR", Permission::Read, -1); p = new CloudWrapperString(_ota_img_sha256); - addPropertyToContainer(_device_property_container, *p, "OTA_SHA256", Permission::Read, -1); + addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_SHA256", Permission::Read, -1); p = new CloudWrapperString(_ota_url); - addPropertyToContainer(_device_property_container, *p, "OTA_URL", Permission::ReadWrite, -1); + addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_URL", Permission::ReadWrite, -1); p = new CloudWrapperBool(_ota_req); - addPropertyToContainer(_device_property_container, *p, "OTA_REQ", Permission::ReadWrite, -1); -#endif /* OTA_ENABLED */ - p = new CloudWrapperString(_thing_id); - _thing_id_property = &addPropertyToContainer(_device_property_container, *p, "thing_id", Permission::ReadWrite, -1).writeOnDemand(); - - _thing.begin(); + addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_REQ", Permission::ReadWrite, -1); -#if OTA_ENABLED _ota_cap = OTA::isCapable(); -#endif + + _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 #ifdef BOARD_HAS_OFFLOADED_ECCX08 if (String(WiFi.firmwareVersion()) < String("1.4.4")) { @@ -257,7 +255,6 @@ void ArduinoIoTCloudTCP::update() watchdog_reset(); #endif - /* Run through the state machine. */ State next_state = _state; switch (_state) @@ -265,23 +262,13 @@ void ArduinoIoTCloudTCP::update() case State::ConnectPhy: next_state = handle_ConnectPhy(); break; case State::SyncTime: next_state = handle_SyncTime(); break; case State::ConnectMqttBroker: next_state = handle_ConnectMqttBroker(); break; - case State::SendDeviceProperties: next_state = handle_SendDeviceProperties(); break; - case State::SubscribeDeviceTopic: next_state = handle_SubscribeDeviceTopic(); break; - case State::CheckDeviceConfig: next_state = handle_CheckDeviceConfig(); break; - case State::SubscribeThingTopics: next_state = handle_SubscribeThingTopics(); break; case State::Connected: next_state = handle_Connected(); break; case State::Disconnect: next_state = handle_Disconnect(); break; } _state = next_state; -#if OTA_ENABLED - if (_state > State::SubscribeDeviceTopic && _state <= State::Connected) { - handle_OTARequest(); - } -#endif /* OTA_ENABLED */ - /* This watchdog feed is actually needed only by the RP2040 Connect because its - * maximum watchdog window is 8389 ms; despite this we feed it for all + * maximum watchdog window is 8389 ms; despite this we feed it for all * supported ARCH to keep code aligned. */ #if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) @@ -338,7 +325,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s connected to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); /* Reconfigure timers for next state */ _connection_attempt.begin(AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms, AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms); - return State::SendDeviceProperties; + return State::Connected; } /* Can't connect to the broker. Wait: 2s -> 4s -> 8s -> 16s -> 32s -> 32s ... */ @@ -350,158 +337,38 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() return State::ConnectPhy; } -ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SendDeviceProperties() -{ - if (!_mqttClient.connected()) - { - return State::Disconnect; - } - - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s announce device to the Cloud %d", __FUNCTION__, _time_service.getTime()); - /* TODO check if write fails */ - sendDevicePropertiesToCloud(); - return State::SubscribeDeviceTopic; -} - -ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeDeviceTopic() -{ - if (!_mqttClient.connected()) - { - return State::Disconnect; - } - - if (_connection_attempt.isRetry() && !_connection_attempt.isExpired()) - return State::SubscribeDeviceTopic; - - if (_connection_attempt.isRetry()) - { - /* Configuration not received or device not attached to a valid thing. Try to resubscribe */ - DEBUG_ERROR("ArduinoIoTCloudTCP::%s device waiting for valid thing_id %d", __FUNCTION__, _time_service.getTime()); - } - - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s request device configuration %d", __FUNCTION__, _time_service.getTime()); - - if (!_mqttClient.subscribe(_deviceTopicIn)) - { - /* If device_id is wrong the board can't connect to the broker so this condition - * should never happen. - */ - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _deviceTopicIn.c_str()); - } - - /* Max retry than disconnect */ - if (_connection_attempt.getRetryCount() > AIOT_CONFIG_DEVICE_TOPIC_MAX_RETRY_CNT) - { - return State::Disconnect; - } - - /* No device configuration received. Wait: 4s -> 8s -> 16s -> 32s -> 32s ...*/ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" - unsigned long const subscribe_retry_delay = _connection_attempt.retry(); -#pragma GCC diagnostic pop - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s %d next configuration request in %d ms", __FUNCTION__, _connection_attempt.getRetryCount(), subscribe_retry_delay); - - return State::SubscribeDeviceTopic; -} - -ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_CheckDeviceConfig() -{ - if (!_mqttClient.connected()) - { - return State::Disconnect; - } - - updateThingTopics(); - - if (_thing_id.length() == 0) - { - /* Device configuration received, but invalid thing_id. Do not increase counter, but recompute delay. - * Device not attached. Wait: 40s -> 80s -> 160s -> 320s -> 640s -> 1280s -> 1280s ... - */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" - unsigned long const attach_retry_delay = _connection_attempt.reconfigure(AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms, AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms); -#pragma GCC diagnostic pop - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s device not attached, next configuration request in %d ms", __FUNCTION__, attach_retry_delay); - return State::SubscribeDeviceTopic; - } - - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s device attached to a new valid thing_id %s %d", __FUNCTION__, getThingId().c_str(), _time_service.getTime()); - - /* Received valid thing_id, reconfigure timers for next state and go on */ - _connection_attempt.begin(AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_RETRY_DELAY_ms); - - return State::SubscribeThingTopics; -} - -ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics() +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() { - if (!_mqttClient.connected() || _thing_id_property->isDifferentFromCloud()) + if (!_mqttClient.connected() || !_thing.connected() || !_device.connected()) { return State::Disconnect; } - if (_connection_attempt.isRetry() && !_connection_attempt.isExpired()) - return State::SubscribeThingTopics; - - if (_connection_attempt.getRetryCount() > AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_MAX_RETRY_CNT) - { - return State::Disconnect; + /* Retransmit data in case there was a lost transaction due + * to phy layer or MQTT connectivity loss. + */ + if (_mqtt_data_request_retransmit && (_mqtt_data_len > 0)) { + write(_dataTopicOut, _mqtt_data_buf, _mqtt_data_len); + _mqtt_data_request_retransmit = false; } - _connection_attempt.retry(); + /* Call CloudDevice process to get configuration */ + _device.update(); - if (!_mqttClient.subscribe(_dataTopicIn)) - { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); - DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); - return State::SubscribeThingTopics; + if (_device.isAttached()) { + /* Call CloudThing process to synchronize properties */ + _thing.update(); } - if (!_mqttClient.subscribe(_shadowTopicIn)) - { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); - DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); - return State::SubscribeThingTopics; +#if OTA_ENABLED + if (_device.connected()) { + handle_OTARequest(); } +#endif /* OTA_ENABLED */ - DEBUG_INFO("Connected to Arduino IoT Cloud"); - DEBUG_INFO("Thing ID: %s", getThingId().c_str()); - execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); - - /* Successfully subscribed to thing topics, reconfigure timers for next state and go on */ - _connection_attempt.begin(AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms); return State::Connected; } -ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() -{ - if (!_mqttClient.connected() || _thing_id_property->isDifferentFromCloud() || !_thing.connected()) - { - /* The last message was definitely lost, trigger a retransmit. */ - _mqtt_data_request_retransmit = true; - return State::Disconnect; - } - /* We are connected so let's to our stuff here. */ - else - { - /* Retransmit data in case there was a lost transaction due - * to phy layer or MQTT connectivity loss. - */ - if (_mqtt_data_request_retransmit && (_mqtt_data_len > 0)) { - write(_dataTopicOut, _mqtt_data_buf, _mqtt_data_len); - _mqtt_data_request_retransmit = false; - } - - /* Call CloudThing process to synchronize properties */ - _thing.update(); - - return State::Connected; - - } -} - #if OTA_ENABLED void ArduinoIoTCloudTCP::handle_OTARequest() { /* Request a OTA download if the hidden property @@ -538,20 +405,17 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect() if (!_mqttClient.connected()) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s MQTT client connection lost", __FUNCTION__); } else { - _mqttClient.unsubscribe(_shadowTopicIn); - _mqttClient.unsubscribe(_dataTopicIn); - /* TODO add device topic */ + /* No need to manually unsubscribe because we are using clean sessions */ _mqttClient.stop(); } Message message = { ResetCmdId }; _thing.handleMessage(&message); + _device.handleMessage(&message); DEBUG_INFO("Disconnected from Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - updateThingTopics(); - /* Setup timer for broker connection and restart */ _connection_attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms); return State::ConnectPhy; @@ -574,11 +438,28 @@ void ArduinoIoTCloudTCP::handleMessage(int length) /* Topic for OTA properties and device configuration */ if (_deviceTopicIn == topic) { - CBORDecoder::decode(_device_property_container, (uint8_t*)bytes, length); - if (_thing_id_property->isDifferentFromCloud() && (_thing_id.length() != 0)) { - _state = State::Disconnect; - } else { - _state = State::CheckDeviceConfig; + CBORDecoder::decode(_device.getPropertyContainer(), (uint8_t*)bytes, length); + + /* Temporary check to avoid flooding device state machine with usless messages */ + if (_thing_id_property->isDifferentFromCloud()) { + _thing_id_property->fromCloudToLocal(); + + Message message; + /* If we are attached we need first to detach */ + if (_device.isAttached()) { + detachThing(); + message = { DeviceDetachedCmdId }; + } + /* If received thing id is valid attach to the new thing */ + if (_thing_id.length()) { + attachThing(); + message = { DeviceAttachedCmdId }; + } else { + /* Send message to device state machine to inform we have received a null thing-id */ + _thing_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; + message = { DeviceRegisteredCmdId }; + } + _device.handleMessage(&message); } } @@ -588,14 +469,15 @@ void ArduinoIoTCloudTCP::handleMessage(int length) } /* Topic for sync Thing last values on connect */ - if (_shadowTopicIn == topic) - { + if (_shadowTopicIn == topic) { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); + /* Decode last values property array */ CBORDecoder::decode(_thing.getPropertyContainer(), (uint8_t*)bytes, length, true); + /* Unlock thing state machine waiting last values */ Message message = { LastValuesUpdateCmdId }; _thing.handleMessage(&message); + /* Call ArduinoIoTCloud sync user callback*/ execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); - _state = State::Connected; } } @@ -603,14 +485,22 @@ void ArduinoIoTCloudTCP::sendMessage(Message * msg) { switch (msg->id) { - case PropertiesUpdateCmdId: - sendThingPropertiesToCloud(); + case DeviceBeginCmdId: + sendDevicePropertiesToCloud(); + break; + + case ThingBeginCmdId: + requestThingId(); break; case LastValuesBeginCmdId: requestLastValue(); break; + case PropertiesUpdateCmdId: + sendThingPropertiesToCloud(); + break; + default: break; } @@ -622,6 +512,7 @@ void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(String const topic, Proper uint8_t data[MQTT_TRANSMIT_BUFFER_SIZE]; if (CBOREncoder::encode(property_container, data, sizeof(data), bytes_encoded, current_property_index, false) == CborNoError) + { if (bytes_encoded > 0) { /* If properties have been encoded store them in the back-up buffer @@ -632,6 +523,7 @@ void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(String const topic, Proper /* Transmit the properties to the MQTT broker */ write(topic, _mqtt_data_buf, _mqtt_data_len); } + } } void ArduinoIoTCloudTCP::sendThingPropertiesToCloud() @@ -649,12 +541,11 @@ void ArduinoIoTCloudTCP::sendDevicePropertiesToCloud() ro_device_property_list.end(), [this, &ro_device_property_container ] (String const & name) { - Property* p = getProperty(this->_device_property_container, name); + Property* p = getProperty(this->_device.getPropertyContainer(), name); if(p != nullptr) addPropertyToContainer(ro_device_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); } ); - sendPropertyContainerToCloud(_deviceTopicOut, ro_device_property_container, last_device_property_index); } @@ -664,7 +555,7 @@ void ArduinoIoTCloudTCP::sendDevicePropertyToCloud(String const name) PropertyContainer temp_device_property_container; unsigned int last_device_property_index = 0; - Property* p = getProperty(this->_device_property_container, name); + Property* p = getProperty(this->_device.getPropertyContainer(), name); if(p != nullptr) { addPropertyToContainer(temp_device_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); @@ -682,6 +573,57 @@ void ArduinoIoTCloudTCP::requestLastValue() write(_shadowTopicOut, CBOR_REQUEST_LAST_VALUE_MSG, sizeof(CBOR_REQUEST_LAST_VALUE_MSG)); } +void ArduinoIoTCloudTCP::requestThingId() +{ + if (!_mqttClient.subscribe(_deviceTopicIn)) + { + /* If device_id is wrong the board can't connect to the broker so this condition + * should never happen. + */ + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _deviceTopicIn.c_str()); + } +} + +void ArduinoIoTCloudTCP::attachThing() +{ + + _dataTopicIn = getTopic_datain(); + _dataTopicOut = getTopic_dataout(); + if (!_mqttClient.subscribe(_dataTopicIn)) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); + DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); + return; + } + + _shadowTopicIn = getTopic_shadowin(); + _shadowTopicOut = getTopic_shadowout(); + if (!_mqttClient.subscribe(_shadowTopicIn)) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); + DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); + return; + } + + DEBUG_INFO("Connected to Arduino IoT Cloud"); + DEBUG_INFO("Thing ID: %s", getThingId().c_str()); + execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); +} + +void ArduinoIoTCloudTCP::detachThing() +{ + if (!_mqttClient.unsubscribe(_dataTopicIn)) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not unsubscribe from %s", __FUNCTION__, _dataTopicIn.c_str()); + return; + } + + if (!_mqttClient.unsubscribe(_shadowTopicIn)) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not unsubscribe from %s", __FUNCTION__, _shadowTopicIn.c_str()); + return; + } + + DEBUG_INFO("Disconnected from Arduino IoT Cloud"); + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); +} + int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const length) { if (_mqttClient.beginMessage(topic, length, false, 0)) { @@ -694,16 +636,6 @@ int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const l return 0; } -void ArduinoIoTCloudTCP::updateThingTopics() -{ - _thing_id_property->fromCloudToLocal(); - - _shadowTopicOut = getTopic_shadowout(); - _shadowTopicIn = getTopic_shadowin(); - _dataTopicOut = getTopic_dataout(); - _dataTopicIn = getTopic_datain(); -} - /****************************************************************************** * EXTERN DEFINITION ******************************************************************************/ diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 3d23e56a1..1c13592df 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -26,6 +26,7 @@ #include #include #include +#include #if defined(BOARD_HAS_SECURE_ELEMENT) #include @@ -51,6 +52,10 @@ #include #endif +#if OTA_ENABLED +#include +#endif + /****************************************************************************** CONSTANTS ******************************************************************************/ @@ -101,8 +106,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass _get_ota_confirmation = cb; _ask_user_before_executing_ota = true; } - - void handle_OTARequest(); + void handle_OTARequest(); #endif private: @@ -113,10 +117,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass ConnectPhy, SyncTime, ConnectMqttBroker, - SendDeviceProperties, - SubscribeDeviceTopic, - CheckDeviceConfig, - SubscribeThingTopics, Connected, Disconnect, }; @@ -126,7 +126,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass MessageStream _message_stream; ArduinoCloudThing _thing; Property * _thing_id_property; - PropertyContainer _device_property_container; + ArduinoCloudDevice _device; String _brokerAddress; uint16_t _brokerPort; @@ -190,10 +190,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass State handle_ConnectPhy(); State handle_SyncTime(); State handle_ConnectMqttBroker(); - State handle_SendDeviceProperties(); - State handle_CheckDeviceConfig(); - State handle_SubscribeDeviceTopic(); - State handle_SubscribeThingTopics(); State handle_Connected(); State handle_Disconnect(); @@ -204,13 +200,15 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass void sendThingPropertiesToCloud(); void sendDevicePropertiesToCloud(); void requestLastValue(); + void requestThingId(); + void attachThing(); + void detachThing(); int write(String const topic, byte const data[], int const length); #if OTA_ENABLED void sendDevicePropertyToCloud(String const name); #endif - void updateThingTopics(); }; /****************************************************************************** From 181bba7a0da3f564b173e85f2d703d18e51ca967 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Apr 2024 11:39:45 +0200 Subject: [PATCH 562/780] Cloud: initialize thing id to non null --- src/ArduinoIoTCloud.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 0603b6759..a565cac44 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -28,9 +28,9 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() : _connection{nullptr} , _time_service(TimeService) -, _thing_id{""} +, _thing_id{"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"} , _lib_version{AIOT_CONFIG_LIB_VERSION} -, _device_id{""} +, _device_id{"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"} , _cloud_event_callback{nullptr} { From 6babc12931248e0aa4904b94c85b4da692f4f62c Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 14 May 2024 16:06:24 +0200 Subject: [PATCH 563/780] LPWAN: fix property container initialization --- src/ArduinoIoTCloudLPWAN.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 22234f97c..0f213e0a5 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -51,7 +51,7 @@ ArduinoIoTCloudLPWAN::ArduinoIoTCloudLPWAN() , _retryEnable{false} , _maxNumRetry{5} , _intervalRetry{AIOT_CONFIG_INTERVAL_RETRY_DELAY_ms} -, _thing_property_container{0} +, _thing_property_container() , _last_checked_property_index{0} { From dab2f4c35233dad45e885b4e0fa317bff9106714 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 14 May 2024 16:32:02 +0200 Subject: [PATCH 564/780] ArduinoIoTCloudDevice: add missing initializers --- src/ArduinoIoTCloudDevice.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ArduinoIoTCloudDevice.cpp b/src/ArduinoIoTCloudDevice.cpp index f72b65588..f6594e027 100644 --- a/src/ArduinoIoTCloudDevice.cpp +++ b/src/ArduinoIoTCloudDevice.cpp @@ -26,6 +26,8 @@ ArduinoCloudDevice::ArduinoCloudDevice(MessageStream *ms) : CloudProcess(ms), _state{State::Init}, _attachAttempt(0, 0), +_propertyContainer(), +_propertyContainerIndex(0), _attached(false), _registered(false) { } From 0b40e42040f8af777cd6cd6a491c6ee6c3f3b00a Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 14 May 2024 17:21:41 +0200 Subject: [PATCH 565/780] ArduinoIoTCloudThing: conform _propertyContainer initialization --- src/ArduinoIoTCloudThing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudThing.cpp b/src/ArduinoIoTCloudThing.cpp index 6ea6dd904..d2f49119b 100644 --- a/src/ArduinoIoTCloudThing.cpp +++ b/src/ArduinoIoTCloudThing.cpp @@ -29,7 +29,7 @@ ArduinoCloudThing::ArduinoCloudThing(MessageStream* ms) : CloudProcess(ms), _state{State::Init}, _syncAttempt(0, 0), -_propertyContainer(0), +_propertyContainer(), _propertyContainerIndex(0), _utcOffset(0), _utcOffsetProperty(nullptr), From c870a7250059c31f38b711be69ff47c6c0860149 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 15 May 2024 14:42:16 +0200 Subject: [PATCH 566/780] Fix thing property reconfiguration after wifi loss --- src/ArduinoIoTCloudTCP.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e9ccd4a94..39d878512 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -413,6 +413,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect() _thing.handleMessage(&message); _device.handleMessage(&message); + _thing_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; DEBUG_INFO("Disconnected from Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); @@ -444,22 +445,20 @@ void ArduinoIoTCloudTCP::handleMessage(int length) if (_thing_id_property->isDifferentFromCloud()) { _thing_id_property->fromCloudToLocal(); - Message message; - /* If we are attached we need first to detach */ - if (_device.isAttached()) { - detachThing(); - message = { DeviceDetachedCmdId }; - } - /* If received thing id is valid attach to the new thing */ - if (_thing_id.length()) { - attachThing(); - message = { DeviceAttachedCmdId }; - } else { + if (!_thing_id.length()) { /* Send message to device state machine to inform we have received a null thing-id */ _thing_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; + Message message; message = { DeviceRegisteredCmdId }; + _device.handleMessage(&message); + } else { + if (_device.isAttached()) { + detachThing(); + } + if (!_device.isAttached()) { + attachThing(); + } } - _device.handleMessage(&message); } } @@ -592,6 +591,7 @@ void ArduinoIoTCloudTCP::attachThing() if (!_mqttClient.subscribe(_dataTopicIn)) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); + _thing_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; return; } @@ -600,9 +600,14 @@ void ArduinoIoTCloudTCP::attachThing() if (!_mqttClient.subscribe(_shadowTopicIn)) { DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); + _thing_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; return; } + Message message; + message = { DeviceAttachedCmdId }; + _device.handleMessage(&message); + DEBUG_INFO("Connected to Arduino IoT Cloud"); DEBUG_INFO("Thing ID: %s", getThingId().c_str()); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); @@ -620,6 +625,11 @@ void ArduinoIoTCloudTCP::detachThing() return; } + Message message; + message = { DeviceDetachedCmdId }; + _device.handleMessage(&message); + + _thing_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; DEBUG_INFO("Disconnected from Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); } From 20dd328826efee37abcee2696a425ecbbdbde046 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 16 May 2024 11:29:09 +0200 Subject: [PATCH 567/780] Debug: print mqttClient error code when connection fails --- src/ArduinoIoTCloudTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 39d878512..0851700cc 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -331,7 +331,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() /* Can't connect to the broker. Wait: 2s -> 4s -> 8s -> 16s -> 32s -> 32s ... */ _connection_attempt.retry(); - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d Error: %d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort, _mqttClient.connectError()); DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s %d next connection attempt in %d ms", __FUNCTION__, _connection_attempt.getRetryCount(), _connection_attempt.getWaitTime()); /* Go back to ConnectPhy and retry to get time from network (invalid time for SSL handshake?)*/ return State::ConnectPhy; From 4577d59c69a672cad70cc76ca3cbc7f20cb84df4 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 18 Apr 2024 15:42:49 +0200 Subject: [PATCH 568/780] CI: added ArduinoHttpClient as dependency --- .github/workflows/compile-examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index baf9a4b1e..0e6c98ef9 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -22,6 +22,7 @@ jobs: # Install the ArduinoIoTCloud library from the repository - source-path: ./ - name: Arduino_ConnectionHandler + - name: ArduinoHttpClient - name: Arduino_DebugUtils - name: ArduinoMqttClient - name: Arduino_SecureElement From ec187076953201640f7bea529f390ea60006d996 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 12 Mar 2024 15:43:32 +0100 Subject: [PATCH 569/780] removing unused dependencies: ESP and Portente OTA --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index c98825ea2..3664ce8c5 100644 --- a/library.properties +++ b/library.properties @@ -8,4 +8,4 @@ category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta,mbed_giga,renesas_portenta,renesas_uno,mbed_edge includes=ArduinoIoTCloud.h -depends=Arduino_ConnectionHandler,Arduino_DebugUtils,Arduino_SecureElement,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,Arduino_ESP32_OTA,Arduino_Portenta_OTA +depends=Arduino_ConnectionHandler,Arduino_DebugUtils,Arduino_SecureElement,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,ArduinoHttpClient From f494795a1a365810dee1863406d59ccf20e800df Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 21 Feb 2024 17:22:27 +0100 Subject: [PATCH 570/780] changing include enrtypoint for OTA --- src/utility/ota/OTA.cpp | 125 ---------------------------------------- src/utility/ota/OTA.h | 81 ++++++++++++-------------- 2 files changed, 36 insertions(+), 170 deletions(-) delete mode 100644 src/utility/ota/OTA.cpp diff --git a/src/utility/ota/OTA.cpp b/src/utility/ota/OTA.cpp deleted file mode 100644 index e71aac5a2..000000000 --- a/src/utility/ota/OTA.cpp +++ /dev/null @@ -1,125 +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 - -#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 - -#ifdef ARDUINO_UNOR4_WIFI -int unor4_onOTARequest(char const * url); -String unor4_getOTAImageSHA256(); -bool unor4_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()); -#elif defined (ARDUINO_UNOR4_WIFI) - (void)iface; - return unor4_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(); -#elif defined (ARDUINO_UNOR4_WIFI) - return unor4_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(); -#elif defined (ARDUINO_UNOR4_WIFI) - return unor4_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 88c7229b9..f8d5fcfdd 100644 --- a/src/utility/ota/OTA.h +++ b/src/utility/ota/OTA.h @@ -1,42 +1,49 @@ /* - This file is part of ArduinoIoTCloud. + This file is part of the ArduinoIoTCloud library. - Copyright 2020 ARDUINO SA (http://www.arduino.cc/) + Copyright (c) 2024 Arduino SA - 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. + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef ARDUINO_OTA_LOGIC_H_ -#define ARDUINO_OTA_LOGIC_H_ +#pragma once +#include "AIoTC_Config.h" +#if OTA_ENABLED -/****************************************************************************** - * INCLUDE - ******************************************************************************/ +#ifdef ARDUINO_ARCH_SAMD +#include "OTASamd.h" +using OTACloudProcess = SAMDOTACloudProcess; -#include +#elif defined(ARDUINO_NANO_RP2040_CONNECT) +#include "OTANanoRP2040.h" +using OTACloudProcess = NANO_RP2040OTACloudProcess; -#if OTA_ENABLED -#include -#include +#elif defined(BOARD_STM32H7) +#include "OTAPortentaH7.h" +using OTACloudProcess = STM32H7OTACloudProcess; -/****************************************************************************** - * DEFINES - ******************************************************************************/ +#elif defined(ARDUINO_ARCH_ESP32) +#include "OTAEsp32.h" +using OTACloudProcess = ESP32OTACloudProcess; -#define RP2040_OTA_ERROR_BASE (-100) -/****************************************************************************** - * TYPEDEF - ******************************************************************************/ +#if defined (ARDUINO_NANO_ESP32) + constexpr uint32_t OtaMagicNumber = 0x23410070; +#else + constexpr uint32_t OtaMagicNumber = 0x45535033; +#endif + +#elif defined(ARDUINO_UNOR4_WIFI) +#include "OTAUnoR4.h" +using OTACloudProcess = UNOR4OTACloudProcess; + +#else +#error "This Board doesn't support OTA" +#endif + +#define RP2040_OTA_ERROR_BASE (-100) enum class OTAError : int { @@ -54,20 +61,4 @@ enum class OTAError : int RP2040_ErrorUnmount = RP2040_OTA_ERROR_BASE - 9, }; -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class OTA -{ -public: - - static int onRequest(String url, NetworkAdapter iface); - static String getImageSHA256(); - static bool isCapable(); - -}; - -#endif /* OTA_ENABLED */ - -#endif /* ARDUINO_OTA_LOGIC_H_ */ +#endif // OTA_ENABLED From a07a23d4390618345b99dfe94e9259f7d7043377 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 21 Feb 2024 17:10:46 +0100 Subject: [PATCH 571/780] included LZSSDecoder library beforme making it a library --- src/utility/lzss/lzss.cpp | 163 ++++++++++++++++++++++++++++++++++++++ src/utility/lzss/lzss.h | 108 +++++++++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 src/utility/lzss/lzss.cpp create mode 100644 src/utility/lzss/lzss.h diff --git a/src/utility/lzss/lzss.cpp b/src/utility/lzss/lzss.cpp new file mode 100644 index 000000000..1a11399f6 --- /dev/null +++ b/src/utility/lzss/lzss.cpp @@ -0,0 +1,163 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + + This implementation took inspiration from https://okumuralab.org/~okumura/compression/lzss.c source code +*/ + +/************************************************************************************** + INCLUDE + **************************************************************************************/ +#include "lzss.h" + +#include + +/************************************************************************************** + LZSS DECODER CLASS IMPLEMENTATION + **************************************************************************************/ + +// get the number of bits the algorithm will try to get given the state +uint8_t LZSSDecoder::bits_required(LZSSDecoder::FSM_STATES s) { + switch(s) { + case FSM_0: + return 1; + case FSM_1: + return 8; + case FSM_2: + return EI; + case FSM_3: + return EJ; + default: + return 0; + } +} + +LZSSDecoder::LZSSDecoder(std::function getc_cbk, std::function putc_cbk) +: available(0), state(FSM_0), put_char_cbk(putc_cbk), get_char_cbk(getc_cbk) { + for (int i = 0; i < N - F; i++) buffer[i] = ' '; + r = N - F; +} + + +LZSSDecoder::LZSSDecoder(std::function putc_cbk) +: available(0), state(FSM_0), put_char_cbk(putc_cbk), get_char_cbk(nullptr) { + for (int i = 0; i < N - F; i++) buffer[i] = ' '; + r = N - F; +} + +LZSSDecoder::status LZSSDecoder::handle_state() { + LZSSDecoder::status res = IN_PROGRESS; + + int c = getbit(bits_required(this->state)); + + if(c == LZSS_BUFFER_EMPTY) { + res = NOT_COMPLETED; + } else if (c == LZSS_EOF) { + res = DONE; + this->state = FSM_EOF; + } else { + switch(this->state) { + case FSM_0: + if(c) { + this->state = FSM_1; + } else { + this->state = FSM_2; + } + break; + case FSM_1: + putc(c); + buffer[r++] = c; + r &= (N - 1); // equivalent to r = r % N when N is a power of 2 + + this->state = FSM_0; + break; + case FSM_2: + this->i = c; + this->state = FSM_3; + break; + case FSM_3: { + int j = c; + + // This is where the actual decompression takes place: we look into the local buffer for reuse + // of byte chunks. This can be improved by means of memcpy and by changing the putc function + // into a put_buf function in order to avoid buffering on the other end. + // TODO improve this section of code + for (int k = 0; k <= j + 1; k++) { + c = buffer[(this->i + k) & (N - 1)]; // equivalent to buffer[(i+k) % N] when N is a power of 2 + putc(c); + buffer[r++] = c; + r &= (N - 1); // equivalent to r = r % N + } + this->state = FSM_0; + + break; + } + case FSM_EOF: + break; + } + } + + return res; +} + +LZSSDecoder::status LZSSDecoder::decompress(uint8_t* const buffer, uint32_t size) { + if(!get_char_cbk) { + this->in_buffer = buffer; + this->available += size; + } + + status res = IN_PROGRESS; + + while((res = handle_state()) == IN_PROGRESS); + + this->in_buffer = nullptr; + + return res; +} + +int LZSSDecoder::getbit(uint8_t n) { // get n bits from buffer + int x=0, c; + + // if the local bit buffer doesn't have enough bit get them + while(buf_size < n) { + switch(c=getc()) { + case LZSS_EOF: + case LZSS_BUFFER_EMPTY: + return c; + } + buf <<= 8; + + buf |= (uint8_t)c; + buf_size += sizeof(uint8_t)*8; + } + + // the result is the content of the buffer starting from msb to n successive bits + x = buf >> (buf_size-n); + + // remove from the buffer the read bits with a mask + buf &= (1<<(buf_size-n))-1; + + buf_size-=n; + + return x; +} + +int LZSSDecoder::getc() { + int c; + + if(get_char_cbk) { + c = get_char_cbk(); + } else if(in_buffer == nullptr || available == 0) { + c = LZSS_BUFFER_EMPTY; + } else { + c = *in_buffer; + in_buffer++; + available--; + } + return c; +} \ No newline at end of file diff --git a/src/utility/lzss/lzss.h b/src/utility/lzss/lzss.h new file mode 100644 index 000000000..bf652026e --- /dev/null +++ b/src/utility/lzss/lzss.h @@ -0,0 +1,108 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +/************************************************************************************** + INCLUDE + **************************************************************************************/ +#include +#include +#include + +/************************************************************************************** + FUNCTION DEFINITION + **************************************************************************************/ + +/************************************************************************************** + LZSS DECODER CLASS + **************************************************************************************/ + + +class LZSSDecoder { +public: + + /** + * Build an LZSS decoder by providing a callback for storing the decoded bytes + * @param putc_cbk: a callback that takes a char and stores it e.g. a callback to fwrite + */ + LZSSDecoder(std::function putc_cbk); + + /** + * Build an LZSS decoder providing a callback for getting a char and putting a char + * in this way you need to call decompress with no parameters + * @param putc_cbk: a callback that takes a char and stores it e.g. a callback to fwrite + * @param getc_cbk: a callback that returns the next char to consume + * -1 means EOF, -2 means buffer is temporairly finished + */ + LZSSDecoder(std::function getc_cbk, std::function putc_cbk); + + /** + * this enum describes the result of the computation of a single FSM computation + * DONE: the decompression is completed + * IN_PROGRESS: the decompression cycle completed successfully, ready to compute next + * NOT_COMPLETED: the current cycle didn't complete because the available data is not enough + */ + enum status: uint8_t { + DONE, + IN_PROGRESS, + NOT_COMPLETED + }; + + /** + * decode the provided buffer until buffer ends, then pause the process + * @return DONE if the decompression is completed, NOT_COMPLETED if not + */ + status decompress(uint8_t* const buffer=nullptr, uint32_t size=0); + + static const int LZSS_EOF = -1; + static const int LZSS_BUFFER_EMPTY = -2; +private: + // TODO provide a way for the user to set these parameters + static const int EI = 11; /* typically 10..13 */ + static const int EJ = 4; /* typically 4..5 */ + static const int N = (1 << EI); /* buffer size */ + static const int F = ((1 << EJ) + 1); /* lookahead buffer size */ + + // algorithm specific buffer used to store text that could be later referenced and copied + uint8_t buffer[N * 2]; + + // this function gets 1 single char from the input buffer + int getc(); + uint8_t* in_buffer = nullptr; + uint32_t available = 0; + + status handle_state(); + + // get 1 bit from the available input buffer + int getbit(uint8_t n); + // the following 2 are variables used by getbits + uint32_t buf, buf_size=0; + + enum FSM_STATES: uint8_t { + FSM_0 = 0, + FSM_1 = 1, + FSM_2 = 2, + FSM_3 = 3, + FSM_EOF + } state; + + // these variable are used in a decode session and specific to the old C implementation + // there is no documentation about their meaning + int i, r; + + std::function put_char_cbk; + std::function get_char_cbk; + + inline void putc(const uint8_t c) { if(put_char_cbk) { put_char_cbk(c); } } + + // get the number of bits the FSM will require given its state + uint8_t bits_required(FSM_STATES s); +}; \ No newline at end of file From a3747d3ed4274e90ad2c0a7b625e945e77c311a9 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 15 Apr 2024 12:20:22 +0200 Subject: [PATCH 572/780] removed FlashSHA256.h --- src/utility/ota/FlashSHA256.cpp | 110 -------------------------------- src/utility/ota/FlashSHA256.h | 51 --------------- 2 files changed, 161 deletions(-) delete mode 100644 src/utility/ota/FlashSHA256.cpp delete mode 100644 src/utility/ota/FlashSHA256.h diff --git a/src/utility/ota/FlashSHA256.cpp b/src/utility/ota/FlashSHA256.cpp deleted file mode 100644 index d0fc3d532..000000000 --- a/src/utility/ota/FlashSHA256.cpp +++ /dev/null @@ -1,110 +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 -#if OTA_ENABLED - -#include "FlashSHA256.h" - -#include "../../tls/utility/SHA256.h" - -#include - -#undef max -#undef min -#include - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -String FlashSHA256::calc(uint32_t const start_addr, uint32_t const max_flash_size) -{ - SHA256 sha256; - uint8_t chunk [FLASH_READ_CHUNK_SIZE], - next_chunk[FLASH_READ_CHUNK_SIZE]; - - sha256.begin(); - - /* Read the first two chunks of flash. */ - uint32_t flash_addr = start_addr; - uint32_t bytes_read = 0; - memcpy(chunk, reinterpret_cast(flash_addr), FLASH_READ_CHUNK_SIZE); - flash_addr += FLASH_READ_CHUNK_SIZE; - - for(; bytes_read < max_flash_size; flash_addr += FLASH_READ_CHUNK_SIZE) - { - /* Read the next chunk of memory. */ - memcpy(next_chunk, reinterpret_cast(flash_addr), FLASH_READ_CHUNK_SIZE); - - /* Check if the next segment is erased, that is if all bytes within - * a read segment are 0xFF -> then we've reached the end of the firmware. - */ - bool const next_chunk_is_erased_flash = std::all_of(next_chunk, - next_chunk+FLASH_READ_CHUNK_SIZE, - [](uint8_t const elem) { return (elem == 0xFF); }); - /* Determine how many bytes at the end of the current chunk are - * already set to 0xFF and therefore erased/non-written flash - * memory. - */ - if (next_chunk_is_erased_flash) - { - /* Eliminate trailing 0xFF. */ - size_t valid_bytes_in_chunk = 0; - for(valid_bytes_in_chunk = FLASH_READ_CHUNK_SIZE; valid_bytes_in_chunk > 0; valid_bytes_in_chunk--) - { - if (chunk[valid_bytes_in_chunk-1] != 0xFF) - break; - } - /* Update with the remaining bytes. */ - sha256.update(chunk, valid_bytes_in_chunk); - bytes_read += valid_bytes_in_chunk; - break; - } - - /* We've read a normal segment with the next segment not containing - * any erased elements, just update the SHA256 hash calculation. - */ - sha256.update(chunk, FLASH_READ_CHUNK_SIZE); - bytes_read += FLASH_READ_CHUNK_SIZE; - - /* Copy next_chunk to chunk. */ - memcpy(chunk, next_chunk, FLASH_READ_CHUNK_SIZE); - } - - /* Retrieve the final hash string. */ - uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; - sha256.finalize(sha256_hash); - String sha256_str; - std::for_each(sha256_hash, - sha256_hash + SHA256::HASH_SIZE, - [&sha256_str](uint8_t const elem) - { - char buf[4]; - snprintf(buf, 4, "%02X", elem); - sha256_str += buf; - }); - /* Do some debug printout. */ - DEBUG_VERBOSE("SHA256: %d bytes read", bytes_read); - return sha256_str; -} - -#endif /* OTA_ENABLED */ diff --git a/src/utility/ota/FlashSHA256.h b/src/utility/ota/FlashSHA256.h deleted file mode 100644 index a3125f717..000000000 --- a/src/utility/ota/FlashSHA256.h +++ /dev/null @@ -1,51 +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_FLASH_SHA256_H_ -#define ARDUINO_OTA_FLASH_SHA256_H_ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include -#if OTA_ENABLED - -#include - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class FlashSHA256 -{ -public: - - static String calc(uint32_t const start_addr, uint32_t const max_flash_size); - -private: - - FlashSHA256() { } - FlashSHA256(FlashSHA256 const &) { } - - static constexpr uint32_t FLASH_READ_CHUNK_SIZE = 64; - -}; - -#endif /* OTA_ENABLED */ - -#endif /* ARDUINO_OTA_FLASH_SHA256_H_ */ From f843fd06f53fcc6e5f40f88610a3852aaf2cce8e Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 15 Apr 2024 12:20:57 +0200 Subject: [PATCH 573/780] adjusting OTA.h --- src/ota/OTA.h | 60 +++++++++++++++++++++++++++++++++ src/ota/OTAConfig.h | 47 ++++++++++++++++++++++++++ src/ota/OTATypes.h | 78 +++++++++++++++++++++++++++++++++++++++++++ src/utility/ota/OTA.h | 64 ----------------------------------- 4 files changed, 185 insertions(+), 64 deletions(-) create mode 100644 src/ota/OTA.h create mode 100644 src/ota/OTAConfig.h create mode 100644 src/ota/OTATypes.h delete mode 100644 src/utility/ota/OTA.h diff --git a/src/ota/OTA.h b/src/ota/OTA.h new file mode 100644 index 000000000..c1a56194a --- /dev/null +++ b/src/ota/OTA.h @@ -0,0 +1,60 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once +#include "AIoTC_Config.h" +#if OTA_ENABLED + +#include "OTAConfig.h" +#ifdef ARDUINO_ARCH_SAMD + +#include "implementation/OTASamd.h" +using ArduinoCloudOTA = SAMDOTACloudProcess; + +// TODO Check if a macro already exist +// constexpr uint32_t OtaMagicNumber = 0x23418054; // MKR_WIFI_1010 +constexpr uint32_t OtaMagicNumber = 0x23418057; // NANO_33_IOT + +#elif defined(ARDUINO_NANO_RP2040_CONNECT) +#include "implementation/OTANanoRP2040.h" +using ArduinoCloudOTA = NANO_RP2040OTACloudProcess; + +// TODO Check if a macro already exist +constexpr uint32_t OtaMagicNumber = 0x2341005E; // TODO check this value is correct + +#elif defined(BOARD_STM32H7) +#include "implementation/OTASTM32H7.h" +using ArduinoCloudOTA = STM32H7OTACloudProcess; + +constexpr uint32_t OtaMagicNumber = ARDUINO_PORTENTA_OTA_MAGIC; + +#elif defined(ARDUINO_ARCH_ESP32) +#include "implementation/OTAEsp32.h" +using ArduinoCloudOTA = ESP32OTACloudProcess; + +#if defined (ARDUINO_NANO_ESP32) + constexpr uint32_t OtaMagicNumber = 0x23410070; +#else + constexpr uint32_t OtaMagicNumber = 0x45535033; +#endif + +#elif defined(ARDUINO_UNOR4_WIFI) + +#include "implementation/OTAUnoR4.h" +using ArduinoCloudOTA = UNOR4OTACloudProcess; + +// TODO Check if a macro already exist +constexpr uint32_t OtaMagicNumber = 0x234110020; // TODO check this value is correct + +#else +#error "This Board doesn't support OTA" +#endif + +#endif // OTA_ENABLED diff --git a/src/ota/OTAConfig.h b/src/ota/OTAConfig.h new file mode 100644 index 000000000..71f78d00e --- /dev/null +++ b/src/ota/OTAConfig.h @@ -0,0 +1,47 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +#ifdef ARDUINO_ARCH_SAMD +#define OFFLOADED_DOWNLOAD + +#elif defined(ARDUINO_NANO_RP2040_CONNECT) + +#elif defined(BOARD_STM32H7) + +#if defined(ARDUINO_PORTENTA_H7_M7) + #define ARDUINO_PORTENTA_OTA_MAGIC 0x2341025b + #define ARDUINO_PORTENTA_OTA_SDMMC_SUPPORT + #define ARDUINO_PORTENTA_OTA_QSPI_SUPPORT +#endif + +#if defined(ARDUINO_NICLA_VISION) + #define ARDUINO_PORTENTA_OTA_MAGIC 0x2341025f + #define ARDUINO_PORTENTA_OTA_QSPI_SUPPORT +#endif + +#if defined(ARDUINO_OPTA) + #define ARDUINO_PORTENTA_OTA_MAGIC 0x23410064 + #define ARDUINO_PORTENTA_OTA_QSPI_SUPPORT +#endif + +#if defined(ARDUINO_GIGA) + #define ARDUINO_PORTENTA_OTA_MAGIC 0x23410266 + #define ARDUINO_PORTENTA_OTA_QSPI_SUPPORT +#endif + + +#elif defined(ARDUINO_ARCH_ESP32) +#define OTA_BASIC_AUTH + +#elif defined(ARDUINO_UNOR4_WIFI) +#define OFFLOADED_DOWNLOAD +#endif diff --git a/src/ota/OTATypes.h b/src/ota/OTATypes.h new file mode 100644 index 000000000..409b9154d --- /dev/null +++ b/src/ota/OTATypes.h @@ -0,0 +1,78 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +#include "AIoTC_Config.h" + +#if OTA_ENABLED +#include + +namespace ota { + enum class OTAError : int16_t { + None = 0, + NoCapableBootloader = -1, + NoOtaStorage = -2, + OtaStorageInit = -3, + OtaStorageOpen = -4, + OtaHeaderLength = -5, + OtaHeaderCrc = -6, + OtaHeaterMagicNumber = -7, + ParseHttpHeader = -8, + UrlParseError = -9, + ServerConnectError = -10, + HttpHeaderError = -11, + OtaDownload = -12, + OtaHeaderTimeout = -13, + HttpResponse = -14, + OtaStorageEnd = -15, + StorageConfig = -16, + Library = -17, + Modem = -18, + ErrorOpenUpdateFile = -19, + ErrorWriteUpdateFile = -20, + ErrorReformat = -21, + ErrorUnmount = -22, + ErrorRename = -23, + CaStorageInit = -24, + CaStorageOpen = -25, + }; + +#ifndef OFFLOADED_DOWNLOAD + union HeaderVersion { + struct __attribute__((packed)) { + uint32_t header_version : 6; + uint32_t compression : 1; + uint32_t signature : 1; + uint32_t spare : 4; + uint32_t payload_target : 4; + uint32_t payload_major : 8; + uint32_t payload_minor : 8; + uint32_t payload_patch : 8; + uint32_t payload_build_num : 24; + } field; + uint8_t buf[sizeof(field)]; + static_assert(sizeof(buf) == 8, "Error: sizeof(HEADER.VERSION) != 8"); + }; + + union OTAHeader { + struct __attribute__((packed)) { + uint32_t len; + uint32_t crc32; + uint32_t magic_number; + HeaderVersion hdr_version; + } header; + uint8_t buf[sizeof(header)]; + static_assert(sizeof(buf) == 20, "Error: sizeof(HEADER) != 20"); + }; +#endif // OFFLOADED_DOWNLOAD +} + +#endif // OTA_ENABLED diff --git a/src/utility/ota/OTA.h b/src/utility/ota/OTA.h deleted file mode 100644 index f8d5fcfdd..000000000 --- a/src/utility/ota/OTA.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -#pragma once -#include "AIoTC_Config.h" -#if OTA_ENABLED - -#ifdef ARDUINO_ARCH_SAMD -#include "OTASamd.h" -using OTACloudProcess = SAMDOTACloudProcess; - -#elif defined(ARDUINO_NANO_RP2040_CONNECT) -#include "OTANanoRP2040.h" -using OTACloudProcess = NANO_RP2040OTACloudProcess; - -#elif defined(BOARD_STM32H7) -#include "OTAPortentaH7.h" -using OTACloudProcess = STM32H7OTACloudProcess; - -#elif defined(ARDUINO_ARCH_ESP32) -#include "OTAEsp32.h" -using OTACloudProcess = ESP32OTACloudProcess; - - -#if defined (ARDUINO_NANO_ESP32) - constexpr uint32_t OtaMagicNumber = 0x23410070; -#else - constexpr uint32_t OtaMagicNumber = 0x45535033; -#endif - -#elif defined(ARDUINO_UNOR4_WIFI) -#include "OTAUnoR4.h" -using OTACloudProcess = UNOR4OTACloudProcess; - -#else -#error "This Board doesn't support OTA" -#endif - -#define RP2040_OTA_ERROR_BASE (-100) - -enum class OTAError : int -{ - None = 0, - DownloadFailed = 1, - RP2040_UrlParseError = RP2040_OTA_ERROR_BASE - 0, - RP2040_ServerConnectError = RP2040_OTA_ERROR_BASE - 1, - RP2040_HttpHeaderError = RP2040_OTA_ERROR_BASE - 2, - RP2040_HttpDataError = RP2040_OTA_ERROR_BASE - 3, - RP2040_ErrorOpenUpdateFile = RP2040_OTA_ERROR_BASE - 4, - RP2040_ErrorWriteUpdateFile = RP2040_OTA_ERROR_BASE - 5, - RP2040_ErrorParseHttpHeader = RP2040_OTA_ERROR_BASE - 6, - RP2040_ErrorFlashInit = RP2040_OTA_ERROR_BASE - 7, - RP2040_ErrorReformat = RP2040_OTA_ERROR_BASE - 8, - RP2040_ErrorUnmount = RP2040_OTA_ERROR_BASE - 9, -}; - -#endif // OTA_ENABLED From 9e24711fd6cce37a1553e12b35a84a611a9a3f66 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 15 Apr 2024 12:21:31 +0200 Subject: [PATCH 574/780] defining OTAInterface --- src/ota/interface/OTAInterface.cpp | 235 ++++++++++++++++++ src/ota/interface/OTAInterface.h | 185 ++++++++++++++ src/ota/interface/OTAInterfaceDefault.cpp | 283 ++++++++++++++++++++++ src/ota/interface/OTAInterfaceDefault.h | 82 +++++++ 4 files changed, 785 insertions(+) create mode 100644 src/ota/interface/OTAInterface.cpp create mode 100644 src/ota/interface/OTAInterface.h create mode 100644 src/ota/interface/OTAInterfaceDefault.cpp create mode 100644 src/ota/interface/OTAInterfaceDefault.h diff --git a/src/ota/interface/OTAInterface.cpp b/src/ota/interface/OTAInterface.cpp new file mode 100644 index 000000000..b659917b0 --- /dev/null +++ b/src/ota/interface/OTAInterface.cpp @@ -0,0 +1,235 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include + +#if OTA_ENABLED +#include "OTAInterface.h" +#include "../OTA.h" + +extern "C" unsigned long getTime(); + +/****************************************************************************** + * PUBLIC MEMBER FUNCTIONS + ******************************************************************************/ + +#ifdef DEBUG_VERBOSE +const char* const OTACloudProcessInterface::STATE_NAMES[] = { // used only for debug purposes + "Resume", + "OtaBegin", + "Idle", + "OtaAvailable", + "StartOTA", + "Fetch", + "FlashOTA", + "Reboot", + "Fail", + "NoCapableBootloaderFail", + "NoOtaStorageFail", + "OtaStorageInitFail", + "OtaStorageOpenFail", + "OtaHeaderLengthFail", + "OtaHeaderCrcFail", + "OtaHeaderMagicNumberFail", + "ParseHttpHeaderFail", + "UrlParseErrorFail", + "ServerConnectErrorFail", + "HttpHeaderErrorFail", + "OtaDownloadFail", + "OtaHeaderTimeoutFail", + "HttpResponseFail", + "OtaStorageEndFail", + "StorageConfigFail", + "LibraryFail", + "ModemFail", + "ErrorOpenUpdateFileFail", + "ErrorWriteUpdateFileFail", + "ErrorReformatFail", + "ErrorUnmountFail", + "ErrorRenameFail", +}; +#endif // DEBUG_VERBOSE + +OTACloudProcessInterface::OTACloudProcessInterface(MessageStream *ms) +: CloudProcess(ms) +, policies(None) +, state(Resume) +, previous_state(Resume) +, report_last_timestamp(0) +, report_counter(0) +, context(nullptr) { +} + +OTACloudProcessInterface::~OTACloudProcessInterface() { + clean(); +} + +void OTACloudProcessInterface::handleMessage(Message* msg) { + + if ((state >= OtaAvailable || state < 0) && previous_state != state) { + reportStatus(static_cast(state<0? state : 0)); + } + + // this allows to do status report only when the state changes + previous_state = state; + + switch(state) { + case Resume: updateState(resume(msg)); break; + case OtaBegin: updateState(otaBegin()); break; + case Idle: updateState(idle(msg)); break; + case OtaAvailable: updateState(otaAvailable()); break; + case StartOTA: updateState(startOTA()); break; + case Fetch: updateState(fetch()); break; + case FlashOTA: updateState(flashOTA()); break; + case Reboot: updateState(reboot()); break; + case OTAUnavailable: break; + default: updateState(fail()); // all the states that are not defined are failures + } +} + +OTACloudProcessInterface::State OTACloudProcessInterface::otaBegin() { + if(!isOtaCapable()) { + DEBUG_VERBOSE("OTA is not available on this board"); + return OTAUnavailable; + } + + struct OtaBeginUp msg = { + OtaBeginUpId, + }; + + SHA256 sha256_calc; + calculateSHA256(sha256_calc); + + sha256_calc.finalize(sha256); + memcpy(msg.params.sha, sha256, SHA256::HASH_SIZE); + + DEBUG_VERBOSE("calculated SHA256: " + "0x%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X" + "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", + sha256[0], sha256[1], sha256[2], sha256[3], sha256[4], sha256[5], sha256[6], sha256[7], + sha256[8], sha256[9], sha256[10], sha256[11], sha256[12], sha256[13], sha256[14], sha256[15], + sha256[16], sha256[17], sha256[18], sha256[19], sha256[20], sha256[21], sha256[22], sha256[23], + sha256[24], sha256[25], sha256[26], sha256[27], sha256[28], sha256[29], sha256[30], sha256[31] + ); + + deliver((Message*)&msg); + + return Idle; +} + +void OTACloudProcessInterface::calculateSHA256(SHA256& sha256_calc) { + auto res = appFlashOpen(); + if(!res) { + // TODO return error + return; + } + + sha256_calc.begin(); + sha256_calc.update( + reinterpret_cast(appStartAddress()), + appSize()); + appFlashClose(); +} + +OTACloudProcessInterface::State OTACloudProcessInterface::idle(Message* msg) { + // if a msg arrived, it may be an OTAavailable, then go to otaAvailable + // otherwise do nothing + if(msg!=nullptr && msg->id == OtaUpdateCmdDownId) { + // save info coming from this message + assert(context == nullptr); // This should never fail + + struct OtaUpdateCmdDown* ota_msg = (struct OtaUpdateCmdDown*)msg; + + context = new OtaContext( + ota_msg->params.id, ota_msg->params.url, + ota_msg->params.initialSha256, ota_msg->params.finalSha256 + ); + + // TODO verify that initialSha256 is the sha256 on board + // TODO verify that final sha is not the current sha256 (?) + return OtaAvailable; + } + + return Idle; +} + +OTACloudProcessInterface::State OTACloudProcessInterface::otaAvailable() { + // depending on the policy decided on this device the ota process can start immediately + // or wait for confirmation from the user + if((policies & (ApprovalRequired | Approved)) == ApprovalRequired ) { + return OtaAvailable; + } else { + policies &= ~Approved; + return StartOTA; + } // TODO add an abortOTA command? in this case delete the context +} + +OTACloudProcessInterface::State OTACloudProcessInterface::fail() { + reset(); + clean(); + + return Idle; +} + +void OTACloudProcessInterface::clean() { + // free the context pointer + if(context != nullptr) { + delete context; + context = nullptr; + } +} + +void OTACloudProcessInterface::reportStatus(int32_t state_data) { + if(context == nullptr) { + // FIXME handle this case: ota not in progress + return; + } + uint32_t new_timestamp = getTime(); + + struct OtaProgressCmdUp msg = { + OtaProgressCmdUpId, + }; + + memcpy(msg.params.id, context->id, ID_SIZE); + msg.params.state = state>=0 ? state : State::Fail; + + if(new_timestamp == report_last_timestamp) { + msg.params.time = new_timestamp*1e6 + ++report_counter; + } else { + msg.params.time = new_timestamp*1e6; + report_counter = 0; + report_last_timestamp = new_timestamp; + } + + msg.params.state_data = state_data; + + deliver((Message*)&msg); +} + +OTACloudProcessInterface::OtaContext::OtaContext( + uint8_t id[ID_SIZE], const char* url, + uint8_t* initialSha256, uint8_t* finalSha256 + ) : url(http://github.com/(char*) malloc(strlen(url) + 1)) { + + memcpy(this->id, id, ID_SIZE); + strcpy(this->url, url); + memcpy(this->initialSha256, initialSha256, 32); + memcpy(this->finalSha256, finalSha256, 32); +} + +OTACloudProcessInterface::OtaContext::~OtaContext() { + free(url); +} + +#endif /* OTA_ENABLED */ diff --git a/src/ota/interface/OTAInterface.h b/src/ota/interface/OTAInterface.h new file mode 100644 index 000000000..a62b7cb21 --- /dev/null +++ b/src/ota/interface/OTAInterface.h @@ -0,0 +1,185 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include + +#if OTA_ENABLED +#include "../OTATypes.h" +#include "tls/utility/SHA256.h" + +#include +#include + +/****************************************************************************** + * CLASS DECLARATION + ******************************************************************************/ + +class OTACloudProcessInterface: public CloudProcess { +public: + OTACloudProcessInterface(MessageStream *ms); + + virtual ~OTACloudProcessInterface(); + + enum State: int16_t { + Resume = 0, + OtaBegin = 1, + Idle = 2, + OtaAvailable = 3, + StartOTA = 4, + Fetch = 5, + FlashOTA = 6, + Reboot = 7, + Fail = 8, + OTAUnavailable = 9, + + // Error states that may generically happen on all board + NoCapableBootloaderFail = static_cast(ota::OTAError::NoCapableBootloader), + NoOtaStorageFail = static_cast(ota::OTAError::NoOtaStorage), + OtaStorageInitFail = static_cast(ota::OTAError::OtaStorageInit), + OtaStorageOpenFail = static_cast(ota::OTAError::OtaStorageOpen), + OtaHeaderLengthFail = static_cast(ota::OTAError::OtaHeaderLength), + OtaHeaderCrcFail = static_cast(ota::OTAError::OtaHeaderCrc), + OtaHeaderMagicNumberFail = static_cast(ota::OTAError::OtaHeaterMagicNumber), + ParseHttpHeaderFail = static_cast(ota::OTAError::ParseHttpHeader), + UrlParseErrorFail = static_cast(ota::OTAError::UrlParseError), + ServerConnectErrorFail = static_cast(ota::OTAError::ServerConnectError), + HttpHeaderErrorFail = static_cast(ota::OTAError::HttpHeaderError), + OtaDownloadFail = static_cast(ota::OTAError::OtaDownload), + OtaHeaderTimeoutFail = static_cast(ota::OTAError::OtaHeaderTimeout), + HttpResponseFail = static_cast(ota::OTAError::HttpResponse), + OtaStorageEndFail = static_cast(ota::OTAError::OtaStorageEnd), + StorageConfigFail = static_cast(ota::OTAError::StorageConfig), + LibraryFail = static_cast(ota::OTAError::Library), + ModemFail = static_cast(ota::OTAError::Modem), + ErrorOpenUpdateFileFail = static_cast(ota::OTAError::ErrorOpenUpdateFile), // FIXME fopen + ErrorWriteUpdateFileFail = static_cast(ota::OTAError::ErrorWriteUpdateFile), // FIXME fwrite + ErrorReformatFail = static_cast(ota::OTAError::ErrorReformat), + ErrorUnmountFail = static_cast(ota::OTAError::ErrorUnmount), + ErrorRenameFail = static_cast(ota::OTAError::ErrorRename), + CaStorageInitFail = static_cast(ota::OTAError::CaStorageInit), + CaStorageOpenFail = static_cast(ota::OTAError::CaStorageOpen), + }; + +#ifdef DEBUG_VERBOSE + static const char* const STATE_NAMES[]; +#endif // DEBUG_VERBOSE + + enum OtaFlags: uint16_t { + None = 0, + ApprovalRequired = 1, + Approved = 1<<1 + }; + + virtual void handleMessage(Message*); + // virtual CloudProcess::State getState(); + // virtual void hook(State s, void* action); + virtual void update() { handleMessage(nullptr); } + + inline void approveOta() { policies |= Approved; } + inline void setOtaPolicies(uint16_t policies) { this->policies = policies; } + + inline State getState() { return state; } + + virtual bool isOtaCapable() = 0; +protected: + // The following methods represent the FSM actions performed in each state + + // the first state is 'resume', where we try to understand if we are booting after a ota + // the objective is to understand the result and report it to the cloud + virtual State resume(Message* msg=nullptr) = 0; + + // This state is used to send to the cloud the initial information on the fw present on the mcu + // this state will only send the sha256 of the board fw and go into Idle state + virtual State otaBegin(); + + // this state is the normal state where no action has to be performed. We may poll the cloud + // for updates in this state + virtual State idle(Message* msg=nullptr); + + // we go in this state if there is an ota available, depending on the policies implemented we may + // start the ota or wait for an user interaction + virtual State otaAvailable(); + + // we start the process of ota update and wait for the server to respond with the ota url and other info + virtual State startOTA() = 0; + + // we start the download and decompress process + virtual State fetch() = 0; + + // whene the download is correctly finished we set the mcu to use the newly downloaded binary + virtual State flashOTA() = 0; + + // we reboot the device + virtual State reboot() = 0; + + // if any of the steps described fail we get into this state and report to the cloud what happened + // then we go back to idle state + virtual State fail(); + + virtual void reset() = 0; + + uint16_t policies; + + inline void updateState(State s) { + if(state!=s) { + DEBUG_VERBOSE("OTAInterface: state change to %s from %s", + STATE_NAMES[s < 0? Fail - s : s], + STATE_NAMES[state < 0? Fail - state : state]); + previous_state = state; state = s; + } + } + + // This method is called to report the current state of the OtaClass + void reportStatus(int32_t state_data); + + // in order to calculate the SHA256 we need to get the start and end address of the Application, + // The Implementation of this class have to implement them. + // The calculation is performed during the otaBegin phase + virtual void* appStartAddress() = 0; + virtual uint32_t appSize() = 0; + + // some architecture require to explicitly open the flash in order to read it + virtual bool appFlashOpen() = 0; + virtual bool appFlashClose() = 0; + + // sha256 is going to be used in the ota process for validation, avoid calculating it twice + uint8_t sha256[SHA256::HASH_SIZE]; + + // calculateSHA256 method is overridable for platforms that do not support access through pointer to program memory + virtual void calculateSHA256(SHA256&); // FIXME return error +private: + void clean(); + + State state, previous_state; + + // status report related attributes + uint32_t report_last_timestamp, report_counter; +protected: + struct OtaContext { + OtaContext( + uint8_t id[ID_SIZE], const char* url, + uint8_t initialSha256[32], uint8_t finalSha256[32]); + ~OtaContext(); + + // parameters present in the ota available message that are of interest of the process + uint8_t id[ID_SIZE]; + char* const url; + uint8_t initialSha256[32]; + uint8_t finalSha256[32]; + } *context; +}; + +#endif // OTA_ENABLED diff --git a/src/ota/interface/OTAInterfaceDefault.cpp b/src/ota/interface/OTAInterfaceDefault.cpp new file mode 100644 index 000000000..de698e660 --- /dev/null +++ b/src/ota/interface/OTAInterfaceDefault.cpp @@ -0,0 +1,283 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ +#include + +#if OTA_ENABLED && ! defined(OFFLOADED_DOWNLOAD) +#include "OTAInterfaceDefault.h" +#include "../OTA.h" + +static uint32_t crc_update(uint32_t crc, const void * data, size_t data_len); + +OTADefaultCloudProcessInterface::OTADefaultCloudProcessInterface(MessageStream *ms, Client* client) +: OTACloudProcessInterface(ms) +, client(client) +, http_client(nullptr) +, username(nullptr), password(nullptr) +, context(nullptr) { +} + +OTADefaultCloudProcessInterface::~OTADefaultCloudProcessInterface() { + reset(); +} + +OTACloudProcessInterface::State OTADefaultCloudProcessInterface::startOTA() { + assert(client != nullptr); + assert(OTACloudProcessInterface::context != nullptr); + assert(context == nullptr); + + context = new Context( + OTACloudProcessInterface::context->url, + [this](uint8_t c) { + // int res = + this->writeFlash(&c, 1); + + // TODO report error in write flash, throw it? + } + ); + + // make the http get request + if(strcmp(context->parsed_url.schema(), "https") == 0) { + http_client = new HttpClient(*client, context->parsed_url.host(), context->parsed_url.port()); + } else { + return UrlParseErrorFail; + } + + http_client->beginRequest(); + auto res = http_client->get(context->parsed_url.path()); + + if(username != nullptr && password != nullptr) { + http_client->sendBasicAuth(username, password); + } + + http_client->endRequest(); + + if(res == HTTP_ERROR_CONNECTION_FAILED) { + DEBUG_VERBOSE("OTA ERROR: http client error connecting to server \"%s:%d\"", + context->parsed_url.host(), context->parsed_url.port()); + return ServerConnectErrorFail; + } else if(res == HTTP_ERROR_TIMED_OUT) { + DEBUG_VERBOSE("OTA ERROR: http client timeout \"%s\"", OTACloudProcessInterface::context->url); + return OtaHeaderTimeoutFail; + } else if(res != HTTP_SUCCESS) { + DEBUG_VERBOSE("OTA ERROR: http client returned %d on get \"%s\"", res, OTACloudProcessInterface::context->url); + return OtaDownloadFail; + } + + int statusCode = http_client->responseStatusCode(); + + if(statusCode != 200) { + DEBUG_VERBOSE("OTA ERROR: get response on \"%s\" returned status %d", OTACloudProcessInterface::context->url, statusCode); + return HttpResponseFail; + } + + // The following call is required to save the header value , keep it + if(http_client->contentLength() == HttpClient::kNoContentLengthHeader) { + DEBUG_VERBOSE("OTA ERROR: the response header doesn't contain \"ContentLength\" field"); + return HttpHeaderErrorFail; + } + + context->lastReportTime = millis(); + + return Fetch; +} + +OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetch() { + OTACloudProcessInterface::State res = Fetch; + int http_res = 0; + + if(http_client->available() == 0) { + goto exit; + } + + http_res = http_client->read(context->buffer, context->buf_len); + + if(http_res < 0) { + DEBUG_VERBOSE("OTA ERROR: Download read error %d", http_res); + res = OtaDownloadFail; + goto exit; + } + + parseOta(context->buffer, http_res); + + // TODO verify that the information present in the ota header match the info in context + if(context->downloadState == OtaDownloadCompleted) { + // Verify that the downloaded file size is matching the expected size ?? + // this could distinguish between consistency of the downloaded bytes and filesize + + // validate CRC + context->calculatedCrc32 ^= 0xFFFFFFFF; // finalize CRC + if(context->header.header.crc32 == context->calculatedCrc32) { + DEBUG_VERBOSE("Ota download completed successfully"); + res = FlashOTA; + } else { + res = OtaHeaderCrcFail; + } + } else if(context->downloadState == OtaDownloadError) { + DEBUG_VERBOSE("OTA ERROR: OtaDownloadError"); + + res = OtaDownloadFail; + } else if(context->downloadState == OtaDownloadMagicNumberMismatch) { + DEBUG_VERBOSE("OTA ERROR: Magic number mismatch"); + res = OtaHeaderMagicNumberFail; + } + +exit: + if(res != Fetch) { + http_client->stop(); // close the connection + delete http_client; + http_client = nullptr; + } + return res; +} + +void OTADefaultCloudProcessInterface::parseOta(uint8_t* buffer, size_t buf_len) { + assert(context != nullptr); // This should never fail + + for(uint8_t* cursor=(uint8_t*)buffer; cursordownloadState) { + case OtaDownloadHeader: { + uint32_t copied = buf_len < sizeof(context->header.buf) ? buf_len : sizeof(context->header.buf); + memcpy(context->header.buf+context->headerCopiedBytes, buffer, copied); + cursor += copied; + context->headerCopiedBytes += copied; + + // when finished go to next state + if(sizeof(context->header.buf) == context->headerCopiedBytes) { + context->downloadState = OtaDownloadFile; + + context->calculatedCrc32 = crc_update( + context->calculatedCrc32, + &(context->header.header.magic_number), + sizeof(context->header) - offsetof(ota::OTAHeader, header.magic_number) + ); + + if(context->header.header.magic_number != OtaMagicNumber) { + context->downloadState = OtaDownloadMagicNumberMismatch; + return; + } + } + + break; + } + case OtaDownloadFile: + context->decoder.decompress(cursor, buf_len - (cursor-buffer)); // TODO verify return value + + context->calculatedCrc32 = crc_update( + context->calculatedCrc32, + cursor, + buf_len - (cursor-buffer) + ); + + cursor += buf_len - (cursor-buffer); + context->downloadedSize += (cursor-buffer); + + if((millis() - context->lastReportTime) > 2000) { // Report the download progress each X millisecond + DEBUG_VERBOSE("OTA Download Progress %d/%d", context->downloadedSize, http_client->contentLength()); + + // FIXME the following line enables the report for download progress, it breaks + // reportStatus(context->downloadedSize); + context->lastReportTime = millis(); + } + + // TODO there should be no more bytes available when the download is completed + if(context->downloadedSize == http_client->contentLength()) { + context->downloadState = OtaDownloadCompleted; + } + + if(context->downloadedSize > http_client->contentLength()) { + context->downloadState = OtaDownloadError; + } + // TODO fail if we exceed a timeout? and available is 0 (client is broken) + break; + case OtaDownloadCompleted: + return; + default: + context->downloadState = OtaDownloadError; + return; + } + } +} + +void OTADefaultCloudProcessInterface::reset() { + if(http_client != nullptr) { + http_client->stop(); // close the connection + delete http_client; + http_client = nullptr; + } + + if(client!=nullptr && client->connected()) { + client->stop(); + } + + // free the context pointer + if(context != nullptr) { + delete context; + context = nullptr; + } +} + +OTADefaultCloudProcessInterface::Context::Context( + const char* url, std::function putc) + : parsed_http://github.com/url(url) + , downloadState(OtaDownloadHeader) + , calculatedCrc32(0xFFFFFFFF) + , headerCopiedBytes(0) + , downloadedSize(0) + , lastReportTime(0) + , decoder(putc) { } + +static const uint32_t crc_table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +uint32_t crc_update(uint32_t crc, const void * data, size_t data_len) { + const unsigned char *d = (const unsigned char *)data; + unsigned int tbl_idx; + + while (data_len--) { + tbl_idx = (crc ^ *d) & 0xff; + crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff; + d++; + } + + return crc & 0xffffffff; +} +#endif /* OTA_ENABLED && ! defined(OFFLOADED_DOWNLOAD) */ diff --git a/src/ota/interface/OTAInterfaceDefault.h b/src/ota/interface/OTAInterfaceDefault.h new file mode 100644 index 000000000..ae68d53bc --- /dev/null +++ b/src/ota/interface/OTAInterfaceDefault.h @@ -0,0 +1,82 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ +#pragma once + +#include + +#if OTA_ENABLED && ! defined(OFFLOADED_DOWNLOAD) +#include + +#include +#include +#include "utility/lzss/lzss.h" +#include "OTAInterface.h" + +/** + * This class is the extension of the abstract class for OTA, with the addition that + * the download is performed by the mcu itself and not offloaded to the network peripheral + */ +class OTADefaultCloudProcessInterface: public OTACloudProcessInterface { +public: + OTADefaultCloudProcessInterface(MessageStream *ms, Client* client=nullptr); + ~OTADefaultCloudProcessInterface(); + + inline virtual void setClient(Client* c) { client = c; } + + void setAuthentication(const char* const username, const char* const password) { + this->username = username; + this->password = password; + } + +protected: + State startOTA(); + State fetch(); + void reset(); + virtual int writeFlash(uint8_t* const buffer, size_t len) = 0; + +private: + void parseOta(uint8_t* buffer, size_t buf_len); + + Client* client; + HttpClient* http_client; + + const char *username, *password; + + enum OTADownloadState: uint8_t { + OtaDownloadHeader, + OtaDownloadFile, + OtaDownloadCompleted, + OtaDownloadMagicNumberMismatch, + OtaDownloadError + }; + +protected: + struct Context { + Context( + const char* url, + std::function putc); + + ParsedUrl parsed_url; + ota::OTAHeader header; + OTADownloadState downloadState; + uint32_t calculatedCrc32; + uint32_t headerCopiedBytes; + uint32_t downloadedSize; + uint32_t lastReportTime; + + // LZSS decoder + LZSSDecoder decoder; + + const size_t buf_len = 64; + uint8_t buffer[64]; + } *context; +}; + +#endif /* OTA_ENABLED && ! defined(OFFLOADED_DOWNLOAD) */ From bbbbd604104c67f2e1b3e09ddebee0beeca55026 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 19 Mar 2024 10:52:32 +0100 Subject: [PATCH 575/780] BearSSLClient: allow configuration after object creation --- src/tls/BearSSLClient.cpp | 24 ++++++++++++++++++------ src/tls/BearSSLClient.h | 7 ++++++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/tls/BearSSLClient.cpp b/src/tls/BearSSLClient.cpp index cdc58794f..a92b42078 100644 --- a/src/tls/BearSSLClient.cpp +++ b/src/tls/BearSSLClient.cpp @@ -34,18 +34,30 @@ #include "BearSSLClient.h" -extern "C" void aiotc_client_profile_init(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); +bool BearSSLClient::_sslio_closing = false; +extern "C" void aiotc_client_profile_init(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); -bool BearSSLClient::_sslio_closing = false; +BearSSLClient::BearSSLClient() : + _noSNI(false), + _get_time_func(nullptr) +{ + _ecKey.curve = 0; + _ecKey.x = NULL; + _ecKey.xlen = 0; + _ecCert.data = NULL; + _ecCert.data_len = 0; + _ecCertDynamic = false; +} BearSSLClient::BearSSLClient(Client* client, const br_x509_trust_anchor* myTAs, int myNumTAs, GetTimeCallbackFunc func) : _client(client), _TAs(myTAs), _numTAs(myNumTAs), _noSNI(false), - _get_time_func(func) + _get_time_func(func), + _br_ssl_client_init_function(aiotc_client_profile_init) { assert(_get_time_func != nullptr); @@ -266,8 +278,8 @@ int BearSSLClient::connectSSL(const char* host) /* Ensure this flag is cleared so we don't terminate a just starting connection. */ _sslio_closing = false; - // initialize client context with all necessary algorithms and hardcoded trust anchors. - aiotc_client_profile_init(&_sc, &_xc, _TAs, _numTAs); + // initialize client context with enabled algorithms and trust anchors + _br_ssl_client_init_function(&_sc, &_xc, _TAs, _numTAs); br_ssl_engine_set_buffers_bidi(&_sc.eng, _ibuf, sizeof(_ibuf), _obuf, sizeof(_obuf)); @@ -278,7 +290,7 @@ int BearSSLClient::connectSSL(const char* host) // ECC508 random success, add custom ECDSA vfry and EC sign br_ssl_engine_set_ecdsa(&_sc.eng, eccX08_vrfy_asn1); br_x509_minimal_set_ecdsa(&_xc, br_ssl_engine_get_ec(&_sc.eng), br_ssl_engine_get_ecdsa(&_sc.eng)); - + // enable client auth using the ECCX08 if (_ecCert.data_len && _ecKey.xlen) { br_ssl_client_set_single_ec(&_sc, &_ecCert, 1, &_ecKey, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, BR_KEYTYPE_EC, br_ec_get_default(), eccX08_sign_asn1); diff --git a/src/tls/BearSSLClient.h b/src/tls/BearSSLClient.h index 457ef92f0..6ea64c714 100644 --- a/src/tls/BearSSLClient.h +++ b/src/tls/BearSSLClient.h @@ -48,11 +48,14 @@ class BearSSLClient : public Client { public: BearSSLClient(Client* client, const br_x509_trust_anchor* myTAs, int myNumTAs, GetTimeCallbackFunc func); + BearSSLClient(); virtual ~BearSSLClient(); inline void setClient(Client& client) { _client = &client; } - + inline void setProfile(void(*client_init_function)(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trustrust_anchorst_anchors_num)) { _br_ssl_client_init_function = client_init_function; } + inline void setTrustAnchors(const br_x509_trust_anchor* myTAs, int myNumTAs) { _TAs = myTAs; _numTAs = myNumTAs; } + inline void onGetTime(GetTimeCallbackFunc callback) { _get_time_func = callback;} virtual int connect(IPAddress ip, uint16_t port); virtual int connect(const char* host, uint16_t port); @@ -103,6 +106,8 @@ class BearSSLClient : public Client { unsigned char _ibuf[BEAR_SSL_CLIENT_IBUF_SIZE]; unsigned char _obuf[BEAR_SSL_CLIENT_OBUF_SIZE]; br_sslio_context _ioc; + + void (*_br_ssl_client_init_function)(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); }; #endif /* #ifdef BOARD_HAS_ECCX08 */ From a8a3bf30d31ed81efb3cf41fd5792f528517c2df Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 21 Feb 2024 17:28:04 +0100 Subject: [PATCH 576/780] renamed files containing implementation of OTA HAL functions --- src/utility/ota/{OTA-esp32.cpp => OTAEsp32.cpp} | 0 src/utility/ota/{OTA-nano-rp2040.cpp => OTANanoRP2040.cpp} | 0 src/utility/ota/{OTA-portenta-h7.cpp => OTAPortentaH7.cpp} | 0 src/utility/ota/{OTA-samd.cpp => OTASamd.cpp} | 0 src/utility/ota/{OTA-unor4.cpp => OTAUnoR4.cpp} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename src/utility/ota/{OTA-esp32.cpp => OTAEsp32.cpp} (100%) rename src/utility/ota/{OTA-nano-rp2040.cpp => OTANanoRP2040.cpp} (100%) rename src/utility/ota/{OTA-portenta-h7.cpp => OTAPortentaH7.cpp} (100%) rename src/utility/ota/{OTA-samd.cpp => OTASamd.cpp} (100%) rename src/utility/ota/{OTA-unor4.cpp => OTAUnoR4.cpp} (100%) diff --git a/src/utility/ota/OTA-esp32.cpp b/src/utility/ota/OTAEsp32.cpp similarity index 100% rename from src/utility/ota/OTA-esp32.cpp rename to src/utility/ota/OTAEsp32.cpp diff --git a/src/utility/ota/OTA-nano-rp2040.cpp b/src/utility/ota/OTANanoRP2040.cpp similarity index 100% rename from src/utility/ota/OTA-nano-rp2040.cpp rename to src/utility/ota/OTANanoRP2040.cpp diff --git a/src/utility/ota/OTA-portenta-h7.cpp b/src/utility/ota/OTAPortentaH7.cpp similarity index 100% rename from src/utility/ota/OTA-portenta-h7.cpp rename to src/utility/ota/OTAPortentaH7.cpp diff --git a/src/utility/ota/OTA-samd.cpp b/src/utility/ota/OTASamd.cpp similarity index 100% rename from src/utility/ota/OTA-samd.cpp rename to src/utility/ota/OTASamd.cpp diff --git a/src/utility/ota/OTA-unor4.cpp b/src/utility/ota/OTAUnoR4.cpp similarity index 100% rename from src/utility/ota/OTA-unor4.cpp rename to src/utility/ota/OTAUnoR4.cpp From 9731f86df40630e294d3a631c2407debdfa89a3d Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 16 Apr 2024 16:29:45 +0200 Subject: [PATCH 577/780] BearSSLClient: allow clients to stop independently making _sslio_closing not static anymore, so that we are able to stop bearsslclients independently from one another --- src/tls/BearSSLClient.cpp | 23 ++++++++++++----------- src/tls/BearSSLClient.h | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/tls/BearSSLClient.cpp b/src/tls/BearSSLClient.cpp index a92b42078..1ebd78653 100644 --- a/src/tls/BearSSLClient.cpp +++ b/src/tls/BearSSLClient.cpp @@ -34,13 +34,12 @@ #include "BearSSLClient.h" -bool BearSSLClient::_sslio_closing = false; - extern "C" void aiotc_client_profile_init(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); BearSSLClient::BearSSLClient() : _noSNI(false), - _get_time_func(nullptr) + _get_time_func(nullptr), + _sslio_closing(false) { _ecKey.curve = 0; _ecKey.x = NULL; @@ -172,7 +171,7 @@ void BearSSLClient::stop() { if (_client->connected()) { if ((br_ssl_engine_current_state(&_sc.eng) & BR_SSL_CLOSED) == 0) { - BearSSLClient::_sslio_closing = true; + _sslio_closing = true; br_sslio_close(&_ioc); } @@ -314,7 +313,7 @@ int BearSSLClient::connectSSL(const char* host) br_x509_minimal_set_time(&_xc, days, sec); // use our own socket I/O operations - br_sslio_init(&_ioc, &_sc.eng, BearSSLClient::clientRead, _client, BearSSLClient::clientWrite, _client); + br_sslio_init(&_ioc, &_sc.eng, BearSSLClient::clientRead, this, BearSSLClient::clientWrite, this); br_sslio_flush(&_ioc); @@ -335,12 +334,13 @@ int BearSSLClient::connectSSL(const char* host) int BearSSLClient::clientRead(void *ctx, unsigned char *buf, size_t len) { - if (BearSSLClient::_sslio_closing) { + BearSSLClient* bc = (BearSSLClient*)ctx; + Client* c = bc->_client; + + if(bc->_sslio_closing) { return -1; } - Client* c = (Client*)ctx; - if (!c->connected()) { return -1; } @@ -370,12 +370,13 @@ int BearSSLClient::clientRead(void *ctx, unsigned char *buf, size_t len) int BearSSLClient::clientWrite(void *ctx, const unsigned char *buf, size_t len) { - if (BearSSLClient::_sslio_closing) { + BearSSLClient* bc = (BearSSLClient*)ctx; + Client* c = bc->_client; + + if(bc->_sslio_closing) { return -1; } - Client* c = (Client*)ctx; - #ifdef DEBUGSERIAL DEBUGSERIAL.print("BearSSLClient::clientWrite - "); DEBUGSERIAL.print(len); diff --git a/src/tls/BearSSLClient.h b/src/tls/BearSSLClient.h index 6ea64c714..2979eebf4 100644 --- a/src/tls/BearSSLClient.h +++ b/src/tls/BearSSLClient.h @@ -100,7 +100,7 @@ class BearSSLClient : public Client { br_x509_certificate _ecCert; bool _ecCertDynamic; - static bool _sslio_closing; + bool _sslio_closing; br_ssl_client_context _sc; br_x509_minimal_context _xc; unsigned char _ibuf[BEAR_SSL_CLIENT_IBUF_SIZE]; From a6a2e2316aa7e47e54b895548c30766122196c90 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 4 Mar 2024 15:47:30 +0100 Subject: [PATCH 578/780] added stub implementation of OTA HAL classes --- src/ota/implementation/OTAEsp32.cpp | 3 + src/ota/implementation/OTAEsp32.h | 20 ++ src/ota/implementation/OTANanoRP2040.cpp | 4 + src/ota/implementation/OTANanoRP2040.h | 23 ++ src/ota/implementation/OTASTM32H7.h | 23 ++ src/ota/implementation/OTASTM32H7.ipp | 32 +++ src/ota/implementation/OTASamd.cpp | 4 + src/ota/implementation/OTASamd.h | 21 ++ src/ota/implementation/OTAUnoR4.cpp | 4 + src/ota/implementation/OTAUnoR4.h | 22 ++ src/utility/ota/OTAEsp32.cpp | 128 ----------- src/utility/ota/OTANanoRP2040.cpp | 266 ----------------------- src/utility/ota/OTAPortentaH7.cpp | 140 ------------ src/utility/ota/OTASamd.cpp | 97 --------- src/utility/ota/OTAUnoR4.cpp | 187 ---------------- 15 files changed, 156 insertions(+), 818 deletions(-) create mode 100644 src/ota/implementation/OTAEsp32.cpp create mode 100644 src/ota/implementation/OTAEsp32.h create mode 100644 src/ota/implementation/OTANanoRP2040.cpp create mode 100644 src/ota/implementation/OTANanoRP2040.h create mode 100644 src/ota/implementation/OTASTM32H7.h create mode 100644 src/ota/implementation/OTASTM32H7.ipp create mode 100644 src/ota/implementation/OTASamd.cpp create mode 100644 src/ota/implementation/OTASamd.h create mode 100644 src/ota/implementation/OTAUnoR4.cpp create mode 100644 src/ota/implementation/OTAUnoR4.h delete mode 100644 src/utility/ota/OTAEsp32.cpp delete mode 100644 src/utility/ota/OTANanoRP2040.cpp delete mode 100644 src/utility/ota/OTAPortentaH7.cpp delete mode 100644 src/utility/ota/OTASamd.cpp delete mode 100644 src/utility/ota/OTAUnoR4.cpp diff --git a/src/ota/implementation/OTAEsp32.cpp b/src/ota/implementation/OTAEsp32.cpp new file mode 100644 index 000000000..7ac036134 --- /dev/null +++ b/src/ota/implementation/OTAEsp32.cpp @@ -0,0 +1,3 @@ +#if defined(ARDUINO_ARCH_ESP32) && OTA_ENABLED + +#endif // defined(ARDUINO_ARCH_ESP32) && OTA_ENABLED \ No newline at end of file diff --git a/src/ota/implementation/OTAEsp32.h b/src/ota/implementation/OTAEsp32.h new file mode 100644 index 000000000..8654d2c7e --- /dev/null +++ b/src/ota/implementation/OTAEsp32.h @@ -0,0 +1,20 @@ +#pragma once + +#include "src/ota/interface/OTAInterface.h" + +class ESP32OTACloudProcess: public OTACloudProcessInterface { +public: + STM32H7OTACloudProcess(); +protected: + // we start the download and decompress process + virtual State fetch(Message* msg=nullptr); + + // when the download is completed we verify for integrity and correctness of the downloaded binary + // virtual State verifyOTA(Message* msg=nullptr); // TODO this may be performed inside download + + // whene the download is correctly finished we set the mcu to use the newly downloaded binary + virtual State flashOTA(Message* msg=nullptr); + + // we reboot the device + virtual State reboot(Message* msg=nullptr); +}; diff --git a/src/ota/implementation/OTANanoRP2040.cpp b/src/ota/implementation/OTANanoRP2040.cpp new file mode 100644 index 000000000..e0f6feb72 --- /dev/null +++ b/src/ota/implementation/OTANanoRP2040.cpp @@ -0,0 +1,4 @@ +#if defined(ARDUINO_NANO_RP2040_CONNECT) && OTA_ENABLED +#include "OTANanoRP2040.h" + +#endif // defined(ARDUINO_NANO_RP2040_CONNECT) && OTA_ENABLED \ No newline at end of file diff --git a/src/ota/implementation/OTANanoRP2040.h b/src/ota/implementation/OTANanoRP2040.h new file mode 100644 index 000000000..165bb1cea --- /dev/null +++ b/src/ota/implementation/OTANanoRP2040.h @@ -0,0 +1,23 @@ +#pragma once + +#include "src/ota/interface/OTAInterface.h" + +#include "FATFileSystem.h" +#include "FlashIAPBlockDevice.h" + +class NANO_RP2040OTACloudProcess: public OTACloudProcessInterface { +public: + STM32H7OTACloudProcess(); +protected: + // we start the download and decompress process + virtual State fetch(Message* msg=nullptr); + + // when the download is completed we verify for integrity and correctness of the downloaded binary + // virtual State verifyOTA(Message* msg=nullptr); // TODO this may be performed inside download + + // whene the download is correctly finished we set the mcu to use the newly downloaded binary + virtual State flashOTA(Message* msg=nullptr); + + // we reboot the device + virtual State reboot(Message* msg=nullptr); +}; diff --git a/src/ota/implementation/OTASTM32H7.h b/src/ota/implementation/OTASTM32H7.h new file mode 100644 index 000000000..455066e37 --- /dev/null +++ b/src/ota/implementation/OTASTM32H7.h @@ -0,0 +1,23 @@ +#pragma once + +#include "src/ota/interface/OTAInterface.h" + +class STM32H7OTACloudProcess: public OTACloudProcessInterface { +public: + STM32H7OTACloudProcess(); + void update(); + + // retrocompatibility functions used in old ota prtotocol based on properties + int otaRequest(char const * ota_url, NetworkAdapter iface); + String getOTAImageSHA256(); + bool isOTACapable(); +protected: + // we start the download and decompress process + virtual State fetch(Message* msg=nullptr); + + // whene the download is correctly finished we set the mcu to use the newly downloaded binary + virtual State flashOTA(Message* msg=nullptr); + + // we reboot the device + virtual State reboot(Message* msg=nullptr); +}; diff --git a/src/ota/implementation/OTASTM32H7.ipp b/src/ota/implementation/OTASTM32H7.ipp new file mode 100644 index 000000000..09093a30d --- /dev/null +++ b/src/ota/implementation/OTASTM32H7.ipp @@ -0,0 +1,32 @@ +#if defined(BOARD_STM32H7) && OTA_ENABLED +#include "OTAPortentaH7.h" + +STM32H7OTACloudProcess::STM32H7OTACloudProcess() {} + +void STM32H7OTACloudProcess::update() { + OTACloudProcessInterface::update(); + watchdog_reset(); +} + +State STM32H7OTACloudProcess::fetch(Message *msg) { + +} + +State STM32H7OTACloudProcess::flashOTA(Message *msg) { + /* Schedule the firmware update. */ + if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) { + DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::update() failed with %d", static_cast(ota_portenta_err)); + return static_cast(ota_portenta_err); + } +} + +State STM32H7OTACloudProcess::reboot(Message *msg) { + // TODO save information about the progress reached in the ota + + // This command reboots the mcu + NVIC_SystemReset(); + + return Resume; // This won't ever be reached +} + +#endif // defined(BOARD_STM32H7) && OTA_ENABLED \ No newline at end of file diff --git a/src/ota/implementation/OTASamd.cpp b/src/ota/implementation/OTASamd.cpp new file mode 100644 index 000000000..1dc307f46 --- /dev/null +++ b/src/ota/implementation/OTASamd.cpp @@ -0,0 +1,4 @@ +#if defined(ARDUINO_ARCH_SAMD) && OTA_ENABLED +#include "OTASamd.h" + +#endif // defined(ARDUINO_ARCH_SAMD) && OTA_ENABLED \ No newline at end of file diff --git a/src/ota/implementation/OTASamd.h b/src/ota/implementation/OTASamd.h new file mode 100644 index 000000000..3c248dd17 --- /dev/null +++ b/src/ota/implementation/OTASamd.h @@ -0,0 +1,21 @@ +#pragma once + +#include "src/ota/interface/OTAInterface.h" +#include + +class SAMDOTACloudProcess: public OTACloudProcessInterface { +public: + STM32H7OTACloudProcess(); +protected: + // we start the download and decompress process + virtual State fetch(Message* msg=nullptr); + + // when the download is completed we verify for integrity and correctness of the downloaded binary + // virtual State verifyOTA(Message* msg=nullptr); // TODO this may be performed inside download + + // whene the download is correctly finished we set the mcu to use the newly downloaded binary + virtual State flashOTA(Message* msg=nullptr); + + // we reboot the device + virtual State reboot(Message* msg=nullptr); +}; diff --git a/src/ota/implementation/OTAUnoR4.cpp b/src/ota/implementation/OTAUnoR4.cpp new file mode 100644 index 000000000..e44e7f65e --- /dev/null +++ b/src/ota/implementation/OTAUnoR4.cpp @@ -0,0 +1,4 @@ +#if defined(ARDUINO_UNOR4_WIFI) && OTA_ENABLED +#include "OTAUnoR4.h" + +#endif // defined(ARDUINO_UNOR4_WIFI) && OTA_ENABLED diff --git a/src/ota/implementation/OTAUnoR4.h b/src/ota/implementation/OTAUnoR4.h new file mode 100644 index 000000000..871ea58a8 --- /dev/null +++ b/src/ota/implementation/OTAUnoR4.h @@ -0,0 +1,22 @@ +#pragma once + +#include "src/ota/interface/OTAInterface.h" +#include "OTAUpdate.h" +#include "r_flash_lp.h" + +class UNOR4OTACloudProcess: public OTACloudProcessInterface { +public: + STM32H7OTACloudProcess(); +protected: + // we start the download and decompress process + virtual State fetch(Message* msg=nullptr); + + // when the download is completed we verify for integrity and correctness of the downloaded binary + // virtual State verifyOTA(Message* msg=nullptr); // TODO this may be performed inside download + + // whene the download is correctly finished we set the mcu to use the newly downloaded binary + virtual State flashOTA(Message* msg=nullptr); + + // we reboot the device + virtual State reboot(Message* msg=nullptr); +}; diff --git a/src/utility/ota/OTAEsp32.cpp b/src/utility/ota/OTAEsp32.cpp deleted file mode 100644 index 51065d1ba..000000000 --- a/src/utility/ota/OTAEsp32.cpp +++ /dev/null @@ -1,128 +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 - -#if defined ARDUINO_ARCH_ESP32 && OTA_ENABLED - -#include "OTA.h" -#include -#include -#include "tls/utility/SHA256.h" - -#include - -/****************************************************************************** - * FUNCTION DEFINITION - ******************************************************************************/ - -int esp32_onOTARequest(char const * ota_url) -{ - Arduino_ESP32_OTA::Error ota_err = Arduino_ESP32_OTA::Error::None; - Arduino_ESP32_OTA ota; - - /* Initialize the board for OTA handling. */ - if ((ota_err = ota.begin()) != Arduino_ESP32_OTA::Error::None) - { - DEBUG_ERROR("Arduino_ESP32_OTA::begin() failed with %d", static_cast(ota_err)); - return static_cast(ota_err); - } - - /* Download the OTA file from the web storage location. */ - int const ota_download = ota.download(ota_url); - if (ota_download <= 0) - { - DEBUG_ERROR("Arduino_ESP_OTA::download() failed with %d", ota_download); - return ota_download; - } - DEBUG_VERBOSE("Arduino_ESP_OTA::download() %d bytes downloaded", static_cast(ota_download)); - - /* Verify update integrity and apply */ - if ((ota_err = ota.update()) != Arduino_ESP32_OTA::Error::None) - { - DEBUG_ERROR("Arduino_ESP_OTA::update() failed with %d", static_cast(ota_err)); - return static_cast(ota_err); - } - - /* Perform the reset to reboot */ - ota.reset(); - - return static_cast(OTAError::None); -} - -String esp32_getOTAImageSHA256() -{ - const esp_partition_t *running = esp_ota_get_running_partition(); - if (!running) { - DEBUG_ERROR("ESP32::SHA256 Running partition could not be found"); - return String(); - } - - uint8_t *b = (uint8_t*)malloc(SPI_FLASH_SEC_SIZE); - if(b == nullptr) { - DEBUG_ERROR("ESP32::SHA256 Not enough memory to allocate buffer"); - return String(); - } - - SHA256 sha256; - uint32_t const app_start = running->address; - uint32_t const app_size = ESP.getSketchSize(); - uint32_t read_bytes = 0; - - sha256.begin(); - for(uint32_t a = app_start; read_bytes < app_size; ) - { - /* Check if we are reading last sector and compute used size */ - uint32_t const read_size = read_bytes + SPI_FLASH_SEC_SIZE < app_size ? SPI_FLASH_SEC_SIZE : app_size - read_bytes; - - /* Use always 4 bytes aligned reads */ - if (!ESP.flashRead(a, reinterpret_cast(b), (read_size + 3) & ~3)) { - DEBUG_ERROR("ESP32::SHA256 Could not read data from flash"); - return String(); - } - sha256.update(b, read_size); - a += read_size; - read_bytes += read_size; - } - free(b); - - /* Retrieve the final hash string. */ - uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; - sha256.finalize(sha256_hash); - String sha256_str; - std::for_each(sha256_hash, - sha256_hash + SHA256::HASH_SIZE, - [&sha256_str](uint8_t const elem) - { - char buf[4]; - snprintf(buf, 4, "%02X", elem); - sha256_str += buf; - }); - DEBUG_VERBOSE("SHA256: %d bytes (of %d) read", read_bytes, app_size); - return sha256_str; -} - -bool esp32_isOTACapable() -{ - return Arduino_ESP32_OTA::isCapable(); -} - -#endif /* ARDUINO_ARCH_ESP32 */ diff --git a/src/utility/ota/OTANanoRP2040.cpp b/src/utility/ota/OTANanoRP2040.cpp deleted file mode 100644 index 4e3c1d047..000000000 --- a/src/utility/ota/OTANanoRP2040.cpp +++ /dev/null @@ -1,266 +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. -*/ - -#if defined(ARDUINO_NANO_RP2040_CONNECT) - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include "OTA.h" - -#include "../watchdog/Watchdog.h" - -#include - -#include - -#include "mbed.h" -#include "FATFileSystem.h" -#include "FlashIAPBlockDevice.h" -#include "utility/ota/FlashSHA256.h" - -/****************************************************************************** - * FUNCTION DEFINITION - ******************************************************************************/ - -/* Original code: http://stackoverflow.com/questions/2616011/easy-way-to-parse-a-url-in-c-cross-platform */ -#include -#include -#include -#include -#include - -struct URI { - public: - URI(const std::string& url_s) { - this->parse(url_s); - } - std::string protocol_, host_, path_, query_; - private: - void parse(const std::string& url_s); -}; - -using namespace std; - -// ctors, copy, equality, ... -// TODO: change me into something embedded friendly (this function adds ~100KB to flash) -void URI::parse(const string& url_s) -{ - const string prot_end("://"); - string::const_iterator prot_i = search(url_s.begin(), url_s.end(), - prot_end.begin(), prot_end.end()); - protocol_.reserve(distance(url_s.begin(), prot_i)); - transform(url_s.begin(), prot_i, - back_inserter(protocol_), - ptr_fun(tolower)); // protocol is icase - if( prot_i == url_s.end() ) - return; - advance(prot_i, prot_end.length()); - string::const_iterator path_i = find(prot_i, url_s.end(), '/'); - host_.reserve(distance(prot_i, path_i)); - transform(prot_i, path_i, - back_inserter(host_), - ptr_fun(tolower)); // host is icase - string::const_iterator query_i = find(path_i, url_s.end(), '?'); - path_.assign(path_i, query_i); - if( query_i != url_s.end() ) - ++query_i; - query_.assign(query_i, url_s.end()); -} - -int rp2040_connect_onOTARequest(char const * ota_url) -{ - watchdog_reset(); - - int err = -1; - FlashIAPBlockDevice flash(XIP_BASE + 0xF00000, 0x100000); - if ((err = flash.init()) < 0) - { - DEBUG_ERROR("%s: flash.init() failed with %d", __FUNCTION__, err); - return static_cast(OTAError::RP2040_ErrorFlashInit); - } - - watchdog_reset(); - - flash.erase(XIP_BASE + 0xF00000, 0x100000); - - watchdog_reset(); - - mbed::FATFileSystem fs("ota"); - if ((err = fs.reformat(&flash)) != 0) - { - DEBUG_ERROR("%s: fs.reformat() failed with %d", __FUNCTION__, err); - return static_cast(OTAError::RP2040_ErrorReformat); - } - - watchdog_reset(); - - FILE * file = fopen("/ota/UPDATE.BIN.LZSS", "wb"); - if (!file) - { - DEBUG_ERROR("%s: fopen() failed", __FUNCTION__); - fclose(file); - return static_cast(OTAError::RP2040_ErrorOpenUpdateFile); - } - - watchdog_reset(); - - URI url(http://github.com/ota_url); - Client * client = nullptr; - int port = 0; - - if (url.protocol_ == "http") { - client = new WiFiClient(); - port = 80; - } else if (url.protocol_ == "https") { - client = new WiFiSSLClient(); - port = 443; - } else { - DEBUG_ERROR("%s: Failed to parse OTA URL %s", __FUNCTION__, ota_url); - fclose(file); - return static_cast(OTAError::RP2040_UrlParseError); - } - - watchdog_reset(); - - if (!client->connect(url.host_.c_str(), port)) - { - DEBUG_ERROR("%s: Connection failure with OTA storage server %s", __FUNCTION__, url.host_.c_str()); - fclose(file); - return static_cast(OTAError::RP2040_ServerConnectError); - } - - watchdog_reset(); - - client->println(String("GET ") + url.path_.c_str() + " HTTP/1.1"); - client->println(String("Host: ") + url.host_.c_str()); - client->println("Connection: close"); - client->println(); - - watchdog_reset(); - - /* Receive HTTP header. */ - String http_header; - bool is_header_complete = false, - is_http_header_timeout = false; - for (unsigned long const start = millis(); !is_header_complete;) - { - is_http_header_timeout = (millis() - start) > AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms; - if (is_http_header_timeout) break; - - watchdog_reset(); - - if (client->available()) - { - char const c = client->read(); - - http_header += c; - if (http_header.endsWith("\r\n\r\n")) - is_header_complete = true; - } - } - - if (!is_header_complete) - { - DEBUG_ERROR("%s: Error receiving HTTP header %s", __FUNCTION__, is_http_header_timeout ? "(timeout)":""); - fclose(file); - return static_cast(OTAError::RP2040_HttpHeaderError); - } - - /* Extract concent length from HTTP header. A typical entry looks like - * "Content-Length: 123456" - */ - char const * content_length_ptr = strstr(http_header.c_str(), "Content-Length"); - if (!content_length_ptr) - { - DEBUG_ERROR("%s: Failure to extract content length from http header", __FUNCTION__); - fclose(file); - return static_cast(OTAError::RP2040_ErrorParseHttpHeader); - } - /* Find start of numerical value. */ - char * ptr = const_cast(content_length_ptr); - for (; (*ptr != '\0') && !isDigit(*ptr); ptr++) { } - /* Extract numerical value. */ - String content_length_str; - for (; isDigit(*ptr); ptr++) content_length_str += *ptr; - int const content_length_val = atoi(content_length_str.c_str()); - DEBUG_VERBOSE("%s: Length of OTA binary according to HTTP header = %d bytes", __FUNCTION__, content_length_val); - - /* Receive as many bytes as are indicated by the HTTP header - or die trying. */ - int bytes_received = 0; - bool is_http_data_timeout = false; - for(unsigned long const start = millis(); bytes_received < content_length_val;) - { - is_http_data_timeout = (millis() - start) > AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms; - if (is_http_data_timeout) break; - - watchdog_reset(); - - if (client->available()) - { - char const c = client->read(); - - if (fwrite(&c, 1, sizeof(c), file) != sizeof(c)) - { - DEBUG_ERROR("%s: Writing of firmware image to flash failed", __FUNCTION__); - fclose(file); - return static_cast(OTAError::RP2040_ErrorWriteUpdateFile); - } - - bytes_received++; - } - } - - if (bytes_received != content_length_val) { - DEBUG_ERROR("%s: Error receiving HTTP data %s (%d bytes received, %d expected)", __FUNCTION__, is_http_data_timeout ? "(timeout)":"", bytes_received, content_length_val); - fclose(file); - return static_cast(OTAError::RP2040_HttpDataError); - } - - DEBUG_INFO("%s: %d bytes received", __FUNCTION__, ftell(file)); - fclose(file); - - /* Unmount the filesystem. */ - if ((err = fs.unmount()) != 0) - { - DEBUG_ERROR("%s: fs.unmount() failed with %d", __FUNCTION__, err); - return static_cast(OTAError::RP2040_ErrorUnmount); - } - - /* Perform the reset to reboot to SFU. */ - mbed_watchdog_trigger_reset(); - /* If watchdog is enabled we should not reach this point */ - NVIC_SystemReset(); - - return static_cast(OTAError::None); -} - -String rp2040_connect_getOTAImageSHA256() -{ - /* The maximum size of a RP2040 OTA update image is 1 MByte (that is 1024 * - * 1024 bytes or 0x100'000 bytes). - */ - return FlashSHA256::calc(XIP_BASE, 0x100000); -} - -bool rp2040_connect_isOTACapable() -{ - return true; -} - -#endif /* ARDUINO_NANO_RP2040_CONNECT */ diff --git a/src/utility/ota/OTAPortentaH7.cpp b/src/utility/ota/OTAPortentaH7.cpp deleted file mode 100644 index 1d7ecf3a7..000000000 --- a/src/utility/ota/OTAPortentaH7.cpp +++ /dev/null @@ -1,140 +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 - -#ifdef BOARD_STM32H7 - -#include "OTA.h" - -#include -#include -#include - -#include - -#include "tls/utility/SHA256.h" - -#include "../watchdog/Watchdog.h" - -/****************************************************************************** - * EXTERN - ******************************************************************************/ - -extern RTC_HandleTypeDef RTCHandle; - -/****************************************************************************** - * FUNCTION DEFINITION - ******************************************************************************/ - -int portenta_h7_onOTARequest(char const * ota_url, NetworkAdapter iface) -{ - watchdog_reset(); - - Arduino_Portenta_OTA::Error ota_portenta_err = Arduino_Portenta_OTA::Error::None; - /* Use 2nd partition of QSPI (1st partition contains WiFi firmware) */ - Arduino_Portenta_OTA_QSPI ota_portenta_qspi(QSPI_FLASH_FATFS_MBR, 2); - -#if defined (ARDUINO_PORTENTA_OTA_HAS_WATCHDOG_FEED) - ota_portenta_qspi.setFeedWatchdogFunc(watchdog_reset); -#endif - - watchdog_reset(); - - /* Initialize the QSPI memory for OTA handling. */ - if((ota_portenta_err = ota_portenta_qspi.begin()) != Arduino_Portenta_OTA::Error::None) { - DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::begin() failed with %d", static_cast(ota_portenta_err)); - return static_cast(ota_portenta_err); - } - - watchdog_reset(); - - /* Just to be safe delete any remains from previous updates. */ - remove("/fs/UPDATE.BIN"); - remove("/fs/UPDATE.BIN.LZSS"); - - watchdog_reset(); - - /* Download the OTA file from the web storage location. */ - MbedSocketClass * download_socket = static_cast(&WiFi); -#if defined (BOARD_HAS_ETHERNET) - if(iface == NetworkAdapter::ETHERNET) { - download_socket = static_cast(&Ethernet); - } -#endif - int const ota_portenta_qspi_download_ret_code = ota_portenta_qspi.downloadAndDecompress(ota_url, true /* is_https */, download_socket); - DEBUG_VERBOSE("Arduino_Portenta_OTA_QSPI::download(%s) returns %d", ota_url, ota_portenta_qspi_download_ret_code); - - watchdog_reset(); - - /* Schedule the firmware update. */ - if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) { - DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::update() failed with %d", static_cast(ota_portenta_err)); - return static_cast(ota_portenta_err); - } - - /* Perform the reset to reboot - then the bootloader performs the actual application update. */ - NVIC_SystemReset(); -} - -String portenta_h7_getOTAImageSHA256() -{ - /* The length of the application can be retrieved the same way it was - * communicated to the bootloader, that is by writing to the non-volatile - * storage registers of the RTC. - */ - SHA256 sha256; - uint32_t const app_start = 0x8040000; - uint32_t const app_size = HAL_RTCEx_BKUPRead(&RTCHandle, RTC_BKP_DR3); - - sha256.begin(); - uint32_t b = 0; - uint32_t bytes_read = 0; for(uint32_t a = app_start; - bytes_read < app_size; - bytes_read += sizeof(b), a += sizeof(b)) - { - /* Read the next chunk of memory. */ - memcpy(&b, reinterpret_cast(a), sizeof(b)); - /* Feed it to SHA256. */ - sha256.update(reinterpret_cast(&b), sizeof(b)); - } - /* Retrieve the final hash string. */ - uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; - sha256.finalize(sha256_hash); - String sha256_str; - std::for_each(sha256_hash, - sha256_hash + SHA256::HASH_SIZE, - [&sha256_str](uint8_t const elem) - { - char buf[4]; - snprintf(buf, 4, "%02X", elem); - sha256_str += buf; - }); - DEBUG_VERBOSE("SHA256: %d bytes (of %d) read", bytes_read, app_size); - return sha256_str; -} - -bool portenta_h7_isOTACapable() -{ - return Arduino_Portenta_OTA::isOtaCapable(); -} - -#endif /* BOARD_STM32H7 */ diff --git a/src/utility/ota/OTASamd.cpp b/src/utility/ota/OTASamd.cpp deleted file mode 100644 index 4ef214f32..000000000 --- a/src/utility/ota/OTASamd.cpp +++ /dev/null @@ -1,97 +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 - -#if defined (ARDUINO_ARCH_SAMD) && OTA_ENABLED - -#include "OTA.h" -#include -#include "../watchdog/Watchdog.h" -#include "utility/ota/FlashSHA256.h" - -#if OTA_STORAGE_SNU -# include -# include /* WiFiStorage */ -#endif - -/****************************************************************************** - * FUNCTION DEFINITION - ******************************************************************************/ - -int samd_onOTARequest(char const * ota_url) -{ - watchdog_reset(); - -#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"); - - watchdog_reset(); - - /* Trigger direct download to NINA module. */ - uint8_t nina_ota_err_code = 0; - if (!WiFiStorage.downloadOTA(ota_url, &nina_ota_err_code)) - { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s error download to nina: %d", __FUNCTION__, nina_ota_err_code); - return static_cast(OTAError::DownloadFailed); - } - - /* Perform the reset to reboot to SxU. */ - NVIC_SystemReset(); - - return static_cast(OTAError::None); -#endif /* OTA_STORAGE_SNU */ - - (void)ota_url; - return static_cast(OTAError::DownloadFailed); -} - -String samd_getOTAImageSHA256() -{ - /* Calculate the SHA256 checksum over the firmware stored in the flash of the - * MCU. Note: As we don't know the length per-se we read chunks of the flash - * until we detect one containing only 0xFF (= flash erased). This only works - * for firmware updated via OTA and second stage bootloaders (SxU family) - * because only those erase the complete flash before performing an update. - * Since the SHA256 firmware image is only required for the cloud servers to - * perform a version check after the OTA update this is a acceptable trade off. - * The bootloader is excluded from the calculation and occupies flash address - * range 0 to 0x2000, total flash size of 0x40000 bytes (256 kByte). - */ - 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/OTAUnoR4.cpp b/src/utility/ota/OTAUnoR4.cpp deleted file mode 100644 index d446476c3..000000000 --- a/src/utility/ota/OTAUnoR4.cpp +++ /dev/null @@ -1,187 +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 - -#if defined ARDUINO_UNOR4_WIFI && OTA_ENABLED - -#include "OTAUpdate.h" -#include -#include "tls/utility/SHA256.h" -#include "fsp_common_api.h" -#include "r_flash_lp.h" -#include "WiFiS3.h" - -/****************************************************************************** - * DEFINES - ******************************************************************************/ - -/* Key code for writing PRCR register. */ -#define BSP_PRV_PRCR_KEY (0xA500U) -#define BSP_PRV_PRCR_PRC1_UNLOCK ((BSP_PRV_PRCR_KEY) | 0x2U) -#define BSP_PRV_PRCR_LOCK ((BSP_PRV_PRCR_KEY) | 0x0U) - -#define OTA_MAGIC (*((volatile uint16_t *) &R_SYSTEM->VBTBKR[4])) -#define OTA_SIZE (*((volatile uint32_t *) &R_SYSTEM->VBTBKR[6])) - -/****************************************************************************** - * FUNCTION DEFINITION - ******************************************************************************/ - -static void unor4_setOTASize(uint32_t size) -{ - R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_PRC1_UNLOCK; - OTA_MAGIC = 0x07AA; - OTA_SIZE = size; - R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_LOCK; -} - -static uint32_t unor4_getOTASize() -{ - if (OTA_MAGIC == 0x07AA) - { - return OTA_SIZE; - } - return 0; -} - -static int unor4_codeFlashOpen(flash_lp_instance_ctrl_t * ctrl) -{ - flash_cfg_t cfg; - - cfg.data_flash_bgo = false; - cfg.p_callback = nullptr; - cfg.p_context = nullptr; - cfg.p_extend = nullptr; - cfg.ipl = (BSP_IRQ_DISABLED); - cfg.irq = FSP_INVALID_VECTOR; - cfg.err_ipl = (BSP_IRQ_DISABLED); - cfg.err_irq = FSP_INVALID_VECTOR; - - fsp_err_t rv = FSP_ERR_UNSUPPORTED; - - rv = R_FLASH_LP_Open(ctrl,&cfg); - return rv; -} - -static int unor4_codeFlashClose(flash_lp_instance_ctrl_t * ctrl) -{ - fsp_err_t rv = FSP_ERR_UNSUPPORTED; - - rv = R_FLASH_LP_Close(ctrl); - return rv; -} - -int unor4_onOTARequest(char const * ota_url) -{ - int ota_err = static_cast(OTAUpdate::Error::None); - OTAUpdate ota; - - /* Initialize the board for OTA handling. */ - if ((ota_err = static_cast(ota.begin("/update.bin"))) != static_cast(OTAUpdate::Error::None)) - { - DEBUG_ERROR("OTAUpdate::begin() failed with %d", ota_err); - return ota_err; - } - - /* Download the OTA file from the web storage location. */ - int const ota_download = ota.download(ota_url,"/update.bin"); - if (ota_download <= 0) - { - DEBUG_ERROR("OTAUpdate::download() failed with %d", ota_download); - return ota_download; - } - DEBUG_VERBOSE("OTAUpdate::download() %d bytes downloaded", ota_download); - - /* Verify update integrity */ - if ((ota_err = static_cast(ota.verify())) != static_cast(OTAUpdate::Error::None)) - { - DEBUG_ERROR("OTAUpdate::verify() failed with %d", ota_err); - return ota_err; - } - - /* Store update size and write OTA magin number */ - unor4_setOTASize(ota_download); - - /* Flash new firmware */ - if ((ota_err = static_cast(ota.update("/update.bin"))) != static_cast(OTAUpdate::Error::None)) - { - DEBUG_ERROR("OTAUpdate::update() failed with %d", ota_err); - return ota_err; - } - - return static_cast(OTAUpdate::Error::None); -} - -String unor4_getOTAImageSHA256() -{ - /* The length of the application can be retrieved the same way it was - * communicated to the bootloader, that is by writing to the non-volatile - * storage registers of the RTC. - */ - SHA256 sha256; - uint32_t const app_start = 0x4000; - uint32_t const app_size = unor4_getOTASize(); - - flash_lp_instance_ctrl_t ctrl; - unor4_codeFlashOpen(&ctrl); - - sha256.begin(); - uint32_t b = 0; - uint32_t bytes_read = 0; for(uint32_t a = app_start; - bytes_read < app_size; - bytes_read += sizeof(b), a += sizeof(b)) - { - /* Read the next chunk of memory. */ - memcpy(&b, reinterpret_cast(a), sizeof(b)); - /* Feed it to SHA256. */ - sha256.update(reinterpret_cast(&b), sizeof(b)); - } - - unor4_codeFlashClose(&ctrl); - - /* Retrieve the final hash string. */ - uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; - sha256.finalize(sha256_hash); - String sha256_str; - std::for_each(sha256_hash, - sha256_hash + SHA256::HASH_SIZE, - [&sha256_str](uint8_t const elem) - { - char buf[4]; - snprintf(buf, 4, "%02X", elem); - sha256_str += buf; - }); - DEBUG_ERROR("SHA256: %d bytes (of %d) read", bytes_read, app_size); - return sha256_str; -} - -bool unor4_isOTACapable() -{ - /* check firmware version */ - String const fv = WiFi.firmwareVersion(); - if (fv < String("0.3.0")) { - return false; - } - return true; -} - -#endif /* ARDUINO_UNOR4_WIFI */ From 356d0c78a999545ca96f291af3e4f4445e9fe7e3 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 16 Apr 2024 16:31:53 +0200 Subject: [PATCH 579/780] BearSSLClient: removing trailing white spaces --- src/tls/BearSSLClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tls/BearSSLClient.cpp b/src/tls/BearSSLClient.cpp index 1ebd78653..995718e93 100644 --- a/src/tls/BearSSLClient.cpp +++ b/src/tls/BearSSLClient.cpp @@ -196,7 +196,7 @@ uint8_t BearSSLClient::connected() BearSSLClient::operator bool() { - return (*_client); + return (*_client); } void BearSSLClient::setInsecure(SNI insecure) @@ -353,7 +353,7 @@ int BearSSLClient::clientRead(void *ctx, unsigned char *buf, size_t len) #ifdef DEBUGSERIAL DEBUGSERIAL.print("BearSSLClient::clientRead - "); DEBUGSERIAL.print(result); - DEBUGSERIAL.print(" - "); + DEBUGSERIAL.print(" - "); for (size_t i = 0; i < result; i++) { byte b = buf[i]; From 30d665ab57ff099203174524b61f94b087bbe9b7 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 25 Mar 2024 13:53:21 +0100 Subject: [PATCH 580/780] implemented stm32h7 ota class --- src/ota/implementation/OTASTM32H7.cpp | 215 ++++++++++++++++++++++++++ src/ota/implementation/OTASTM32H7.h | 90 +++++++++-- src/ota/implementation/OTASTM32H7.ipp | 32 ---- 3 files changed, 293 insertions(+), 44 deletions(-) create mode 100644 src/ota/implementation/OTASTM32H7.cpp delete mode 100644 src/ota/implementation/OTASTM32H7.ipp diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp new file mode 100644 index 000000000..b1cbe7017 --- /dev/null +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -0,0 +1,215 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#include "AIoTC_Config.h" +#if defined(BOARD_STM32H7) && OTA_ENABLED +#include "OTASTM32H7.h" + +#include "utility/watchdog/Watchdog.h" +#include + +static bool findProgramLength(DIR * dir, uint32_t & program_length); + +const char STM32H7OTACloudProcess::UPDATE_FILE_NAME[] = "/fs/UPDATE.BIN"; + +STM32H7OTACloudProcess::STM32H7OTACloudProcess(MessageStream *ms, Client* client) +: OTADefaultCloudProcessInterface(ms, client) +, decompressed(nullptr) +, _bd_raw_qspi(nullptr) +, _program_length(0) +, _bd(nullptr) +, _fs(nullptr) { + +} + +STM32H7OTACloudProcess::~STM32H7OTACloudProcess() { + if(decompressed != nullptr) { + fclose(decompressed); + decompressed = nullptr; + } + + storageClean(); +} + +OTACloudProcessInterface::State STM32H7OTACloudProcess::resume(Message* msg) { + return OtaBegin; +} + +void STM32H7OTACloudProcess::update() { + OTADefaultCloudProcessInterface::update(); + watchdog_reset(); // FIXME this should npot be performed here +} + +int STM32H7OTACloudProcess::writeFlash(uint8_t* const buffer, size_t len) { + if (decompressed == nullptr) { + return -1; + } + return fwrite(buffer, sizeof(uint8_t), len, decompressed); +} + +OTACloudProcessInterface::State STM32H7OTACloudProcess::startOTA() { + if (!isOtaCapable()) { + return NoCapableBootloaderFail; + } + + /* Initialize the QSPI memory for OTA handling. */ + if (!storageInit()) { + return OtaStorageInitFail; + } + + // this could be useless, since we are writing over it + remove(UPDATE_FILE_NAME); + + decompressed = fopen(UPDATE_FILE_NAME, "wb"); + + // start the download if the setup for ota storage is successful + return OTADefaultCloudProcessInterface::startOTA(); +} + + +OTACloudProcessInterface::State STM32H7OTACloudProcess::flashOTA() { + fclose(decompressed); + decompressed = nullptr; + + /* Schedule the firmware update. */ + if(!storageOpen()) { + return OtaStorageOpenFail; + } + + // this sets the registries in RTC to load the firmware from the storage selected at the next reboot + STM32H747::writeBackupRegister(RTCBackup::DR0, 0x07AA); + STM32H747::writeBackupRegister(RTCBackup::DR1, storage); + STM32H747::writeBackupRegister(RTCBackup::DR2, data_offset); + STM32H747::writeBackupRegister(RTCBackup::DR3, _program_length); + + return Reboot; +} + +OTACloudProcessInterface::State STM32H7OTACloudProcess::reboot() { + // TODO save information about the progress reached in the ota + + // This command reboots the mcu + NVIC_SystemReset(); + + return Resume; // This won't ever be reached +} + +void STM32H7OTACloudProcess::reset() { + OTADefaultCloudProcessInterface::reset(); + + remove(UPDATE_FILE_NAME); + + storageClean(); +} + +void STM32H7OTACloudProcess::storageClean() { + DEBUG_VERBOSE(F("storage clean")); + + if(decompressed != nullptr) { + fclose(decompressed); + decompressed = nullptr; + } + + if(_fs != nullptr) { + _fs->unmount(); + delete _fs; + _fs = nullptr; + } + + if(_bd != nullptr) { + delete _bd; + _bd = nullptr; + } +} + +bool STM32H7OTACloudProcess::isOtaCapable() { + #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) + return false; + else + return true; +} + +bool STM32H7OTACloudProcess::storageInit() { + int err_mount=1; + + if(_bd_raw_qspi == nullptr) { + _bd_raw_qspi = mbed::BlockDevice::get_default_instance(); + + if (_bd_raw_qspi->init() != QSPIF_BD_ERROR_OK) { + DEBUG_VERBOSE(F("Error: QSPI init failure.")); + return false; + } + } + + if (storage == portenta::QSPI_FLASH_FATFS) { + _fs = new mbed::FATFileSystem("fs"); + err_mount = _fs->mount(_bd_raw_qspi); + } else if (storage == portenta::QSPI_FLASH_FATFS_MBR) { + _bd = new mbed::MBRBlockDevice(_bd_raw_qspi, data_offset); + _fs = new mbed::FATFileSystem("fs"); + err_mount = _fs->mount(_bd); + } + + if (!err_mount) { + return true; + } + DEBUG_VERBOSE(F("Error while mounting the filesystem. Err = %d"), err_mount); + return false; +} + +bool STM32H7OTACloudProcess::storageOpen() { + DIR * dir = NULL; + if ((dir = opendir("/fs")) != NULL) + { + if (findProgramLength(dir, _program_length)) + { + closedir(dir); + return true; + } + closedir(dir); + } + + return false; +} + +bool findProgramLength(DIR * dir, uint32_t & program_length) { + struct dirent * entry = NULL; + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, "UPDATE.BIN") == 0) { // FIXME use constants + struct stat stat_buf; + stat("/fs/UPDATE.BIN", &stat_buf); + program_length = stat_buf.st_size; + return true; + } + } + + return false; +} + +// extern uint32_t __stext = ~0; +extern uint32_t __etext; +extern uint32_t _sdata; +extern uint32_t _edata; + +void* STM32H7OTACloudProcess::appStartAddress() { + return (void*)0x8040000; + // return &__stext; +} + +uint32_t STM32H7OTACloudProcess::appSize() { + return ((&__etext - (uint32_t*)appStartAddress()) + (&_edata - &_sdata))*sizeof(void*); +} + + +#endif // defined(BOARD_STM32H7) && OTA_ENABLED \ No newline at end of file diff --git a/src/ota/implementation/OTASTM32H7.h b/src/ota/implementation/OTASTM32H7.h index 455066e37..ac1021715 100644 --- a/src/ota/implementation/OTASTM32H7.h +++ b/src/ota/implementation/OTASTM32H7.h @@ -1,23 +1,89 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + #pragma once +#include "ota/interface/OTAInterfaceDefault.h" + +#include + +#include +#include +#include +#include -#include "src/ota/interface/OTAInterface.h" +#include "WiFi.h" /* WiFi from ArduinoCore-mbed */ +#include -class STM32H7OTACloudProcess: public OTACloudProcessInterface { +#define APOTA_QSPI_FLASH_FLAG (1 << 2) +#define APOTA_SDCARD_FLAG (1 << 3) +#define APOTA_RAW_FLAG (1 << 4) +#define APOTA_FATFS_FLAG (1 << 5) +#define APOTA_LITTLEFS_FLAG (1 << 6) +#define APOTA_MBR_FLAG (1 << 7) + +namespace portenta { + enum StorageType { + QSPI_FLASH_FATFS = APOTA_QSPI_FLASH_FLAG | APOTA_FATFS_FLAG, + QSPI_FLASH_FATFS_MBR = APOTA_QSPI_FLASH_FLAG | APOTA_FATFS_FLAG | APOTA_MBR_FLAG, + SD_FATFS = APOTA_SDCARD_FLAG | APOTA_FATFS_FLAG, + SD_FATFS_MBR = APOTA_SDCARD_FLAG | APOTA_FATFS_FLAG | APOTA_MBR_FLAG, + }; +} + +class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { public: - STM32H7OTACloudProcess(); - void update(); + STM32H7OTACloudProcess(MessageStream *ms, Client* client=nullptr); + ~STM32H7OTACloudProcess(); + void update() override; - // retrocompatibility functions used in old ota prtotocol based on properties - int otaRequest(char const * ota_url, NetworkAdapter iface); - String getOTAImageSHA256(); - bool isOTACapable(); + virtual bool isOtaCapable() override; protected: - // we start the download and decompress process - virtual State fetch(Message* msg=nullptr); + virtual OTACloudProcessInterface::State resume(Message* msg=nullptr) override; + + // we are overriding the method of startOTA in order to open the destination file for the ota download + virtual OTACloudProcessInterface::State startOTA() override; // whene the download is correctly finished we set the mcu to use the newly downloaded binary - virtual State flashOTA(Message* msg=nullptr); + virtual OTACloudProcessInterface::State flashOTA() override; // we reboot the device - virtual State reboot(Message* msg=nullptr); + virtual OTACloudProcessInterface::State reboot() override; + + // write the decompressed char buffer of the incoming ota + virtual int writeFlash(uint8_t* const buffer, size_t len) override; + + virtual void reset() override; + + void* appStartAddress(); + uint32_t appSize(); + bool appFlashOpen() { return true; }; + bool appFlashClose() { return true; }; +private: + bool storageInit(); + bool storageOpen(); + + void storageClean(); + + FILE* decompressed; + // static const char UPDATE_FILE_NAME[]; + mbed::BlockDevice* _bd_raw_qspi; + uint32_t _program_length; + + mbed::BlockDevice* _bd; + mbed::FATFileSystem* _fs; + + mbed::MBRBlockDevice* cert_bd_qspi; + mbed::FATFileSystem* cert_fs_qspi; + + const portenta::StorageType storage=portenta::QSPI_FLASH_FATFS_MBR; + const uint32_t data_offset=2; + + static const char UPDATE_FILE_NAME[]; }; diff --git a/src/ota/implementation/OTASTM32H7.ipp b/src/ota/implementation/OTASTM32H7.ipp deleted file mode 100644 index 09093a30d..000000000 --- a/src/ota/implementation/OTASTM32H7.ipp +++ /dev/null @@ -1,32 +0,0 @@ -#if defined(BOARD_STM32H7) && OTA_ENABLED -#include "OTAPortentaH7.h" - -STM32H7OTACloudProcess::STM32H7OTACloudProcess() {} - -void STM32H7OTACloudProcess::update() { - OTACloudProcessInterface::update(); - watchdog_reset(); -} - -State STM32H7OTACloudProcess::fetch(Message *msg) { - -} - -State STM32H7OTACloudProcess::flashOTA(Message *msg) { - /* Schedule the firmware update. */ - if((ota_portenta_err = ota_portenta_qspi.update()) != Arduino_Portenta_OTA::Error::None) { - DEBUG_ERROR("Arduino_Portenta_OTA_QSPI::update() failed with %d", static_cast(ota_portenta_err)); - return static_cast(ota_portenta_err); - } -} - -State STM32H7OTACloudProcess::reboot(Message *msg) { - // TODO save information about the progress reached in the ota - - // This command reboots the mcu - NVIC_SystemReset(); - - return Resume; // This won't ever be reached -} - -#endif // defined(BOARD_STM32H7) && OTA_ENABLED \ No newline at end of file From 891c85f9edf19719d9f03ac8c08083ec9eb1af1b Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 16 Apr 2024 16:39:08 +0200 Subject: [PATCH 581/780] BearSSLClient: adding FIXME comment --- src/tls/BearSSLClient.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tls/BearSSLClient.h b/src/tls/BearSSLClient.h index 2979eebf4..32fb18727 100644 --- a/src/tls/BearSSLClient.h +++ b/src/tls/BearSSLClient.h @@ -100,6 +100,11 @@ class BearSSLClient : public Client { br_x509_certificate _ecCert; bool _ecCertDynamic; + /* FIXME By introducing _sslio_closing we are overriding the correct behaviour of SSL protocol + * where the client is require to correctly close the ssl session. In the way we use it + * we are blocking bearssl from sending any data on the underlying level, this fix requires + * further investigation in the bearssl code + */ bool _sslio_closing; br_ssl_client_context _sc; br_x509_minimal_context _xc; From 51020b00ddebd8e79693877f2966a96efb63fff6 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 29 Feb 2024 13:35:02 +0100 Subject: [PATCH 582/780] implemented rp2040 ota class --- src/ota/implementation/OTANanoRP2040.cpp | 129 +++++++++++++++++++++++ src/ota/implementation/OTANanoRP2040.h | 46 ++++++-- 2 files changed, 166 insertions(+), 9 deletions(-) diff --git a/src/ota/implementation/OTANanoRP2040.cpp b/src/ota/implementation/OTANanoRP2040.cpp index e0f6feb72..5b1266f60 100644 --- a/src/ota/implementation/OTANanoRP2040.cpp +++ b/src/ota/implementation/OTANanoRP2040.cpp @@ -1,4 +1,133 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#include + #if defined(ARDUINO_NANO_RP2040_CONNECT) && OTA_ENABLED +#include #include "OTANanoRP2040.h" +#include +#include "mbed.h" +#include "utility/watchdog/Watchdog.h" + +#define SD_MOUNT_PATH "ota" +#define FULL_UPDATE_FILE_PATH "/ota/UPDATE.BIN" + +const char NANO_RP2040OTACloudProcess::UPDATE_FILE_NAME[] = FULL_UPDATE_FILE_PATH; + + +NANO_RP2040OTACloudProcess::NANO_RP2040OTACloudProcess(MessageStream *ms, Client* client) +: OTADefaultCloudProcessInterface(ms, client) +, flash((uint32_t)appStartAddress() + 0xF00000, 0x100000) // TODO make this numbers a constant +, decompressed(nullptr) +, fs(nullptr) { +} + +NANO_RP2040OTACloudProcess::~NANO_RP2040OTACloudProcess() { + close_fs(); +} + +OTACloudProcessInterface::State NANO_RP2040OTACloudProcess::resume(Message* msg) { + return OtaBegin; +} + +int NANO_RP2040OTACloudProcess::writeFlash(uint8_t* const buffer, size_t len) { + if(decompressed == nullptr) { + DEBUG_VERBOSE("writing on a file that is not open"); // FIXME change log message + return 0; + } + return fwrite(buffer, sizeof(uint8_t), len, decompressed); +} + +OTACloudProcessInterface::State NANO_RP2040OTACloudProcess::startOTA() { + int err = -1; + if ((err = flash.init()) < 0) { + DEBUG_VERBOSE("%s: flash.init() failed with %d", __FUNCTION__, err); + return OtaStorageInitFail; + } + + flash.erase((uint32_t)appStartAddress() + 0xF00000, 0x100000); + + fs = new mbed::FATFileSystem(SD_MOUNT_PATH); // FIXME can this be allocated in the stack? + if ((err = fs->reformat(&flash)) != 0) { + DEBUG_VERBOSE("%s: fs.reformat() failed with %d", __FUNCTION__, err); + return ErrorReformatFail; + } + + decompressed = fopen(UPDATE_FILE_NAME, "wb"); // TODO make this a constant + if (!decompressed) { + DEBUG_VERBOSE("%s: fopen() failed", __FUNCTION__); + fclose(decompressed); + return ErrorOpenUpdateFileFail; + } + + // we start the download here + return OTADefaultCloudProcessInterface::startOTA();; +} + + +OTACloudProcessInterface::State NANO_RP2040OTACloudProcess::flashOTA() { + int err = 0; + if((err = close_fs()) != 0) { + return ErrorUnmountFail; + } + + return Reboot; +} + +OTACloudProcessInterface::State NANO_RP2040OTACloudProcess::reboot() { + mbed_watchdog_trigger_reset(); + /* If watchdog is enabled we should not reach this point */ + NVIC_SystemReset(); + + return Resume; // This won't ever be reached +} + +void NANO_RP2040OTACloudProcess::reset() { + OTADefaultCloudProcessInterface::reset(); + + close_fs(); +} + +int NANO_RP2040OTACloudProcess::close_fs() { + int err = 0; + + if(decompressed != nullptr) { + fclose(decompressed); + decompressed = nullptr; + } + + if (fs != nullptr && (err = fs->unmount()) != 0) { + DEBUG_VERBOSE("%s: fs.unmount() failed with %d", __FUNCTION__, err); + } else { + delete fs; + fs = nullptr; + } + + return err; +} + +bool NANO_RP2040OTACloudProcess::isOtaCapable() { + return true; +} + +// extern void* __stext; +extern uint32_t __flash_binary_end; + + +void* NANO_RP2040OTACloudProcess::appStartAddress() { + // return &__flash_binary_start; + return (void*)XIP_BASE; +} +uint32_t NANO_RP2040OTACloudProcess::appSize() { + return (&__flash_binary_end - (uint32_t*)appStartAddress())*sizeof(void*); +} #endif // defined(ARDUINO_NANO_RP2040_CONNECT) && OTA_ENABLED \ No newline at end of file diff --git a/src/ota/implementation/OTANanoRP2040.h b/src/ota/implementation/OTANanoRP2040.h index 165bb1cea..dd165d27e 100644 --- a/src/ota/implementation/OTANanoRP2040.h +++ b/src/ota/implementation/OTANanoRP2040.h @@ -1,23 +1,51 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + #pragma once -#include "src/ota/interface/OTAInterface.h" +#include "ota/interface/OTAInterfaceDefault.h" #include "FATFileSystem.h" #include "FlashIAPBlockDevice.h" -class NANO_RP2040OTACloudProcess: public OTACloudProcessInterface { +class NANO_RP2040OTACloudProcess: public OTADefaultCloudProcessInterface { public: - STM32H7OTACloudProcess(); + NANO_RP2040OTACloudProcess(MessageStream *ms, Client* client=nullptr); + ~NANO_RP2040OTACloudProcess(); + + virtual bool isOtaCapable() override; protected: - // we start the download and decompress process - virtual State fetch(Message* msg=nullptr); + virtual OTACloudProcessInterface::State resume(Message* msg=nullptr) override; - // when the download is completed we verify for integrity and correctness of the downloaded binary - // virtual State verifyOTA(Message* msg=nullptr); // TODO this may be performed inside download + virtual OTACloudProcessInterface::State startOTA() override; // whene the download is correctly finished we set the mcu to use the newly downloaded binary - virtual State flashOTA(Message* msg=nullptr); + virtual OTACloudProcessInterface::State flashOTA() override; // we reboot the device - virtual State reboot(Message* msg=nullptr); + virtual OTACloudProcessInterface::State reboot() override; + + // write the decompressed char buffer of the incoming ota + virtual int writeFlash(uint8_t* const buffer, size_t len) override; + + virtual void reset() override; + + void* appStartAddress(); + uint32_t appSize(); + bool appFlashOpen() { return true; }; + bool appFlashClose() { return true; }; +private: + FlashIAPBlockDevice flash; + FILE* decompressed; + mbed::FATFileSystem* fs; + static const char UPDATE_FILE_NAME[]; + + int close_fs(); }; From 07b1a6ed4cb6addbc0c7a5b57578ad2dbf215603 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 19 Mar 2024 09:28:15 +0100 Subject: [PATCH 583/780] Add TLSClientMqtt --- src/tls/utility/TLSClientMqtt.cpp | 68 ++++++++++++++++++++++++++++++ src/tls/utility/TLSClientMqtt.h | 69 +++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 src/tls/utility/TLSClientMqtt.cpp create mode 100644 src/tls/utility/TLSClientMqtt.h diff --git a/src/tls/utility/TLSClientMqtt.cpp b/src/tls/utility/TLSClientMqtt.cpp new file mode 100644 index 000000000..8c6c3f529 --- /dev/null +++ b/src/tls/utility/TLSClientMqtt.cpp @@ -0,0 +1,68 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#include + +#ifdef HAS_TCP + +#include "TLSClientMqtt.h" + +#if defined(BOARD_HAS_SECRET_KEY) + #include "tls/AIoTCUPCert.h" +#endif + +#if defined(BOARD_HAS_SE050) || defined(BOARD_HAS_SOFTSE) + #include "tls/AIoTCSSCert.h" +#endif + +#ifdef BOARD_HAS_ECCX08 + #include "tls/BearSSLTrustAnchors.h" + extern "C" { + void aiotc_client_profile_init(br_ssl_client_context *cc, + br_x509_minimal_context *xc, + const br_x509_trust_anchor *trust_anchors, + size_t trust_anchors_num); + unsigned long getTime(); + } +#endif + +void TLSClientMqtt::begin(ConnectionHandler & connection) { + +#if defined(BOARD_HAS_OFFLOADED_ECCX08) + /* Arduino Root CA is configured in nina-fw + * https://github.com/arduino/nina-fw/blob/master/arduino/libraries/ArduinoBearSSL/src/BearSSLTrustAnchors.h + */ +#elif defined(BOARD_HAS_ECCX08) + setClient(connection.getClient()); + setProfile(aiotc_client_profile_init); + setTrustAnchors(ArduinoIoTCloudTrustAnchor, ArduinoIoTCloudTrustAnchor_NUM); + onGetTime(getTime); +#elif defined(ARDUINO_PORTENTA_C33) + setClient(connection.getClient()); + setCACert(AIoTSSCert); +#elif defined(ARDUINO_NICLA_VISION) + appendCustomCACert(AIoTSSCert); +#elif defined(ARDUINO_EDGE_CONTROL) + appendCustomCACert(AIoTUPCert); +#elif defined(ARDUINO_UNOR4_WIFI) + /* Arduino Root CA is configured in uno-r4-wifi-usb-bridge fw >= 0.4.1 + * https://github.com/arduino/uno-r4-wifi-usb-bridge/blob/main/certificates/cacrt_all.pem + * Boards using username/password authentication relies on Starfield Class 2 CA + * also present in older firmware revisions + * https://github.com/arduino/uno-r4-wifi-usb-bridge/blob/f09ca94fdcab845b8368d4435fdac9f6999d21d2/certificates/certificates.pem#L852 + */ +#elif defined(ARDUINO_ARCH_ESP32) + setCACertBundle(x509_crt_bundle); +#elif defined(ARDUINO_ARCH_ESP8266) + setInsecure(); +#endif +} + +#endif diff --git a/src/tls/utility/TLSClientMqtt.h b/src/tls/utility/TLSClientMqtt.h new file mode 100644 index 000000000..837e76dec --- /dev/null +++ b/src/tls/utility/TLSClientMqtt.h @@ -0,0 +1,69 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +#include +#include + +#if defined(BOARD_HAS_OFFLOADED_ECCX08) + /* + * Arduino MKR WiFi1010 - WiFi + * Arduino NANO 33 IoT - WiFi + */ + #include "WiFiSSLClient.h" + class TLSClientMqtt : public WiFiBearSSLClient { +#elif defined(BOARD_HAS_ECCX08) + /* + * Arduino MKR GSM 1400 + * Arduino MKR NB 1500 + * Arduino Portenta H7 + * Arduino Giga R1 + * OPTA + */ + #include + class TLSClientMqtt : public BearSSLClient { +#elif defined(ARDUINO_PORTENTA_C33) + /* + * Arduino Portenta C33 + */ + #include + class TLSClientMqtt : public SSLClient { +#elif defined(ARDUINO_NICLA_VISION) + /* + * Arduino Nicla Vision + */ + #include + class TLSClientMqtt : public WiFiSSLSE050Client { +#elif defined(ARDUINO_EDGE_CONTROL) + /* + * Arduino Edge Control + */ + #include + class TLSClientMqtt : public GSMSSLClient { +#elif defined(ARDUINO_UNOR4_WIFI) + /* + * Arduino UNO R4 WiFi + */ + #include + class TLSClientMqtt : public WiFiSSLClient { +#elif defined(BOARD_ESP) + /* + * ESP32* + * ESP82* + */ + #include + class TLSClientMqtt : public WiFiClientSecure { +#endif + +public: + void begin(ConnectionHandler & connection); + +}; From 94df318eee139d8ec208be61fa360bdffccd2bd5 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 29 Feb 2024 13:48:08 +0100 Subject: [PATCH 584/780] implemented unor4 ota class --- src/ota/implementation/OTAUnoR4.cpp | 163 ++++++++++++++++++++++++++++ src/ota/implementation/OTAUnoR4.h | 46 ++++++-- 2 files changed, 201 insertions(+), 8 deletions(-) diff --git a/src/ota/implementation/OTAUnoR4.cpp b/src/ota/implementation/OTAUnoR4.cpp index e44e7f65e..8119c2432 100644 --- a/src/ota/implementation/OTAUnoR4.cpp +++ b/src/ota/implementation/OTAUnoR4.cpp @@ -1,4 +1,167 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#include + #if defined(ARDUINO_UNOR4_WIFI) && OTA_ENABLED #include "OTAUnoR4.h" +#include +#include "tls/utility/SHA256.h" +#include "fsp_common_api.h" +#include "r_flash_lp.h" +#include "WiFi.h" + +/****************************************************************************** + * DEFINES + ******************************************************************************/ + +const char UNOR4OTACloudProcess::UPDATE_FILE_NAME[] = "/update.bin"; + +static OTACloudProcessInterface::State convertUnor4ErrorToState(int error_code); + +UNOR4OTACloudProcess::UNOR4OTACloudProcess(MessageStream *ms) +: OTACloudProcessInterface(ms){ + +} + +OTACloudProcessInterface::State UNOR4OTACloudProcess::resume(Message* msg) { + return OtaBegin; +} + +OTACloudProcessInterface::State UNOR4OTACloudProcess::startOTA() { + int ota_err = OTAUpdate::OTA_ERROR_NONE; + + // Open fs for ota + if((ota_err = ota.begin(UPDATE_FILE_NAME)) != OTAUpdate::OTA_ERROR_NONE) { + DEBUG_VERBOSE("OTAUpdate::begin() failed with %d", ota_err); + return convertUnor4ErrorToState(ota_err); + } + + return Fetch; +} + +OTACloudProcessInterface::State UNOR4OTACloudProcess::fetch() { + int ota_err = OTAUpdate::OTA_ERROR_NONE; + + int const ota_download = ota.download(this->context->url,UPDATE_FILE_NAME); + if (ota_download <= 0) { + DEBUG_VERBOSE("OTAUpdate::download() failed with %d", ota_download); + return convertUnor4ErrorToState(ota_download); + } + DEBUG_VERBOSE("OTAUpdate::download() %d bytes downloaded", ota_download); + + if ((ota_err = ota.verify()) != OTAUpdate::OTA_ERROR_NONE) { + DEBUG_VERBOSE("OTAUpdate::verify() failed with %d", ota_err); + return convertUnor4ErrorToState(ota_err); + } + + return FlashOTA; +} + +OTACloudProcessInterface::State UNOR4OTACloudProcess::flashOTA() { + int ota_err = OTAUpdate::OTA_ERROR_NONE; + + /* Flash new firmware */ + if ((ota_err = ota.update(UPDATE_FILE_NAME)) != OTAUpdate::OTA_ERROR_NONE) { // This reboots the MCU + DEBUG_VERBOSE("OTAUpdate::update() failed with %d", ota_err); + return convertUnor4ErrorToState(ota_err); + } +} + +OTACloudProcessInterface::State UNOR4OTACloudProcess::reboot() { +} + +void UNOR4OTACloudProcess::reset() { +} + +bool UNOR4OTACloudProcess::isOtaCapable() { + String const fv = WiFi.firmwareVersion(); + if (fv < String("0.3.0")) { + return false; + } + return true; +} + +extern void* __ROM_Start; +extern void* __etext; +extern void* __data_end__; +extern void* __data_start__; + +constexpr void* UNOR4OTACloudProcess::appStartAddress() { return &__ROM_Start; } +uint32_t UNOR4OTACloudProcess::appSize() { + return ((&__etext - &__ROM_Start) + (&__data_end__ - &__data_start__))*sizeof(void*); +} + +bool UNOR4OTACloudProcess::appFlashOpen() { + cfg.data_flash_bgo = false; + cfg.p_callback = nullptr; + cfg.p_context = nullptr; + cfg.p_extend = nullptr; + cfg.ipl = (BSP_IRQ_DISABLED); + cfg.irq = FSP_INVALID_VECTOR; + cfg.err_ipl = (BSP_IRQ_DISABLED); + cfg.err_irq = FSP_INVALID_VECTOR; + + fsp_err_t rv = FSP_ERR_UNSUPPORTED; + + rv = R_FLASH_LP_Open(&ctrl,&cfg); + DEBUG_VERBOSE("Flash open %X", rv); + + return rv == FSP_SUCCESS; +} + +bool UNOR4OTACloudProcess::appFlashClose() { + fsp_err_t rv = FSP_ERR_UNSUPPORTED; + rv = R_FLASH_LP_Close(&ctrl); + DEBUG_VERBOSE("Flash close %X", rv); + + return rv == FSP_SUCCESS; +} + +static OTACloudProcessInterface::State convertUnor4ErrorToState(int error_code) { + switch(error_code) { + case -2: + return OTACloudProcessInterface::NoOtaStorageFail; + case -3: + return OTACloudProcessInterface::OtaStorageInitFail; + case -4: + return OTACloudProcessInterface::OtaStorageEndFail; + case -5: + return OTACloudProcessInterface::UrlParseErrorFail; + case -6: + return OTACloudProcessInterface::ServerConnectErrorFail; + case -7: + return OTACloudProcessInterface::HttpHeaderErrorFail; + case -8: + return OTACloudProcessInterface::ParseHttpHeaderFail; + case -9: + return OTACloudProcessInterface::OtaHeaderLengthFail; + case -10: + return OTACloudProcessInterface::OtaHeaderCrcFail; + case -11: + return OTACloudProcessInterface::OtaHeaderMagicNumberFail; + case -12: + return OTACloudProcessInterface::OtaDownloadFail; + case -13: + return OTACloudProcessInterface::OtaHeaderTimeoutFail; + case -14: + return OTACloudProcessInterface::HttpResponseFail; + case -25: + return OTACloudProcessInterface::LibraryFail; + case -26: + return OTACloudProcessInterface::ModemFail; + default: + DEBUG_VERBOSE("Unrecognized error code %d", error_code); + return OTACloudProcessInterface::Fail; + } +} + #endif // defined(ARDUINO_UNOR4_WIFI) && OTA_ENABLED diff --git a/src/ota/implementation/OTAUnoR4.h b/src/ota/implementation/OTAUnoR4.h index 871ea58a8..28c70e2f1 100644 --- a/src/ota/implementation/OTAUnoR4.h +++ b/src/ota/implementation/OTAUnoR4.h @@ -1,22 +1,52 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + #pragma once -#include "src/ota/interface/OTAInterface.h" +#include "ota/interface/OTAInterface.h" #include "OTAUpdate.h" #include "r_flash_lp.h" class UNOR4OTACloudProcess: public OTACloudProcessInterface { public: - STM32H7OTACloudProcess(); + UNOR4OTACloudProcess(MessageStream *ms); + + bool isOtaCapable() override; protected: - // we start the download and decompress process - virtual State fetch(Message* msg=nullptr); + virtual OTACloudProcessInterface::State resume(Message* msg=nullptr) override; + + // we are overriding the method of startOTA in order to download ota file on ESP32 + virtual OTACloudProcessInterface::State startOTA() override; - // when the download is completed we verify for integrity and correctness of the downloaded binary - // virtual State verifyOTA(Message* msg=nullptr); // TODO this may be performed inside download + // we start the download and decompress process + virtual OTACloudProcessInterface::State fetch() override; // whene the download is correctly finished we set the mcu to use the newly downloaded binary - virtual State flashOTA(Message* msg=nullptr); + virtual OTACloudProcessInterface::State flashOTA() override; // we reboot the device - virtual State reboot(Message* msg=nullptr); + virtual OTACloudProcessInterface::State reboot() override; + + virtual void reset() override; + + constexpr void* appStartAddress(); + uint32_t appSize(); + + bool appFlashOpen(); + bool appFlashClose(); + +public: + // used to access to flash memory for sha256 calculation + flash_lp_instance_ctrl_t ctrl; + flash_cfg_t cfg; + + OTAUpdate ota; + static const char UPDATE_FILE_NAME[]; }; From 8bbc4e7d84fa82bef3a9b7b7c83efea54f1cdbde Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 5 Feb 2024 09:12:47 +0100 Subject: [PATCH 585/780] Defining encoder/decoder interfaces --- src/interfaces/Decoder.h | 41 ++++++++++++++++++++++++++++++++++++++++ src/interfaces/Encoder.h | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/interfaces/Decoder.h create mode 100644 src/interfaces/Encoder.h diff --git a/src/interfaces/Decoder.h b/src/interfaces/Decoder.h new file mode 100644 index 000000000..fc725ec8b --- /dev/null +++ b/src/interfaces/Decoder.h @@ -0,0 +1,41 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +/****************************************************************************** + * INCLUDES + ******************************************************************************/ + +#include +#include + +/****************************************************************************** + * CLASS DECLARATION + ******************************************************************************/ + +class Decoder { +public: + enum Status: uint8_t { + Complete, + InProgress, + Error + }; + + /** + * Decode a buffer into a provided message structure + * @param msg: the message structure that is going to be filled with data provided in the buffer + * @param buf: the incoming buffer that needs to be decoded + * @param len: the length of the incoming buffer, value will be updated with the used len of the buffer + * @return SUCCESS: if the message is decoded correctly + * ERROR: if the message wasn't decoded correctly + */ + virtual Status decode(Message* msg, const uint8_t* const buf, size_t &len) = 0; +}; diff --git a/src/interfaces/Encoder.h b/src/interfaces/Encoder.h new file mode 100644 index 000000000..38fbe0edd --- /dev/null +++ b/src/interfaces/Encoder.h @@ -0,0 +1,40 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +/****************************************************************************** + * INCLUDES + ******************************************************************************/ +#include +#include + +/****************************************************************************** + * CLASS DECLARATION + ******************************************************************************/ + +class Encoder { +public: + enum Status: uint8_t { + Complete, + InProgress, + Error + }; + + /** + * Encode a message into a buffer in a single shot + * @param msg: the message that needs to be encoded + * @param buf: the buffer the message will be encoded into + * @param len: the length of the provided buffer, value will be updated with the consumed len of the buffer + * @return SUCCESS: if the message is encoded correctly + * ERROR: error during the encoding of the message + */ + virtual Status encode(Message* msg, uint8_t* buf, size_t& len) = 0; +}; From 5de85593f9258f51f73d990825770a4c49ec7bcc Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 25 Mar 2024 15:57:35 +0100 Subject: [PATCH 586/780] Add TLSClientOta --- src/tls/utility/TLSClientOta.cpp | 64 +++++++++++++++++++++ src/tls/utility/TLSClientOta.h | 96 ++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 src/tls/utility/TLSClientOta.cpp create mode 100644 src/tls/utility/TLSClientOta.h diff --git a/src/tls/utility/TLSClientOta.cpp b/src/tls/utility/TLSClientOta.cpp new file mode 100644 index 000000000..8aabf652e --- /dev/null +++ b/src/tls/utility/TLSClientOta.cpp @@ -0,0 +1,64 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#include + +#if defined(HAS_TCP) && OTA_ENABLED + +#include "TLSClientOta.h" + +#if defined(BOARD_HAS_SECRET_KEY) + #include "tls/AIoTCUPCert.h" +#endif + +#if defined(BOARD_HAS_SE050) || defined(BOARD_HAS_SOFTSE) + #include "tls/AIoTCSSCert.h" +#endif + +#ifdef BOARD_HAS_ECCX08 + #include "tls/BearSSLTrustAnchors.h" + extern "C" { + void aiotc_client_profile_init(br_ssl_client_context *cc, + br_x509_minimal_context *xc, + const br_x509_trust_anchor *trust_anchors, + size_t trust_anchors_num); + unsigned long getTime(); + } +#endif + +void TLSClientOta::begin(ConnectionHandler &connection) { +#if defined(BOARD_HAS_OFFLOADED_ECCX08) + /* AWS Root CAs are configured in nina-fw + * https://github.com/arduino/nina-fw/blob/master/data/roots.pem + */ +#elif defined(BOARD_HAS_ECCX08) + setClient(*getNewClient(connection.getInterface())); + setProfile(aiotc_client_profile_init); + setTrustAnchors(ArduinoIoTCloudTrustAnchor, ArduinoIoTCloudTrustAnchor_NUM); + onGetTime(getTime); +#elif defined(ARDUINO_PORTENTA_C33) + setClient(*getNewClient(connection.getInterface())); + setCACert(AIoTSSCert); +#elif defined(ARDUINO_NICLA_VISION) + appendCustomCACert(AIoTSSCert); +#elif defined(ARDUINO_EDGE_CONTROL) + appendCustomCACert(AIoTUPCert); +#elif defined(ARDUINO_UNOR4_WIFI) + /* AWS Root CAs are configured in uno-r4-wifi-usb-bridge/libraries/Arduino_ESP32_OTA + * https://github.com/arduino-libraries/Arduino_ESP32_OTA/blob/fc755e7d1d3946232107e2590662ee08d6ccdec4/src/tls/amazon_root_ca.h + */ +#elif defined(ARDUINO_ARCH_ESP32) + setCACertBundle(x509_crt_bundle); +#elif defined(ARDUINO_ARCH_ESP8266) + setInsecure(); +#endif +} + +#endif diff --git a/src/tls/utility/TLSClientOta.h b/src/tls/utility/TLSClientOta.h new file mode 100644 index 000000000..3e76433ab --- /dev/null +++ b/src/tls/utility/TLSClientOta.h @@ -0,0 +1,96 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +#include +#include + +#if defined(BOARD_HAS_OFFLOADED_ECCX08) + /* + * Arduino MKR WiFi1010 - WiFi + * Arduino NANO 33 IoT - WiFi + */ + #include "WiFiSSLClient.h" + class TLSClientOta : public WiFiBearSSLClient { +#elif defined(BOARD_HAS_ECCX08) + /* + * Arduino MKR GSM 1400 + * Arduino MKR NB 1500 + * Arduino Portenta H7 + * Arduino Giga R1 + * OPTA + */ + #include + class TLSClientOta : public BearSSLClient { +#elif defined(ARDUINO_PORTENTA_C33) + /* + * Arduino Portenta C33 + */ + #include + class TLSClientOta : public SSLClient { +#elif defined(ARDUINO_NICLA_VISION) + /* + * Arduino Nicla Vision + */ + #include + class TLSClientOta : public WiFiSSLSE050Client { +#elif defined(ARDUINO_EDGE_CONTROL) + /* + * Arduino Edge Control + */ + #include + class TLSClientOta : public GSMSSLClient { +#elif defined(ARDUINO_UNOR4_WIFI) + /* + * Arduino UNO R4 WiFi + */ + #include + class TLSClientOta : public WiFiSSLClient { +#elif defined(BOARD_ESP) + /* + * ESP32* + * ESP82* + */ + #include + class TLSClientOta : public WiFiClientSecure { +#endif + +public: + void begin(ConnectionHandler & connection); + +private: + inline Client* getNewClient(NetworkAdapter net) { + switch(net) { +#ifdef BOARD_HAS_WIFI + case NetworkAdapter::WIFI: + return new WiFiClient(); +#endif // BOARD_HAS_WIFI +#ifdef BOARD_HAS_ETHERNET + case NetworkAdapter::ETHERNET: + return new EthernetClient(); +#endif // BOARD_HAS_ETHERNET +#ifdef BOARD_HAS_NB + case NetworkAdapter::NB: + return new NBClient(); +#endif // BOARD_HAS_NB +#ifdef BOARD_HAS_GSM + case NetworkAdapter::GSM: + return new GSMClient(); +#endif // BOARD_HAS_GSM +#ifdef BOARD_HAS_CATM1_NBIOT + case NetworkAdapter::CATM1: + return new GSMClient(); +#endif // BOARD_HAS_CATM1_NBIOT + default: + return nullptr; + } + } +}; From 0a811cb14d0aadbbee4329ec47d048015fa75eed Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 29 Feb 2024 14:02:00 +0100 Subject: [PATCH 587/780] implemented esp32 ota class --- src/ota/implementation/OTAEsp32.cpp | 114 ++++++++++++++++++++++++++++ src/ota/implementation/OTAEsp32.h | 41 +++++++--- 2 files changed, 146 insertions(+), 9 deletions(-) diff --git a/src/ota/implementation/OTAEsp32.cpp b/src/ota/implementation/OTAEsp32.cpp index 7ac036134..f52e64721 100644 --- a/src/ota/implementation/OTAEsp32.cpp +++ b/src/ota/implementation/OTAEsp32.cpp @@ -1,3 +1,117 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#include "AIoTC_Config.h" #if defined(ARDUINO_ARCH_ESP32) && OTA_ENABLED +#include "OTAEsp32.h" +#include +#include + +ESP32OTACloudProcess::ESP32OTACloudProcess(MessageStream *ms, Client* client) +: OTADefaultCloudProcessInterface(ms), rom_partition(nullptr) { + +} + + +OTACloudProcessInterface::State ESP32OTACloudProcess::resume(Message* msg) { + return OtaBegin; +} + +OTACloudProcessInterface::State ESP32OTACloudProcess::startOTA() { + if(Update.isRunning()) { + Update.abort(); + DEBUG_VERBOSE("%s: Aborting running update", __FUNCTION__); + } + + if(!Update.begin(UPDATE_SIZE_UNKNOWN)) { + DEBUG_VERBOSE("%s: failed to initialize flash update", __FUNCTION__); + return OtaStorageInitFail; + } + + return OTADefaultCloudProcessInterface::startOTA(); +} + +OTACloudProcessInterface::State ESP32OTACloudProcess::flashOTA() { + + if (!Update.end(true)) { + DEBUG_VERBOSE("%s: Failure to apply OTA update", __FUNCTION__); + return OtaStorageEndFail; + } + + return Reboot; +} + +OTACloudProcessInterface::State ESP32OTACloudProcess::reboot() { + ESP.restart(); + + return Idle; // we won't reach this +} + +int ESP32OTACloudProcess::writeFlash(uint8_t* const buffer, size_t len) { + return Update.write(buffer, len); +} + +bool ESP32OTACloudProcess::isOtaCapable() { + const esp_partition_t * ota_0 = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_0, NULL); + const esp_partition_t * ota_1 = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1, NULL); + return ((ota_0 != nullptr) && (ota_1 != nullptr)); +} + +void* ESP32OTACloudProcess::appStartAddress() { + return nullptr; +} +uint32_t ESP32OTACloudProcess::appSize() { + return ESP.getSketchSize(); +} + +bool ESP32OTACloudProcess::appFlashOpen() { + rom_partition = esp_ota_get_running_partition(); + + if(rom_partition == nullptr) { + return false; + } + + return true; +} + +void ESP32OTACloudProcess::calculateSHA256(SHA256& sha256_calc) { + if(!appFlashOpen()) { + return; // TODO error reporting + } + + sha256_calc.begin(); + + uint8_t b[SPI_FLASH_SEC_SIZE]; + if(b == nullptr) { + DEBUG_VERBOSE("ESP32::SHA256 Not enough memory to allocate buffer"); + return; // TODO error reporting + } + + uint32_t read_bytes = 0; + uint32_t const app_size = ESP.getSketchSize(); + for(uint32_t a = rom_partition->address; read_bytes < app_size; ) { + /* Check if we are reading last sector and compute used size */ + uint32_t const read_size = read_bytes + SPI_FLASH_SEC_SIZE < app_size ? + SPI_FLASH_SEC_SIZE : app_size - read_bytes; + + /* Use always 4 bytes aligned reads */ + if (!ESP.flashRead(a, reinterpret_cast(b), (read_size + 3) & ~3)) { + DEBUG_VERBOSE("ESP32::SHA256 Could not read data from flash"); + return; + } + sha256_calc.update(b, read_size); + a += read_size; + read_bytes += read_size; + } + + appFlashClose(); +} #endif // defined(ARDUINO_ARCH_ESP32) && OTA_ENABLED \ No newline at end of file diff --git a/src/ota/implementation/OTAEsp32.h b/src/ota/implementation/OTAEsp32.h index 8654d2c7e..b904308e8 100644 --- a/src/ota/implementation/OTAEsp32.h +++ b/src/ota/implementation/OTAEsp32.h @@ -1,20 +1,43 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + #pragma once -#include "src/ota/interface/OTAInterface.h" +#include "ota/interface/OTAInterfaceDefault.h" -class ESP32OTACloudProcess: public OTACloudProcessInterface { +class ESP32OTACloudProcess: public OTADefaultCloudProcessInterface { public: - STM32H7OTACloudProcess(); + ESP32OTACloudProcess(MessageStream *ms, Client* client=nullptr); + + virtual bool isOtaCapable() override; protected: - // we start the download and decompress process - virtual State fetch(Message* msg=nullptr); + virtual OTACloudProcessInterface::State resume(Message* msg=nullptr) override; - // when the download is completed we verify for integrity and correctness of the downloaded binary - // virtual State verifyOTA(Message* msg=nullptr); // TODO this may be performed inside download + // we are overriding the method of startOTA in order to download ota file on ESP32 + virtual OTACloudProcessInterface::State startOTA() override; // whene the download is correctly finished we set the mcu to use the newly downloaded binary - virtual State flashOTA(Message* msg=nullptr); + virtual State flashOTA() override; // we reboot the device - virtual State reboot(Message* msg=nullptr); + virtual State reboot() override; + + // write the decompressed char buffer of the incoming ota + virtual int writeFlash(uint8_t* const buffer, size_t len) override; + + void* appStartAddress(); + uint32_t appSize(); + bool appFlashOpen(); + bool appFlashClose() { return true; }; + + void calculateSHA256(SHA256&) override; +private: + const esp_partition_t *rom_partition; }; From 06e2adc0dde03f4c58480508ee409255ee40e0c7 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 17 Apr 2024 17:31:35 +0200 Subject: [PATCH 588/780] CBOR encoder and decoder implementation for Command protocol model --- src/cbor/CBOR.cpp | 73 ++++++++++++ src/cbor/CBOR.h | 49 ++++++++ src/cbor/MessageDecoder.cpp | 230 ++++++++++++++++++++++++++++++++++++ src/cbor/MessageDecoder.h | 74 ++++++++++++ src/cbor/MessageEncoder.cpp | 175 +++++++++++++++++++++++++++ src/cbor/MessageEncoder.h | 65 ++++++++++ 6 files changed, 666 insertions(+) create mode 100644 src/cbor/CBOR.cpp create mode 100644 src/cbor/CBOR.h create mode 100644 src/cbor/MessageDecoder.cpp create mode 100644 src/cbor/MessageDecoder.h create mode 100644 src/cbor/MessageEncoder.cpp create mode 100644 src/cbor/MessageEncoder.h diff --git a/src/cbor/CBOR.cpp b/src/cbor/CBOR.cpp new file mode 100644 index 000000000..ced5e3e7f --- /dev/null +++ b/src/cbor/CBOR.cpp @@ -0,0 +1,73 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include "CBOR.h" + +/****************************************************************************** + * FUNCTION DEFINITION + ******************************************************************************/ + +CommandId toCommandId(CBORCommandTag tag) { + switch(tag) { + case CBORCommandTag::CBOROtaBeginUp: + return CommandId::OtaBeginUpId; + case CBORCommandTag::CBORThingBeginCmd: + return CommandId::ThingBeginCmdId; + case CBORCommandTag::CBORLastValuesBeginCmd: + return CommandId::LastValuesBeginCmdId; + case CBORCommandTag::CBORDeviceBeginCmd: + return CommandId::DeviceBeginCmdId; + case CBORCommandTag::CBOROtaProgressCmdUp: + return CommandId::OtaProgressCmdUpId; + case CBORCommandTag::CBORTimezoneCommandUp: + return CommandId::TimezoneCommandUpId; + case CBORCommandTag::CBOROtaUpdateCmdDown: + return CommandId::OtaUpdateCmdDownId; + case CBORCommandTag::CBORThingUpdateCmd: + return CommandId::ThingUpdateCmdId; + case CBORCommandTag::CBORLastValuesUpdate: + return CommandId::LastValuesUpdateCmdId; + case CBORCommandTag::CBORTimezoneCommandDown: + return CommandId::TimezoneCommandDownId; + default: + return CommandId::UnknownCmdId; + } +} + +CBORCommandTag toCBORCommandTag(CommandId id) { + switch(id) { + case CommandId::OtaBeginUpId: + return CBORCommandTag::CBOROtaBeginUp; + case CommandId::ThingBeginCmdId: + return CBORCommandTag::CBORThingBeginCmd; + case CommandId::LastValuesBeginCmdId: + return CBORCommandTag::CBORLastValuesBeginCmd; + case CommandId::DeviceBeginCmdId: + return CBORCommandTag::CBORDeviceBeginCmd; + case CommandId::OtaProgressCmdUpId: + return CBORCommandTag::CBOROtaProgressCmdUp; + case CommandId::TimezoneCommandUpId: + return CBORCommandTag::CBORTimezoneCommandUp; + case CommandId::OtaUpdateCmdDownId: + return CBORCommandTag::CBOROtaUpdateCmdDown; + case CommandId::ThingUpdateCmdId: + return CBORCommandTag::CBORThingUpdateCmd; + case CommandId::LastValuesUpdateCmdId: + return CBORCommandTag::CBORLastValuesUpdate; + case CommandId::TimezoneCommandDownId: + return CBORCommandTag::CBORTimezoneCommandDown; + default: + return CBORCommandTag::CBORUnknownCmdTag; + } +} diff --git a/src/cbor/CBOR.h b/src/cbor/CBOR.h new file mode 100644 index 000000000..999570455 --- /dev/null +++ b/src/cbor/CBOR.h @@ -0,0 +1,49 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ +#include + +/****************************************************************************** + TYPEDEF + ******************************************************************************/ + +enum CBORCommandTag: uint64_t { + // Commands UP + CBOROtaBeginUp = 0x010000, + CBORThingBeginCmd = 0x010300, + CBORLastValuesBeginCmd = 0x010500, + CBORDeviceBeginCmd = 0x010700, + CBOROtaProgressCmdUp = 0x010200, + CBORTimezoneCommandUp = 0x010800, + + // Commands DOWN + CBOROtaUpdateCmdDown = 0x010100, + CBORThingUpdateCmd = 0x010400, + CBORLastValuesUpdate = 0x010600, + CBORTimezoneCommandDown = 0x010900, + + // Unknown Command Tag https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml + CBORUnknownCmdTag16b = 0xffff, // invalid tag + CBORUnknownCmdTag32b = 0xffffffff, // invalid tag + CBORUnknownCmdTag64b = 0xffffffffffffffff, // invalid tag + CBORUnknownCmdTag = CBORUnknownCmdTag32b +}; + +/****************************************************************************** + * FUNCTION DECLARATION + ******************************************************************************/ + +CommandId toCommandId(CBORCommandTag tag); +CBORCommandTag toCBORCommandTag(CommandId id); diff --git a/src/cbor/MessageDecoder.cpp b/src/cbor/MessageDecoder.cpp new file mode 100644 index 000000000..c500ceae9 --- /dev/null +++ b/src/cbor/MessageDecoder.cpp @@ -0,0 +1,230 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +/****************************************************************************** + INCLUDE + ******************************************************************************/ + +#include + +#undef max +#undef min +#include + +#include "MessageDecoder.h" +#include + +/****************************************************************************** + PUBLIC MEMBER FUNCTIONS + ******************************************************************************/ + +Decoder::Status CBORMessageDecoder::decode(Message * message, uint8_t const * const payload, size_t& length) +{ + CborValue main_iter, array_iter; + CborTag tag; + CborParser parser; + + if (cbor_parser_init(payload, length, 0, &parser, &main_iter) != CborNoError) + return Decoder::Status::Error; + + if (main_iter.type != CborTagType) + return Decoder::Status::Error; + + if (cbor_value_get_tag(&main_iter, &tag) == CborNoError) { + message->id = toCommandId(CBORCommandTag(tag)); + } + + if (cbor_value_advance(&main_iter) != CborNoError) { + return Decoder::Status::Error; + } + + ArrayParserState current_state = ArrayParserState::EnterArray, + next_state = ArrayParserState::Error; + + while (current_state != ArrayParserState::Complete) { + switch (current_state) { + case ArrayParserState::EnterArray : next_state = handle_EnterArray(&main_iter, &array_iter); break; + case ArrayParserState::ParseParam : next_state = handle_Param(&array_iter, message); break; + case ArrayParserState::LeaveArray : next_state = handle_LeaveArray(&main_iter, &array_iter); break; + case ArrayParserState::Complete : return Decoder::Status::Complete; + case ArrayParserState::MessageNotSupported : return Decoder::Status::Error; + case ArrayParserState::Error : return Decoder::Status::Error; + } + + current_state = next_state; + } + + return Decoder::Status::Complete; +} + +/****************************************************************************** + PRIVATE MEMBER FUNCTIONS + ******************************************************************************/ + +bool copyCBORStringToArray(CborValue * param, char * dest, size_t dest_size) { + if (cbor_value_is_text_string(param)) { + // NOTE: keep in mind that _cbor_value_copy_string tries to put a \0 at the end of the string + if(_cbor_value_copy_string(param, dest, &dest_size, NULL) == CborNoError) { + return true; + } + } + + return false; +} + +// FIXME dest_size should be also returned, the copied byte array can have a different size from the starting one +// for the time being we need this on SHA256 only +bool copyCBORByteToArray(CborValue * param, uint8_t * dest, size_t dest_size) { + if (cbor_value_is_byte_string(param)) { + // NOTE: keep in mind that _cbor_value_copy_string tries to put a \0 at the end of the string + if(_cbor_value_copy_string(param, dest, &dest_size, NULL) == CborNoError) { + return true; + } + } + + return false; +} + +CBORMessageDecoder::ArrayParserState CBORMessageDecoder::handle_EnterArray(CborValue * main_iter, CborValue * array_iter) { + ArrayParserState next_state = ArrayParserState::Error; + if (cbor_value_get_type(main_iter) == CborArrayType) { + if (cbor_value_enter_container(main_iter, array_iter) == CborNoError) { + next_state = ArrayParserState::ParseParam; + } + } + + return next_state; +} + +CBORMessageDecoder::ArrayParserState CBORMessageDecoder::handle_LeaveArray(CborValue * main_iter, CborValue * array_iter) { + // Advance to the next parameter (the last one in the array) + if (cbor_value_advance(array_iter) == CborNoError) { + // Leave the array + if (cbor_value_leave_container(main_iter, array_iter) == CborNoError) { + return ArrayParserState::Complete; + } + } + + return ArrayParserState::Error; +} + +/****************************************************************************** + MESSAGE DECODE FUNCTIONS + ******************************************************************************/ + +CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeThingUpdateCmd(CborValue * param, Message * message) { + ThingUpdateCmd * thingCommand = (ThingUpdateCmd *) message; + + // Message is composed of a single parameter, a string (thing_id) + if (!copyCBORStringToArray(param, thingCommand->params.thing_id, sizeof(thingCommand->params.thing_id))) { + return ArrayParserState::Error; + } + + return ArrayParserState::LeaveArray; +} + +CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeTimezoneCommandDown(CborValue * param, Message * message) { + TimezoneCommandDown * setTz = (TimezoneCommandDown *) message; + + // Message is composed of 2 parameters, offset 32-bit signed integer and until 32-bit unsigned integer + // Get offset + if (cbor_value_is_integer(param)) { + int64_t val = 0; + if (cbor_value_get_int64(param, &val) == CborNoError) { + setTz->params.offset = static_cast(val); + } + } + + // Next + if (cbor_value_advance(param) != CborNoError) { + return ArrayParserState::Error; + } + + // Get until + if (cbor_value_is_integer(param)) { + uint64_t val = 0; + if (cbor_value_get_uint64(param, &val) == CborNoError) { + setTz->params.until = static_cast(val); + } + } + + return ArrayParserState::LeaveArray; +} + +CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeLastValuesUpdateCmd(CborValue * param, Message * message) { + LastValuesUpdateCmd * setLv = (LastValuesUpdateCmd *) message; + + // Message is composed by a single parameter, a variable length byte array. + if (cbor_value_is_byte_string(param)) { + // Cortex M0 is not able to assign a value to pointed memory that is not 32bit aligned + // we use a support variable to cope with that + size_t s; + if (cbor_value_dup_byte_string(param, &setLv->params.last_values, &s, NULL) != CborNoError) { + return ArrayParserState::Error; + } + + setLv->params.length = s; + } + + return ArrayParserState::LeaveArray; +} + +CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeOtaUpdateCmdDown(CborValue * param, Message * message) { + CborError error = CborNoError; + OtaUpdateCmdDown * ota = (OtaUpdateCmdDown *) message; + + // Message is composed 4 parameters: id, url, initialSha, finalSha + if (!copyCBORByteToArray(param, ota->params.id, sizeof(ota->params.id))) { + return ArrayParserState::Error; + } + + error = cbor_value_advance(param); + + if ((error != CborNoError) || !copyCBORStringToArray(param, ota->params.url, sizeof(ota->params.url))) { + return ArrayParserState::Error; + } + + error = cbor_value_advance(param); + + if ((error != CborNoError) || !copyCBORByteToArray(param, ota->params.initialSha256, sizeof(ota->params.initialSha256))) { + return ArrayParserState::Error; + } + + error = cbor_value_advance(param); + + if ((error != CborNoError) || !copyCBORByteToArray(param, ota->params.finalSha256, sizeof(ota->params.finalSha256))) { + return ArrayParserState::Error; + } + + return ArrayParserState::LeaveArray; +} + +CBORMessageDecoder::ArrayParserState CBORMessageDecoder::handle_Param(CborValue * param, Message * message) { + + switch (message->id) + { + case CommandId::ThingUpdateCmdId: + return CBORMessageDecoder::decodeThingUpdateCmd(param, message); + + case CommandId::TimezoneCommandDownId: + return CBORMessageDecoder::decodeTimezoneCommandDown(param, message); + + case CommandId::LastValuesUpdateCmdId: + return CBORMessageDecoder::decodeLastValuesUpdateCmd(param, message); + + case CommandId::OtaUpdateCmdDownId: + return CBORMessageDecoder::decodeOtaUpdateCmdDown(param, message); + + default: + return ArrayParserState::MessageNotSupported; + } + + return ArrayParserState::LeaveArray; +} diff --git a/src/cbor/MessageDecoder.h b/src/cbor/MessageDecoder.h new file mode 100644 index 000000000..712289c9d --- /dev/null +++ b/src/cbor/MessageDecoder.h @@ -0,0 +1,74 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#ifndef ARDUINO_CBOR_MESSAGE_DECODER_H_ +#define ARDUINO_CBOR_MESSAGE_DECODER_H_ + +/****************************************************************************** + INCLUDE + ******************************************************************************/ + +#include + +#undef max +#undef min +#include + +#include "CBOR.h" +#include "../interfaces/Decoder.h" +#include "lib/tinycbor/cbor-lib.h" + +/****************************************************************************** + CLASS DECLARATION + ******************************************************************************/ + +class CBORMessageDecoder: public Decoder +{ +public: + CBORMessageDecoder() { } + CBORMessageDecoder(CBORMessageDecoder const &) { } + + /* decode a CBOR payload received from the cloud */ + Decoder::Status decode(Message * msg, uint8_t const * const payload, size_t& length); + +private: + + enum class DecoderState { + Success, + MessageNotSupported, + MalformedMessage, + Error + }; + + enum class ArrayParserState { + EnterArray, + ParseParam, + LeaveArray, + Complete, + Error, + MessageNotSupported + }; + + ArrayParserState handle_EnterArray(CborValue * main_iter, CborValue * array_iter); + ArrayParserState handle_Param(CborValue * param, Message * message); + ArrayParserState handle_LeaveArray(CborValue * main_iter, CborValue * array_iter); + + bool ifNumericConvertToDouble(CborValue * value_iter, double * numeric_val); + double convertCborHalfFloatToDouble(uint16_t const half_val); + + // Message specific decoders + ArrayParserState decodeThingUpdateCmd(CborValue * param, Message * message); + ArrayParserState decodeTimezoneCommandDown(CborValue * param, Message * message); + ArrayParserState decodeLastValuesUpdateCmd(CborValue * param, Message * message); + ArrayParserState decodeOtaUpdateCmdDown(CborValue * param, Message * message); + +}; + +#endif /* ARDUINO_CBOR_MESSAGE_DECODER_H_ */ diff --git a/src/cbor/MessageEncoder.cpp b/src/cbor/MessageEncoder.cpp new file mode 100644 index 000000000..cdeb0f8ed --- /dev/null +++ b/src/cbor/MessageEncoder.cpp @@ -0,0 +1,175 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include "CBOREncoder.h" + +#undef max +#undef min +#include +#include + +#include "lib/tinycbor/cbor-lib.h" +#include "MessageEncoder.h" + +/****************************************************************************** + * PUBLIC MEMBER FUNCTIONS + ******************************************************************************/ + +Encoder::Status CBORMessageEncoder::encode(Message * message, uint8_t * data, size_t& len) +{ + EncoderState current_state = EncoderState::EncodeTag, + next_state = EncoderState::Error; + + CborEncoder encoder; + CborEncoder arrayEncoder; + + cbor_encoder_init(&encoder, data, len, 0); + + while (current_state != EncoderState::Complete) { + + switch (current_state) { + case EncoderState::EncodeTag : next_state = handle_EncodeTag(&encoder, message); break; + case EncoderState::EncodeArray : next_state = handle_EncodeArray(&encoder, &arrayEncoder, message); break; + case EncoderState::EncodeParam : next_state = handle_EncodeParam(&arrayEncoder, message); break; + case EncoderState::CloseArray : next_state = handle_CloseArray(&encoder, &arrayEncoder); break; + case EncoderState::Complete : /* Nothing to do */ break; + case EncoderState::MessageNotSupported : + case EncoderState::Error : return Encoder::Status::Error; + } + + current_state = next_state; + } + + len = cbor_encoder_get_buffer_size(&encoder, data); + + return Encoder::Status::Complete; +} + +/****************************************************************************** + PRIVATE MEMBER FUNCTIONS + ******************************************************************************/ + +CBORMessageEncoder::EncoderState CBORMessageEncoder::handle_EncodeTag(CborEncoder * encoder, Message * message) +{ + CborTag commandTag = toCBORCommandTag(message->id); + if (commandTag == CBORCommandTag::CBORUnknownCmdTag16b || + commandTag == CBORCommandTag::CBORUnknownCmdTag32b || + commandTag == CBORCommandTag::CBORUnknownCmdTag64b || + cbor_encode_tag(encoder, commandTag) != CborNoError) { + return EncoderState::Error; + } + + return EncoderState::EncodeArray; +} + +CBORMessageEncoder::EncoderState CBORMessageEncoder::handle_EncodeArray(CborEncoder * encoder, CborEncoder * array_encoder, Message * message) +{ + // Set array size based on the message id + size_t array_size = 0; + switch (message->id) + { + case CommandId::OtaBeginUpId: + array_size = 1; + break; + case CommandId::ThingBeginCmdId: + array_size = 1; + break; + case CommandId::DeviceBeginCmdId: + array_size = 1; + break; + case CommandId::LastValuesBeginCmdId: + break; + case CommandId::OtaProgressCmdUpId: + array_size = 4; + break; + case CommandId::TimezoneCommandUpId: + break; + default: + return EncoderState::MessageNotSupported; + } + + // Start an array with fixed width based on message type + if (cbor_encoder_create_array(encoder, array_encoder, array_size) != CborNoError){ + return EncoderState::Error; + } + + return EncoderState::EncodeParam; +} + +CBORMessageEncoder::EncoderState CBORMessageEncoder::handle_EncodeParam(CborEncoder * array_encoder, Message * message) +{ + CborError error = CborNoError; + switch (message->id) + { + case CommandId::OtaBeginUpId: + error = CBORMessageEncoder::encodeOtaBeginUp(array_encoder, message); + break; + case CommandId::ThingBeginCmdId: + error = CBORMessageEncoder::encodeThingBeginCmd(array_encoder, message); + break; + case CommandId::DeviceBeginCmdId: + error = CBORMessageEncoder::encodeDeviceBeginCmd(array_encoder, message); + break; + case CommandId::LastValuesBeginCmdId: + break; + case CommandId::OtaProgressCmdUpId: + error = CBORMessageEncoder::encodeOtaProgressCmdUp(array_encoder, message); + break; + case CommandId::TimezoneCommandUpId: + break; + default: + return EncoderState::MessageNotSupported; + } + + return (error != CborNoError) ? EncoderState::Error : EncoderState::CloseArray; +} + +CBORMessageEncoder::EncoderState CBORMessageEncoder::handle_CloseArray(CborEncoder * encoder, CborEncoder * array_encoder) +{ + CborError error = cbor_encoder_close_container(encoder, array_encoder); + + return (error != CborNoError) ? EncoderState::Error : EncoderState::Complete; +} + +// Message specific encoders +CborError CBORMessageEncoder::encodeOtaBeginUp(CborEncoder * array_encoder, Message * message) +{ + OtaBeginUp * otaBeginUp = (OtaBeginUp *) message; + CHECK_CBOR(cbor_encode_byte_string(array_encoder, otaBeginUp->params.sha, SHA256_SIZE)); + return CborNoError; +} + +CborError CBORMessageEncoder::encodeThingBeginCmd(CborEncoder * array_encoder, Message * message) +{ + ThingBeginCmd * thingBeginCmd = (ThingBeginCmd *) message; + CHECK_CBOR(cbor_encode_text_stringz(array_encoder, thingBeginCmd->params.thing_id)); + return CborNoError; +} + +CborError CBORMessageEncoder::encodeDeviceBeginCmd(CborEncoder * array_encoder, Message * message) +{ + DeviceBeginCmd * deviceBeginCmd = (DeviceBeginCmd *) message; + CHECK_CBOR(cbor_encode_text_stringz(array_encoder, deviceBeginCmd->params.lib_version)); + return CborNoError; +} + +CborError CBORMessageEncoder::encodeOtaProgressCmdUp(CborEncoder * array_encoder, Message * message) +{ + OtaProgressCmdUp * ota = (OtaProgressCmdUp *)message; + CHECK_CBOR(cbor_encode_byte_string(array_encoder, ota->params.id, ID_SIZE)); + CHECK_CBOR(cbor_encode_simple_value(array_encoder, ota->params.state)); + CHECK_CBOR(cbor_encode_int(array_encoder, ota->params.state_data)); + CHECK_CBOR(cbor_encode_uint(array_encoder, ota->params.time)); + return CborNoError; +} diff --git a/src/cbor/MessageEncoder.h b/src/cbor/MessageEncoder.h new file mode 100644 index 000000000..86792eb19 --- /dev/null +++ b/src/cbor/MessageEncoder.h @@ -0,0 +1,65 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#ifndef ARDUINO_CBOR_MESSAGE_ENCODER_H_ +#define ARDUINO_CBOR_MESSAGE_ENCODER_H_ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include + +#undef max +#undef min +#include + +#include "CBOR.h" +#include "../interfaces/Encoder.h" +#include "lib/tinycbor/cbor-lib.h" + +/****************************************************************************** + * CLASS DECLARATION + ******************************************************************************/ + +class CBORMessageEncoder: public Encoder +{ + +public: + CBORMessageEncoder() { } + CBORMessageEncoder(CborEncoder const &) { } + Encoder::Status encode(Message * message, uint8_t * data, size_t& len); + +private: + + enum class EncoderState + { + EncodeTag, + EncodeArray, + EncodeParam, + CloseArray, + MessageNotSupported, + Complete, + Error + }; + + EncoderState handle_EncodeTag(CborEncoder * encoder, Message * message); + EncoderState handle_EncodeArray(CborEncoder * encoder, CborEncoder * array_encoder, Message * message); + EncoderState handle_EncodeParam(CborEncoder * array_encoder, Message * message); + EncoderState handle_CloseArray(CborEncoder * encoder, CborEncoder * array_encoder); + + // Message specific encoders + CborError encodeThingBeginCmd(CborEncoder * array_encoder, Message * message); + CborError encodeOtaBeginUp(CborEncoder * array_encoder, Message * message); + CborError encodeDeviceBeginCmd(CborEncoder * array_encoder, Message * message); + CborError encodeOtaProgressCmdUp(CborEncoder * array_encoder, Message * message); +}; + +#endif /* ARDUINO_CBOR_MESSAGE_ENCODER_H_ */ From f8f635c3f543416371cf5b434a450bb53d81915c Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 25 Mar 2024 15:54:19 +0100 Subject: [PATCH 589/780] BearSLL: increase input buffer size to allow file downloading --- src/AIoTC_Config.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index dad0c38ac..26bc377ad 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -115,9 +115,14 @@ #endif #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_OPTA) || defined(ARDUINO_GIGA) + #define BEAR_SSL_CLIENT_IBUF_SIZE (16384 + 325) // Allows download from storage API #define BOARD_STM32H7 #endif +#if defined(ARDUINO_NANO_RP2040_CONNECT) + #define BEAR_SSL_CLIENT_IBUF_SIZE (16384 + 325) // Allows download from storage API +#endif + #if defined(ARDUINO_EDGE_CONTROL) #define BOARD_HAS_SECRET_KEY #define HAS_TCP From aa78ef8ffc6a12f41aa7eded9789ad31b001b4ef Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 29 Feb 2024 15:07:20 +0100 Subject: [PATCH 590/780] implemented samd ota class --- src/ota/implementation/OTASamd.cpp | 93 ++++++++++++++++++++++++++++++ src/ota/implementation/OTASamd.h | 47 ++++++++++++--- 2 files changed, 132 insertions(+), 8 deletions(-) diff --git a/src/ota/implementation/OTASamd.cpp b/src/ota/implementation/OTASamd.cpp index 1dc307f46..bc9194491 100644 --- a/src/ota/implementation/OTASamd.cpp +++ b/src/ota/implementation/OTASamd.cpp @@ -1,4 +1,97 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#include + #if defined(ARDUINO_ARCH_SAMD) && OTA_ENABLED #include "OTASamd.h" +#include +#if OTA_STORAGE_SNU +# include +# include /* WiFiStorage */ +#endif + +SAMDOTACloudProcess::SAMDOTACloudProcess(MessageStream *ms) +: OTACloudProcessInterface(ms){ + +} + +OTACloudProcessInterface::State SAMDOTACloudProcess::resume(Message* msg) { + return OtaBegin; +} + +OTACloudProcessInterface::State SAMDOTACloudProcess::startOTA() { + reset(); + return Fetch; +} + +OTACloudProcessInterface::State SAMDOTACloudProcess::fetch() { +#if OTA_STORAGE_SNU + uint8_t nina_ota_err_code = 0; + if (!WiFiStorage.downloadOTA(this->context->url, &nina_ota_err_code)) { + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s error download to nina: %d", __FUNCTION__, nina_ota_err_code); + switch(static_cast(nina_ota_err_code)) { + case ninaOTAError::Open: + return ErrorOpenUpdateFileFail; + case ninaOTAError::Length: + return OtaDownloadFail; + case ninaOTAError::CRC: + return OtaHeaderCrcFail; + case ninaOTAError::Rename: + return ErrorRenameFail; + default: + return OtaDownloadFail; + } + } +#endif // OTA_STORAGE_SNU + + return FlashOTA; +} + +OTACloudProcessInterface::State SAMDOTACloudProcess::flashOTA() { + return Reboot; +} + +OTACloudProcessInterface::State SAMDOTACloudProcess::reboot() { + NVIC_SystemReset(); +} + +void SAMDOTACloudProcess::reset() { +#if OTA_STORAGE_SNU + WiFiStorage.remove("/fs/UPDATE.BIN.LZSS"); + WiFiStorage.remove("/fs/UPDATE.BIN.LZSS.TMP"); +#endif // OTA_STORAGE_SNU +} + +bool SAMDOTACloudProcess::isOtaCapable() { +#if OTA_STORAGE_SNU + if (strcmp(WiFi.firmwareVersion(), "1.4.1") < 0) { + DEBUG_VERBOSE("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; +} + +extern void* __text_start__; +extern void* __etext; +extern void* __data_end__; +extern void* __data_start__; + +void* SAMDOTACloudProcess::appStartAddress() { return &__text_start__; } + +uint32_t SAMDOTACloudProcess::appSize() { + return ((&__etext - &__text_start__) + (&__data_end__ - &__data_start__))*sizeof(void*); +} + #endif // defined(ARDUINO_ARCH_SAMD) && OTA_ENABLED \ No newline at end of file diff --git a/src/ota/implementation/OTASamd.h b/src/ota/implementation/OTASamd.h index 3c248dd17..3f448c779 100644 --- a/src/ota/implementation/OTASamd.h +++ b/src/ota/implementation/OTASamd.h @@ -1,21 +1,52 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + #pragma once -#include "src/ota/interface/OTAInterface.h" +#include "ota/interface/OTAInterface.h" #include class SAMDOTACloudProcess: public OTACloudProcessInterface { public: - STM32H7OTACloudProcess(); + SAMDOTACloudProcess(MessageStream *ms); + + virtual bool isOtaCapable() override; protected: - // we start the download and decompress process - virtual State fetch(Message* msg=nullptr); + virtual OTACloudProcessInterface::State resume(Message* msg=nullptr) override; - // when the download is completed we verify for integrity and correctness of the downloaded binary - // virtual State verifyOTA(Message* msg=nullptr); // TODO this may be performed inside download + // we are overriding the method of startOTA in order to download ota file on ESP32 + virtual OTACloudProcessInterface::State startOTA() override; + + // we start the download and decompress process + virtual OTACloudProcessInterface::State fetch() override; // whene the download is correctly finished we set the mcu to use the newly downloaded binary - virtual State flashOTA(Message* msg=nullptr); + virtual OTACloudProcessInterface::State flashOTA(); // we reboot the device - virtual State reboot(Message* msg=nullptr); + virtual OTACloudProcessInterface::State reboot(); + + virtual void reset() override; + + void* appStartAddress(); + uint32_t appSize(); + + bool appFlashOpen() { return true; } + bool appFlashClose() { return true; } + +private: + enum class ninaOTAError : int { + None = 0, + Open = 1, + Length = 2, + CRC = 3, + Rename = 4, + }; }; From 9c57868f715059feec2c02aa093c59cf729bd87d Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 17 Apr 2024 17:31:59 +0200 Subject: [PATCH 591/780] Add tests for encoder and decoder --- extras/test/CMakeLists.txt | 5 + extras/test/src/test_command_decode.cpp | 736 ++++++++++++++++++++++++ extras/test/src/test_command_encode.cpp | 322 +++++++++++ 3 files changed, 1063 insertions(+) create mode 100644 extras/test/src/test_command_decode.cpp create mode 100644 extras/test/src/test_command_encode.cpp diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index 2588c27c0..2aab9ab9b 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -36,6 +36,8 @@ set(TEST_SRCS src/test_CloudSchedule.cpp src/test_decode.cpp src/test_encode.cpp + src/test_command_decode.cpp + src/test_command_encode.cpp src/test_publishEvery.cpp src/test_publishOnChange.cpp src/test_publishOnChangeRateLimit.cpp @@ -55,6 +57,9 @@ set(TEST_DUT_SRCS ../../src/property/PropertyContainer.cpp ../../src/cbor/CBORDecoder.cpp ../../src/cbor/CBOREncoder.cpp + ../../src/cbor/MessageDecoder.cpp + ../../src/cbor/MessageEncoder.cpp + ../../src/cbor/CBOR.cpp ../../src/cbor/lib/tinycbor/src/cborencoder.c ../../src/cbor/lib/tinycbor/src/cborencoder_close_container_checked.c ../../src/cbor/lib/tinycbor/src/cborerrorstrings.c diff --git a/extras/test/src/test_command_decode.cpp b/extras/test/src/test_command_decode.cpp new file mode 100644 index 000000000..818d02136 --- /dev/null +++ b/extras/test/src/test_command_decode.cpp @@ -0,0 +1,736 @@ +/* + Copyright (c) 2024 Arduino. All rights reserved. +*/ + +/****************************************************************************** + INCLUDE + ******************************************************************************/ + +#include +#include + +#include + +#include +#include + +/****************************************************************************** + TEST CODE + ******************************************************************************/ + +SCENARIO("Test the decoding of command messages") { + /****************************************************************************/ + + WHEN("Decode the ThingUpdateCmdId message") + { + CommandDown command; + /* + DA 00010400 # tag(66560) + 81 # array(1) + 78 24 # text(36) + 65343439346435352D383732612D346664322D393634362D393266383739343933393463 # "e4494d55-872a-4fd2-9646-92f87949394c" + */ + uint8_t const payload[] = {0xDA, 0x00, 0x01, 0x04, 0x00, 0x81, 0x78, 0x24, + 0x65, 0x34, 0x34, 0x39, 0x34, 0x64, 0x35, 0x35, + 0x2D, 0x38, 0x37, 0x32, 0x61, 0x2D, 0x34, 0x66, + 0x64, 0x32, 0x2D, 0x39, 0x36, 0x34, 0x36, 0x2D, + 0x39, 0x32, 0x66, 0x38, 0x37, 0x39, 0x34, 0x39, + 0x33, 0x39, 0x34, 0x63}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + const char *thingIdToMatch = "e4494d55-872a-4fd2-9646-92f87949394c"; + + THEN("The decode is successful") { + REQUIRE(err == Decoder::Status::Complete); + REQUIRE(strcmp(command.thingUpdateCmd.params.thing_id, thingIdToMatch) == 0); + REQUIRE(command.c.id == ThingUpdateCmdId); + } + } + + /****************************************************************************/ + + WHEN("Decode the ThingUpdateCmdId message containing a number instead of a string") + { + CommandDown command; + /* + DA 00010400 # tag(66560) + 81 # array(1) + 1A 65DCB821 # unsigned(1708963873) + */ + uint8_t const payload[] = {0xDA, 0x00, 0x01, 0x04, 0x00, 0x81, 0x1A, 0x65, + 0xDC, 0xB8, 0x21}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful") { + REQUIRE(err == Decoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Decode the SetTimezoneCommand message") + { + CommandDown command; + + /* + DA 00010764 # tag(67840) + 82 # array(2) + 1A 65DCB821 # unsigned(1708963873) + 1A 78ACA191 # unsigned(2024579473) + */ + + uint8_t const payload[] = {0xDA, 0x00, 0x01, 0x09, 0x00, 0x82, 0x1A, 0x65, + 0xDC, 0xB8, 0x21, 0x1A, 0x78, 0xAC, 0xA1, 0x91}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is successful") { + REQUIRE(err == Decoder::Status::Complete); + REQUIRE(command.timezoneCommandDown.params.offset == (uint32_t)1708963873); + REQUIRE(command.timezoneCommandDown.params.until == (uint32_t)2024579473); + REQUIRE(command.c.id == TimezoneCommandDownId); + } + } + + /****************************************************************************/ + + WHEN("Decode the LastValuesUpdateCmd message") + { + CommandDown command; + + /* + DA 00010600 # tag(67072) + 81 # array(1) + 4D # bytes(13) + 00010203040506070809101112 # "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\u0010\u0011\u0012" + + */ + + uint8_t const payload[] = {0xDA, 0x00, 0x01, 0x06, 0x00, 0x81, 0x4D, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x10, 0x11, 0x12}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is successful") { + REQUIRE(err == Decoder::Status::Complete); + REQUIRE(command.lastValuesUpdateCmd.params.length == 13); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[0] == (uint8_t)0x00); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[1] == (uint8_t)0x01); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[2] == (uint8_t)0x02); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[3] == (uint8_t)0x03); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[4] == (uint8_t)0x04); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[5] == (uint8_t)0x05); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[6] == (uint8_t)0x06); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[7] == (uint8_t)0x07); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[8] == (uint8_t)0x08); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[9] == (uint8_t)0x09); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[10] == (uint8_t)0x10); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[11] == (uint8_t)0x11); + REQUIRE(command.lastValuesUpdateCmd.params.last_values[12] == (uint8_t)0x12); + REQUIRE(command.c.id == LastValuesUpdateCmdId); + } + free(command.lastValuesUpdateCmd.params.last_values); + } + + /****************************************************************************/ + + WHEN("Decode the OtaUpdateCmdDown message") + { + CommandDown command; + + /* + DA 00010100 # tag(65792) + 84 # array(4) + 50 # bytes(16) + C73CB045F9C2434585AFFA36A307BFE7"\xC7<\xB0E\xF9\xC2CE\x85\xAF\xFA6\xA3\a\xBF\xE7" + 78 72 # text(141) + 68747470733A2F2F626F617264732D69 + 6E742E6F6E69756472612E63632F7374 + 6F726167652F6669726D776172652F76 + 312F6466316561633963376264363334 + 37336666666231313766393837333730 + 33653465633935353933316532363766 + 32363236326230393439626331366463 + 3439 # "https://boards-int.oniudra.cc/storage/firmware/v1/df1eac9c7bd63473fffb117f9873703e4ec955931e267f26262b0949bc16dc49" + 58 20 # bytes(32) + 00000000000000000000000000000000 + 00000000000000000000000000000000# "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + 58 20 # bytes(32) + DF1EAC9C7BD63473FFFB117F9873703E + 4EC955931E267F26262B0949BC16DC49# "\xDF\u001E\xAC\x9C{\xD64s\xFF\xFB\u0011\u007F\x98sp>N\xC9U\x93\u001E&\u007F&&+\tI\xBC\u0016\xDCI" + + */ + uint8_t const payload[] = {0xda, 0x00, 0x01, 0x01, 0x00, 0x84, 0x50, 0xc7, + 0x3c, 0xb0, 0x45, 0xf9, 0xc2, 0x43, 0x45, 0x85, + 0xaf, 0xfa, 0x36, 0xa3, 0x07, 0xbf, 0xe7, 0x78, + 0x72, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, + 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x2d, + 0x69, 0x6e, 0x74, 0x2e, 0x6f, 0x6e, 0x69, 0x75, + 0x64, 0x72, 0x61, 0x2e, 0x63, 0x63, 0x2f, 0x73, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x66, + 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x2f, + 0x76, 0x31, 0x2f, 0x64, 0x66, 0x31, 0x65, 0x61, + 0x63, 0x39, 0x63, 0x37, 0x62, 0x64, 0x36, 0x33, + 0x34, 0x37, 0x33, 0x66, 0x66, 0x66, 0x62, 0x31, + 0x31, 0x37, 0x66, 0x39, 0x38, 0x37, 0x33, 0x37, + 0x30, 0x33, 0x65, 0x34, 0x65, 0x63, 0x39, 0x35, + 0x35, 0x39, 0x33, 0x31, 0x65, 0x32, 0x36, 0x37, + 0x66, 0x32, 0x36, 0x32, 0x36, 0x32, 0x62, 0x30, + 0x39, 0x34, 0x39, 0x62, 0x63, 0x31, 0x36, 0x64, + 0x63, 0x34, 0x39, 0x58, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x20, 0xdf, + 0x1e, 0xac, 0x9c, 0x7b, 0xd6, 0x34, 0x73, 0xff, + 0xfb, 0x11, 0x7f, 0x98, 0x73, 0x70, 0x3e, 0x4e, + 0xc9, 0x55, 0x93, 0x1e, 0x26, 0x7f, 0x26, 0x26, + 0x2b, 0x09, 0x49, 0xbc, 0x16, 0xdc, 0x49}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + uint8_t otaIdToMatch[ID_SIZE] = { 0xC7, 0x3C, 0xB0, 0x45, 0xF9, 0xC2, 0x43, 0x45, + 0x85, 0xAF, 0xFA, 0x36, 0xA3, 0x07, 0xBF, 0xE7}; + const char *urlToMatch = "https://boards-int.oniudra.cc/storage/firmware/v1/df1eac9c7bd63473fffb117f9873703e4ec955931e267f26262b0949bc16dc49"; + + THEN("The decode is successful") { + REQUIRE(err == Decoder::Status::Complete); + REQUIRE(memcmp(command.otaUpdateCmdDown.params.id, otaIdToMatch, ID_SIZE) == 0); + REQUIRE(strcmp(command.otaUpdateCmdDown.params.url, urlToMatch) == 0); + // Initial SHA256 check + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[0] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[1] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[2] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[3] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[4] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[5] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[6] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[7] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[8] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[9] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[10] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[11] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[12] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[13] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[14] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[15] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[16] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[17] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[18] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[19] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[20] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[21] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[22] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[23] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[24] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[25] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[26] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[27] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[28] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[29] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[30] == (uint8_t)0x00); + REQUIRE(command.otaUpdateCmdDown.params.initialSha256[31] == (uint8_t)0x00); + + // Final SHA256 check + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[0] == (uint8_t)0xdf); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[1] == (uint8_t)0x1e); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[2] == (uint8_t)0xac); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[3] == (uint8_t)0x9c); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[4] == (uint8_t)0x7b); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[5] == (uint8_t)0xd6); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[6] == (uint8_t)0x34); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[7] == (uint8_t)0x73); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[8] == (uint8_t)0xff); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[9] == (uint8_t)0xfb); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[10] == (uint8_t)0x11); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[11] == (uint8_t)0x7f); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[12] == (uint8_t)0x98); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[13] == (uint8_t)0x73); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[14] == (uint8_t)0x70); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[15] == (uint8_t)0x3e); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[16] == (uint8_t)0x4e); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[17] == (uint8_t)0xc9); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[18] == (uint8_t)0x55); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[19] == (uint8_t)0x93); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[20] == (uint8_t)0x1e); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[21] == (uint8_t)0x26); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[22] == (uint8_t)0x7f); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[23] == (uint8_t)0x26); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[24] == (uint8_t)0x26); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[25] == (uint8_t)0x2b); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[26] == (uint8_t)0x09); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[27] == (uint8_t)0x49); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[28] == (uint8_t)0xbc); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[29] == (uint8_t)0x16); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[30] == (uint8_t)0xdc); + REQUIRE(command.otaUpdateCmdDown.params.finalSha256[31] == (uint8_t)0x49); + + REQUIRE(command.c.id == OtaUpdateCmdDownId); + } + } + +/****************************************************************************/ + + WHEN("Decode the OtaUpdateCmdDown message with out of order fields 1") + { + CommandDown command; + + /* + DA 00010100 # tag(65792) + 84 # array(4) + 78 72 # text(141) + 68747470733A2F2F626F617264732D69 + 6E742E6F6E69756472612E63632F7374 + 6F726167652F6669726D776172652F76 + 312F6466316561633963376264363334 + 37336666666231313766393837333730 + 33653465633935353933316532363766 + 32363236326230393439626331366463 + 3439 # "https://boards-int.oniudra.cc/storage/firmware/v1/df1eac9c7bd63473fffb117f9873703e4ec955931e267f26262b0949bc16dc49" + 50 # bytes(16) + C73CB045F9C2434585AFFA36A307BFE7"\xC7<\xB0E\xF9\xC2CE\x85\xAF\xFA6\xA3\a\xBF\xE7" + 58 20 # bytes(32) + 00000000000000000000000000000000 + 00000000000000000000000000000000# "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + 58 20 # bytes(32) + DF1EAC9C7BD63473FFFB117F9873703E + 4EC955931E267F26262B0949BC16DC49# "\xDF\u001E\xAC\x9C{\xD64s\xFF\xFB\u0011\u007F\x98sp>N\xC9U\x93\u001E&\u007F&&+\tI\xBC\u0016\xDCI" + + */ + uint8_t const payload[] = {0xda, 0x00, 0x01, 0x01, 0x00, 0x84, 0x78, 0x72, + 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x2d, 0x69, + 0x6e, 0x74, 0x2e, 0x6f, 0x6e, 0x69, 0x75, 0x64, + 0x72, 0x61, 0x2e, 0x63, 0x63, 0x2f, 0x73, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x66, 0x69, + 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x2f, 0x76, + 0x31, 0x2f, 0x64, 0x66, 0x31, 0x65, 0x61, 0x63, + 0x39, 0x63, 0x37, 0x62, 0x64, 0x36, 0x33, 0x34, + 0x37, 0x33, 0x66, 0x66, 0x66, 0x62, 0x31, 0x31, + 0x37, 0x66, 0x39, 0x38, 0x37, 0x33, 0x37, 0x30, + 0x33, 0x65, 0x34, 0x65, 0x63, 0x39, 0x35, 0x35, + 0x39, 0x33, 0x31, 0x65, 0x32, 0x36, 0x37, 0x66, + 0x32, 0x36, 0x32, 0x36, 0x32, 0x62, 0x30, 0x39, + 0x34, 0x39, 0x62, 0x63, 0x31, 0x36, 0x64, 0x63, + 0x34, 0x39, 0x50, 0xc7, 0x3c, 0xb0, 0x45, 0xf9, + 0xc2, 0x43, 0x45, 0x85, 0xaf, 0xfa, 0x36, 0xa3, + 0x07, 0xbf, 0xe7, 0x58, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x20, 0xdf, + 0x1e, 0xac, 0x9c, 0x7b, 0xd6, 0x34, 0x73, 0xff, + 0xfb, 0x11, 0x7f, 0x98, 0x73, 0x70, 0x3e, 0x4e, + 0xc9, 0x55, 0x93, 0x1e, 0x26, 0x7f, 0x26, 0x26, + 0x2b, 0x09, 0x49, 0xbc, 0x16, 0xdc, 0x49}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is successful") { + REQUIRE(err == Decoder::Status::Error); + } + } + +/****************************************************************************/ + + WHEN("Decode the OtaUpdateCmdDown message with out of order fields 2") + { + CommandDown command; + + /* + DA 00010100 # tag(65792) + 84 # array(4) + 50 # bytes(16) + C73CB045F9C2434585AFFA36A307BFE7"\xC7<\xB0E\xF9\xC2CE\x85\xAF\xFA6\xA3\a\xBF\xE7" + 58 20 # bytes(32) + 00000000000000000000000000000000 + 00000000000000000000000000000000# "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + 78 72 # text(141) + 68747470733A2F2F626F617264732D69 + 6E742E6F6E69756472612E63632F7374 + 6F726167652F6669726D776172652F76 + 312F6466316561633963376264363334 + 37336666666231313766393837333730 + 33653465633935353933316532363766 + 32363236326230393439626331366463 + 3439 # "https://boards-int.oniudra.cc/storage/firmware/v1/df1eac9c7bd63473fffb117f9873703e4ec955931e267f26262b0949bc16dc49" + 58 20 # bytes(32) + DF1EAC9C7BD63473FFFB117F9873703E + 4EC955931E267F26262B0949BC16DC49# "\xDF\u001E\xAC\x9C{\xD64s\xFF\xFB\u0011\u007F\x98sp>N\xC9U\x93\u001E&\u007F&&+\tI\xBC\u0016\xDCI" + + */ + uint8_t const payload[] = {0xda, 0x00, 0x01, 0x01, 0x00, 0x84, 0x50, 0xc7, + 0x3c, 0xb0, 0x45, 0xf9, 0xc2, 0x43, 0x45, 0x85, + 0xaf, 0xfa, 0x36, 0xa3, 0x07, 0xbf, 0xe7, 0x58, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x72, 0x68, 0x74, 0x74, 0x70, 0x73, + 0x3a, 0x2f, 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, + 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x2e, 0x6f, 0x6e, + 0x69, 0x75, 0x64, 0x72, 0x61, 0x2e, 0x63, 0x63, + 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, + 0x2f, 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, + 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x66, 0x31, + 0x65, 0x61, 0x63, 0x39, 0x63, 0x37, 0x62, 0x64, + 0x36, 0x33, 0x34, 0x37, 0x33, 0x66, 0x66, 0x66, + 0x62, 0x31, 0x31, 0x37, 0x66, 0x39, 0x38, 0x37, + 0x33, 0x37, 0x30, 0x33, 0x65, 0x34, 0x65, 0x63, + 0x39, 0x35, 0x35, 0x39, 0x33, 0x31, 0x65, 0x32, + 0x36, 0x37, 0x66, 0x32, 0x36, 0x32, 0x36, 0x32, + 0x62, 0x30, 0x39, 0x34, 0x39, 0x62, 0x63, 0x31, + 0x36, 0x64, 0x63, 0x34, 0x39, 0x58, 0x20, 0xdf, + 0x1e, 0xac, 0x9c, 0x7b, 0xd6, 0x34, 0x73, 0xff, + 0xfb, 0x11, 0x7f, 0x98, 0x73, 0x70, 0x3e, 0x4e, + 0xc9, 0x55, 0x93, 0x1e, 0x26, 0x7f, 0x26, 0x26, + 0x2b, 0x09, 0x49, 0xbc, 0x16, 0xdc, 0x49}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is successful") { + REQUIRE(err == Decoder::Status::Error); + } + } + +/****************************************************************************/ + + WHEN("Decode the OtaUpdateCmdDown message with corrupted fields 1") + { + CommandDown command; + + /* + DA 00010100 # tag(65792) + 84 # array(4) + 50 # bytes(16) + C73CB045F9C2434585AFFA36A307BFE7"\xC7<\xB0E\xF9\xC2CE\x85\xAF\xFA6\xA3\a\xBF\xE7" + 78 72 # text(141) + 68747470733A2F2F626F617264732D69 + 6E742E6F6E69756472612E63632F7374 + 6F726167652F6669726D776172652F76 + 312F6466316561633963376264363334 + 37336666666231313766393837333730 + 33653465633935353933316532363766 + 32363236326230393439626331366463 + 3439 # "https://boards-int.oniudra.cc/storage/firmware/v1/df1eac9c7bd63473fffb117f9873703e4ec955931e267f26262b0949bc16dc49" + 1A 65DCB821 # unsigned(1708963873) + 58 20 # bytes(32) + DF1EAC9C7BD63473FFFB117F9873703E + 4EC955931E267F26262B0949BC16DC49# "\xDF\u001E\xAC\x9C{\xD64s\xFF\xFB\u0011\u007F\x98sp>N\xC9U\x93\u001E&\u007F&&+\tI\xBC\u0016\xDCI" + + */ + uint8_t const payload[] = {0xda, 0x00, 0x01, 0x01, 0x00, 0x84, 0x50, 0xc7, + 0x3c, 0xb0, 0x45, 0xf9, 0xc2, 0x43, 0x45, 0x85, + 0xaf, 0xfa, 0x36, 0xa3, 0x07, 0xbf, 0xe7, 0x78, + 0x72, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, + 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x2d, + 0x69, 0x6e, 0x74, 0x2e, 0x6f, 0x6e, 0x69, 0x75, + 0x64, 0x72, 0x61, 0x2e, 0x63, 0x63, 0x2f, 0x73, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x66, + 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x2f, + 0x76, 0x31, 0x2f, 0x64, 0x66, 0x31, 0x65, 0x61, + 0x63, 0x39, 0x63, 0x37, 0x62, 0x64, 0x36, 0x33, + 0x34, 0x37, 0x33, 0x66, 0x66, 0x66, 0x62, 0x31, + 0x31, 0x37, 0x66, 0x39, 0x38, 0x37, 0x33, 0x37, + 0x30, 0x33, 0x65, 0x34, 0x65, 0x63, 0x39, 0x35, + 0x35, 0x39, 0x33, 0x31, 0x65, 0x32, 0x36, 0x37, + 0x66, 0x32, 0x36, 0x32, 0x36, 0x32, 0x62, 0x30, + 0x39, 0x34, 0x39, 0x62, 0x63, 0x31, 0x36, 0x64, + 0x63, 0x34, 0x39, 0x1A, 0x65, 0xDC, 0xB8, 0x21, + 0x58, 0x20, 0xdf, 0x1e, 0xac, 0x9c, 0x7b, 0xd6, + 0x34, 0x73, 0xff, 0xfb, 0x11, 0x7f, 0x98, 0x73, + 0x70, 0x3e, 0x4e, 0xc9, 0x55, 0x93, 0x1e, 0x26, + 0x7f, 0x26, 0x26, 0x2b, 0x09, 0x49, 0xbc, 0x16, + 0xdc, 0x49}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is successful") { + REQUIRE(err == Decoder::Status::Error); + } + } + +/****************************************************************************/ + + WHEN("Decode the OtaUpdateCmdDown message with corrupted fields 2") + { + CommandDown command; + + /* + DA 00010100 # tag(65792) + 84 # array(4) + 50 # bytes(16) + C73CB045F9C2434585AFFA36A307BFE7"\xC7<\xB0E\xF9\xC2CE\x85\xAF\xFA6\xA3\a\xBF\xE7" + 78 72 # text(141) + 68747470733A2F2F626F617264732D69 + 6E742E6F6E69756472612E63632F7374 + 6F726167652F6669726D776172652F76 + 312F6466316561633963376264363334 + 37336666666231313766393837333730 + 33653465633935353933316532363766 + 32363236326230393439626331366463 + 3439 # "https://boards-int.oniudra.cc/storage/firmware/v1/df1eac9c7bd63473fffb117f9873703e4ec955931e267f26262b0949bc16dc49" + 58 20 # bytes(32) + DF1EAC9C7BD63473FFFB117F9873703E + 4EC955931E267F26262B0949BC16DC49# "\xDF\u001E\xAC\x9C{\xD64s\xFF\xFB\u0011\u007F\x98sp>N\xC9U\x93\u001E&\u007F&&+\tI\xBC\u0016\xDCI" + 1A 65DCB821 # unsigned(1708963873) + + */ + uint8_t const payload[] = {0xda, 0x00, 0x01, 0x01, 0x00, 0x84, 0x50, 0xc7, + 0x3c, 0xb0, 0x45, 0xf9, 0xc2, 0x43, 0x45, 0x85, + 0xaf, 0xfa, 0x36, 0xa3, 0x07, 0xbf, 0xe7, 0x78, + 0x72, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, + 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x2d, + 0x69, 0x6e, 0x74, 0x2e, 0x6f, 0x6e, 0x69, 0x75, + 0x64, 0x72, 0x61, 0x2e, 0x63, 0x63, 0x2f, 0x73, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x66, + 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x2f, + 0x76, 0x31, 0x2f, 0x64, 0x66, 0x31, 0x65, 0x61, + 0x63, 0x39, 0x63, 0x37, 0x62, 0x64, 0x36, 0x33, + 0x34, 0x37, 0x33, 0x66, 0x66, 0x66, 0x62, 0x31, + 0x31, 0x37, 0x66, 0x39, 0x38, 0x37, 0x33, 0x37, + 0x30, 0x33, 0x65, 0x34, 0x65, 0x63, 0x39, 0x35, + 0x35, 0x39, 0x33, 0x31, 0x65, 0x32, 0x36, 0x37, + 0x66, 0x32, 0x36, 0x32, 0x36, 0x32, 0x62, 0x30, + 0x39, 0x34, 0x39, 0x62, 0x63, 0x31, 0x36, 0x64, + 0x63, 0x34, 0x39, 0x58, 0x20, 0xdf, 0x1e, 0xac, + 0x9c, 0x7b, 0xd6, 0x34, 0x73, 0xff, 0xfb, 0x11, + 0x7f, 0x98, 0x73, 0x70, 0x3e, 0x4e, 0xc9, 0x55, + 0x93, 0x1e, 0x26, 0x7f, 0x26, 0x26, 0x2b, 0x09, + 0x49, 0xbc, 0x16, 0xdc, 0x49, 0x1A, 0x65, 0xDC, + 0xB8, 0x21}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is successful") { + REQUIRE(err == Decoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Decode the OtaBeginUp message") + { + CommandDown command; + /* + DA 00010000 # tag(65536) + 81 # array(1) + 58 20 # bytes(32) + 01020304 + */ + uint8_t const payload[] = {0xda, 0x00, 0x01, 0x00, 0x00, 0x81, 0x58, 0x20, + 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful - OtaBeginUp is not supported") { + REQUIRE(err == Decoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Decode the ThingBeginCmd message") + { + CommandDown command; + /* + DA 00010300 # tag(66304) + 81 # array(1) + 68 # text(8) + 7468696E675F6964 # "thing_id" + */ + uint8_t const payload[] = {0xda, 0x00, 0x01, 0x03, 0x00, 0x81, 0x68, 0x74, + 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful - ThingBeginCmd is not supported") { + REQUIRE(err == Decoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Decode the LastValuesBeginCmd message") + { + CommandDown command; + /* + DA 00010500 # tag(66816) + 80 # array(0) + */ + uint8_t const payload[] = {0xda, 0x00, 0x01, 0x05, 0x00, 0x80}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful - LastValuesBeginCmd is not supported") { + REQUIRE(err == Decoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Decode the DeviceBeginCmd message") + { + CommandDown command; + /* + DA 00010700 # tag(67328) + 81 # array(1) + 65 # text(5) + 322E302E30 # "2.0.0" + */ + uint8_t const payload[] = {0xda, 0x00, 0x01, 0x07, 0x00, 0x81, 0x65, 0x32, + 0x2e, 0x30, 0x2e, 0x30}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful - DeviceBeginCmd is not supported") { + REQUIRE(err == Decoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Decode the OtaProgressCmdUp message") + { + CommandDown command; + /* + DA 00010200 # tag(66048) + 84 # array(4) + 50 # bytes(16) + 000102030405060708090A0B0C0D0E0F # "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f" + E1 # primitive(1) + 20 # negative(0) + 18 64 # unsigned(100) + */ + uint8_t const payload[] = {0xda, 0x00, 0x01, 0x02, 0x00, 0x84, 0x50, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xe1, + 0x20, 0x18, 0x64}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful - OtaProgressCmdUp is not supported") { + REQUIRE(err == Decoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Decode the TimezoneCommandUp message") + { + CommandDown command; + /* + DA 00010800 # tag(67584) + 80 # array(0) + */ + uint8_t const payload[] = {0xda, 0x00, 0x01, 0x08, 0x00, 0x80}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful - TimezoneCommandUp is not supported") { + REQUIRE(err == Decoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Decode a message with invalid CBOR tag") + { + CommandDown command; + + /* + DA ffffffff # invalid tag + 82 # array(2) + 1A 65DCB821 # unsigned(1708963873) + 1A 78ACA191 # unsigned(2024579473) + */ + + uint8_t const payload[] = {0xDA, 0xff, 0xff, 0xff, 0xff, 0x82, 0x1A, 0x65, + 0xDC, 0xB8, 0x21, 0x1A, 0x78, 0xAC, 0xA1, 0x91}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful") { + REQUIRE(err == Decoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Decode a message not starting with a CBOR tag") + { + CommandDown command; + + /* + 82 # array(2) + 1A 65DCB821 # unsigned(1708963873) + 1A 78ACA191 # unsigned(2024579473) + */ + + uint8_t const payload[] = {0x82, 0x1A, 0x65, 0xDC, 0xB8, 0x21, 0x1A, 0x78, + 0xAC, 0xA1, 0x91}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful") { + REQUIRE(err == Decoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Decode an invalid CBOR message") + { + CommandDown command; + + uint8_t const payload[] = {0xFF}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful") { + REQUIRE(err == Decoder::Status::Error); + } + } + +} diff --git a/extras/test/src/test_command_encode.cpp b/extras/test/src/test_command_encode.cpp new file mode 100644 index 000000000..7e31c1487 --- /dev/null +++ b/extras/test/src/test_command_encode.cpp @@ -0,0 +1,322 @@ +/* + Copyright (c) 2024 Arduino. All rights reserved. +*/ + +/****************************************************************************** + INCLUDE + ******************************************************************************/ + +#include + +#include + +#include +#include + +/****************************************************************************** + TEST CODE + ******************************************************************************/ + +SCENARIO("Test the encoding of command messages") { + /****************************************************************************/ + + WHEN("Encode the OtaBeginUp message") + { + OtaBeginUp command; + uint8_t sha[SHA256_SIZE] = {0x01, 0x02, 0x03, 0x04}; + memcpy(command.params.sha, sha, SHA256_SIZE); + + command.c.id = CommandId::OtaBeginUpId; + + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + uint8_t expected_result[] = { + 0xda, 0x00, 0x01, 0x00, 0x00, 0x81, 0x58, 0x20, + 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + // Test the encoding is + // DA 00010000 # tag(65536) + // 81 # array(1) + // 58 20 # bytes(32) + // 01020304 + THEN("The encoding is successful") { + REQUIRE(err == Encoder::Status::Complete); + REQUIRE(bytes_encoded == sizeof(expected_result)); + REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + } + } + + + /****************************************************************************/ + + WHEN("Encode the ThingBeginCmd message") + { + ThingBeginCmd command; + String thing_id = "thing_id"; + strcpy(command.params.thing_id, thing_id.c_str()); + + command.c.id = CommandId::ThingBeginCmdId; + + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + uint8_t expected_result[] = { + 0xda, 0x00, 0x01, 0x03, 0x00, 0x81, 0x68, 0x74, + 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64 + }; + + // Test the encoding is + // DA 00010300 # tag(66304) + // 81 # array(1) + // 68 # text(8) + // 7468696E675F6964 # "thing_id" + + THEN("The encoding is successful") { + REQUIRE(err == Encoder::Status::Complete); + REQUIRE(bytes_encoded == sizeof(expected_result)); + REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + } + } + + /****************************************************************************/ + + WHEN("Encode the LastValuesBeginCmd message") + { + LastValuesBeginCmd command; + command.c.id = CommandId::LastValuesBeginCmdId; + + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + uint8_t expected_result[] = { + 0xda, 0x00, 0x01, 0x05, 0x00, 0x80 + }; + + // Test the encoding is + // DA 00010500 # tag(66816) + // 80 # array(0) + THEN("The encoding is successful") { + REQUIRE(err == Encoder::Status::Complete); + REQUIRE(bytes_encoded == sizeof(expected_result)); + REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + } + } + + /**************************************************************************/ + + WHEN("Encode the DeviceBeginCmd message") + { + DeviceBeginCmd command; + String lib_version = "2.0.0"; + strcpy(command.params.lib_version, lib_version.c_str()); + + command.c.id = CommandId::DeviceBeginCmdId; + + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + uint8_t expected_result[] = { + 0xda, 0x00, 0x01, 0x07, 0x00, 0x81, 0x65, 0x32, + 0x2e, 0x30, 0x2e, 0x30 + }; + + // Test the encoding is + // DA 00010700 # tag(67328) + // 81 # array(1) + // 65 # text(5) + // 322E302E30 # "2.0.0" + THEN("The encoding is successful") { + REQUIRE(err == Encoder::Status::Complete); + REQUIRE(bytes_encoded == sizeof(expected_result)); + REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + } + } + + /****************************************************************************/ + + WHEN("Encode the OtaProgressCmdUp message") + { + OtaProgressCmdUp command; + command.params.time = 2; + + uint8_t id[ID_SIZE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + memcpy(command.params.id, id, ID_SIZE); + command.params.state = 1; + command.params.state_data = -1; + command.params.time = 100; + + command.c.id = CommandId::OtaProgressCmdUpId; + + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + uint8_t expected_result[] = { + 0xda, 0x00, 0x01, 0x02, 0x00, 0x84, 0x50, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xe1, + 0x20, 0x18, 0x64 + }; + + // Test the encoding is + // DA 00010200 # tag(66048) + // 84 # array(4) + // 50 # bytes(16) + // 000102030405060708090A0B0C0D0E0F # "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f" + // E1 # primitive(1) + // 20 # negative(0) + // 18 64 # unsigned(100) + THEN("The encoding is successful") { + REQUIRE(err == Encoder::Status::Complete); + REQUIRE(bytes_encoded == sizeof(expected_result)); + REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + } + } + + /****************************************************************************/ + + WHEN("Encode the TimezoneCommandUp message") + { + TimezoneCommandUp command; + command.c.id = CommandId::TimezoneCommandUpId; + + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + uint8_t expected_result[] = { + 0xda, 0x00, 0x01, 0x08, 0x00, 0x80 + }; + + // Test the encoding is + // DA 00010800 # tag(67584) + // 80 # array(0) + THEN("The encoding is successful") { + REQUIRE(err == Encoder::Status::Complete); + REQUIRE(bytes_encoded == sizeof(expected_result)); + REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + } + } + + /****************************************************************************/ + + WHEN("Encode the ThingUpdateCmdId message") + { + ThingUpdateCmd command; + command.c.id = CommandId::ThingUpdateCmdId; + + String thing_id = "e4494d55-872a-4fd2-9646-92f87949394c"; + strcpy(command.params.thing_id, thing_id.c_str()); + + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + THEN("The encoding is unsuccessful - ThingUpdateCmdId is not supported") { + REQUIRE(err == Encoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Encode the SetTimezoneCommand message") + { + TimezoneCommandDown command; + command.c.id = CommandId::TimezoneCommandDownId; + + command.params.offset = 1708963873; + command.params.until = 2024579473; + + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + THEN("The encoding is unsuccessful - SetTimezoneCommand is not supported") { + REQUIRE(err == Encoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Encode the LastValuesUpdateCmd message") + { + LastValuesUpdateCmd command; + command.c.id = CommandId::LastValuesUpdateCmdId; + + command.params.length = 13; + uint8_t last_values[13] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x10, 0x11, 0x12}; + command.params.last_values = last_values; + + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + THEN("The encoding is unsuccessful - LastValuesUpdateCmd is not supported") { + REQUIRE(err == Encoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Encode the OtaUpdateCmdDown message") + { + OtaUpdateCmdDown command; + command.c.id = CommandId::OtaUpdateCmdDownId; + + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + THEN("The encoding is unsuccessful - OtaUpdateCmdDown is not supported") { + REQUIRE(err == Encoder::Status::Error); + } + } + + /****************************************************************************/ + + WHEN("Encode a message with unknown command Id") + { + OtaUpdateCmdDown command; + command.c.id = CommandId::UnknownCmdId; + + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + THEN("The encoding is unsuccessful - UnknownCmdId is not supported") { + REQUIRE(err == Encoder::Status::Error); + } + } +} From 5a69c2eb9d2cfce8772269611f0791649961f3d0 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 17 Apr 2024 17:13:45 +0200 Subject: [PATCH 592/780] Removing x509_crt_bundle_len since not used anywhere --- src/tls/AIoTCUPCert.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tls/AIoTCUPCert.h b/src/tls/AIoTCUPCert.h index 330b8cb78..46a933d73 100644 --- a/src/tls/AIoTCUPCert.h +++ b/src/tls/AIoTCUPCert.h @@ -224,7 +224,6 @@ static const unsigned char x509_crt_bundle[] = { 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, 0x39, 0x8b, 0x7f, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01 }; -unsigned int x509_crt_bundle_len = 2164; #elif defined (ARDUINO_EDGE_CONTROL) /* From bfeb4b0b6c320f455d7d4051982a1434daf65984 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 18 Mar 2024 14:49:24 +0100 Subject: [PATCH 593/780] disabling ota on mkrgsm1400 --- src/AIoTC_Config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 26bc377ad..e889bbdde 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -65,7 +65,7 @@ #endif #ifdef ARDUINO_SAMD_MKRGSM1400 - #define OTA_STORAGE_SSU (1) + #define OTA_STORAGE_SSU (1) // OTA_STORAGE_SSU is not implemented yet in OTASamd #else #define OTA_STORAGE_SSU (0) #endif @@ -80,7 +80,7 @@ #define OTA_STORAGE_ESP (1) #endif -#if (OTA_STORAGE_SFU || OTA_STORAGE_SSU || OTA_STORAGE_SNU || OTA_STORAGE_PORTENTA_QSPI || OTA_STORAGE_ESP) +#if (OTA_STORAGE_SFU || OTA_STORAGE_SNU || OTA_STORAGE_PORTENTA_QSPI || OTA_STORAGE_ESP) #define OTA_ENABLED (1) #else #define OTA_ENABLED (0) From 04d7bf89e07ba8232ce22030d6fe55e50c555f98 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 19 Mar 2024 17:09:11 +0100 Subject: [PATCH 594/780] Extend Commands.h to include new Command protocol model --- src/message/Commands.h | 103 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/src/message/Commands.h b/src/message/Commands.h index 0f9cdac20..ce71f9c81 100644 --- a/src/message/Commands.h +++ b/src/message/Commands.h @@ -18,10 +18,20 @@ #include /****************************************************************************** - * TYPEDEF + * DEFINE ******************************************************************************/ -enum CommandId : uint16_t { +#define THING_ID_SIZE 37 +#define SHA256_SIZE 32 +#define URL_SIZE 256 +#define ID_SIZE 16 +#define MAX_LIB_VERSION_SIZE 10 + +/****************************************************************************** + TYPEDEF + ******************************************************************************/ + +enum CommandId: uint32_t { /* Device commands */ DeviceBeginCmdId, @@ -39,6 +49,15 @@ enum CommandId : uint16_t { /* Generic commands */ ResetCmdId, + /* OTA commands */ + OtaBeginUpId, + OtaProgressCmdUpId, + OtaUpdateCmdDownId, + + /* Timezone commands */ + TimezoneCommandUpId, + TimezoneCommandDownId, + /* Unknown command id */ UnknownCmdId }; @@ -48,3 +67,83 @@ struct Command { }; typedef Command Message; + +struct DeviceBeginCmd { + Command c; + struct { + char lib_version[MAX_LIB_VERSION_SIZE]; + } params; +}; + +struct ThingBeginCmd { + Command c; + struct { + char thing_id[THING_ID_SIZE]; + } params; +}; + +struct ThingUpdateCmd { + Command c; + struct { + char thing_id[THING_ID_SIZE]; + } params; +}; + +struct LastValuesBeginCmd { + Command c; +}; + +struct LastValuesUpdateCmd { + Command c; + struct { + uint8_t * last_values; + size_t length; + } params; +}; + +struct OtaBeginUp { + Command c; + struct { + uint8_t sha [SHA256_SIZE]; + } params; +}; + +struct OtaProgressCmdUp { + Command c; + struct { + uint8_t id[ID_SIZE]; + uint8_t state; + int32_t state_data; + uint64_t time; + } params; +}; + +struct OtaUpdateCmdDown { + Command c; + struct { + uint8_t id[ID_SIZE]; + char url[URL_SIZE]; + uint8_t initialSha256[SHA256_SIZE]; + uint8_t finalSha256[SHA256_SIZE]; + } params; +}; + +struct TimezoneCommandUp { + Command c; +}; + +struct TimezoneCommandDown { + Command c; + struct { + int32_t offset; + uint32_t until; + } params; +}; + +union CommandDown { + struct Command c; + struct OtaUpdateCmdDown otaUpdateCmdDown; + struct ThingUpdateCmd thingUpdateCmd; + struct LastValuesUpdateCmd lastValuesUpdateCmd; + struct TimezoneCommandDown timezoneCommandDown; +}; From 828dc5377104d0ddb1619778cce99656dc89a922 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 9 Apr 2024 09:46:42 +0200 Subject: [PATCH 595/780] Add ArduinoLCC certificate inside certificate bundle --- src/tls/AIoTCUPCert.h | 157 +++++++++++++++++++++++------------------- 1 file changed, 86 insertions(+), 71 deletions(-) diff --git a/src/tls/AIoTCUPCert.h b/src/tls/AIoTCUPCert.h index 46a933d73..1e942bcb8 100644 --- a/src/tls/AIoTCUPCert.h +++ b/src/tls/AIoTCUPCert.h @@ -38,11 +38,12 @@ * https://www.amazontrust.com/repository/AmazonRootCA4.pem * https://www.amazontrust.com/repository/SFSRootCAG2.pem * https://certs.secureserver.net/repository/sf-class2-root.crt + * https://iot.arduino.cc */ static const unsigned char x509_crt_bundle[] = { - 0x00, 0x06, 0x00, 0x3b, 0x01, 0x26, 0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, + 0x00, 0x07, 0x00, 0x3b, 0x01, 0x26, 0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x06, 0x41, 0x6d, 0x61, 0x7a, 0x6f, 0x6e, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, @@ -151,78 +152,92 @@ static const unsigned char x509_crt_bundle[] = { 0xe0, 0xe3, 0xbd, 0x5f, 0x84, 0x62, 0xf3, 0x70, 0x64, 0x33, 0xa0, 0xcb, 0x24, 0x2f, 0x70, 0xba, 0x88, 0xa1, 0x2a, 0xa0, 0x75, 0xf8, 0x81, 0xae, 0x62, 0x06, 0xc4, 0x81, 0xdb, 0x39, 0x6e, 0x29, 0xb0, 0x1e, 0xfa, 0x2e, - 0x5c, 0x00, 0x6a, 0x01, 0x24, 0x30, 0x68, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, - 0x6f, 0x67, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, - 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x29, 0x53, 0x74, - 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x43, 0x6c, 0x61, 0x73, - 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x20, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, - 0x01, 0x0d, 0x00, 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, - 0xb7, 0x32, 0xc8, 0xfe, 0xe9, 0x71, 0xa6, 0x04, 0x85, 0xad, 0x0c, 0x11, - 0x64, 0xdf, 0xce, 0x4d, 0xef, 0xc8, 0x03, 0x18, 0x87, 0x3f, 0xa1, 0xab, - 0xfb, 0x3c, 0xa6, 0x9f, 0xf0, 0xc3, 0xa1, 0xda, 0xd4, 0xd8, 0x6e, 0x2b, - 0x53, 0x90, 0xfb, 0x24, 0xa4, 0x3e, 0x84, 0xf0, 0x9e, 0xe8, 0x5f, 0xec, - 0xe5, 0x27, 0x44, 0xf5, 0x28, 0xa6, 0x3f, 0x7b, 0xde, 0xe0, 0x2a, 0xf0, - 0xc8, 0xaf, 0x53, 0x2f, 0x9e, 0xca, 0x05, 0x01, 0x93, 0x1e, 0x8f, 0x66, - 0x1c, 0x39, 0xa7, 0x4d, 0xfa, 0x5a, 0xb6, 0x73, 0x04, 0x25, 0x66, 0xeb, - 0x77, 0x7f, 0xe7, 0x59, 0xc6, 0x4a, 0x99, 0x25, 0x14, 0x54, 0xeb, 0x26, - 0xc7, 0xf3, 0x7f, 0x19, 0xd5, 0x30, 0x70, 0x8f, 0xaf, 0xb0, 0x46, 0x2a, - 0xff, 0xad, 0xeb, 0x29, 0xed, 0xd7, 0x9f, 0xaa, 0x04, 0x87, 0xa3, 0xd4, - 0xf9, 0x89, 0xa5, 0x34, 0x5f, 0xdb, 0x43, 0x91, 0x82, 0x36, 0xd9, 0x66, - 0x3c, 0xb1, 0xb8, 0xb9, 0x82, 0xfd, 0x9c, 0x3a, 0x3e, 0x10, 0xc8, 0x3b, - 0xef, 0x06, 0x65, 0x66, 0x7a, 0x9b, 0x19, 0x18, 0x3d, 0xff, 0x71, 0x51, - 0x3c, 0x30, 0x2e, 0x5f, 0xbe, 0x3d, 0x77, 0x73, 0xb2, 0x5d, 0x06, 0x6c, - 0xc3, 0x23, 0x56, 0x9a, 0x2b, 0x85, 0x26, 0x92, 0x1c, 0xa7, 0x02, 0xb3, - 0xe4, 0x3f, 0x0d, 0xaf, 0x08, 0x79, 0x82, 0xb8, 0x36, 0x3d, 0xea, 0x9c, - 0xd3, 0x35, 0xb3, 0xbc, 0x69, 0xca, 0xf5, 0xcc, 0x9d, 0xe8, 0xfd, 0x64, - 0x8d, 0x17, 0x80, 0x33, 0x6e, 0x5e, 0x4a, 0x5d, 0x99, 0xc9, 0x1e, 0x87, - 0xb4, 0x9d, 0x1a, 0xc0, 0xd5, 0x6e, 0x13, 0x35, 0x23, 0x5e, 0xdf, 0x9b, - 0x5f, 0x3d, 0xef, 0xd6, 0xf7, 0x76, 0xc2, 0xea, 0x3e, 0xbb, 0x78, 0x0d, - 0x1c, 0x42, 0x67, 0x6b, 0x04, 0xd8, 0xf8, 0xd6, 0xda, 0x6f, 0x8b, 0xf2, - 0x44, 0xa0, 0x01, 0xab, 0x02, 0x01, 0x03, 0x00, 0x9b, 0x01, 0x26, 0x30, - 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30, - 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74, - 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, + 0x5c, 0x00, 0x47, 0x00, 0x5b, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x41, 0x72, 0x64, 0x75, 0x69, + 0x6e, 0x6f, 0x20, 0x4c, 0x4c, 0x43, 0x20, 0x55, 0x53, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x02, 0x49, 0x54, 0x31, 0x10, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x07, 0x41, 0x72, 0x64, + 0x75, 0x69, 0x6e, 0x6f, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x6d, 0x77, 0x6c, 0x5a, 0xcf, + 0x61, 0x1c, 0x7d, 0x44, 0x98, 0x51, 0xf2, 0x5e, 0xe1, 0x02, 0x40, 0x77, + 0xb7, 0x9c, 0xbd, 0x49, 0xa2, 0xa3, 0x8c, 0x4e, 0xab, 0x5e, 0x98, 0xac, + 0x82, 0xfc, 0x69, 0x5b, 0x44, 0x22, 0x77, 0xb4, 0x4d, 0x2e, 0x8e, 0xdf, + 0x2a, 0x71, 0xc1, 0x39, 0x6c, 0xd6, 0x39, 0x14, 0xbd, 0xd9, 0x6b, 0x18, + 0x4b, 0x4b, 0xec, 0xb3, 0xd5, 0xee, 0x42, 0x89, 0x89, 0x55, 0x22, 0x00, + 0x6a, 0x01, 0x24, 0x30, 0x68, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, - 0x69, 0x65, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x3b, 0x30, - 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, 0x72, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, 0x82, - 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, - 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd5, 0x0c, 0x3a, 0xc4, 0x2a, - 0xf9, 0x4e, 0xe2, 0xf5, 0xbe, 0x19, 0x97, 0x5f, 0x8e, 0x88, 0x53, 0xb1, - 0x1f, 0x3f, 0xcb, 0xcf, 0x9f, 0x20, 0x13, 0x6d, 0x29, 0x3a, 0xc8, 0x0f, - 0x7d, 0x3c, 0xf7, 0x6b, 0x76, 0x38, 0x63, 0xd9, 0x36, 0x60, 0xa8, 0x9b, - 0x5e, 0x5c, 0x00, 0x80, 0xb2, 0x2f, 0x59, 0x7f, 0xf6, 0x87, 0xf9, 0x25, - 0x43, 0x86, 0xe7, 0x69, 0x1b, 0x52, 0x9a, 0x90, 0xe1, 0x71, 0xe3, 0xd8, - 0x2d, 0x0d, 0x4e, 0x6f, 0xf6, 0xc8, 0x49, 0xd9, 0xb6, 0xf3, 0x1a, 0x56, - 0xae, 0x2b, 0xb6, 0x74, 0x14, 0xeb, 0xcf, 0xfb, 0x26, 0xe3, 0x1a, 0xba, - 0x1d, 0x96, 0x2e, 0x6a, 0x3b, 0x58, 0x94, 0x89, 0x47, 0x56, 0xff, 0x25, - 0xa0, 0x93, 0x70, 0x53, 0x83, 0xda, 0x84, 0x74, 0x14, 0xc3, 0x67, 0x9e, - 0x04, 0x68, 0x3a, 0xdf, 0x8e, 0x40, 0x5a, 0x1d, 0x4a, 0x4e, 0xcf, 0x43, - 0x91, 0x3b, 0xe7, 0x56, 0xd6, 0x00, 0x70, 0xcb, 0x52, 0xee, 0x7b, 0x7d, - 0xae, 0x3a, 0xe7, 0xbc, 0x31, 0xf9, 0x45, 0xf6, 0xc2, 0x60, 0xcf, 0x13, - 0x59, 0x02, 0x2b, 0x80, 0xcc, 0x34, 0x47, 0xdf, 0xb9, 0xde, 0x90, 0x65, - 0x6d, 0x02, 0xcf, 0x2c, 0x91, 0xa6, 0xa6, 0xe7, 0xde, 0x85, 0x18, 0x49, - 0x7c, 0x66, 0x4e, 0xa3, 0x3a, 0x6d, 0xa9, 0xb5, 0xee, 0x34, 0x2e, 0xba, - 0x0d, 0x03, 0xb8, 0x33, 0xdf, 0x47, 0xeb, 0xb1, 0x6b, 0x8d, 0x25, 0xd9, - 0x9b, 0xce, 0x81, 0xd1, 0x45, 0x46, 0x32, 0x96, 0x70, 0x87, 0xde, 0x02, - 0x0e, 0x49, 0x43, 0x85, 0xb6, 0x6c, 0x73, 0xbb, 0x64, 0xea, 0x61, 0x41, - 0xac, 0xc9, 0xd4, 0x54, 0xdf, 0x87, 0x2f, 0xc7, 0x22, 0xb2, 0x26, 0xcc, - 0x9f, 0x59, 0x54, 0x68, 0x9f, 0xfc, 0xbe, 0x2a, 0x2f, 0xc4, 0x55, 0x1c, - 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55, 0x39, 0x8b, 0x7f, 0x05, 0x02, - 0x03, 0x01, 0x00, 0x01 + 0x69, 0x65, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x32, 0x30, + 0x30, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, + 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x30, 0x82, 0x01, 0x20, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0d, + 0x00, 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb7, 0x32, + 0xc8, 0xfe, 0xe9, 0x71, 0xa6, 0x04, 0x85, 0xad, 0x0c, 0x11, 0x64, 0xdf, + 0xce, 0x4d, 0xef, 0xc8, 0x03, 0x18, 0x87, 0x3f, 0xa1, 0xab, 0xfb, 0x3c, + 0xa6, 0x9f, 0xf0, 0xc3, 0xa1, 0xda, 0xd4, 0xd8, 0x6e, 0x2b, 0x53, 0x90, + 0xfb, 0x24, 0xa4, 0x3e, 0x84, 0xf0, 0x9e, 0xe8, 0x5f, 0xec, 0xe5, 0x27, + 0x44, 0xf5, 0x28, 0xa6, 0x3f, 0x7b, 0xde, 0xe0, 0x2a, 0xf0, 0xc8, 0xaf, + 0x53, 0x2f, 0x9e, 0xca, 0x05, 0x01, 0x93, 0x1e, 0x8f, 0x66, 0x1c, 0x39, + 0xa7, 0x4d, 0xfa, 0x5a, 0xb6, 0x73, 0x04, 0x25, 0x66, 0xeb, 0x77, 0x7f, + 0xe7, 0x59, 0xc6, 0x4a, 0x99, 0x25, 0x14, 0x54, 0xeb, 0x26, 0xc7, 0xf3, + 0x7f, 0x19, 0xd5, 0x30, 0x70, 0x8f, 0xaf, 0xb0, 0x46, 0x2a, 0xff, 0xad, + 0xeb, 0x29, 0xed, 0xd7, 0x9f, 0xaa, 0x04, 0x87, 0xa3, 0xd4, 0xf9, 0x89, + 0xa5, 0x34, 0x5f, 0xdb, 0x43, 0x91, 0x82, 0x36, 0xd9, 0x66, 0x3c, 0xb1, + 0xb8, 0xb9, 0x82, 0xfd, 0x9c, 0x3a, 0x3e, 0x10, 0xc8, 0x3b, 0xef, 0x06, + 0x65, 0x66, 0x7a, 0x9b, 0x19, 0x18, 0x3d, 0xff, 0x71, 0x51, 0x3c, 0x30, + 0x2e, 0x5f, 0xbe, 0x3d, 0x77, 0x73, 0xb2, 0x5d, 0x06, 0x6c, 0xc3, 0x23, + 0x56, 0x9a, 0x2b, 0x85, 0x26, 0x92, 0x1c, 0xa7, 0x02, 0xb3, 0xe4, 0x3f, + 0x0d, 0xaf, 0x08, 0x79, 0x82, 0xb8, 0x36, 0x3d, 0xea, 0x9c, 0xd3, 0x35, + 0xb3, 0xbc, 0x69, 0xca, 0xf5, 0xcc, 0x9d, 0xe8, 0xfd, 0x64, 0x8d, 0x17, + 0x80, 0x33, 0x6e, 0x5e, 0x4a, 0x5d, 0x99, 0xc9, 0x1e, 0x87, 0xb4, 0x9d, + 0x1a, 0xc0, 0xd5, 0x6e, 0x13, 0x35, 0x23, 0x5e, 0xdf, 0x9b, 0x5f, 0x3d, + 0xef, 0xd6, 0xf7, 0x76, 0xc2, 0xea, 0x3e, 0xbb, 0x78, 0x0d, 0x1c, 0x42, + 0x67, 0x6b, 0x04, 0xd8, 0xf8, 0xd6, 0xda, 0x6f, 0x8b, 0xf2, 0x44, 0xa0, + 0x01, 0xab, 0x02, 0x01, 0x03, 0x00, 0x9b, 0x01, 0x26, 0x30, 0x81, 0x98, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x07, + 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74, 0x74, 0x73, + 0x64, 0x61, 0x6c, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x65, + 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x3b, 0x30, 0x39, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, + 0x02, 0x82, 0x01, 0x01, 0x00, 0xd5, 0x0c, 0x3a, 0xc4, 0x2a, 0xf9, 0x4e, + 0xe2, 0xf5, 0xbe, 0x19, 0x97, 0x5f, 0x8e, 0x88, 0x53, 0xb1, 0x1f, 0x3f, + 0xcb, 0xcf, 0x9f, 0x20, 0x13, 0x6d, 0x29, 0x3a, 0xc8, 0x0f, 0x7d, 0x3c, + 0xf7, 0x6b, 0x76, 0x38, 0x63, 0xd9, 0x36, 0x60, 0xa8, 0x9b, 0x5e, 0x5c, + 0x00, 0x80, 0xb2, 0x2f, 0x59, 0x7f, 0xf6, 0x87, 0xf9, 0x25, 0x43, 0x86, + 0xe7, 0x69, 0x1b, 0x52, 0x9a, 0x90, 0xe1, 0x71, 0xe3, 0xd8, 0x2d, 0x0d, + 0x4e, 0x6f, 0xf6, 0xc8, 0x49, 0xd9, 0xb6, 0xf3, 0x1a, 0x56, 0xae, 0x2b, + 0xb6, 0x74, 0x14, 0xeb, 0xcf, 0xfb, 0x26, 0xe3, 0x1a, 0xba, 0x1d, 0x96, + 0x2e, 0x6a, 0x3b, 0x58, 0x94, 0x89, 0x47, 0x56, 0xff, 0x25, 0xa0, 0x93, + 0x70, 0x53, 0x83, 0xda, 0x84, 0x74, 0x14, 0xc3, 0x67, 0x9e, 0x04, 0x68, + 0x3a, 0xdf, 0x8e, 0x40, 0x5a, 0x1d, 0x4a, 0x4e, 0xcf, 0x43, 0x91, 0x3b, + 0xe7, 0x56, 0xd6, 0x00, 0x70, 0xcb, 0x52, 0xee, 0x7b, 0x7d, 0xae, 0x3a, + 0xe7, 0xbc, 0x31, 0xf9, 0x45, 0xf6, 0xc2, 0x60, 0xcf, 0x13, 0x59, 0x02, + 0x2b, 0x80, 0xcc, 0x34, 0x47, 0xdf, 0xb9, 0xde, 0x90, 0x65, 0x6d, 0x02, + 0xcf, 0x2c, 0x91, 0xa6, 0xa6, 0xe7, 0xde, 0x85, 0x18, 0x49, 0x7c, 0x66, + 0x4e, 0xa3, 0x3a, 0x6d, 0xa9, 0xb5, 0xee, 0x34, 0x2e, 0xba, 0x0d, 0x03, + 0xb8, 0x33, 0xdf, 0x47, 0xeb, 0xb1, 0x6b, 0x8d, 0x25, 0xd9, 0x9b, 0xce, + 0x81, 0xd1, 0x45, 0x46, 0x32, 0x96, 0x70, 0x87, 0xde, 0x02, 0x0e, 0x49, + 0x43, 0x85, 0xb6, 0x6c, 0x73, 0xbb, 0x64, 0xea, 0x61, 0x41, 0xac, 0xc9, + 0xd4, 0x54, 0xdf, 0x87, 0x2f, 0xc7, 0x22, 0xb2, 0x26, 0xcc, 0x9f, 0x59, + 0x54, 0x68, 0x9f, 0xfc, 0xbe, 0x2a, 0x2f, 0xc4, 0x55, 0x1c, 0x75, 0x40, + 0x60, 0x17, 0x85, 0x02, 0x55, 0x39, 0x8b, 0x7f, 0x05, 0x02, 0x03, 0x01, + 0x00, 0x01 }; #elif defined (ARDUINO_EDGE_CONTROL) From a33cd85ce6cfa2edf4a4382aea129f0268f121ab Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 15 Mar 2024 11:47:55 +0100 Subject: [PATCH 596/780] ArduinoIoTCloud integration --- src/ArduinoIoTCloudDevice.cpp | 1 - src/ArduinoIoTCloudTCP.cpp | 179 +++++++++------------------------- src/ArduinoIoTCloudTCP.h | 61 +++--------- 3 files changed, 58 insertions(+), 183 deletions(-) diff --git a/src/ArduinoIoTCloudDevice.cpp b/src/ArduinoIoTCloudDevice.cpp index 09151f4d2..53fcb74d5 100644 --- a/src/ArduinoIoTCloudDevice.cpp +++ b/src/ArduinoIoTCloudDevice.cpp @@ -135,7 +135,6 @@ ArduinoCloudDevice::State ArduinoCloudDevice::handleConnected() { } return State::SendCapabilities; } - return State::Connected; } diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 6e38a896b..687cdddf0 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -22,22 +22,11 @@ #include #ifdef HAS_TCP -#include - -#if defined(BOARD_HAS_SECRET_KEY) - #include "tls/AIoTCUPCert.h" -#endif -#ifdef BOARD_HAS_ECCX08 - #include "tls/BearSSLTrustAnchors.h" -#endif - -#if defined(BOARD_HAS_SE050) || defined(BOARD_HAS_SOFTSE) - #include "tls/AIoTCSSCert.h" -#endif +#include #if OTA_ENABLED - #include "utility/ota/OTA.h" + #include "ota/OTA.h" #endif #include @@ -67,26 +56,16 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _mqtt_data_buf{0} , _mqtt_data_len{0} , _mqtt_data_request_retransmit{false} -#ifdef BOARD_HAS_ECCX08 -, _sslClient(nullptr, ArduinoIoTCloudTrustAnchor, ArduinoIoTCloudTrustAnchor_NUM, getTime) -#endif #ifdef BOARD_HAS_SECRET_KEY , _password("") #endif , _mqttClient{nullptr} -, _deviceTopicOut("") -, _deviceTopicIn("") , _messageTopicOut("") , _messageTopicIn("") , _dataTopicOut("") , _dataTopicIn("") #if OTA_ENABLED -, _ota_cap{false} -, _ota_error{static_cast(OTAError::None)} -, _ota_img_sha256{"Inv."} -, _ota_url{""} -, _ota_req{false} -, _ask_user_before_executing_ota{false} +, _ota(&_message_stream) , _get_ota_confirmation{nullptr} #endif /* OTA_ENABLED */ { @@ -107,8 +86,16 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_ _brokerPort = brokerPort; #endif + /* Setup broker TLS client */ + _brokerClient.begin(connection); + +#if OTA_ENABLED + /* Setup OTA TLS client */ + _otaClient.begin(connection); +#endif + /* Setup TimeService */ - _time_service.begin(&connection); + _time_service.begin(_connection); /* Setup retry timers */ _connection_attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms); @@ -148,33 +135,19 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not read device certificate.", __FUNCTION__); return 0; } - _sslClient.setEccSlot(static_cast(SElementArduinoCloudSlot::Key), _cert.bytes(), _cert.length()); + _brokerClient.setEccSlot(static_cast(SElementArduinoCloudSlot::Key), _cert.bytes(), _cert.length()); + #if OTA_ENABLED + _otaClient.setEccSlot(static_cast(SElementArduinoCloudSlot::Key), _cert.bytes(), _cert.length()); + #endif #endif #endif + #if defined(BOARD_HAS_SECRET_KEY) } #endif -#if defined(BOARD_HAS_OFFLOADED_ECCX08) - -#elif defined(BOARD_HAS_ECCX08) - _sslClient.setClient(_connection->getClient()); -#elif defined(ARDUINO_PORTENTA_C33) - _sslClient.setClient(_connection->getClient()); - _sslClient.setCACert(AIoTSSCert); -#elif defined(ARDUINO_NICLA_VISION) - _sslClient.appendCustomCACert(AIoTSSCert); -#elif defined(ARDUINO_EDGE_CONTROL) - _sslClient.appendCustomCACert(AIoTUPCert); -#elif defined(ARDUINO_UNOR4_WIFI) - -#elif defined(ARDUINO_ARCH_ESP32) - _sslClient.setCACertBundle(x509_crt_bundle); -#elif defined(ARDUINO_ARCH_ESP8266) - _sslClient.setInsecure(); -#endif + _mqttClient.setClient(_brokerClient); - _mqttClient.setClient(_sslClient); #ifdef BOARD_HAS_SECRET_KEY if(_password.length()) { @@ -187,32 +160,19 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _mqttClient.setConnectionTimeout(1500); _mqttClient.setId(getDeviceId().c_str()); - _deviceTopicOut = getTopic_deviceout(); - _deviceTopicIn = getTopic_devicein(); - _messageTopicIn = getTopic_messagein(); _messageTopicOut = getTopic_messageout(); + _messageTopicIn = getTopic_messagein(); _thing.begin(); _device.begin(); -#if OTA_ENABLED - Property* p; - p = new CloudWrapperBool(_ota_cap); - addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_CAP", Permission::Read, -1); - p = new CloudWrapperInt(_ota_error); - addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_ERROR", Permission::Read, -1); - p = new CloudWrapperString(_ota_img_sha256); - addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_SHA256", Permission::Read, -1); - p = new CloudWrapperString(_ota_url); - addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_URL", Permission::ReadWrite, -1); - p = new CloudWrapperBool(_ota_req); - addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_REQ", Permission::ReadWrite, -1); - - _ota_cap = OTA::isCapable(); - - _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 +#if OTA_ENABLED && !defined(OFFLOADED_DOWNLOAD) + _ota.setClient(&_otaClient); +#endif // OTA_ENABLED && !defined(OFFLOADED_DOWNLOAD) + +#if OTA_ENABLED && defined(OTA_BASIC_AUTH) + _ota.setAuthentication(getDeviceId().c_str(), _password.c_str()); +#endif // OTA_ENABLED && !defined(OFFLOADED_DOWNLOAD) && defined(OTA_BASIC_AUTH) #ifdef BOARD_HAS_OFFLOADED_ECCX08 if (String(WiFi.firmwareVersion()) < String("1.4.4")) { @@ -323,9 +283,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() /* Subscribe to message topic to receive commands */ _mqttClient.subscribe(_messageTopicIn); - /* Temoporarly subscribe to device topic to receive OTA properties */ - _mqttClient.subscribe(_deviceTopicIn); - /* Reconfigure timers for next state */ _connection_attempt.begin(AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms, AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms); @@ -360,50 +317,24 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() /* Call CloudDevice process to get configuration */ _device.update(); - if (_device.isAttached()) { - /* Call CloudThing process to synchronize properties */ - _thing.update(); - } - -#if OTA_ENABLED - if (_device.connected()) { - handle_OTARequest(); +#if OTA_ENABLED + if(_get_ota_confirmation != nullptr && + _ota.getState() == OTACloudProcessInterface::State::OtaAvailable && + _get_ota_confirmation()) { + _ota.approveOta(); } -#endif /* OTA_ENABLED */ - return State::Connected; -} + _ota.update(); +#endif // OTA_ENABLED -#if OTA_ENABLED -void ArduinoIoTCloudTCP::handle_OTARequest() { - /* Request a OTA download if the hidden property - * OTA request has been set. - */ - if (_ota_req) - { - bool const ota_execution_allowed_by_user = (_get_ota_confirmation != nullptr && _get_ota_confirmation()); - bool const perform_ota_now = ota_execution_allowed_by_user || !_ask_user_before_executing_ota; - if (perform_ota_now) { - /* Clear the error flag. */ - _ota_error = static_cast(OTAError::None); - /* Clear the request flag. */ - _ota_req = false; - /* Transmit the cleared request flags to the cloud. */ - sendDevicePropertyToCloud("OTA_REQ"); - /* Call member function to handle OTA request. */ - _ota_error = OTA::onRequest(_ota_url, _connection->getInterface()); - /* If something fails send the OTA error to the cloud */ - sendDevicePropertyToCloud("OTA_ERROR"); - } + if (_device.isAttached()) { + /* Call CloudThing process to synchronize properties */ + _thing.update(); } - /* Check if we have received the OTA_URL property and provide - * echo to the cloud. - */ - sendDevicePropertyToCloud("OTA_URL"); + return State::Connected; } -#endif /* OTA_ENABLED */ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect() { @@ -441,11 +372,6 @@ void ArduinoIoTCloudTCP::handleMessage(int length) bytes[i] = _mqttClient.read(); } - /* Topic for OTA properties and device configuration */ - if (_deviceTopicIn == topic) { - CBORDecoder::decode(_device.getPropertyContainer(), (uint8_t*)bytes, length); - } - /* Topic for user input data */ if (_dataTopicIn == topic) { CBORDecoder::decode(_thing.getPropertyContainer(), (uint8_t*)bytes, length); @@ -502,6 +428,14 @@ void ArduinoIoTCloudTCP::handleMessage(int length) } break; +#if OTA_ENABLED + case CommandId::OtaUpdateCmdDownId: + { + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] ota update received", __FUNCTION__, millis()); + _ota.handleMessage((Message*)&command); + } +#endif + default: break; } @@ -522,14 +456,6 @@ void ArduinoIoTCloudTCP::sendMessage(Message * msg) _thing.getPropertyContainerIndex()); break; -#if OTA_ENABLED - case DeviceBeginCmdId: - sendDevicePropertyToCloud("OTA_CAP"); - sendDevicePropertyToCloud("OTA_ERROR"); - sendDevicePropertyToCloud("OTA_SHA256"); - break; -#endif - default: break; } @@ -562,21 +488,6 @@ void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(String const topic, Proper } } -#if OTA_ENABLED -void ArduinoIoTCloudTCP::sendDevicePropertyToCloud(String const name) -{ - PropertyContainer temp_device_property_container; - unsigned int last_device_property_index = 0; - - Property* p = getProperty(this->_device.getPropertyContainer(), name); - if(p != nullptr) - { - addPropertyToContainer(temp_device_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); - sendPropertyContainerToCloud(_deviceTopicOut, temp_device_property_container, last_device_property_index); - } -} -#endif - void ArduinoIoTCloudTCP::attachThing(String thingId) { _thing_id = thingId; diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 7f08c3ce2..29dfc7543 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -36,24 +36,11 @@ #endif #endif -#if defined(BOARD_HAS_OFFLOADED_ECCX08) - #include "WiFiSSLClient.h" -#elif defined(BOARD_HAS_ECCX08) - #include "tls/BearSSLClient.h" -#elif defined(ARDUINO_PORTENTA_C33) - #include -#elif defined(ARDUINO_NICLA_VISION) - #include -#elif defined(ARDUINO_EDGE_CONTROL) - #include -#elif defined(ARDUINO_UNOR4_WIFI) - #include -#elif defined(BOARD_ESP) - #include -#endif +#include +#include #if OTA_ENABLED -#include +#include #endif #include "cbor/MessageDecoder.h" @@ -107,9 +94,13 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass */ void onOTARequestCb(onOTARequestCallbackFunc cb) { _get_ota_confirmation = cb; - _ask_user_before_executing_ota = true; + + if(_get_ota_confirmation) { + _ota.setOtaPolicies(OTACloudProcessInterface::ApprovalRequired); + } else { + _ota.setOtaPolicies(OTACloudProcessInterface::None); + } } - void handle_OTARequest(); #endif private: @@ -147,44 +138,21 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #endif #endif -#if defined(BOARD_HAS_OFFLOADED_ECCX08) - WiFiBearSSLClient _sslClient; -#elif defined(BOARD_HAS_ECCX08) - BearSSLClient _sslClient; -#elif defined(ARDUINO_PORTENTA_C33) - SSLClient _sslClient; -#elif defined(ARDUINO_NICLA_VISION) - WiFiSSLSE050Client _sslClient; -#elif defined(ARDUINO_EDGE_CONTROL) - GSMSSLClient _sslClient; -#elif defined(ARDUINO_UNOR4_WIFI) - WiFiSSLClient _sslClient; -#elif defined(BOARD_ESP) - WiFiClientSecure _sslClient; -#endif - + TLSClientMqtt _brokerClient; MqttClient _mqttClient; - String _deviceTopicOut; - String _deviceTopicIn; String _messageTopicOut; String _messageTopicIn; String _dataTopicOut; String _dataTopicIn; + #if OTA_ENABLED - bool _ota_cap; - int _ota_error; - String _ota_img_sha256; - String _ota_url; - bool _ota_req; - bool _ask_user_before_executing_ota; + TLSClientOta _otaClient; + ArduinoCloudOTA _ota; onOTARequestCallbackFunc _get_ota_confirmation; #endif /* OTA_ENABLED */ - inline String getTopic_deviceout() { return String("/a/d/" + getDeviceId() + "/e/o");} - inline String getTopic_devicein () { return String("/a/d/" + getDeviceId() + "/e/i");} - inline String getTopic_messageout() { return String("/a/d/" + getDeviceId() + "/c/up");} inline String getTopic_messagein () { return String("/a/d/" + getDeviceId() + "/c/dw");} @@ -206,9 +174,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass void detachThing(); int write(String const topic, byte const data[], int const length); -#if OTA_ENABLED - void sendDevicePropertyToCloud(String const name); -#endif }; /****************************************************************************** From 3a0b4ceeb32cf0524910b3a1c9a672635b146d3c Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 29 Feb 2024 17:25:28 +0100 Subject: [PATCH 597/780] ArduinoIoTCloudTCP: switch to messages --- src/ArduinoIoTCloudTCP.cpp | 211 +++++++++++++++++-------------------- src/ArduinoIoTCloudTCP.h | 22 ++-- 2 files changed, 107 insertions(+), 126 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 0851700cc..6e38a896b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -43,6 +43,7 @@ #include #include "cbor/CBOREncoder.h" #include "utility/watchdog/Watchdog.h" +#include /****************************************************************************** LOCAL MODULE FUNCTIONS @@ -62,7 +63,6 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _connection_attempt(0,0) , _message_stream(std::bind(&ArduinoIoTCloudTCP::sendMessage, this, std::placeholders::_1)) , _thing(&_message_stream) -, _thing_id_property{nullptr} , _device(&_message_stream) , _mqtt_data_buf{0} , _mqtt_data_len{0} @@ -76,8 +76,8 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _mqttClient{nullptr} , _deviceTopicOut("") , _deviceTopicIn("") -, _shadowTopicOut("") -, _shadowTopicIn("") +, _messageTopicOut("") +, _messageTopicIn("") , _dataTopicOut("") , _dataTopicIn("") #if OTA_ENABLED @@ -181,6 +181,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _mqttClient.setUsernamePassword(getDeviceId(), _password); } #endif + _mqttClient.onMessage(ArduinoIoTCloudTCP::onMessage); _mqttClient.setKeepAliveInterval(30 * 1000); _mqttClient.setConnectionTimeout(1500); @@ -188,17 +189,14 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, _deviceTopicOut = getTopic_deviceout(); _deviceTopicIn = getTopic_devicein(); - - Property* p; - p = new CloudWrapperString(_lib_version); - addPropertyToContainer(_device.getPropertyContainer(), *p, "LIB_VERSION", Permission::Read, -1); - p = new CloudWrapperString(_thing_id); - _thing_id_property = &addPropertyToContainer(_device.getPropertyContainer(), *p, "thing_id", Permission::ReadWrite, -1).writeOnDemand(); + _messageTopicIn = getTopic_messagein(); + _messageTopicOut = getTopic_messageout(); _thing.begin(); _device.begin(); #if OTA_ENABLED + Property* p; p = new CloudWrapperBool(_ota_cap); addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_CAP", Permission::Read, -1); p = new CloudWrapperInt(_ota_error); @@ -322,9 +320,16 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() { if (_mqttClient.connect(_brokerAddress.c_str(), _brokerPort)) { - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s connected to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); + /* Subscribe to message topic to receive commands */ + _mqttClient.subscribe(_messageTopicIn); + + /* Temoporarly subscribe to device topic to receive OTA properties */ + _mqttClient.subscribe(_deviceTopicIn); + /* Reconfigure timers for next state */ _connection_attempt.begin(AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms, AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms); + + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s connected to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); return State::Connected; } @@ -413,7 +418,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect() _thing.handleMessage(&message); _device.handleMessage(&message); - _thing_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; DEBUG_INFO("Disconnected from Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); @@ -440,26 +444,6 @@ void ArduinoIoTCloudTCP::handleMessage(int length) /* Topic for OTA properties and device configuration */ if (_deviceTopicIn == topic) { CBORDecoder::decode(_device.getPropertyContainer(), (uint8_t*)bytes, length); - - /* Temporary check to avoid flooding device state machine with usless messages */ - if (_thing_id_property->isDifferentFromCloud()) { - _thing_id_property->fromCloudToLocal(); - - if (!_thing_id.length()) { - /* Send message to device state machine to inform we have received a null thing-id */ - _thing_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; - Message message; - message = { DeviceRegisteredCmdId }; - _device.handleMessage(&message); - } else { - if (_device.isAttached()) { - detachThing(); - } - if (!_device.isAttached()) { - attachThing(); - } - } - } } /* Topic for user input data */ @@ -467,41 +451,94 @@ void ArduinoIoTCloudTCP::handleMessage(int length) CBORDecoder::decode(_thing.getPropertyContainer(), (uint8_t*)bytes, length); } - /* Topic for sync Thing last values on connect */ - if (_shadowTopicIn == topic) { - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); - /* Decode last values property array */ - CBORDecoder::decode(_thing.getPropertyContainer(), (uint8_t*)bytes, length, true); - /* Unlock thing state machine waiting last values */ - Message message = { LastValuesUpdateCmdId }; - _thing.handleMessage(&message); - /* Call ArduinoIoTCloud sync user callback*/ - execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); + /* Topic for device commands */ + if (_messageTopicIn == topic) { + CommandDown command; + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] received %d bytes", __FUNCTION__, millis(), length); + CBORMessageDecoder decoder; + + size_t buffer_length = length; + if (decoder.decode((Message*)&command, bytes, buffer_length) != Decoder::Status::Error) { + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] received command id %d", __FUNCTION__, millis(), command.c.id); + switch (command.c.id) + { + case CommandId::ThingUpdateCmdId: + { + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] device configuration received", __FUNCTION__, millis()); + String new_thing_id = String(command.thingUpdateCmd.params.thing_id); + + if (!new_thing_id.length()) { + /* Send message to device state machine to inform we have received a null thing-id */ + _thing_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; + Message message; + message = { DeviceRegisteredCmdId }; + _device.handleMessage(&message); + } else { + if (_device.isAttached() && _thing_id != new_thing_id) { + detachThing(); + } + if (!_device.isAttached()) { + attachThing(new_thing_id); + } + } + } + break; + + case CommandId::LastValuesUpdateCmdId: + { + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); + CBORDecoder::decode(_thing.getPropertyContainer(), + (uint8_t*)command.lastValuesUpdateCmd.params.last_values, + command.lastValuesUpdateCmd.params.length, true); + _thing.handleMessage((Message*)&command); + execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); + + /* + * NOTE: in this current version properties are not properly integrated with the new paradigm of + * modeling the messages with C structs. The current CBOR library allocates an array in the heap + * thus we need to delete it after decoding it with the old CBORDecoder + */ + free(command.lastValuesUpdateCmd.params.last_values); + } + break; + + default: + break; + } + } } } void ArduinoIoTCloudTCP::sendMessage(Message * msg) { - switch (msg->id) - { - case DeviceBeginCmdId: - sendDevicePropertiesToCloud(); - break; + uint8_t data[MQTT_TRANSMIT_BUFFER_SIZE]; + size_t bytes_encoded = sizeof(data); + CBORMessageEncoder encoder; - case ThingBeginCmdId: - requestThingId(); - break; + switch (msg->id) { + case PropertiesUpdateCmdId: + return sendPropertyContainerToCloud(_dataTopicOut, + _thing.getPropertyContainer(), + _thing.getPropertyContainerIndex()); + break; - case LastValuesBeginCmdId: - requestLastValue(); - break; +#if OTA_ENABLED + case DeviceBeginCmdId: + sendDevicePropertyToCloud("OTA_CAP"); + sendDevicePropertyToCloud("OTA_ERROR"); + sendDevicePropertyToCloud("OTA_SHA256"); + break; +#endif - case PropertiesUpdateCmdId: - sendThingPropertiesToCloud(); - break; + default: + break; + } - default: - break; + if (encoder.encode(msg, data, bytes_encoded) == Encoder::Status::Complete && + bytes_encoded > 0) { + write(_messageTopicOut, data, bytes_encoded); + } else { + DEBUG_ERROR("error encoding %d", msg->id); } } @@ -525,29 +562,6 @@ void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(String const topic, Proper } } -void ArduinoIoTCloudTCP::sendThingPropertiesToCloud() -{ - sendPropertyContainerToCloud(_dataTopicOut, _thing.getPropertyContainer(), _thing.getPropertyContainerIndex()); -} - -void ArduinoIoTCloudTCP::sendDevicePropertiesToCloud() -{ - PropertyContainer ro_device_property_container; - unsigned int last_device_property_index = 0; - - std::list ro_device_property_list {"LIB_VERSION", "OTA_CAP", "OTA_ERROR", "OTA_SHA256"}; - std::for_each(ro_device_property_list.begin(), - ro_device_property_list.end(), - [this, &ro_device_property_container ] (String const & name) - { - Property* p = getProperty(this->_device.getPropertyContainer(), name); - if(p != nullptr) - addPropertyToContainer(ro_device_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read); - } - ); - sendPropertyContainerToCloud(_deviceTopicOut, ro_device_property_container, last_device_property_index); -} - #if OTA_ENABLED void ArduinoIoTCloudTCP::sendDevicePropertyToCloud(String const name) { @@ -563,28 +577,9 @@ void ArduinoIoTCloudTCP::sendDevicePropertyToCloud(String const name) } #endif -void ArduinoIoTCloudTCP::requestLastValue() -{ - // Send the getLastValues CBOR message to the cloud - // [{0: "r:m", 3: "getLastValues"}] = 81 A2 00 63 72 3A 6D 03 6D 67 65 74 4C 61 73 74 56 61 6C 75 65 73 - // Use http://cbor.me to easily generate CBOR encoding - const uint8_t CBOR_REQUEST_LAST_VALUE_MSG[] = { 0x81, 0xA2, 0x00, 0x63, 0x72, 0x3A, 0x6D, 0x03, 0x6D, 0x67, 0x65, 0x74, 0x4C, 0x61, 0x73, 0x74, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73 }; - write(_shadowTopicOut, CBOR_REQUEST_LAST_VALUE_MSG, sizeof(CBOR_REQUEST_LAST_VALUE_MSG)); -} - -void ArduinoIoTCloudTCP::requestThingId() -{ - if (!_mqttClient.subscribe(_deviceTopicIn)) - { - /* If device_id is wrong the board can't connect to the broker so this condition - * should never happen. - */ - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _deviceTopicIn.c_str()); - } -} - -void ArduinoIoTCloudTCP::attachThing() +void ArduinoIoTCloudTCP::attachThing(String thingId) { + _thing_id = thingId; _dataTopicIn = getTopic_datain(); _dataTopicOut = getTopic_dataout(); @@ -595,15 +590,6 @@ void ArduinoIoTCloudTCP::attachThing() return; } - _shadowTopicIn = getTopic_shadowin(); - _shadowTopicOut = getTopic_shadowout(); - if (!_mqttClient.subscribe(_shadowTopicIn)) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _shadowTopicIn.c_str()); - DEBUG_ERROR("Check your thing configuration, and press the reset button on your board."); - _thing_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; - return; - } - Message message; message = { DeviceAttachedCmdId }; _device.handleMessage(&message); @@ -620,11 +606,6 @@ void ArduinoIoTCloudTCP::detachThing() return; } - if (!_mqttClient.unsubscribe(_shadowTopicIn)) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not unsubscribe from %s", __FUNCTION__, _shadowTopicIn.c_str()); - return; - } - Message message; message = { DeviceDetachedCmdId }; _device.handleMessage(&message); diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 1c13592df..7f08c3ce2 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -56,6 +56,9 @@ #include #endif +#include "cbor/MessageDecoder.h" +#include "cbor/MessageEncoder.h" + /****************************************************************************** CONSTANTS ******************************************************************************/ @@ -125,7 +128,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass TimedAttempt _connection_attempt; MessageStream _message_stream; ArduinoCloudThing _thing; - Property * _thing_id_property; ArduinoCloudDevice _device; String _brokerAddress; @@ -165,8 +167,8 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass String _deviceTopicOut; String _deviceTopicIn; - String _shadowTopicOut; - String _shadowTopicIn; + String _messageTopicOut; + String _messageTopicIn; String _dataTopicOut; String _dataTopicIn; @@ -182,8 +184,10 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass inline String getTopic_deviceout() { return String("/a/d/" + getDeviceId() + "/e/o");} inline String getTopic_devicein () { return String("/a/d/" + getDeviceId() + "/e/i");} - inline String getTopic_shadowout() { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/shadow/o"); } - inline String getTopic_shadowin () { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/shadow/i"); } + + inline String getTopic_messageout() { return String("/a/d/" + getDeviceId() + "/c/up");} + inline String getTopic_messagein () { return String("/a/d/" + getDeviceId() + "/c/dw");} + inline String getTopic_dataout () { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/e/o"); } inline String getTopic_datain () { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/e/i"); } @@ -197,18 +201,14 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass void handleMessage(int length); void sendMessage(Message * msg); void sendPropertyContainerToCloud(String const topic, PropertyContainer & property_container, unsigned int & current_property_index); - void sendThingPropertiesToCloud(); - void sendDevicePropertiesToCloud(); - void requestLastValue(); - void requestThingId(); - void attachThing(); + + void attachThing(String thingId); void detachThing(); int write(String const topic, byte const data[], int const length); #if OTA_ENABLED void sendDevicePropertyToCloud(String const name); #endif - }; /****************************************************************************** From 91a43380be6ac70eb83063f104dc55b9b1ae2360 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 24 Apr 2024 09:07:22 +0200 Subject: [PATCH 598/780] BearSSL Trust Anchors: remove ces.iot.arduino.cc --- src/tls/BearSSLTrustAnchors.h | 36 ++--------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/src/tls/BearSSLTrustAnchors.h b/src/tls/BearSSLTrustAnchors.h index 802dff3a5..3646b6e8f 100644 --- a/src/tls/BearSSLTrustAnchors.h +++ b/src/tls/BearSSLTrustAnchors.h @@ -55,26 +55,7 @@ static const unsigned char TA0_EC_Q[] = { 0x42, 0x89, 0x89, 0x55, 0x22 }; -static const unsigned char TA1_DN[] = { - 0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x13, 0x0E, 0x41, 0x72, 0x64, 0x75, 0x69, 0x6E, 0x6F, 0x20, 0x4C, 0x4C, - 0x43, 0x20, 0x55, 0x53, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x0B, 0x13, 0x02, 0x49, 0x54, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x12, 0x63, 0x65, 0x73, 0x2E, 0x69, 0x6F, 0x74, 0x2E, - 0x61, 0x72, 0x64, 0x75, 0x69, 0x6E, 0x6F, 0x2E, 0x63, 0x63 -}; - -static const unsigned char TA1_EC_Q[] = { - 0x04, 0x57, 0x4A, 0xF7, 0xFB, 0x20, 0x2A, 0x1E, 0xBD, 0x98, 0xD5, 0xA8, - 0xFF, 0xD4, 0xEF, 0x7B, 0x90, 0xB9, 0x37, 0xA0, 0xB7, 0x00, 0x16, 0x09, - 0x57, 0x3C, 0xD5, 0x92, 0x42, 0xAA, 0x9F, 0x78, 0xCF, 0xD5, 0x54, 0x21, - 0xE6, 0x28, 0x89, 0x73, 0x2A, 0x4E, 0xC3, 0x9D, 0xBC, 0x10, 0x57, 0x79, - 0x91, 0x87, 0x93, 0xD8, 0xAE, 0x15, 0xA7, 0xDB, 0x79, 0x56, 0x4D, 0x5F, - 0x96, 0x8D, 0xE3, 0xDC, 0x51 -}; - -static const br_x509_trust_anchor ArduinoIoTCloudTrustAnchor[2] = { +static const br_x509_trust_anchor ArduinoIoTCloudTrustAnchor[1] = { { { (unsigned char *)TA0_DN, sizeof TA0_DN }, BR_X509_TA_CA, @@ -87,23 +68,10 @@ static const br_x509_trust_anchor ArduinoIoTCloudTrustAnchor[2] = { } } } - }, - { - { (unsigned char *)TA1_DN, sizeof TA1_DN }, - 0, - { - BR_KEYTYPE_EC, - { - .ec = { - BR_EC_secp256r1, - (unsigned char *)TA1_EC_Q, sizeof TA1_EC_Q, - } - } - } } }; -#define ArduinoIoTCloudTrustAnchor_NUM (2) +#define ArduinoIoTCloudTrustAnchor_NUM (1) #endif /* #ifdef BOARD_HAS_ECCX08 */ From 613eae25e276e2be0b1b536b275134bef4fda657 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 24 Apr 2024 14:34:26 +0200 Subject: [PATCH 599/780] Ota default interface: making the download run at least a configurable amount of time --- src/ota/interface/OTAInterfaceDefault.cpp | 24 +++++++++++++---------- src/ota/interface/OTAInterfaceDefault.h | 4 ++++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/ota/interface/OTAInterfaceDefault.cpp b/src/ota/interface/OTAInterfaceDefault.cpp index de698e660..d96442bc3 100644 --- a/src/ota/interface/OTAInterfaceDefault.cpp +++ b/src/ota/interface/OTAInterfaceDefault.cpp @@ -91,20 +91,24 @@ OTACloudProcessInterface::State OTADefaultCloudProcessInterface::startOTA() { OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetch() { OTACloudProcessInterface::State res = Fetch; int http_res = 0; + uint32_t start = millis(); - if(http_client->available() == 0) { - goto exit; - } + do { + if(http_client->available() == 0) { + goto exit; + } - http_res = http_client->read(context->buffer, context->buf_len); + http_res = http_client->read(context->buffer, context->buf_len); - if(http_res < 0) { - DEBUG_VERBOSE("OTA ERROR: Download read error %d", http_res); - res = OtaDownloadFail; - goto exit; - } + if(http_res < 0) { + DEBUG_VERBOSE("OTA ERROR: Download read error %d", http_res); + res = OtaDownloadFail; + goto exit; + } - parseOta(context->buffer, http_res); + parseOta(context->buffer, http_res); + } while((context->downloadState == OtaDownloadFile || context->downloadState == OtaDownloadHeader) && + millis() - start < downloadTime); // TODO verify that the information present in the ota header match the info in context if(context->downloadState == OtaDownloadCompleted) { diff --git a/src/ota/interface/OTAInterfaceDefault.h b/src/ota/interface/OTAInterfaceDefault.h index ae68d53bc..8f7aaf18a 100644 --- a/src/ota/interface/OTAInterfaceDefault.h +++ b/src/ota/interface/OTAInterfaceDefault.h @@ -49,6 +49,10 @@ class OTADefaultCloudProcessInterface: public OTACloudProcessInterface { const char *username, *password; + // The amount of time that each iteration of Fetch has to take at least + // This mitigate the issues arising from tasks run in main loop that are using all the computing time + static constexpr uint32_t downloadTime = 100; + enum OTADownloadState: uint8_t { OtaDownloadHeader, OtaDownloadFile, From 35db5e7f33684864366aae4d7fd28cb775c536f8 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 15 May 2024 16:05:00 +0200 Subject: [PATCH 600/780] Ota H7 unmount filesystem before reset hotfix --- src/ota/implementation/OTASTM32H7.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp index b1cbe7017..c3cefdd86 100644 --- a/src/ota/implementation/OTASTM32H7.cpp +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -83,6 +83,8 @@ OTACloudProcessInterface::State STM32H7OTACloudProcess::flashOTA() { return OtaStorageOpenFail; } + storageClean(); + // this sets the registries in RTC to load the firmware from the storage selected at the next reboot STM32H747::writeBackupRegister(RTCBackup::DR0, 0x07AA); STM32H747::writeBackupRegister(RTCBackup::DR1, storage); @@ -113,7 +115,9 @@ void STM32H7OTACloudProcess::storageClean() { DEBUG_VERBOSE(F("storage clean")); if(decompressed != nullptr) { - fclose(decompressed); + int res = fclose(decompressed); + DEBUG_VERBOSE("error on fclose %d", res); + decompressed = nullptr; } From ba2d5841e24029cc7e878cf68f5993b6a25b5802 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 20 Mar 2024 10:43:43 +0100 Subject: [PATCH 601/780] ArduinoIoTCloudDevice: switch to messages --- src/ArduinoIoTCloudDevice.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ArduinoIoTCloudDevice.cpp b/src/ArduinoIoTCloudDevice.cpp index f6594e027..09151f4d2 100644 --- a/src/ArduinoIoTCloudDevice.cpp +++ b/src/ArduinoIoTCloudDevice.cpp @@ -104,12 +104,12 @@ ArduinoCloudDevice::State ArduinoCloudDevice::handleInit() { ArduinoCloudDevice::State ArduinoCloudDevice::handleSendCapabilities() { /* Sends device capabilities message */ - Message message = { DeviceBeginCmdId }; - deliver(&message); + DeviceBeginCmd deviceBegin = { DeviceBeginCmdId, AIOT_CONFIG_LIB_VERSION }; + deliver(reinterpret_cast(&deviceBegin)); /* Subscribe to device topic to request */ - message = { ThingBeginCmdId }; - deliver(&message); + ThingBeginCmd thingBegin = { ThingBeginCmdId }; + deliver(reinterpret_cast(&thingBegin)); /* No device configuration received. Wait: 4s -> 8s -> 16s -> 32s -> 32s ...*/ _attachAttempt.retry(); From a4719bbbdf982aa2396c6c8f289aef67e8a26e76 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 24 Apr 2024 09:13:33 +0200 Subject: [PATCH 602/780] UNO R4 WiFi: remove unused certificate bundle --- src/tls/AIoTCUPCert.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tls/AIoTCUPCert.h b/src/tls/AIoTCUPCert.h index 1e942bcb8..5c933da03 100644 --- a/src/tls/AIoTCUPCert.h +++ b/src/tls/AIoTCUPCert.h @@ -24,7 +24,7 @@ ******************************************************************************/ #include -#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_UNOR4_WIFI) +#if defined(ARDUINO_ARCH_ESP32) /****************************************************************************** * CONSTANTS From 249bae3723b12fc4741f776f8aa926ca96b61835 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 24 Apr 2024 15:02:39 +0200 Subject: [PATCH 603/780] Ota interface Default: adding download progress status report --- src/ota/interface/OTAInterfaceDefault.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ota/interface/OTAInterfaceDefault.cpp b/src/ota/interface/OTAInterfaceDefault.cpp index d96442bc3..d39ec0f2d 100644 --- a/src/ota/interface/OTAInterfaceDefault.cpp +++ b/src/ota/interface/OTAInterfaceDefault.cpp @@ -182,11 +182,10 @@ void OTADefaultCloudProcessInterface::parseOta(uint8_t* buffer, size_t buf_len) cursor += buf_len - (cursor-buffer); context->downloadedSize += (cursor-buffer); - if((millis() - context->lastReportTime) > 2000) { // Report the download progress each X millisecond + if((millis() - context->lastReportTime) > 10000) { // Report the download progress each X millisecond DEBUG_VERBOSE("OTA Download Progress %d/%d", context->downloadedSize, http_client->contentLength()); - // FIXME the following line enables the report for download progress, it breaks - // reportStatus(context->downloadedSize); + reportStatus(context->downloadedSize); context->lastReportTime = millis(); } From ee8e9bb37064cc19035195c7e803d7b63e86bbe1 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 18 Apr 2024 15:39:52 +0200 Subject: [PATCH 604/780] CI: removed unused libraries --- .github/workflows/compile-examples.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 0e6c98ef9..a4e68ab0d 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -170,7 +170,6 @@ jobs: - name: arduino:mbed_portenta libraries: | - name: ArduinoECCX08 - - name: Arduino_Portenta_OTA sketch-paths: | - examples/ArduinoIoTCloud-DeferredOTA - examples/utility/Provisioning @@ -181,7 +180,6 @@ jobs: # Install mbed_nicla platform via Boards Manager - name: arduino:mbed_nicla libraries: | - - name: Arduino_Portenta_OTA sketch-paths: | - examples/ArduinoIoTCloud-DeferredOTA - examples/utility/Provisioning @@ -193,7 +191,6 @@ jobs: - name: arduino:mbed_opta libraries: | - name: ArduinoECCX08 - - name: Arduino_Portenta_OTA sketch-paths: | - examples/ArduinoIoTCloud-DeferredOTA - examples/utility/Provisioning @@ -205,7 +202,6 @@ jobs: - name: arduino:mbed_giga libraries: | - name: ArduinoECCX08 - - name: Arduino_Portenta_OTA sketch-paths: | - examples/ArduinoIoTCloud-DeferredOTA - examples/utility/Provisioning @@ -229,8 +225,6 @@ jobs: platforms: | # Install arduino_esp32 platform via Boards Manager - name: arduino:esp32 - libraries: | - - name: Arduino_ESP32_OTA sketch-paths: | - examples/ArduinoIoTCloud-DeferredOTA # Edge Control @@ -257,8 +251,6 @@ jobs: # Install ESP32 platform via Boards Manager - name: esp32:esp32 source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - libraries: | - - name: Arduino_ESP32_OTA sketch-paths: | - examples/ArduinoIoTCloud-DeferredOTA From 59b63d2c82cf4410725116735628896da262a925 Mon Sep 17 00:00:00 2001 From: Roberto Gazia Date: Mon, 29 Apr 2024 11:20:47 +0200 Subject: [PATCH 605/780] Add detach command support --- extras/test/src/test_command_decode.cpp | 50 +++++++++++++++++++++++++ extras/test/src/test_command_encode.cpp | 18 +++++++++ src/ArduinoIoTCloudTCP.cpp | 11 ++++++ src/cbor/CBOR.cpp | 4 ++ src/cbor/CBOR.h | 1 + src/cbor/MessageDecoder.cpp | 14 +++++++ src/cbor/MessageDecoder.h | 1 + src/message/Commands.h | 9 +++++ 8 files changed, 108 insertions(+) diff --git a/extras/test/src/test_command_decode.cpp b/extras/test/src/test_command_decode.cpp index 818d02136..434d7807d 100644 --- a/extras/test/src/test_command_decode.cpp +++ b/extras/test/src/test_command_decode.cpp @@ -50,6 +50,35 @@ SCENARIO("Test the decoding of command messages") { } /****************************************************************************/ + WHEN("Decode the ThingDetachCmd message") + { + CommandDown command; + /* + DA 00011000 # tag(69632) + 81 # array(1) + 78 24 # text(36) + 65343439346435352D383732612D346664322D393634362D393266383739343933393463 # "e4494d55-872a-4fd2-9646-92f87949394c" + */ + uint8_t const payload[] = {0xDA, 0x00, 0x01, 0x10, 0x00, 0x81, 0x78, 0x24, + 0x65, 0x34, 0x34, 0x39, 0x34, 0x64, 0x35, 0x35, + 0x2D, 0x38, 0x37, 0x32, 0x61, 0x2D, 0x34, 0x66, + 0x64, 0x32, 0x2D, 0x39, 0x36, 0x34, 0x36, 0x2D, + 0x39, 0x32, 0x66, 0x38, 0x37, 0x39, 0x34, 0x39, + 0x33, 0x39, 0x34, 0x63}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + const char *thingIdToMatch = "e4494d55-872a-4fd2-9646-92f87949394c"; + + THEN("The decode is successful") { + REQUIRE(err == Decoder::Status::Complete); + REQUIRE(strcmp(command.thingDetachCmd.params.thing_id, thingIdToMatch) == 0); + REQUIRE(command.c.id == ThingDetachCmdId); + } + } + + /************************************************************************************/ WHEN("Decode the ThingUpdateCmdId message containing a number instead of a string") { @@ -71,6 +100,27 @@ SCENARIO("Test the decoding of command messages") { } } + /****************************************************************************/ + WHEN("Decode the ThingDetachCmd message containing a number instead of a string") + { + CommandDown command; + /* + DA 00011000 # tag(69632) + 81 # array(1) + 1A 65DCB821 # unsigned(1708963873) + */ + uint8_t const payload[] = {0xDA, 0x00, 0x01, 0x10, 0x00, 0x81, 0x1A, 0x65, + 0xDC, 0xB8, 0x21}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is successful") { + REQUIRE(err == Decoder::Status::Error); + } + } + /****************************************************************************/ WHEN("Decode the SetTimezoneCommand message") diff --git a/extras/test/src/test_command_encode.cpp b/extras/test/src/test_command_encode.cpp index 7e31c1487..1f3b38baa 100644 --- a/extras/test/src/test_command_encode.cpp +++ b/extras/test/src/test_command_encode.cpp @@ -304,6 +304,24 @@ SCENARIO("Test the encoding of command messages") { /****************************************************************************/ + WHEN("Encode the ThingDetachCmd message") + { + ThingDetachCmd command; + command.c.id = CommandId::ThingDetachCmdId; + + uint8_t buffer[512]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + THEN("The encoding is unsuccessful - ThingDetachCmd is not supported") { + REQUIRE(err == Encoder::Status::Error); + } + } + + /****************************************************************************/ + WHEN("Encode a message with unknown command Id") { OtaUpdateCmdDown command; diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 687cdddf0..ea23d1e81 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -410,6 +410,17 @@ void ArduinoIoTCloudTCP::handleMessage(int length) } break; + case CommandId::ThingDetachCmdId: + { + if (!_device.isAttached() || _thing_id != String(command.thingDetachCmd.params.thing_id)) { + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] thing detach rejected", __FUNCTION__, millis()); + } + + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] thing detach received", __FUNCTION__, millis()); + detachThing(); + } + break; + case CommandId::LastValuesUpdateCmdId: { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); diff --git a/src/cbor/CBOR.cpp b/src/cbor/CBOR.cpp index ced5e3e7f..b043f5a14 100644 --- a/src/cbor/CBOR.cpp +++ b/src/cbor/CBOR.cpp @@ -36,6 +36,8 @@ CommandId toCommandId(CBORCommandTag tag) { return CommandId::OtaUpdateCmdDownId; case CBORCommandTag::CBORThingUpdateCmd: return CommandId::ThingUpdateCmdId; + case CBORCommandTag::CBORThingDetachCmd: + return CommandId::ThingDetachCmdId; case CBORCommandTag::CBORLastValuesUpdate: return CommandId::LastValuesUpdateCmdId; case CBORCommandTag::CBORTimezoneCommandDown: @@ -63,6 +65,8 @@ CBORCommandTag toCBORCommandTag(CommandId id) { return CBORCommandTag::CBOROtaUpdateCmdDown; case CommandId::ThingUpdateCmdId: return CBORCommandTag::CBORThingUpdateCmd; + case CommandId::ThingDetachCmdId: + return CBORCommandTag::CBORThingDetachCmd; case CommandId::LastValuesUpdateCmdId: return CBORCommandTag::CBORLastValuesUpdate; case CommandId::TimezoneCommandDownId: diff --git a/src/cbor/CBOR.h b/src/cbor/CBOR.h index 999570455..7e9a04d97 100644 --- a/src/cbor/CBOR.h +++ b/src/cbor/CBOR.h @@ -31,6 +31,7 @@ enum CBORCommandTag: uint64_t { // Commands DOWN CBOROtaUpdateCmdDown = 0x010100, CBORThingUpdateCmd = 0x010400, + CBORThingDetachCmd = 0x011000, CBORLastValuesUpdate = 0x010600, CBORTimezoneCommandDown = 0x010900, diff --git a/src/cbor/MessageDecoder.cpp b/src/cbor/MessageDecoder.cpp index c500ceae9..7c3e9a215 100644 --- a/src/cbor/MessageDecoder.cpp +++ b/src/cbor/MessageDecoder.cpp @@ -130,6 +130,17 @@ CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeThingUpdateCmd(Cb return ArrayParserState::LeaveArray; } +CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeThingDetachCmd(CborValue * param, Message * message) { + ThingDetachCmd * thingCommand = (ThingDetachCmd *) message; + + // Message is composed of a single parameter, a string (thing_id) + if (!copyCBORStringToArray(param, thingCommand->params.thing_id, sizeof(thingCommand->params.thing_id))) { + return ArrayParserState::Error; + } + + return ArrayParserState::LeaveArray; +} + CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeTimezoneCommandDown(CborValue * param, Message * message) { TimezoneCommandDown * setTz = (TimezoneCommandDown *) message; @@ -213,6 +224,9 @@ CBORMessageDecoder::ArrayParserState CBORMessageDecoder::handle_Param(CborValue case CommandId::ThingUpdateCmdId: return CBORMessageDecoder::decodeThingUpdateCmd(param, message); + case CommandId::ThingDetachCmdId: + return CBORMessageDecoder::decodeThingDetachCmd(param, message); + case CommandId::TimezoneCommandDownId: return CBORMessageDecoder::decodeTimezoneCommandDown(param, message); diff --git a/src/cbor/MessageDecoder.h b/src/cbor/MessageDecoder.h index 712289c9d..1223e947b 100644 --- a/src/cbor/MessageDecoder.h +++ b/src/cbor/MessageDecoder.h @@ -65,6 +65,7 @@ class CBORMessageDecoder: public Decoder // Message specific decoders ArrayParserState decodeThingUpdateCmd(CborValue * param, Message * message); + ArrayParserState decodeThingDetachCmd(CborValue * param, Message * message); ArrayParserState decodeTimezoneCommandDown(CborValue * param, Message * message); ArrayParserState decodeLastValuesUpdateCmd(CborValue * param, Message * message); ArrayParserState decodeOtaUpdateCmdDown(CborValue * param, Message * message); diff --git a/src/message/Commands.h b/src/message/Commands.h index ce71f9c81..f0e9a15c9 100644 --- a/src/message/Commands.h +++ b/src/message/Commands.h @@ -37,6 +37,7 @@ enum CommandId: uint32_t { DeviceBeginCmdId, ThingBeginCmdId, ThingUpdateCmdId, + ThingDetachCmdId, DeviceRegisteredCmdId, DeviceAttachedCmdId, DeviceDetachedCmdId, @@ -89,6 +90,13 @@ struct ThingUpdateCmd { } params; }; +struct ThingDetachCmd { + Command c; + struct { + char thing_id[THING_ID_SIZE]; + } params; +}; + struct LastValuesBeginCmd { Command c; }; @@ -144,6 +152,7 @@ union CommandDown { struct Command c; struct OtaUpdateCmdDown otaUpdateCmdDown; struct ThingUpdateCmd thingUpdateCmd; + struct ThingDetachCmd thingDetachCmd; struct LastValuesUpdateCmd lastValuesUpdateCmd; struct TimezoneCommandDown timezoneCommandDown; }; From 00880124946ee633a6f019734d2e1387b755dd46 Mon Sep 17 00:00:00 2001 From: Roberto Gazia Date: Mon, 29 Apr 2024 11:21:04 +0200 Subject: [PATCH 606/780] Add update timezone command support --- src/ArduinoIoTCloudTCP.cpp | 7 +++++++ src/ArduinoIoTCloudThing.cpp | 14 ++++++++++---- src/ArduinoIoTCloudThing.h | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index ea23d1e81..1c44f8611 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -421,6 +421,13 @@ void ArduinoIoTCloudTCP::handleMessage(int length) } break; + case CommandId::TimezoneCommandDownId: + { + DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] timezone update received", __FUNCTION__, millis()); + _thing.handleMessage((Message*)&command); + } + break; + case CommandId::LastValuesUpdateCmdId: { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); diff --git a/src/ArduinoIoTCloudThing.cpp b/src/ArduinoIoTCloudThing.cpp index d2f49119b..d3df764a3 100644 --- a/src/ArduinoIoTCloudThing.cpp +++ b/src/ArduinoIoTCloudThing.cpp @@ -69,7 +69,7 @@ void ArduinoCloudThing::update() { } /* Handle external events */ - switch (_command) { + switch (_command.c.id) { case LastValuesUpdateCmdId: if (_state == State::RequestLastValues) { DEBUG_VERBOSE("CloudThing::%s Thing is synced", __FUNCTION__); @@ -77,6 +77,12 @@ void ArduinoCloudThing::update() { } break; + /* We have received a timezone update */ + case TimezoneCommandDownId: + TimeService.setTimeZoneData(_command.timezoneCommandDown.params.offset, + _command.timezoneCommandDown.params.until); + break; + /* We have received a reset command */ case ResetCmdId: nextState = State::Init; @@ -86,7 +92,7 @@ void ArduinoCloudThing::update() { break; } - _command = UnknownCmdId; + _command.c.id = UnknownCmdId; _state = nextState; } @@ -95,9 +101,9 @@ int ArduinoCloudThing::connected() { } void ArduinoCloudThing::handleMessage(Message* m) { - _command = UnknownCmdId; + _command.c.id = UnknownCmdId; if (m != nullptr) { - _command = m->id; + memcpy(&_command, m, sizeof(CommandDown)); } } diff --git a/src/ArduinoIoTCloudThing.h b/src/ArduinoIoTCloudThing.h index de52bc002..86cfb850f 100644 --- a/src/ArduinoIoTCloudThing.h +++ b/src/ArduinoIoTCloudThing.h @@ -51,7 +51,7 @@ class ArduinoCloudThing : public CloudProcess { }; State _state; - CommandId _command; + CommandDown _command; TimedAttempt _syncAttempt; PropertyContainer _propertyContainer; unsigned int _propertyContainerIndex; From b95a6fd623048b3a64eaee3c80134ef2d68cb5ce Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 17 May 2024 11:40:53 +0200 Subject: [PATCH 607/780] Use correct command name TimezoneCommandDown in test name --- extras/test/src/test_command_decode.cpp | 2 +- extras/test/src/test_command_encode.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/test/src/test_command_decode.cpp b/extras/test/src/test_command_decode.cpp index 434d7807d..b20f88605 100644 --- a/extras/test/src/test_command_decode.cpp +++ b/extras/test/src/test_command_decode.cpp @@ -123,7 +123,7 @@ SCENARIO("Test the decoding of command messages") { /****************************************************************************/ - WHEN("Decode the SetTimezoneCommand message") + WHEN("Decode the TimezoneCommandDown message") { CommandDown command; diff --git a/extras/test/src/test_command_encode.cpp b/extras/test/src/test_command_encode.cpp index 1f3b38baa..b18ecff7a 100644 --- a/extras/test/src/test_command_encode.cpp +++ b/extras/test/src/test_command_encode.cpp @@ -242,7 +242,7 @@ SCENARIO("Test the encoding of command messages") { /****************************************************************************/ - WHEN("Encode the SetTimezoneCommand message") + WHEN("Encode the TimezoneCommandDown message") { TimezoneCommandDown command; command.c.id = CommandId::TimezoneCommandDownId; From c84110ae496d997a0bedf65b55538752584788fa Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 20 May 2024 11:37:28 +0200 Subject: [PATCH 608/780] removing .DS_Store --- extras/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 extras/.DS_Store diff --git a/extras/.DS_Store b/extras/.DS_Store deleted file mode 100644 index 2bf60533173cb0027117c9b7d98faa167d25091e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKIS#@=4752UBpOP}{Q^H&A$S2Fpg^KQLE@@Y@h+am_-LXi9TcE(S-46wBSQFbozdA5@3jmxT?1s7b62M{sU`=cT z5rJt?fkD-5F*N9im&~h)ZD7zvv-!|`vu1~){&t*SJYBQ~a-;%OpsT<*mJ6%@Tlhf# z-z9NH1*pJZDWH?hZnMTGWo_+!oYmR_-@`5E1vkUoDHyyQ1HBw$VdZ$~Ns(7Hq)$ From 335daf8ade5639a6aeb65f918ea4105014244c5c Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 20 May 2024 12:21:51 +0200 Subject: [PATCH 609/780] Release v2.0.0 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 3664ce8c5..f874be78c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=1.15.1 +version=2.0.0 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index e889bbdde..2dd03e223 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -158,6 +158,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "1.15.1" +#define AIOT_CONFIG_LIB_VERSION "2.0.0" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 3069915ef7d07314bf9e32962415f217a7e0accc Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 27 May 2024 09:18:42 +0200 Subject: [PATCH 610/780] Avoid using memcpy to store timezone data --- src/ArduinoIoTCloudThing.cpp | 15 +++++++++------ src/ArduinoIoTCloudThing.h | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ArduinoIoTCloudThing.cpp b/src/ArduinoIoTCloudThing.cpp index d3df764a3..9b3656b0f 100644 --- a/src/ArduinoIoTCloudThing.cpp +++ b/src/ArduinoIoTCloudThing.cpp @@ -69,7 +69,7 @@ void ArduinoCloudThing::update() { } /* Handle external events */ - switch (_command.c.id) { + switch (_command) { case LastValuesUpdateCmdId: if (_state == State::RequestLastValues) { DEBUG_VERBOSE("CloudThing::%s Thing is synced", __FUNCTION__); @@ -79,8 +79,7 @@ void ArduinoCloudThing::update() { /* We have received a timezone update */ case TimezoneCommandDownId: - TimeService.setTimeZoneData(_command.timezoneCommandDown.params.offset, - _command.timezoneCommandDown.params.until); + TimeService.setTimeZoneData(_utcOffset, _utcOffsetExpireTime); break; /* We have received a reset command */ @@ -92,7 +91,7 @@ void ArduinoCloudThing::update() { break; } - _command.c.id = UnknownCmdId; + _command = UnknownCmdId; _state = nextState; } @@ -101,9 +100,13 @@ int ArduinoCloudThing::connected() { } void ArduinoCloudThing::handleMessage(Message* m) { - _command.c.id = UnknownCmdId; + _command = UnknownCmdId; if (m != nullptr) { - memcpy(&_command, m, sizeof(CommandDown)); + _command = m->id; + if (_command == TimezoneCommandDownId) { + _utcOffset = reinterpret_cast(m)->params.offset; + _utcOffsetExpireTime = reinterpret_cast(m)->params.until; + } } } diff --git a/src/ArduinoIoTCloudThing.h b/src/ArduinoIoTCloudThing.h index 86cfb850f..de52bc002 100644 --- a/src/ArduinoIoTCloudThing.h +++ b/src/ArduinoIoTCloudThing.h @@ -51,7 +51,7 @@ class ArduinoCloudThing : public CloudProcess { }; State _state; - CommandDown _command; + CommandId _command; TimedAttempt _syncAttempt; PropertyContainer _propertyContainer; unsigned int _propertyContainerIndex; From 461025bfa67cee3b2773b2526f8f87cb7f23f2ce Mon Sep 17 00:00:00 2001 From: "Zachary J. Fields" Date: Thu, 16 May 2024 14:35:39 -0500 Subject: [PATCH 611/780] fix: Warnings --- src/utility/time/TimeService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index cc3872150..05290b211 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -281,7 +281,7 @@ bool TimeServiceClass::connected() if(_con_hdl == nullptr) { return false; } else { - return _con_hdl->getStatus() == NetworkConnectionState::CONNECTED; + return _con_hdl->check() == NetworkConnectionState::CONNECTED; } } From 1e3d7d5978c7b74763c8a496d0ce5d1e789cdf4c Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 27 May 2024 12:42:00 +0200 Subject: [PATCH 612/780] Delete nullptr check on local fixed size array --- src/ota/implementation/OTAEsp32.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ota/implementation/OTAEsp32.cpp b/src/ota/implementation/OTAEsp32.cpp index f52e64721..055eb6a0e 100644 --- a/src/ota/implementation/OTAEsp32.cpp +++ b/src/ota/implementation/OTAEsp32.cpp @@ -89,10 +89,6 @@ void ESP32OTACloudProcess::calculateSHA256(SHA256& sha256_calc) { sha256_calc.begin(); uint8_t b[SPI_FLASH_SEC_SIZE]; - if(b == nullptr) { - DEBUG_VERBOSE("ESP32::SHA256 Not enough memory to allocate buffer"); - return; // TODO error reporting - } uint32_t read_bytes = 0; uint32_t const app_size = ESP.getSketchSize(); From dd4c09d7e6e0654ddec7bd1425194fb0209579a9 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 28 May 2024 09:00:04 +0200 Subject: [PATCH 613/780] Release v2.0.1 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index f874be78c..c044ef343 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=2.0.0 +version=2.0.1 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 2dd03e223..592b19f3c 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -158,6 +158,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "2.0.0" +#define AIOT_CONFIG_LIB_VERSION "2.0.1" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 6c98e07e2928ef56dedbccc521a041db0b85f6f7 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 31 May 2024 11:21:27 +0200 Subject: [PATCH 614/780] OTA: ESP32 fix build on core 3.0.0 --- src/ota/implementation/OTAEsp32.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ota/implementation/OTAEsp32.cpp b/src/ota/implementation/OTAEsp32.cpp index 055eb6a0e..5845087c2 100644 --- a/src/ota/implementation/OTAEsp32.cpp +++ b/src/ota/implementation/OTAEsp32.cpp @@ -12,6 +12,11 @@ #if defined(ARDUINO_ARCH_ESP32) && OTA_ENABLED #include "OTAEsp32.h" #include +#if defined __has_include + #if __has_include() + #include + #endif +#endif #include ESP32OTACloudProcess::ESP32OTACloudProcess(MessageStream *ms, Client* client) From ffa84d1224958f37902d0dac091c55617d7873d6 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 3 Jun 2024 12:36:21 +0200 Subject: [PATCH 615/780] Watchdog: OTA, Remove mbed_watchdog_trigger_reset Hack to trigger board reset --- src/ota/implementation/OTANanoRP2040.cpp | 2 -- src/utility/watchdog/Watchdog.cpp | 15 --------------- src/utility/watchdog/Watchdog.h | 4 ---- 3 files changed, 21 deletions(-) diff --git a/src/ota/implementation/OTANanoRP2040.cpp b/src/ota/implementation/OTANanoRP2040.cpp index 5b1266f60..7dad7baf6 100644 --- a/src/ota/implementation/OTANanoRP2040.cpp +++ b/src/ota/implementation/OTANanoRP2040.cpp @@ -83,8 +83,6 @@ OTACloudProcessInterface::State NANO_RP2040OTACloudProcess::flashOTA() { } OTACloudProcessInterface::State NANO_RP2040OTACloudProcess::reboot() { - mbed_watchdog_trigger_reset(); - /* If watchdog is enabled we should not reach this point */ NVIC_SystemReset(); return Resume; // This won't ever be reached diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 942b569f1..19034026b 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -131,21 +131,6 @@ static void mbed_watchdog_enable_network_feed(NetworkAdapter ni) #endif } } - -void mbed_watchdog_trigger_reset() -{ - watchdog_config_t cfg; - cfg.timeout_ms = 1; - - if (hal_watchdog_init(&cfg) == WATCHDOG_STATUS_OK) { - is_watchdog_enabled = true; - while(1){} - } - else { - DEBUG_WARNING("%s: watchdog could not be reconfigured", __FUNCTION__); - } - -} #endif /* ARDUINO_ARCH_MBED */ #if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) diff --git a/src/utility/watchdog/Watchdog.h b/src/utility/watchdog/Watchdog.h index 3bfd35453..2ba43a875 100644 --- a/src/utility/watchdog/Watchdog.h +++ b/src/utility/watchdog/Watchdog.h @@ -34,8 +34,4 @@ void watchdog_reset(); void watchdog_enable_network_feed(NetworkAdapter ni); #endif /* (ARDUINO_ARCH_SAMD) || (ARDUINO_ARCH_MBED) */ -#ifdef ARDUINO_ARCH_MBED -void mbed_watchdog_trigger_reset(); -#endif /* ARDUINO_ARCH_MBED */ - #endif /* ARDUINO_AIOTC_UTILITY_WATCHDOG_H_ */ From 3dfe573cd34333e4d1848eec0df3e2ee2f53dc92 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 2 May 2024 17:12:10 +0200 Subject: [PATCH 616/780] TimeService: do no use NTP if we are using cellular connection --- src/utility/time/TimeService.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index 05290b211..5bf081de7 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -292,9 +292,11 @@ unsigned long TimeServiceClass::getRemoteTime() * This is the most reliable time source and it will * ensure a correct behaviour of the library. */ - unsigned long const ntp_time = NTPUtils::getTime(_con_hdl->getUDP()); - if(isTimeValid(ntp_time)) { - return ntp_time; + if(_con_hdl->getInterface() != NetworkAdapter::CELL) { + unsigned long const ntp_time = NTPUtils::getTime(_con_hdl->getUDP()); + if(isTimeValid(ntp_time)) { + return ntp_time; + } } /* As fallback if NTP request fails try to obtain the From 03b69d3f9f8bcbb84839dcde7bca796a9c33eb62 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 2 May 2024 17:11:52 +0200 Subject: [PATCH 617/780] Watchdog: use mbed API to enable and trigger watchdog --- src/utility/watchdog/Watchdog.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/utility/watchdog/Watchdog.cpp b/src/utility/watchdog/Watchdog.cpp index 19034026b..d47234064 100644 --- a/src/utility/watchdog/Watchdog.cpp +++ b/src/utility/watchdog/Watchdog.cpp @@ -33,7 +33,7 @@ #endif /* ARDUINO_ARCH_SAMD */ #ifdef ARDUINO_ARCH_MBED -# include +# include # define PORTENTA_H7_WATCHDOG_MAX_TIMEOUT_ms (32760) # define NANO_RP2040_WATCHDOG_MAX_TIMEOUT_ms (8389) # define EDGE_CONTROL_WATCHDOG_MAX_TIMEOUT_ms (65536) @@ -42,7 +42,7 @@ /****************************************************************************** * GLOBAL VARIABLES ******************************************************************************/ -#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_MBED) +#if defined(ARDUINO_ARCH_SAMD) static bool is_watchdog_enabled = false; #endif @@ -96,18 +96,15 @@ static void mbed_watchdog_enable() # error "You need to define the maximum possible timeout for this architecture." #endif - if (hal_watchdog_init(&cfg) == WATCHDOG_STATUS_OK) { - is_watchdog_enabled = true; - } - else { + if (!mbed::Watchdog::get_instance().start(cfg.timeout_ms)) { DEBUG_WARNING("%s: watchdog could not be enabled", __FUNCTION__); } } static void mbed_watchdog_reset() { - if (is_watchdog_enabled) { - hal_watchdog_kick(); + if (mbed::Watchdog::get_instance().is_running()) { + mbed::Watchdog::get_instance().kick(); } } From 7ebc044f5b9cdd65b3d107ca8942d13d7597644a Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 3 Jun 2024 18:14:04 +0200 Subject: [PATCH 618/780] ArduinoIoTCloudTCP: Add debug print on time sync failures --- src/ArduinoIoTCloudTCP.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 1c44f8611..f2a1b6fc1 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -273,6 +273,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() return State::ConnectMqttBroker; } + DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not get valid time. Retrying now.", __FUNCTION__); return State::ConnectPhy; } From 45b1120c5bffb2955e95adc181538a81c5af19f5 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 14:30:43 +0200 Subject: [PATCH 619/780] OTA: handle fwrite error --- src/ota/interface/OTAInterfaceDefault.cpp | 14 ++++++++++---- src/ota/interface/OTAInterfaceDefault.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/ota/interface/OTAInterfaceDefault.cpp b/src/ota/interface/OTAInterfaceDefault.cpp index d39ec0f2d..1b0a34fd4 100644 --- a/src/ota/interface/OTAInterfaceDefault.cpp +++ b/src/ota/interface/OTAInterfaceDefault.cpp @@ -35,10 +35,9 @@ OTACloudProcessInterface::State OTADefaultCloudProcessInterface::startOTA() { context = new Context( OTACloudProcessInterface::context->url, [this](uint8_t c) { - // int res = - this->writeFlash(&c, 1); - - // TODO report error in write flash, throw it? + if (this->writeFlash(&c, 1) != 1) { + this->context->writeError = true; + } } ); @@ -107,6 +106,12 @@ OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetch() { } parseOta(context->buffer, http_res); + + if(context->writeError) { + DEBUG_VERBOSE("OTA ERROR: File write error"); + res = ErrorWriteUpdateFileFail; + goto exit; + } } while((context->downloadState == OtaDownloadFile || context->downloadState == OtaDownloadHeader) && millis() - start < downloadTime); @@ -234,6 +239,7 @@ OTADefaultCloudProcessInterface::Context::Context( , headerCopiedBytes(0) , downloadedSize(0) , lastReportTime(0) + , writeError(false) , decoder(putc) { } static const uint32_t crc_table[256] = { diff --git a/src/ota/interface/OTAInterfaceDefault.h b/src/ota/interface/OTAInterfaceDefault.h index 8f7aaf18a..9e09d3cf2 100644 --- a/src/ota/interface/OTAInterfaceDefault.h +++ b/src/ota/interface/OTAInterfaceDefault.h @@ -74,6 +74,7 @@ class OTADefaultCloudProcessInterface: public OTACloudProcessInterface { uint32_t headerCopiedBytes; uint32_t downloadedSize; uint32_t lastReportTime; + bool writeError; // LZSS decoder LZSSDecoder decoder; From c300878841091d5e946c83339e4ee071b63fb85c Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 17:58:08 +0200 Subject: [PATCH 620/780] OTA: increase blocking download window to 2s --- src/ota/interface/OTAInterfaceDefault.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ota/interface/OTAInterfaceDefault.h b/src/ota/interface/OTAInterfaceDefault.h index 9e09d3cf2..95384817f 100644 --- a/src/ota/interface/OTAInterfaceDefault.h +++ b/src/ota/interface/OTAInterfaceDefault.h @@ -51,7 +51,7 @@ class OTADefaultCloudProcessInterface: public OTACloudProcessInterface { // The amount of time that each iteration of Fetch has to take at least // This mitigate the issues arising from tasks run in main loop that are using all the computing time - static constexpr uint32_t downloadTime = 100; + static constexpr uint32_t downloadTime = 2000; enum OTADownloadState: uint8_t { OtaDownloadHeader, From b8d5305f22a6f9aac5b92428f464156941a7ef51 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 15:36:02 +0200 Subject: [PATCH 621/780] OTA: make fetch blocking for real and also wait for data --- src/ota/interface/OTAInterfaceDefault.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ota/interface/OTAInterfaceDefault.cpp b/src/ota/interface/OTAInterfaceDefault.cpp index 1b0a34fd4..9e9891c85 100644 --- a/src/ota/interface/OTAInterfaceDefault.cpp +++ b/src/ota/interface/OTAInterfaceDefault.cpp @@ -94,7 +94,9 @@ OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetch() { do { if(http_client->available() == 0) { - goto exit; + /* Avoid tight loop and allow yield */ + delay(1); + continue; } http_res = http_client->read(context->buffer, context->buf_len); From e1280af412f650e350ec39407778145f15066ce0 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 31 May 2024 11:32:04 +0200 Subject: [PATCH 622/780] OTA: check for client connected during fetch --- src/ota/interface/OTAInterfaceDefault.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ota/interface/OTAInterfaceDefault.cpp b/src/ota/interface/OTAInterfaceDefault.cpp index 9e9891c85..fabb145a4 100644 --- a/src/ota/interface/OTAInterfaceDefault.cpp +++ b/src/ota/interface/OTAInterfaceDefault.cpp @@ -93,6 +93,11 @@ OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetch() { uint32_t start = millis(); do { + if(!http_client->connected()) { + res = OtaDownloadFail; + goto exit; + } + if(http_client->available() == 0) { /* Avoid tight loop and allow yield */ delay(1); From f9c4543ea7172100850fe79c99db4fa1a1a84645 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 10 Jun 2024 10:25:04 +0200 Subject: [PATCH 623/780] CI: add Arduino_Cellular dependency --- .github/workflows/compile-examples.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index a4e68ab0d..4e286b9f6 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -170,6 +170,7 @@ jobs: - name: arduino:mbed_portenta libraries: | - name: ArduinoECCX08 + - name: Arduino_Cellular sketch-paths: | - examples/ArduinoIoTCloud-DeferredOTA - examples/utility/Provisioning @@ -211,6 +212,8 @@ jobs: platforms: | # Install renesas_portenta platform via Boards Manager - name: arduino:renesas_portenta + libraries: | + - name: Arduino_Cellular sketch-paths: | - examples/utility/Provisioning # UNO R4 WiFi From a869130fd5926cf6c649e3431254c5caaf05bd92 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 09:43:22 +0200 Subject: [PATCH 624/780] OTA: STM32H7 remove watchdog kik --- src/ota/implementation/OTASTM32H7.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp index c3cefdd86..20b1d3773 100644 --- a/src/ota/implementation/OTASTM32H7.cpp +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -11,8 +11,6 @@ #include "AIoTC_Config.h" #if defined(BOARD_STM32H7) && OTA_ENABLED #include "OTASTM32H7.h" - -#include "utility/watchdog/Watchdog.h" #include static bool findProgramLength(DIR * dir, uint32_t & program_length); @@ -44,7 +42,6 @@ OTACloudProcessInterface::State STM32H7OTACloudProcess::resume(Message* msg) { void STM32H7OTACloudProcess::update() { OTADefaultCloudProcessInterface::update(); - watchdog_reset(); // FIXME this should npot be performed here } int STM32H7OTACloudProcess::writeFlash(uint8_t* const buffer, size_t len) { From e5eca055a80047a3cef60372e5c7d0a60fc0f873 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 09:50:11 +0200 Subject: [PATCH 625/780] OTA: STM32H7 remove unused variables --- src/ota/implementation/OTASTM32H7.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ota/implementation/OTASTM32H7.h b/src/ota/implementation/OTASTM32H7.h index ac1021715..d87bfe42f 100644 --- a/src/ota/implementation/OTASTM32H7.h +++ b/src/ota/implementation/OTASTM32H7.h @@ -79,9 +79,6 @@ class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { mbed::BlockDevice* _bd; mbed::FATFileSystem* _fs; - mbed::MBRBlockDevice* cert_bd_qspi; - mbed::FATFileSystem* cert_fs_qspi; - const portenta::StorageType storage=portenta::QSPI_FLASH_FATFS_MBR; const uint32_t data_offset=2; From 44b5dc30ad1c692252a7bf12726f063a8c0a90c1 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 09:51:25 +0200 Subject: [PATCH 626/780] OTA: STM32H7 remove commented code --- src/ota/implementation/OTASTM32H7.cpp | 2 -- src/ota/implementation/OTASTM32H7.h | 1 - 2 files changed, 3 deletions(-) diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp index 20b1d3773..b41df5056 100644 --- a/src/ota/implementation/OTASTM32H7.cpp +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -198,14 +198,12 @@ bool findProgramLength(DIR * dir, uint32_t & program_length) { return false; } -// extern uint32_t __stext = ~0; extern uint32_t __etext; extern uint32_t _sdata; extern uint32_t _edata; void* STM32H7OTACloudProcess::appStartAddress() { return (void*)0x8040000; - // return &__stext; } uint32_t STM32H7OTACloudProcess::appSize() { diff --git a/src/ota/implementation/OTASTM32H7.h b/src/ota/implementation/OTASTM32H7.h index d87bfe42f..13f5d33fe 100644 --- a/src/ota/implementation/OTASTM32H7.h +++ b/src/ota/implementation/OTASTM32H7.h @@ -72,7 +72,6 @@ class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { void storageClean(); FILE* decompressed; - // static const char UPDATE_FILE_NAME[]; mbed::BlockDevice* _bd_raw_qspi; uint32_t _program_length; From 5956436d9871bc508db105a825bdd2656975ab2a Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 09:57:29 +0200 Subject: [PATCH 627/780] OTA: STM32H7 storage type is always QSPI_FLASH_FATFS_MBR --- src/ota/implementation/OTASTM32H7.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp index b41df5056..cc3013184 100644 --- a/src/ota/implementation/OTASTM32H7.cpp +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -153,14 +153,9 @@ bool STM32H7OTACloudProcess::storageInit() { } } - if (storage == portenta::QSPI_FLASH_FATFS) { - _fs = new mbed::FATFileSystem("fs"); - err_mount = _fs->mount(_bd_raw_qspi); - } else if (storage == portenta::QSPI_FLASH_FATFS_MBR) { - _bd = new mbed::MBRBlockDevice(_bd_raw_qspi, data_offset); - _fs = new mbed::FATFileSystem("fs"); - err_mount = _fs->mount(_bd); - } + _bd = new mbed::MBRBlockDevice(_bd_raw_qspi, data_offset); + _fs = new mbed::FATFileSystem("fs"); + err_mount = _fs->mount(_bd); if (!err_mount) { return true; From 603acd5e6fbf37b827ecb2308cce90d543be7591 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 10:01:01 +0200 Subject: [PATCH 628/780] OTA: STM32H7 rename portenta namespace in STM32H747OTA --- src/ota/implementation/OTASTM32H7.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ota/implementation/OTASTM32H7.h b/src/ota/implementation/OTASTM32H7.h index 13f5d33fe..22e5cac09 100644 --- a/src/ota/implementation/OTASTM32H7.h +++ b/src/ota/implementation/OTASTM32H7.h @@ -28,7 +28,7 @@ #define APOTA_LITTLEFS_FLAG (1 << 6) #define APOTA_MBR_FLAG (1 << 7) -namespace portenta { +namespace STM32H747OTA { enum StorageType { QSPI_FLASH_FATFS = APOTA_QSPI_FLASH_FLAG | APOTA_FATFS_FLAG, QSPI_FLASH_FATFS_MBR = APOTA_QSPI_FLASH_FLAG | APOTA_FATFS_FLAG | APOTA_MBR_FLAG, @@ -78,7 +78,7 @@ class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { mbed::BlockDevice* _bd; mbed::FATFileSystem* _fs; - const portenta::StorageType storage=portenta::QSPI_FLASH_FATFS_MBR; + const STM32H747OTA::StorageType storage=STM32H747OTA::QSPI_FLASH_FATFS_MBR; const uint32_t data_offset=2; static const char UPDATE_FILE_NAME[]; From 4888d274bf4e654e5690c724d5659d4631bf3c8d Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 10:02:22 +0200 Subject: [PATCH 629/780] OTA: STM32H7 remove storage variable --- src/ota/implementation/OTASTM32H7.cpp | 2 +- src/ota/implementation/OTASTM32H7.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp index cc3013184..6b24edbf1 100644 --- a/src/ota/implementation/OTASTM32H7.cpp +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -84,7 +84,7 @@ OTACloudProcessInterface::State STM32H7OTACloudProcess::flashOTA() { // this sets the registries in RTC to load the firmware from the storage selected at the next reboot STM32H747::writeBackupRegister(RTCBackup::DR0, 0x07AA); - STM32H747::writeBackupRegister(RTCBackup::DR1, storage); + STM32H747::writeBackupRegister(RTCBackup::DR1, STM32H747OTA::StorageType::QSPI_FLASH_FATFS_MBR); STM32H747::writeBackupRegister(RTCBackup::DR2, data_offset); STM32H747::writeBackupRegister(RTCBackup::DR3, _program_length); diff --git a/src/ota/implementation/OTASTM32H7.h b/src/ota/implementation/OTASTM32H7.h index 22e5cac09..c31ba8040 100644 --- a/src/ota/implementation/OTASTM32H7.h +++ b/src/ota/implementation/OTASTM32H7.h @@ -78,7 +78,6 @@ class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { mbed::BlockDevice* _bd; mbed::FATFileSystem* _fs; - const STM32H747OTA::StorageType storage=STM32H747OTA::QSPI_FLASH_FATFS_MBR; const uint32_t data_offset=2; static const char UPDATE_FILE_NAME[]; From 9f1117a2263580b7e11df360fc1557d578a9a3ba Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 10:15:01 +0200 Subject: [PATCH 630/780] OTA: STM32H7 Add storage type constexpr --- src/ota/implementation/OTASTM32H7.cpp | 2 +- src/ota/implementation/OTASTM32H7.h | 15 ++------------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp index 6b24edbf1..dc3396eb6 100644 --- a/src/ota/implementation/OTASTM32H7.cpp +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -84,7 +84,7 @@ OTACloudProcessInterface::State STM32H7OTACloudProcess::flashOTA() { // this sets the registries in RTC to load the firmware from the storage selected at the next reboot STM32H747::writeBackupRegister(RTCBackup::DR0, 0x07AA); - STM32H747::writeBackupRegister(RTCBackup::DR1, STM32H747OTA::StorageType::QSPI_FLASH_FATFS_MBR); + STM32H747::writeBackupRegister(RTCBackup::DR1, STM32H747OTA::STORAGE_TYPE); STM32H747::writeBackupRegister(RTCBackup::DR2, data_offset); STM32H747::writeBackupRegister(RTCBackup::DR3, _program_length); diff --git a/src/ota/implementation/OTASTM32H7.h b/src/ota/implementation/OTASTM32H7.h index c31ba8040..506481f5c 100644 --- a/src/ota/implementation/OTASTM32H7.h +++ b/src/ota/implementation/OTASTM32H7.h @@ -21,20 +21,9 @@ #include "WiFi.h" /* WiFi from ArduinoCore-mbed */ #include -#define APOTA_QSPI_FLASH_FLAG (1 << 2) -#define APOTA_SDCARD_FLAG (1 << 3) -#define APOTA_RAW_FLAG (1 << 4) -#define APOTA_FATFS_FLAG (1 << 5) -#define APOTA_LITTLEFS_FLAG (1 << 6) -#define APOTA_MBR_FLAG (1 << 7) - namespace STM32H747OTA { - enum StorageType { - QSPI_FLASH_FATFS = APOTA_QSPI_FLASH_FLAG | APOTA_FATFS_FLAG, - QSPI_FLASH_FATFS_MBR = APOTA_QSPI_FLASH_FLAG | APOTA_FATFS_FLAG | APOTA_MBR_FLAG, - SD_FATFS = APOTA_SDCARD_FLAG | APOTA_FATFS_FLAG, - SD_FATFS_MBR = APOTA_SDCARD_FLAG | APOTA_FATFS_FLAG | APOTA_MBR_FLAG, - }; + /* External QSPI flash + MBR + FatFs */ + static const uint32_t constexpr STORAGE_TYPE = ((1 << 2) | (1 << 5) | (1 << 7)); } class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { From af07e716a385ba9a0ae406f759268e00250db70e Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 10:16:39 +0200 Subject: [PATCH 631/780] OTA: STM32H7 add partition constexpr --- src/ota/implementation/OTASTM32H7.cpp | 4 ++-- src/ota/implementation/OTASTM32H7.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp index dc3396eb6..3c3a0eb81 100644 --- a/src/ota/implementation/OTASTM32H7.cpp +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -85,7 +85,7 @@ OTACloudProcessInterface::State STM32H7OTACloudProcess::flashOTA() { // this sets the registries in RTC to load the firmware from the storage selected at the next reboot STM32H747::writeBackupRegister(RTCBackup::DR0, 0x07AA); STM32H747::writeBackupRegister(RTCBackup::DR1, STM32H747OTA::STORAGE_TYPE); - STM32H747::writeBackupRegister(RTCBackup::DR2, data_offset); + STM32H747::writeBackupRegister(RTCBackup::DR2, STM32H747OTA::PARTITION); STM32H747::writeBackupRegister(RTCBackup::DR3, _program_length); return Reboot; @@ -153,7 +153,7 @@ bool STM32H7OTACloudProcess::storageInit() { } } - _bd = new mbed::MBRBlockDevice(_bd_raw_qspi, data_offset); + _bd = new mbed::MBRBlockDevice(_bd_raw_qspi, STM32H747OTA::PARTITION); _fs = new mbed::FATFileSystem("fs"); err_mount = _fs->mount(_bd); diff --git a/src/ota/implementation/OTASTM32H7.h b/src/ota/implementation/OTASTM32H7.h index 506481f5c..adac10db1 100644 --- a/src/ota/implementation/OTASTM32H7.h +++ b/src/ota/implementation/OTASTM32H7.h @@ -24,6 +24,8 @@ namespace STM32H747OTA { /* External QSPI flash + MBR + FatFs */ static const uint32_t constexpr STORAGE_TYPE = ((1 << 2) | (1 << 5) | (1 << 7)); + /* Default OTA partition */ + static const uint32_t constexpr PARTITION = 2; } class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { @@ -67,7 +69,5 @@ class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { mbed::BlockDevice* _bd; mbed::FATFileSystem* _fs; - const uint32_t data_offset=2; - static const char UPDATE_FILE_NAME[]; }; From 66949808f04ac16c8fbcfc137d3cbebb0da70d69 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 10:18:19 +0200 Subject: [PATCH 632/780] OTA: STM32H7 add OTA magic number constexpr --- src/ota/implementation/OTASTM32H7.cpp | 2 +- src/ota/implementation/OTASTM32H7.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp index 3c3a0eb81..346561dec 100644 --- a/src/ota/implementation/OTASTM32H7.cpp +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -83,7 +83,7 @@ OTACloudProcessInterface::State STM32H7OTACloudProcess::flashOTA() { storageClean(); // this sets the registries in RTC to load the firmware from the storage selected at the next reboot - STM32H747::writeBackupRegister(RTCBackup::DR0, 0x07AA); + STM32H747::writeBackupRegister(RTCBackup::DR0, STM32H747OTA::MAGIC); STM32H747::writeBackupRegister(RTCBackup::DR1, STM32H747OTA::STORAGE_TYPE); STM32H747::writeBackupRegister(RTCBackup::DR2, STM32H747OTA::PARTITION); STM32H747::writeBackupRegister(RTCBackup::DR3, _program_length); diff --git a/src/ota/implementation/OTASTM32H7.h b/src/ota/implementation/OTASTM32H7.h index adac10db1..3c1946dcf 100644 --- a/src/ota/implementation/OTASTM32H7.h +++ b/src/ota/implementation/OTASTM32H7.h @@ -26,6 +26,8 @@ namespace STM32H747OTA { static const uint32_t constexpr STORAGE_TYPE = ((1 << 2) | (1 << 5) | (1 << 7)); /* Default OTA partition */ static const uint32_t constexpr PARTITION = 2; + /* OTA Magic number */ + static const uint32_t constexpr MAGIC = 0x07AA; } class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { From 7671c39677751c8d93a3f9b91bf44312a8b183e5 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 10:41:08 +0200 Subject: [PATCH 633/780] OTA: STM32H7 merge storageOpen and findProgramLength --- src/ota/implementation/OTASTM32H7.cpp | 30 +++++++++------------------ src/ota/implementation/OTASTM32H7.h | 3 +-- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp index 346561dec..e7e468886 100644 --- a/src/ota/implementation/OTASTM32H7.cpp +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -13,8 +13,6 @@ #include "OTASTM32H7.h" #include -static bool findProgramLength(DIR * dir, uint32_t & program_length); - const char STM32H7OTACloudProcess::UPDATE_FILE_NAME[] = "/fs/UPDATE.BIN"; STM32H7OTACloudProcess::STM32H7OTACloudProcess(MessageStream *ms, Client* client) @@ -76,7 +74,7 @@ OTACloudProcessInterface::State STM32H7OTACloudProcess::flashOTA() { decompressed = nullptr; /* Schedule the firmware update. */ - if(!storageOpen()) { + if(!findProgramLength(_program_length)) { return OtaStorageOpenFail; } @@ -164,33 +162,25 @@ bool STM32H7OTACloudProcess::storageInit() { return false; } -bool STM32H7OTACloudProcess::storageOpen() { +bool STM32H7OTACloudProcess::findProgramLength(uint32_t & program_length) { DIR * dir = NULL; - if ((dir = opendir("/fs")) != NULL) - { - if (findProgramLength(dir, _program_length)) - { - closedir(dir); - return true; - } - closedir(dir); - } + struct dirent * entry = NULL; + bool found = false; - return false; -} + if ((dir = opendir("/fs")) == NULL) { + return false; + } -bool findProgramLength(DIR * dir, uint32_t & program_length) { - struct dirent * entry = NULL; while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, "UPDATE.BIN") == 0) { // FIXME use constants struct stat stat_buf; stat("/fs/UPDATE.BIN", &stat_buf); program_length = stat_buf.st_size; - return true; + found = true; } } - - return false; + closedir(dir); + return found; } extern uint32_t __etext; diff --git a/src/ota/implementation/OTASTM32H7.h b/src/ota/implementation/OTASTM32H7.h index 3c1946dcf..a71c276ff 100644 --- a/src/ota/implementation/OTASTM32H7.h +++ b/src/ota/implementation/OTASTM32H7.h @@ -60,8 +60,7 @@ class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { bool appFlashClose() { return true; }; private: bool storageInit(); - bool storageOpen(); - + bool findProgramLength(uint32_t & program_length); void storageClean(); FILE* decompressed; From 340ab063892f7bd15eb8bbbeeb9c4ef6d049779d Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 29 May 2024 17:46:21 +0200 Subject: [PATCH 634/780] OTA: STM32H7 use constants for filename and path --- src/ota/implementation/OTASTM32H7.cpp | 20 ++++++++++---------- src/ota/implementation/OTASTM32H7.h | 6 +++++- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp index e7e468886..0f0e757e5 100644 --- a/src/ota/implementation/OTASTM32H7.cpp +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -13,15 +13,14 @@ #include "OTASTM32H7.h" #include -const char STM32H7OTACloudProcess::UPDATE_FILE_NAME[] = "/fs/UPDATE.BIN"; - STM32H7OTACloudProcess::STM32H7OTACloudProcess(MessageStream *ms, Client* client) : OTADefaultCloudProcessInterface(ms, client) , decompressed(nullptr) , _bd_raw_qspi(nullptr) , _program_length(0) , _bd(nullptr) -, _fs(nullptr) { +, _fs(nullptr) +, _filename("/" + String(STM32H747OTA::FOLDER) + "/" + String(STM32H747OTA::NAME)) { } @@ -60,9 +59,9 @@ OTACloudProcessInterface::State STM32H7OTACloudProcess::startOTA() { } // this could be useless, since we are writing over it - remove(UPDATE_FILE_NAME); + remove(_filename.c_str()); - decompressed = fopen(UPDATE_FILE_NAME, "wb"); + decompressed = fopen(_filename.c_str(), "wb"); // start the download if the setup for ota storage is successful return OTADefaultCloudProcessInterface::startOTA(); @@ -101,7 +100,7 @@ OTACloudProcessInterface::State STM32H7OTACloudProcess::reboot() { void STM32H7OTACloudProcess::reset() { OTADefaultCloudProcessInterface::reset(); - remove(UPDATE_FILE_NAME); + remove(_filename.c_str()); storageClean(); } @@ -152,7 +151,7 @@ bool STM32H7OTACloudProcess::storageInit() { } _bd = new mbed::MBRBlockDevice(_bd_raw_qspi, STM32H747OTA::PARTITION); - _fs = new mbed::FATFileSystem("fs"); + _fs = new mbed::FATFileSystem(STM32H747OTA::FOLDER); err_mount = _fs->mount(_bd); if (!err_mount) { @@ -165,16 +164,17 @@ bool STM32H7OTACloudProcess::storageInit() { bool STM32H7OTACloudProcess::findProgramLength(uint32_t & program_length) { DIR * dir = NULL; struct dirent * entry = NULL; + String dirName = "/" + String(STM32H747OTA::FOLDER); bool found = false; - if ((dir = opendir("/fs")) == NULL) { + if ((dir = opendir(dirName.c_str())) == NULL) { return false; } while ((entry = readdir(dir)) != NULL) { - if (strcmp(entry->d_name, "UPDATE.BIN") == 0) { // FIXME use constants + if (strcmp(entry->d_name, STM32H747OTA::NAME) == 0) { struct stat stat_buf; - stat("/fs/UPDATE.BIN", &stat_buf); + stat(_filename.c_str(), &stat_buf); program_length = stat_buf.st_size; found = true; } diff --git a/src/ota/implementation/OTASTM32H7.h b/src/ota/implementation/OTASTM32H7.h index a71c276ff..28b6308a1 100644 --- a/src/ota/implementation/OTASTM32H7.h +++ b/src/ota/implementation/OTASTM32H7.h @@ -28,6 +28,10 @@ namespace STM32H747OTA { static const uint32_t constexpr PARTITION = 2; /* OTA Magic number */ static const uint32_t constexpr MAGIC = 0x07AA; + /* OTA download folder name */ + static const char constexpr FOLDER[] = "ota"; + /* OTA update filename */ + static const char constexpr NAME[] = "UPDATE.BIN"; } class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { @@ -70,5 +74,5 @@ class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { mbed::BlockDevice* _bd; mbed::FATFileSystem* _fs; - static const char UPDATE_FILE_NAME[]; + String _filename; }; From 4edf9b4f70ade343ed908a595e8c1ba2b7bcaf0b Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 31 May 2024 11:33:59 +0200 Subject: [PATCH 635/780] OTA: STM32H7 remove _private_length private variable --- src/ota/implementation/OTASTM32H7.cpp | 7 ++++--- src/ota/implementation/OTASTM32H7.h | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp index 0f0e757e5..cf9bb7018 100644 --- a/src/ota/implementation/OTASTM32H7.cpp +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -17,7 +17,6 @@ STM32H7OTACloudProcess::STM32H7OTACloudProcess(MessageStream *ms, Client* client : OTADefaultCloudProcessInterface(ms, client) , decompressed(nullptr) , _bd_raw_qspi(nullptr) -, _program_length(0) , _bd(nullptr) , _fs(nullptr) , _filename("/" + String(STM32H747OTA::FOLDER) + "/" + String(STM32H747OTA::NAME)) { @@ -72,8 +71,10 @@ OTACloudProcessInterface::State STM32H7OTACloudProcess::flashOTA() { fclose(decompressed); decompressed = nullptr; + uint32_t updateLength = 0; + /* Schedule the firmware update. */ - if(!findProgramLength(_program_length)) { + if(!findProgramLength(updateLength)) { return OtaStorageOpenFail; } @@ -83,7 +84,7 @@ OTACloudProcessInterface::State STM32H7OTACloudProcess::flashOTA() { STM32H747::writeBackupRegister(RTCBackup::DR0, STM32H747OTA::MAGIC); STM32H747::writeBackupRegister(RTCBackup::DR1, STM32H747OTA::STORAGE_TYPE); STM32H747::writeBackupRegister(RTCBackup::DR2, STM32H747OTA::PARTITION); - STM32H747::writeBackupRegister(RTCBackup::DR3, _program_length); + STM32H747::writeBackupRegister(RTCBackup::DR3, updateLength); return Reboot; } diff --git a/src/ota/implementation/OTASTM32H7.h b/src/ota/implementation/OTASTM32H7.h index 28b6308a1..0b56f20fe 100644 --- a/src/ota/implementation/OTASTM32H7.h +++ b/src/ota/implementation/OTASTM32H7.h @@ -69,7 +69,6 @@ class STM32H7OTACloudProcess: public OTADefaultCloudProcessInterface { FILE* decompressed; mbed::BlockDevice* _bd_raw_qspi; - uint32_t _program_length; mbed::BlockDevice* _bd; mbed::FATFileSystem* _fs; From 81437415a3e65b2c81ef6d2a91c74accb26e647b Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 10 Jun 2024 10:02:41 +0200 Subject: [PATCH 636/780] OTA: STM32H7 add check on fopen failures Co-authored-by: Andrea Gilardoni <4046444+andreagilardoni@users.noreply.github.com> --- src/ota/implementation/OTASTM32H7.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ota/implementation/OTASTM32H7.cpp b/src/ota/implementation/OTASTM32H7.cpp index cf9bb7018..d9675aa21 100644 --- a/src/ota/implementation/OTASTM32H7.cpp +++ b/src/ota/implementation/OTASTM32H7.cpp @@ -62,6 +62,9 @@ OTACloudProcessInterface::State STM32H7OTACloudProcess::startOTA() { decompressed = fopen(_filename.c_str(), "wb"); + if(decompressed == nullptr) { + return ErrorOpenUpdateFileFail; + } // start the download if the setup for ota storage is successful return OTADefaultCloudProcessInterface::startOTA(); } From 337bc0bd84aa9df5ea00b0631229f8dd39997dd1 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 10 Jun 2024 14:16:36 +0200 Subject: [PATCH 637/780] Release v2.0.2 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index c044ef343..1d298252b 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=2.0.1 +version=2.0.2 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 592b19f3c..24effc7a6 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -158,6 +158,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "2.0.1" +#define AIOT_CONFIG_LIB_VERSION "2.0.2" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 323e5675e12b646c74103dde2dae3fd2a6929ea3 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 18 Jun 2024 15:10:15 +0200 Subject: [PATCH 638/780] TimedAttempt: fix reload function not applying tick retry limit --- src/utility/time/TimedAttempt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utility/time/TimedAttempt.cpp b/src/utility/time/TimedAttempt.cpp index 01da506d7..4ff027fd6 100644 --- a/src/utility/time/TimedAttempt.cpp +++ b/src/utility/time/TimedAttempt.cpp @@ -54,8 +54,8 @@ unsigned long TimedAttempt::retry() { unsigned long TimedAttempt::reload() { unsigned long retryDelay = (1 << _retryCount) * _minDelay; _retryDelay = min(retryDelay, _maxDelay); - _nextRetryTick = millis() + retryDelay; - return retryDelay; + _nextRetryTick = millis() + _retryDelay; + return _retryDelay; } void TimedAttempt::reset() { From 8b6ff40997530f6ac490704d7bca6c6dc7eda1df Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 19 Jun 2024 09:28:12 +0200 Subject: [PATCH 639/780] Release v2.0.3 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index 1d298252b..c478c9ecf 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=2.0.2 +version=2.0.3 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 24effc7a6..a34793180 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -158,6 +158,6 @@ #define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) #define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) -#define AIOT_CONFIG_LIB_VERSION "2.0.2" +#define AIOT_CONFIG_LIB_VERSION "2.0.3" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From be59d2410f4c6cc022a2c888e9a978d1d81aa4f5 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 25 Jun 2024 15:52:57 +0200 Subject: [PATCH 640/780] OTA: UNO R4 WiFi fix magic number --- src/ota/OTA.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ota/OTA.h b/src/ota/OTA.h index c1a56194a..019fc889d 100644 --- a/src/ota/OTA.h +++ b/src/ota/OTA.h @@ -50,8 +50,7 @@ using ArduinoCloudOTA = ESP32OTACloudProcess; #include "implementation/OTAUnoR4.h" using ArduinoCloudOTA = UNOR4OTACloudProcess; -// TODO Check if a macro already exist -constexpr uint32_t OtaMagicNumber = 0x234110020; // TODO check this value is correct +constexpr uint32_t OtaMagicNumber = 0x23411002; #else #error "This Board doesn't support OTA" From 605e16bd7f17f028383905b62f02727da7804986 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 25 Jun 2024 15:54:36 +0200 Subject: [PATCH 641/780] UNO R4 WiFi suppress unused variable warning --- src/tls/utility/TLSClientMqtt.cpp | 1 + src/tls/utility/TLSClientOta.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/tls/utility/TLSClientMqtt.cpp b/src/tls/utility/TLSClientMqtt.cpp index 8c6c3f529..374618163 100644 --- a/src/tls/utility/TLSClientMqtt.cpp +++ b/src/tls/utility/TLSClientMqtt.cpp @@ -58,6 +58,7 @@ void TLSClientMqtt::begin(ConnectionHandler & connection) { * also present in older firmware revisions * https://github.com/arduino/uno-r4-wifi-usb-bridge/blob/f09ca94fdcab845b8368d4435fdac9f6999d21d2/certificates/certificates.pem#L852 */ + (void)connection; #elif defined(ARDUINO_ARCH_ESP32) setCACertBundle(x509_crt_bundle); #elif defined(ARDUINO_ARCH_ESP8266) diff --git a/src/tls/utility/TLSClientOta.cpp b/src/tls/utility/TLSClientOta.cpp index 8aabf652e..77096b6f2 100644 --- a/src/tls/utility/TLSClientOta.cpp +++ b/src/tls/utility/TLSClientOta.cpp @@ -54,6 +54,7 @@ void TLSClientOta::begin(ConnectionHandler &connection) { /* AWS Root CAs are configured in uno-r4-wifi-usb-bridge/libraries/Arduino_ESP32_OTA * https://github.com/arduino-libraries/Arduino_ESP32_OTA/blob/fc755e7d1d3946232107e2590662ee08d6ccdec4/src/tls/amazon_root_ca.h */ + (void)connection; #elif defined(ARDUINO_ARCH_ESP32) setCACertBundle(x509_crt_bundle); #elif defined(ARDUINO_ARCH_ESP8266) From 2aa4a280d80a4441de6addfc6cde964242279e15 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Jul 2024 16:44:53 +0200 Subject: [PATCH 642/780] LPWAN: rename AIOT_CONFIG_INTERVAL_RETRY_DELAY_ms to AIOT_CONFIG_LPWAN_UPDATE_RETRY_DELAY_ms --- src/AIoTC_Config.h | 5 ++++- src/ArduinoIoTCloudLPWAN.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index a34793180..aa28c2d16 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -142,7 +142,10 @@ * CONSTANTS ******************************************************************************/ -#define AIOT_CONFIG_INTERVAL_RETRY_DELAY_ms (10000UL) +#if defined(HAS_LORA) + #define AIOT_CONFIG_LPWAN_UPDATE_RETRY_DELAY_ms (10000UL) +#endif + #define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) #define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) #define AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (2000UL) diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 0f213e0a5..3c6a74daf 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -50,7 +50,7 @@ ArduinoIoTCloudLPWAN::ArduinoIoTCloudLPWAN() : _state{State::ConnectPhy} , _retryEnable{false} , _maxNumRetry{5} -, _intervalRetry{AIOT_CONFIG_INTERVAL_RETRY_DELAY_ms} +, _intervalRetry{AIOT_CONFIG_LPWAN_UPDATE_RETRY_DELAY_ms} , _thing_property_container() , _last_checked_property_index{0} { From 1cdc310c08f3dad5180b183af754eaba31ad7947 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Jul 2024 16:46:09 +0200 Subject: [PATCH 643/780] Config: remove RP2040 OTA defines --- src/AIoTC_Config.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index aa28c2d16..a0d11ff53 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -158,9 +158,6 @@ #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) -#define AIOT_CONFIG_RP2040_OTA_HTTP_HEADER_RECEIVE_TIMEOUT_ms (10*1000UL) -#define AIOT_CONFIG_RP2040_OTA_HTTP_DATA_RECEIVE_TIMEOUT_ms (4*60*1000UL) - #define AIOT_CONFIG_LIB_VERSION "2.0.3" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 6e646c5975de6f9ad0c061a22b5eacc7eeff2d5a Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Jul 2024 16:48:06 +0200 Subject: [PATCH 644/780] Config: remove THING_TOPICS unused defines --- src/AIoTC_Config.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index a0d11ff53..4329fefbc 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -153,8 +153,6 @@ #define AIOT_CONFIG_DEVICE_TOPIC_MAX_RETRY_CNT (10UL) #define AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (20000UL) #define AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (1280000UL) -#define AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_RETRY_DELAY_ms (1000UL) -#define AIOT_CONFIG_THING_TOPICS_SUBSCRIBE_MAX_RETRY_CNT (10UL) #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) From 91860fcdc616adb4818093a7d5b1a15f5d2a07af Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Jul 2024 17:22:30 +0200 Subject: [PATCH 645/780] Config: rename AIOT_CONFIG_DEVICE_TOPIC_ to AIOT_CONFIG_THING_ID_REQUEST_ --- src/AIoTC_Config.h | 8 +++++--- src/ArduinoIoTCloudDevice.cpp | 10 +++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 4329fefbc..32d837373 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -148,9 +148,11 @@ #define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) #define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) -#define AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (2000UL) -#define AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms (32000UL) -#define AIOT_CONFIG_DEVICE_TOPIC_MAX_RETRY_CNT (10UL) + +#define AIOT_CONFIG_THING_ID_REQUEST_RETRY_DELAY_ms (2000UL) +#define AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms (32000UL) +#define AIOT_CONFIG_THING_ID_REQUEST_MAX_RETRY_CNT (10UL) + #define AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (20000UL) #define AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (1280000UL) #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) diff --git a/src/ArduinoIoTCloudDevice.cpp b/src/ArduinoIoTCloudDevice.cpp index 53fcb74d5..5645a067a 100644 --- a/src/ArduinoIoTCloudDevice.cpp +++ b/src/ArduinoIoTCloudDevice.cpp @@ -33,8 +33,8 @@ _registered(false) { } void ArduinoCloudDevice::begin() { - _attachAttempt.begin(AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms, - AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms); + _attachAttempt.begin(AIOT_CONFIG_THING_ID_REQUEST_RETRY_DELAY_ms, + AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms); } void ArduinoCloudDevice::update() { @@ -93,8 +93,8 @@ void ArduinoCloudDevice::handleMessage(Message *m) { ArduinoCloudDevice::State ArduinoCloudDevice::handleInit() { /* Reset attempt struct for the nex retry after disconnection */ - _attachAttempt.begin(AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms, - AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms); + _attachAttempt.begin(AIOT_CONFIG_THING_ID_REQUEST_RETRY_DELAY_ms, + AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms); _attached = false; _registered = false; @@ -120,7 +120,7 @@ ArduinoCloudDevice::State ArduinoCloudDevice::handleSendCapabilities() { ArduinoCloudDevice::State ArduinoCloudDevice::handleConnected() { /* Max retry than disconnect */ - if (_attachAttempt.getRetryCount() > AIOT_CONFIG_DEVICE_TOPIC_MAX_RETRY_CNT) { + if (_attachAttempt.getRetryCount() > AIOT_CONFIG_THING_ID_REQUEST_MAX_RETRY_CNT) { return State::Disconnected; } From fa89e5b268ac9ed36932ff59236bef8906bed4e0 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Jul 2024 17:23:18 +0200 Subject: [PATCH 646/780] ArduinoIoTCloudTCP: remove wrong connection_attempt reconfiguration --- src/ArduinoIoTCloudTCP.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index f2a1b6fc1..dcab5ae7d 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -284,9 +284,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() /* Subscribe to message topic to receive commands */ _mqttClient.subscribe(_messageTopicIn); - /* Reconfigure timers for next state */ - _connection_attempt.begin(AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms, AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms); - DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s connected to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); return State::Connected; } From 79c3c03ee1f2e7bd3d89b33b3dacb44cd6a66013 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Jul 2024 17:56:11 +0200 Subject: [PATCH 647/780] Config: usa a multiplier to handle thing id request retries for detached by user devices --- src/AIoTC_Config.h | 5 +++-- src/ArduinoIoTCloudDevice.cpp | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 32d837373..8653047e7 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -153,8 +153,9 @@ #define AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms (32000UL) #define AIOT_CONFIG_THING_ID_REQUEST_MAX_RETRY_CNT (10UL) -#define AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (20000UL) -#define AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms (1280000UL) +#define AIOT_CONFIG_DEVICE_REGISTERED_RETRY_DELAY_k (10UL) +#define AIOT_CONFIG_MAX_DEVICE_REGISTERED_RETRY_DELAY_k (4UL) + #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) diff --git a/src/ArduinoIoTCloudDevice.cpp b/src/ArduinoIoTCloudDevice.cpp index 5645a067a..3e67fda10 100644 --- a/src/ArduinoIoTCloudDevice.cpp +++ b/src/ArduinoIoTCloudDevice.cpp @@ -130,8 +130,10 @@ ArduinoCloudDevice::State ArduinoCloudDevice::handleConnected() { * counter, but recompute delay. * Wait: 4s -> 80s -> 160s -> 320s -> 640s -> 1280s -> 1280s ... */ - _attachAttempt.reconfigure(AIOT_CONFIG_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms, - AIOT_CONFIG_MAX_DEVICE_TOPIC_ATTACH_RETRY_DELAY_ms); + _attachAttempt.reconfigure(AIOT_CONFIG_THING_ID_REQUEST_RETRY_DELAY_ms * + AIOT_CONFIG_DEVICE_REGISTERED_RETRY_DELAY_k, + AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms * + AIOT_CONFIG_MAX_DEVICE_REGISTERED_RETRY_DELAY_k); } return State::SendCapabilities; } From 1e9d38c17897904b9108c3b06bc9ddaa367c2b34 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 17 Jul 2024 15:25:25 +0200 Subject: [PATCH 648/780] If available force network time sync when connecting or reconnecting --- src/ArduinoIoTCloudTCP.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index f2a1b6fc1..8c74a32aa 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -267,7 +267,8 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() { - if (TimeServiceClass::isTimeValid(getTime())) + /* If available force network time sync when connecting or reconnecting */ + if (_time_service.sync()) { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d", __FUNCTION__, getTime()); return State::ConnectMqttBroker; From 8e347b35493cc51a82cc134e7a6a458656248a45 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Jul 2024 17:58:13 +0200 Subject: [PATCH 649/780] Config: wrap TCP constants inside HAS_TCP --- src/AIoTC_Config.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 8653047e7..d7a1bf8f0 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -146,18 +146,20 @@ #define AIOT_CONFIG_LPWAN_UPDATE_RETRY_DELAY_ms (10000UL) #endif -#define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) -#define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) +#if defined(HAS_TCP) + #define AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms (1000UL) + #define AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms (32000UL) -#define AIOT_CONFIG_THING_ID_REQUEST_RETRY_DELAY_ms (2000UL) -#define AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms (32000UL) -#define AIOT_CONFIG_THING_ID_REQUEST_MAX_RETRY_CNT (10UL) + #define AIOT_CONFIG_THING_ID_REQUEST_RETRY_DELAY_ms (2000UL) + #define AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms (32000UL) + #define AIOT_CONFIG_THING_ID_REQUEST_MAX_RETRY_CNT (10UL) -#define AIOT_CONFIG_DEVICE_REGISTERED_RETRY_DELAY_k (10UL) -#define AIOT_CONFIG_MAX_DEVICE_REGISTERED_RETRY_DELAY_k (4UL) + #define AIOT_CONFIG_DEVICE_REGISTERED_RETRY_DELAY_k (10UL) + #define AIOT_CONFIG_MAX_DEVICE_REGISTERED_RETRY_DELAY_k (4UL) -#define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) -#define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) + #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) + #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) +#endif #define AIOT_CONFIG_LIB_VERSION "2.0.3" From 12beae5c622c81847cbdc26a9c464ed65a5251fa Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 18 Jul 2024 10:45:28 +0200 Subject: [PATCH 650/780] CloudDevice: unify update and handleMessage --- src/ArduinoIoTCloudDevice.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/ArduinoIoTCloudDevice.cpp b/src/ArduinoIoTCloudDevice.cpp index 53fcb74d5..43d3a3611 100644 --- a/src/ArduinoIoTCloudDevice.cpp +++ b/src/ArduinoIoTCloudDevice.cpp @@ -38,6 +38,19 @@ void ArduinoCloudDevice::begin() { } void ArduinoCloudDevice::update() { + handleMessage(nullptr); +} + +int ArduinoCloudDevice::connected() { + return _state != State::Disconnected ? 1 : 0; +} + +void ArduinoCloudDevice::handleMessage(Message *m) { + _command = UnknownCmdId; + if (m != nullptr) { + _command = m->id; + } + /* Run through the state machine. */ State nextState = _state; switch (_state) { @@ -80,17 +93,6 @@ void ArduinoCloudDevice::update() { _state = nextState; } -int ArduinoCloudDevice::connected() { - return _state != State::Disconnected ? 1 : 0; -} - -void ArduinoCloudDevice::handleMessage(Message *m) { - _command = UnknownCmdId; - if (m != nullptr) { - _command = m->id; - } -} - ArduinoCloudDevice::State ArduinoCloudDevice::handleInit() { /* Reset attempt struct for the nex retry after disconnection */ _attachAttempt.begin(AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms, From 8196fbc634f4fd2bca0c0c92d312be3c010639fa Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 18 Jul 2024 10:45:55 +0200 Subject: [PATCH 651/780] CloudThing: unify update and handleMessage --- src/ArduinoIoTCloudThing.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/ArduinoIoTCloudThing.cpp b/src/ArduinoIoTCloudThing.cpp index 9b3656b0f..98ebb0fb3 100644 --- a/src/ArduinoIoTCloudThing.cpp +++ b/src/ArduinoIoTCloudThing.cpp @@ -59,6 +59,23 @@ void ArduinoCloudThing::begin() { } void ArduinoCloudThing::update() { + handleMessage(nullptr); +} + +int ArduinoCloudThing::connected() { + return _state > State::Disconnect ? 1 : 0; +} + +void ArduinoCloudThing::handleMessage(Message* m) { + _command = UnknownCmdId; + if (m != nullptr) { + _command = m->id; + if (_command == TimezoneCommandDownId) { + _utcOffset = reinterpret_cast(m)->params.offset; + _utcOffsetExpireTime = reinterpret_cast(m)->params.until; + } + } + /* Run through the state machine. */ State nextState = _state; switch (_state) { @@ -95,21 +112,6 @@ void ArduinoCloudThing::update() { _state = nextState; } -int ArduinoCloudThing::connected() { - return _state > State::Disconnect ? 1 : 0; -} - -void ArduinoCloudThing::handleMessage(Message* m) { - _command = UnknownCmdId; - if (m != nullptr) { - _command = m->id; - if (_command == TimezoneCommandDownId) { - _utcOffset = reinterpret_cast(m)->params.offset; - _utcOffsetExpireTime = reinterpret_cast(m)->params.until; - } - } -} - ArduinoCloudThing::State ArduinoCloudThing::handleInit() { _syncAttempt.begin(AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms); return State::RequestLastValues; From dbc42420fede7363caa74e5870bf696a133da1ac Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 16 Jul 2024 15:34:26 +0200 Subject: [PATCH 652/780] moving mqtt poll into ArduinoIoTCloudTCP::handle_Connected --- src/ArduinoIoTCloudTCP.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index f2a1b6fc1..fe5a5b01d 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -232,10 +232,6 @@ void ArduinoIoTCloudTCP::update() #if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) watchdog_reset(); #endif - - /* Check for new data from the MQTT client. */ - if (_mqttClient.connected()) - _mqttClient.poll(); } int ArduinoIoTCloudTCP::connected() @@ -307,6 +303,9 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() return State::Disconnect; } + /* Check for new data from the MQTT client. */ + _mqttClient.poll(); + /* Retransmit data in case there was a lost transaction due * to phy layer or MQTT connectivity loss. */ From ee008cbae9f00ad0097730b4fb4ccbbe08cda4cf Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 22 Jul 2024 17:23:13 +0200 Subject: [PATCH 653/780] OTA: fix sign-compare compiler warnings --- src/ota/interface/OTAInterfaceDefault.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ota/interface/OTAInterfaceDefault.cpp b/src/ota/interface/OTAInterfaceDefault.cpp index fabb145a4..4f68d774c 100644 --- a/src/ota/interface/OTAInterfaceDefault.cpp +++ b/src/ota/interface/OTAInterfaceDefault.cpp @@ -182,7 +182,8 @@ void OTADefaultCloudProcessInterface::parseOta(uint8_t* buffer, size_t buf_len) break; } - case OtaDownloadFile: + case OtaDownloadFile: { + uint32_t contentLength = http_client->contentLength(); context->decoder.decompress(cursor, buf_len - (cursor-buffer)); // TODO verify return value context->calculatedCrc32 = crc_update( @@ -195,22 +196,23 @@ void OTADefaultCloudProcessInterface::parseOta(uint8_t* buffer, size_t buf_len) context->downloadedSize += (cursor-buffer); if((millis() - context->lastReportTime) > 10000) { // Report the download progress each X millisecond - DEBUG_VERBOSE("OTA Download Progress %d/%d", context->downloadedSize, http_client->contentLength()); + DEBUG_VERBOSE("OTA Download Progress %d/%d", context->downloadedSize, contentLength); reportStatus(context->downloadedSize); context->lastReportTime = millis(); } // TODO there should be no more bytes available when the download is completed - if(context->downloadedSize == http_client->contentLength()) { + if(context->downloadedSize == contentLength) { context->downloadState = OtaDownloadCompleted; } - if(context->downloadedSize > http_client->contentLength()) { + if(context->downloadedSize > contentLength) { context->downloadState = OtaDownloadError; } // TODO fail if we exceed a timeout? and available is 0 (client is broken) break; + } case OtaDownloadCompleted: return; default: From 6ef7ad86afee69987af8ef57fbad5c1e2224edde Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 23 Jul 2024 12:11:55 +0200 Subject: [PATCH 654/780] Release v2.0.4 --- library.properties | 2 +- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index c478c9ecf..267c5b403 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=2.0.3 +version=2.0.4 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index d7a1bf8f0..14137ae1e 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -161,6 +161,6 @@ #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) #endif -#define AIOT_CONFIG_LIB_VERSION "2.0.3" +#define AIOT_CONFIG_LIB_VERSION "2.0.4" #endif /* ARDUINO_AIOTC_CONFIG_H_ */ From 87b0ff5a36ae291b7392b5d6c7e1169e84ce17cb Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 8 Aug 2024 08:40:36 +0200 Subject: [PATCH 655/780] ESP32: fix certificate bundle loading using core >= 3.0.4 --- src/tls/utility/TLSClientMqtt.cpp | 6 +++++- src/tls/utility/TLSClientOta.cpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/tls/utility/TLSClientMqtt.cpp b/src/tls/utility/TLSClientMqtt.cpp index 374618163..831f31cf5 100644 --- a/src/tls/utility/TLSClientMqtt.cpp +++ b/src/tls/utility/TLSClientMqtt.cpp @@ -60,7 +60,11 @@ void TLSClientMqtt::begin(ConnectionHandler & connection) { */ (void)connection; #elif defined(ARDUINO_ARCH_ESP32) - setCACertBundle(x509_crt_bundle); + #if (ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 4)) + setCACertBundle(x509_crt_bundle); + #else + setCACertBundle(x509_crt_bundle, sizeof(x509_crt_bundle)); + #endif #elif defined(ARDUINO_ARCH_ESP8266) setInsecure(); #endif diff --git a/src/tls/utility/TLSClientOta.cpp b/src/tls/utility/TLSClientOta.cpp index 77096b6f2..f03af7696 100644 --- a/src/tls/utility/TLSClientOta.cpp +++ b/src/tls/utility/TLSClientOta.cpp @@ -56,7 +56,11 @@ void TLSClientOta::begin(ConnectionHandler &connection) { */ (void)connection; #elif defined(ARDUINO_ARCH_ESP32) - setCACertBundle(x509_crt_bundle); + #if (ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 4)) + setCACertBundle(x509_crt_bundle); + #else + setCACertBundle(x509_crt_bundle, sizeof(x509_crt_bundle)); + #endif #elif defined(ARDUINO_ARCH_ESP8266) setInsecure(); #endif From e57ab50f841ade1dd9af7b7c3271c84d3e345c4a Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 14 Aug 2024 11:07:32 +0200 Subject: [PATCH 656/780] examples: add CellularConnectionHandler --- examples/ArduinoIoTCloud-Advanced/arduino_secrets.h | 4 +++- examples/ArduinoIoTCloud-Advanced/thingProperties.h | 2 ++ examples/ArduinoIoTCloud-Basic/arduino_secrets.h | 4 +++- examples/ArduinoIoTCloud-Basic/thingProperties.h | 2 ++ examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h | 4 +++- examples/ArduinoIoTCloud-Callbacks/thingProperties.h | 2 ++ examples/ArduinoIoTCloud-Schedule/arduino_secrets.h | 4 +++- examples/ArduinoIoTCloud-Schedule/thingProperties.h | 2 ++ examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h | 4 +++- examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h | 2 ++ 10 files changed, 25 insertions(+), 5 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h index 44a9e21d2..0be56888a 100644 --- a/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Advanced/arduino_secrets.h @@ -14,7 +14,9 @@ #endif /* MKR GSM 1400 */ /* MKR NB 1500 */ /* Portenta CAT.M1/NB IoT GNSS Shield */ -#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_CATM1_NBIOT) +/* Portenta H7 and C33 + Portenta Mid Carrier + 4G Module */ +#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || \ + defined(BOARD_HAS_CATM1_NBIOT) || defined(BOARD_HAS_CELLULAR) #define SECRET_PIN "" #define SECRET_APN "" #define SECRET_LOGIN "" diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index 43187104d..21639c458 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -49,4 +49,6 @@ void initProperties() { //EthernetConnectionHandler ArduinoIoTPreferredConnection; /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_OPTIONAL_IP, SECRET_OPTIONAL_DNS, SECRET_OPTIONAL_GATEWAY, SECRET_OPTIONAL_NETMASK); +#elif defined(BOARD_HAS_CELLULAR) + CellularConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #endif diff --git a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h index 44a9e21d2..0be56888a 100644 --- a/examples/ArduinoIoTCloud-Basic/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Basic/arduino_secrets.h @@ -14,7 +14,9 @@ #endif /* MKR GSM 1400 */ /* MKR NB 1500 */ /* Portenta CAT.M1/NB IoT GNSS Shield */ -#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_CATM1_NBIOT) +/* Portenta H7 and C33 + Portenta Mid Carrier + 4G Module */ +#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || \ + defined(BOARD_HAS_CATM1_NBIOT) || defined(BOARD_HAS_CELLULAR) #define SECRET_PIN "" #define SECRET_APN "" #define SECRET_LOGIN "" diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index 4193b440b..16f75829b 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -48,4 +48,6 @@ void initProperties() { NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #elif defined(BOARD_HAS_CATM1_NBIOT) CatM1ConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); +#elif defined(BOARD_HAS_CELLULAR) + CellularConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #endif diff --git a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h index 44a9e21d2..0be56888a 100644 --- a/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Callbacks/arduino_secrets.h @@ -14,7 +14,9 @@ #endif /* MKR GSM 1400 */ /* MKR NB 1500 */ /* Portenta CAT.M1/NB IoT GNSS Shield */ -#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_CATM1_NBIOT) +/* Portenta H7 and C33 + Portenta Mid Carrier + 4G Module */ +#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || \ + defined(BOARD_HAS_CATM1_NBIOT) || defined(BOARD_HAS_CELLULAR) #define SECRET_PIN "" #define SECRET_APN "" #define SECRET_LOGIN "" diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index 8f2b5055e..89a365ce6 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -33,4 +33,6 @@ void initProperties() { //EthernetConnectionHandler ArduinoIoTPreferredConnection; /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_OPTIONAL_IP, SECRET_OPTIONAL_DNS, SECRET_OPTIONAL_GATEWAY, SECRET_OPTIONAL_NETMASK); +#elif defined(BOARD_HAS_CELLULAR) + CellularConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #endif diff --git a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h index 44a9e21d2..0be56888a 100644 --- a/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-Schedule/arduino_secrets.h @@ -14,7 +14,9 @@ #endif /* MKR GSM 1400 */ /* MKR NB 1500 */ /* Portenta CAT.M1/NB IoT GNSS Shield */ -#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_CATM1_NBIOT) +/* Portenta H7 and C33 + Portenta Mid Carrier + 4G Module */ +#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || \ + defined(BOARD_HAS_CATM1_NBIOT) || defined(BOARD_HAS_CELLULAR) #define SECRET_PIN "" #define SECRET_APN "" #define SECRET_LOGIN "" diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 8d2d7dfc6..0af38fe3c 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -56,4 +56,6 @@ void initProperties() { //EthernetConnectionHandler ArduinoIoTPreferredConnection; /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_OPTIONAL_IP, SECRET_OPTIONAL_DNS, SECRET_OPTIONAL_GATEWAY, SECRET_OPTIONAL_NETMASK); +#elif defined(BOARD_HAS_CELLULAR) + CellularConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #endif diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h index 2ae0cefa6..a3fd8a7e8 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/arduino_secrets.h @@ -14,7 +14,9 @@ #endif /* MKR GSM 1400 */ /* MKR NB 1500 */ /* Portenta CAT.M1/NB IoT GNSS Shield */ -#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_CATM1_NBIOT) +/* Portenta H7 and C33 + Portenta Mid Carrier + 4G Module */ +#if defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || \ + defined(BOARD_HAS_CATM1_NBIOT) || defined(BOARD_HAS_CELLULAR) #define SECRET_PIN "" #define SECRET_APN "" #define SECRET_LOGIN "" diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index 36604ebf7..8ecd70770 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -69,6 +69,8 @@ String str_property_8; //EthernetConnectionHandler ArduinoIoTPreferredConnection; /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_OPTIONAL_IP, SECRET_OPTIONAL_DNS, SECRET_OPTIONAL_GATEWAY, SECRET_OPTIONAL_NETMASK); +#elif defined(BOARD_HAS_CELLULAR) + CellularConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS); #endif /****************************************************************************** From bd8de84bfc7f5a38d72f8e6c02eb0a6ffba6165c Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 14 Aug 2024 11:10:03 +0200 Subject: [PATCH 657/780] examples: use HAS_TCP or HAS_LORA to reduce maintenance efforts --- examples/ArduinoIoTCloud-Advanced/thingProperties.h | 9 ++++----- examples/ArduinoIoTCloud-Basic/thingProperties.h | 9 ++++----- examples/ArduinoIoTCloud-Callbacks/thingProperties.h | 5 ++--- examples/ArduinoIoTCloud-Schedule/thingProperties.h | 9 ++++----- .../ArduinoIoTCloud_Travis_CI/thingProperties.h | 11 +++++------ 5 files changed, 19 insertions(+), 24 deletions(-) diff --git a/examples/ArduinoIoTCloud-Advanced/thingProperties.h b/examples/ArduinoIoTCloud-Advanced/thingProperties.h index 21639c458..6e1e66564 100644 --- a/examples/ArduinoIoTCloud-Advanced/thingProperties.h +++ b/examples/ArduinoIoTCloud-Advanced/thingProperties.h @@ -2,9 +2,8 @@ #include #include "arduino_secrets.h" -#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ - defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) - #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" +#if !(defined(HAS_TCP) || defined(HAS_LORA)) + #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif #if defined(BOARD_HAS_SECRET_KEY) @@ -23,11 +22,11 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif -#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT) +#if defined(HAS_TCP) ArduinoCloud.addProperty(switchButton, Permission::Write).onUpdate(onSwitchButtonChange); ArduinoCloud.addProperty(location, Permission::Read).publishOnChange(0.0f); ArduinoCloud.addProperty(color, Permission::ReadWrite).onUpdate(onColorChange); -#elif defined(BOARD_HAS_LORA) +#elif defined(HAS_LORA) ArduinoCloud.addProperty(switchButton, 1, Permission::Write).onUpdate(onSwitchButtonChange); ArduinoCloud.addProperty(location, 2, Permission::Read).publishOnChange(0.0f); ArduinoCloud.addProperty(color, 3, Permission::ReadWrite).onUpdate(onColorChange); diff --git a/examples/ArduinoIoTCloud-Basic/thingProperties.h b/examples/ArduinoIoTCloud-Basic/thingProperties.h index 16f75829b..48be1bf9a 100644 --- a/examples/ArduinoIoTCloud-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-Basic/thingProperties.h @@ -2,9 +2,8 @@ #include #include "arduino_secrets.h" -#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ - defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) - #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" +#if !(defined(HAS_TCP) || defined(HAS_LORA)) + #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif #if defined(BOARD_HAS_SECRET_KEY) @@ -22,11 +21,11 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif -#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT) +#if defined(HAS_TCP) ArduinoCloud.addProperty(led, Permission::Write).onUpdate(onLedChange); ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10); ArduinoCloud.addProperty(seconds, Permission::Read).publishOnChange(1); -#elif defined(BOARD_HAS_LORA) +#elif defined(HAS_LORA) ArduinoCloud.addProperty(led, 1, Permission::ReadWrite).onUpdate(onLedChange); ArduinoCloud.addProperty(potentiometer, 2, Permission::Read).publishOnChange(10); ArduinoCloud.addProperty(seconds, 3, Permission::Read).publishEvery(5 * MINUTES); diff --git a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h index 89a365ce6..d52660a92 100644 --- a/examples/ArduinoIoTCloud-Callbacks/thingProperties.h +++ b/examples/ArduinoIoTCloud-Callbacks/thingProperties.h @@ -2,9 +2,8 @@ #include #include "arduino_secrets.h" -#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ - defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) - #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" +#if !(defined(HAS_TCP) || defined(HAS_LORA)) + #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif #if defined(BOARD_HAS_SECRET_KEY) diff --git a/examples/ArduinoIoTCloud-Schedule/thingProperties.h b/examples/ArduinoIoTCloud-Schedule/thingProperties.h index 0af38fe3c..8a3d21f93 100644 --- a/examples/ArduinoIoTCloud-Schedule/thingProperties.h +++ b/examples/ArduinoIoTCloud-Schedule/thingProperties.h @@ -2,9 +2,8 @@ #include #include "arduino_secrets.h" -#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ - defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) - #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" +#if !(defined(HAS_TCP) || defined(HAS_LORA)) + #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif #if defined(BOARD_HAS_SECRET_KEY) @@ -27,7 +26,7 @@ void initProperties() { ArduinoCloud.setBoardId(BOARD_ID); ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY); #endif -#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT) +#if defined(HAS_TCP) ArduinoCloud.addProperty(switchButton, Permission::Write); ArduinoCloud.addProperty(oneShot, Permission::ReadWrite); ArduinoCloud.addProperty(minute, Permission::ReadWrite); @@ -36,7 +35,7 @@ void initProperties() { ArduinoCloud.addProperty(weekly, Permission::ReadWrite); ArduinoCloud.addProperty(monthly, Permission::ReadWrite); ArduinoCloud.addProperty(yearly, Permission::ReadWrite); -#elif defined(BOARD_HAS_LORA) +#elif defined(HAS_LORA) ArduinoCloud.addProperty(switchButton, 1, Permission::Write); #endif } diff --git a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h index 8ecd70770..2574220f4 100644 --- a/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h +++ b/examples/utility/ArduinoIoTCloud_Travis_CI/thingProperties.h @@ -2,9 +2,8 @@ #include #include "arduino_secrets.h" -#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ - defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) - #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" +#if !(defined(HAS_TCP) || defined(HAS_LORA)) + #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" #endif /****************************************************************************** @@ -15,7 +14,7 @@ #define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #endif -#if defined(BOARD_HAS_LORA) +#if defined(HAS_LORA) #define THING_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #endif @@ -85,7 +84,7 @@ void onStringPropertyChange(); /****************************************************************************** FUNCTIONS ******************************************************************************/ -#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined (BOARD_HAS_NB) || defined (BOARD_HAS_CATM1_NBIOT) +#if defined(HAS_TCP) void initProperties() { #if defined(BOARD_HAS_SECRET_KEY) ArduinoCloud.setBoardId(BOARD_ID); @@ -118,7 +117,7 @@ void initProperties() { ArduinoCloud.addProperty(str_property_8, Permission::ReadWrite).publishEvery(1 * SECONDS).onSync(DEVICE_WINS); } -#elif defined(BOARD_HAS_LORA) +#elif defined(HAS_LORA) void initProperties() { ArduinoCloud.setThingId(THING_ID); From 6c8931cd463beca5033645a90d897fb2ec55abec Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 22 Aug 2024 14:56:25 +0200 Subject: [PATCH 658/780] OTA RP2040: fix appSize() --- src/ota/implementation/OTANanoRP2040.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/ota/implementation/OTANanoRP2040.cpp b/src/ota/implementation/OTANanoRP2040.cpp index 7dad7baf6..c24ebf9ed 100644 --- a/src/ota/implementation/OTANanoRP2040.cpp +++ b/src/ota/implementation/OTANanoRP2040.cpp @@ -116,16 +116,27 @@ bool NANO_RP2040OTACloudProcess::isOtaCapable() { return true; } -// extern void* __stext; +extern uint32_t __flash_binary_start; extern uint32_t __flash_binary_end; +#if defined(UNINITIALIZED_DATA_SECTION) +extern uint32_t __uninitialized_data_start__; +extern uint32_t __uninitialized_data_end__; +#endif void* NANO_RP2040OTACloudProcess::appStartAddress() { - // return &__flash_binary_start; +#if defined(UNINITIALIZED_DATA_SECTION) + return &__flash_binary_start; +#else return (void*)XIP_BASE; +#endif } uint32_t NANO_RP2040OTACloudProcess::appSize() { - return (&__flash_binary_end - (uint32_t*)appStartAddress())*sizeof(void*); +#if defined(UNINITIALIZED_DATA_SECTION) + return ((&__flash_binary_end - (uint32_t*)appStartAddress()) - (&__uninitialized_data_end__ - &__uninitialized_data_start__)) * sizeof(void*); +#else + return (&__flash_binary_end - (uint32_t*)appStartAddress()) * sizeof(void*); +#endif } -#endif // defined(ARDUINO_NANO_RP2040_CONNECT) && OTA_ENABLED \ No newline at end of file +#endif // defined(ARDUINO_NANO_RP2040_CONNECT) && OTA_ENABLED From b9c21cd1a13aef841a4b5049feccfc2a40ebdc5f Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 6 Aug 2024 18:10:50 +0200 Subject: [PATCH 659/780] TimedAttempt: fix rollover --- src/utility/time/TimedAttempt.cpp | 4 ++-- src/utility/time/TimedAttempt.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utility/time/TimedAttempt.cpp b/src/utility/time/TimedAttempt.cpp index 4ff027fd6..2335116c5 100644 --- a/src/utility/time/TimedAttempt.cpp +++ b/src/utility/time/TimedAttempt.cpp @@ -54,7 +54,7 @@ unsigned long TimedAttempt::retry() { unsigned long TimedAttempt::reload() { unsigned long retryDelay = (1 << _retryCount) * _minDelay; _retryDelay = min(retryDelay, _maxDelay); - _nextRetryTick = millis() + _retryDelay; + _retryTick = millis(); return _retryDelay; } @@ -67,7 +67,7 @@ bool TimedAttempt::isRetry() { } bool TimedAttempt::isExpired() { - return millis() > _nextRetryTick; + return millis() - _retryTick > _retryDelay; } unsigned int TimedAttempt::getRetryCount() { diff --git a/src/utility/time/TimedAttempt.h b/src/utility/time/TimedAttempt.h index 67a1931c0..9a95e310f 100644 --- a/src/utility/time/TimedAttempt.h +++ b/src/utility/time/TimedAttempt.h @@ -34,7 +34,7 @@ class TimedAttempt { private: unsigned long _minDelay; unsigned long _maxDelay; - unsigned long _nextRetryTick; + unsigned long _retryTick; unsigned long _retryDelay; unsigned int _retryCount; }; From 74b906e9c65def30e63ebc1a81f1a1902bde86f8 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 8 Aug 2024 10:49:36 +0200 Subject: [PATCH 660/780] TimedAttempt: fix reload overflow --- src/utility/time/TimedAttempt.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/utility/time/TimedAttempt.cpp b/src/utility/time/TimedAttempt.cpp index 2335116c5..d41036055 100644 --- a/src/utility/time/TimedAttempt.cpp +++ b/src/utility/time/TimedAttempt.cpp @@ -52,8 +52,9 @@ unsigned long TimedAttempt::retry() { } unsigned long TimedAttempt::reload() { - unsigned long retryDelay = (1 << _retryCount) * _minDelay; - _retryDelay = min(retryDelay, _maxDelay); + unsigned long shift = _retryCount > 31 ? 31 : _retryCount; + unsigned long delay = (1UL << shift) * _minDelay; + _retryDelay = min(delay, _maxDelay); _retryTick = millis(); return _retryDelay; } From eaf2a47066d6316d46a5d0538cbf19775fbdf99f Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 8 Aug 2024 11:37:01 +0200 Subject: [PATCH 661/780] Config: fix thing id request backoff in case of detached board --- src/AIoTC_Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 14137ae1e..2efb70212 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -155,7 +155,7 @@ #define AIOT_CONFIG_THING_ID_REQUEST_MAX_RETRY_CNT (10UL) #define AIOT_CONFIG_DEVICE_REGISTERED_RETRY_DELAY_k (10UL) - #define AIOT_CONFIG_MAX_DEVICE_REGISTERED_RETRY_DELAY_k (4UL) + #define AIOT_CONFIG_MAX_DEVICE_REGISTERED_RETRY_DELAY_k (40UL) #define AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms (30000UL) #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) From 17b03b633209f132f35e04a93ff78bdcd2dc54c0 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 8 Aug 2024 12:39:08 +0200 Subject: [PATCH 662/780] TimedAttempt: initialize missing variables at begin --- src/utility/time/TimedAttempt.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utility/time/TimedAttempt.cpp b/src/utility/time/TimedAttempt.cpp index d41036055..70b6d0253 100644 --- a/src/utility/time/TimedAttempt.cpp +++ b/src/utility/time/TimedAttempt.cpp @@ -30,12 +30,16 @@ TimedAttempt::TimedAttempt(unsigned long minDelay, unsigned long maxDelay) void TimedAttempt::begin(unsigned long delay) { _retryCount = 0; + _retryDelay = 0; + _retryTick = 0; _minDelay = delay; _maxDelay = delay; } void TimedAttempt::begin(unsigned long minDelay, unsigned long maxDelay) { _retryCount = 0; + _retryDelay = 0; + _retryTick = 0; _minDelay = minDelay; _maxDelay = maxDelay; } From 08092f6af5f61c08cf9169626fd964a01ebe4a2b Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 8 Aug 2024 12:41:41 +0200 Subject: [PATCH 663/780] TimedAttempt: add tests --- extras/test/CMakeLists.txt | 4 +- extras/test/include/Arduino.h | 7 + extras/test/src/test_TimedAttempt.cpp | 186 ++++++++++++++++++++++++++ 3 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 extras/test/src/test_TimedAttempt.cpp diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index 2aab9ab9b..527fd7558 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -45,6 +45,7 @@ set(TEST_SRCS src/test_writeOnly.cpp src/test_writeOnDemand.cpp src/test_writeOnChange.cpp + src/test_TimedAttempt.cpp ) set(TEST_UTIL_SRCS @@ -53,6 +54,7 @@ set(TEST_UTIL_SRCS ) set(TEST_DUT_SRCS + ../../src/utility/time/TimedAttempt.cpp ../../src/property/Property.cpp ../../src/property/PropertyContainer.cpp ../../src/cbor/CBORDecoder.cpp @@ -84,7 +86,7 @@ set(TEST_TARGET_SRCS ########################################################################## -add_compile_definitions(HOST) +add_compile_definitions(HOST HAS_TCP) add_compile_options(-Wall -Wextra -Wpedantic -Werror) add_compile_options(-Wno-cast-function-type) diff --git a/extras/test/include/Arduino.h b/extras/test/include/Arduino.h index 6e66167a3..9e743f96f 100644 --- a/extras/test/include/Arduino.h +++ b/extras/test/include/Arduino.h @@ -11,6 +11,13 @@ #include +/****************************************************************************** + DEFINES + ******************************************************************************/ +#ifndef min + #define min(a,b) ((a)<(b)?(a):(b)) +#endif + /****************************************************************************** TYPEDEF ******************************************************************************/ diff --git a/extras/test/src/test_TimedAttempt.cpp b/extras/test/src/test_TimedAttempt.cpp new file mode 100644 index 000000000..d1490a138 --- /dev/null +++ b/extras/test/src/test_TimedAttempt.cpp @@ -0,0 +1,186 @@ +/* + Copyright (c) 2024 Arduino. All rights reserved. +*/ + +/****************************************************************************** + INCLUDE + ******************************************************************************/ + +#include + +#include +#include +#include +#include + +/****************************************************************************** + TEST CODE + ******************************************************************************/ + +SCENARIO("Test broker connection retries") +{ + TimedAttempt _connection_attempt(0,0); + + _connection_attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, + AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms); + + /* 100000 retries are more or less 37 days without connection */ + while(_connection_attempt.getRetryCount() < 100000) { + _connection_attempt.retry(); + + switch(_connection_attempt.getRetryCount()) { + case 1: + REQUIRE(_connection_attempt.getWaitTime() == 2000); + break; + case 2: + REQUIRE(_connection_attempt.getWaitTime() == 4000); + break; + case 3: + REQUIRE(_connection_attempt.getWaitTime() == 8000); + break; + case 4: + REQUIRE(_connection_attempt.getWaitTime() == 16000); + break; + default: + REQUIRE(_connection_attempt.getWaitTime() == 32000); + break; + } + } +} + +SCENARIO("Test thing id request with no answer from the cloud") +{ + TimedAttempt _attachAttempt(0,0); + + _attachAttempt.begin(AIOT_CONFIG_THING_ID_REQUEST_RETRY_DELAY_ms, + AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms); + + /* 100000 retries are more or less 37 days of requests */ + while(_attachAttempt.getRetryCount() < 100000) { + _attachAttempt.retry(); + + switch(_attachAttempt.getRetryCount()) { + case 1: + REQUIRE(_attachAttempt.getWaitTime() == 4000); + break; + case 2: + REQUIRE(_attachAttempt.getWaitTime() == 8000); + break; + case 3: + REQUIRE(_attachAttempt.getWaitTime() == 16000); + break; + default: + REQUIRE(_attachAttempt.getWaitTime() == 32000); + break; + } + } +} + +SCENARIO("Test thing id request of a detached device") +{ + TimedAttempt _attachAttempt(0,0); + + _attachAttempt.begin(AIOT_CONFIG_THING_ID_REQUEST_RETRY_DELAY_ms, + AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms); + + while(_attachAttempt.getRetryCount() < 100000) { + _attachAttempt.retry(); + + switch(_attachAttempt.getRetryCount()) { + case 1: + REQUIRE(_attachAttempt.getWaitTime() == 4000); + _attachAttempt.reconfigure(AIOT_CONFIG_THING_ID_REQUEST_RETRY_DELAY_ms * + AIOT_CONFIG_DEVICE_REGISTERED_RETRY_DELAY_k, + AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms * + AIOT_CONFIG_MAX_DEVICE_REGISTERED_RETRY_DELAY_k); + break; + case 2: + REQUIRE(_attachAttempt.getWaitTime() == 80000); + break; + case 3: + REQUIRE(_attachAttempt.getWaitTime() == 160000); + break; + case 4: + REQUIRE(_attachAttempt.getWaitTime() == 320000); + break; + case 5: + REQUIRE(_attachAttempt.getWaitTime() == 640000); + break; + default: + REQUIRE(_attachAttempt.getWaitTime() == 1280000); + break; + } + } +} + +SCENARIO("Test last value request") +{ + TimedAttempt _syncAttempt(0,0); + + _syncAttempt.begin(AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms); + + /* 100000 retries are more or less 37 days of requests */ + while(_syncAttempt.getRetryCount() < 100000) { + _syncAttempt.retry(); + + switch(_syncAttempt.getRetryCount()) { + default: + REQUIRE(_syncAttempt.getWaitTime() == 30000); + break; + } + } +} + +SCENARIO("Test isExpired() and isRetry()") +{ + TimedAttempt attempt(0,0); + + attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, + AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms); + + /* Initial condition */ + set_millis(0); + REQUIRE(attempt.isExpired() == false); + REQUIRE(attempt.isRetry() == false); + + /* Normal retry 2000ms */ + attempt.retry(); + REQUIRE(attempt.isRetry() == true); + set_millis(1000); + REQUIRE(attempt.isExpired() == false); + set_millis(1999); + REQUIRE(attempt.isExpired() == false); + set_millis(2000); + REQUIRE(attempt.isExpired() == false); + set_millis(2001); + REQUIRE(attempt.isExpired() == true); + + /* Retry with rollover 4000ms */ + set_millis(ULONG_MAX - 1999); + attempt.retry(); + REQUIRE(attempt.isRetry() == true); + set_millis(0); + REQUIRE(attempt.isExpired() == false); + set_millis(1999); + REQUIRE(attempt.isExpired() == false); + set_millis(2000); + REQUIRE(attempt.isExpired() == false); + set_millis(2001); + REQUIRE(attempt.isExpired() == true); + + /* Normal retry 8000ms */ + set_millis(4000); + attempt.retry(); + REQUIRE(attempt.isRetry() == true); + set_millis(4000); + REQUIRE(attempt.isExpired() == false); + set_millis(11999); + REQUIRE(attempt.isExpired() == false); + set_millis(12000); + REQUIRE(attempt.isExpired() == false); + set_millis(12001); + REQUIRE(attempt.isExpired() == true); + + attempt.reset(); + REQUIRE(attempt.isRetry() == false); +} From 3cfe957a9b8af6920e47c56244cb7dfa6f8480ea Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 22 Aug 2024 11:31:07 +0200 Subject: [PATCH 664/780] improving cmake for tests --- extras/test/CMakeLists.txt | 14 +- .../external/catch/v2.13.10/include/catch.hpp | 17976 ---------------- .../external/fakeit/v2.0.5/include/fakeit.hpp | 9375 -------- extras/test/src/test_CloudColor.cpp | 2 +- extras/test/src/test_CloudLocation.cpp | 2 +- extras/test/src/test_CloudSchedule.cpp | 2 +- extras/test/src/test_TimedAttempt.cpp | 2 +- extras/test/src/test_addPropertyReal.cpp | 2 +- extras/test/src/test_callback.cpp | 3 +- extras/test/src/test_command_decode.cpp | 2 +- extras/test/src/test_command_encode.cpp | 2 +- extras/test/src/test_decode.cpp | 5 +- extras/test/src/test_encode.cpp | 2 +- extras/test/src/test_main.cpp | 2 +- extras/test/src/test_publishEvery.cpp | 2 +- extras/test/src/test_publishOnChange.cpp | 2 +- .../src/test_publishOnChangeRateLimit.cpp | 2 +- extras/test/src/test_readOnly.cpp | 2 +- extras/test/src/test_writeOnChange.cpp | 2 +- extras/test/src/test_writeOnDemand.cpp | 2 +- extras/test/src/test_writeOnly.cpp | 2 +- 21 files changed, 34 insertions(+), 27371 deletions(-) delete mode 100644 extras/test/external/catch/v2.13.10/include/catch.hpp delete mode 100644 extras/test/external/fakeit/v2.0.5/include/fakeit.hpp diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index 527fd7558..e71791f66 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -6,6 +6,16 @@ cmake_minimum_required(VERSION 2.8) project(testArduinoIoTCloud) +Include(FetchContent) + +FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v3.4.0 +) + +FetchContent_MakeAvailable(Catch2) + ########################################################################## include_directories(include) @@ -13,8 +23,6 @@ include_directories(../../src) include_directories(../../src/cbor) include_directories(../../src/property) include_directories(../../src/utility/time) -include_directories(external/catch/v2.13.10/include) -include_directories(external/fakeit/v2.0.5/include) ########################################################################## @@ -100,5 +108,7 @@ add_executable( ${TEST_TARGET_SRCS} ) +target_link_libraries( ${TEST_TARGET} Catch2WithMain ) + ########################################################################## diff --git a/extras/test/external/catch/v2.13.10/include/catch.hpp b/extras/test/external/catch/v2.13.10/include/catch.hpp deleted file mode 100644 index 9b309bddc..000000000 --- a/extras/test/external/catch/v2.13.10/include/catch.hpp +++ /dev/null @@ -1,17976 +0,0 @@ -/* - * Catch v2.13.10 - * Generated: 2022-10-16 11:01:23.452308 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved. - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -// start catch.hpp - - -#define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 13 -#define CATCH_VERSION_PATCH 10 - -#ifdef __clang__ -# pragma clang system_header -#elif defined __GNUC__ -# pragma GCC system_header -#endif - -// start catch_suppress_warnings.h - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(push) -# pragma warning(disable: 161 1682) -# else // __ICC -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wswitch-enum" -# pragma clang diagnostic ignored "-Wcovered-switch-default" -# endif -#elif defined __GNUC__ - // Because REQUIREs trigger GCC's -Wparentheses, and because still - // supported version of g++ have only buggy support for _Pragmas, - // Wparentheses have to be suppressed globally. -# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details - -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wpadded" -#endif -// end catch_suppress_warnings.h -#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) -# define CATCH_IMPL -# define CATCH_CONFIG_ALL_PARTS -#endif - -// In the impl file, we want to have access to all parts of the headers -// Can also be used to sanely support PCHs -#if defined(CATCH_CONFIG_ALL_PARTS) -# define CATCH_CONFIG_EXTERNAL_INTERFACES -# if defined(CATCH_CONFIG_DISABLE_MATCHERS) -# undef CATCH_CONFIG_DISABLE_MATCHERS -# endif -# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) -# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -# endif -#endif - -#if !defined(CATCH_CONFIG_IMPL_ONLY) -// start catch_platform.h - -// See e.g.: -// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html -#ifdef __APPLE__ -# include -# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ - (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) -# define CATCH_PLATFORM_MAC -# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) -# define CATCH_PLATFORM_IPHONE -# endif - -#elif defined(linux) || defined(__linux) || defined(__linux__) -# define CATCH_PLATFORM_LINUX - -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) -# define CATCH_PLATFORM_WINDOWS -#endif - -// end catch_platform.h - -#ifdef CATCH_IMPL -# ifndef CLARA_CONFIG_MAIN -# define CLARA_CONFIG_MAIN_NOT_DEFINED -# define CLARA_CONFIG_MAIN -# endif -#endif - -// start catch_user_interfaces.h - -namespace Catch { - unsigned int rngSeed(); -} - -// end catch_user_interfaces.h -// start catch_tag_alias_autoregistrar.h - -// start catch_common.h - -// start catch_compiler_capabilities.h - -// Detect a number of compiler features - by compiler -// The following features are defined: -// -// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? -// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? -// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? -// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? -// **************** -// Note to maintainers: if new toggles are added please document them -// in configuration.md, too -// **************** - -// In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -#ifdef __cplusplus - -# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) -# define CATCH_CPP14_OR_GREATER -# endif - -# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -# define CATCH_CPP17_OR_GREATER -# endif - -#endif - -// Only GCC compiler should be used in this block, so other compilers trying to -// mask themselves as GCC should be ignored. -#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) - -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) - -#endif - -#if defined(__clang__) - -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) - -// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug -// which results in calls to destructors being emitted for each temporary, -// without a matching initialization. In practice, this can result in something -// like `std::string::~string` being called on an uninitialized value. -// -// For example, this code will likely segfault under IBM XL: -// ``` -// REQUIRE(std::string("12") + "34" == "1234") -// ``` -// -// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. -# if !defined(__ibmxl__) && !defined(__CUDACC__) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ -# endif - -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ - _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") - -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) - -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) - -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) - -# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// Assume that non-Windows platforms support posix signals by default -#if !defined(CATCH_PLATFORM_WINDOWS) - #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS -#endif - -//////////////////////////////////////////////////////////////////////////////// -// We know some environments not to support full POSIX signals -#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) - #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -#endif - -#ifdef __OS400__ -# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -# define CATCH_CONFIG_COLOUR_NONE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Android somehow still does not support std::to_string -#if defined(__ANDROID__) -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING -# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Not all Windows environments support SEH properly -#if defined(__MINGW32__) -# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH -#endif - -//////////////////////////////////////////////////////////////////////////////// -// PS4 -#if defined(__ORBIS__) -# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Cygwin -#ifdef __CYGWIN__ - -// Required for some versions of Cygwin to declare gettimeofday -// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin -# define _BSD_SOURCE -// some versions of cygwin (most) do not support std::to_string. Use the libstd check. -// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 -# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ - && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) - -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING - -# endif -#endif // __CYGWIN__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#if defined(_MSC_VER) - -// Universal Windows platform does not support SEH -// Or console colours (or console at all...) -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -# define CATCH_CONFIG_COLOUR_NONE -# else -# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH -# endif - -# if !defined(__clang__) // Handle Clang masquerading for msvc - -// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ -// _MSVC_TRADITIONAL == 0 means new conformant preprocessor -// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) -# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -# endif // MSVC_TRADITIONAL - -// Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop` -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) -# endif // __clang__ - -#endif // _MSC_VER - -#if defined(_REENTRANT) || defined(_MSC_VER) -// Enable async processing, as -pthread is specified or no additional linking is required -# define CATCH_INTERNAL_CONFIG_USE_ASYNC -#endif // _MSC_VER - -//////////////////////////////////////////////////////////////////////////////// -// Check if we are compiled with -fno-exceptions or equivalent -#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) -# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED -#endif - -//////////////////////////////////////////////////////////////////////////////// -// DJGPP -#ifdef __DJGPP__ -# define CATCH_INTERNAL_CONFIG_NO_WCHAR -#endif // __DJGPP__ - -//////////////////////////////////////////////////////////////////////////////// -// Embarcadero C++Build -#if defined(__BORLANDC__) - #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// Use of __COUNTER__ is suppressed during code analysis in -// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly -// handled by it. -// Otherwise all supported compilers support COUNTER macro, -// but user still might want to turn it off -#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) - #define CATCH_INTERNAL_CONFIG_COUNTER -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// RTX is a special version of Windows that is real time. -// This means that it is detected as Windows, but does not provide -// the same set of capabilities as real Windows does. -#if defined(UNDER_RTSS) || defined(RTX64_BUILD) - #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH - #define CATCH_INTERNAL_CONFIG_NO_ASYNC - #define CATCH_CONFIG_COLOUR_NONE -#endif - -#if !defined(_GLIBCXX_USE_C99_MATH_TR1) -#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER -#endif - -// Various stdlib support checks that require __has_include -#if defined(__has_include) - // Check if string_view is available and usable - #if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW - #endif - - // Check if optional is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) - - // Check if byte is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # include - # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) - # define CATCH_INTERNAL_CONFIG_CPP17_BYTE - # endif - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) - - // Check if variant is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # if defined(__clang__) && (__clang_major__ < 8) - // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 - // fix should be in clang 8, workaround in libstdc++ 8.2 - # include - # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) - # define CATCH_CONFIG_NO_CPP17_VARIANT - # else - # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT - # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) - # else - # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT - # endif // defined(__clang__) && (__clang_major__ < 8) - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) -#endif // defined(__has_include) - -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) -# define CATCH_CONFIG_COUNTER -#endif -#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) -# define CATCH_CONFIG_WINDOWS_SEH -#endif -// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. -#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) -# define CATCH_CONFIG_POSIX_SIGNALS -#endif -// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. -#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) -# define CATCH_CONFIG_WCHAR -#endif - -#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) -# define CATCH_CONFIG_CPP11_TO_STRING -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) -# define CATCH_CONFIG_CPP17_OPTIONAL -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) -# define CATCH_CONFIG_CPP17_STRING_VIEW -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) -# define CATCH_CONFIG_CPP17_VARIANT -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) -# define CATCH_CONFIG_CPP17_BYTE -#endif - -#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) -# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE -#endif - -#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) -# define CATCH_CONFIG_NEW_CAPTURE -#endif - -#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -# define CATCH_CONFIG_DISABLE_EXCEPTIONS -#endif - -#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) -# define CATCH_CONFIG_POLYFILL_ISNAN -#endif - -#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) -# define CATCH_CONFIG_USE_ASYNC -#endif - -#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) -# define CATCH_CONFIG_ANDROID_LOGWRITE -#endif - -#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) -# define CATCH_CONFIG_GLOBAL_NEXTAFTER -#endif - -// Even if we do not think the compiler has that warning, we still have -// to provide a macro that can be used by the code. -#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION -#endif -#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS -#endif - -// The goal of this macro is to avoid evaluation of the arguments, but -// still have the compiler warn on problems inside... -#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) -#endif - -#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) -# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#elif defined(__clang__) && (__clang_major__ < 5) -# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#endif - -#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#endif - -#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -#define CATCH_TRY if ((true)) -#define CATCH_CATCH_ALL if ((false)) -#define CATCH_CATCH_ANON(type) if ((false)) -#else -#define CATCH_TRY try -#define CATCH_CATCH_ALL catch (...) -#define CATCH_CATCH_ANON(type) catch (type) -#endif - -#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) -#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#endif - -// end catch_compiler_capabilities.h -#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line -#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) -#ifdef CATCH_CONFIG_COUNTER -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) -#else -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) -#endif - -#include -#include -#include - -// We need a dummy global operator<< so we can bring it into Catch namespace later -struct Catch_global_namespace_dummy {}; -std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); - -namespace Catch { - - struct CaseSensitive { enum Choice { - Yes, - No - }; }; - - class NonCopyable { - NonCopyable( NonCopyable const& ) = delete; - NonCopyable( NonCopyable && ) = delete; - NonCopyable& operator = ( NonCopyable const& ) = delete; - NonCopyable& operator = ( NonCopyable && ) = delete; - - protected: - NonCopyable(); - virtual ~NonCopyable(); - }; - - struct SourceLineInfo { - - SourceLineInfo() = delete; - SourceLineInfo( char const* _file, std::size_t _line ) noexcept - : file( _file ), - line( _line ) - {} - - SourceLineInfo( SourceLineInfo const& other ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo( SourceLineInfo&& ) noexcept = default; - SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; - - bool empty() const noexcept { return file[0] == '\0'; } - bool operator == ( SourceLineInfo const& other ) const noexcept; - bool operator < ( SourceLineInfo const& other ) const noexcept; - - char const* file; - std::size_t line; - }; - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); - - // Bring in operator<< from global namespace into Catch namespace - // This is necessary because the overload of operator<< above makes - // lookup stop at namespace Catch - using ::operator<<; - - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() const; - }; - template - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } -} - -#define CATCH_INTERNAL_LINEINFO \ - ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) - -// end catch_common.h -namespace Catch { - - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - }; - -} // end namespace Catch - -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - -// end catch_tag_alias_autoregistrar.h -// start catch_test_registry.h - -// start catch_interfaces_testcase.h - -#include - -namespace Catch { - - class TestSpec; - - struct ITestInvoker { - virtual void invoke () const = 0; - virtual ~ITestInvoker(); - }; - - class TestCase; - struct IConfig; - - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; - }; - - bool isThrowSafe( TestCase const& testCase, IConfig const& config ); - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); - -} - -// end catch_interfaces_testcase.h -// start catch_stringref.h - -#include -#include -#include -#include - -namespace Catch { - - /// A non-owning string class (similar to the forthcoming std::string_view) - /// Note that, because a StringRef may be a substring of another string, - /// it may not be null terminated. - class StringRef { - public: - using size_type = std::size_t; - using const_iterator = const char*; - - private: - static constexpr char const* const s_empty = ""; - - char const* m_start = s_empty; - size_type m_size = 0; - - public: // construction - constexpr StringRef() noexcept = default; - - StringRef( char const* rawChars ) noexcept; - - constexpr StringRef( char const* rawChars, size_type size ) noexcept - : m_start( rawChars ), - m_size( size ) - {} - - StringRef( std::string const& stdString ) noexcept - : m_start( stdString.c_str() ), - m_size( stdString.size() ) - {} - - explicit operator std::string() const { - return std::string(m_start, m_size); - } - - public: // operators - auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator != (StringRef const& other) const noexcept -> bool { - return !(*this == other); - } - - auto operator[] ( size_type index ) const noexcept -> char { - assert(index < m_size); - return m_start[index]; - } - - public: // named queries - constexpr auto empty() const noexcept -> bool { - return m_size == 0; - } - constexpr auto size() const noexcept -> size_type { - return m_size; - } - - // Returns the current start pointer. If the StringRef is not - // null-terminated, throws std::domain_exception - auto c_str() const -> char const*; - - public: // substrings and searches - // Returns a substring of [start, start + length). - // If start + length > size(), then the substring is [start, size()). - // If start > size(), then the substring is empty. - auto substr( size_type start, size_type length ) const noexcept -> StringRef; - - // Returns the current start pointer. May not be null-terminated. - auto data() const noexcept -> char const*; - - constexpr auto isNullTerminated() const noexcept -> bool { - return m_start[m_size] == '\0'; - } - - public: // iterators - constexpr const_iterator begin() const { return m_start; } - constexpr const_iterator end() const { return m_start + m_size; } - }; - - auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; - auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; - - constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { - return StringRef( rawChars, size ); - } -} // namespace Catch - -constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { - return Catch::StringRef( rawChars, size ); -} - -// end catch_stringref.h -// start catch_preprocessor.hpp - - -#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ -#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) - -#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ -// MSVC needs more evaluations -#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) -#else -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) -#endif - -#define CATCH_REC_END(...) -#define CATCH_REC_OUT - -#define CATCH_EMPTY() -#define CATCH_DEFER(id) id CATCH_EMPTY() - -#define CATCH_REC_GET_END2() 0, CATCH_REC_END -#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 -#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 -#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT -#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) -#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) - -#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) - -#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) - -// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, -// and passes userdata as the first parameter to each invocation, -// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) -#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) -#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ -#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ -#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF -#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ -#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) -#else -// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF -#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) -#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ -#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) -#endif - -#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ -#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) - -#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) - -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) -#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) -#else -#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) -#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) -#endif - -#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ - CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) - -#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) -#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) -#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) -#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) -#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) -#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) -#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) -#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) -#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) -#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) -#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) - -#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N - -#define INTERNAL_CATCH_TYPE_GEN\ - template struct TypeList {};\ - template\ - constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ - template class...> struct TemplateTypeList{};\ - template class...Cs>\ - constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ - template\ - struct append;\ - template\ - struct rewrap;\ - template class, typename...>\ - struct create;\ - template class, typename>\ - struct convert;\ - \ - template \ - struct append { using type = T; };\ - template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ - struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ - template< template class L1, typename...E1, typename...Rest>\ - struct append, TypeList, Rest...> { using type = L1; };\ - \ - template< template class Container, template class List, typename...elems>\ - struct rewrap, List> { using type = TypeList>; };\ - template< template class Container, template class List, class...Elems, typename...Elements>\ - struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ - \ - template