Get started with device twins (.NET)

Device twins are JSON documents that store device state information, including metadata, configurations, and conditions. IoT Hub persists a device twin for each device that connects to it.

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 IoT Hub tiers, see Choose the right IoT Hub tier.

Use device twins to:

  • Store device metadata from your solution back end.

  • Report current state information such as available capabilities and conditions, for example, the connectivity method used, from your device app.

  • Synchronize the state of long-running workflows, such as firmware and configuration updates, between a device app and a back-end app.

  • Query your device metadata, configuration, or state.

Device twins are designed for synchronization and for querying device configurations and conditions. More information on when to use device twins can be found in Understand device twins.

Device twins are stored in an IoT hub and contain the following elements:

  • Tags. Device metadata accessible only by the solution back end.

  • Desired properties. JSON objects modifiable by the solution back end and observable by the device app.

  • Reported properties. JSON objects modifiable by the device app and readable by the solution back end.

Tags and properties cannot contain arrays, but objects can be nested.

The following illustration shows device twin organization:

Device twin image showing functionality

Additionally, the solution back end can query device twins based on all the above data. For more information about device twins, see Understand device twins. For more information about querying, see IoT Hub query language.

This tutorial shows you how to:

  • Create a back-end app that adds tags to a device twin, and a simulated device app that reports its connectivity channel as a reported property on the device twin.

  • Query devices from your back-end app using filters on the tags and properties previously created.

In this tutorial, you create these .NET console apps:

  • CreateDeviceIdentity. This app creates a device identity and associated security key to connect your simulated device app.

  • AddTagsAndQuery. This back-end app adds tags and queries device twins.

  • ReportConnectivity. This device app simulates a device that connects to your IoT hub with the device identity created earlier, and reports its connectivity condition.

Note

The article Azure IoT SDKs provides information about the Azure IoT SDKs that you can use to build both device and back-end apps.

Prerequisites

  • Visual Studio.

  • An active Azure account. If you don't have an account, you can create a free account in just a couple of minutes.

Create an IoT hub

This section describes how to create an IoT hub using the Azure portal.

  1. Sign in to the Azure portal.

  2. From the Azure homepage, select the + Create a resource button, and then enter IoT Hub in the Search the Marketplace field.

  3. Select IoT Hub from the search results, and then select Create.

  4. On the Basics tab, complete the fields as follows:

    • Subscription: Select the subscription to use for your hub.

    • Resource Group: Select a resource group or create a new one. To create a new one, select Create new and fill in the name you want to use. To use an existing resource group, select that resource group. For more information, see Manage Azure Resource Manager resource groups.

    • Region: Select the region in which you want your hub to be located. Select the location closest to you.

    • IoT Hub Name: Enter a name for your hub. This name must be globally unique. If the name you enter is available, a green check mark appears.

    Important

    Because the IoT hub will be publicly discoverable as a DNS endpoint, be sure to avoid entering any sensitive or personally identifiable information when you name it.

    Create a hub in the Azure portal

  5. Select Next: Size and scale to continue creating your hub.

    Set the size and scale for a new hub using the Azure portal

    This screen allows you to set the following values:

    • Pricing and scale tier: Your selected tier. You can choose from several tiers, depending on how many features you want and how many messages you send through your solution per day. The free tier is intended for testing and evaluation. It allows 500 devices to be connected to the hub and up to 8,000 messages per day. Each Azure subscription can create one IoT hub in the free tier.

    • IoT Hub units: The number of messages allowed per unit per day depends on your hub's pricing tier. For example, if you want the hub to support ingress of 700,000 messages, you choose two S1 tier units. For details about the other tier options, see Choosing the right IoT Hub tier.

    • Advanced Settings > Device-to-cloud partitions: This property relates the device-to-cloud messages to the number of simultaneous readers of the messages. Most hubs need only four partitions.

  6. For this article, accept the default choices, and then select Review + create to review your choices. You see something similar to this screen.

    Review information for creating the new hub

  7. Select Create to create your new hub. Creating the hub takes a few minutes.

Register a new device in the IoT hub

In this section, you create a device identity in the identity registry in your IoT hub. A device cannot connect to a hub unless it has an entry in the identity registry. For more information, see the IoT Hub developer guide.

  1. In your IoT hub navigation menu, open IoT Devices, then select New to add a device in your IoT hub.

    Create device identity in portal

  2. In Create a device, provide a name for your new device, such as myDeviceId, and select Save. This action creates a device identity for your IoT hub.

    Add a new device

    Important

    The device ID may be visible in the logs collected for customer support and troubleshooting, so make sure to avoid any sensitive information while naming it.

  3. After the device is created, open the device from the list in the IoT devices pane. Copy the Primary Connection String to use later.

    Device connection string

