Azure  

Working with Device Twins in Azure IoT Hub: Managing Configuration and State

Introduction

In IoT solutions, devices are often deployed in large numbers and operate remotely. Managing their configuration and tracking their state without direct access becomes a critical requirement. This is where device twins in Azure IoT Hub come into play. A device twin acts as a cloud-based representation of a physical device, allowing you to configure and monitor it in real time. In this article, we’ll explore how device twins work, understand desired and reported properties, and implement them using Azure CLI and .NET.

Prerequisites

Before getting started, ensure you have:

  • An active Microsoft Azure account

  • An IoT Hub instance

  • A registered IoT device

  • Azure CLI installed (az login)

  • .NET SDK installed

Device Twin

A device twin is a JSON document stored in the cloud that represents the state and configuration of a device.

It contains:

  • Metadata about the device

  • Configuration settings

  • Runtime state information

This allows you to interact with devices even when they are offline and synchronize state when they reconnect.

Understanding Desired and Reported Properties

Device twins are built around two important concepts:

Desired Properties

Desired properties are defined in the cloud and represent how the device is expected to behave.

They are used to:

  • Push configuration changes

  • Control device behavior remotely

  • Maintain a target state

Example

{
  "telemetryInterval": 10
}

Reported Properties

Reported properties are sent by the device and reflect its current state.

They are used to:

  • Confirm applied configurations

  • Share device status

  • Provide runtime insights

Example

{
  "status": "active",
  "telemetryInterval": 10
}

Updating Desired Properties using Azure CLI

We can update device configuration directly from the cloud using Azure CLI:

az iot hub device-twin update \
  --hub-name MyIoTHubDemo \
  --device-id mydevice001 \
  --set properties.desired.telemetryInterval=10

Output

{
  "properties": {
    "desired": {
      "telemetryInterval": 10
    }
  }
}

This sets the expected behavior for the device.

Working with Device Twins in .NET

The following example demonstrates how a device interacts with its twin:

using System;
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.Devices.Shared;

class Program
{
    private static string connectionString = "<DEVICE_CONNECTION_STRING>";
    private static DeviceClient deviceClient;

    static async Task Main(string[] args)
    {
        deviceClient = DeviceClient.CreateFromConnectionString(connectionString, TransportType.Mqtt);
        await deviceClient.OpenAsync();

        Console.WriteLine("Device connected.");

        // Read desired properties
        var twin = await deviceClient.GetTwinAsync();
        int interval = twin.Properties.Desired.Contains("telemetryInterval") 
            ? twin.Properties.Desired["telemetryInterval"] 
            : 5;

        Console.WriteLine($"Initial telemetry interval: {interval}");

        // Send reported properties
        var reported = new TwinCollection();
        reported["status"] = "active";
        reported["telemetryInterval"] = interval;

        await deviceClient.UpdateReportedPropertiesAsync(reported);
        Console.WriteLine("Reported properties sent.");

        // Listen for updates
        await deviceClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredChanged, null);

        Console.WriteLine("Waiting for updates...");
        await Task.Delay(-1);
    }

    private static async Task OnDesiredChanged(TwinCollection desiredProperties, object userContext)
    {
        if (desiredProperties.Contains("telemetryInterval"))
        {
            int newInterval = desiredProperties["telemetryInterval"];
            Console.WriteLine($"New interval received: {newInterval}");

            var reported = new TwinCollection();
            reported["telemetryInterval"] = newInterval;
            reported["ack"] = "updated";

            await deviceClient.UpdateReportedPropertiesAsync(reported);
            Console.WriteLine("Reported properties updated.");
        }
    }
}

Output

Device connected.
Initial telemetry interval: 10
Reported properties sent.
Waiting for updates...

New interval received: 20
Reported properties updated.

Conclusion

Device twins provide a powerful way to manage IoT devices remotely and efficiently. Desired properties allow you to control device behavior from the cloud, while reported properties give you real-time visibility into device state. Using both effectively helps you build scalable and maintainable IoT solutions.