Azure IoT Hub

The Azure IoT Hub library provides an API to connect to an Azure IoT Hub instance and interact with it. It connects to Azure IoT Hub using MQTT over TLS.

Optionally, the library supports Azure IoT Hub Device Provisioning Service (DPS). DPS can be enabled at compile time to make use of the device provisioning services for onboarding of devices to Azure IoT Hub. When the device provisioning is complete, the library automatically connects to the assigned Azure IoT Hub.

The library also has integrated support for Azure FOTA. For more information on Azure FOTA, see the documentation on Azure FOTA library and nRF9160: Azure FOTA sample.

Important

If the server sends a device-bound message when the device is unavailable for a period of time, for instance while in LTE Power Saving Mode, the server will most likely terminate the TCP connection. This will result in additional data traffic as the device has to reconnect to the server, which in turn requires a new TLS handshake and MQTT connection establishment.

Prerequisites for connecting to Azure IoT Hub

In order to connect to Azure IoT Hub, an Azure account and an Azure IoT Hub instance must first be created and configured. See Creating an Azure IoT Hub instance using the Azure portal for more information.

Note

If you do not use DPS to provision devices to your IoT Hub, make sure that you select X.509 CA Signed as the Authentication type while Registering the device with Azure IoT Hub.

The connection to Azure IoT Hub with MQTT is secured using TLS. For testing purposes, see Creating Azure IoT Hub certificates for the steps to create certificates and a private key for the leaf device, and to register the generated test root certificate to be used with an IoT hub.

The Azure IoT Hub library requires the provisioning of the following certificates and a private key for a successful TLS connection:

  1. Baltimore CyberTrust Root certificate - Server certificate, used to verify the server’s certificate while connecting.

  2. Public device certificate - generated by the procedures described in Creating Azure IoT Hub certificates , used by Azure IoT Hub to authenticate the device.

  3. Private key of the device.

Note

The location and name of the generated public device certificate and private key files vary depending on the method you use for the credential generation. For PowerShell scripts, the device certificate is called mydevice-public.pem and the private key is mydevice-private.pem. These files are located in the working directory with the other generated files.

For bash scripts, the public device certificate is called new-device.cert.pem and is located in a directory called certs within the script directory. The private key is called new-device.key.pem and located in a directory called private within the script directory.

The file and directory names may change if Azure changes their scripts.

Provisioning of the certificates

To provision the certificates and the private key to the nRF9160 modem, complete the following steps:

  1. Download nRF Connect for Desktop.

  2. Update the modem firmware on the onboard modem of the nRF9160-based device to the latest version by following the steps in Updating the modem firmware.

  3. Build and program the nRF9160: AT Client sample to the nRF9160-based device as explained in Building and programming an application.

  4. Launch the LTE Link Monitor application, which is part of nRF Connect for Desktop.

  5. Click Certificate manager located at the top right corner.

  6. Copy the Baltimore CyberTrust Root certificate into the CA certificate entry.

  7. Copy and paste the device certificate and the key created using the scripts located in Creating Azure IoT Hub certificates, into the respective entries (Client certificate, Private key).

  8. Select a desired security tag (any positive integer, for example, 42) and click Update certificates.

Note

The chosen security tag while provisioning the certificates must be same as the security tag configured by the CONFIG_AZURE_IOT_HUB_SEC_TAG option.

Configuring the library

You can configure the library to connect to Azure IoT Hub with or without using DPS.

Configuration without using DPS

To connect to Azure IoT Hub without using DPS, complete the following minimum required configuration:

  1. In the Azure Portal, navigate to IoT Hub and select the desired IoT hub.

  2. In the overview page, locate and copy the Hostname and configure CONFIG_AZURE_IOT_HUB_HOSTNAME to this address.

  3. Set the option CONFIG_AZURE_IOT_HUB_DEVICE_ID to the device ID. The device ID must match the device ID used while creating the certificates.

  4. Make sure that the device is already registered with your Azure IoT Hub, or follow the instructions in Registering the device with Azure IoT Hub.

  5. Set CONFIG_AZURE_IOT_HUB_SEC_TAG to the security tag used in Provisioning of the certificates.

Configuration using DPS

To connect to Azure IoT Hub using DPS, complete the following steps:

  1. Set up an Azure IoT Hub Device Provisioning Service (DPS) instance and obtain the ID scope.

  2. Add certificates to the DPS instance.

  3. Create an enrollment group as described in Device enrollments with Azure Portal and link it to your IoT hub. Select the certificate added in the previous step as the Primary certificate​​​​​​​.

  4. Enable CONFIG_AZURE_IOT_HUB_DPS.

  5. In the Azure Portal, click Device Provisioning Services and select the DPS instance to use.

  6. In the overview page, locate and copy the ID Scope and configure CONFIG_AZURE_IOT_HUB_DPS_ID_SCOPE to this string.

  7. Set the CONFIG_AZURE_IOT_HUB_DEVICE_ID option to device ID, unless CONFIG_AZURE_IOT_HUB_DEVICE_ID_APP is enabled. The device ID must match the device ID used while creating the certificates.

  8. Set CONFIG_AZURE_IOT_HUB_SEC_TAG to the security tag used while Provisioning of the certificates.

Initializing the library

The library is initialized by calling the azure_iot_hub_init() function. If the initialization fails, the application cannot use any APIs of the library. Optionally, you can enable CONFIG_AZURE_IOT_HUB_DEVICE_ID_APP and include a pointer to the azure_iot_hub_config structure containing the device ID in the azure_iot_hub_init() function call.

Below is an example for setting the device ID at run time instead of compile time by configuring the CONFIG_AZURE_IOT_HUB_DEVICE_ID option:

struct azure_iot_hub_config cfg = {
    .device_id = "my-device",
    .device_id_len = sizeof("my-device") - 1,
};

int err = azure_iot_hub_init(&cfg, event_handler);
if (err) {
    printk("azure_iot_hub_init failed: %d\n", err);
    return err;
}

Connecting to Azure IoT Hub

After the initialization, a azure_iot_hub_connect() function call connects the device to the configured IoT hub or DPS instance, depending on the configuration. The initial TLS handshake takes some time to complete, typically in the range of few seconds, depending on the network conditions and the TLS cipher suite used. During the TLS handshake, azure_iot_hub_connect() blocks, so care must be taken when deciding the context from which the API is called.

After a successful connection, the library automatically subscribes to the following standard Azure IoT Hub MQTT topics (See Azure IoT Hub MQTT protocol support for details):

  • devices/<device ID>/messages/devicebound/# (cloud-to-device messages)

  • $iothub/twin/PATCH/properties/desired/# (desired properties update notifications)

  • $iothub/twin/res/# (operation responses)

  • $iothub/methods/POST/# (direct method requests)

Currently, the library does not support persistent MQTT sessions. Hence subscriptions are requested for each connection to the IoT hub.

Configuration

Configure the following parameters when using this library:

API documentation

Header file: include/net/azure_iot_hub.h
Source files: subsys/net/lib/azur_iot_hub/src/
group azure_iot_hub

Library to connect a device to Azure IoT Hub.

Typedefs

typedef void (*azure_iot_hub_evt_handler_t)(struct azure_iot_hub_evt *evt)

Azure IoT Hub library event handler.

Param evt

Pointer to event structure.

Enums

enum azure_iot_hub_evt_type

Azure IoT Hub notification events used to notify the user.

Values:

enumerator AZURE_IOT_HUB_EVT_CONNECTING

Connecting to Azure IoT Hub.

enumerator AZURE_IOT_HUB_EVT_CONNECTED

Connected to Azure IoT Hub.

enumerator AZURE_IOT_HUB_EVT_CONNECTION_FAILED

Connection attempt failed. The reported error code from the IoT Hub is available in the data.err member in the event structure. The error codes correspond to return codes in MQTT CONNACK messages.

enumerator AZURE_IOT_HUB_EVT_READY

Azure IoT Hub connection established and ready.

enumerator AZURE_IOT_HUB_EVT_DISCONNECTED

Disconnected from Azure IoT Hub.

enumerator AZURE_IOT_HUB_EVT_DATA_RECEIVED

Device-bound data received from Azure IoT Hub.

enumerator AZURE_IOT_HUB_EVT_PUBACK

Acknowledgment for data sent to Azure IoT Hub.

enumerator AZURE_IOT_HUB_EVT_TWIN_RECEIVED

Device twin has been received.

enumerator AZURE_IOT_HUB_EVT_TWIN_DESIRED_RECEIVED

Device twin has received a desired property update.

enumerator AZURE_IOT_HUB_EVT_TWIN_RESULT_SUCCESS

Device twin update successful. The request ID and status are contained in the data.result member of the event structure.

enumerator AZURE_IOT_HUB_EVT_TWIN_RESULT_FAIL

Device twin update failed. The request ID and status are contained in the data.result member of the event structure.

enumerator AZURE_IOT_HUB_EVT_DPS_CONNECTING

Connecting to Device Provisioning Service.

enumerator AZURE_IOT_HUB_EVT_DPS_REGISTERING

Device Provisioning Service registration has started.

enumerator AZURE_IOT_HUB_EVT_DPS_DONE

Device Provisioning Service is done, and Azure IoT Hub information obtained.

enumerator AZURE_IOT_HUB_EVT_DPS_FAILED

Device Provisioning Service failed to retrieve information to connect to Azure IoT Hub.

enumerator AZURE_IOT_HUB_EVT_DIRECT_METHOD

Direct method invoked from the cloud side.

Note

After a direct method has been executed, azure_iot_hub_method_respond must be called to report back the result of the method invocation.

enumerator AZURE_IOT_HUB_EVT_FOTA_START

FOTA download starting.

enumerator AZURE_IOT_HUB_EVT_FOTA_DONE

FOTA update done, reboot required to apply update.

enumerator AZURE_IOT_HUB_EVT_FOTA_ERASE_PENDING

FOTA erase pending. On nRF9160-based devices this is typically caused by an active LTE connection preventing erase operation.

enumerator AZURE_IOT_HUB_EVT_FOTA_ERASE_DONE

FOTA erase done.

enumerator AZURE_IOT_HUB_EVT_FOTA_ERROR

FOTA failed

enumerator AZURE_IOT_HUB_EVT_ERROR

Internal library error

enum azure_iot_hub_topic_type

Azure IoT Hub topic type, used to route messages to the correct destination.

Values:

enumerator AZURE_IOT_HUB_TOPIC_DEVICEBOUND

Data received on the devicebound topic.

enumerator AZURE_IOT_HUB_TOPIC_EVENT

Event topic used to send event data to Azure IoT Hub.

enumerator AZURE_IOT_HUB_TOPIC_TWIN_DESIRED

Received “desired” properties from the device twin.

enumerator AZURE_IOT_HUB_TOPIC_TWIN_REPORTED

Send updates to the “reported” properties in the device twin.

enumerator AZURE_IOT_HUB_TOPIC_TWIN_REQUEST

Topic to request to receive the device twin.

Functions

int azure_iot_hub_init(const struct azure_iot_hub_config *config, azure_iot_hub_evt_handler_t event_handler)

Initialize the module.

Warning

This API must be called exactly once, and it must return successfully for subsequent calls to this library to succeed.

Parameters
  • config[in] Pointer to struct containing connection parameters. Can be NULL if CONFIG_AZURE_IOT_HUB_DEVICE_ID is set.

  • event_handler[in] Pointer to event handler function.

Return values

0 – If successful. Otherwise, a (negative) error code is returned.

int azure_iot_hub_connect(void)

Establish connection to Azure IoT Hub. The function blocks until a connection to the hub is established on the transport level. Subsequent calls to other library function should await AZURE_IOT_HUB_EVT_CONNECTED and AZURE_IOT_HUB_EVT_READY events.

Return values

0 – If successful. Otherwise, a (negative) error code is returned.

int azure_iot_hub_disconnect(void)

Disconnect from Azure IoT Hub. Calling this function initiates the disconnection procedure, and the event AZURE_IOT_HUB_EVT_DISCONNECTED is received when it is completed.

Return values

0 – If successful. Otherwise, a (negative) error code is returned.

int azure_iot_hub_send(const struct azure_iot_hub_data *const tx_data)

Send data to Azure IoT Hub.

Parameters
  • tx_data[in] Pointer to struct containing data to be transmitted to Azure IoT Hub.

Return values

0 – If successful. Otherwise, a (negative) error code is returned.

int azure_iot_hub_input(void)

Receive incoming data from Azure IoT Hub.

Implicitly this function calls a non-blocking recv() on the socket with IoT hub connection. It can be polled periodically, but by default this functionality is handled internally in the library.

Return values

0 – If successful. Otherwise, a (negative) error code is returned.

int azure_iot_hub_ping(void)

Ping Azure IoT Hub. Must be called periodically to keep connection alive. By default ping is handled internally in the library.

Return values

0 – If successful. Otherwise, a (negative) error code is returned.

int azure_iot_hub_method_respond(struct azure_iot_hub_result *result)

Send response to a direct method invoked from the cloud.

Parameters
  • result[in] Structure containing result data from the direct method execution.

Return values

0 – If successful. Otherwise, a (negative) error code is returned.

int azure_iot_hub_keepalive_time_left(void)

Helper function to determine when next ping should be sent in order to keep the connection alive. By default, ping is sent in time automatically by the library.

Returns

Time in milliseconds until next keepalive ping will be sent.

Returns

-1 if keepalive messages are not enabled.

int azure_iot_hub_dps_reset(void)

Reset the stored Azure IoT Hub device provisioning data. This can be used to trigger a new provisioning of the device upon next time the device initiates connection to an IoT Hub.

Return values

0 – If successful. Otherwise, a (negative) error code is returned.

struct azure_iot_hub_prop_bag
#include <azure_iot_hub.h>

Property bag structure for key/value string pairs. Per Azure IoT Hub documentation, the key must be defined, while the value can be a string, an empty string or NULL.

Note

If value is provided as a string, it’s the equivalent to “key=value”. If the value is an empty string (only null-terminator), it’s the equivalent of “key=”. If value is NULL, it’s the equivalent of “key”.

Public Members

char *key

Null-terminated key string.

char *value

Null-terminated value string.

struct azure_iot_hub_topic_data
#include <azure_iot_hub.h>

Azure IoT Hub topic data.

Public Members

enum azure_iot_hub_topic_type type

Topic type.

char *str

Pointer to topic name.

size_t len

Length of topic name.

struct azure_iot_hub_data
#include <azure_iot_hub.h>

Azure IoT Hub transmission data.

Public Members

struct azure_iot_hub_topic_data topic

Topic data is sent/received on.

char *ptr

Pointer to data sent/received from Azure IoT Hub.

size_t len

Length of data.

enum mqtt_qos qos

Quality of Service for the message.

uint16_t message_id

Message id used for the message, used to match acknowledgments.

uint8_t dup_flag

Duplicate flag. 1 indicates the message is a retransmission, Usually triggered by missing publication acknowledgment.

uint8_t retain_flag

Retain flag. 1 indicates to the IoT hub that the message should be stored persistently.

struct azure_iot_hub_method
#include <azure_iot_hub.h>

Azure IoT Hub direct method data.

Public Members

const char *name

Method name, null-terminated string.

char *rid

Method request ID, null-terminated string.

const char *payload

Method payload.

size_t payload_len

Method payload length.

struct azure_iot_hub_result
#include <azure_iot_hub.h>

Azure IoT Hub result structure.

Used to signal result of direct method execution from device to cloud, and to receive result of device twin updates (twin updates sent from the device will receive a result message back from the cloud with success or failure).

Public Members

char *rid

Request ID to which the result belongs, null-terminated string.

uint32_t status

Status code.

const char *payload

Result payload.

size_t payload_len

Size of payload.

struct azure_iot_hub_evt
#include <azure_iot_hub.h>

Struct with data received from Azure IoT Hub.

Public Members

enum azure_iot_hub_evt_type type

Type of event.

struct azure_iot_hub_config
#include <azure_iot_hub.h>

Structure for Azure IoT Hub connection parameters.

Public Members

int socket

Socket for the Azure IoT Hub connection. Polling on the socket happens internally in the library.

char *device_id

Device id for the Azure IoT Hub connection. If NULL, the device ID provided by Kconfig is used.

size_t device_id_len

Length of device string.