Note

The IoT Hub identity registry only stores device identities to enable secure access to the IoT hub. It stores device IDs and keys to use as security credentials, and an enabled/disabled flag that you can use to disable access for an individual device. If your application needs to store other device-specific metadata, it should use an application-specific store. For more information, see IoT Hub developer guide.

Get the IoT hub connection string

In this article, you create a back-end service that adds desired properties to a device twin and then queries the identity registry to find all devices with reported properties that have been updated accordingly. Your service needs the service connect permission to modify desired properties of a device twin, and it needs the registry read permission to query the identity registry. There is no default shared access policy that contains only these two permissions, so you need to create one.

To create a shared access policy that grants service connect and registry read permissions and get a connection string for this policy, follow these steps:

  1. In the Azure portal, select Resource groups. Select the resource group where your hub is located, and then select your hub from the list of resources.

  2. On the left-side pane of your hub, select Shared access policies.

  3. From the top menu above the list of policies, select Add.

  4. Under Add a shared access policy, enter a descriptive name for your policy, such as serviceAndRegistryRead. Under Permissions, select Registry read and Service connect, and then select Create.

    Show how to add a new shared access policy

  5. Select your new policy from the list of policies.

  6. Under Shared access keys, select the copy icon for the Connection string -- primary key and save the value.

    Show how to retrieve the connection string

For more information about IoT Hub shared access policies and permissions, see Access control and permissions.

Create the service app

In this section, you create a .NET console app, using C#, that adds location metadata to the device twin associated with myDeviceId. It then queries the device twins stored in the IoT hub selecting the devices located in the US, and then the ones that reported a cellular connection.

  1. In Visual Studio, select Create a new project. In Create new project, select Console App (.NET Framework), and then select Next.

  2. In Configure your new project, name the project AddTagsAndQuery.

    Configure your AddTagsAndQuery project

  3. In Solution Explorer, right-click the AddTagsAndQuery project, and then select Manage NuGet Packages.

  4. Select Browse and search for and select Microsoft.Azure.Devices. Select Install.

    NuGet Package Manager window

    This step downloads, installs, and adds a reference to the Azure IoT service SDK NuGet package and its dependencies.

  5. Add the following using statements at the top of the Program.cs file:

    using Microsoft.Azure.Devices;
    
  6. Add the following fields to the Program class. Replace {iot hub connection string} with the IoT Hub connection string that you copied in Get the IoT hub connection string.

    static RegistryManager registryManager;
    static string connectionString = "{iot hub connection string}";
    
  7. Add the following method to the Program class:

    public static async Task AddTagsAndQuery()
    {
        var twin = await registryManager.GetTwinAsync("myDeviceId");
        var patch =
            @"{
                tags: {
                    location: {
                        region: 'US',
                        plant: 'Redmond43'
                    }
                }
            }";
        await registryManager.UpdateTwinAsync(twin.DeviceId, patch, twin.ETag);
    
        var query = registryManager.CreateQuery(
          "SELECT * FROM devices WHERE tags.location.plant = 'Redmond43'", 100);
        var twinsInRedmond43 = await query.GetNextAsTwinAsync();
        Console.WriteLine("Devices in Redmond43: {0}", 
          string.Join(", ", twinsInRedmond43.Select(t => t.DeviceId)));
    
        query = registryManager.CreateQuery("SELECT * FROM devices WHERE tags.location.plant = 'Redmond43' AND properties.reported.connectivity.type = 'cellular'", 100);
        var twinsInRedmond43UsingCellular = await query.GetNextAsTwinAsync();
        Console.WriteLine("Devices in Redmond43 using cellular network: {0}", 
          string.Join(", ", twinsInRedmond43UsingCellular.Select(t => t.DeviceId)));
    }
    

    The RegistryManager class exposes all the methods required to interact with device twins from the service. The previous code first initializes the registryManager object, then retrieves the device twin for myDeviceId, and finally updates its tags with the desired location information.

    After updating, it executes two queries: the first selects only the device twins of devices located in the Redmond43 plant, and the second refines the query to select only the devices that are also connected through cellular network.

    The previous code, when it creates the query object, specifies a maximum number of returned documents. The query object contains a HasMoreResults boolean property that you can use to invoke the GetNextAsTwinAsync methods multiple times to retrieve all results. A method called GetNextAsJson is available for results that are not device twins, for example, results of aggregation queries.

  8. Finally, add the following lines to the Main method:

    registryManager = RegistryManager.CreateFromConnectionString(connectionString);
    AddTagsAndQuery().Wait();
    Console.WriteLine("Press Enter to exit.");
    Console.ReadLine();
    
  9. Run this application by right-clicking on the AddTagsAndQuery project and selecting Debug, followed by Start new instance. You should see one device in the results for the query asking for all devices located in Redmond43 and none for the query that restricts the results to devices that use a cellular network.

    Query results in window

In the next section, you create a device app that reports the connectivity information and changes the result of the query in the previous section.

Create the device app

In this section, you create a .NET console app that connects to your hub as myDeviceId, and then updates its reported properties to contain the information that it is connected using a cellular network.

  1. In Visual Studio, select File > New > Project. In Create new project, choose Console App (.NET Framework), and then select Next.

  2. In Configure your new project, name the project ReportConnectivity. For Solution, choose Add to solution, and then select Create.

  3. In Solution Explorer, right-click the ReportConnectivity project, and then select Manage NuGet Packages.

  4. Select Browse and search for and choose Microsoft.Azure.Devices.Client. Select Install.

    This step downloads, installs, and adds a reference to the Azure IoT device SDK NuGet package and its dependencies.

  5. Add the following using statements at the top of the Program.cs file:

    using Microsoft.Azure.Devices.Client;
    using Microsoft.Azure.Devices.Shared;
    using Newtonsoft.Json;
    
  6. Add the following fields to the Program class. Replace {device connection string} with the device connection string that you noted in Register a new device in the IoT hub.

    static string DeviceConnectionString = "HostName=<yourIotHubName>.azure-devices.net;DeviceId=<yourIotDeviceName>;SharedAccessKey=<yourIotDeviceAccessKey>";
    static DeviceClient Client = null;
    
  7. Add the following method to the Program class:

    public static async void InitClient()
    {
        try
        {
            Console.WriteLine("Connecting to hub");
            Client = DeviceClient.CreateFromConnectionString(DeviceConnectionString, 
              TransportType.Mqtt);
            Console.WriteLine("Retrieving twin");
            await Client.GetTwinAsync();
        }
        catch (Exception ex)
        {
            Console.WriteLine();
            Console.WriteLine("Error in sample: {0}", ex.Message);
        }
    }
    

    The Client object exposes all the methods you require to interact with device twins from the device. The code shown above initializes the Client object, and then retrieves the device twin for myDeviceId.

  8. Add the following method to the Program class:

    public static async void ReportConnectivity()
    {
        try
        {
            Console.WriteLine("Sending connectivity data as reported property");
    
            TwinCollection reportedProperties, connectivity;
            reportedProperties = new TwinCollection();
            connectivity = new TwinCollection();
            connectivity["type"] = "cellular";
            reportedProperties["connectivity"] = connectivity;
            await Client.UpdateReportedPropertiesAsync(reportedProperties);
        }
        catch (Exception ex)
        {
            Console.WriteLine();
            Console.WriteLine("Error in sample: {0}", ex.Message);
        }
    }
    

    The code above updates the reported property of myDeviceId with the connectivity information.

  9. Finally, add the following lines to the Main method:

    try
    {
        InitClient();
        ReportConnectivity();
    }
    catch (Exception ex)
    {
        Console.WriteLine();
        Console.WriteLine("Error in sample: {0}", ex.Message);
    }
    Console.WriteLine("Press Enter to exit.");
    Console.ReadLine();
    
  10. In Solution Explorer, right-click on your solution, and select Set StartUp Projects.

  11. In Common Properties > Startup Project, select Multiple startup projects. For ReportConnectivity, select Start as the Action. Select OK to save your changes.

  12. Run this app by right-clicking the ReportConnectivity project and selecting Debug, then Start new instance. You should see the app getting the twin information, and then sending connectivity as a reported property.

    Run device app to report connectivity

    After the device reported its connectivity information, it should appear in both queries.

  13. Right-click the AddTagsAndQuery project and select Debug > Start new instance to run the queries again. This time, myDeviceId should appear in both query results.

    Device connectivity reported successfully

Next steps

In this tutorial, you configured a new IoT hub in the Azure portal, and then created a device identity in the IoT hub's identity registry. You added device metadata as tags from a back-end app, and wrote a simulated device app to report device connectivity information in the device twin. You also learned how to query this information using the SQL-like IoT Hub query language.

You can learn more from the following resources: