From 068107a53476a7e028f8d8749635e201874a794e Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 27 Apr 2023 09:26:30 +0200 Subject: [PATCH 001/415] 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 002/415] 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 003/415] 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 004/415] 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 005/415] 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 006/415] 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 007/415] 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 008/415] 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 009/415] 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 010/415] 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 011/415] 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 012/415] 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 013/415] 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 014/415] 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 015/415] 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 016/415] 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 017/415] 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 018/415] 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 019/415] 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 020/415] 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 021/415] 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 022/415] 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 023/415] 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 024/415] 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 025/415] 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 026/415] 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 027/415] 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 028/415] 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 029/415] 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 030/415] 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 031/415] 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 032/415] 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 033/415] 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 034/415] 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 035/415] 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 036/415] 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 037/415] 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 038/415] 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 039/415] 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 040/415] 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 041/415] 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 042/415] 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 043/415] 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 044/415] 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 045/415] 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 046/415] 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 047/415] 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 048/415] 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 049/415] 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 050/415] 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 051/415] 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 052/415] 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 053/415] 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 054/415] 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 055/415] 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 056/415] 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 057/415] 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 058/415] 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 059/415] 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 060/415] 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 061/415] 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 062/415] 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 063/415] 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 064/415] 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 065/415] 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 066/415] 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 067/415] 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 068/415] 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 069/415] 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 070/415] 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 071/415] 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 072/415] 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 073/415] 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 074/415] 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 075/415] 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 076/415] 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 077/415] 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 078/415] 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 079/415] 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 080/415] 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 081/415] 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 082/415] 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 083/415] 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 084/415] 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 085/415] 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 086/415] 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 087/415] 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 088/415] 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 089/415] 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 090/415] 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 091/415] 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 092/415] 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 093/415] 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 094/415] 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 095/415] 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 096/415] 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 097/415] 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 098/415] 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 099/415] 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 100/415] 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 101/415] 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 102/415] 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 103/415] 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 104/415] 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 105/415] 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 106/415] 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 107/415] 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 108/415] 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 109/415] 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 110/415] 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 111/415] 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 112/415] 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 113/415] 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 114/415] 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 115/415] 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 116/415] 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 117/415] 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 118/415] 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 119/415] 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 120/415] 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 121/415] 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 122/415] 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 123/415] 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 124/415] 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 125/415] 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 126/415] 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 127/415] 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 128/415] 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 129/415] 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 130/415] 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 131/415] 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 132/415] 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 133/415] 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 134/415] 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 135/415] 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 136/415] 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 137/415] 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 138/415] 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 139/415] 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 140/415] 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 141/415] 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 142/415] 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 143/415] 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 144/415] 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 145/415] 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 146/415] 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 147/415] 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 148/415] 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 149/415] 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 150/415] 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 151/415] 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 152/415] 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 153/415] 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 154/415] 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 155/415] 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 156/415] 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 157/415] 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 158/415] 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((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_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 159/415] 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 160/415] 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 161/415] 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 162/415] 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(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 163/415] 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 164/415] 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 165/415] 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 166/415] 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 167/415] 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 168/415] 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 169/415] 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 170/415] 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 171/415] 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 172/415] 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 173/415] 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 174/415] 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 175/415] 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 176/415] 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 177/415] 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 178/415] 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 179/415] 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 180/415] 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 181/415] 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 182/415] 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 183/415] 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 184/415] 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 185/415] 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 186/415] 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 187/415] 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 188/415] 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 189/415] 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 190/415] 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 191/415] 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 192/415] 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 193/415] 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 194/415] 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 195/415] 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 196/415] 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 197/415] 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 198/415] 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 199/415] 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 200/415] 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 201/415] 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 202/415] 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 203/415] 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 204/415] 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 205/415] 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 206/415] 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 207/415] 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 208/415] 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 209/415] 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 210/415] 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 211/415] 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 212/415] 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 213/415] 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 214/415] 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 215/415] 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 216/415] 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 217/415] 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 218/415] 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 219/415] 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 220/415] 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 221/415] 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 222/415] 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 223/415] 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 224/415] 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 225/415] 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 226/415] 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 227/415] 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 228/415] 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 229/415] 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 230/415] 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 231/415] 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 232/415] 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 233/415] 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 234/415] 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 235/415] 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 236/415] 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 237/415] 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 238/415] 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 239/415] 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 240/415] 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 241/415] 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 242/415] 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 243/415] 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 244/415] 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 245/415] 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 246/415] 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 247/415] 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 248/415] 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