你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用 Azure 门户和 .NET 设备创建 IoT 中心模块标识和模块孪生入门

模块标识和模块孪生类似于 Azure IoT 中心设备标识和设备孪生,但提供更精细的粒度。 Azure IoT 中心设备标识和设备孪生允许后端应用程序配置设备并提供设备条件的可见性,而模块标识和模块孪生为设备的各个组件提供这些功能。 在支持多个组件的设备上(例如操作系统设备或固件设备),模块标识和模块孪生允许每个部件拥有独立的配置和条件。

注意

本文所述的功能只能用于 IoT 中心的标准层。 有关 IoT 中心基本层和标准/免费层的详细信息,请参阅选择适合你的解决方案的 IoT 中心层

在本文中,你将学习如何:

  • 在门户中创建模块标识。

  • 使用 .NET 设备 SDK 更新设备的模块孪生。

注意

有关可用于生成设备和后端应用的 SDK 工具的详细信息,请参阅 Azure IoT SDK

先决条件

  • Visual Studio。

  • Azure 订阅中的 IoT 中心。 如果还没有中心,则可以按照创建 IoT 中心中的步骤进行操作。

  • 在 IoT 中心注册的设备。 如果 IoT 中心内没有设备,请按照注册设备中的步骤操作。

模块身份验证

你可以使用对称密钥或 X.509 证书对模块标识进行身份验证。 对于 X.509 证书身份验证,模块的证书的公用名 (CN) 格式必须 如 CN=<deviceid>/<moduleid> 所示。 例如:

openssl req -new -key d1m1.key.pem -out d1m1.csr -subj "/CN=device01\/module01"

在门户中创建模块标识

在一个设备标识中,最多可以创建 20 个模块标识。 若要添加标识,请执行以下步骤:

  1. 从 Azure 门户中的现有设备,选择“添加模块标识”以创建你的第一个模块标识。

  2. 输入名称“myFirstModule”。 保存模块标识。

  3. 新的模块标识将出现在屏幕底部。 选择它即可查看模块标识详细信息。

  4. 找到“连接字符串(主密钥)”。 可以在下一部分使用它,以便在控制台应用中的设备上设置模块。

    显示“模块标识详细信息”菜单的屏幕截图。

使用 .NET 设备 SDK 更新模块孪生

现在让我们从模拟设备与云进行通信。 创建模块标识后,在 IoT 中心内隐式创建模块孪生。 在本节中,将在更新模块孪生报告属性的模拟设备上创建 .NET 控制台应用。

创建 Visual Studio 项目

若要创建一个应用来更新模块孪生报告属性,请执行以下步骤:

  1. 在 Visual Studio 中依次选择“创建新项目”、“控制台应用(.NET Framework)”、“下一步”。

  2. 在“配置新项目”中,输入 UpdateModuleTwinReportedProperties 作为“项目名称”。 选择“下一步”继续操作。

    显示“配置你的新项目”弹出窗口的屏幕截图。

  3. 保留默认的 .NET 框架,然后选择“创建”。

安装最新的 Azure IoT 中心 .NET 设备 SDK

模块标识和模块孪生功能仅在 IoT 中心预发行设备 SDK 中可用。 若要安装它,请执行以下步骤:

  1. 在 Visual Studio 中,打开“工具”>“NuGet 包管理器”>“管理解决方案的 NuGet 包”。

  2. 选择“浏览”,然后选择“包括预发行版” 。 搜索 Microsoft.Azure.Devices.Client。 选择最新版本并安装。

    显示如何安装 Microsoft.Azure.Devices.Client 的屏幕截图。

    现在可以访问所有模块功能。

创建 UpdateModuleTwinReportedProperties 控制台应用

重要

本文包括使用共享访问签名(也称为对称密钥身份验证)连接设备的步骤。 此身份验证方法便于测试和评估,但使用 X.509 证书对设备进行身份验证是一种更安全的方法。 若要了解详细信息,请参阅“安全最佳做法 > 连接安全性”。

若要创建应用,请按以下步骤操作:

  1. Program.cs 文件顶部添加以下 using 语句:
using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.Devices.Shared;
using Newtonsoft.Json;
  1. 将以下字段添加到 Program 类。 将占位符值替换为之前保存的模块连接字符串。
private const string ModuleConnectionString = "<Your module connection string>";
private static ModuleClient Client = null;
  1. 将以下方法“OnDesiredPropertyChanged”添加到“Program”类 :
private static async Task OnDesiredPropertyChanged(TwinCollection desiredProperties, object userContext)
    {
        Console.WriteLine("desired property change:");
        Console.WriteLine(JsonConvert.SerializeObject(desiredProperties));
        Console.WriteLine("Sending current time as reported property");
        TwinCollection reportedProperties = new TwinCollection
        {
            ["DateTimeLastDesiredPropertyChangeReceived"] = DateTime.Now
        };

        await Client.UpdateReportedPropertiesAsync(reportedProperties).ConfigureAwait(false);
    }
  1. 最后,将 Main方法替换为以下代码:
static void Main(string[] args)
{
    Microsoft.Azure.Devices.Client.TransportType transport = Microsoft.Azure.Devices.Client.TransportType.Amqp;

    try
    {
        Client = ModuleClient.CreateFromConnectionString(ModuleConnectionString, transport);
        Client.SetConnectionStatusChangesHandler(ConnectionStatusChangeHandler);
        Client.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertyChanged, null).Wait();

        Console.WriteLine("Retrieving twin");
        var twinTask = Client.GetTwinAsync();
        twinTask.Wait();
        var twin = twinTask.Result;
        Console.WriteLine(JsonConvert.SerializeObject(twin));

        Console.WriteLine("Sending app start time as reported property");
        TwinCollection reportedProperties = new TwinCollection();
        reportedProperties["DateTimeLastAppLaunch"] = DateTime.Now;

        Client.UpdateReportedPropertiesAsync(reportedProperties);
    }
    catch (AggregateException ex)
    {
        Console.WriteLine("Error in sample: {0}", ex);
    }

    Console.WriteLine("Waiting for Events.  Press enter to exit...");
    Console.ReadKey();
    Client.CloseAsync().Wait();
}

private static void ConnectionStatusChangeHandler(ConnectionStatus status, ConnectionStatusChangeReason reason)
{
    Console.WriteLine($"Status {status} changed: {reason}");
}

可以通过 F5 生成并运行此应用。

现在你了解了如何检索模块孪生和借助 AMQP 协议更新报告属性。

后续步骤

若要继续了解 IoT 中心入门知识并浏览其他 IoT 方案,请参阅: