Skip to content

Commit

Permalink
ArduinoIoTCloud integration
Browse files Browse the repository at this point in the history
  • Loading branch information
pennam authored and andreagilardoni committed Apr 22, 2024
1 parent 7f37295 commit 7010475
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 180 deletions.
1 change: 0 additions & 1 deletion src/ArduinoIoTCloudDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ ArduinoCloudDevice::State ArduinoCloudDevice::handleConnected() {
}
return State::SendCapabilities;
}

return State::Connected;
}

Expand Down
172 changes: 39 additions & 133 deletions src/ArduinoIoTCloudTCP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,11 @@
#include <AIoTC_Config.h>

#ifdef HAS_TCP
#include <ArduinoIoTCloudTCP.h>

#if defined(BOARD_HAS_SECRET_KEY)
#include "tls/AIoTCUPCert.h"
#endif

#ifdef BOARD_HAS_ECCX08
#include "tls/BearSSLTrustAnchors.h"
#endif

#if defined(BOARD_HAS_SE050) || defined(BOARD_HAS_SOFTSE)
#include "tls/AIoTCSSCert.h"
#endif
#include <ArduinoIoTCloudTCP.h>

#if OTA_ENABLED
#include "utility/ota/OTA.h"
#include "ota/OTA.h"
#endif

#include <algorithm>
Expand Down Expand Up @@ -67,25 +56,16 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP()
, _mqtt_data_buf{0}
, _mqtt_data_len{0}
, _mqtt_data_request_retransmit{false}
#ifdef BOARD_HAS_ECCX08
, _sslClient(nullptr, ArduinoIoTCloudTrustAnchor, ArduinoIoTCloudTrustAnchor_NUM, getTime)
#endif
#ifdef BOARD_HAS_SECRET_KEY
, _password("")
#endif
, _mqttClient{nullptr}
, _deviceTopicOut("")
, _deviceTopicIn("")
, _messageTopicOut("")
, _messageTopicIn("")
, _dataTopicOut("")
, _dataTopicIn("")
#if OTA_ENABLED
, _ota_cap{false}
, _ota_error{static_cast<int>(OTAError::None)}
, _ota_img_sha256{"Inv."}
, _ota_url{""}
, _ota_req{false}
, _ota(&_message_stream)
, _ask_user_before_executing_ota{false}
, _get_ota_confirmation{nullptr}
#endif /* OTA_ENABLED */
Expand All @@ -107,8 +87,16 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, bool const enable_
_brokerPort = brokerPort;
#endif

/* Setup broker TLS client */
_brokerClient.begin(connection);

#if OTA_ENABLED
/* Setup OTA TLS client */
_otaClient.begin(connection);
#endif

/* Setup TimeService */
_time_service.begin(&connection);
_time_service.begin(_connection);

/* Setup retry timers */
_connection_attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms);
Expand Down Expand Up @@ -148,33 +136,19 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress,
DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not read device certificate.", __FUNCTION__);
return 0;
}
_sslClient.setEccSlot(static_cast<int>(SElementArduinoCloudSlot::Key), _cert.bytes(), _cert.length());
_brokerClient.setEccSlot(static_cast<int>(SElementArduinoCloudSlot::Key), _cert.bytes(), _cert.length());
#if OTA_ENABLED
_otaClient.setEccSlot(static_cast<int>(SElementArduinoCloudSlot::Key), _cert.bytes(), _cert.length());
#endif
#endif
#endif

#if defined(BOARD_HAS_SECRET_KEY)
}
#endif

#if defined(BOARD_HAS_OFFLOADED_ECCX08)

#elif defined(BOARD_HAS_ECCX08)
_sslClient.setClient(_connection->getClient());
#elif defined(ARDUINO_PORTENTA_C33)
_sslClient.setClient(_connection->getClient());
_sslClient.setCACert(AIoTSSCert);
#elif defined(ARDUINO_NICLA_VISION)
_sslClient.appendCustomCACert(AIoTSSCert);
#elif defined(ARDUINO_EDGE_CONTROL)
_sslClient.appendCustomCACert(AIoTUPCert);
#elif defined(ARDUINO_UNOR4_WIFI)

#elif defined(ARDUINO_ARCH_ESP32)
_sslClient.setCACertBundle(x509_crt_bundle);
#elif defined(ARDUINO_ARCH_ESP8266)
_sslClient.setInsecure();
#endif
_mqttClient.setClient(_brokerClient);

