From 760489954a34484f89915435797b442a8d459b8b Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 13 Feb 2025 16:16:10 +0100 Subject: [PATCH 01/14] use network configurator in iotCloud update test ci update example of sketch that uses the NetworkConfigurator use NetworkConfigurator wrappers for agentsManager --- .github/workflows/compile-examples.yml | 19 ++- .../ArduinoIoTCloud-NetConfig.ino | 62 ++++++++ .../thingProperties.h | 47 ++++++ src/AIoTC_Config.h | 8 + src/ArduinoIoTCloud.cpp | 3 + src/ArduinoIoTCloud.h | 9 ++ src/ArduinoIoTCloudTCP.cpp | 138 +++++++++++++----- src/ArduinoIoTCloudTCP.h | 8 + 8 files changed, 256 insertions(+), 38 deletions(-) create mode 100644 examples/ArduinoIoTCloud-NetConfig/ArduinoIoTCloud-NetConfig.ino create mode 100644 examples/ArduinoIoTCloud-NetConfig/thingProperties.h diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 5eb4f66d9..94681d24b 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -21,12 +21,19 @@ jobs: UNIVERSAL_LIBRARIES: | # Install the ArduinoIoTCloud library from the repository - source-path: ./ - - name: Arduino_ConnectionHandler + - source-url: https://github.com/andreagilardoni/Arduino_ConnectionHandler.git + version: 0ca6d61eb538c5a21983e582ee1c8794442f8c75 + - source-url: https://github.com/fabik111/ArduinoBLE.git + version: 82e2a28f871e97b313846cee6d9efed8943dca53 - name: ArduinoHttpClient - name: Arduino_DebugUtils - name: ArduinoMqttClient - name: Arduino_SecureElement - name: Arduino_CloudUtils + - source-url: https://github.com/andreagilardoni/ArduinoStorage.git + version: 39f0bd138103967aaafcaa7f5c0e1e237b4ccb4d + - source-url: https://github.com/bcmi-labs/arduino-network-configurator.git + version: 962ab36dfb00eb9cebe089907223e576f463519f # sketch paths to compile (recursive) for all boards UNIVERSAL_SKETCH_PATHS: | - examples/ArduinoIoTCloud-Advanced @@ -127,10 +134,12 @@ jobs: - name: ArduinoECCX08 - name: Blues Wireless Notecard - name: RTCZero - - name: WiFiNINA + - source-url: https://github.com/andreagilardoni/WiFiNINA.git + version: ca7a9224f86b9aaf00de4f7feccea583a23b3d53 - name: Arduino_JSON - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | + - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-DeferredOTA - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule @@ -195,6 +204,7 @@ jobs: - name: Arduino_Cellular - name: Blues Wireless Notecard sketch-paths: | + - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-DeferredOTA - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule @@ -208,6 +218,7 @@ jobs: libraries: | - name: Blues Wireless Notecard sketch-paths: | + - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-DeferredOTA - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule @@ -223,6 +234,7 @@ jobs: - name: ArduinoECCX08 - name: Blues Wireless Notecard sketch-paths: | + - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-DeferredOTA - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule @@ -238,6 +250,7 @@ jobs: - name: ArduinoECCX08 - name: Blues Wireless Notecard sketch-paths: | + - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-DeferredOTA - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule @@ -252,6 +265,7 @@ jobs: - name: Arduino_Cellular - name: Blues Wireless Notecard sketch-paths: | + - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning @@ -264,6 +278,7 @@ jobs: libraries: | - name: Blues Wireless Notecard sketch-paths: | + - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule # Nano ESP32 diff --git a/examples/ArduinoIoTCloud-NetConfig/ArduinoIoTCloud-NetConfig.ino b/examples/ArduinoIoTCloud-NetConfig/ArduinoIoTCloud-NetConfig.ino new file mode 100644 index 000000000..238b59f55 --- /dev/null +++ b/examples/ArduinoIoTCloud-NetConfig/ArduinoIoTCloud-NetConfig.ino @@ -0,0 +1,62 @@ +/* + This sketch demonstrates how to exchange data between your board and the Arduino IoT Cloud. + + * Connect a potentiometer (or other analog sensor) to A0. + * When the potentiometer (or sensor) value changes the data is sent to the Cloud. + * When you flip the switch in the Cloud dashboard the onboard LED lights gets turned ON or OFF. + + IMPORTANT: + This sketch works with WiFi, GSM, NB, Ethernet and Lora enabled boards supported by Arduino IoT Cloud. + On a LoRa board, if it is configured as a class A device (default and preferred option), + values from Cloud dashboard are received only after a value is sent to Cloud. + + The full list of compatible boards can be found here: + - https://github.com/arduino-libraries/ArduinoIoTCloud#what +*/ + +#include "thingProperties.h" + +#if !defined(LED_BUILTIN) && !defined(ARDUINO_NANO_ESP32) +static int const LED_BUILTIN = 2; +#endif + +void setup() { + /* Initialize serial and wait up to 5 seconds for port to open */ + Serial.begin(9600); + for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime <= 5000); ) { } + + /* Set the debug message level: + * - DBG_ERROR: Only show error messages + * - DBG_WARNING: Show warning and error messages + * - DBG_INFO: Show info, warning, and error messages + * - DBG_DEBUG: Show debug, info, warning, and error messages + * - DBG_VERBOSE: Show all messages + */ + setDebugMessageLevel(DBG_INFO); + + /* Configure LED pin as an output */ + pinMode(LED_BUILTIN, OUTPUT); + + /* This function takes care of connecting your sketch variables to the ArduinoIoTCloud object */ + initProperties(); + + /* Initialize Arduino IoT Cloud library */ + ArduinoCloud.begin(ArduinoIoTPreferredConnection); + + ArduinoCloud.printDebugInfo(); +} + +void loop() { + ArduinoCloud.update(); + potentiometer = analogRead(A0); + seconds = millis() / 1000; +} + +/* + * 'onLedChange' is called when the "led" property of your Thing changes + */ +void onLedChange() { + Serial.print("LED set to "); + Serial.println(led); + digitalWrite(LED_BUILTIN, led); +} diff --git a/examples/ArduinoIoTCloud-NetConfig/thingProperties.h b/examples/ArduinoIoTCloud-NetConfig/thingProperties.h new file mode 100644 index 000000000..833927042 --- /dev/null +++ b/examples/ArduinoIoTCloud-NetConfig/thingProperties.h @@ -0,0 +1,47 @@ +#if !defined(ARDUINO_SAMD_MKRWIFI1010) && !defined(ARDUINO_SAMD_NANO_33_IOT) && !defined(ARDUINO_NANO_RP2040_CONNECT) \ + && !defined(ARDUINO_PORTENTA_H7_M7) && !defined(ARDUINO_NICLA_VISION) && !defined(ARDUINO_OPTA) && !defined(ARDUINO_GIGA) \ + && !defined(ARDUINO_UNOR4_WIFI) && !defined(ARDUINO_PORTENTA_C33) +#error "This example is not compatible with this board." +#endif +#include +#include +#include "ConfiguratorAgents/agents/BLE/BLEAgent.h" +#include "ConfiguratorAgents/agents/Serial/SerialAgent.h" + +void onLedChange(); + +bool led; +int potentiometer; +int seconds; + +GenericConnectionHandler ArduinoIoTPreferredConnection; +KVStore kvStore; +NetworkConfiguratorClass NetworkConfigurator(ArduinoIoTPreferredConnection); +BLEAgentClass BLEAgent; +SerialAgentClass SerialAgent; + +void initProperties() { + NetworkConfigurator.addAgent(BLEAgent); + NetworkConfigurator.addAgent(SerialAgent); + NetworkConfigurator.setStorage(kvStore); + + /* For changing the default reset pin uncomment and set your preferred pin. + * Use DISABLE_PIN for disabling the reset procedure. + * The pin must be in the list of digital pins usable for interrupts. + * Please refer to the Arduino documentation for more details: + * https://docs.arduino.cc/language-reference/en/functions/external-interrupts/attachInterrupt/ + */ + //NetworkConfigurator.setReconfigurePin(your_pin); + + /* Otherwise if you need to monitor the pin status changes + * you can set a custom callback function that is fired on every change + */ + //NetworkConfigurator.setPinChangedCallback(your_callback); + + ArduinoCloud.setConfigurator(NetworkConfigurator); + + ArduinoCloud.addProperty(led, Permission::Write).onUpdate(onLedChange); + ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10); + ArduinoCloud.addProperty(seconds, Permission::Read).publishOnChange(1); + +} diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 82e5093ef..cf3e259d5 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -148,6 +148,14 @@ #define BOARD_STM32H7 #endif +#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_NANO_RP2040_CONNECT) \ + || defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_OPTA) || defined(ARDUINO_GIGA) \ + || defined(ARDUINO_UNOR4_WIFI) || defined(ARDUINO_PORTENTA_C33) + #define NETWORK_CONFIGURATOR_ENABLED (1) +#else + #define NETWORK_CONFIGURATOR_ENABLED (0) +#endif + /****************************************************************************** * CONSTANTS ******************************************************************************/ diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index a565cac44..74443ff5b 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -27,6 +27,9 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass() : _connection{nullptr} +#if NETWORK_CONFIGURATOR_ENABLED +, _configurator{nullptr} +#endif , _time_service(TimeService) , _thing_id{"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"} , _lib_version{AIOT_CONFIG_LIB_VERSION} diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 7cea9382e..95f7379d1 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -25,6 +25,9 @@ #include #include +#if NETWORK_CONFIGURATOR_ENABLED +#include +#endif #if defined(DEBUG_ERROR) || defined(DEBUG_WARNING) || defined(DEBUG_INFO) || defined(DEBUG_DEBUG) || defined(DEBUG_VERBOSE) # include @@ -101,6 +104,9 @@ class ArduinoIoTCloudClass inline unsigned long getInternalTime() { return _time_service.getTime(); } inline unsigned long getLocalTime() { return _time_service.getLocalTime(); } + #if NETWORK_CONFIGURATOR_ENABLED + inline void setConfigurator(NetworkConfiguratorClass & configurator) { _configurator = &configurator; } + #endif void addCallback(ArduinoIoTCloudEvent const event, OnCloudEventCallback callback); #define addProperty( v, ...) addPropertyReal(v, #v, __VA_ARGS__) @@ -146,6 +152,9 @@ class ArduinoIoTCloudClass protected: ConnectionHandler * _connection; + #if NETWORK_CONFIGURATOR_ENABLED + NetworkConfiguratorClass * _configurator = nullptr; + #endif TimeServiceClass & _time_service; String _thing_id; String _lib_version; diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index dc8bb86d0..2d1600e35 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -35,7 +35,7 @@ #include /****************************************************************************** - LOCAL MODULE FUNCTIONS + LOCAL MODULE FUNCTIONS ******************************************************************************/ unsigned long getTime() @@ -48,7 +48,7 @@ unsigned long getTime() ******************************************************************************/ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() -: _state{State::ConnectPhy} +: _state{State::ConfigPhy} , _connection_attempt(0,0) , _message_stream(std::bind(&ArduinoIoTCloudTCP::sendMessage, this, std::placeholders::_1)) , _thing(&_message_stream) @@ -84,24 +84,16 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_ _connection = &connection; _brokerAddress = brokerAddress; - ArduinoIoTAuthenticationMode authMode = ArduinoIoTAuthenticationMode::CERTIFICATE; + _authMode = ArduinoIoTAuthenticationMode::CERTIFICATE; #if defined (BOARD_HAS_SECRET_KEY) /* If board supports and sketch is configured for username and password login */ if(_password.length()) { - authMode = ArduinoIoTAuthenticationMode::PASSWORD; + _authMode = ArduinoIoTAuthenticationMode::PASSWORD; } #endif - /* Setup broker TLS client */ - _brokerClient.begin(connection, authMode); - -#if OTA_ENABLED - /* Setup OTA TLS client */ - _otaClient.begin(connection); -#endif - /* If board is configured for certificate authentication and mTLS */ - if(authMode == ArduinoIoTAuthenticationMode::CERTIFICATE) + if(_authMode == ArduinoIoTAuthenticationMode::CERTIFICATE) { #if defined(BOARD_HAS_SECURE_ELEMENT) if (!_selement.begin()) @@ -141,9 +133,6 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_ _brokerPort = (brokerPort == DEFAULT_BROKER_PORT_AUTO) ? DEFAULT_BROKER_PORT_USER_PASS_AUTH : brokerPort; } - /* 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); @@ -151,6 +140,7 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, uint16_t brokerPort) { + _enable_watchdog = enable_watchdog; _brokerAddress = brokerAddress; _brokerPort = brokerPort; @@ -195,20 +185,12 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, } #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 - * set a rather large timeout at first. - */ -#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) - if (enable_watchdog) { - /* Initialize watchdog hardware */ - watchdog_enable(); - /* Setup callbacks to feed the watchdog during offloaded network operations (connection/download)*/ - watchdog_enable_network_feed(_connection->getInterface()); +#if NETWORK_CONFIGURATOR_ENABLED + if(_configurator != nullptr){ + _configurator->enableBLE(false); + _configurator->begin(); } #endif - return 1; } @@ -225,12 +207,16 @@ void ArduinoIoTCloudTCP::update() State next_state = _state; switch (_state) { + case State::ConfigPhy: next_state = handle_ConfigPhy(); break; + case State::updatePhy: next_state = handle_updatePhy(); break; + case State::Init: next_state = handle_Init(); break; case State::ConnectPhy: next_state = handle_ConnectPhy(); break; case State::SyncTime: next_state = handle_SyncTime(); break; case State::ConnectMqttBroker: next_state = handle_ConnectMqttBroker(); break; case State::Connected: next_state = handle_Connected(); break; case State::Disconnect: next_state = handle_Disconnect(); break; } + _state = next_state; /* This watchdog feed is actually needed only by the RP2040 Connect because its @@ -241,11 +227,24 @@ void ArduinoIoTCloudTCP::update() watchdog_reset(); #endif + /* Poll the network configurator to check if it is updating the configuration. + * The polling must be performed only if the the first configuration is completed. + */ + #if NETWORK_CONFIGURATOR_ENABLED + if(_configurator != nullptr && _state > State::Init && _configurator->update() == NetworkConfiguratorStates::UPDATING_CONFIG){ + _state = State::updatePhy; + } + #endif + #if OTA_ENABLED /* OTA FSM needs to reach the Idle state before being able to run independently from * the mqttClient. The state can be reached only after the mqttClient is connected to * the broker. */ + if(_state <= State::Init){ + return; + } + if((_ota.getState() != OTACloudProcessInterface::Resume && _ota.getState() != OTACloudProcessInterface::OtaBegin) || _mqttClient.connected()) { @@ -262,6 +261,9 @@ void ArduinoIoTCloudTCP::update() int ArduinoIoTCloudTCP::connected() { + if (_state <= State::Init) { + return 0; + } return _mqttClient.connected(); } @@ -276,6 +278,70 @@ void ArduinoIoTCloudTCP::printDebugInfo() * PRIVATE MEMBER FUNCTIONS ******************************************************************************/ +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConfigPhy() +{ +#if NETWORK_CONFIGURATOR_ENABLED + if (_configurator == nullptr) { + return State::Init; + } + + if(_configurator->update() == NetworkConfiguratorStates::CONFIGURED) { + _configurator->disconnectAgent(); + return State::Init; + } + return State::ConfigPhy; +#else + return State::Init; +#endif + +} + +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_updatePhy() +{ +#if NETWORK_CONFIGURATOR_ENABLED + if(_configurator != nullptr && _configurator->update() == NetworkConfiguratorStates::CONFIGURED){ + _configurator->disconnectAgent(); + // Go to Connected state since the connectionHandler obj doesn't change + return State::Connected; + } + + return State::updatePhy; +#else + return State::Connected; +#endif +} + +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Init() +{ + /* Setup broker TLS client */ + /* Setup broker TLS client */ + _brokerClient.begin(*_connection, _authMode); + +#if OTA_ENABLED + /* Setup OTA TLS client */ + _otaClient.begin(*_connection); +#endif + + /* Setup TimeService */ + _time_service.begin(_connection); + + /* Since we do not control what code the user inserts + * between ArduinoIoTCloudTCP::begin() and the first + * call to ArduinoIoTCloudTCP::update() it is wise to + * set a rather large timeout at first. + */ +#if defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_MBED) + if (_enable_watchdog) { + /* Initialize watchdog hardware */ + watchdog_enable(); + /* Setup callbacks to feed the watchdog during offloaded network operations (connection/download)*/ + watchdog_enable_network_feed(_connection->getInterface()); + } +#endif + + return State::ConnectPhy; +} + ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() { if (_connection->check() == NetworkConnectionState::CONNECTED) @@ -467,10 +533,10 @@ void ArduinoIoTCloudTCP::handleMessage(int length) 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 - */ + * 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; @@ -525,8 +591,8 @@ void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(String const topic, Proper if (bytes_encoded > 0) { /* If properties have been encoded store them in the back-up buffer - * in order to allow retransmission in case of failure. - */ + * in order to allow retransmission in case of failure. + */ _mqtt_data_len = bytes_encoded; memcpy(_mqtt_data_buf, data, _mqtt_data_len); /* Transmit the properties to the MQTT broker */ @@ -633,8 +699,8 @@ int ArduinoIoTCloudTCP::updateCertificate(String authorityKeyIdentifier, String #endif /****************************************************************************** - * EXTERN DEFINITION - ******************************************************************************/ +* EXTERN DEFINITION +******************************************************************************/ ArduinoIoTCloudTCP ArduinoCloud; diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 6560a5f70..c9b4bd11e 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -120,6 +120,9 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass enum class State { + ConfigPhy, + updatePhy, + Init, ConnectPhy, SyncTime, ConnectMqttBroker, @@ -133,11 +136,13 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass ArduinoCloudThing _thing; ArduinoCloudDevice _device; + ArduinoIoTAuthenticationMode _authMode; String _brokerAddress; uint16_t _brokerPort; uint8_t _mqtt_data_buf[MQTT_TRANSMIT_BUFFER_SIZE]; int _mqtt_data_len; bool _mqtt_data_request_retransmit; + bool _enable_watchdog; #if defined(BOARD_HAS_SECRET_KEY) String _password; @@ -170,6 +175,9 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass inline String getTopic_dataout () { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/e/o"); } inline String getTopic_datain () { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/e/i"); } + State handle_ConfigPhy(); + State handle_updatePhy(); + State handle_Init(); State handle_ConnectPhy(); State handle_SyncTime(); State handle_ConnectMqttBroker(); From 850bea28a26b71194ab9e8a9c8ae002b3dfc69c8 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Wed, 19 Mar 2025 16:30:20 +0100 Subject: [PATCH 02/14] add disconnect method --- src/ArduinoIoTCloud.h | 2 +- src/ArduinoIoTCloudTCP.cpp | 31 +++++++++++++++++++++++++------ src/ArduinoIoTCloudTCP.h | 7 +++++-- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 95f7379d1..4512e9a6d 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -90,7 +90,7 @@ class ArduinoIoTCloudClass virtual void update () = 0; virtual int connected () = 0; virtual void printDebugInfo() = 0; - + virtual void disconnect () { } void push(); bool setTimestamp(String const & prop_name, unsigned long const timestamp); diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 2d1600e35..deecd3ea4 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -79,7 +79,7 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() * PUBLIC MEMBER FUNCTIONS ******************************************************************************/ -int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_watchdog, String brokerAddress, uint16_t brokerPort) +int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_watchdog, String brokerAddress, uint16_t brokerPort, bool auto_reconnect) { _connection = &connection; _brokerAddress = brokerAddress; @@ -135,14 +135,17 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_ /* 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); + return begin(enable_watchdog, _brokerAddress, _brokerPort, auto_reconnect); } -int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, uint16_t brokerPort) +int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, uint16_t brokerPort, bool auto_reconnect) { _enable_watchdog = enable_watchdog; _brokerAddress = brokerAddress; _brokerPort = brokerPort; + _auto_reconnect = auto_reconnect; + + _state = State::ConfigPhy; _mqttClient.setClient(_brokerClient); @@ -215,6 +218,7 @@ void ArduinoIoTCloudTCP::update() case State::ConnectMqttBroker: next_state = handle_ConnectMqttBroker(); break; case State::Connected: next_state = handle_Connected(); break; case State::Disconnect: next_state = handle_Disconnect(); break; + case State::Disconnected: break; } _state = next_state; @@ -274,6 +278,16 @@ void ArduinoIoTCloudTCP::printDebugInfo() DEBUG_INFO("MQTT Broker: %s:%d", _brokerAddress.c_str(), _brokerPort); } +void ArduinoIoTCloudTCP::disconnect() { + if (_state == State::ConfigPhy || _state == State::Init) { + return; + } + + _mqttClient.stop(); + _auto_reconnect = false; + _state = State::Disconnect; +} + /****************************************************************************** * PRIVATE MEMBER FUNCTIONS ******************************************************************************/ @@ -447,9 +461,13 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect() 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; + if(_auto_reconnect) { + /* 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; + } + + return State::Disconnected; } void ArduinoIoTCloudTCP::onMessage(int length) @@ -696,6 +714,7 @@ int ArduinoIoTCloudTCP::updateCertificate(String authorityKeyIdentifier, String } return 0; } + #endif /****************************************************************************** diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index c9b4bd11e..aa075827c 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -72,9 +72,10 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass virtual void update () override; virtual int connected () override; virtual void printDebugInfo() override; + virtual void disconnect () override; - int begin(ConnectionHandler & connection, bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS, uint16_t brokerPort = DEFAULT_BROKER_PORT_AUTO); - int begin(bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS, uint16_t brokerPort = DEFAULT_BROKER_PORT_AUTO); + int begin(ConnectionHandler & connection, bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS, uint16_t brokerPort = DEFAULT_BROKER_PORT_AUTO, bool auto_reconnect = true); + int begin(bool const enable_watchdog = true, String brokerAddress = DEFAULT_BROKER_ADDRESS, uint16_t brokerPort = DEFAULT_BROKER_PORT_AUTO, bool auto_reconnect = true); #if defined(BOARD_HAS_SECURE_ELEMENT) int updateCertificate(String authorityKeyIdentifier, String serialNumber, String notBefore, String notAfter, String signature); @@ -128,6 +129,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass ConnectMqttBroker, Connected, Disconnect, + Disconnected, }; State _state; @@ -143,6 +145,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass int _mqtt_data_len; bool _mqtt_data_request_retransmit; bool _enable_watchdog; + bool _auto_reconnect; #if defined(BOARD_HAS_SECRET_KEY) String _password; From 97e88d34742ee01cd2a329bbdb9ea62d69808316 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 31 Mar 2025 16:11:19 +0200 Subject: [PATCH 03/14] new Provisioning_2.0 sketch --- .github/workflows/compile-examples.yml | 24 +- .../utility/Provisioning_2.0/CSRHandler.cpp | 424 ++++++++++++++++++ .../utility/Provisioning_2.0/CSRHandler.h | 74 +++ .../Provisioning_2.0/ClaimingHandler.cpp | 173 +++++++ .../Provisioning_2.0/ClaimingHandler.h | 50 +++ .../Provisioning_2.0/Provisioning_2.0.ino | 222 +++++++++ .../utility/Provisioning_2.0/SecretsHelper.h | 20 + .../Provisioning_2.0/thingProperties.h | 33 ++ src/ArduinoIoTCloudTCP.cpp | 2 +- 9 files changed, 1013 insertions(+), 9 deletions(-) create mode 100644 examples/utility/Provisioning_2.0/CSRHandler.cpp create mode 100644 examples/utility/Provisioning_2.0/CSRHandler.h create mode 100644 examples/utility/Provisioning_2.0/ClaimingHandler.cpp create mode 100644 examples/utility/Provisioning_2.0/ClaimingHandler.h create mode 100644 examples/utility/Provisioning_2.0/Provisioning_2.0.ino create mode 100644 examples/utility/Provisioning_2.0/SecretsHelper.h create mode 100644 examples/utility/Provisioning_2.0/thingProperties.h diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 94681d24b..794a90077 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -21,19 +21,20 @@ jobs: UNIVERSAL_LIBRARIES: | # Install the ArduinoIoTCloud library from the repository - source-path: ./ - - source-url: https://github.com/andreagilardoni/Arduino_ConnectionHandler.git - version: 0ca6d61eb538c5a21983e582ee1c8794442f8c75 + - source-url: https://github.com/fabik111/Arduino_ConnectionHandler.git + version: e8539870f2f8b7936f3126070b45055c38856bb1 - source-url: https://github.com/fabik111/ArduinoBLE.git version: 82e2a28f871e97b313846cee6d9efed8943dca53 - name: ArduinoHttpClient - name: Arduino_DebugUtils - name: ArduinoMqttClient - - name: Arduino_SecureElement - - name: Arduino_CloudUtils - - source-url: https://github.com/andreagilardoni/ArduinoStorage.git - version: 39f0bd138103967aaafcaa7f5c0e1e237b4ccb4d - - source-url: https://github.com/bcmi-labs/arduino-network-configurator.git - version: 962ab36dfb00eb9cebe089907223e576f463519f + - source-url: https://github.com/fabik111/Arduino_SecureElement.git + version: f5a23964a1c70048e48d5ed2d2657004446f0e3d + - source-url: https://github.com/fabik111/Arduino_CloudUtils.git + version: a8b52eaf500c63b2e8bd3e4b6f6c77b70fc3e65d + - source-url: https://github.com/arduino-libraries/Arduino_KVStore.git + - source-url: https://github.com/arduino-libraries/Arduino_UniqueHWId.git + - source-url: https://github.com/arduino-libraries/Arduino_NetworkConfigurator.git # sketch paths to compile (recursive) for all boards UNIVERSAL_SKETCH_PATHS: | - examples/ArduinoIoTCloud-Advanced @@ -145,6 +146,7 @@ jobs: - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning - examples/utility/SelfProvisioning + - examples/utility/Provisioning_2.0 - board: type: wan platforms: | @@ -209,6 +211,7 @@ jobs: - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning + - examples/utility/Provisioning_2.0 # Nicla Vision - board: type: mbed_nicla @@ -223,6 +226,7 @@ jobs: - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning + - examples/utility/Provisioning_2.0 # Opta - board: type: mbed_opta @@ -239,6 +243,7 @@ jobs: - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning + - examples/utility/Provisioning_2.0 # GIGA - board: type: mbed_giga @@ -255,6 +260,7 @@ jobs: - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning + - examples/utility/Provisioning_2.0 # Portenta C33 - board: type: renesas_portenta @@ -269,6 +275,7 @@ jobs: - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning + - examples/utility/Provisioning_2.0 # UNO R4 WiFi - board: type: renesas_uno @@ -281,6 +288,7 @@ jobs: - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule + - examples/utility/Provisioning_2.0 # Nano ESP32 - board: type: arduino_esp32 diff --git a/examples/utility/Provisioning_2.0/CSRHandler.cpp b/examples/utility/Provisioning_2.0/CSRHandler.cpp new file mode 100644 index 000000000..4f7649fb7 --- /dev/null +++ b/examples/utility/Provisioning_2.0/CSRHandler.cpp @@ -0,0 +1,424 @@ +/* + 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 "CSRHandler.h" +#include +#include +#include +#include +#include +#include +#include +#include "Arduino_DebugUtils.h" +#include + +#define RESPONSE_TIMEOUT 5000 +#define CONNECTION_RETRY_TIMEOUT_MS 2000 +#define BACKEND_INTERVAL_s 12 +#define MAX_CSR_REQUEST_INTERVAL 180000 +#define MAX_CSR_REQUEST_INTERVAL_ATTEMPTS 15 + +constexpr char *server = "boards-v2.arduino.cc"; + +CSRHandlerClass::CSRHandlerClass() : + _ledFeedback{LEDFeedbackClass::getInstance()}, + _state{CSRHandlerStates::END}, + _nextRequestAt{0}, + _requestAttempt{0}, + _startWaitingResponse{0}, + _uhwid{nullptr}, + _certForCSR{nullptr}, + _connectionHandler{nullptr}, + _secureElement{nullptr}, + _tlsClient{nullptr}, + _client{nullptr}, + _fw_version{""}, + _deviceId{""}, + _issueYear{0}, + _issueMonth{0}, + _issueDay{0}, + _issueHour{0} { + memset(_serialNumber, 0, sizeof(_serialNumber)); + memset(_authorityKeyIdentifier, 0, sizeof(_authorityKeyIdentifier)); + memset(_signature, 0, sizeof(_signature)); +} + +CSRHandlerClass::~CSRHandlerClass() { + if (_certForCSR) { + delete _certForCSR; + _certForCSR = nullptr; + } + if (_client) { + delete _client; + _client = nullptr; + } + + if(_tlsClient){ + delete _tlsClient; + _tlsClient = nullptr; + } +} + +bool CSRHandlerClass::begin(ConnectionHandler &connectionHandler, SecureElement &secureElement, String &uhwid) { + if(_state != CSRHandlerStates::END) { + return true; + } + + if(uhwid == "") { + return false; + } + + _connectionHandler = &connectionHandler; + _secureElement = &secureElement; + _uhwid = &uhwid; + +#ifdef BOARD_HAS_WIFI + _fw_version = WiFi.firmwareVersion(); +#endif + if(!_tlsClient){ + _tlsClient = new TLSClientMqtt(); + } + _tlsClient->begin(*_connectionHandler); + _tlsClient->setTimeout(RESPONSE_TIMEOUT); + _client = new HttpClient(*_tlsClient, server, 443); + TimeService.begin(_connectionHandler); + _requestAttempt = 0; + _nextRequestAt = 0; + _startWaitingResponse = 0; + _state = CSRHandlerStates::BUILD_CSR; +} + +void CSRHandlerClass::end() { + if (_client) { + _client->stop(); + delete _client; + _client = nullptr; + } + + if (_certForCSR) { + delete _certForCSR; + _certForCSR = nullptr; + } + + if(_tlsClient){ + delete _tlsClient; + _tlsClient = nullptr; + } + _fw_version = ""; + _deviceId = ""; + _state = CSRHandlerStates::END; +} + +CSRHandlerClass::CSRHandlerStates CSRHandlerClass::poll() { + switch (_state) { + case CSRHandlerStates::BUILD_CSR: _state = handleBuildCSR (); break; + case CSRHandlerStates::REQUEST_SIGNATURE: _state = handleRequestSignature (); break; + case CSRHandlerStates::WAITING_RESPONSE: _state = handleWaitingResponse (); break; + case CSRHandlerStates::PARSE_RESPONSE: _state = handleParseResponse (); break; + case CSRHandlerStates::BUILD_CERTIFICATE: _state = handleBuildCertificate (); break; + case CSRHandlerStates::CERT_CREATED: _state = handleCertCreated (); break; + case CSRHandlerStates::WAITING_COMPLETE_RES: _state = handleWaitingCompleteRes(); break; + case CSRHandlerStates::COMPLETED: break; + case CSRHandlerStates::ERROR: handleError (); break; + case CSRHandlerStates::END: break; + } + + return _state; +} + +void CSRHandlerClass::updateNextRequestAt() { + uint32_t delay; + if(_requestAttempt <= MAX_CSR_REQUEST_INTERVAL_ATTEMPTS) { + delay = BACKEND_INTERVAL_s * _requestAttempt * 1000; // use linear backoff since backend has a rate limit + }else { + delay = MAX_CSR_REQUEST_INTERVAL; + } + + _nextRequestAt = millis() + delay + jitter(); +} + +uint32_t CSRHandlerClass::jitter(uint32_t base, uint32_t max) { + srand(millis()); + return base + rand() % (max - base); +} + +bool CSRHandlerClass::postRequest(const char *url, String &postData) { + if(!_client){ + _client = new HttpClient(*_tlsClient, server, 443); + } + + uint32_t ts = getTimestamp(); + if(ts == 0){ + DEBUG_WARNING("CSRH::%s Failed getting timestamp", __FUNCTION__); + return false; + } + + String token = getAIoTCloudJWT(*_secureElement, *_uhwid, ts, 1); + + _requestAttempt++; + _client->beginRequest(); + + if(_client->post(url) == 0){ + _client->sendHeader("Host", server); + _client->sendHeader("Connection", "close"); + _client->sendHeader("Content-Type", "application/json;charset=UTF-8"); + _client->sendHeader("Authorization", "Bearer " + token); + _client->sendHeader("Content-Length", postData.length()); + _client->beginBody(); + _client->print(postData); + _startWaitingResponse = millis(); + return true; + } + return false; +} + +uint32_t CSRHandlerClass::getTimestamp() { + uint8_t getTsAttempt = 0; + uint32_t ts = 0; + do{ + TimeService.sync(); + ts = TimeService.getTime(); + getTsAttempt++; + }while(ts == 0 && getTsAttempt < 3); + + return ts; +} + +CSRHandlerClass::CSRHandlerStates CSRHandlerClass::handleBuildCSR() { + if (!_certForCSR) { + _certForCSR = new ECP256Certificate(); + } + _certForCSR->begin(); + + _certForCSR->setSubjectCommonName(*_uhwid); + + if (!SElementCSR::build(*_secureElement, *_certForCSR, static_cast(SElementArduinoCloudSlot::Key), true)) { + DEBUG_ERROR("CSRH::%s Error generating CSR!", __FUNCTION__); + _ledFeedback.setMode(LEDFeedbackClass::LEDFeedbackMode::ERROR); + return CSRHandlerStates::ERROR; + } + return CSRHandlerStates::REQUEST_SIGNATURE; +} + +CSRHandlerClass::CSRHandlerStates CSRHandlerClass::handleRequestSignature() { + CSRHandlerStates nextState = _state; + + if(millis() < _nextRequestAt) { + return nextState; + } + + NetworkConnectionState connectionRes = _connectionHandler->check(); + if (connectionRes != NetworkConnectionState::CONNECTED) { + nextNetworkRetry(); + return nextState; + } + + if(!_certForCSR){ + return CSRHandlerStates::BUILD_CSR; + } + + String csr = _certForCSR->getCSRPEM(); + csr.replace("\n", "\\n"); + + String PostData = "{\"csr\":\""; + PostData += csr; + PostData += "\"}"; + DEBUG_INFO("CSRH Downloading certificate..."); + + if(postRequest("/provisioning/v1/onboarding/provision/csr", PostData)){ + nextState = CSRHandlerStates::WAITING_RESPONSE; + } else { + updateNextRequestAt(); + DEBUG_WARNING("CSRH::%s Failed sending request, retrying in %d ms", __FUNCTION__, _nextRequestAt - millis()); + } + + return nextState; +} + +CSRHandlerClass::CSRHandlerStates CSRHandlerClass::handleWaitingResponse() { + CSRHandlerStates nextState = _state; + NetworkConnectionState connectionRes = _connectionHandler->check(); + if (connectionRes != NetworkConnectionState::CONNECTED) { + nextNetworkRetry(); + _client->stop(); + return CSRHandlerStates::REQUEST_SIGNATURE; + } + + if (millis() - _startWaitingResponse > RESPONSE_TIMEOUT) { + _client->stop(); + updateNextRequestAt(); + DEBUG_WARNING("CSRH::%s CSR request timeout, retrying in %d ms", __FUNCTION__, _nextRequestAt - millis()); + nextState = CSRHandlerStates::REQUEST_SIGNATURE; + } + + + int statusCode = _client->responseStatusCode(); + if(statusCode == 200){ + nextState = CSRHandlerStates::PARSE_RESPONSE; + } else { + _client->stop(); + updateNextRequestAt(); + DEBUG_WARNING("CSRH::%s CSR request error code %d, retrying in %d ms", __FUNCTION__, statusCode ,_nextRequestAt - millis()); + nextState = CSRHandlerStates::REQUEST_SIGNATURE; + } + + return nextState; +} + +CSRHandlerClass::CSRHandlerStates CSRHandlerClass::handleParseResponse() { + String certResponse = _client->responseBody(); + _client->stop(); + + /* Parse the response in format: + * device_id|authority_key_identifier|not_before|serial|signature_asn1_x|signature_asn1_y + */ + char *response = (char *)certResponse.c_str(); + char *token[6]; + int i = 1; + token[0] = strtok(response, "|"); + for (; i < 6; i++) { + char *tok = strtok(NULL, "|"); + if(tok == NULL){ + break; + } + token[i] = tok; + } + + if(i < 6 || strlen(token[0]) != 36 || strlen(token[1]) != 40 + || strlen(token[2]) < 10 || strlen(token[3]) != 32 + || strlen(token[4]) != 64 || strlen(token[5]) != 64 + || sscanf(token[2], "%4d-%2d-%2dT%2d", &_issueYear, &_issueMonth, &_issueDay, &_issueHour) != 4){ + updateNextRequestAt(); + DEBUG_ERROR("CSRH::%s Error parsing response, retrying in %d ms", __FUNCTION__, _nextRequestAt - millis()); + return CSRHandlerStates::REQUEST_SIGNATURE; + } + + _deviceId = token[0]; + hex::decode(token[1], _authorityKeyIdentifier, sizeof(_authorityKeyIdentifier)); + hex::decode(token[3], _serialNumber, sizeof(_serialNumber)); + hex::decode(token[4], _signature, sizeof(_signature)); + hex::decode(token[5], &_signature[32], sizeof(_signature) - 32); + + return CSRHandlerStates::BUILD_CERTIFICATE; +} + +CSRHandlerClass::CSRHandlerStates CSRHandlerClass::handleBuildCertificate() { + int expireYears = 31; + + if (!SElementArduinoCloudDeviceId::write(*_secureElement, _deviceId, SElementArduinoCloudSlot::DeviceId)) { + DEBUG_ERROR("CSRH::%s Error storing device id!", __FUNCTION__); + _ledFeedback.setMode(LEDFeedbackClass::LEDFeedbackMode::ERROR); + return CSRHandlerStates::ERROR; + } + + ECP256Certificate cert; + cert.begin(); + + cert.setSubjectCommonName(_deviceId); + cert.setIssuerCountryName("US"); + cert.setIssuerOrganizationName("Arduino LLC US"); + cert.setIssuerOrganizationalUnitName("IT"); + cert.setIssuerCommonName("Arduino"); + cert.setSignature(_signature, sizeof(_signature)); + cert.setAuthorityKeyId(_authorityKeyIdentifier, sizeof(_authorityKeyIdentifier)); + cert.setSerialNumber(_serialNumber, sizeof(_serialNumber)); + cert.setIssueYear(_issueYear); + cert.setIssueMonth(_issueMonth); + cert.setIssueDay(_issueDay); + cert.setIssueHour(_issueHour); + cert.setExpireYears(expireYears); + + if (!SElementArduinoCloudCertificate::build(*_secureElement, cert, static_cast(SElementArduinoCloudSlot::Key))) { + DEBUG_ERROR("CSRH::%s Error building secureElement compressed cert!", __FUNCTION__); + _ledFeedback.setMode(LEDFeedbackClass::LEDFeedbackMode::ERROR); + return CSRHandlerStates::ERROR; + } + + if (!SElementArduinoCloudCertificate::write(*_secureElement, cert, SElementArduinoCloudSlot::CompressedCertificate)) { + DEBUG_ERROR("CSRH::%s Error storing cert!" , __FUNCTION__); + _ledFeedback.setMode(LEDFeedbackClass::LEDFeedbackMode::ERROR); + return CSRHandlerStates::ERROR; + } + + DEBUG_INFO("CSRH Certificate created!"); + _nextRequestAt = 0; + _requestAttempt = 0; + return CSRHandlerStates::CERT_CREATED; +} + +CSRHandlerClass::CSRHandlerStates CSRHandlerClass::handleCertCreated() { + CSRHandlerStates nextState = _state; + + if(millis() < _nextRequestAt) { + return nextState; + } + + NetworkConnectionState connectionRes = _connectionHandler->check(); + if (connectionRes != NetworkConnectionState::CONNECTED) { + nextNetworkRetry(); + return nextState; + } + + String PostData = "{\"wifi_fw_version\":\""; + PostData += _fw_version; + PostData += "\"}"; + if(postRequest("/provisioning/v1/onboarding/provision/complete", PostData)){ + nextState = CSRHandlerStates::WAITING_COMPLETE_RES; + } else { + updateNextRequestAt(); + DEBUG_WARNING("CSRH::%s Error sending complete request, retrying in %d ms", __FUNCTION__, _nextRequestAt - millis()); + } + + return nextState; +} + +CSRHandlerClass::CSRHandlerStates CSRHandlerClass::handleWaitingCompleteRes() { + CSRHandlerStates nextState = _state; + NetworkConnectionState connectionRes = _connectionHandler->check(); + if (connectionRes != NetworkConnectionState::CONNECTED) { + nextNetworkRetry(); + _client->stop(); + return CSRHandlerStates::CERT_CREATED; + } + + if (millis() - _startWaitingResponse > RESPONSE_TIMEOUT) { + _client->stop(); + updateNextRequestAt(); + DEBUG_WARNING("CSRH::%s Complete request timeout, retrying in %d ms", __FUNCTION__, _nextRequestAt - millis()); + nextState = CSRHandlerStates::CERT_CREATED; + } + + int statusCode = _client->responseStatusCode(); + if(statusCode == 200){ + if (_certForCSR) { + delete _certForCSR; + _certForCSR = nullptr; + } + DEBUG_INFO("CSRH Provisioning completed!"); + nextState = CSRHandlerStates::COMPLETED; + } else if (statusCode == 429 || statusCode == 503) { + updateNextRequestAt(); + nextState = CSRHandlerStates::CERT_CREATED; + } else { + DEBUG_WARNING("CSRH::%s Complete request error code %d, retrying in %d ms", __FUNCTION__, statusCode ,_nextRequestAt - millis()); + _requestAttempt = 0; + _nextRequestAt = 0; + nextState = CSRHandlerStates::REQUEST_SIGNATURE; + } + _client->stop(); + + return nextState; +} + +void CSRHandlerClass::nextNetworkRetry() { + _nextRequestAt = millis() + CONNECTION_RETRY_TIMEOUT_MS; +} + +void CSRHandlerClass::handleError() { + _ledFeedback.update(); +} diff --git a/examples/utility/Provisioning_2.0/CSRHandler.h b/examples/utility/Provisioning_2.0/CSRHandler.h new file mode 100644 index 000000000..1165ac05b --- /dev/null +++ b/examples/utility/Provisioning_2.0/CSRHandler.h @@ -0,0 +1,74 @@ +/* + 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 +#include +#include "Utility/LEDFeedback/LEDFeedback.h" +#define JITTER_BASE 0 +#define JITTER_MAX 1000 + +class CSRHandlerClass { +public: + CSRHandlerClass(); + ~CSRHandlerClass(); + enum class CSRHandlerStates { + BUILD_CSR, + REQUEST_SIGNATURE, + WAITING_RESPONSE, + PARSE_RESPONSE, + BUILD_CERTIFICATE, + CERT_CREATED, + WAITING_COMPLETE_RES, + COMPLETED, + ERROR, + END + }; + bool begin(ConnectionHandler &connectionHandler, SecureElement &secureElement, String &uhwid); + void end(); + CSRHandlerStates poll(); +private: + CSRHandlerStates _state; + unsigned long _nextRequestAt; + uint32_t _requestAttempt; + uint32_t _startWaitingResponse; + String *_uhwid; + String _fw_version; + + int _issueYear; + uint8_t _issueMonth; + uint8_t _issueDay; + uint8_t _issueHour; + byte _serialNumber[16]; + byte _authorityKeyIdentifier[20]; + byte _signature[64]; + String _deviceId; + + ECP256Certificate *_certForCSR; + ConnectionHandler *_connectionHandler; + SecureElement *_secureElement; + TLSClientMqtt *_tlsClient; + HttpClient *_client; + LEDFeedbackClass &_ledFeedback; + void updateNextRequestAt(); + void nextNetworkRetry(); + uint32_t jitter(uint32_t base = JITTER_BASE, uint32_t max = JITTER_MAX); + bool postRequest(const char *url, String &postData); + uint32_t getTimestamp(); + CSRHandlerStates handleBuildCSR(); + CSRHandlerStates handleRequestSignature(); + CSRHandlerStates handleWaitingResponse(); + CSRHandlerStates handleParseResponse(); + CSRHandlerStates handleBuildCertificate(); + CSRHandlerStates handleCertCreated(); + CSRHandlerStates handleWaitingCompleteRes(); + void handleError(); +}; diff --git a/examples/utility/Provisioning_2.0/ClaimingHandler.cpp b/examples/utility/Provisioning_2.0/ClaimingHandler.cpp new file mode 100644 index 000000000..3e794300d --- /dev/null +++ b/examples/utility/Provisioning_2.0/ClaimingHandler.cpp @@ -0,0 +1,173 @@ +/* + 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 "ClaimingHandler.h" +#include +#include "Arduino_DebugUtils.h" +#include +#include "utility/HCI.h" +#include + +ClaimingHandlerClass::ClaimingHandlerClass(): + _uhwid {nullptr}, + _state {ClaimingHandlerStates::END}, + _secureElement {nullptr}, + _clearStoredCredentials {nullptr}, + _agentManager { AgentsManagerClass::getInstance()}, + _ledFeedback {LEDFeedbackClass::getInstance()} { + _receivedEvent = ClaimingReqEvents::NONE; + _ts = 0; +} + +bool ClaimingHandlerClass::begin(SecureElement &secureElement, String &uhwid, ClearStoredCredentialsHandler clearStoredCredentials) { + if(_state != ClaimingHandlerStates::END) { + return true; + } + + if(uhwid == "" || clearStoredCredentials == nullptr) { + return false; + } + + if (!_agentManager.addRequestHandler(RequestType::GET_ID, getIdRequestCb)) { + return false; + } + + if (!_agentManager.addRequestHandler(RequestType::RESET, resetStoredCredRequestCb)) { + return false; + } + + if(!_agentManager.addRequestHandler(RequestType::GET_BLE_MAC_ADDRESS, getBLEMacAddressRequestCb)) { + return false; + } + + if (!_agentManager.addReturnTimestampCallback(setTimestamp)) { + return false; + } + + _agentManager.begin(); + _uhwid = &uhwid; + _secureElement = &secureElement; + _clearStoredCredentials = clearStoredCredentials; + _state = ClaimingHandlerStates::INIT; +} + +void ClaimingHandlerClass::end() { + if(_state == ClaimingHandlerStates::END) { + return; + } + + _agentManager.removeReturnTimestampCallback(); + _agentManager.removeRequestHandler(RequestType::GET_ID); + _agentManager.removeRequestHandler(RequestType::RESET); + _agentManager.end(); + _state = ClaimingHandlerStates::END; +} + +void ClaimingHandlerClass::poll() { + if(_state == ClaimingHandlerStates::END) { + return; + } + _ledFeedback.update(); + _agentManager.update(); + + switch (_receivedEvent) { + case ClaimingReqEvents::GET_ID: getIdReqHandler (); break; + case ClaimingReqEvents::RESET: resetStoredCredReqHandler (); break; + case ClaimingReqEvents::GET_BLE_MAC_ADDRESS: getBLEMacAddressReqHandler(); break; + } + _receivedEvent = ClaimingReqEvents::NONE; + return; +} + +void ClaimingHandlerClass::getIdReqHandler() { + if (_ts != 0) { + byte _uhwidBytes[32]; + hex::decode(_uhwid->c_str(), _uhwidBytes, _uhwid->length()); + //Send UHWID + ProvisioningOutputMessage idMsg = {MessageOutputType::UHWID}; + idMsg.m.uhwid = _uhwidBytes; + _agentManager.sendMsg(idMsg); + + String token = getAIoTCloudJWT(*_secureElement, *_uhwid, _ts, 1); + if (token == "") { + DEBUG_ERROR("CH::%s Error: token not created", __FUNCTION__); + sendStatus(StatusMessage::ERROR); + return; + } + + //Send JWT + ProvisioningOutputMessage jwtMsg = {MessageOutputType::JWT}; + jwtMsg.m.jwt = token.c_str(); + _agentManager.sendMsg(jwtMsg); + _ts = 0; + } else { + DEBUG_ERROR("CH::%s Error: timestamp not provided" , __FUNCTION__); + sendStatus(StatusMessage::PARAMS_NOT_FOUND); + } +} + +void ClaimingHandlerClass::resetStoredCredReqHandler() { + if( !_clearStoredCredentials()){ + DEBUG_ERROR("CH::%s Error: reset stored credentials failed", __FUNCTION__); + sendStatus(StatusMessage::ERROR); + } else { + sendStatus(StatusMessage::RESET_COMPLETED); + } + +} + +void ClaimingHandlerClass::getBLEMacAddressReqHandler() { + uint8_t mac[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + bool activated = false; + ConfiguratorAgent * connectedAgent = _agentManager.getConnectedAgent(); + if(!_agentManager.isAgentEnabled(ConfiguratorAgent::AgentTypes::BLE) || (connectedAgent != nullptr && + connectedAgent->getAgentType() != ConfiguratorAgent::AgentTypes::BLE)) { + activated = true; + BLE.begin(); + } + + HCI.readBdAddr(mac); + + for(int i = 0; i < 3; i++){ + uint8_t byte = mac[i]; + mac[i] = mac[5-i]; + mac[5-i] = byte; + } + if (activated) { + BLE.end(); + } + + ProvisioningOutputMessage outputMsg; + outputMsg.type = MessageOutputType::BLE_MAC_ADDRESS; + outputMsg.m.BLEMacAddress = mac; + _agentManager.sendMsg(outputMsg); +} + +void ClaimingHandlerClass::getIdRequestCb() { + DEBUG_VERBOSE("CH Get ID request received"); + _receivedEvent = ClaimingReqEvents::GET_ID; +} +void ClaimingHandlerClass::setTimestamp(uint64_t ts) { + _ts = ts; +} + +void ClaimingHandlerClass::resetStoredCredRequestCb() { + DEBUG_VERBOSE("CH Reset stored credentials request received"); + _receivedEvent = ClaimingReqEvents::RESET; +} + +void ClaimingHandlerClass::getBLEMacAddressRequestCb() { + DEBUG_VERBOSE("CH Get BLE MAC address request received"); + _receivedEvent = ClaimingReqEvents::GET_BLE_MAC_ADDRESS; +} + +bool ClaimingHandlerClass::sendStatus(StatusMessage msg) { + ProvisioningOutputMessage statusMsg = { MessageOutputType::STATUS, { msg } }; + return _agentManager.sendMsg(statusMsg); +} diff --git a/examples/utility/Provisioning_2.0/ClaimingHandler.h b/examples/utility/Provisioning_2.0/ClaimingHandler.h new file mode 100644 index 000000000..7229b47c0 --- /dev/null +++ b/examples/utility/Provisioning_2.0/ClaimingHandler.h @@ -0,0 +1,50 @@ +/* + 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 "Arduino.h" +#include "ConfiguratorAgents/AgentsManager.h" +#include +#include "Utility/LEDFeedback/LEDFeedback.h" + +typedef bool (*ClearStoredCredentialsHandler)(); +class ClaimingHandlerClass { +public: + ClaimingHandlerClass(); + bool begin(SecureElement &secureElement, String &uhwid, ClearStoredCredentialsHandler clearStoredCredentials); + void end(); + void poll(); +private: + String *_uhwid; + enum class ClaimingHandlerStates { + INIT, + END + }; + enum class ClaimingReqEvents { NONE, + GET_ID, + RESET, + GET_BLE_MAC_ADDRESS }; + static inline ClaimingReqEvents _receivedEvent; + ClaimingHandlerStates _state; + AgentsManagerClass &_agentManager; + LEDFeedbackClass &_ledFeedback; + static inline uint64_t _ts; + SecureElement *_secureElement; + + bool sendStatus(StatusMessage msg); + /* Commands handlers */ + void getIdReqHandler(); + void resetStoredCredReqHandler(); + void getBLEMacAddressReqHandler(); + ClearStoredCredentialsHandler _clearStoredCredentials; + /* Callbacks for receiving commands */ + static void getIdRequestCb(); + static void setTimestamp(uint64_t ts); + static void resetStoredCredRequestCb(); + static void getBLEMacAddressRequestCb(); +}; diff --git a/examples/utility/Provisioning_2.0/Provisioning_2.0.ino b/examples/utility/Provisioning_2.0/Provisioning_2.0.ino new file mode 100644 index 000000000..5cc612e8f --- /dev/null +++ b/examples/utility/Provisioning_2.0/Provisioning_2.0.ino @@ -0,0 +1,222 @@ +/* + 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 "thingProperties.h" +#include "CSRHandler.h" +#include "ClaimingHandler.h" +#include "SecretsHelper.h" +#include +#include +#include +#include +#include "Utility/LEDFeedback/LEDFeedback.h" + +enum class DeviceState { + HARDWARE_CHECK, + BEGIN, + NETWORK_CONFIG, + CSR, + BEGIN_CLOUD, + RUN, + ERROR + }; + +DeviceState _state = DeviceState::HARDWARE_CHECK; +SecureElement secureElement; + +String uhwid = ""; +bool resetEvent = false; + +CSRHandlerClass CSRHandler; +ClaimingHandlerClass ClaimingHandler; + +bool clearStoredCredentials() { + const uint8_t empty[4] = {0x00,0x00,0x00,0x00}; + if(!NetworkConfigurator.resetStoredConfiguration() || \ + !secureElement.writeSlot(static_cast(SElementArduinoCloudSlot::DeviceId), (byte*)empty, sizeof(empty)) || \ + !secureElement.writeSlot(static_cast(SElementArduinoCloudSlot::CompressedCertificate), (byte*)empty, sizeof(empty))) { + return false; + } + + ArduinoCloud.disconnect(); + resetEvent = true; + return true; + } + +void setup() { + Serial.begin(9600); + + delay(1500); + + setDebugMessageLevel(4); + + initProperties(); + AgentsManagerClass::getInstance().begin(); + LEDFeedbackClass::getInstance().begin(); + DEBUG_INFO("Starting Provisioning"); +} + +void sendStatus(StatusMessage msg) { + ProvisioningOutputMessage outMsg = { MessageOutputType::STATUS, { msg } }; + AgentsManagerClass::getInstance().sendMsg(outMsg); +} + +DeviceState handleHardwareCheck() { + // Init the secure element + if(!secureElement.begin()) { + DEBUG_ERROR("Sketch: Error during secureElement begin!"); + LEDFeedbackClass::getInstance().setMode(LEDFeedbackClass::LEDFeedbackMode::ERROR); + sendStatus(StatusMessage::HW_ERROR_SE_BEGIN); + return DeviceState::ERROR; + } + + if (!secureElement.locked()) { + if (!secureElement.writeConfiguration()) { + DEBUG_ERROR("Sketch: Writing secureElement configuration failed!"); + LEDFeedbackClass::getInstance().setMode(LEDFeedbackClass::LEDFeedbackMode::ERROR); + sendStatus(StatusMessage::HW_ERROR_SE_CONFIG); + return DeviceState::ERROR; + } + + if (!secureElement.lock()) { + DEBUG_ERROR("Sketch: Locking secureElement configuration failed!"); + LEDFeedbackClass::getInstance().setMode(LEDFeedbackClass::LEDFeedbackMode::ERROR); + sendStatus(StatusMessage::HW_ERROR_SE_LOCK); + return DeviceState::ERROR; + } + DEBUG_INFO("secureElement locked successfully"); + } + + FlashFormatter flashFormatter; + // Check if the board storage is properly formatted + if(!flashFormatter.checkandFormatPartition()) { + DEBUG_ERROR("Sketch: Error partitioning storage"); + LEDFeedbackClass::getInstance().setMode(LEDFeedbackClass::LEDFeedbackMode::ERROR); + sendStatus(StatusMessage::FAIL_TO_PARTITION_STORAGE); + return DeviceState::ERROR; + } + + return DeviceState::BEGIN; +} + +DeviceState handleBegin() { + uhwid = GetUHWID(); + if(uhwid == ""){ + DEBUG_ERROR("Sketch: Error getting UHWID"); + LEDFeedbackClass::getInstance().setMode(LEDFeedbackClass::LEDFeedbackMode::ERROR); + sendStatus(StatusMessage::ERROR_GENERATING_UHWID); + return DeviceState::ERROR; + } + // Scan the network options + NetworkConfigurator.scanNetworkOptions(); + NetworkConfigurator.begin(); + ClaimingHandler.begin(secureElement, uhwid, clearStoredCredentials); + DEBUG_INFO("BLE Available"); + return DeviceState::NETWORK_CONFIG; +} + +DeviceState handleNetworkConfig() { + ClaimingHandler.poll(); + if(resetEvent){ + resetEvent = false; + } + NetworkConfiguratorStates s = NetworkConfigurator.update(); + + DeviceState nextState = _state; + if (s == NetworkConfiguratorStates::CONFIGURED) { + String deviceId = ""; + SElementArduinoCloudDeviceId::read(secureElement, deviceId, SElementArduinoCloudSlot::DeviceId); + + if (deviceId == "") { + CSRHandler.begin(ArduinoIoTPreferredConnection, secureElement, uhwid); + nextState = DeviceState::CSR; + } else { + nextState = DeviceState::BEGIN_CLOUD; + } + } + return nextState; +} + +DeviceState handleCSR() { + NetworkConfigurator.update(); + ClaimingHandler.poll(); + if(resetEvent) { + resetEvent = false; + CSRHandler.end(); + return DeviceState::NETWORK_CONFIG; + } + + DeviceState nextState = _state; + + CSRHandlerClass::CSRHandlerStates res = CSRHandler.poll(); + if (res == CSRHandlerClass::CSRHandlerStates::COMPLETED) { + CSRHandler.end(); + nextState = DeviceState::BEGIN_CLOUD; + } + + return nextState; +} + +DeviceState handleBeginCloud() { + // Close the connection to the peer (App mobile, FE, etc) + NetworkConfigurator.disconnectAgent(); + // Close the BLE connectivity + if (NetworkConfigurator.isAgentEnabled(ConfiguratorAgent::AgentTypes::BLE)) { + NetworkConfigurator.enableAgent(ConfiguratorAgent::AgentTypes::BLE, false); + } + // Connect to Arduino IoT Cloud + ArduinoCloud.begin(ArduinoIoTPreferredConnection); + ArduinoCloud.printDebugInfo(); + + return DeviceState::RUN; +} + +void cloudConnectedHandler(bool connected) { + static bool _status = false; + if(connected != _status){ + _status = connected; + if(connected){ + LEDFeedbackClass::getInstance().setMode(LEDFeedbackClass::LEDFeedbackMode::CONNECTED_TO_CLOUD); + } else { + LEDFeedbackClass::getInstance().setMode(LEDFeedbackClass::LEDFeedbackMode::NONE); + } + } +} + +DeviceState handleRun() { + ClaimingHandler.poll(); + if(resetEvent) { + resetEvent = false; + return DeviceState::NETWORK_CONFIG; + } + + DeviceState nextState = _state; + ArduinoCloud.update(); + + cloudConnectedHandler(ArduinoCloud.connected()); + + return nextState; +} + +DeviceState handleError() { + LEDFeedbackClass::getInstance().update(); + AgentsManagerClass::getInstance().update(); + return DeviceState::ERROR; +} + +void loop() { + switch (_state) { + case DeviceState::HARDWARE_CHECK: _state = handleHardwareCheck(); break; + case DeviceState::BEGIN: _state = handleBegin (); break; + case DeviceState::NETWORK_CONFIG : _state = handleNetworkConfig(); break; + case DeviceState::CSR: _state = handleCSR (); break; + case DeviceState::BEGIN_CLOUD: _state = handleBeginCloud (); break; + case DeviceState::RUN: _state = handleRun (); break; + case DeviceState::ERROR: _state = handleError (); break; + default: break; + } +} diff --git a/examples/utility/Provisioning_2.0/SecretsHelper.h b/examples/utility/Provisioning_2.0/SecretsHelper.h new file mode 100644 index 000000000..bdb6354d1 --- /dev/null +++ b/examples/utility/Provisioning_2.0/SecretsHelper.h @@ -0,0 +1,20 @@ +/* + 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 + +inline String GetUHWID() { + UniqueHWId Id; + if (Id.begin()) { + return Id.get(); + } + return ""; +} diff --git a/examples/utility/Provisioning_2.0/thingProperties.h b/examples/utility/Provisioning_2.0/thingProperties.h new file mode 100644 index 000000000..0bdc6c85f --- /dev/null +++ b/examples/utility/Provisioning_2.0/thingProperties.h @@ -0,0 +1,33 @@ +/* + 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/. +*/ +#if defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) +#error "Board not supported for Provisioning 2.0" +#endif + +#include +#include +#include +#include "NetworkConfigurator.h" +#include "ConfiguratorAgents/agents/BLE/BLEAgent.h" +#include "ConfiguratorAgents/agents/Serial/SerialAgent.h" + +GenericConnectionHandler ArduinoIoTPreferredConnection; +KVStore kvStore; +BLEAgentClass BLEAgent; +SerialAgentClass SerialAgent; +NetworkConfiguratorClass NetworkConfigurator(ArduinoIoTPreferredConnection); + +void initProperties() { + + NetworkConfigurator.addAgent(BLEAgent); + NetworkConfigurator.addAgent(SerialAgent); + NetworkConfigurator.setStorage(kvStore); + ArduinoCloud.setConfigurator(NetworkConfigurator); +} + + diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index deecd3ea4..2f2f67770 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -190,7 +190,7 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #if NETWORK_CONFIGURATOR_ENABLED if(_configurator != nullptr){ - _configurator->enableBLE(false); + _configurator->enableAgent(ConfiguratorAgent::AgentTypes::BLE,false); _configurator->begin(); } #endif From b36f3ec8db0257b2d87c50e6dc3cb35fcbb66361 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Wed, 2 Apr 2025 17:53:51 +0200 Subject: [PATCH 04/14] rename NetworkConfigurator.h into Arduino_NetworkConfigurator.h --- examples/utility/Provisioning_2.0/thingProperties.h | 1 - src/ArduinoIoTCloud.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/utility/Provisioning_2.0/thingProperties.h b/examples/utility/Provisioning_2.0/thingProperties.h index 0bdc6c85f..d2127c693 100644 --- a/examples/utility/Provisioning_2.0/thingProperties.h +++ b/examples/utility/Provisioning_2.0/thingProperties.h @@ -12,7 +12,6 @@ #include #include #include -#include "NetworkConfigurator.h" #include "ConfiguratorAgents/agents/BLE/BLEAgent.h" #include "ConfiguratorAgents/agents/Serial/SerialAgent.h" diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index 4512e9a6d..16e07d1c7 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -26,7 +26,7 @@ #include #if NETWORK_CONFIGURATOR_ENABLED -#include +#include #endif #if defined(DEBUG_ERROR) || defined(DEBUG_WARNING) || defined(DEBUG_INFO) || defined(DEBUG_DEBUG) || defined(DEBUG_VERBOSE) From 3f5419f75455a87ab69bb47c936f4b5db41500ea Mon Sep 17 00:00:00 2001 From: fabik111 Date: Tue, 8 Apr 2025 15:11:30 +0200 Subject: [PATCH 05/14] update test --- .github/workflows/compile-examples.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 794a90077..4123bf35b 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -188,7 +188,8 @@ jobs: - name: ArduinoECCX08 - name: Blues Wireless Notecard - name: RTCZero - - name: MKRNB + - source-url: https://github.com/fabik111/MKRNB + version: f514c2a497b80a1f1992f62156f4ba12569db464 - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | - examples/ArduinoIoTCloud-Notecard From 43b3ae4ccde629ddef310978f0ccf19fe2fb1ac9 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Fri, 11 Apr 2025 11:45:18 +0200 Subject: [PATCH 06/14] add GET_PROVISIONING_SKETCH_VERSION command --- .../Provisioning_2.0/ClaimingHandler.cpp | 25 ++++++++++++++++--- .../Provisioning_2.0/ClaimingHandler.h | 5 +++- .../Provisioning_2.0/Provisioning_2.0.ino | 2 ++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/examples/utility/Provisioning_2.0/ClaimingHandler.cpp b/examples/utility/Provisioning_2.0/ClaimingHandler.cpp index 3e794300d..7456f410b 100644 --- a/examples/utility/Provisioning_2.0/ClaimingHandler.cpp +++ b/examples/utility/Provisioning_2.0/ClaimingHandler.cpp @@ -13,6 +13,8 @@ #include "utility/HCI.h" #include +extern const char *SKETCH_VERSION; + ClaimingHandlerClass::ClaimingHandlerClass(): _uhwid {nullptr}, _state {ClaimingHandlerStates::END}, @@ -45,6 +47,10 @@ bool ClaimingHandlerClass::begin(SecureElement &secureElement, String &uhwid, Cl return false; } + if(!_agentManager.addRequestHandler(RequestType::GET_PROVISIONING_SKETCH_VERSION, getProvSketchVersionRequestCb)) { + return false; + } + if (!_agentManager.addReturnTimestampCallback(setTimestamp)) { return false; } @@ -76,9 +82,10 @@ void ClaimingHandlerClass::poll() { _agentManager.update(); switch (_receivedEvent) { - case ClaimingReqEvents::GET_ID: getIdReqHandler (); break; - case ClaimingReqEvents::RESET: resetStoredCredReqHandler (); break; - case ClaimingReqEvents::GET_BLE_MAC_ADDRESS: getBLEMacAddressReqHandler(); break; + case ClaimingReqEvents::GET_ID: getIdReqHandler (); break; + case ClaimingReqEvents::RESET: resetStoredCredReqHandler (); break; + case ClaimingReqEvents::GET_BLE_MAC_ADDRESS: getBLEMacAddressReqHandler (); break; + case ClaimingReqEvents::GET_PROV_SKETCH_VERSION: getProvSketchVersionReqHandler(); break; } _receivedEvent = ClaimingReqEvents::NONE; return; @@ -149,6 +156,13 @@ void ClaimingHandlerClass::getBLEMacAddressReqHandler() { _agentManager.sendMsg(outputMsg); } +void ClaimingHandlerClass::getProvSketchVersionReqHandler() { + ProvisioningOutputMessage outputMsg; + outputMsg.type = MessageOutputType::PROV_SKETCH_VERSION; + outputMsg.m.provSketchVersion = SKETCH_VERSION; + _agentManager.sendMsg(outputMsg); +} + void ClaimingHandlerClass::getIdRequestCb() { DEBUG_VERBOSE("CH Get ID request received"); _receivedEvent = ClaimingReqEvents::GET_ID; @@ -167,6 +181,11 @@ void ClaimingHandlerClass::getBLEMacAddressRequestCb() { _receivedEvent = ClaimingReqEvents::GET_BLE_MAC_ADDRESS; } +void ClaimingHandlerClass::getProvSketchVersionRequestCb() { + DEBUG_VERBOSE("CH Get provisioning sketch version request received"); + _receivedEvent = ClaimingReqEvents::GET_PROV_SKETCH_VERSION; +} + bool ClaimingHandlerClass::sendStatus(StatusMessage msg) { ProvisioningOutputMessage statusMsg = { MessageOutputType::STATUS, { msg } }; return _agentManager.sendMsg(statusMsg); diff --git a/examples/utility/Provisioning_2.0/ClaimingHandler.h b/examples/utility/Provisioning_2.0/ClaimingHandler.h index 7229b47c0..fc6a2605e 100644 --- a/examples/utility/Provisioning_2.0/ClaimingHandler.h +++ b/examples/utility/Provisioning_2.0/ClaimingHandler.h @@ -28,7 +28,8 @@ class ClaimingHandlerClass { enum class ClaimingReqEvents { NONE, GET_ID, RESET, - GET_BLE_MAC_ADDRESS }; + GET_BLE_MAC_ADDRESS, + GET_PROV_SKETCH_VERSION}; static inline ClaimingReqEvents _receivedEvent; ClaimingHandlerStates _state; AgentsManagerClass &_agentManager; @@ -41,10 +42,12 @@ class ClaimingHandlerClass { void getIdReqHandler(); void resetStoredCredReqHandler(); void getBLEMacAddressReqHandler(); + void getProvSketchVersionReqHandler(); ClearStoredCredentialsHandler _clearStoredCredentials; /* Callbacks for receiving commands */ static void getIdRequestCb(); static void setTimestamp(uint64_t ts); static void resetStoredCredRequestCb(); static void getBLEMacAddressRequestCb(); + static void getProvSketchVersionRequestCb(); }; diff --git a/examples/utility/Provisioning_2.0/Provisioning_2.0.ino b/examples/utility/Provisioning_2.0/Provisioning_2.0.ino index 5cc612e8f..14fc3aecc 100644 --- a/examples/utility/Provisioning_2.0/Provisioning_2.0.ino +++ b/examples/utility/Provisioning_2.0/Provisioning_2.0.ino @@ -15,6 +15,8 @@ #include #include "Utility/LEDFeedback/LEDFeedback.h" +const char *SKETCH_VERSION = "0.1.0"; + enum class DeviceState { HARDWARE_CHECK, BEGIN, From a8ad0e2f91d99e43f6f243a74d678ba45b3196e8 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 14 Apr 2025 11:10:16 +0200 Subject: [PATCH 07/14] compile-examples: save provisioning binary as artifact --- .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 4123bf35b..9541fb6bf 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -368,6 +368,9 @@ jobs: ${{ matrix.sketch-paths }} enable-deltas-report: "true" sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} + cli-compile-flags: | + - --output-dir + - ${{ runner.temp }}/arduino-cli-output - name: Write data to size trends report spreadsheet # Update report on every push to the master branch @@ -384,3 +387,10 @@ jobs: with: name: sketches-report-${{ matrix.board.artifact-name-suffix }} path: ${{ env.SKETCHES_REPORTS_PATH }} + + - name: Save build artifact + if: github.event_name == 'pull_request' + uses: actions/upload-artifact@v4 + with: + name: provisioning-${{ matrix.board.artifact-name-suffix }} + path: ${{ runner.temp }}/arduino-cli-output/Provisioning* From 9d58d9dbc8814b725b88adbc024becc8ceeb203b Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 14 Apr 2025 15:17:33 +0200 Subject: [PATCH 08/14] update compile ci --- .github/workflows/compile-examples.yml | 15 ++++++++------- .../ArduinoIoTCloud-NetConfig/thingProperties.h | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 9541fb6bf..d2839b11a 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -22,9 +22,8 @@ jobs: # Install the ArduinoIoTCloud library from the repository - source-path: ./ - source-url: https://github.com/fabik111/Arduino_ConnectionHandler.git - version: e8539870f2f8b7936f3126070b45055c38856bb1 - - source-url: https://github.com/fabik111/ArduinoBLE.git - version: 82e2a28f871e97b313846cee6d9efed8943dca53 + version: 0314cf54593029aea05bb8c179e40a26128f7d67 + - name: ArduinoBLE - name: ArduinoHttpClient - name: Arduino_DebugUtils - name: ArduinoMqttClient @@ -136,7 +135,7 @@ jobs: - name: Blues Wireless Notecard - name: RTCZero - source-url: https://github.com/andreagilardoni/WiFiNINA.git - version: ca7a9224f86b9aaf00de4f7feccea583a23b3d53 + version: 31616ac5a30f6281c68f982bc39800771b2fbaeb - name: Arduino_JSON - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | @@ -188,8 +187,7 @@ jobs: - name: ArduinoECCX08 - name: Blues Wireless Notecard - name: RTCZero - - source-url: https://github.com/fabik111/MKRNB - version: f514c2a497b80a1f1992f62156f4ba12569db464 + - name: MKRNB - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git sketch-paths: | - examples/ArduinoIoTCloud-Notecard @@ -221,6 +219,7 @@ jobs: - name: arduino:mbed_nicla libraries: | - name: Blues Wireless Notecard + - name: ArduinoECCX08 sketch-paths: | - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-DeferredOTA @@ -271,6 +270,7 @@ jobs: libraries: | - name: Arduino_Cellular - name: Blues Wireless Notecard + - name: ArduinoECCX08 sketch-paths: | - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-Notecard @@ -285,6 +285,7 @@ jobs: - name: arduino:renesas_uno libraries: | - name: Blues Wireless Notecard + - name: ArduinoECCX08 sketch-paths: | - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-Notecard @@ -393,4 +394,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: provisioning-${{ matrix.board.artifact-name-suffix }} - path: ${{ runner.temp }}/arduino-cli-output/Provisioning* + path: ${{ runner.temp }}/arduino-cli-output/Provisioning_2.0* diff --git a/examples/ArduinoIoTCloud-NetConfig/thingProperties.h b/examples/ArduinoIoTCloud-NetConfig/thingProperties.h index 833927042..ce3e17a39 100644 --- a/examples/ArduinoIoTCloud-NetConfig/thingProperties.h +++ b/examples/ArduinoIoTCloud-NetConfig/thingProperties.h @@ -5,6 +5,7 @@ #endif #include #include +#include #include "ConfiguratorAgents/agents/BLE/BLEAgent.h" #include "ConfiguratorAgents/agents/Serial/SerialAgent.h" From 51edc23d48b484262081e5e62ec22969cd2a4697 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Tue, 15 Apr 2025 10:40:22 +0200 Subject: [PATCH 09/14] add define for compile with test env --- examples/utility/Provisioning_2.0/CSRHandler.cpp | 4 ++++ examples/utility/Provisioning_2.0/Provisioning_2.0.ino | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/examples/utility/Provisioning_2.0/CSRHandler.cpp b/examples/utility/Provisioning_2.0/CSRHandler.cpp index 4f7649fb7..1a6101e4b 100644 --- a/examples/utility/Provisioning_2.0/CSRHandler.cpp +++ b/examples/utility/Provisioning_2.0/CSRHandler.cpp @@ -23,7 +23,11 @@ #define MAX_CSR_REQUEST_INTERVAL 180000 #define MAX_CSR_REQUEST_INTERVAL_ATTEMPTS 15 +#ifdef COMPILE_TEST +constexpr char *server = "boards-v2.oniudra.cc"; +#else constexpr char *server = "boards-v2.arduino.cc"; +#endif CSRHandlerClass::CSRHandlerClass() : _ledFeedback{LEDFeedbackClass::getInstance()}, diff --git a/examples/utility/Provisioning_2.0/Provisioning_2.0.ino b/examples/utility/Provisioning_2.0/Provisioning_2.0.ino index 14fc3aecc..c6ccc5c9d 100644 --- a/examples/utility/Provisioning_2.0/Provisioning_2.0.ino +++ b/examples/utility/Provisioning_2.0/Provisioning_2.0.ino @@ -171,7 +171,11 @@ DeviceState handleBeginCloud() { NetworkConfigurator.enableAgent(ConfiguratorAgent::AgentTypes::BLE, false); } // Connect to Arduino IoT Cloud +#ifdef COMPILE_TEST + ArduinoCloud.begin(ArduinoIoTPreferredConnection, false, "mqtts-sa.iot.oniudra.cc"); +#else ArduinoCloud.begin(ArduinoIoTPreferredConnection); +#endif ArduinoCloud.printDebugInfo(); return DeviceState::RUN; From f4c330b3d187c2220185db95474eef394f90db6b Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 15 Apr 2025 10:52:36 +0200 Subject: [PATCH 10/14] Add dedicated workflow to compile provisioning binaries --- .github/workflows/compile-provisioning.yml | 205 +++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 .github/workflows/compile-provisioning.yml diff --git a/.github/workflows/compile-provisioning.yml b/.github/workflows/compile-provisioning.yml new file mode 100644 index 000000000..4bf4362ab --- /dev/null +++ b/.github/workflows/compile-provisioning.yml @@ -0,0 +1,205 @@ +name: Compile Provisioning + +on: + pull_request: + paths: + - ".github/workflows/compile-provisioning.yml" + - "examples/**" + - "src/**" + push: + paths: + - ".github/workflows/compile-provisioning.yml" + - "examples/**" + - "src/**" + +jobs: + build: + runs-on: ubuntu-latest + + env: + # libraries to install for all boards + UNIVERSAL_LIBRARIES: | + # Install the ArduinoIoTCloud library from the repository + - source-path: ./ + - source-url: https://github.com/fabik111/Arduino_ConnectionHandler.git + version: 0314cf54593029aea05bb8c179e40a26128f7d67 + - name: ArduinoBLE + - name: ArduinoECCX08 + - name: ArduinoBearSSL + - name: ArduinoHttpClient + - name: Arduino_DebugUtils + - name: ArduinoMqttClient + - source-url: https://github.com/fabik111/Arduino_SecureElement.git + version: f5a23964a1c70048e48d5ed2d2657004446f0e3d + - source-url: https://github.com/fabik111/Arduino_CloudUtils.git + version: a8b52eaf500c63b2e8bd3e4b6f6c77b70fc3e65d + - source-url: https://github.com/arduino-libraries/Arduino_KVStore.git + - source-url: https://github.com/arduino-libraries/Arduino_UniqueHWId.git + - source-url: https://github.com/arduino-libraries/Arduino_NetworkConfigurator.git + # sketch paths to compile (recursive) for all boards + UNIVERSAL_SKETCH_PATHS: | + - examples/utility/Provisioning_2.0 + SKETCHES_REPORTS_PATH: sketches-reports + + strategy: + fail-fast: false + + matrix: + board: + - 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:mbed_portenta:envie_m7:split=100_0 + type: mbed_portenta + artifact-name-suffix: arduino-mbed_portenta-envie_m7 + - 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 + + # make board type-specific customizations to the matrix jobs + include: + # MKR WiFi 1010, Nano 33 IoT, Nano RP2040 Connect + - board: + type: nina + platforms: | + # Install samd and mbed_nano platform via Boards Manager + - name: arduino:samd + - name: arduino:mbed_nano + libraries: | + - name: RTCZero + - source-url: https://github.com/andreagilardoni/WiFiNINA.git + version: 31616ac5a30f6281c68f982bc39800771b2fbaeb + - name: Arduino_JSON + - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git + # Portenta + - board: + type: mbed_portenta + platforms: | + # Install mbed_portenta platform via Boards Manager + - name: arduino:mbed_portenta + libraries: | + - name: Arduino_Cellular + # Nicla Vision + - board: + type: mbed_nicla + platforms: | + # Install mbed_nicla platform via Boards Manager + - name: arduino:mbed_nicla + # Opta + - board: + type: mbed_opta + platforms: | + # Install mbed_opta platform via Boards Manager + - name: arduino:mbed_opta + # GIGA + - board: + type: mbed_giga + platforms: | + # Install mbed_giga platform via Boards Manager + - name: arduino:mbed_giga + # Portenta C33 + - board: + type: renesas_portenta + platforms: | + # Install renesas_portenta platform via Boards Manager + - name: arduino:renesas_portenta + libraries: | + - name: Arduino_Cellular + # UNO R4 WiFi + - board: + type: renesas_uno + platforms: | + # Install renesas_uno platform via Boards Manager + - name: arduino:renesas_uno + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Compile production provisioning sketch + uses: arduino/compile-sketches@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + platforms: ${{ matrix.platforms }} + fqbn: ${{ matrix.board.fqbn }} + libraries: | + ${{ env.UNIVERSAL_LIBRARIES }} + ${{ matrix.libraries }} + sketch-paths: | + ${{ env.UNIVERSAL_SKETCH_PATHS }} + ${{ matrix.sketch-paths }} + enable-deltas-report: "true" + sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} + cli-compile-flags: | + - --verbose + - --output-dir + - ${{ runner.temp }}/provisioning-prod + + - name: Compile staging provisioning sketch + uses: arduino/compile-sketches@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + platforms: ${{ matrix.platforms }} + fqbn: ${{ matrix.board.fqbn }} + libraries: | + ${{ env.UNIVERSAL_LIBRARIES }} + ${{ matrix.libraries }} + sketch-paths: | + ${{ env.UNIVERSAL_SKETCH_PATHS }} + ${{ matrix.sketch-paths }} + enable-deltas-report: "true" + sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} + cli-compile-flags: | + - --verbose + - --build-property + - "build.extra_flags=-DCOMPILE_TEST=1" + - --output-dir + - ${{ runner.temp }}/provisioning-staging + + - name: Write data to size trends report spreadsheet + # Update report on every push to the master branch + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + uses: arduino/report-size-trends@main + with: + sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} + google-key-file: ${{ secrets.GOOGLE_KEY_FILE }} + spreadsheet-id: 1I6NZkpZpf8KugBkE92adB1Z3_b7ZepOpCdYTOigJpN4 + + - 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 }} + + - name: Save production artifact + if: github.event_name == 'pull_request' + uses: actions/upload-artifact@v4 + with: + name: provisioning-prod-${{ matrix.board.artifact-name-suffix }} + path: ${{ runner.temp }}/provisioning-prod/ + + - name: Save staging artifact + if: github.event_name == 'pull_request' + uses: actions/upload-artifact@v4 + with: + name: provisioning-staging-${{ matrix.board.artifact-name-suffix }} + path: ${{ runner.temp }}/provisioning-staging/ From 67ec58213e5133ec027d47c402c1b121395dcfed Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 15 Apr 2025 13:43:04 +0200 Subject: [PATCH 11/14] cleanup compile examples --- .github/workflows/compile-examples.yml | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index d2839b11a..9c60a5c9f 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -24,6 +24,7 @@ jobs: - source-url: https://github.com/fabik111/Arduino_ConnectionHandler.git version: 0314cf54593029aea05bb8c179e40a26128f7d67 - name: ArduinoBLE + - name: Arduino_KVStore - name: ArduinoHttpClient - name: Arduino_DebugUtils - name: ArduinoMqttClient @@ -31,8 +32,6 @@ jobs: version: f5a23964a1c70048e48d5ed2d2657004446f0e3d - source-url: https://github.com/fabik111/Arduino_CloudUtils.git version: a8b52eaf500c63b2e8bd3e4b6f6c77b70fc3e65d - - source-url: https://github.com/arduino-libraries/Arduino_KVStore.git - - source-url: https://github.com/arduino-libraries/Arduino_UniqueHWId.git - source-url: https://github.com/arduino-libraries/Arduino_NetworkConfigurator.git # sketch paths to compile (recursive) for all boards UNIVERSAL_SKETCH_PATHS: | @@ -145,7 +144,6 @@ jobs: - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning - examples/utility/SelfProvisioning - - examples/utility/Provisioning_2.0 - board: type: wan platforms: | @@ -210,7 +208,6 @@ jobs: - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning - - examples/utility/Provisioning_2.0 # Nicla Vision - board: type: mbed_nicla @@ -219,14 +216,12 @@ jobs: - name: arduino:mbed_nicla libraries: | - name: Blues Wireless Notecard - - name: ArduinoECCX08 sketch-paths: | - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-DeferredOTA - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning - - examples/utility/Provisioning_2.0 # Opta - board: type: mbed_opta @@ -243,7 +238,6 @@ jobs: - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning - - examples/utility/Provisioning_2.0 # GIGA - board: type: mbed_giga @@ -260,7 +254,6 @@ jobs: - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning - - examples/utility/Provisioning_2.0 # Portenta C33 - board: type: renesas_portenta @@ -270,13 +263,11 @@ jobs: libraries: | - name: Arduino_Cellular - name: Blues Wireless Notecard - - name: ArduinoECCX08 sketch-paths: | - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule - examples/utility/Provisioning - - examples/utility/Provisioning_2.0 # UNO R4 WiFi - board: type: renesas_uno @@ -285,12 +276,10 @@ jobs: - name: arduino:renesas_uno libraries: | - name: Blues Wireless Notecard - - name: ArduinoECCX08 sketch-paths: | - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule - - examples/utility/Provisioning_2.0 # Nano ESP32 - board: type: arduino_esp32 @@ -369,9 +358,6 @@ jobs: ${{ matrix.sketch-paths }} enable-deltas-report: "true" sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} - cli-compile-flags: | - - --output-dir - - ${{ runner.temp }}/arduino-cli-output - name: Write data to size trends report spreadsheet # Update report on every push to the master branch @@ -388,10 +374,3 @@ jobs: with: name: sketches-report-${{ matrix.board.artifact-name-suffix }} path: ${{ env.SKETCHES_REPORTS_PATH }} - - - name: Save build artifact - if: github.event_name == 'pull_request' - uses: actions/upload-artifact@v4 - with: - name: provisioning-${{ matrix.board.artifact-name-suffix }} - path: ${{ runner.temp }}/arduino-cli-output/Provisioning_2.0* From d97774d1a6a5931f11a5a4ef80152bf2c50f676b Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 16 Apr 2025 14:42:51 +0200 Subject: [PATCH 12/14] update compile examples library refs --- .github/workflows/compile-examples.yml | 48 +++++++++++++++----------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 9c60a5c9f..79c30b5a6 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -21,17 +21,17 @@ jobs: UNIVERSAL_LIBRARIES: | # Install the ArduinoIoTCloud library from the repository - source-path: ./ - - source-url: https://github.com/fabik111/Arduino_ConnectionHandler.git - version: 0314cf54593029aea05bb8c179e40a26128f7d67 - name: ArduinoBLE - name: Arduino_KVStore - name: ArduinoHttpClient - name: Arduino_DebugUtils - name: ArduinoMqttClient - - source-url: https://github.com/fabik111/Arduino_SecureElement.git - version: f5a23964a1c70048e48d5ed2d2657004446f0e3d - - source-url: https://github.com/fabik111/Arduino_CloudUtils.git - version: a8b52eaf500c63b2e8bd3e4b6f6c77b70fc3e65d + - source-url: https://github.com/arduino-libraries/Arduino_ConnectionHandler.git + version: 0314cf54593029aea05bb8c179e40a26128f7d67 + - source-url: https://github.com/arduino-libraries/Arduino_SecureElement.git + version: 4900febf84435c1a06bb13451bced3bac6f16e76 + - source-url: https://github.com/arduino-libraries/Arduino_CloudUtils.git + version: 2e2facc2209b66905c180ec0058ef8b083912278 - source-url: https://github.com/arduino-libraries/Arduino_NetworkConfigurator.git # sketch paths to compile (recursive) for all boards UNIVERSAL_SKETCH_PATHS: | @@ -111,12 +111,13 @@ jobs: # Install samd platform via Boards Manager - name: arduino:samd libraries: | - - name: ArduinoBearSSL + - source-url: https://github.com/arduino-libraries/ArduinoBearSSL.git + version: a891ad3cb15bca3d080adc8188a63277f92fa81c - name: ArduinoECCX08 - name: Blues Wireless Notecard - name: RTCZero - name: WiFi101 - - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git + - name: Adafruit SleepyDog Library sketch-paths: | - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule @@ -129,14 +130,14 @@ jobs: - name: arduino:samd - name: arduino:mbed_nano libraries: | - - name: ArduinoBearSSL + - source-url: https://github.com/arduino-libraries/ArduinoBearSSL.git + version: a891ad3cb15bca3d080adc8188a63277f92fa81c - name: ArduinoECCX08 - name: Blues Wireless Notecard - name: RTCZero - - source-url: https://github.com/andreagilardoni/WiFiNINA.git - version: 31616ac5a30f6281c68f982bc39800771b2fbaeb - - name: Arduino_JSON - - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git + - source-url: https://github.com/arduino-libraries/WiFiNINA.git + version: 69e786c5c73fe94b7f408853550f6f151cfc58b0 + - name: Adafruit SleepyDog Library sketch-paths: | - examples/ArduinoIoTCloud-NetConfig - examples/ArduinoIoTCloud-DeferredOTA @@ -154,7 +155,7 @@ jobs: - name: Blues Wireless Notecard - name: RTCZero - name: MKRWAN - - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git + - name: Adafruit SleepyDog Library sketch-paths: | - examples/ArduinoIoTCloud-Notecard # GSM boards @@ -164,12 +165,13 @@ jobs: # Install samd platform via Boards Manager - name: arduino:samd libraries: | - - name: ArduinoBearSSL + - source-url: https://github.com/arduino-libraries/ArduinoBearSSL.git + version: a891ad3cb15bca3d080adc8188a63277f92fa81c - name: ArduinoECCX08 - name: Blues Wireless Notecard - name: RTCZero - name: MKRGSM - - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git + - name: Adafruit SleepyDog Library sketch-paths: | - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule @@ -181,12 +183,13 @@ jobs: # Install samd platform via Boards Manager - name: arduino:samd libraries: | - - name: ArduinoBearSSL + - source-url: https://github.com/arduino-libraries/ArduinoBearSSL.git + version: a891ad3cb15bca3d080adc8188a63277f92fa81c - name: ArduinoECCX08 - name: Blues Wireless Notecard - name: RTCZero - name: MKRNB - - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git + - name: Adafruit SleepyDog Library sketch-paths: | - examples/ArduinoIoTCloud-Notecard - examples/ArduinoIoTCloud-Schedule @@ -198,7 +201,8 @@ jobs: # Install mbed_portenta platform via Boards Manager - name: arduino:mbed_portenta libraries: | - - name: ArduinoBearSSL + - source-url: https://github.com/arduino-libraries/ArduinoBearSSL.git + version: a891ad3cb15bca3d080adc8188a63277f92fa81c - name: ArduinoECCX08 - name: Arduino_Cellular - name: Blues Wireless Notecard @@ -229,7 +233,8 @@ jobs: # Install mbed_opta platform via Boards Manager - name: arduino:mbed_opta libraries: | - - name: ArduinoBearSSL + - source-url: https://github.com/arduino-libraries/ArduinoBearSSL.git + version: a891ad3cb15bca3d080adc8188a63277f92fa81c - name: ArduinoECCX08 - name: Blues Wireless Notecard sketch-paths: | @@ -245,7 +250,8 @@ jobs: # Install mbed_giga platform via Boards Manager - name: arduino:mbed_giga libraries: | - - name: ArduinoBearSSL + - source-url: https://github.com/arduino-libraries/ArduinoBearSSL.git + version: a891ad3cb15bca3d080adc8188a63277f92fa81c - name: ArduinoECCX08 - name: Blues Wireless Notecard sketch-paths: | From a40a3bd2b710984ba3be4c36bf73b2caa6e45a20 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 16 Apr 2025 14:43:10 +0200 Subject: [PATCH 13/14] update compile provisioning library refs --- .github/workflows/compile-provisioning.yml | 60 +++++++++++++++++----- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/.github/workflows/compile-provisioning.yml b/.github/workflows/compile-provisioning.yml index 4bf4362ab..e4aa0d923 100644 --- a/.github/workflows/compile-provisioning.yml +++ b/.github/workflows/compile-provisioning.yml @@ -21,21 +21,26 @@ jobs: UNIVERSAL_LIBRARIES: | # Install the ArduinoIoTCloud library from the repository - source-path: ./ - - source-url: https://github.com/fabik111/Arduino_ConnectionHandler.git - version: 0314cf54593029aea05bb8c179e40a26128f7d67 - name: ArduinoBLE - - name: ArduinoECCX08 - - name: ArduinoBearSSL + version: 1.4.0 - name: ArduinoHttpClient + version: 0.6.1 - name: Arduino_DebugUtils + version: 1.4.0 - name: ArduinoMqttClient - - source-url: https://github.com/fabik111/Arduino_SecureElement.git - version: f5a23964a1c70048e48d5ed2d2657004446f0e3d - - source-url: https://github.com/fabik111/Arduino_CloudUtils.git - version: a8b52eaf500c63b2e8bd3e4b6f6c77b70fc3e65d - - source-url: https://github.com/arduino-libraries/Arduino_KVStore.git + version: 0.1.8 + - name: Arduino_KVStore + version: 1.0.0 + - source-url: https://github.com/arduino-libraries/Arduino_ConnectionHandler.git + version: 0314cf54593029aea05bb8c179e40a26128f7d67 + - source-url: https://github.com/arduino-libraries/Arduino_SecureElement.git + version: 4900febf84435c1a06bb13451bced3bac6f16e76 + - source-url: https://github.com/arduino-libraries/Arduino_CloudUtils.git + version: 2e2facc2209b66905c180ec0058ef8b083912278 - source-url: https://github.com/arduino-libraries/Arduino_UniqueHWId.git + version: 7e1bfeb586cac00f043c39997a1e9937ed8152b0 - source-url: https://github.com/arduino-libraries/Arduino_NetworkConfigurator.git + version: d887ec0fd15d3d6bd427fa3e2c4f95b582f964a0 # sketch paths to compile (recursive) for all boards UNIVERSAL_SKETCH_PATHS: | - examples/utility/Provisioning_2.0 @@ -82,53 +87,82 @@ jobs: platforms: | # Install samd and mbed_nano platform via Boards Manager - name: arduino:samd + version: 1.8.14 - name: arduino:mbed_nano + version: 4.2.4 libraries: | - name: RTCZero - - source-url: https://github.com/andreagilardoni/WiFiNINA.git - version: 31616ac5a30f6281c68f982bc39800771b2fbaeb - - name: Arduino_JSON - - source-url: https://github.com/adafruit/Adafruit_SleepyDog.git + version: 1.6.0 + - name: ArduinoECCX08 + version: 1.3.8 + - name: Adafruit SleepyDog Library + version: 1.6.5 + - source-url: https://github.com/arduino-libraries/ArduinoBearSSL.git + version: a891ad3cb15bca3d080adc8188a63277f92fa81c + - source-url: https://github.com/arduino-libraries/WiFiNINA.git + version: 69e786c5c73fe94b7f408853550f6f151cfc58b0 # Portenta - board: type: mbed_portenta platforms: | # Install mbed_portenta platform via Boards Manager - name: arduino:mbed_portenta + version: 4.2.4 libraries: | - name: Arduino_Cellular + version: 1.2.1 + - name: ArduinoECCX08 + version: 1.3.8 + - source-url: https://github.com/arduino-libraries/ArduinoBearSSL.git + version: a891ad3cb15bca3d080adc8188a63277f92fa81c # Nicla Vision - board: type: mbed_nicla platforms: | # Install mbed_nicla platform via Boards Manager - name: arduino:mbed_nicla + version: 4.2.4 # Opta - board: type: mbed_opta platforms: | # Install mbed_opta platform via Boards Manager - name: arduino:mbed_opta + version: 4.2.4 + libraries: | + - name: ArduinoECCX08 + version: 1.3.8 + - source-url: https://github.com/arduino-libraries/ArduinoBearSSL.git + version: a891ad3cb15bca3d080adc8188a63277f92fa81c # GIGA - board: type: mbed_giga platforms: | # Install mbed_giga platform via Boards Manager - name: arduino:mbed_giga + version: 4.2.4 + libraries: | + - name: ArduinoECCX08 + version: 1.3.8 + - source-url: https://github.com/arduino-libraries/ArduinoBearSSL.git + version: a891ad3cb15bca3d080adc8188a63277f92fa81c # Portenta C33 - board: type: renesas_portenta platforms: | # Install renesas_portenta platform via Boards Manager - name: arduino:renesas_portenta + version: 1.4.1 libraries: | - name: Arduino_Cellular + version: 1.2.1 # UNO R4 WiFi - board: type: renesas_uno platforms: | # Install renesas_uno platform via Boards Manager - name: arduino:renesas_uno + version: 1.4.1 steps: - name: Checkout From b7e20b791ea581d349113b672e9eca0e23e6601f Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 16 Apr 2025 14:45:20 +0200 Subject: [PATCH 14/14] Provisioning v0.1.1 --- examples/utility/Provisioning_2.0/Provisioning_2.0.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/utility/Provisioning_2.0/Provisioning_2.0.ino b/examples/utility/Provisioning_2.0/Provisioning_2.0.ino index c6ccc5c9d..5f9e2831c 100644 --- a/examples/utility/Provisioning_2.0/Provisioning_2.0.ino +++ b/examples/utility/Provisioning_2.0/Provisioning_2.0.ino @@ -15,7 +15,7 @@ #include #include "Utility/LEDFeedback/LEDFeedback.h" -const char *SKETCH_VERSION = "0.1.0"; +const char *SKETCH_VERSION = "0.1.1"; enum class DeviceState { HARDWARE_CHECK,