| author | SoniaLopezBravo | ||||
|---|---|---|---|---|---|
| ms.author | sonialopez | ||||
| ms.service | azure-iot-hub | ||||
| ms.devlang | nodejs | ||||
| ms.topic | include | ||||
| ms.date | 12/19/2024 | ||||
| ms.custom |
|
This section describes how to receive cloud-to-device messages using the azure-iot-device package in the Azure IoT SDK for Node.js.
For a Node.js-based device application to receive cloud-to-device messages, it must connect to IoT Hub, then set up a callback listener and message handler to process incoming messages from IoT Hub. The device application should also be able to detect and handle disconnects in case the device-to-IoT Hub message connection is broken.
The azure-iot-device package contains objects that interface with IoT devices. Run this command to install the azure-iot-device device SDK on your development machine:
npm install azure-iot-device --save
A device app can authenticate with IoT Hub using the following methods:
- X.509 certificate
- Shared access key
[!INCLUDE iot-authentication-device-connection-string.md]
[!INCLUDE iot-hub-howto-auth-device-cert-node]
The Client object supports these protocols:
AmqpHttp- When usingHttp, theClientinstance checks for messages from IoT Hub infrequently (a minimum of every 25 minutes).MqttMqttWsAmqpWs
Install needed transport protocols on your development machine.
For example, this command installs the Amqp protocol:
npm install azure-iot-device-amqp --save
For more information about the differences between MQTT, AMQP, and HTTPS support, see Cloud-to-device communications guidance and Choose a communication protocol.
This example assigns the AMQP protocol to a Protocol variable. This Protocol variable is passed to the Client.fromConnectionString method in the Add the connection string section of this article.
const Protocol = require('azure-iot-device-mqtt').Amqp;Message completion, rejection, and abandon methods can be used depending on the protocol chosen.
The AMQP and HTTP transports can complete, reject, or abandon a message:
- Complete - To complete a message, the service that sent the cloud-to-device message is notified that the message is received. IoT Hub removes the message from the message queue. The method takes the form of
client.complete(message, callback function). - Reject - To reject a message, the service that sent the cloud-to-device message is notified that the message is not processed by the device. IoT Hub permanently removes the message from the device queue. The method takes the form of
client.reject(message, callback function). - Abandon - To abandon a message, IoT Hub immediately tries to resend it. IoT Hub retains the message in the device queue for future consumption. The method takes the form of
client.abandon(message, callback function).
MQTT does not support message complete, reject, or abandon functions. Instead, MQTT accepts a message by default and the message is removed from the IoT Hub message queue.
If something happens that prevents the device from completing, abandoning, or rejecting the message, IoT Hub will, after a fixed timeout period, queue the message for delivery again. For this reason, the message processing logic in the device app must be idempotent, so that receiving the same message multiple times produces the same result.
Create a Client object using the installed package.
For example:
const Client = require('azure-iot-device').Client;Create a Protocol object using an installed transport package.
This example assigns the AMQP protocol:
const Protocol = require('azure-iot-device-amqp').Amqp;Call fromConnectionString to supply device connection parameters:
- connStr - The device connection string.
- transportCtor - The transport protocol.
This example uses the Amqp transport protocol:
const deviceConnectionString = "{IoT hub device connection string}"
const Protocol = require('azure-iot-device-mqtt').Amqp;
let client = Client.fromConnectionString(deviceConnectionString, Protocol);The message handler is called for each incoming message.
After a message is successfully received, if using AMQP or HTTP transport then call the client.complete method to inform IoT Hub that the message can be removed from the message queue.
For example, this message handler prints the message ID and message body to the console, then calls client.complete to notify IoT Hub that it processed the message and that it can safely be removed from the device queue. The call to complete isn't required if you're using MQTT transport and can be omitted. A call tocomplete is required for AMQP or HTTPS transport.
function messageHandler(msg) {
console.log('Id: ' + msg.messageId + ' Body: ' + msg.data);
client.complete(msg, printResultFor('completed'));
}The disconnect handler is called when the connection is disconnected. A disconnect handler is useful for implementing reconnect code.
This example catches and displays the disconnect error message to the console.
function disconnectHandler() {
clearInterval(sendInterval);
sendInterval = null;
client.open().catch((err) => {
console.error(err.message);
});
}You can specify these event listeners using the .on method.
- Connection handler
- Error handler
- Disconnect handler
- Message handler
This example includes the message and disconnect handlers defined previously.
client.on('connect', connectHandler);
client.on('error', errorHandler);
client.on('disconnect', disconnectHandler);
client.on('message', messageHandler);Use the open method to open a connection between an IoT device and IoT Hub.
Use .catch(err) to catch an error and call handler code.
For example:
client.open()
.catch((err) => {
console.error('Could not connect: ' + err.message);
});The Azure IoT SDK for Node.js provides a working sample of a device app that handles message receive. For more information, see:
simple_sample_device - A device app that connects to your IoT hub and receives cloud-to-device messages.
This section describes how to send a cloud-to-device message. As discussed previously, a solution backend application connects to an IoT Hub and messages are sent to IoT Hub encoded with a destination device. IoT Hub stores incoming messages to its message queue, and messages are delivered from the IoT Hub message queue to the target device.
A solution backend application can also request and receive delivery feedback for a message sent to IoT Hub that is destined for device delivery via the message queue.
The azure-iothub package contains objects that interface with IoT Hub. This article describes Client class code that sends a message from an application to a device via IoT Hub.
Run this command to install azure-iothub on your development machine:
npm install azure-iothub --save
Declare a Client object using the Client class from the azure-iothub package.
Declare a Message object using the Message class from the azure-iot-common package.
'use strict';
var Client = require('azure-iothub').Client;
var Message = require('azure-iot-common').Message;You can connect a backend service to IoT Hub using the following methods:
- Shared access policy
- Microsoft Entra
[!INCLUDE iot-authentication-service-connection-string.md]
Use fromConnectionString to connect to IoT hub.
In this example, the serviceClient object is created with the Amqp transport type.
var connectionString = '{IoT hub device connection string}';
var serviceClient = Client.fromConnectionString(connectionString,`Amqp`);Call the Client open method to open a connection between an application and IoT Hub.
open can be called with or without specifying a callback function that is called when the open operation is complete.
In this example, the open method includes an optional err open connection callback function. If an open error occurs, an error object is returned. If the open connection is successful, a null callback value is returned.
serviceClient.open(function (err)
if (err)
console.error('Could not connect: ' + err.message);[!INCLUDE iot-hub-howto-connect-service-iothub-entra-node]
The message object includes the asynchronous cloud-to-device message. The message functionality works the same way over AMQP, MQTT, and HTTP.
The message object supports several properties, including these properties. See the message properties for a complete list.
ack- Delivery feedback. Described in the next section.properties- A map containing string keys and values for storing custom message properties.- messageId - Used to correlate two-way communication.
Add the message body when the message object is instantiated. In this example, a 'Cloud to device message.' message is added.
var message = new Message('Cloud to device message.');
message.ack = 'full';
message.messageId = "My Message ID";A sending program can request delivery (or expiration) acknowledgments from IoT Hub for each cloud-to-device message. This option enables the sending program to use inform, retry, or compensation logic. A complete description of message feedback operations and properties are described at Message feedback.
Each message that is to receive message feedback must include a value for the delivery acknowledgment ack property. The ack property can be one of these values:
-
none (default): no feedback message is generated.
-
sent: receive a feedback message if the message was completed. -
: receive a feedback message if the message expired (or maximum delivery count was reached) without being completed by the device.
-
full: feedback for both sent and not sent results.
In this example, the ack property is set to full, requesting both sent and not sent message delivery feedback for one message.
message.ack = 'full';The message feedback receiver callback function is linked to the Client using getFeedbackReceiver.
The message feedback receiver receives two arguments:
- Error object (can be null)
- AmqpReceiver object - Emits events when new feedback messages are received by the client.
This example function receives and prints a delivery feedback message to the console.
function receiveFeedback(err, receiver){
receiver.on('message', function (msg) {
console.log('Feedback message:')
console.log(msg.getData().toString('utf-8'));
});
}This code links the receiveFeedback feedback callback function to the service Client object using getFeedbackReceiver.
serviceClient.getFeedbackReceiver(receiveFeedback);The message send completion callback function is called after each message is sent.
This example function prints message send operation results to the console. In this example, the printResultFor function is supplied as a parameter to the send function described in the next section.
function printResultFor(op) {
return function printResult(err, res) {
if (err) console.log(op + ' error: ' + err.toString());
if (res) console.log(op + ' status: ' + res.constructor.name);
};
}Use the send function to send an asynchronous cloud-to-device message to the device app through IoT Hub.
send supports these parameters:
- deviceID - The device ID of the target device.
- message - The body of the message to send to the device.
- done - The optional function to call when the operation is complete. Done is called with two arguments:
- Error object (can be null).
- transport-specific response object useful for logging or debugging.
This code calls send to send a cloud-to-device message to the device app through IoT Hub. The callback function printResultFor defined in the previous section receives the delivery acknowledgment information.
var targetDevice = '{device ID}';
serviceClient.send(targetDevice, message, printResultFor('send'));This example shows how to send a message to your device and handle the feedback message when the device acknowledges the cloud-to-device message:
serviceClient.open(function (err) {
if (err) {
console.error('Could not connect: ' + err.message);
} else {
console.log('Service client connected');
serviceClient.getFeedbackReceiver(receiveFeedback);
var message = new Message('Cloud to device message.');
message.ack = 'full';
message.messageId = "My Message ID";
console.log('Sending message: ' + message.getData());
serviceClient.send(targetDevice, message, printResultFor('send'));
}
});The Azure IoT SDK for Node.js provides working samples of a service app that handles send message tasks. For more information, see:
send_c2d_message.js - Send C2D messages to a device through IoT Hub.