_mqttClient.setClient(_sslClient);
#ifdef BOARD_HAS_SECRET_KEY
if(_password.length())
{
Expand All @@ -187,32 +161,19 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress,
_mqttClient.setConnectionTimeout(1500);
_mqttClient.setId(getDeviceId().c_str());

_deviceTopicOut = getTopic_deviceout();
_deviceTopicIn = getTopic_devicein();
_messageTopicIn = getTopic_messagein();
_messageTopicOut = getTopic_messageout();
_messageTopicIn = getTopic_messagein();

_thing.begin();
_device.begin();

#if OTA_ENABLED
Property* p;
p = new CloudWrapperBool(_ota_cap);
addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_CAP", Permission::Read, -1);
p = new CloudWrapperInt(_ota_error);
addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_ERROR", Permission::Read, -1);
p = new CloudWrapperString(_ota_img_sha256);
addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_SHA256", Permission::Read, -1);
p = new CloudWrapperString(_ota_url);
addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_URL", Permission::ReadWrite, -1);
p = new CloudWrapperBool(_ota_req);
addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_REQ", Permission::ReadWrite, -1);

_ota_cap = OTA::isCapable();

_ota_img_sha256 = OTA::getImageSHA256();
DEBUG_VERBOSE("SHA256: HASH(%d) = %s", strlen(_ota_img_sha256.c_str()), _ota_img_sha256.c_str());
#endif // OTA_ENABLED
#if OTA_ENABLED && !defined(OFFLOADED_DOWNLOAD)
_ota.setClient(&_otaClient);
#endif // OTA_ENABLED && !defined(OFFLOADED_DOWNLOAD)

#if OTA_ENABLED && defined(OTA_BASIC_AUTH)
_ota.setAuthentication(getDeviceId().c_str(), _password.c_str());
#endif // OTA_ENABLED && !defined(OFFLOADED_DOWNLOAD) && defined(OTA_BASIC_AUTH)

#ifdef BOARD_HAS_OFFLOADED_ECCX08
if (String(WiFi.firmwareVersion()) < String("1.4.4")) {
Expand Down Expand Up @@ -323,9 +284,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker()
/* Subscribe to message topic to receive commands */
_mqttClient.subscribe(_messageTopicIn);

/* Temoporarly subscribe to device topic to receive OTA properties */
_mqttClient.subscribe(_deviceTopicIn);

/* Reconfigure timers for next state */
_connection_attempt.begin(AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms, AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms);

Expand Down Expand Up @@ -361,51 +319,19 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected()
/* Call CloudDevice process to get configuration */
_device.update();

#if OTA_ENABLED
_ota.update();
#endif // OTA_ENABLED


if (_device.isAttached()) {
/* Call CloudThing process to synchronize properties */
_thing.update();
}

#if OTA_ENABLED
if (_device.connected()) {
handle_OTARequest();
}
#endif /* OTA_ENABLED */

return State::Connected;
}

#if OTA_ENABLED
void ArduinoIoTCloudTCP::handle_OTARequest() {
/* Request a OTA download if the hidden property
* OTA request has been set.
*/

if (_ota_req)
{
bool const ota_execution_allowed_by_user = (_get_ota_confirmation != nullptr && _get_ota_confirmation());
bool const perform_ota_now = ota_execution_allowed_by_user || !_ask_user_before_executing_ota;
if (perform_ota_now) {
/* Clear the error flag. */
_ota_error = static_cast<int>(OTAError::None);
/* Clear the request flag. */
_ota_req = false;
/* Transmit the cleared request flags to the cloud. */
sendDevicePropertyToCloud("OTA_REQ");
/* Call member function to handle OTA request. */
_ota_error = OTA::onRequest(_ota_url, _connection->getInterface());
/* If something fails send the OTA error to the cloud */
sendDevicePropertyToCloud("OTA_ERROR");
}
}

/* Check if we have received the OTA_URL property and provide
* echo to the cloud.
*/
sendDevicePropertyToCloud("OTA_URL");
}
#endif /* OTA_ENABLED */

ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect()
{
if (!_mqttClient.connected()) {
Expand Down Expand Up @@ -442,11 +368,6 @@ void ArduinoIoTCloudTCP::handleMessage(int length)
bytes[i] = _mqttClient.read();
}

/* Topic for OTA properties and device configuration */
if (_deviceTopicIn == topic) {
CBORDecoder::decode(_device.getPropertyContainer(), (uint8_t*)bytes, length);
}

/* Topic for user input data */
if (_dataTopicIn == topic) {
CBORDecoder::decode(_thing.getPropertyContainer(), (uint8_t*)bytes, length);
Expand Down Expand Up @@ -506,6 +427,14 @@ void ArduinoIoTCloudTCP::handleMessage(int length)
}
break;

#if OTA_ENABLED
case CommandId::OtaUpdateCmdDownId:
{
DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] ota update received", __FUNCTION__, millis());
_ota.handleMessage((Message*)&command);
}
#endif

default:
break;
}
Expand All @@ -526,14 +455,6 @@ void ArduinoIoTCloudTCP::sendMessage(Message * msg)
_thing.getPropertyContainerIndex());
break;

#if OTA_ENABLED
case DeviceBeginCmdId:
sendDevicePropertyToCloud("OTA_CAP");
sendDevicePropertyToCloud("OTA_ERROR");
sendDevicePropertyToCloud("OTA_SHA256");
break;
#endif

default:
break;
}
Expand Down Expand Up @@ -566,21 +487,6 @@ void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(String const topic, Proper
}
}

#if OTA_ENABLED
void ArduinoIoTCloudTCP::sendDevicePropertyToCloud(String const name)
{
PropertyContainer temp_device_property_container;
unsigned int last_device_property_index = 0;

Property* p = getProperty(this->_device.getPropertyContainer(), name);
if(p != nullptr)
{
addPropertyToContainer(temp_device_property_container, *p, p->name(), p->isWriteableByCloud() ? Permission::ReadWrite : Permission::Read);
sendPropertyContainerToCloud(_deviceTopicOut, temp_device_property_container, last_device_property_index);
}
}
#endif

void ArduinoIoTCloudTCP::attachThing()
{

Expand Down
53 changes: 7 additions & 46 deletions src/ArduinoIoTCloudTCP.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,11 @@
#endif
#endif

#if defined(BOARD_HAS_OFFLOADED_ECCX08)
#include "WiFiSSLClient.h"
#elif defined(BOARD_HAS_ECCX08)
#include "tls/BearSSLClient.h"
#elif defined(ARDUINO_PORTENTA_C33)
#include <SSLClient.h>
#elif defined(ARDUINO_NICLA_VISION)
#include <WiFiSSLSE050Client.h>
#elif defined(ARDUINO_EDGE_CONTROL)
#include <GSMSSLClient.h>
#elif defined(ARDUINO_UNOR4_WIFI)
#include <WiFiSSLClient.h>
#elif defined(BOARD_ESP)
#include <WiFiClientSecure.h>
#endif
#include <tls/utility/TLSClientMqtt.h>
#include <tls/utility/TLSClientOta.h>

#if OTA_ENABLED
#include <utility/ota/OTA.h>
#include <ota/OTA.h>
#endif

#include "cbor/MessageDecoder.h"
Expand Down Expand Up @@ -109,7 +96,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
_get_ota_confirmation = cb;
_ask_user_before_executing_ota = true;
}
void handle_OTARequest();
#endif

private:
Expand Down Expand Up @@ -147,44 +133,22 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
#endif
#endif

#if defined(BOARD_HAS_OFFLOADED_ECCX08)
WiFiBearSSLClient _sslClient;
#elif defined(BOARD_HAS_ECCX08)
BearSSLClient _sslClient;
#elif defined(ARDUINO_PORTENTA_C33)
SSLClient _sslClient;
#elif defined(ARDUINO_NICLA_VISION)
WiFiSSLSE050Client _sslClient;
#elif defined(ARDUINO_EDGE_CONTROL)
GSMSSLClient _sslClient;
#elif defined(ARDUINO_UNOR4_WIFI)
WiFiSSLClient _sslClient;
#elif defined(BOARD_ESP)
WiFiClientSecure _sslClient;
#endif

TLSClientMqtt _brokerClient;
MqttClient _mqttClient;

String _deviceTopicOut;
String _deviceTopicIn;
String _messageTopicOut;
String _messageTopicIn;
String _dataTopicOut;
String _dataTopicIn;


#if OTA_ENABLED
bool _ota_cap;
int _ota_error;
String _ota_img_sha256;
String _ota_url;
bool _ota_req;
TLSClientOta _otaClient;
OTACloudProcess _ota;
bool _ask_user_before_executing_ota;
onOTARequestCallbackFunc _get_ota_confirmation;
#endif /* OTA_ENABLED */

inline String getTopic_deviceout() { return String("/a/d/" + getDeviceId() + "/e/o");}
inline String getTopic_devicein () { return String("/a/d/" + getDeviceId() + "/e/i");}

inline String getTopic_messageout() { return String("/a/d/" + getDeviceId() + "/c/up");}
inline String getTopic_messagein () { return String("/a/d/" + getDeviceId() + "/c/dw");}

Expand All @@ -206,9 +170,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
void detachThing();
int write(String const topic, byte const data[], int const length);

#if OTA_ENABLED
void sendDevicePropertyToCloud(String const name);
#endif
};

/******************************************************************************
Expand Down

0 comments on commit 7010475

Please sign in to comment.