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

教程:将 Linux 或 Windows 上运行的 IoT 即插即用多组件设备应用程序连接到 IoT 中心

本教程介绍如何使用组件生成示例 IoT 即插即用设备应用程序,将其连接到 IoT 中心,并使用 Azure IoT 资源管理器工具来查看它发送到中心的信息。 该示例应用程序以 C 编写,包含在适用于 C 的 Azure IoT 设备 SDK 中。解决方案构建者可以使用 Azure IoT 资源管理器工具来了解 IoT 即插即用设备的功能,而无需查看任何设备代码。

浏览代码

本教程介绍以下操作:

  • 下载示例代码。
  • 生成示例代码。
  • 运行该示例设备应用程序,并验证它是否会连接到 IoT 中心。
  • 检查源代码。

先决条件

请确保设置环境(包括 IoT 中心)后再继续。

可以在 Linux 或 Windows 上完成本教程。 本教程中的 shell 命令遵循适用于路径分隔符“/”的 Linux 约定,如果你是在 Windows 上操作,请务必将这些分隔符替换为“\”。

先决条件根据操作系统而异:

Linux

本教程假设你使用 Ubuntu Linux。 本教程中的步骤已使用 Ubuntu 18.04 进行了测试。

若要在 Linux 上完成本教程,需在本地 Linux 环境上安装以下软件:

使用 命令安装“GCC”、“Git”、“cmake”和所有必要的依赖项:

sudo apt-get update
sudo apt-get install -y git cmake build-essential curl libcurl4-openssl-dev libssl-dev uuid-dev

验证 cmake 的版本是否高于 2.8.12,GCC 的版本是否高于 4.4.7 。

cmake --version
gcc --version

Windows

若要在 Windows 上完成本教程,需在本地 Windows 环境上安装以下软件:

下载代码

如果你完成了教程:将 Linux 或 Windows 上运行的示例 IoT 即插即用设备应用程序连接到 IoT 中心 (C),则已下载了该代码。

在本教程中,你将准备一个用于克隆和生成 Azure IoT 中心设备 C SDK 的开发环境。

在所选文件夹中打开命令提示符。 执行以下命令将 Azure IoT C SDK 和库 GitHub 存储库克隆到此位置:

git clone https://github.com/Azure/azure-iot-sdk-c.git
cd azure-iot-sdk-c
git submodule update --init

此操作需要几分钟才能完成。

生成并运行代码

可以使用 Visual Studio 或在命令行使用 cmake 生成并运行代码。

使用 Visual Studio

  1. 打开克隆存储库的根文件夹。 几秒钟后,Visual Studio 中的 CMake 支持会创建运行和调试项目所需的所有内容。

  2. Visual Studio 准备就绪后,在“解决方案资源管理器”中,导航到示例 iothub_client/samples/pnp/pnp_temperature_controller/。

  3. 右键单击“pnp_temperature_controller.c”文件并选择“添加调试配置”。 选择“默认值”。

  4. Visual Studio 将打开“launch.vs.json”文件。 按照以下代码片段编辑此文件,设置所需的环境变量。 完成为 IoT 即插即用设置环境的快速入门和教程后,请记下范围 ID 和注册主密钥:

    {
      "version": "0.2.1",
      "defaults": {},
      "configurations": [
        {
          "type": "default",
          "project": "iothub_client\\samples\\pnp\\pnp_temperature_controller\\pnp_temperature_controller.c",
          "projectTarget": "",
          "name": "pnp_temperature_controller.c",
          "env": {
            "IOTHUB_DEVICE_SECURITY_TYPE": "DPS",
            "IOTHUB_DEVICE_DPS_ID_SCOPE": "<Your ID scope>",
            "IOTHUB_DEVICE_DPS_DEVICE_ID": "my-pnp-device",
            "IOTHUB_DEVICE_DPS_DEVICE_KEY": "<Your enrollment primary key>"
          }
        }
      ]
    }
    
  5. 右键单击“pnp_temperature_controller.c”文件并选择“设置为启动项”。

  6. 若要在 Visual Studio 中跟踪代码执行,请在 pnp_temperature_controller.c 文件中向 main 函数添加一个断点。

  7. 现在可以从“调试”菜单中运行并调试示例。

设备现在可以接收命令和属性更新,并已开始向中心发送遥测数据。 在执行后续步骤时,保持示例处于运行状态。

在命令行上使用 cmake

生成示例:

  1. 在克隆设备 SDK 根文件夹中创建一个 cmake 子文件夹,并导航到该文件夹:

    cd azure-iot-sdk-c
    mkdir cmake
    cd cmake
    
  2. 运行以下命令,为 SDK 和示例生成项目文件:

    cmake ..
    cmake --build .
    

设置环境部分创建了四个环境变量来配置示例,以使用设备预配服务 (DPS) 连接到 IoT 中心:

  • 具有值 的 IOTHUB_DEVICE_SECURITY_TYPE
  • 包含 DPS ID 范围的 IOTHUB_DEVICE_DPS_ID_SCOPE。
  • 包含值 的 IOTHUB_DEVICE_DPS_DEVICE_ID。
  • 包含注册主密钥的 IOTHUB_DEVICE_DPS_DEVICE_KEY。
  • 包含值 的 IOTHUB_DEVICE_DPS_ENDPOINT。

若要详细了解示例配置,请参阅示例自述文件

若要运行该示例:

  1. 在 cmake 文件夹中,导航到包含可执行文件的文件夹,并运行该文件:

    # Bash
    cd iothub_client/samples/pnp/pnp_temperature_controller
    ./pnp_temperature_controller
    
    REM Windows
    cd iothub_client\samples\pnp\pnp_temperature_controller\Debug
    pnp_temperature_controller.exe
    

设备现在可以接收命令和属性更新,并已开始向中心发送遥测数据。 在执行后续步骤时,保持示例处于运行状态。

使用 Azure IoT 资源管理器验证代码

设备客户端示例启动后,使用 Azure IoT 资源管理器工具验证它是否正常工作。

  1. 打开 Azure IoT 资源管理器。

  2. 在“IoT 中心”页上,如果尚未将连接添加到 IoT 中心,请选择“+ 添加连接”。 输入先前创建的 IoT 中心的连接字符串,然后选择“保存”。

  3. 在“IoT 即插即用设置”页上,选择“+ 添加”“本地文件夹”,然后选择在其中保存了模型文件的本地“模型”文件夹。

  4. 在“IoT 中心”页上,单击要使用的中心的名称。 你将看到已注册到 IoT 中心的设备的列表。

  5. 单击前面创建的设备的“设备 ID”。

  6. 左侧菜单显示了可用于设备的不同类型的信息。

  7. 选择“IoT 即插即用组件”以查看设备的模型信息。

  8. 可以查看设备的不同组件。 默认组件和任何其他组件。 选择要使用的组件。

  9. 选择“遥测”页,然后选择“开始”,查看设备正在为此组件发送的遥测数据。

  10. 选择“属性(只读)”页以查看为此组件报告的只读属性。

  11. 选择“属性(可写)”页以查看可以为此组件更新的可写属性。

  12. 按名称选择属性,为其输入新值,然后选择“更新所需值”。

  13. 若要查看显示的新值,请选择“刷新”按钮。

  14. 选择“命令”页以查看此组件的所有命令。

  15. 选择要测试参数的命令(如果有)。 选择“发送命令”以调用设备上的命令。 可以在正在运行示例代码的命令提示符窗口中看到你的设备响应命令。

查看代码

此示例实现 IoT 即插即用温度控制器设备。 此示例实现具有多个组件的模型。 温度设备的数字孪生定义语言 (DTDL) 模型文件定义了设备实现的遥测、属性和命令。

IoT 即插即用帮助程序函数

对于本示例,代码使用 /common 文件夹中的一些帮助程序函数:

pnp_device_client_ll 包含 IoT 即插即用连接方法,其中包含 作为参数 PnP_CreateDeviceClientLLHandle

pnp_protocol 包含 IoT 即插即用帮助程序函数:

  • PnP_CreateReportedProperty
  • PnP_CreateReportedPropertyWithStatus
  • PnP_ParseCommandName
  • PnP_CreateTelemetryMessageHandle
  • PnP_ProcessTwinData
  • PnP_CopyPayloadToString
  • PnP_CreateDeviceClientLLHandle_ViaDps

这些帮助程序函数是通用的,足以供你在自己的项目中使用。 此示例在与模型中每个组件对应的三个文件中使用:

  • pnp_deviceinfo_component
  • pnp_temperature_controller
  • pnp_thermostat_component

例如,在 pnp_deviceinfo_component 文件中, 函数使用两种帮助程序函数:

if ((jsonToSend = PnP_CreateReportedProperty(componentName, propertyName, propertyValue)) == NULL)
{
    LogError("Unable to build reported property response for propertyName=%s, propertyValue=%s", propertyName, propertyValue);
}
else
{
    const char* jsonToSendStr = STRING_c_str(jsonToSend);
    size_t jsonToSendStrLen = strlen(jsonToSendStr);

    if ((iothubClientResult = IoTHubDeviceClient_LL_SendReportedState(deviceClientLL, (const unsigned char*)jsonToSendStr, jsonToSendStrLen, NULL, NULL)) != IOTHUB_CLIENT_OK)
    {
        LogError("Unable to send reported state for property=%s, error=%d", propertyName, iothubClientResult);
    }
    else
    {
        LogInfo("Sending device information property to IoTHub.  propertyName=%s, propertyValue=%s", propertyName, propertyValue);
    }
}

示例中的每个组件都遵循此模式。

代码流

main 函数将初始化连接并发送模型 ID:

deviceClient = CreateDeviceClientAndAllocateComponents();

此代码使用 PnP_CreateDeviceClientLLHandle 连接到 IoT 中心,将 modelId 设置为一个选项,并设置设备方法和设备孪生回叫处理程序,以提供直接方法和设备孪生更新:

g_pnpDeviceConfiguration.deviceMethodCallback = PnP_TempControlComponent_DeviceMethodCallback;
g_pnpDeviceConfiguration.deviceTwinCallback = PnP_TempControlComponent_DeviceTwinCallback;
g_pnpDeviceConfiguration.modelId = g_temperatureControllerModelId;
...

deviceClient = PnP_CreateDeviceClientLLHandle(&g_pnpDeviceConfiguration);

&g_pnpDeviceConfiguration 也包含连接信息。 环境变量 IOTHUB_DEVICE_SECURITY_TYPE 确定示例是使用连接字符串还是使用设备预配服务来连接到 IoT 中心。

设备发送模型 ID 时,它会成为 IoT 即插即用设备。

回叫处理程序就绪后,设备会响应孪生更新和直接方法调用:

  • 对于设备孪生回叫,PnP_TempControlComponent_DeviceTwinCallback 调用 PnP_ProcessTwinData 函数来处理数据。 PnP_ProcessTwinData 使用访问者模式分析 JSON,然后访问每个属性,并对每个元素调用 PnP_TempControlComponent_ApplicationPropertyCallback

  • 对于命令回叫,PnP_TempControlComponent_DeviceMethodCallback 函数使用帮助程序函数来分析命令和组件名称:

    PnP_ParseCommandName(methodName, &componentName, &componentNameSize, &pnpCommandName);
    

    然后 PnP_TempControlComponent_DeviceMethodCallback 函数对该组件调用命令:

    LogInfo("Received PnP command for component=%.*s, command=%s", (int)componentNameSize, componentName, pnpCommandName);
    if (strncmp((const char*)componentName, g_thermostatComponent1Name, g_thermostatComponent1Size) == 0)
    {
        result = PnP_ThermostatComponent_ProcessCommand(g_thermostatHandle1, pnpCommandName, rootValue, response, responseSize);
    }
    else if (strncmp((const char*)componentName, g_thermostatComponent2Name, g_thermostatComponent2Size) == 0)
    {
        result = PnP_ThermostatComponent_ProcessCommand(g_thermostatHandle2, pnpCommandName, rootValue, response, responseSize);
    }
    else
    {
        LogError("PnP component=%.*s is not supported by TemperatureController", (int)componentNameSize, componentName);
        result = PNP_STATUS_NOT_FOUND;
    }
    

main 函数将初始化发送到 IoT 中心的只读属性:

PnP_TempControlComponent_ReportSerialNumber_Property(deviceClient);
PnP_DeviceInfoComponent_Report_All_Properties(g_deviceInfoComponentName, deviceClient);
PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property(g_thermostatHandle1, deviceClient);
PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property(g_thermostatHandle2, deviceClient);

main 函数进入一个循环,以更新每个组件的事件和遥测数据:

while (true)
{
    PnP_TempControlComponent_SendWorkingSet(deviceClient);
    PnP_ThermostatComponent_SendTelemetry(g_thermostatHandle1, deviceClient);
    PnP_ThermostatComponent_SendTelemetry(g_thermostatHandle2, deviceClient);
}

PnP_ThermostatComponent_SendTelemetry 函数演示如何使用 PNP_THERMOSTAT_COMPONENT 结构。 该示例使用此结构来存储关于温度控制器中两个调温器的信息。 代码使用 PnP_CreateTelemetryMessageHandle 函数来准备并发送消息:

messageHandle = PnP_CreateTelemetryMessageHandle(pnpThermostatComponent->componentName, temperatureStringBuffer);
...
iothubResult = IoTHubDeviceClient_LL_SendEventAsync(deviceClientLL, messageHandle, NULL, NULL);

main 函数最终会销毁不同的组件,并关闭与中心的连接。

本教程介绍如何使用组件生成示例 IoT 即插即用设备应用程序,将其连接到 IoT 中心,并使用 Azure IoT 资源管理器工具来查看它发送到中心的信息。 该示例应用程序以 C# 编写,包含在用于 C# 的 Azure IoT 设备 SDK 中。 解决方案构建者可以使用 Azure IoT 资源管理器工具来了解 IoT 即插即用设备的功能,而无需查看任何设备代码。

浏览代码

本教程介绍以下操作:

  • 下载示例代码。
  • 生成示例代码。
  • 运行该示例设备应用程序,并验证它是否会连接到 IoT 中心。
  • 检查源代码。

先决条件

请确保设置环境(包括 IoT 中心)后再继续。

可以在 Linux 或 Windows 上运行本教程。 本教程中的 shell 命令遵循适用于路径分隔符“/”的 Linux 约定,如果你是在 Windows 上操作,请务必将这些分隔符替换为“\”。

使用示例代码克隆 SDK 存储库

如果你完成了教程:将 Windows 上运行的示例 IoT 即插即用设备应用程序连接到 IoT 中心 (C#),则已经克隆了该存储库。

为 C# GitHub 存储库克隆 Azure IoT 示例中的示例。 在所选文件夹中打开命令提示符。 运行以下命令,以克隆适用于 .NET 的 Microsoft Azure IoT SDK GitHub 存储库:

git clone https://github.com/Azure/azure-iot-sdk-csharp.git

生成代码

现在可以生成示例并运行它。 运行以下命令生成示例:

cd azure-iot-sdk-csharp/iothub/device/samples/solutions/PnpDeviceSamples/TemperatureController
dotnet build

运行设备示例

若要运行示例,请运行以下命令:

dotnet run

设备现在可以接收命令和属性更新,并已开始向中心发送遥测数据。 在执行后续步骤时,保持示例处于运行状态。

使用 Azure IoT 资源管理器验证代码

设备客户端示例启动后,使用 Azure IoT 资源管理器工具验证它是否正常工作。

  1. 打开 Azure IoT 资源管理器。

  2. 在“IoT 中心”页上,如果尚未将连接添加到 IoT 中心,请选择“+ 添加连接”。 输入先前创建的 IoT 中心的连接字符串,然后选择“保存”。

  3. 在“IoT 即插即用设置”页上,选择“+ 添加”“本地文件夹”,然后选择在其中保存了模型文件的本地“模型”文件夹。

  4. 在“IoT 中心”页上,单击要使用的中心的名称。 你将看到已注册到 IoT 中心的设备的列表。

  5. 单击前面创建的设备的“设备 ID”。

  6. 左侧菜单显示了可用于设备的不同类型的信息。

  7. 选择“IoT 即插即用组件”以查看设备的模型信息。

  8. 可以查看设备的不同组件。 默认组件和任何其他组件。 选择要使用的组件。

  9. 选择“遥测”页,然后选择“开始”,查看设备正在为此组件发送的遥测数据。

  10. 选择“属性(只读)”页以查看为此组件报告的只读属性。

  11. 选择“属性(可写)”页以查看可以为此组件更新的可写属性。

  12. 按名称选择属性,为其输入新值,然后选择“更新所需值”。

  13. 若要查看显示的新值,请选择“刷新”按钮。

  14. 选择“命令”页以查看此组件的所有命令。

  15. 选择要测试参数的命令(如果有)。 选择“发送命令”以调用设备上的命令。 可以在正在运行示例代码的命令提示符窗口中看到你的设备响应命令。

查看代码

此示例实现 IoT 即插即用温度控制器设备。 此示例实现的模型使用多个组件温度设备的数字孪生定义语言 (DTDL) 模型文件定义了设备实现的遥测、属性和命令。

设备代码使用标准 CreateFromConnectionString 方法连接到 IoT 中心。 设备发送在连接请求中实现的 DTDL 模型的模型 ID。 发送模型 ID 的设备是 IoT 即插即用设备:

private static DeviceClient InitializeDeviceClient(string hostname, IAuthenticationMethod authenticationMethod)
{
    var options = new ClientOptions
    {
        ModelId = ModelId,
    };

    var deviceClient = DeviceClient.Create(hostname, authenticationMethod, TransportType.Mqtt, options);
    deviceClient.SetConnectionStatusChangesHandler((status, reason) =>
    {
        s_logger.LogDebug($"Connection status change registered - status={status}, reason={reason}.");
    });

    return deviceClient;
}

模型 ID 存储在代码中,如以下代码片段所示:

private const string ModelId = "dtmi:com:example:TemperatureController;1";

设备连接到 IoT 中心后,代码将注册命令处理程序。 reboot 命令是在默认组件中定义的。 getMaxMinReport 命令分别定义在两个恒温器组件中:

await _deviceClient.SetMethodHandlerAsync("reboot", HandleRebootCommandAsync, _deviceClient, cancellationToken);
await _deviceClient.SetMethodHandlerAsync("thermostat1*getMaxMinReport", HandleMaxMinReportCommandAsync, Thermostat1, cancellationToken);
await _deviceClient.SetMethodHandlerAsync("thermostat2*getMaxMinReport", HandleMaxMinReportCommandAsync, Thermostat2, cancellationToken);

对于两个恒温器组件上的所需属性更新,有单独的处理程序:

_desiredPropertyUpdateCallbacks.Add(Thermostat1, TargetTemperatureUpdateCallbackAsync);
_desiredPropertyUpdateCallbacks.Add(Thermostat2, TargetTemperatureUpdateCallbackAsync);

示例代码从每个恒温器组件发送遥测数据:

await SendTemperatureAsync(Thermostat1, cancellationToken);
await SendTemperatureAsync(Thermostat2, cancellationToken);

SendTemperatureTelemetryAsync 方法使用 PnpHhelper 类为每个组件创建消息:

using Message msg = PnpHelper.CreateIothubMessageUtf8(telemetryName, JsonConvert.SerializeObject(currentTemperature), componentName);

PnpHelper 类包含可以在多组件模型中使用的其他示例方法。

使用 Azure IoT 资源管理器工具查看两个恒温器组件中的遥测数据和属性:

Azure IoT 资源管理器中的多组件设备

还可以使用 Azure IoT 资源管理器工具在两个恒温器组件或默认组件中调用命令。

本教程介绍如何使用组件生成示例 IoT 即插即用设备应用程序,将其连接到 IoT 中心,并使用 Azure IoT 资源管理器工具来查看它发送到中心的信息。 该示例应用程序以 Java 编写,包含在用于 Java 的 Azure IoT 设备 SDK 中。 解决方案构建者可以使用 Azure IoT 资源管理器工具来了解 IoT 即插即用设备的功能,而无需查看任何设备代码。

浏览代码

本教程介绍以下操作:

  • 下载示例代码。
  • 生成示例代码。
  • 运行该示例设备应用程序,并验证它是否会连接到 IoT 中心。
  • 检查源代码。

先决条件

请确保设置环境(包括 IoT 中心)后再继续。

可以在 Linux 或 Windows 上运行本教程。 本教程中的 shell 命令遵循适用于路径分隔符“/”的 Linux 约定,如果你是在 Windows 上操作,请务必将这些分隔符替换为“\”。

若要完成本教程,需在本地开发环境中安装以下软件:

下载代码

如果完成了教程:将示例 IoT 即插即用设备应用程序连接到 IoT 中心 (Java),则已经克隆了该存储库。

在所选目录中打开命令提示符。 执行以下命令将 Azure IoT Java SDK 和库 GitHub 存储库克隆到此位置:

git clone https://github.com/Azure/azure-iot-sdk-java.git

此操作需要几分钟才能完成。

生成代码

导航到克隆的 Java SDK 存储库中温度控制器示例的根文件夹并生成它:

cd azure-iot-sdk-java/device/iot-device-samples/pnp-device-sample/temperature-controller-device-sample
mvn clean package

运行设备示例

设置环境部分创建了四个环境变量来配置示例,以使用设备预配服务 (DPS) 连接到 IoT 中心:

  • 具有值 的 IOTHUB_DEVICE_SECURITY_TYPE
  • 包含 DPS ID 范围的 IOTHUB_DEVICE_DPS_ID_SCOPE。
  • 包含值 的 IOTHUB_DEVICE_DPS_DEVICE_ID。
  • 包含注册主密钥的 IOTHUB_DEVICE_DPS_DEVICE_KEY。
  • 包含值 的 IOTHUB_DEVICE_DPS_ENDPOINT。

若要运行示例应用程序,请导航到“/device/iot-device-samples/pnp-device-sample/temperature-controller-device-sample”文件夹,并运行以下命令:

mvn exec:java -Dexec.mainClass="samples.com.microsoft.azure.sdk.iot.device.TemperatureController"

设备现在可以接收命令和属性更新,并已开始向中心发送遥测数据。 在执行后续步骤时,保持示例处于运行状态。

使用 Azure IoT 资源管理器验证代码

设备客户端示例启动后,使用 Azure IoT 资源管理器工具验证它是否正常工作。

  1. 打开 Azure IoT 资源管理器。

  2. 在“IoT 中心”页上,如果尚未将连接添加到 IoT 中心,请选择“+ 添加连接”。 输入先前创建的 IoT 中心的连接字符串,然后选择“保存”。

  3. 在“IoT 即插即用设置”页上,选择“+ 添加”“本地文件夹”,然后选择在其中保存了模型文件的本地“模型”文件夹。

  4. 在“IoT 中心”页上,单击要使用的中心的名称。 你将看到已注册到 IoT 中心的设备的列表。

  5. 单击前面创建的设备的“设备 ID”。

  6. 左侧菜单显示了可用于设备的不同类型的信息。

  7. 选择“IoT 即插即用组件”以查看设备的模型信息。

  8. 可以查看设备的不同组件。 默认组件和任何其他组件。 选择要使用的组件。

  9. 选择“遥测”页,然后选择“开始”,查看设备正在为此组件发送的遥测数据。

  10. 选择“属性(只读)”页以查看为此组件报告的只读属性。

  11. 选择“属性(可写)”页以查看可以为此组件更新的可写属性。

  12. 按名称选择属性,为其输入新值,然后选择“更新所需值”。

  13. 若要查看显示的新值,请选择“刷新”按钮。

  14. 选择“命令”页以查看此组件的所有命令。

  15. 选择要测试参数的命令(如果有)。 选择“发送命令”以调用设备上的命令。 可以在正在运行示例代码的命令提示符窗口中看到你的设备响应命令。

查看代码

此示例实现 IoT 即插即用温度控制器设备。 此示例实现的模型使用多个组件温度设备的数字孪生定义语言 (DTDL) 模型文件定义了设备实现的遥测、属性和命令。

设备代码使用标准 DeviceClient 类连接到 IoT 中心。 设备发送在连接请求中实现的 DTDL 模型的模型 ID。 发送模型 ID 的设备是 IoT 即插即用设备:

private static void initializeDeviceClient() throws URISyntaxException, IOException {
    ClientOptions options = new ClientOptions();
    options.setModelId(MODEL_ID);
    deviceClient = new DeviceClient(deviceConnectionString, protocol, options);

    deviceClient.registerConnectionStatusChangeCallback((status, statusChangeReason, throwable, callbackContext) -> {
        log.debug("Connection status change registered: status={}, reason={}", status, statusChangeReason);

        if (throwable != null) {
            log.debug("The connection status change was caused by the following Throwable: {}", throwable.getMessage());
            throwable.printStackTrace();
        }
    }, deviceClient);

    deviceClient.open();
}

模型 ID 存储在代码中,如以下代码片段所示:

private static final String MODEL_ID = "dtmi:com:example:Thermostat;1";

设备连接到 IoT 中心后,代码将注册命令处理程序。

deviceClient.subscribeToDeviceMethod(new MethodCallback(), null, new MethodIotHubEventCallback(), null);

对于两个恒温器组件上的所需属性更新,有单独的处理程序:

deviceClient.startDeviceTwin(new TwinIotHubEventCallback(), null, new GenericPropertyUpdateCallback(), null);
Map<Property, Pair<TwinPropertyCallBack, Object>> desiredPropertyUpdateCallback = Stream.of(
        new AbstractMap.SimpleEntry<Property, Pair<TwinPropertyCallBack, Object>>(
                new Property(THERMOSTAT_1, null),
                new Pair<>(new TargetTemperatureUpdateCallback(), THERMOSTAT_1)),
        new AbstractMap.SimpleEntry<Property, Pair<TwinPropertyCallBack, Object>>(
                new Property(THERMOSTAT_2, null),
                new Pair<>(new TargetTemperatureUpdateCallback(), THERMOSTAT_2))
).collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));

deviceClient.subscribeToTwinDesiredProperties(desiredPropertyUpdateCallback);

示例代码从每个恒温器组件发送遥测数据:

sendTemperatureReading(THERMOSTAT_1);
sendTemperatureReading(THERMOSTAT_2);

sendTemperatureReading 方法使用 PnpHhelper 类为每个组件创建消息:

Message message = PnpHelper.createIotHubMessageUtf8(telemetryName, currentTemperature, componentName);

PnpHelper 类包含可以在多组件模型中使用的其他示例方法。

使用 Azure IoT 资源管理器工具查看两个恒温器组件中的遥测数据和属性:

Azure IoT 资源管理器中的多组件设备

还可以使用 Azure IoT 资源管理器工具在两个恒温器组件或默认组件中调用命令。

本教程介绍如何使用组件生成示例 IoT 即插即用设备应用程序,将其连接到 IoT 中心,并使用 Azure IoT 资源管理器工具来查看它发送到中心的信息。 该示例应用程序针对 Node.js 编写,包含在用于 Node.js 的 Azure IoT 中心设备 SDK 中。 解决方案构建者可以使用 Azure IoT 资源管理器工具来了解 IoT 即插即用设备的功能,而无需查看任何设备代码。

浏览代码

本教程介绍以下操作:

  • 下载示例代码。
  • 运行该示例设备应用程序,并验证它是否会连接到 IoT 中心。
  • 检查源代码。

先决条件

请确保设置环境(包括 IoT 中心)后再继续。

若要完成本教程,需要在开发计算机上使用 Node.js。 可以从 nodejs.org 下载适用于多个平台的最新推荐版本。

可以使用以下命令验证开发计算机上 Node.js 当前的版本:

node --version

下载代码

如果你完成了教程:将 Windows 上运行的示例 IoT 即插即用设备应用程序连接到 IoT 中心 (Node),则已经克隆了该存储库。

在所选目录中打开命令提示符。 执行以下命令,将用于 Node.js 的 Microsoft Azure IoT SDK GitHub 存储库克隆到此位置:

git clone https://github.com/Azure/azure-iot-sdk-node

安装所需的库

使用设备 SDK 生成包含的示例代码。 你构建的应用程序会模拟一个即插即用设备,其中包含多个连接到 IoT 中心的组件。 应用程序将发送遥测数据和属性,并接收命令。

  1. 在本地终端窗口中,前往克隆的存储库的文件夹,导航到 /azure-iot-sdk-node/device/samples/javascript 文件夹。 然后运行以下命令以安装所需的库:
npm install

此命令会在文件夹中安装运行示例所需的相关 npm 文件。

查看代码

导航到 azure-iot-sdk-node/device/samples/javascript 文件夹。

azure-iot-sdk-node/device/samples/javascript 文件夹包含 IoT 即插即用温度控制器设备的示例代码。

pnp_temperature_controller.js 文件中的代码可实现 IoT 即插即用温度控制器设备。 此示例实现的模型使用多个组件温度设备的数字孪生定义语言 (DTDL) 模型文件定义了设备实现的遥测、属性和命令。

在你自己选择的代码编辑器中打开 pnp_temperature_controller.js 文件。 示例代码演示如何执行以下操作:

  • 定义 modelId,即你正在实现的设备的 DTMI。 此 DTMI 是用户定义的,必须与温度控制器 DTDL 模型的 DTMI 相匹配。

  • 实现温度控制器 DTDL 模型中定义的组件。 实际温度控制器中的组件应实现这两个接口。 这两个接口已在中央存储库中发布。 在此示例中,这两个接口为:

    • 恒温调节器
    • Azure 开发的设备信息
  • 定义组件名称。 此示例包含两个恒温器和一个设备信息组件。

  • 定义设备所响应的命令的命令名称。

  • 定义 serialNumber 常量。 serialNumber 是任何指定的固定设备。

  • 定义命令处理程序。

  • 定义用于发送命令响应的函数。

  • 定义用于记录命令请求的 helper 函数。

  • 定义用于创建属性的 helper 函数。

  • 为属性更新定义侦听器。

  • 定义一个函数,用于从此设备发送遥测数据。 恒温器和默认组件都发送遥测数据。 此函数接收组件名称作为参数。

  • 定义 main 函数:

    • 使用设备 SDK 创建设备客户端并连接到 IoT 中心。 设备提供 modelId 以便 IoT 中心可以将设备标识为 IoT 即插即用设备。

    • 使用 onDeviceMethod 函数开始侦听命令请求。 函数为来自服务的命令请求设置侦听器:

      • 设备 DTDL 定义 rebootgetMaxMinReport 命令。
      • commandHandler 函数定义设备对命令的响应方式。
    • 使用 setIntervalsendTelemetry 开始发送遥测数据。

    • 使用 helperCreateReportedPropertiesPatch 函数创建属性,并使用 updateComponentReportedProperties 来更新属性。

    • 使用 desiredPropertyPatchListener 侦听属性更新。

    • 禁用所有侦听器和任务,并在按 Q 或 q 时退出循环。

设置环境部分创建了四个环境变量来配置示例,以使用设备预配服务 (DPS) 连接到 IoT 中心:

  • 具有值 的 IOTHUB_DEVICE_SECURITY_TYPE
  • 包含 DPS ID 范围的 IOTHUB_DEVICE_DPS_ID_SCOPE。
  • 包含值 的 IOTHUB_DEVICE_DPS_DEVICE_ID。
  • 包含注册主密钥的 IOTHUB_DEVICE_DPS_DEVICE_KEY。
  • 包含值 的 IOTHUB_DEVICE_DPS_ENDPOINT。

若要详细了解示例配置,请参阅示例自述文件

看到代码后,请使用以下命令运行该示例:

node pnp_temperature_controller.js

将显示以下输出,这表明设备已开始向中心发送遥测数据,现在可以接收命令和属性更新。

设备确认消息

在执行后续步骤时,保持示例处于运行状态。

使用 Azure IoT 资源管理器验证代码

设备客户端示例启动后,使用 Azure IoT 资源管理器工具验证它是否正常工作。

  1. 打开 Azure IoT 资源管理器。

  2. 在“IoT 中心”页上,如果尚未将连接添加到 IoT 中心,请选择“+ 添加连接”。 输入先前创建的 IoT 中心的连接字符串,然后选择“保存”。

  3. 在“IoT 即插即用设置”页上,选择“+ 添加”“本地文件夹”,然后选择在其中保存了模型文件的本地“模型”文件夹。

  4. 在“IoT 中心”页上,单击要使用的中心的名称。 你将看到已注册到 IoT 中心的设备的列表。

  5. 单击前面创建的设备的“设备 ID”。

  6. 左侧菜单显示了可用于设备的不同类型的信息。

  7. 选择“IoT 即插即用组件”以查看设备的模型信息。

  8. 可以查看设备的不同组件。 默认组件和任何其他组件。 选择要使用的组件。

  9. 选择“遥测”页,然后选择“开始”,查看设备正在为此组件发送的遥测数据。

  10. 选择“属性(只读)”页以查看为此组件报告的只读属性。

  11. 选择“属性(可写)”页以查看可以为此组件更新的可写属性。

  12. 按名称选择属性,为其输入新值,然后选择“更新所需值”。

  13. 若要查看显示的新值,请选择“刷新”按钮。

  14. 选择“命令”页以查看此组件的所有命令。

  15. 选择要测试参数的命令(如果有)。 选择“发送命令”以调用设备上的命令。 可以在正在运行示例代码的命令提示符窗口中看到你的设备响应命令。

本教程介绍如何使用组件生成示例 IoT 即插即用设备应用程序,将其连接到 IoT 中心,并使用 Azure IoT 资源管理器工具来查看它发送到中心的信息。 该示例应用程序以 Python 编写,包含在用于 Python 的 Azure IoT 设备 SDK 中。 解决方案构建者可以使用 Azure IoT 资源管理器工具来了解 IoT 即插即用设备的功能,而无需查看任何设备代码。

浏览代码

本教程介绍以下操作:

  • 下载示例代码。
  • 运行该示例设备应用程序,并验证它是否会连接到 IoT 中心。
  • 检查源代码。

先决条件

请确保设置环境(包括 IoT 中心)后再继续。

可以在 Linux 或 Windows 上运行本教程。 本教程中的 shell 命令遵循适用于路径分隔符“/”的 Linux 约定,如果你是在 Windows 上操作,请务必将这些分隔符替换为“\”。

若要完成本教程,需要在开发计算机上安装 Python。 查看 Azure IoT Python SDK 以了解当前的 Python 版本要求。 可以使用以下命令检查 Python 版本:

python --version

可以从 python.org 下载适用于多个平台的最新推荐版本。

下载代码

azure-iot-device 包以 PIP 的形式发布。

在本地 Python 环境中安装该包,如下所示:

pip install azure-iot-device

如果完成教程:将 Windows 上运行的示例 IoT 即插即用设备应用程序连接到 IoT 中心 (Python),则已经克隆了该存储库。

克隆 Python SDK IoT 存储库:

git clone --branch v2 https://github.com/Azure/azure-iot-sdk-python

查看代码

此示例实现 IoT 即插即用温度控制器设备。 此示例实现的模型使用多个组件温度设备的数字孪生定义语言 (DTDL) 模型文件定义了设备实现的遥测、属性和命令。

azure-iot-sdk-python/samples/pnp 文件夹包含 IoT 即插即用设备的示例代码。 温度控制器示例的文件包括:

  • temp_controller_with_thermostats.py
  • pnp_helper.py

温度控制器基于温度控制器 DTDL 模型,具有多个组件和一个默认组件。

在所选的编辑器中打开 temp_controller_with_thermostats.py 文件。 此文件中的代码:

  1. 导入 pnp_helper.py 以获取对帮助器方法的访问权限。

  2. 定义两个数字孪生模型标识符 (DTMI),它们唯一表示 DTDL 模型中定义的两个不同接口。 实际温度控制器中的组件应实现这两个接口。 这两个接口已在中央存储库中发布。 这些 DTMI 必须为用户所知,并且根据设备实现方案而有所不同。 对于当前示例,这两个接口表示:

    • 调温器
    • Azure 开发的设备信息。
  3. 为要实现的设备定义 DTMI model_id。 DTMI 是用户定义的,必须与 DTDL 模型文件中的 DTMI 匹配。

  4. 定义为 DTDL 文件中的组件提供的名称。 DTDL 中有两个调温器和一个设备信息组件。 名为 serial_number 的常量也是在默认组件中定义。 设备的 serial_number 无法更改。

  5. 定义命令处理程序实现。 这些处理程序定义设备接收命令请求时执行哪些操作。

  6. 定义创建命令响应的函数。 这些函数定义设备如何响应命令请求。 如果命令需要将自定义响应发送回 IoT 中心,你可以创建命令响应函数。 如果未提供命令的响应函数,则发送通用响应。 在此示例中,只有 getMaxMinReport 命令具有自定义响应。

  7. 定义一个函数,用于从此设备发送遥测数据。 恒温器和默认组件都发送遥测数据。 此函数采用可选的组件名称参数,这让它能够识别哪个组件发送了遥测数据。

  8. 定义命令请求的侦听器。

  9. 定义所需属性更新的侦听器。

  10. 有一个 main 函数:

    • 使用设备 SDK 创建设备客户端并连接到 IoT 中心。 设备发送 model_id,以便 IoT 中心可以将设备标识为 IoT 即插即用设备。

    • 使用帮助器文件中的 create_reported_properties 函数创建属性。 将组件名称和属性作为键值对传递给此函数。

    • 通过调用 patch_twin_reported_properties 为其组件更新可读属性。

    • 使用 execute_command_listener 函数开始侦听命令请求。 函数为来自服务的命令请求设置侦听器。 设置侦听器时,提供 method_nameuser_command_handler 和可选的 create_user_response_handler 作为参数。

      • method_name 定义命令请求。 在此示例中,模型定义命令“reboot”和“getMaxMinReport”。
      • user_command_handler 函数定义设备在收到命令时应执行的操作。
      • 命令成功执行时,create_user_response_handler 函数将创建要发送到 IoT 中心的响应。 可以在门户中查看此响应。 如果未提供此函数,则向服务发送通用响应。
    • 使用 execute_property_listener 侦听属性更新。

    • 使用 send_telemetry 开始发送遥测数据。 示例代码使用循环来调用三个发送遥测数据的函数。 每八秒调用一次每个函数

    • 禁用所有侦听器和任务,并在按 Q 或 q 时退出循环 。

设置环境部分创建了四个环境变量来配置示例,以使用设备预配服务 (DPS) 连接到 IoT 中心:

  • 具有值 的 IOTHUB_DEVICE_SECURITY_TYPE
  • 包含 DPS ID 范围的 IOTHUB_DEVICE_DPS_ID_SCOPE。
  • 包含值 的 IOTHUB_DEVICE_DPS_DEVICE_ID。
  • 包含注册主密钥的 IOTHUB_DEVICE_DPS_DEVICE_KEY。
  • 包含值 的 IOTHUB_DEVICE_DPS_ENDPOINT。

若要详细了解示例配置,请参阅示例自述文件

使用以下命令运行示例:

python temp_controller_with_thermostats.py

示例设备每隔几秒钟向 IoT 中心发送遥测消息。

你会看到以下输出,这表明设备正在向中心发送遥测数据,现在可以接收命令和属性更新。

设备确认消息

在执行后续步骤时,保持示例处于运行状态。

使用 Azure IoT 资源管理器验证代码

设备客户端示例启动后,使用 Azure IoT 资源管理器工具验证它是否正常工作。

  1. 打开 Azure IoT 资源管理器。

  2. 在“IoT 中心”页上,如果尚未将连接添加到 IoT 中心,请选择“+ 添加连接”。 输入先前创建的 IoT 中心的连接字符串,然后选择“保存”。

  3. 在“IoT 即插即用设置”页上,选择“+ 添加”“本地文件夹”,然后选择在其中保存了模型文件的本地“模型”文件夹。

  4. 在“IoT 中心”页上,单击要使用的中心的名称。 你将看到已注册到 IoT 中心的设备的列表。

  5. 单击前面创建的设备的“设备 ID”。

  6. 左侧菜单显示了可用于设备的不同类型的信息。

  7. 选择“IoT 即插即用组件”以查看设备的模型信息。

  8. 可以查看设备的不同组件。 默认组件和任何其他组件。 选择要使用的组件。

  9. 选择“遥测”页,然后选择“开始”,查看设备正在为此组件发送的遥测数据。

  10. 选择“属性(只读)”页以查看为此组件报告的只读属性。

  11. 选择“属性(可写)”页以查看可以为此组件更新的可写属性。

  12. 按名称选择属性,为其输入新值,然后选择“更新所需值”。

  13. 若要查看显示的新值,请选择“刷新”按钮。

  14. 选择“命令”页以查看此组件的所有命令。

  15. 选择要测试参数的命令(如果有)。 选择“发送命令”以调用设备上的命令。 可以在正在运行示例代码的命令提示符窗口中看到你的设备响应命令。

清理资源

如果计划继续学习其他设备开发者文章,可保留并重复使用在本文中使用的资源。 否则,可删除在本文中创建的资源,以免产生额外费用。

可通过使用以下 Azure CLI 命令删除整个资源组来一次性删除中心和注册设备。 如果这些资源与你想要保留的其他资源共享一个资源组,则不要使用此命令。

az group delete --name <YourResourceGroupName>

若要仅删除 IoT 中心,请使用 Azure CLI 运行以下命令:

az iot hub delete --name <YourIoTHubName>

若要仅删除注册到 IoT 中心的设备标识,请使用 Azure CLI 运行以下命令:

az iot hub device-identity delete --hub-name <YourIoTHubName> --device-id <YourDeviceID>

你可能还需要从开发计算机中删除克隆的示例文件。

后续步骤

本教程已介绍如何将 IoT 即插即用设备和组件连接到 IoT 中心。 若要详细了解 IoT 即插即用设备模型,请参阅: