Get started with device management

Back-end apps can use Azure IoT Hub primitives, such as device twins and direct methods, to remotely start and monitor device management actions on devices.

Use a direct method from a back-end application to initiate device management actions, such as reboot, factory reset, and firmware update.

The device is responsible for:

  • Handling the direct method request sent from IoT Hub
  • Initiating the corresponding device-specific action on the device
  • Providing status updates through reported properties to IoT Hub

This article shows you how a back-end app and a device app can work together to initiate and monitor a remote device action using a direct method.

  • A service app calls a direct method to reboot in a device app through an IoT hub.
  • A device app handles a direct method to reboot a device.

Note

The features described in this article are available only in the standard tier of IoT Hub. For more information about the basic and standard/free IoT Hub tiers, see Choose the right IoT Hub tier for your solution.

Note

This article is meant to complement Azure IoT SDKs samples that are referenced from within this article. You can use SDK tools to build both device and back-end applications.

Prerequisites

  • An IoT hub

  • A registered device

  • If your application uses the MQTT protocol, make sure that port 8883 is open in your firewall. The MQTT protocol communicates over port 8883. This port may be blocked in some corporate and educational network environments. For more information and ways to work around this issue, see Connecting to IoT Hub (MQTT).

  • Requires Visual Studio

Overview

This article describes how to use the Azure IoT SDK for .NET to create device and backend service application code for device direct messages.

Create a device application

This section describes how to use device application code to create a direct method callback listener.

Important

This article includes steps to connect a device using a shared access signature, also called symmetric key authentication. This authentication method is convenient for testing and evaluation, but authenticating a device using X.509 certificates is a more secure approach. To learn more, see Security best practices > Connection security.

Required device NuGet package

Device client applications written in C# require the Microsoft.Azure.Devices.Client NuGet package.

Add these using statements to use the device library.

using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.Devices.Shared;

Connect to a device

The DeviceClient class exposes all the methods required to interact with device messages from the device.

Connect to the device using the CreateFromConnectionString method along with device connection string and the connection transport protocol.

The CreateFromConnectionString TransportType transport protocol parameter supports the following transport protocols:

  • Mqtt
  • Mqtt_WebSocket_Only
  • Mqtt_Tcp_Only
  • Amqp
  • Amqp_WebSocket_Only
  • Amqp_Tcp_Only
  • Http1

This example connects to a device using the Mqtt transport protocol.

static string DeviceConnectionString = "{IoT hub device connection string}";
static deviceClient = null;
deviceClient = DeviceClient.CreateFromConnectionString(DeviceConnectionString, 
   TransportType.Mqtt);

Create a direct method callback listener

Use SetMethodHandlerAsync to initialize a direct method callback listener. The listener is associated with a method name keyword, such as "reboot". The method name can be used in an IoT Hub or backend application to trigger the callback method on the device.

This example sets up a callback listener named onReboot that will trigger when the "reboot" direct method name is called.

try
{
      // setup callback for "reboot" method
      deviceClient.SetMethodHandlerAsync("reboot", onReboot, null).Wait();
      Console.WriteLine("Waiting for reboot method\n Press enter to exit.");
      Console.ReadLine();

      Console.WriteLine("Exiting...");

      // as a good practice, remove the "reboot" handler
      deviceClient.SetMethodHandlerAsync("reboot", null, null).Wait();
      deviceClient.CloseAsync().Wait();
}
catch (Exception ex)
{
      Console.WriteLine();
      Console.WriteLine("Error in sample: {0}", ex.Message);
}

Continuing the example, the onReboot callback method implements the direct method on the device.

The handler function calls MethodResponse to send a response acknowledgment to the calling application.

static Task<MethodResponse> onReboot(MethodRequest methodRequest, object userContext)
{
      // In a production device, you would trigger a reboot 
      // scheduled to start after this method returns.
      // For this sample, we simulate the reboot by writing to the console
      // and updating the reported properties.
      try
      {
         Console.WriteLine("Rebooting!");
      }
      catch (Exception ex)
      {
         Console.WriteLine();
         Console.WriteLine("Error in sample: {0}", ex.Message);
      }

      string result = @"{""result"":""Reboot started.""}";
      return Task.FromResult(new MethodResponse(Encoding.UTF8.GetBytes(result), 200));
}

Note

To keep things simple, this article does not implement any retry policy. In production code, you should implement retry policies (such as an exponential backoff), as suggested in Transient fault handling.

SDK device samples

The Azure IoT SDK for .NET provides working samples of device apps that handle direct method tasks. For more information, see:

Create a backend application

This section describes how to trigger a direct method on a device.

The ServiceClient class exposes all methods required to create a backend application to send direct method calls to devices.

Required service NuGet package

Backend service applications require the Microsoft.Azure.Devices NuGet package.

Add these using statements to use the service library.

using Microsoft.Azure.Devices;
using Microsoft.Azure.Devices.Shared;

Connect to IoT hub

You can connect a backend service to IoT Hub using the following methods:

  • Shared access policy
  • Microsoft Entra

Important

This article includes steps to connect to a service using a shared access signature. This authentication method is convenient for testing and evaluation, but authenticating to a service with Microsoft Entra ID or managed identities is a more secure approach. To learn more, see Security best practices > Cloud security.

Connect using a shared access policy

Connect a backend application using CreateFromConnectionString.

To invoke a direct method on a device through IoT Hub, your service needs the service connect permission. By default, every IoT Hub is created with a shared access policy named service that grants this permission.

As a parameter to CreateFromConnectionString, supply the service shared access policy. For more information about shared access policies, see Control access to IoT Hub with shared access signatures.

ServiceClient serviceClient;
string connectionString = "{IoT hub service shared access policy connection string}";
serviceClient = ServiceClient.CreateFromConnectionString(connectionString);

Connect using Microsoft Entra

A backend app that uses Microsoft Entra must successfully authenticate and obtain a security token credential before connecting to IoT Hub. This token is passed to a IoT Hub connection method. For general information about setting up and using Microsoft Entra for IoT Hub, see Control access to IoT Hub by using Microsoft Entra ID.

Configure Microsoft Entra app

You must set up a Microsoft Entra app that is configured for your preferred authentication credential. The app contains parameters such as client secret that are used by the backend application to authenticate. The available app authentication configurations are:

  • Client secret
  • Certificate
  • Federated identity credential

Microsoft Entra apps may require specific role permissions depending on operations being performed. For example, IoT Hub Twin Contributor is required to enable read and write access to a IoT Hub device and module twins. For more information, see Manage access to IoT Hub by using Azure RBAC role assignment.

For more information about setting up a Microsoft Entra app, see Quickstart: Register an application with the Microsoft identity platform.

Authenticate using DefaultAzureCredential

The easiest way to use Microsoft Entra to authenticate a backend application is to use DefaultAzureCredential, but it's recommended to use a different method in a production environment including a specific TokenCredential or pared-down ChainedTokenCredential. For simplicity, this section describes authentication using DefaultAzureCredential and Client secret. For more information about the pros and cons of using DefaultAzureCredential, see Usage guidance for DefaultAzureCredential.

DefaultAzureCredential supports different authentication mechanisms and determines the appropriate credential type based on the environment it's executing in. It attempts to use multiple credential types in an order until it finds a working credential.

Microsoft Entra requires these NuGet packages and corresponding using statements:

  • Azure.Core
  • Azure.Identity
using Azure.Core;
using Azure.Identity;

In this example, Microsoft Entra app registration client secret, client ID, and tenant ID are added to environment variables. These environment variables are used by DefaultAzureCredential to authenticate the application. The result of a successful Microsoft Entra authentication is a security token credential that is passed to an IoT Hub connection method.

string clientSecretValue = "xxxxxxxxxxxxxxx";
string clientID = "xxxxxxxxxxxxxx";
string tenantID = "xxxxxxxxxxxxx";

Environment.SetEnvironmentVariable("AZURE_CLIENT_SECRET", clientSecretValue);
Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", clientID);
Environment.SetEnvironmentVariable("AZURE_TENANT_ID", tenantID);

TokenCredential tokenCredential = new DefaultAzureCredential();

The resulting TokenCredential can then be passed to a connect to IoT Hub method for any SDK client that accepts Microsoft Entra credentials:

In this example, the TokenCredential is passed to ServiceClient.Create to create a ServiceClient connection object.

string hostname = "xxxxxxxxxx.azure-devices.net";
using var serviceClient = ServiceClient.Create(hostname, tokenCredential, TransportType.Amqp);

In this example, the TokenCredential is passed to RegistryManager.Create to create a RegistryManager object.

