Working Portenta H7 IoT Hub sample

This commit is contained in:
Lauren George 2022-03-10 19:57:57 -08:00
Родитель 73b782a091
Коммит 2d8d44d4db
7 изменённых файлов: 863 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,282 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#include "AzIoTSasToken.h"
#include "SerialLogger.h"
#include <az_result.h>
#include <mbedtls/base64.h>
#include <mbedtls/md.h>
#include <mbedtls/sha256.h>
#include <stdlib.h>
#include <time.h>
#define INDEFINITE_TIME ((time_t)-1)
#define is_az_span_empty(x) (az_span_size(x) == az_span_size(AZ_SPAN_EMPTY) && az_span_ptr(x) == az_span_ptr(AZ_SPAN_EMPTY))
static uint32_t getSasTokenExpiration(const char* sasToken)
{
const char SE[] = { '&', 's', 'e', '=' };
uint32_t se_as_unix_time = 0;
int i, j;
for (i = 0, j = 0; sasToken[i] != '\0'; i++)
{
if (sasToken[i] == SE[j])
{
j++;
if (j == sizeof(SE))
{
// i is still at the '=' position. We must advance it by 1.
i++;
break;
}
}
else
{
j = 0;
}
}
if (j != sizeof(SE))
{
Logger.Error("Failed finding `se` field in SAS token");
}
else
{
int k = i;
while (sasToken[k] != '\0' && sasToken[k] != '&') { k++; }
if (az_result_failed(
az_span_atou32(az_span_create((uint8_t*)sasToken + i, k - i), &se_as_unix_time)))
{
Logger.Error("Failed parsing SAS token expiration timestamp");
}
}
return se_as_unix_time;
}
static void mbedtls_hmac_sha256(az_span key, az_span payload, az_span signed_payload)
{
mbedtls_md_context_t ctx;
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
mbedtls_md_init(&ctx);
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1);
mbedtls_md_hmac_starts(&ctx, (const unsigned char*)az_span_ptr(key), az_span_size(key));
mbedtls_md_hmac_update(&ctx, (const unsigned char*)az_span_ptr(payload), az_span_size(payload));
mbedtls_md_hmac_finish(&ctx, (byte*)az_span_ptr(signed_payload));
mbedtls_md_free(&ctx);
}
static void hmac_sha256_sign_signature(
az_span decoded_key,
az_span signature,
az_span signed_signature,
az_span* out_signed_signature)
{
mbedtls_hmac_sha256(decoded_key, signature, signed_signature);
*out_signed_signature = az_span_slice(signed_signature, 0, 32);
}
static void base64_encode_bytes(
az_span decoded_bytes,
az_span base64_encoded_bytes,
az_span* out_base64_encoded_bytes)
{
size_t len;
if (mbedtls_base64_encode(
az_span_ptr(base64_encoded_bytes),
(size_t)az_span_size(base64_encoded_bytes),
&len,
az_span_ptr(decoded_bytes),
(size_t)az_span_size(decoded_bytes))
!= 0)
{
Logger.Error("mbedtls_base64_encode fail");
}
*out_base64_encoded_bytes = az_span_create(az_span_ptr(base64_encoded_bytes), (int32_t)len);
}
static int decode_base64_bytes(
az_span base64_encoded_bytes,
az_span decoded_bytes,
az_span* out_decoded_bytes)
{
memset(az_span_ptr(decoded_bytes), 0, (size_t)az_span_size(decoded_bytes));
size_t len;
if (mbedtls_base64_decode(
az_span_ptr(decoded_bytes),
(size_t)az_span_size(decoded_bytes),
&len,
az_span_ptr(base64_encoded_bytes),
(size_t)az_span_size(base64_encoded_bytes))
!= 0)
{
Logger.Error("mbedtls_base64_decode fail");
return 1;
}
else
{
*out_decoded_bytes = az_span_create(az_span_ptr(decoded_bytes), (int32_t)len);
return 0;
}
}
static int iot_sample_generate_sas_base64_encoded_signed_signature(
az_span sas_base64_encoded_key,
az_span sas_signature,
az_span sas_base64_encoded_signed_signature,
az_span* out_sas_base64_encoded_signed_signature)
{
// Decode the sas base64 encoded key to use for HMAC signing.
char sas_decoded_key_buffer[32];
az_span sas_decoded_key = AZ_SPAN_FROM_BUFFER(sas_decoded_key_buffer);
if (decode_base64_bytes(sas_base64_encoded_key, sas_decoded_key, &sas_decoded_key) != 0)
{
Logger.Error("Failed generating encoded signed signature");
return 1;
}
// HMAC-SHA256 sign the signature with the decoded key.
char sas_hmac256_signed_signature_buffer[32];
az_span sas_hmac256_signed_signature = AZ_SPAN_FROM_BUFFER(sas_hmac256_signed_signature_buffer);
hmac_sha256_sign_signature(
sas_decoded_key, sas_signature, sas_hmac256_signed_signature, &sas_hmac256_signed_signature);
// Base64 encode the result of the HMAC signing.
base64_encode_bytes(
sas_hmac256_signed_signature,
sas_base64_encoded_signed_signature,
out_sas_base64_encoded_signed_signature);
return 0;
}
int64_t iot_sample_get_epoch_expiration_time_from_minutes(uint32_t minutes)
{
time_t now = time(NULL);
return (int64_t)(now + minutes * 60);
}
az_span generate_sas_token(
az_iot_hub_client* hub_client,
az_span device_key,
az_span sas_signature,
unsigned int expiryTimeInMinutes,
az_span sas_token)
{
az_result rc;
// Create the POSIX expiration time from input minutes.
uint64_t sas_duration = iot_sample_get_epoch_expiration_time_from_minutes(expiryTimeInMinutes);
// Get the signature that will later be signed with the decoded key.
// az_span sas_signature = AZ_SPAN_FROM_BUFFER(signature);
rc = az_iot_hub_client_sas_get_signature(hub_client, sas_duration, sas_signature, &sas_signature);
if (az_result_failed(rc))
{
Logger.Error("Could not get the signature for SAS key: az_result return code " + rc);
return AZ_SPAN_EMPTY;
}
// Generate the encoded, signed signature (b64 encoded, HMAC-SHA256 signing).
char b64enc_hmacsha256_signature[64];
az_span sas_base64_encoded_signed_signature = AZ_SPAN_FROM_BUFFER(b64enc_hmacsha256_signature);
if (iot_sample_generate_sas_base64_encoded_signed_signature(
device_key,
sas_signature,
sas_base64_encoded_signed_signature,
&sas_base64_encoded_signed_signature) != 0)
{
Logger.Error("Failed generating SAS token signed signature");
return AZ_SPAN_EMPTY;
}
// Get the resulting MQTT password, passing the base64 encoded, HMAC signed bytes.
size_t mqtt_password_length;
rc = az_iot_hub_client_sas_get_password(
hub_client,
sas_duration,
sas_base64_encoded_signed_signature,
AZ_SPAN_EMPTY,
(char*)az_span_ptr(sas_token),
az_span_size(sas_token),
&mqtt_password_length);
if (az_result_failed(rc))
{
Logger.Error("Could not get the password: az_result return code " + rc);
return AZ_SPAN_EMPTY;
}
else
{
return az_span_slice(sas_token, 0, mqtt_password_length);
}
}
AzIoTSasToken::AzIoTSasToken(
az_iot_hub_client* client,
az_span deviceKey,
az_span signatureBuffer,
az_span sasTokenBuffer)
{
this->client = client;
this->deviceKey = deviceKey;
this->signatureBuffer = signatureBuffer;
this->sasTokenBuffer = sasTokenBuffer;
this->expirationUnixTime = 0;
this->sasToken = AZ_SPAN_EMPTY;
}
int AzIoTSasToken::Generate(unsigned int expiryTimeInMinutes)
{
this->sasToken = generate_sas_token(
this->client,
this->deviceKey,
this->signatureBuffer,
expiryTimeInMinutes,
this->sasTokenBuffer);
if (is_az_span_empty(this->sasToken))
{
Logger.Error("Failed generating SAS token");
return 1;
}
else
{
this->expirationUnixTime = getSasTokenExpiration((const char*)az_span_ptr(this->sasToken));
if (this->expirationUnixTime == 0)
{
Logger.Error("Failed getting the SAS token expiration time");
this->sasToken = AZ_SPAN_EMPTY;
return 1;
}
else
{
return 0;
}
}
}
bool AzIoTSasToken::IsExpired()
{
time_t now = time(NULL);
if (now == INDEFINITE_TIME)
{
Logger.Error("Failed getting current time");
return true;
}
else
{
return (now >= this->expirationUnixTime);
}
}
az_span AzIoTSasToken::Get() { return this->sasToken; }

Просмотреть файл

@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#ifndef AZIOTSASTOKEN_H
#define AZIOTSASTOKEN_H
#include <Arduino.h>
#include <az_iot_hub_client.h>
#include <az_span.h>
class AzIoTSasToken
{
public:
AzIoTSasToken(
az_iot_hub_client* client,
az_span deviceKey,
az_span signatureBuffer,
az_span sasTokenBuffer);
int Generate(unsigned int expiryTimeInMinutes);
bool IsExpired();
az_span Get();
private:
az_iot_hub_client* client;
az_span deviceKey;
az_span signatureBuffer;
az_span sasTokenBuffer;
az_span sasToken;
uint32_t expirationUnixTime;
};
#endif // AZIOTSASTOKEN_H

Просмотреть файл

@ -0,0 +1,250 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/*
* This is an Arduino-based Azure IoT Hub sample for Arduino Portenta H7 boards.
* It uses our Azure Embedded SDK for C to help interact with Azure IoT.
* For reference, please visit https://github.com/azure/azure-sdk-for-c.
*
* To connect and work with Azure IoT Hub you need an MQTT client, connecting, subscribing
* and publishing to specific topics to use the messaging features of the hub.
* Our azure-sdk-for-c is an MQTT client support library, helping composing and parsing the
* MQTT topic names and messages exchanged with the Azure IoT Hub.
*
* This sample performs the following tasks:
* - Synchronize the device clock with a NTP server;
* - Initialize our "az_iot_hub_client" (struct for data, part of our azure-sdk-for-c);
* - Initialize the MQTT client (here we use Arduino's ArduinoMqttClient, which also handle the tcp connection and TLS);
* - Connect the MQTT client (using server-certificate validation, SAS-tokens for client authentication);
* - Periodically send telemetry data to the Azure IoT Hub.
*
* To properly connect to your Azure IoT Hub, please fill the information in the `iot_configs.h` file.
*/
// C99 libraries
#include <cstdlib>
#include <cstdarg>
#include <string.h>
#include <time.h>
// Libraries for MQTT client and WiFi connection
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include <NTPClient_Generic.h>
#include <ArduinoMqttClient.h>
// Azure IoT SDK for C includes
#include <az_core.h>
#include <az_iot.h>
#include <azure_ca.h>
// Additional sample headers
#include "AzIoTSasToken.h"
#include "SerialLogger.h"
#include "iot_configs.h"
// When developing for your own Arduino-based platform,
// please follow the format '(ard;<platform>)'.
#define AZURE_SDK_CLIENT_USER_AGENT "c/" AZ_SDK_VERSION_STRING "(ard;ststm32)"
// Utility macros and defines
#define sizeofarray(a) (sizeof(a) / sizeof(a[0]))
#define NTP_SERVER "pool.ntp.org"
#define MQTT_QOS1 1
#define DO_NOT_RETAIN_MSG 0
#define SAS_TOKEN_DURATION_IN_MINUTES 60
#define UNIX_TIME_NOV_13_2017 1510592825
#define PST_TIME_ZONE -8
#define PST_TIME_ZONE_DAYLIGHT_SAVINGS_DIFF 1
#define GMT_OFFSET_SECS (PST_TIME_ZONE * 3600)
#define GMT_OFFSET_SECS_DST ((PST_TIME_ZONE + PST_TIME_ZONE_DAYLIGHT_SAVINGS_DIFF) * 3600)
// Translate iot_configs.h defines into variables used by the sample
static const char *ssid = IOT_CONFIG_WIFI_SSID;
static const char *password = IOT_CONFIG_WIFI_PASSWORD;
static const char *host = IOT_CONFIG_IOTHUB_FQDN;
static const char *mqtt_broker_uri = "mqtts://" IOT_CONFIG_IOTHUB_FQDN;
static const char *device_id = IOT_CONFIG_DEVICE_ID;
static const int mqtt_port = AZ_IOT_DEFAULT_MQTT_CONNECT_PORT;
// Memory allocated for the sample's variables and structures.
static az_iot_hub_client client;
static char mqtt_client_id[128];
static char mqtt_username[128];
static char mqtt_password[200];
static uint8_t sas_signature_buffer[256];
static unsigned long next_telemetry_send_time_ms = 0;
static char telemetry_topic[128];
static uint8_t telemetry_payload[100];
static uint32_t telemetry_send_count = 0;
static WiFiClient wifiClient;
static MqttClient mqttClient(wifiClient);
static WiFiUDP ntpUDP;
static NTPClient timeClient(ntpUDP, NTP_SERVER, GMT_OFFSET_SECS_DST);
static AzIoTSasToken sasToken(
&client,
AZ_SPAN_FROM_STR(IOT_CONFIG_DEVICE_KEY),
AZ_SPAN_FROM_BUFFER(sas_signature_buffer),
AZ_SPAN_FROM_BUFFER(mqtt_password));
void onMqttMessage(int length) {
Serial.print("Received a message with topic '");
Serial.print(mqttClient.messageTopic());
Serial.print("', duplicate = ");
Serial.print(mqttClient.messageDup() ? "true" : "false");
Serial.print(", QoS = ");
Serial.print(mqttClient.messageQoS());
Serial.print(", retained = ");
Serial.print(mqttClient.messageRetain() ? "true" : "false");
Serial.print("', length ");
Serial.print(length);
Serial.println(" bytes:");
while (mqttClient.available()) {
Serial.print((char)mqttClient.read());
}
Serial.println();
}
static char *getTelemetryPayload() {
az_span temp_span = az_span_create(telemetry_payload, sizeof(telemetry_payload));
temp_span = az_span_copy(temp_span, AZ_SPAN_FROM_STR("{ \"msgCount\": "));
(void)az_span_u32toa(temp_span, telemetry_send_count++, &temp_span);
temp_span = az_span_copy(temp_span, AZ_SPAN_FROM_STR(" }"));
temp_span = az_span_copy_u8(temp_span, '\0');
return (char *)telemetry_payload;
}
static void sendTelemetry() {
Logger.Info("Sending telemetry . . . ");
if (az_result_failed(az_iot_hub_client_telemetry_get_publish_topic(
&client, NULL, telemetry_topic, sizeof(telemetry_topic), NULL))) {
Logger.Error("Failed az_iot_hub_client_telemetry_get_publish_topic");
return;
}
char *telemetry = getTelemetryPayload();
mqttClient.beginMessage(telemetry_topic, sizeof(telemetry), DO_NOT_RETAIN_MSG, MQTT_QOS1, false);
mqttClient.print(telemetry);
mqttClient.endMessage();
Logger.Info("OK");
delay(100);
}
static void initializeIoTHubClient() {
az_iot_hub_client_options options = az_iot_hub_client_options_default();
options.user_agent = AZ_SPAN_FROM_STR(AZURE_SDK_CLIENT_USER_AGENT);
if (az_result_failed(az_iot_hub_client_init(
&client,
az_span_create((uint8_t *)host, strlen(host)),
az_span_create((uint8_t *)device_id, strlen(device_id)),
&options))) {
Logger.Error("Failed initializing Azure IoT Hub client");
return;
}
size_t client_id_length;
if (az_result_failed(az_iot_hub_client_get_client_id(
&client, mqtt_client_id, sizeof(mqtt_client_id) - 1, &client_id_length))) {
Logger.Error("Failed getting client id");
return;
}
if (az_result_failed(az_iot_hub_client_get_user_name(
&client, mqtt_username, sizeofarray(mqtt_username), NULL))) {
Logger.Error("Failed to get MQTT clientId, return code");
return;
}
Logger.Info("Client ID: " + String(mqtt_client_id));
Logger.Info("Username: " + String(mqtt_username));
}
static int initializeMqttClient() {
int result;
int token_result = sasToken.Generate(SAS_TOKEN_DURATION_IN_MINUTES);
if (token_result != 0) {
Logger.Error("Failed generating SAS token");
result = 1;
}
Logger.Info("MQTT client target uri set to " + String(mqtt_broker_uri));
if (!mqttClient.connect(mqtt_broker_uri, mqtt_port)) {
Logger.Error("Could not start mqtt client; error code:" + String(mqttClient.connectError()));
mqttClient.stop();
result = 1;
} else {
Logger.Info("MQTT client started");
mqttClient.setId(mqtt_client_id);
mqttClient.setKeepAliveInterval(30);
mqttClient.setCleanSession(false);
mqttClient.onMessage(onMqttMessage);
Logger.Info("Subscribing to topic:" + String(telemetry_topic));
mqttClient.subscribe(telemetry_topic, MQTT_QOS1);
result = 0;
}
return result;
}
static void connectToWiFi() {
Logger.Info("Connecting to WIFI SSID " + String(ssid));
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(3000);
Serial.print(".");
}
Serial.println("");
Logger.Info("WiFi connected, IP address: " + String(WiFi.localIP()));
}
static void initializeTime() {
Logger.Info("Setting time using SNTP");
timeClient.begin();
Logger.Info("Time initialized!");
}
void setup() {
Serial.begin(9600);
while (!Serial) {}
connectToWiFi();
initializeTime();
initializeIoTHubClient();
initializeMqttClient();
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
connectToWiFi();
}
if (sasToken.IsExpired() || !mqttClient.connected()) {
Logger.Info("SAS token expired; reconnecting with a new one.");
initializeMqttClient();
}
mqttClient.poll();
timeClient.update();
if (millis() > next_telemetry_send_time_ms) {
sendTelemetry();
next_telemetry_send_time_ms = millis() + TELEMETRY_FREQUENCY_MILLISECS;
}
}

Просмотреть файл

@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#include "SerialLogger.h"
#include <time.h>
#define UNIX_EPOCH_START_YEAR 1900
static void writeTime()
{
struct tm* ptm;
time_t now = time(NULL);
ptm = gmtime(&now);
Serial.print(ptm->tm_year + UNIX_EPOCH_START_YEAR);
Serial.print("/");
Serial.print(ptm->tm_mon + 1);
Serial.print("/");
Serial.print(ptm->tm_mday);
Serial.print(" ");
if (ptm->tm_hour < 10)
{
Serial.print(0);
}
Serial.print(ptm->tm_hour);
Serial.print(":");
if (ptm->tm_min < 10)
{
Serial.print(0);
}
Serial.print(ptm->tm_min);
Serial.print(":");
if (ptm->tm_sec < 10)
{
Serial.print(0);
}
Serial.print(ptm->tm_sec);
}
SerialLogger::SerialLogger() { Serial.begin(SERIAL_LOGGER_BAUD_RATE); }
void SerialLogger::Info(String message)
{
writeTime();
Serial.print(" [INFO] ");
Serial.println(message);
}
void SerialLogger::Error(String message)
{
writeTime();
Serial.print(" [ERROR] ");
Serial.println(message);
}
SerialLogger Logger;

Просмотреть файл

@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#ifndef SERIALLOGGER_H
#define SERIALLOGGER_H
#include <Arduino.h>
#ifndef SERIAL_LOGGER_BAUD_RATE
#define SERIAL_LOGGER_BAUD_RATE 115200
#endif
class SerialLogger
{
public:
SerialLogger();
void Info(String message);
void Error(String message);
};
extern SerialLogger Logger;
#endif // SERIALLOGGER_H

Просмотреть файл

@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
// Wifi
#define IOT_CONFIG_WIFI_SSID "SSID"
#define IOT_CONFIG_WIFI_PASSWORD "PWD"
// Azure IoT
#define IOT_CONFIG_IOTHUB_FQDN "[your Azure IoT host name].azure-devices.net"
#define IOT_CONFIG_DEVICE_ID "Device ID"
#define IOT_CONFIG_DEVICE_KEY "Device Key"
// Publish 1 message every 2 seconds
#define TELEMETRY_FREQUENCY_MILLISECS 2000

Просмотреть файл

@ -0,0 +1,199 @@
---
page_type: sample
description: Connecting a Arduino Portenta H7 device to Azure IoT using the Azure SDK for Embedded C
languages:
- c
products:
- azure-iot
- azure-iot-pnp
- azure-iot-dps
- azure-iot-hub
---
# How to Setup and Run Azure SDK for Embedded C IoT Hub Client on Arduino Portenta H7
- [Introduction](#introduction)
- [What is Covered](#what-is-covered)
- [Prerequisites](#prerequisites)
- [Setup and Run Instructions](#setup-and-run-instructions)
- [Certificates - Important to know](#certificates---important-to-know)
- [Additional Information](#additional-information)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
- [License](#license)
## Introduction
This is a guide outlining how to run an Azure SDK for Embedded C IoT Hub telemetry sample on an Arduino Portenta H7 development board.
### What is Covered
- Configuration instructions for the Arduino IDE to compile a sample using the Azure SDK for Embedded C.
- Configuration, build, and run instructions for the IoT Hub telemetry sample.
_The following was run on Windows 11 environments, with Arduino IDE 1.8.19 and Arduino Mbed OS Portenta Boards module 2.8.0._
## Prerequisites
- Have an [Azure account](https://azure.microsoft.com/) created.
- Have an [Azure IoT Hub](https://docs.microsoft.com/azure/iot-hub/iot-hub-create-through-portal) created.
- Have a [logical device](https://docs.microsoft.com/azure/iot-hub/iot-hub-create-through-portal#register-a-new-device-in-the-iot-hub) created in your Azure IoT Hub using the authentication type "Symmetric Key".
NOTE: Device keys are used to automatically generate a SAS token for authentication, which is only valid for one hour.
- Have the latest [Arduino IDE](https://www.arduino.cc/en/Main/Software) installed.
- Have the [Arduino Portenta H7 board packages](https://docs.arduino.cc/tutorials/portenta-h7/por-ard-gs) installed on Arduino IDE. Mbed OS boards are not natively supported by Arduino IDE, so you need to add them manually.
- Have one of the following interfaces to your Azure IoT Hub set up:
- [Azure Command Line Interface](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest) (Azure CLI) utility installed, along with the [Azure IoT CLI extension](https://github.com/Azure/azure-iot-cli-extension).
On Windows:
Download and install: https://aka.ms/installazurecliwindows
```powershell
PS C:\>az extension add --name azure-iot
```
On Linux:
```bash
$ curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
$ az extension add --name azure-iot
```
A list of all the Azure IoT CLI extension commands can be found [here](https://docs.microsoft.com/cli/azure/iot?view=azure-cli-latest).
- The most recent version of [Azure IoT Explorer](https://github.com/Azure/azure-iot-explorer/releases) installed. More instruction on its usage can be found [here](https://docs.microsoft.com/azure/iot-pnp/howto-use-iot-explorer).
NOTE: This guide demonstrates use of the Azure CLI and does NOT demonstrate use of Azure IoT Explorer.
## Setup and Run Instructions
1. Run the Arduino IDE.
2. Install the required libraries:
1. In the Arduino IDE, go to menu `Sketch`, `Include Library`, `Manage Libraries...`.
1. Search for and install the following:
- `Azure SDK for C` by Microsoft ([repo](https://github.com/Azure/azure-sdk-for-c-arduino))
- `ArduinoMqttLibrary` by Arduino ([repo](https://github.com/arduino-libraries/ArduinoMqttClient))
- `NTPClient_Generic` ([repo](https://github.com/khoih-prog/NTPClient_Generic))
3. Open the Arduino Portenta H7 sample.
1. On the Arduino IDE, go to menu `File`, `Examples`, `azure-sdk-for-c`.
1. Click on `Azure_IoT_Hub_PortentaH7` to open the sample.
4. Configure the Arduino Portenta H7 sample.
Enter your Azure IoT Hub and device information into the sample's `iot_configs.h`.
5. Connect the Arduino Portenta H7 board to your USB port.
6. On the Arduino IDE, select the board and port.
- Go to menu `Tools`, `Board` and select `Arduino Mbed OS Portenta Boards`/`Arduino Portenta H7 (M7 core)` .
- Go to menu `Tools`, `Port` and select the port to which the microcontroller is connected.
7. Upload the sketch.
- Go to menu `Sketch` and click on `Upload`.
8. Monitor the MCU (microcontroller) locally via the Serial Port.
- Go to menu `Tools`, `Serial Monitor`.
If you perform this step right away after uploading the sketch, the serial monitor will show an output similar to the following upon success:
```text
Connecting to WIFI SSID buckaroo
.......................WiFi connected, IP address:
192.168.1.123
Setting time using SNTP..............................done!
Current time: Thu May 28 02:55:05 2020
Client ID: mydeviceid
Username: myiothub.azure-devices.net/mydeviceid/?api-version=2018-06-30&DeviceClientType=c%2F1.0.0
Password: SharedAccessSignature sr=myiothub.azure-devices.net%2Fdevices%2Fmydeviceid&sig=placeholder-password&se=1590620105
MQTT connecting ... connected.
```
9. Monitor the telemetry messages sent to the Azure IoT Hub using the connection string for the policy name `iothubowner` found under "Shared access policies" on your IoT Hub in the Azure portal.
```bash
$ az iot hub monitor-events --login <your Azure IoT Hub owner connection string in quotes> --device-id <your device id>
```
<details><summary><i>Expected telemetry output:</i></summary>
<p>
```bash
Starting event monitor, filtering on device: mydeviceid, use ctrl-c to stop...
{
"event": {
"origin": "mydeviceid",
"payload": "payload"
}
}
{
"event": {
"origin": "mydeviceid",
"payload": "payload"
}
}
{
"event": {
"origin": "mydeviceid",
"payload": "payload"
}
}
{
"event": {
"origin": "mydeviceid",
"payload": "payload"
}
}
{
"event": {
"origin": "mydeviceid",
"payload": "payload"
}
}
{
"event": {
"origin": "mydeviceid",
"payload": "payload"
}
}
^CStopping event monitor...
```
</p>
</details>
## Certificates - Important to know
The Azure IoT service certificates presented during TLS negotiation shall always be validated, on the device, using the appropriate trusted root CA certificate(s).
For the Arduino Portenta H7 sample, our script `generate_arduino_zip_library.sh` automatically downloads the root certificate used in the United States regions (Baltimore CA certificate) and adds it to the Arduino sketch project.
For other regions (and private cloud environments), please use the appropriate root CA certificate.
### Additional Information
For important information and additional guidance about certificates, please refer to [this blog post](https://techcommunity.microsoft.com/t5/internet-of-things/azure-iot-tls-changes-are-coming-and-why-you-should-care/ba-p/1658456) from the security team.
## Troubleshooting
- The error policy for the Embedded C SDK client library is documented [here](https://github.com/Azure/azure-sdk-for-c/blob/main/sdk/docs/iot/mqtt_state_machine.md#error-policy).
- File an issue via [Github Issues](https://github.com/Azure/azure-sdk-for-c/issues/new/choose).
- Check [previous questions](https://stackoverflow.com/questions/tagged/azure+c) or ask new ones on StackOverflow using the `azure` and `c` tags.
## Contributing
This project welcomes contributions and suggestions. Find more contributing details [here](https://github.com/Azure/azure-sdk-for-c/blob/main/CONTRIBUTING.md).
### License
This Azure SDK for C Arduino library is licensed under [MIT](https://github.com/Azure/azure-sdk-for-c-arduino/blob/main/LICENSE) license.
Azure SDK for Embedded C is licensed under the [MIT](https://github.com/Azure/azure-sdk-for-c/blob/main/LICENSE) license.