Skip to main content

Azure IoT Hub

Latest Version: 5.1.0

Azure IoT Hub is an Electric Imp agent-side library for interfacing with Azure IoT Hub API version "2016-11-14". Starting with version 3, the library integrates with Azure IoT Hub using the MQTT protocol (previous versions used AMQP) as there is certain functionality, such as Device Twins and Direct Methods, that IoT Hub only supports via MQTT. Starting with version 5, the library supports the Azure IoT Hub Device Provisioning Service.

The library consists of the following classes and methods:

You can view the library’s source code on GitHub. Click here to see information on the available versions of this library.

To include this library in your project, add

#require "AzureIoTHub.agent.lib.nut:5.1.0"

at the top of your agent code.

Authentication

You will need a Microsoft Azure account. If you do not have one, please sign up here before continuing.

Communication with a concrete Azure IoT Hub uses the AzureIoTHub.Client class. To instantiate an object of this class and authenticate a device in the Azure IoT Hub, you need to have a Device Connection String. It may be obtained in one of the following ways:

Using The Device Provisioning Service

Use this method when you have several Azure IoT Hubs and an instance of the Azure Device Provisioning Service, which distributes your devices between the hubs. This is the primary production-oriented method.

  1. Open the Azure Portal. You need to have owner-level permissions.
  2. Select or create your Azure IoT Hub resource(s).
  3. Select or create your Azure IoT Hub Device Provisioning Service (DPS) resource.
  4. Open the Overview page of your DPS, copy the ID Scope to the clipboard and paste it (as the scopeId parameter) into the AzureIoTHub.DPS constructor in your Squirrel application code.
  5. Link your IoT Hub(s) to the DPS (if not linked yet) on the Linked IoT hubs page of your DPS.
  6. Create an Individual Enrollment on the Manage enrollments page of your DPS (if not created yet). The enrollment must use the Symmetric key attestation mechanism.
  7. Open your Individual Enrollment, copy the Primary key to the clipboard and paste it (as the deviceKey parameter) into the AzureIoTHub.DPS constructor in your Squirrel application code.
  8. Put the Registration ID you used when creating the Individual Enrollment into the AzureIoTHub.DPS constructor’s registrationId parameter in your Squirrel application code.
  9. Using the AzureIoTHub.DPS instance’s register() method, register your device in the IoT Hub and obtain a Device Connection String.
  10. Pass the Device Connection String into the AzureIoTHub.Client constructor.

Using The IoT Hub Registry

Use this method when you have only one Azure IoT Hub, or when you know in advance which device should be registered in which IoT Hub.

  1. Open the Azure Portal. You need to have owner-level permissions.
  2. Select or create your Azure IoT Hub resource.
  3. Under Settings click Shared Access Policies.
  4. Select a policy which has read/write permissions (such as the registryReadWrite) or create a new policy.
  5. Copy the Connection string--primary key to the clipboard and paste it into the AzureIoTHub.Registry constructor in your Squirrel application code.
  6. Using the AzureIoTHub.Registry instance’s create() method, register your device in the IoT Hub and obtain the device description as an instance of the AzureIoTHub.Device class.
  7. Using the AzureIoTHub.Device instance’s connectionString() method, get the Device Connection String and pass it into the AzureIoTHub.Client constructor.

Using The Azure Portal

Use this method if your device is already registered in an Azure IoT Hub. In this case you can obtain the Device Connection String from the Azure portal.

  1. Open the Azure Portal. You need to have device-level permissions.
  2. Select or create your Azure IoT Hub resource.
  3. Click Device Explorer.
  4. Select your device — you will need to know the device ID used to register the device with IoT Hub.
  5. Copy the Connection string--primary key (this is the Device Connection String) to the clipboard and paste it into the AzureIoTHub.Client constructor in your Squirrel application code.

AzureIoTHub.Registry

The AzureIoTHub.Registry class is used to manage IoT Hub devices. This class allows you to create, remove, update, delete and list the IoT Hub devices in your Azure account. Please see the ‘Authentication’ section, above, for access information.

AzureIoTHub.Registry Class Usage

Constructor: AzureIoTHub.Registry(connectionString)

This method instantiates an AzureIoTHub.Registry object which exposes the Device Registry functions.

Parameters

Parameter Data Type Required? Description
connectionString String Yes Provided by the Azure Portal (see ‘Authentication’, above)

Example

#require "AzureIoTHub.agent.lib.nut:5.1.0"

// Instantiate a client using your connection string
const AZURE_REGISTRY_CONN_STRING = "HostName=<HUB_ID>.azure-devices.net;SharedAccessKeyName=<KEY_NAME>;SharedAccessKey=<KEY_HASH>";
registry <- AzureIoTHub.Registry(AZURE_REGISTRY_CONN_STRING);

AzureIoTHub.Registry Class Methods

All class methods make asynchronous HTTP requests to IoT Hub. Each one can therefore take a callback function which will be executed when a response is received from IoT Hub. The callback provides the following parameters:

Parameter Value
err This will be null if there was no error. Otherwise it will be a table containing two keys: response, the original httpresponse object, and message, an error report string
response For create(), update() and get(): an AzureIoTHub.Device object.
For list(): an array of AzureIoTHub.Device objects.
For remove(): nothing

create([deviceInfo][, callback])

This method creates a new device identity in IoT Hub.

Parameters

Parameter Data Type Required? Description
deviceInfo Table No Must contain the required keys specified in the Device Info Table or an AzureIoTHub.Device object. If the deviceInfo table’s deviceId key is not provided, the agent’s ID will be used
callback Function No A function to be called when the IoT Hub responds

update(deviceInfo[, callback])

This method updates an existing device identity in IoT Hub. The update function cannot change the values of any read-only properties, including the deviceId, and the statusReason value cannot be updated via this method.

Parameters

Parameter Data Type Required? Description
deviceInfo Table Yes Must contain the required keys specified in the Device Info Table or an AzureIoTHub.Device object. It must include a deviceId key
callback Function No A function to be called when the IoT Hub responds

remove(deviceID[, callback])

This method deletes a single device identity from IoT Hub.

Parameters

Parameter Data Type Required? Description
deviceID String Yes A device identifier
callback Function No A function to be called when the IoT Hub responds

get(deviceId, callback)

This method requests the properties of an existing device identity in IoT Hub.

Parameters

Parameter Data Type Required? Description
deviceID String Yes A device identifier
callback Function Yes A function to be called when the IoT Hub responds

list(callback)

This method requests a list of device identities. When IoT Hub responds, an array of up to 1000 existing AzureIoTHub.Device objects will be passed to the callback function.

Parameters

Parameter Data Type Required? Description
callback Function Yes A function to be called when the IoT Hub responds

AzureIoTHub.Registry Example

This example code will create an IoT Hub device using an imp’s agent ID if one isn’t found in the IoT Hub device registry. It will then instantiate the AzureIoTHub.Client class for later use.

#require "AzureIoTHub.agent.lib.nut:5.1.0"

const AZURE_REGISTRY_CONN_STRING = "HostName=<HUB_ID>.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=<KEY_HASH>";

client <- null;
local agentId = split(http.agenturl(), "/").pop();

local registry = AzureIoTHub.Registry(AZURE_REGISTRY_CONN_STRING);
local hostname = AzureIoTHub.ConnectionString.Parse(AZURE_REGISTRY_CONN_STRING).HostName;

function onConnected(err) {
    if (err != 0) {
        server.error("Connection failed: " + err);
    }
}

function createDevice() {
    registry.create({"deviceId" : agentId}, function(error, iotHubDevice) {
        if (error) {
            server.error(error.message);
        } else {
            server.log("Created " + iotHubDevice.getBody().deviceId);

            // Create a client with the device authentication provided from the registry response
            ::client <- AzureIoTHub.Client(iotHubDevice.connectionString(hostname), onConnected);
        }
    }.bindenv(this));
}

// Find this device in the registry
registry.get(agentId, function(err, iothubDevice) {
    if (err) {
        if (err.response.statuscode == 404) {
            // No such device, so let's create one with default parameters
            createDevice();
        } else {
            server.error(err.message);
        }
    } else {
        // Found the device 
        server.log("Device registered as " + iothubDevice.getBody().deviceId);

        // Create a client with the device authentication provided from the registry response
        ::client <- AzureIoTHub.Client(iothubDevice.connectionString(hostname), onConnected);
    }
}.bindenv(this));

AzureIoTHub.Device

The AzureIoTHub.Device class is used to create Devices identity objects used by the AzureIoTHub.Registry class. Registry methods will create device objects for you if you choose to pass in tables.

AzureIoTHub.Device Class Usage

Constructor: AzureIoTHub.Device([deviceInfo])

The constructor creates a device object from the deviceInfo parameter. See the Device Info Table below for details on what to include in the table. If no deviceInfo is provided, default settings will be used.

Parameters

Parameter Data Type Required? Description
deviceInfo Table No Device specification information: see ‘Device Info Table’, below

Device Info Table

Key Required? Description
deviceId Yes, read-only on updates A case-sensitive string (up to 128 characters long) of Ascii 7-bit alphanumeric characters plus -, :, ., +, %, _, #, *, ?, !, (, ), =, @, ;, $, ' and ,
Default: the device’s agent ID
generationId Read only An IoT Hub-generated, case-sensitive string up to 128 characters long. This value is used to distinguish devices with the same deviceId, when they have been deleted and re-created. Default: null
etag Read only A string representing a weak ETag for the device identity, as per RFC7232. Default: null
connectionState Read only A field indicating connection status: either "Connected" or "Disconnected". This field represents the IoT Hub view of the device connection status. Important This field should be used only for development/debugging purposes. The connection state is updated only for devices using MQTT or AMQP. It is based on protocol-level pings (MQTT pings, or AMQP pings), and it can have a maximum delay of only five minutes. For these reasons, there can be false positives, such as devices reported as connected but that are disconnected. Default: "Disconnected"
status Yes An access indicator. Can be "Enabled" or "Disabled". If "Enabled", the device is allowed to connect. If "Disabled", this device cannot access any device-facing endpoint. Default: "Enabled"
statusReason Optional A 128-character string that stores the reason for the device status. All UTF-8 characters are allowed. Default: null
connectionStateUpdatedTime Read only A temporal indicator, showing the date and time the connection state was last updated. Default: null
statusUpdatedTime Read only A temporal indicator, showing the date and time of the last status update. Default: null
lastActivityTime Read only A temporal indicator, showing the date and time the device last connected, received or sent a message. Default: null
cloudToDeviceMessageCount Read only The number of cloud to device messages awaiting delivery. Default: 0
authentication Optional An authentication table containing information and security materials. The primary and a secondary key are stored in base64 format. Default: {"symmetricKey" : {"primaryKey" : null, "secondaryKey" : null}}

Note The default authentication parameters do not contain the authentication needed to create an AzureIoTHub.Client object.

AzureIoTHub.Device Class Methods

connectionString(hostname)

This method retrieves the Device Connection String from the stored authentication and deviceId properties of the specified host. A Device Connection String is needed to create an AzureIoTHub.Client object.

Parameters

Parameter Data Type Required? Description
hostname String Yes The name of the host, found within the Device Connection String

Returns

String — The requested Device Connection String.

getBody()

This method returns the stored device properties.

Returns

Table — The stored device properties. See the Device Info Table, above, for details of the possible keys the table may contain.

AzureIoTHub.DPS

This class is used to provision devices using the Azure IoT Hub Device Provisioning Service. It allows you to register a device and obtain its Device Connection String. Please see the ‘Authentication’ section, above, for more information.

AzureIoTHub.DPS Class Usage

Constructor: AzureIoTHub.DPS(scopeId, registrationId, deviceKey)

This method returns a new AzureIoTHub.DPS instance.

Parameters

Parameter Data Type Required? Description
scopeId String Yes The Scope ID of Azure IoT Hub DPS
registrationId String Yes The Registration ID of the device
deviceKey String Yes A Device symmetric key

Example

const AZURE_DPS_SCOPE_ID = "<YOUR_SCOPE_ID>";
const AZURE_DPS_REG_ID   = "<YOUR_REGISTRATION_ID>";
const AZURE_DPS_DEV_KEY  = "<YOUR_DEVICE_KEY>";

// Create an instance
dps <- AzureIoTHub.DPS(AZURE_DPS_SCOPE_ID, AZURE_DPS_REG_ID, AZURE_DPS_DEV_KEY);

AzureIoTHub.DPS Class Methods

onCompleted Callback

A callback of this type is executed when any AzureIoTHub.DPS method completes. All of the methods below make use of this callback type, but each method can have its own callback. In other words, you may choose to implement as many different onCompleted handlers as you wish, or simply register a single callback with all of the methods. If you register a callback with one method, the handler will not be called by other methods: each method has to explicitly register its own callback.

The callback has the following parameters:

Parameter Data Type Description
error Integer 0 if the operation is successful, otherwise an error code
response Table Key-value table with the response provided by the Azure server. May be null. For information on the response format, please see the Azure documentation. May also contain error details
connectionString String The Device Connection String. null in case of an error

register(onCompleted)

This method registers the device using the Azure IoT Hub Device Provisioning Service. If registration is successful, and the device is assigned to an IoT Hub, this method returns the Device Connection String via the onCompleted handler.

Parameters

Parameter Data Type Required? Description
onCompleted Function Yes A function to be called when the operation is completed or an error occurs

Returns

Nothing — The result of the operation may be obtained via the onCompleted handler.

Example

function onCompleted(err, resp, connStr) {
    if (err != 0) {
        server.error("Registration failed: code = " + err + ", response = " + http.jsonencode(resp));
    } else {
        server.log("Registration finished successfully. Connection string = " + connStr);
    }
}

dps.register(onCompleted);

getConnectionString(onCompleted)

If the device is already registered and assigned to an IoT Hub, this method returns its Device Connection String via the onCompleted handler, or the AZURE_DPS_ERROR_NOT_REGISTERED error (see error codes).

Parameters

Parameter Data Type Required? Description
onCompleted Function Yes A function to be called when the operation is completed or an error occurs

Returns

Nothing — The result of the operation may be obtained via the onCompleted handler.

Example

function onCompleted(err, resp, connStr) {
    if (err != 0) {
        server.error("Getting the connection string failed: code = " + err + ", response = " + http.jsonencode(resp));
    } else {
        server.log("Connection string = " + connStr);
    }
}

dps.getConnectionString(onCompleted);

AzureIoTHub.DPS Example

#require "AzureIoTHub.agent.lib.nut:5.1.0"

const AZURE_DPS_SCOPE_ID = "<YOUR_AZURE_DPS_SCOPE_ID>";
const AZURE_DPS_REGISTRATION_ID = "<YOUR_AZURE_DPS_REGISTRATION_ID>";
const AZURE_DPS_DEVICE_KEY = "<YOUR_AZURE_DPS_DEVICE_KEY>";

client <- null;

local dps = AzureIoTHub.DPS(AZURE_DPS_SCOPE_ID, AZURE_DPS_REGISTRATION_ID, AZURE_DPS_DEVICE_KEY);

function onConnected(err) {
    if (err != 0) {
        server.error("Connection failed: " + err);
    }
}

local registrationCalled = false;
local onCompleted = function(err, resp, connStr) {
    if (err == 0) {
        server.log(registrationCalled ? "Device has been registered" : "Device is registered already");
        ::client <- AzureIoTHub.Client(connStr, onConnected);
    } else if (err == AZURE_DPS_ERROR_NOT_REGISTERED && !registrationCalled) {
        // The device is not registered
        server.log("Device is not registered. Starting registration...");
        registrationCalled = true;

        // Register the device
        dps.register(onCompleted);
    } else {
        server.error("Error occurred: code = " + err + ", response = " + http.jsonencode(resp));
    }
}.bindenv(this);

// Try to get a Device Connection String
dps.getConnectionString(onCompleted);

AzureIoTHub.Message

This class is used as a wrapper for messages send to and received from Azure IoT Hub.

AzureIoTHub.Message Class Usage

Constructor: AzureIoTHub.Message(message[, properties])

This method returns a new AzureIoTHub.Message instance.

Parameter Data Type Required? Description
message Any supported by the MQTT API Yes The message body
properties Table Optional The message properties. Keys (which are always strings) and values are entirely application specific

Example

local message1 = AzureIoTHub.Message("This is a message");
local message2 = AzureIoTHub.Message(blob(256));
local message3 = AzureIoTHub.Message("This is a message with properties", {"property": "value"});

AzureIoTHub.Message Class Methods

getProperties()

This method provides the properties of the message. Incoming messages contain properties set by Azure IoT Hub.

Returns

Table — The application-specific message properties.

getBody()

This method returns the message’s body. Messages that have been created locally will be of the same type as they were when created, but messages that were received from Azure IoT Hub are of one of the types supported by the MQTT API.

Returns

Various — The message body.

AzureIoTHub.DirectMethodResponse

This class is used to create a response to the received Direct Method call to return it to Azure IoT Hub.

AzureIoTHub.DirectMethodResponse Class Usage

Constructor: AzureIoTHub.DirectMethodResponse(status[, body])

This method returns a new AzureIoTHub.DirectMethodResponse instance.

Parameters

Parameter Data Type Required? Description
status Integer Yes The status of the Direct Method execution. Fully application specific
body Table Optional The returned data. Every key is always a string. Keys and values are fully application specific

AzureIoTHub.Client

This class is used to transfer data to and from Azure IoT Hub. To use this class, the device must be registered as an IoT Hub device in an Azure account.

Only one instance of this class is allowed.

AzureIoTHub.Client uses the MQTT 3.1.1 protocol. It supports the following functionality:

  • Connecting and disconnecting to/from Azure IoT Hub. Azure IoT Hub supports only one connection per device.
  • Sending messages to Azure IoT Hub.
  • Receiving messages from Azure IoT Hub (optional functionality).
  • Device Twin operations (optional functionality).
  • Direct Method processing (optional functionality).

Please keep in mind the Azure IoT Hub limitations.

All optional functionalities are disabled after a client instantiation. If an optional function is needed, it should be enabled after the client has successfully connected, and it should be explicitly re-enabled after every re-connection of the client. The class provides methods to enable every optional feature.

Most of the methods return nothing. A result of an operation may be obtained via a callback function specified in the method. Specific callbacks are described within every method. Many callbacks provide an error code which specifies a concrete error (if any) happened during the operation.

AzureIoTHub.Client Class Usage

Constructor: AzureIoTHub.Client(deviceConnectionString[, onConnected][, onDisconnected][, options])

This method returns a new AzureIoTHub.Client instance.

Parameters

Parameter Data Type Required? Description
deviceConnectionString String Yes A Device Connection String: includes the host name to connect, the device ID and the shared access string. See the ‘Authentication’ section for more information
onConnected Function Optional A function to be called every time the device connects (see below)
onDisconnected Function Optional A function to be called every time the device is disconnected (see below)
options Table Optional Optional client configuration settings (see below)

onConnected Callback

This callback is a good place to enable optional functionality, if needed.

Parameter Data Type Description
error Integer 0 if the connection was successful, otherwise an error code

onDisconnected Callback

This callback is a good place to call the connect() method again, if an unexpected disconnection occurred.

Note Every authentication token has an expiry time. The library is configured to request tokens with a one-day life. If the SAS token auto-refresh feature is disabled and the current token has expired, the Azure IoT Hub disconnects the device and the onDisconnected() handler is called. To reconnect with a new token, you can simply execute the connection flow again by calling connect().

Parameter Data Type Description
error Integer 0 if the disconnection was caused by the disconnect() method, otherwise an error code

Optional Settings

These settings affect the behavior of the client and the operations it performs. Every setting is optional and has a default.

Key Value Type Description
qos Integer An MQTT Quality of Service (QoS) setting. Azure IoT Hub supports QoS 0 and 1 only. Default: 0
keepAlive Integer Keep-alive MQTT parameter, in seconds. See here for more information. Default: 60s
twinsTimeout Integer Timeout in seconds for the retrieve twin and update twin operations. Default: 10s
dMethodsTimeout Integer Time (in seconds) allowed to reply to direct method call. Default: 30s
maxPendingTwinRequests Integer Maximum number of pending update twin operations. Default: 3
maxPendingSendRequests Integer Maximum number of pending send message operations. Default: 3
tokenTTL Integer SAS token’s time-to-live (in seconds). For more information, please see the Azure documentation. Default: 86400s
tokenAutoRefresh Boolean If true, the SAS token auto-refresh feature is enabled, otherwise disabled. Default: true

Example

const AZURE_DEVICE_CONN_STRING = "HostName=<HUB_ID>.azure-devices.net;DeviceId=<DEVICE_ID>;SharedAccessKey=<DEVICE_KEY_HASH>";

function onConnected(err) {
    if (err != 0) {
        server.error("Connect failed: " + err);
        return;
    }
    server.log("Connected");

    // Here is a good place to enable required features, like Device Twins or Direct Methods
}

function onDisconnected(err) {
    if (err != 0) {
        server.error("Disconnected unexpectedly with code: " + err);

        // Reconnect if disconnection is not initiated by application
        client.connect();
    } else {
        server.log("Disconnected by application");
    }
}

// Instantiate and connect a client
client <- AzureIoTHub.Client(AZURE_DEVICE_CONN_STRING, onConnected, onDisconnected);
client.connect();

AzureIoTHub.Client Class Methods

Azure IoT Hub supports only one connection per device.

All methods other than connect() and isConnected() should be called when the client is connected.

onDone Callback

This callback is executed when a AzureIoTHub.Client method completes. Many of the methods below make use of this callback, but it is important to understand that each of these methods registers their own callback. In other words, you may choose to implement as many different onDone handlers as there are AzureIoTHub.Client methods capable of using one, or simply register a single callback with all of the methods. If you register a callback with one method, the handler will not be called by other methods: each method has to explicitly register its callback.

The callback has the following parameter:

Parameter Data Type Description
error Integer 0 if the operation is completed successfully, otherwise an error code

connect()

This method opens a connection to Azure IoT Hub.

Returns

Nothing — The result of the connection attempt may be obtained via the onConnected handler, if set.

disconnect()

This method closes the connection to Azure IoT Hub. It does nothing if the connection is already closed.

Returns

Nothing — When the disconnection is completed the onDisconnected handler, if set, is called.

isConnected()

This method checks if the client is connected to Azure IoT Hub.

Returns

Boolean — true if the client is connected, otherwise false.

sendMessage(message[, onSent])

This method sends a message to Azure IoT Hub.

You may send send one further message while the previous send operation is still in progress. The maximum number of pending operations is defined by the client settings.

The Azure IoT Hub provides only limited support of the retain MQTT flag (as described here) so this library doesn't currently support retain.

Parameters

Parameter Data Type Required? Description
message AzureIoTHub.Message Yes The message to send
onSent Function Optional A function to be called when the message is considered as sent or an error occurs

If null is passed into message, or the argument is of an incompatible type, the method will throw an exception.

onSent Callback

Parameter Data Type Description
error Integer 0 if the operation completed successfully, otherwise an error code
message AzureIoTHub.Message The original message passed to sendMessage()

Returns

Nothing — The result of the operation may be obtained via the onSent handler, if specified in this method.

Example

// Send a string with no callback
message1 <- AzureIoTHub.Message("This is a string");
client.sendMessage(message1);

// Send a string with a callback
message2 <- AzureIoTHub.Message("This is another string");

function onSent(err, msg) {
    if (err != 0) {
        server.error("Message sending failed: " + err);
        server.log("Trying to send again...");

        // For example simplicity trying to resend the message in case of any error
        client.sendMessage(message2, onSent);
    } else {
        server.log("Message sent at " + time());
    }
}

client.sendMessage(message2, onSent);

enableIncomingMessages(onReceive[, onDone])

This method enables or disables the receipt of messages from Azure IoT Hub.

To enable the feature, pass a function into onReceive. To disable the feature, pass in null.

The feature is automatically disabled every time the client disconnects. It should be re-enabled after every new connection, if needed.

Parameters

Parameter Data Type Required? Description
onReceive Function Yes A function to be called every time a new message is received from Azure IoT Hub, or null to disable message receipt
onDone Function Optional A function to be called when the operation is completed or an error occurs

onReceive Callback

Parameter Data Type Description
message AzureIoTHub.Message A received message

Returns

Nothing — The result of the operation may be obtained via the onDone handler, if specified in this method.

Example

function onReceive(msg) {
    server.log("Message received: " + msg.getBody());
}

function onDone(err) {
    if (err != 0) {
        server.error("Enabling message receiving failed: " + err);
    } else {
        server.log("Message receiving enabled successfully");
    }
}

client.enableIncomingMessages(onReceive, onDone);

enableTwin(onRequest[, onDone])

This method enables or disables Azure IoT Hub Device Twins functionality.

To enable the feature, pass a function into onRequest. To disable the feature, pass in null.

The feature is automatically disabled every time the client disconnects. It should be re-enabled after every new connection, if needed.

Parameters

Parameter Data Type Required? Description
onRequest Function Yes A function to be called every time a new request with desired Device Twin properties is received from Azure IoT Hub, null to disable the feature
onDone Function Optional A function to be called when the operation is completed or an error occurs

onRequest Callback

Parameter Data Type Description
properties Table The desired properties and their version. Every key is a string. Keys and values are entirely application specific

Returns

Nothing — The result of the operation may be obtained via the onDone handler, if specified in this method.

Example

function onRequest(props) {
    server.log("Desired properties received");
}

function onDone(err) {
    if (err != 0) {
        server.error("Enabling Twins functionality failed: " + err);
    } else {
        server.log("Twins functionality enabled successfully");
    }
}

client.enableTwin(onRequest, onDone);

retrieveTwinProperties(onRetrieved)

This method retrieves Device Twin properties.

It may be called only if Device Twins functionality is enabled. Do not call this method until any previous retrieve operation has completed.

Parameters

Parameter Data Type Required? Description
onRetrieved Function Yes A function to be called when the properties have been retrieved

onRetrieved Callback

Parameter Data Type Description
error Integer 0 if the operation is completed successfully, otherwise an error code
reportedProperties Table The reported properties and their version. This parameter should be ignored if error is not 0. Every key is always a string. Keys and values are entirely application specific
desiredProperties Table The desired properties and their version. This parameter should be ignored if error is not 0. Every key is always a string. Keys and values are entirely application specific

Returns

Nothing — The result of the operation may be obtained via the onRetrieved handler.

Example

function onRetrieved(err, repProps, desProps) {
    if (err != 0) {
        server.error("Retrieving Twin properties failed: " + err);
        return;
    }

    server.log("Twin properties retrieved successfully");
}

// It is assumed that Twins functionality is enabled
client.retrieveTwinProperties(onRetrieved);

updateTwinProperties(properties[, onUpdated])

This method updates Device Twin reported properties.

It may be called only if Device Twins functionality is enabled.

You can call this method again while the previous update operation is not yet complete. The maximum number of pending operations is defined by the client settings.

Parameters

Parameter Data Type Required? Description
properties Table Yes The reported properties. Every key is always a string. Keys and values are entirely application specific
onUpdated Function Optional A function to be called when the operation is completed or an error occurs

If the properties parameter is passed null or an item of incompatible type, the method will throw an exception.

onUpdated Callback

Parameter Data Type Description
error Integer 0 if the operation is completed successfully, otherwise an error code
properties Table The original properties passed to updateTwinProperties()

Returns

Nothing — The result of the operation may be obtained via the onUpdated handler, if set.

Example

props <- {"exampleProp": "val"};

function onUpdated(err, props) {
    if (err != 0) {
        server.error("Twin properties update failed: " + err);
    } else {
        server.log("Twin properties updated successfully");
    }
}

// It is assumed that Twins functionality is enabled
client.updateTwinProperties(props, onUpdated);

enableDirectMethods(onMethod[, onDone])

This method enables or disables Azure IoT Hub Direct Methods.

To enable the feature, pass a function into onMethod. To disable the feature, pass in null.

The feature is automatically disabled every time the client is disconnected. It should be re-enabled after every new connection, if needed.

Parameters

Parameter Data Type Required? Description
onMethod Function Yes A function to be called every time a Direct Method is called by Azure IoT Hub, or null to disable the feature
onDone Function Optional A function to be called when the operation is completed or an error occurs

onMethod Callback

Parameter Data Type Description
name String Name of the called Direct Method
params Table The input parameters of the called Direct Method. Every key is always a string. Keys and values are entirely application specific
reply Function A function to be called to send a reply to the direct method call. Details below

The onMethod Callback Reply Function

The function passed into the onMethod callback’s reply parameter has the following parameters of its own:

Parameter Data Type Required? Description
data AzureIoTHub.DirectMethodResponse Yes Data to send in response to the direct method call
onReplySent Function No A function to be called when the operation is complete or an error occurs. It returns nothing, and has the following parameters:
error — An integer which will be 0 if the operation is completed successfully, otherwise an error code
data — A reference to the data passed into the callback function

Returns

Nothing — The result of the operation may be obtained via the onDone handler.

Example

function onReplySent(err, data) {
    if (err != 0) {
        server.error("Sending reply failed: " + err);
    } else {
        server.log("Reply was sent successfully");
    }
}

function onMethod(name, params, reply) {
    server.log("Direct Method called. Name = " + name);
    local responseStatusCode = 200;
    local responseBody = {"example" : "val"};
    local response = AzureIoTHub.DirectMethodResponse(responseStatusCode, responseBody);
    reply(response, onReplySent);
}

function onDone(err) {
    if (err != 0) {
        server.error("Enabling Direct Methods failed: " + err);
    } else {
        server.log("Direct Methods enabled successfully");
    }
}

client.enableDirectMethods(onMethod, onDone);

setDebug(value)

This method enables (value is true) or disables (value is false) the client debug output (including error logging). It is disabled by default.

Returns

Nothing.

Refreshing SAS Tokens Automatically

Every SAS token always has an expiry time. If the token has expired, Azure IoT Hub disconnects the device. To prevent the disconnection, the token must be updated before it expires.

The library supports updating tokens, and this functionality is enabled by default.

The token update algorithm operates as follows:

  1. A timer fires when the current token is near to expiry.
  2. The library waits for all current operations to be completed (see the note below).
  3. The library generates a new token using the Device Connection String.
  4. The library disconnects from Azure IoT Hub.
  5. The library re-connects to Azure IoT Hub using the new token as the MQTT client’s password.
  6. The library subscribes to the topics to which it was subscribed before the reconnection.
  7. The library sets a new timer to fire just before the new token is due to expire.

The library performs all of these operations automatically and invisibly to an application. The onConnected and onDisconnected callbacks are not called. Any API calls made by the application during the update process are retained in a queue and processed once the token has been successfully updated. If the token can’t be updated, the onDisconnected callback is executed (if set).

To stop the token being updated automatically, you can set the tokenAutoRefresh option in the AzureIoTHub.Client constructor to false.

Note Some of the operations (such as retrieving twin properties) are two-phase. This means that the library sends a message and waits for a response message from the server. During these operations, the library doesn’t start to refresh an expired or nearly expired token but waits for the operations to finish first. This rule also applies to direct methods: when the library receives a direct method call, it doesn't start to refresh an expired or nearly expired token until that call has been replied to or has timed out. Please bear this in mind when setting the timeouts for these operations.

Error Codes

The table below describes the error codes for all of the library classes. Each error code is an integer which specifies a concrete error which occurred during an operation.

Error Code Error Name Applicable Classes Description
0 DPS, Client No error
-99..-1 and 128 Client Codes returned by the MQTT API
1..99 DPS Internal errors of the HTTP API
100-999 except 128 DPS, Client For the Client class: Azure IoT Hub errors.
For the DPS class: HTTP error codes from Azure DPS REST API.
1000 "AZURE_CLIENT_ERROR_NOT_CONNECTED" Client The client is not connected
1001 "AZURE_CLIENT_ERROR_ALREADY_CONNECTED" Client The client is already connected
1002 "AZURE_CLIENT_ERROR_NOT_ENABLED" Client The feature is not enabled
1003 "AZURE_CLIENT_ERROR_ALREADY_ENABLED" Client The feature is already enabled
1004 "AZURE_CLIENT_ERROR_OP_NOT_ALLOWED_NOW" Client The operation is not allowed at the moment, typically because the same operation is already in process. For more information, please see Note 1 below
1005 "AZURE_CLIENT_ERROR_OP_TIMED_OUT" Client The operation timed out. For more information, please see Note 2 below
1010 "AZURE_DPS_ERROR_NOT_REGISTERED" DPS The device is/was not registered
1100 "AZURE_ERROR_GENERAL" DPS, Client General error. For more information, please see Note 3 below

Note 1 The error "AZURE_CLIENT_ERROR_OP_NOT_ALLOWED_NOW" may appear in the following situations:

  • The connection is still being established when you try to call one or more library methods, such as sendMessage().
  • You try to call one or more library methods, such as sendMessage(), when a disconnection is in progress (because you called disconnect() earlier).
  • Too many messages are being sent and you try to send another one. Please see the maxPendingSendRequests parameter in the Optional Settings section for information on dealing with this.
  • A retrieve twin properties operation is already in progress when you try to retrieve the properties again.
  • Too many update twin properties operations are in progress when you try to update another. Please see the maxPendingTwinRequests parameter in the Optional Settings section for information on dealing with this.
  • You try to enable a feature after already attempting to enable it.

Note 2 The error "AZURE_CLIENT_ERROR_OP_TIMED_OUT" may appear in the following situations:

  • A direct method call has already expired when you try to reply to it. Please see the dMethodsTimeout parameter in the Optional Settings section for information on dealing with this.
  • One of the two-phase operations (retrieving or updating of twin properties) has not received a response from the server. Please see the twinsTimeout parameter in the Optional Settings section for information on dealing with this.

Note 3 The error "AZURE_ERROR_GENERAL" may appear in the following situations:

  • An unexpected response was received from the server.
  • A parsing error occurred.
  • An unexpected disconnection took place.

Release History

The Electric Imp Dev Center documents the latest version of the library. For past versions, please see the Electric Imp public GitHub repos listed below.

Version Source Code Notes
1.0.0 GitHub Initial release
1.1.0 GitHub Add receive(), sendFeedback() methods
1.2.0 GitHub Improved sendEvent() code; add getMessageId() and getCorrelationId() iothub.message methods
1.2.1 GitHub Raised polling interval from 1s to 10.8s; updated for latest version of the Azure IoT API
2.0.0 GitHub Added AMQP support; updated library name to match new naming system; AzureIoTHub.Client methods sendFeedback(), sendEventBatch() removed, connect(), disconnect() added; AzureIoTHub.Device, AzureIoTHub.Message and AzureIoTHub.Delivery classes added
2.1.0 GitHub Added onDisconnect handler
2.2.0 GitHub Support custom data encoding for message
3.0.0 GitHub Added support for MQTT
4.0.0 GitHub Allow async replies for Direct Methods; follow the "error-first" practice in callbacks
5.0.0 GitHub Auth token update introduced; registration using DPS; further callbacks’ parameter order changes
5.1.0 GitHub Update typo in function name: anDayFromNow() is now aDayFromNow(); patch to avoid error if disconnect is called while connecting: if disconnect is called while connecting, disconnect will be triggered as soon as connection attempt is completed

License

This library is licensed under the MIT License.