string hostname = "xxxxxxxxxx.azure-devices.net";
registryManager = RegistryManager.Create(hostname, tokenCredential);
Code sample

For a working sample of Microsoft Entra service authentication, see Role based authentication sample.

Invoke a method on a device

To invoke a method on a device:

  1. Create a CloudToDeviceMethod object. Pass the device direct method name as a parameter.
  2. Call InvokeDeviceMethodAsync to invoke the method on the device.

This example calls the "reboot" method to initiate a reboot on the device. The "reboot" method is mapped to a listener on the device as described in the Create a direct method callback listener section of this article.

string targetDevice = "myDeviceId";
CloudToDeviceMethod method = new CloudToDeviceMethod("reboot");
method.ResponseTimeout = TimeSpan.FromSeconds(30);

CloudToDeviceMethodResult response = await serviceClient.InvokeDeviceMethodAsync(targetDevice, method);

Console.WriteLine("Invoked firmware update on device.");

SDK service samples

The Azure IoT SDK for .NET provides working samples of service apps that handle message tasks. For more information, see:

  • Requires Java SE Development Kit 8. Make sure you select Java 8 under Long-term support to navigate to downloads for JDK 8.

Overview

This article describes how to use the Azure IoT SDK for Java to create device and backend service application code for device direct methods.

Create a device application

This section describes how to use device application code to create a direct method callback listener.

Important

This article includes steps to connect a device using a shared access signature, also called symmetric key authentication. This authentication method is convenient for testing and evaluation, but authenticating a device using X.509 certificates is a more secure approach. To learn more, see Security best practices > Connection security.

Device import statement

Use the following device import statements to access the Azure IoT SDK for Java.

import com.microsoft.azure.sdk.iot.device.*;
import com.microsoft.azure.sdk.iot.device.exceptions.IotHubClientException;
import com.microsoft.azure.sdk.iot.device.twin.DirectMethodPayload;
import com.microsoft.azure.sdk.iot.device.twin.DirectMethodResponse;
import com.microsoft.azure.sdk.iot.device.twin.MethodCallback;
import com.microsoft.azure.sdk.iot.device.transport.IotHubConnectionStatus;
import com.microsoft.azure.sdk.iot.device.twin.SubscriptionAcknowledgedCallback;

Connect to a device

The DeviceClient class exposes all the methods you require to interact with direct methods on the device.

To connect to a device:

  1. Use IotHubClientProtocol to choose a transport protocol. For example:

    IotHubClientProtocol protocol = IotHubClientProtocol.MQTT;
    
  2. Use the DeviceClient constructor to add the device primary connection string and protocol.

    String connString = "{IoT hub device connection string}";
    DeviceClient client = new DeviceClient(connString, protocol);
    
  3. Use open to connect the device to IoT hub. If the client is already open, the method does nothing.

    client.open(true);
    

Create a direct method callback listener

Use subscribeToMethods to initialize a direct method callback listener. subscribeToMethods listens for incoming direct methods until the connection is terminated. The method name and payload is received for each direct method call.

The listener should call DirectMethodResponse to send a method response acknowledgment to the calling application.

For example:

client.subscribeToMethods(
    (methodName, methodData, context) ->
    {
        System.out.println("Received a direct method invocation with name " + methodName + " and payload " + methodData.getPayloadAsJsonString());
        return new DirectMethodResponse(200, methodData);
    },
    null);
System.out.println("Successfully subscribed to direct methods");

Note

To keep things simple, this article does not implement any retry policy. In production code, you should implement retry policies (such as an exponential backoff), as suggested in Transient fault handling.

SDK device samples

The Azure IoT SDK for Java includes a working sample to test the device app concepts described in this article. For more information, see Direct Method Sample.

Create a backend application

This section describes how to initiate a remote reboot on a device using a direct method.

The ServiceClient DeviceMethod class contains methods that services can use to access device twins.

Service import statements

Use the following service import statements to access the Azure IoT SDK for Java.

import com.microsoft.azure.sdk.iot.service.methods.DirectMethodRequestOptions;
import com.microsoft.azure.sdk.iot.service.methods.DirectMethodsClient;
import com.microsoft.azure.sdk.iot.service.methods.DirectMethodResponse;

Connect to IoT hub

You can connect a backend service to IoT Hub using the following methods:

  • Shared access policy
  • Microsoft Entra

Important

This article includes steps to connect to a service using a shared access signature. This authentication method is convenient for testing and evaluation, but authenticating to a service with Microsoft Entra ID or managed identities is a more secure approach. To learn more, see Security best practices > Cloud security.

Connect using a shared access policy

Use the DeviceMethod constructor to add the service primary connection string and connect to IoT Hub.

To invoke a direct method on a device through IoT Hub, your service needs the service connect permission. By default, every IoT Hub is created with a shared access policy named service that grants this permission.

As a parameter to the DeviceMethod constructor, supply the service shared access policy. For more information about shared access policies, see Control access to IoT Hub with shared access signatures.

For example:

String iotHubConnectionString = "HostName=xxxxx.azure-devices.net;SharedAccessKeyName=service;SharedAccessKey=xxxxxxxxxxxxxxxxxxxxxxxx";
DeviceMethod methodClient = new DeviceMethod(iotHubConnectionString);

Connect using Microsoft Entra

A backend app that uses Microsoft Entra must successfully authenticate and obtain a security token credential before connecting to IoT Hub. This token is passed to a IoT Hub connection method. For general information about setting up and using Microsoft Entra for IoT Hub, see Control access to IoT Hub by using Microsoft Entra ID.

For an overview of Java SDK authentication, see Azure authentication with Java and Azure Identity.

For simplicity, this section focuses on describing authentication using client secret.

Configure Microsoft Entra app

You must set up a Microsoft Entra app that is configured for your preferred authentication credential. The app contains parameters such as client secret that are used by the backend application to authenticate. The available app authentication configurations are:

  • Client secret
  • Certificate
  • Federated identity credential

Microsoft Entra apps may require specific role permissions depending on operations being performed. For example, IoT Hub Twin Contributor is required to enable read and write access to a IoT Hub device and module twins. For more information, see Manage access to IoT Hub by using Azure RBAC role assignment.

For more information about setting up a Microsoft Entra app, see Quickstart: Register an application with the Microsoft identity platform.

Authenticate using DefaultAzureCredential

The easiest way to use Microsoft Entra to authenticate a backend application is to use DefaultAzureCredential, but it's recommended to use a different method in a production environment including a specific TokenCredential or pared-down ChainedTokenCredential. For more information about the pros and cons of using DefaultAzureCredential, see Credential chains in the Azure Identity client library for Java.

DefaultAzureCredential supports different authentication mechanisms and determines the appropriate credential type based on the environment it's executing in. It attempts to use multiple credential types in an order until it finds a working credential.

You can authenticate Microsoft Entra app credentials using DefaultAzureCredentialBuilder. Save connection parameters such as client secret tenantID, clientID, and client secret values as environmental variables. Once the TokenCredential is created, pass it to ServiceClient or other builder as the 'credential' parameter.

In this example, DefaultAzureCredentialBuilder attempts to authenticate a connection from the list described in DefaultAzureCredential. The result of a successful Microsoft Entra authentication is a security token credential that is passed to a constructor such as ServiceClient.

TokenCredential defaultAzureCredential = new DefaultAzureCredentialBuilder().build();
Authenticate using ClientSecretCredentialBuilder

You can use ClientSecretCredentialBuilder to create a credential using client secret information. If successful, this method returns a TokenCredential that can be passed to ServiceClient or other builder as the 'credential' parameter.

In this example, Microsoft Entra app registration client secret, client ID, and tenant ID values have been added to environment variables. These environment variables are used by ClientSecretCredentialBuilder to build the credential.

string clientSecretValue = System.getenv("AZURE_CLIENT_SECRET");
string clientID = System.getenv("AZURE_CLIENT_ID");
string tenantID = System.getenv("AZURE_TENANT_ID");

TokenCredential credential =
     new ClientSecretCredentialBuilder()
          .tenantId(tenantID)
          .clientId(clientID)
          .clientSecret(clientSecretValue)
          .build();
Other authentication classes

The Java SDK also includes these classes that authenticate a backend app with Microsoft Entra:

Code samples

For working samples of Microsoft Entra service authentication, see Role based authentication sample.

Invoke a method on a device

Call DeviceMethod.invoke to invoke a method on a device and return the result status.

The invoke payload parameter is optional. Use null if there is no payload supplied. The payload parameter can take different data forms including string, byte array, and HashMap. For examples, see Direct Method Tests.

This example calls the "reboot" method to initiate a reboot on the device. The "reboot" method is mapped to a listener on the device as described in the Create a direct method callback listener section of this article.

For example:

String deviceId = "myFirstDevice";
String methodName = "reboot";
String payload = "Test payload";
Long responseTimeout = TimeUnit.SECONDS.toSeconds(30);
Long connectTimeout = TimeUnit.SECONDS.toSeconds(5);

MethodResult result = methodClient.invoke(deviceId, methodName, responseTimeout, connectTimeout, payload);
if (result == null)
{
    throw new IOException("Method invoke returns null");
}
System.out.println("Status=" + result.getStatus());

SDK service samples

The Azure IoT SDK for Java provides a working sample of service apps that handle direct method tasks. For more information, see:

  • Python SDK - Python version 3.7 or later is recommended. Make sure to use the 32-bit or 64-bit installation as required by your setup. When prompted during the installation, make sure to add Python to your platform-specific environment variable.

Overview

This article describes how to use the Azure IoT SDK for Python to create device and backend service application code for device direct methods.

Install packages

The azure-iot-device library must be installed to create device applications.

pip install azure-iot-device

The azure-iot-hub library must be installed to create backend service applications.

pip install azure-iot-hub

Create a device application

This section describes how to use device application code to create a direct method callback listener.

Important

This article includes steps to connect a device using a shared access signature, also called symmetric key authentication. This authentication method is convenient for testing and evaluation, but authenticating a device using X.509 certificates is a more secure approach. To learn more, see Security best practices > Connection security.

Device import statements

Add this import statement to access IoTHubDeviceClient and MethodResponse.

# import the device client library
from azure.iot.device import IoTHubDeviceClient, MethodResponse

Connect to a device

The IoTHubDeviceClient class contains methods that can be used to work with direct methods.

Use create_from_connection_string to connect an application to a device using a device connection string.

# substitute the device connection string in conn_str
# and add it to the IoTHubDeviceClient object
conn_str = "{IoT hub device connection string}"
device_client = IoTHubDeviceClient.create_from_connection_string(conn_str)

Create a direct method callback

Use on_method_request_received to create a handler function or coroutine that is called when a direct method is received. The listener is associated with a method name keyword, such as "reboot". The method name can be used in an IoT Hub or backend application to trigger the callback method on the device.

The handler function should create a MethodResponse and pass it to send_method_response to send a direct method response acknowledgment to the calling application.

This example sets up a direct method handler named method_request_handler.

try:
    # Attach the handler to the client
    client.on_method_request_received = method_request_handler
except:
    # In the event of failure, clean up
    client.shutdown()

In this example, the method_request_handler callback method implements the direct method on the device. The code is executed when the "rebootDevice" direct method is called from a service application. The method calls send_method_response to send a direct method response acknowledgment to the calling application.

# Define the handler for method requests
def method_request_handler(method_request):
    if method_request.name == "rebootDevice":
        # Act on the method by rebooting the device
        print("Rebooting device")
        time.sleep(20)
        print("Device rebooted")
        # Create a method response indicating the method request was resolved
        resp_status = 200
        resp_payload = {"Response": "This is the response from the device"}
        method_response = MethodResponse(method_request.request_id, resp_status, resp_payload)
    else:
        # Create a method response indicating the method request was for an unknown method
        resp_status = 404
        resp_payload = {"Response": "Unknown method"}
        method_response = MethodResponse(method_request.request_id, resp_status, resp_payload)

    # Send the method response
    client.send_method_response(method_response)

SDK device samples

The Azure IoT SDK for Python provides a working sample of a device app that handles direct method tasks. For more information, see Receive direct method.

Create a backend application

This section describes how to use a backend service application to call a direct method on a device.

The IoTHubRegistryManager class exposes all methods required to create a backend application to send messages to a device.

Service import statements

Add these import statements to connect to Iot Hub, send cloud-to-device direct methods, and receive device direct method responses.

from azure.iot.hub import IoTHubRegistryManager
from azure.iot.hub.models import CloudToDeviceMethod, CloudToDeviceMethodResult

Connect to IoT hub

You can connect a backend service to IoT Hub using the following methods:

  • Shared access policy
  • Microsoft Entra

Important

This article includes steps to connect to a service using a shared access signature. This authentication method is convenient for testing and evaluation, but authenticating to a service with Microsoft Entra ID or managed identities is a more secure approach. To learn more, see Security best practices > Cloud security.

Connect using a shared access policy

Connect to IoT hub using from_connection_string.

To invoke a direct method on a device through IoT Hub, your service needs the service connect permission. By default, every IoT Hub is created with a shared access policy named service that grants this permission.

As a parameter to from_connection_string, supply the service shared access policy. For more information about shared access policies, see Control access to IoT Hub with shared access signatures.

For example:

# Connect to IoT hub
IOTHUB_CONNECTION_STRING = "{IoT hub service connection string}"
iothub_registry_manager = IoTHubRegistryManager.from_connection_string(IOTHUB_CONNECTION_STRING)

Connect using Microsoft Entra

A backend app that uses Microsoft Entra must successfully authenticate and obtain a security token credential before connecting to IoT Hub. This token is passed to a IoT Hub connection method. For general information about setting up and using Microsoft Entra for IoT Hub, see Control access to IoT Hub by using Microsoft Entra ID.

For an overview of Python SDK authentication, see Authenticate Python apps to Azure services by using the Azure SDK for Python

Configure Microsoft Entra app

You must set up a Microsoft Entra app that is configured for your preferred authentication credential. The app contains parameters such as client secret that are used by the backend application to authenticate. The available app authentication configurations are:

  • Client secret
  • Certificate
  • Federated identity credential

Microsoft Entra apps may require specific role permissions depending on operations being performed. For example, IoT Hub Twin Contributor is required to enable read and write access to a IoT Hub device and module twins. For more information, see Manage access to IoT Hub by using Azure RBAC role assignment.

For more information about setting up a Microsoft Entra app, see Quickstart: Register an application with the Microsoft identity platform.

Authenticate using DefaultAzureCredential

The easiest way to use Microsoft Entra to authenticate a backend application is to use DefaultAzureCredential, but it's recommended to use a different method in a production environment including a specific TokenCredential or pared-down ChainedTokenCredential. For simplicity, this section describes authentication using DefaultAzureCredential and Client secret. For more information about the pros and cons of using DefaultAzureCredential, see Credential chains in the Azure Identity client library for Python.

DefaultAzureCredential supports different authentication mechanisms and determines the appropriate credential type based on the environment it's executing in. It attempts to use multiple credential types in an order until it finds a working credential.

Microsoft Entra requires this import package and corresponding import statement:

pip install azure-identity
from azure.identity import DefaultAzureCredential

In this example, Microsoft Entra app registration client secret, client ID, and tenant ID have been added to environment variables. These environment variables are used by DefaultAzureCredential to authenticate the application. The result of a successful Microsoft Entra authentication is a security token credential that is passed to an IoT Hub connection method.

from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()

The resulting AccessToken can then be passed to from_token_credential to connect to IoT Hub for any SDK client that accepts Microsoft Entra credentials:

from_token_credential requires two parameters:

  • The Azure service URL - The Azure service URL should be in the format {Your Entra domain URL}.azure-devices.net without a https:// prefix. For example, MyAzureDomain.azure-devices.net.
  • The Azure credential token

In this example, the Azure credential is obtained using DefaultAzureCredential. The Azure service URL and credential are then supplied to IoTHubRegistryManager.from_token_credential to create the connection to IoT Hub.

import sys
import os

from azure.identity import DefaultAzureCredential
from azure.iot.hub import IoTHubRegistryManager

# Define the client secret values
clientSecretValue = 'xxxxxxxxxxxxxxx'
clientID = 'xxxxxxxxxxxxxx'
tenantID = 'xxxxxxxxxxxxx'

# Set environment variables
os.environ['AZURE_CLIENT_SECRET'] = clientSecretValue
os.environ['AZURE_CLIENT_ID'] = clientID
os.environ['AZURE_TENANT_ID'] = tenantID

# Acquire a credential object
credential = DefaultAzureCredential()

# Use Entra to authorize IoT Hub service
print("Connecting to IoTHubRegistryManager...")
iothub_registry_manager = IoTHubRegistryManager.from_token_credential(
url="MyAzureDomain.azure-devices.net",
token_credential=credential)
Code samples

For working samples of Microsoft Entra service authentication, see Microsoft Authentication Library (MSAL) for Python.

Invoke a method on a device

You can invoke a direct method by name on a device. The method name identifies the method. In the following and previous device example shown in Create a direct method callback, the direct method name is "rebootDevice".

To invoke a direct method on a device:

  1. Create a CloudToDeviceMethod object. Supply the method name and payload as parameters.
  2. Call invoke_device_method to invoke a direct method on a device. Supply the device ID and CloudToDeviceMethod payload object as parameters.

This example calls CloudToDeviceMethod to invoke a direct method named "rebootDevice" on a device. After the direct method has been successfully invoked, the direct method response payload is displayed.

CONNECTION_STRING = "{IoTHubConnectionString}"
DEVICE_ID = "{deviceId}"

METHOD_NAME = "rebootDevice"
METHOD_PAYLOAD = "{\"method_number\":\"42\"}"
TIMEOUT = 60
WAIT_COUNT = 10

try:
    print ( "" )
    print ( "Invoking device to reboot..." )

    # Call the direct method.
    deviceMethod = CloudToDeviceMethod(method_name=METHOD_NAME, payload=METHOD_PAYLOAD)
    response = registry_manager.invoke_device_method(DEVICE_ID, deviceMethod)

    print ( "Successfully invoked the device to reboot." )

    print ( "The device has returned this payload:" )
    print ( response.payload )

except Exception as ex:
    print ( "" )
    print ( "Unexpected error {0}".format(ex) )
    return

SDK service samples

The Azure IoT SDK for Python provides working samples of service apps that handle direct method tasks. For more information, see:

  • Requires Node.js version 10.0.x or later

Overview

This article describes how to use the Azure IoT SDK for Node.js to create device and backend service application code for device direct methods.

Create a device application

This section describes how to use device application code to create a direct method callback.

Install SDK packages

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

Choose a transport protocol

The Client object supports these protocols:

  • Amqp
  • Http - When using Http, the Client instance checks for messages from IoT Hub infrequently (a minimum of every 25 minutes).
  • Mqtt
  • MqttWs
  • AmqpWs

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.

Create a client object

Create a Client object using the installed package.

For example:

const Client = require('azure-iot-device').Client;

Create a protocol object

Create a Protocol object using an installed transport package.

This example assigns the AMQP protocol:

const Protocol = require('azure-iot-device-amqp').Amqp;

Add the device connection string and transport protocol

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);

Open the connection to IoT Hub

Use the open method to open connection between an IoT device and IoT Hub.

For example:

client.open(function(err) {
  if (err) {
    console.error('error connecting to hub: ' + err);
    process.exit(1);
  }
})

Create a direct method callback

Call onDeviceMethod to create a callback handler function or coroutine that is called when a direct method is received. The listener is associated with a method name keyword, such as "reboot". The method name can be used in an IoT Hub or backend application to trigger the callback method on the device.

The callback handler function should call response.send to send a response acknowledgment message to the calling application.

This example sets up a direct method handler named onReboot that is called when the "reboot" direct method name is used.

client.onDeviceMethod('reboot', onReboot);

In this example, the onReboot callback method implements the direct method on the device. The code is executed when the "reboot" direct method is called from a service application. The function calls response.send to send a response acknowledgment message to the calling application.

var onReboot = function(request, response) {

    // Respond the cloud app for the direct method
    response.send(200, 'Reboot started', function(err) {
        if (err) {
            console.error('An error occurred when sending a method response:\n' + err.toString());
        } else {
            console.log('Response to method \'' + request.methodName + '\' sent successfully.');
        }
    });

    // Add your device's reboot API for physical restart.
    console.log('Rebooting!');
};

SDK device samples

The Azure IoT SDK for Node.js provides working samples of device apps that handle device management tasks. For more information, see:

Create a backend application

This section describes how to invoke a direct method on a device.

Install service SDK package

Run this command to install azure-iothub on your development machine:

npm install azure-iothub --save

Connect to IoT hub

You can connect a backend service to IoT Hub using the following methods:

  • Shared access policy
  • Microsoft Entra

Important

This article includes steps to connect to a service using a shared access signature. This authentication method is convenient for testing and evaluation, but authenticating to a service with Microsoft Entra ID or managed identities is a more secure approach. To learn more, see Security best practices > Cloud security.

Connect using a shared access policy

Use fromConnectionString to connect to IoT hub.

To invoke a direct method on a device through IoT Hub, your service needs the service connect permission. By default, every IoT Hub is created with a shared access policy named service that grants this permission.

As a parameter to CreateFromConnectionString, supply the service shared access policy connection string. For more information about shared access policies, see Control access to IoT Hub with shared access signatures.

var Client = require('azure-iothub').Client;
var connectionString = '{IoT hub shared access policy connection string}';
var client = Client.fromConnectionString(connectionString);

Connect using Microsoft Entra

A backend app that uses Microsoft Entra must successfully authenticate and obtain a security token credential before connecting to IoT Hub. This token is passed to a IoT Hub connection method. For general information about setting up and using Microsoft Entra for IoT Hub, see Control access to IoT Hub by using Microsoft Entra ID.

For an overview of Node.js SDK authentication, see:

Configure Microsoft Entra app

You must set up a Microsoft Entra app that is configured for your preferred authentication credential. The app contains parameters such as client secret that are used by the backend application to authenticate. The available app authentication configurations are:

  • Client secret
  • Certificate
  • Federated identity credential

Microsoft Entra apps may require specific role permissions depending on operations being performed. For example, IoT Hub Twin Contributor is required to enable read and write access to a IoT Hub device and module twins. For more information, see Manage access to IoT Hub by using Azure RBAC role assignment.

For more information about setting up a Microsoft Entra app, see Quickstart: Register an application with the Microsoft identity platform.

Authenticate using DefaultAzureCredential

The easiest way to use Microsoft Entra to authenticate a backend application is to use DefaultAzureCredential, but it's recommended to use a different method in a production environment including a specific TokenCredential or pared-down ChainedTokenCredential. For simplicity, this section describes authentication using DefaultAzureCredential and Client secret. For more information about the pros and cons of using DefaultAzureCredential, see Credential chains in the Azure Identity client library for JavaScript

DefaultAzureCredential supports different authentication mechanisms and determines the appropriate credential type based on the environment it's executing in. It attempts to use multiple credential types in an order until it finds a working credential.

Microsoft Entra requires this package:

npm install --save @azure/identity

In this example, Microsoft Entra app registration client secret, client ID, and tenant ID have been added to environment variables. These environment variables are used by DefaultAzureCredential to authenticate the application. The result of a successful Microsoft Entra authentication is a security token credential that is passed to an IoT Hub connection method.

import { DefaultAzureCredential } from "@azure/identity";

// Azure SDK clients accept the credential as a parameter
const credential = new DefaultAzureCredential();

The resulting credential token can then be passed to fromTokenCredential to connect to IoT Hub for any SDK client that accepts Microsoft Entra credentials:

fromTokenCredential requires two parameters:

  • The Azure service URL - The Azure service URL should be in the format {Your Entra domain URL}.azure-devices.net without a https:// prefix. For example, MyAzureDomain.azure-devices.net.
  • The Azure credential token

In this example, the Azure credential is obtained using DefaultAzureCredential. The Azure domain URL and credential are then supplied to Registry.fromTokenCredential to create the connection to IoT Hub.

const { DefaultAzureCredential } = require("@azure/identity");

let Registry = require('azure-iothub').Registry;

// Define the client secret values
clientSecretValue = 'xxxxxxxxxxxxxxx'
clientID = 'xxxxxxxxxxxxxx'
tenantID = 'xxxxxxxxxxxxx'

// Set environment variables
process.env['AZURE_CLIENT_SECRET'] = clientSecretValue;
process.env['AZURE_CLIENT_ID'] = clientID;
process.env['AZURE_TENANT_ID'] = tenantID;

// Acquire a credential object
const credential = new DefaultAzureCredential()

// Create an instance of the IoTHub registry
hostName = 'MyAzureDomain.azure-devices.net';
let registry = Registry.fromTokenCredential(hostName,credential);
Code samples

For working samples of Microsoft Entra service authentication, see Azure identity examples.

Invoke a method on a device

Use invokeDeviceMethod to invoke a direct method by name on a device. The method name parameter identifies the direct method.

This example calls the "reboot" method to initiate a reboot on the device. The "reboot" method is mapped to a callback handler function on the device as described in the Create a direct method callback section of this article.

var startRebootDevice = function(deviceToReboot) {

    var methodName = "reboot";

    var methodParams = {
        methodName: methodName,
        payload: null,
        timeoutInSeconds: 30
    };

    client.invokeDeviceMethod(deviceToReboot, methodParams, function(err, result) {
        if (err) {
            console.error("Direct method error: "+err.message);
        } else {
            console.log("Successfully invoked the device to reboot.");  
        }
    });
};

SDK service samples

The Azure IoT SDK for Node.js provides working samples of service apps that handle device management tasks. For more information, see: