设备孪生是存储设备状态信息的 JSON 文档,包括元数据、配置和条件。 IoT 中心为连接到它的每台设备保留设备孪生。
注释
本文中所述的功能仅在 IoT 中心的标准层中可用。 有关基本层和标准/免费 IoT 中心层的详细信息,请参阅 为解决方案选择正确的 IoT 中心层和大小。
使用设备孪生可以:
从解决方案后端存储设备元数据。
报告当前状态信息,例如可用功能和条件,例如设备应用中使用的连接方法。
在设备应用和后端应用之间同步长时间运行的工作流的状态,例如固件和配置更新。
查询设备元数据、配置或状态。
设备孪生专为同步和查询设备配置和条件而设计。 有关设备孪生的详细信息,包括何时使用设备孪生,请参阅 了解设备孪生。
IoT 中心存储设备孪生体,其中包含以下元素:
标记。 设备元数据只能由解决方案后端访问。
所需属性。 解决方案后端可修改的 JSON 对象,并且设备应用程序可对其进行观察。
报告的属性。 设备应用可修改的 JSON 对象,解决方案后端可读。
标记和属性不能包含数组,但可以包含嵌套对象。
下图显示了设备孪生结构:
此外,解决方案后端可以根据上述所有数据查询设备孪生。 有关设备孪生的详细信息,请参阅 了解设备孪生。 有关查询的详细信息,请参阅 IoT 中心查询语言。
在本文中,你将创建两个 Node.js 控制台应用:
AddTagsAndQuery.js:添加标记和查询设备孪生的后端应用。
TwinSimulatedDevice.js:一个连接到 IoT 中心的模拟设备应用,并报告其连接条件。
注释
有关可用于生成设备和后端应用的 SDK 工具的详细信息,请参阅 Azure IoT SDK 。
先决条件
若要完成本文,需要做好以下准备:
已注册的设备。 在 Azure 门户中注册一个。
Node.js 版本 10.0.x 或更高版本。
确保已在防火墙中打开端口 8883。 本文中的设备示例使用通过端口 8883 进行通信的 MQTT 协议。 某些企业和教育网络环境中可能会阻止此端口。 有关解决此问题的详细信息和方法,请参阅“连接到 IoT 中心”(MQTT)。
获取 IoT 中心连接字符串
在本文中,你将创建一个后端服务,该服务将所需属性添加到设备孪生,然后查询标识注册表以查找报告的属性已相应地更新的所有设备。 服务需要 服务连接 权限来修改设备孪生的所需属性,并且需要 注册表读取 权限才能查询标识注册表。 没有仅包含这两个权限的默认共享访问策略,因此需要创建一个。
若要创建一个共享访问策略,用于授予 服务连接 和 注册表读取 权限并获取此策略的连接字符串,请执行以下步骤:
在 Azure 门户中,选择 资源组。 选择中心所在的资源组,然后从资源列表中选择中心。
在中心的左侧窗格中,选择 “共享访问策略”。
从策略列表上方的顶部菜单中,选择 “添加共享策略访问策略”。
在右侧的 “添加共享访问策略 ”窗格中,输入策略的描述性名称,例如 serviceAndRegistryRead。 在“权限”下,选择“注册表读取”和服务连接,然后选择“添加”。
从策略列表中选择新策略。
选择 主连接字符串 的复制图标并保存值。
有关 IoT 中心共享访问策略和权限的详细信息,请参阅 访问控制和权限。
创建更新报告属性的设备应用
在本部分中,将创建一个 Node.js 控制台应用,该应用以 myDeviceId 身份连接到中心,然后更新其设备孪生的报告属性,以确认它已使用手机网络进行连接。
创建名为 reportconnectivity 的新空文件夹。 在 reportconnectivity 文件夹中,在命令提示符处使用以下命令创建新的 package.json 文件。 该
--yes参数接受所有默认值。npm init --yes在 reportconnectivity 文件夹中的命令提示符处运行以下命令,安装 azure-iot-device 和 azure-iot-device-mqtt 包:
npm install azure-iot-device azure-iot-device-mqtt --save使用文本编辑器,在 reportconnectivity 文件夹中创建新的 ReportConnectivity.js 文件。
将以下代码添加到 ReportConnectivity.js 文件。 替换为
{device connection string}在 IoT 中心注册设备时看到的设备连接字符串:'use strict'; var Client = require('azure-iot-device').Client; var Protocol = require('azure-iot-device-mqtt').Mqtt; var connectionString = '{device connection string}'; var client = Client.fromConnectionString(connectionString, Protocol); client.open(function(err) { if (err) { console.error('could not open IotHub client'); } else { console.log('client opened'); client.getTwin(function(err, twin) { if (err) { console.error('could not get twin'); } else { var patch = { connectivity: { type: 'cellular' } }; twin.properties.reported.update(patch, function(err) { if (err) { console.error('could not update twin'); } else { console.log('twin state reported'); process.exit(); } }); } }); } });Client 对象公开了从设备与设备孪生交互所需的所有方法。 在初始化 Client 对象后,前面的代码检索 myDeviceId 的设备孪生,并使用连接信息更新其报告的属性。
运行设备应用
node ReportConnectivity.js应该看到消息
twin state reported。设备报告其连接信息后,它应出现在这两个查询中。 返回 addtagsandqueryapp 文件夹中,然后再次运行查询:
node AddTagsAndQuery.js这一次 myDeviceId 应出现在两个查询结果中。
创建用于更新所需属性和查询孪生的服务应用
在本部分中,你将创建一个 Node.js 控制台应用,用于将位置元数据添加到与 myDeviceId 关联的设备孪生。 该应用查询 IoT 中心以查找位于美国的设备,然后查询报告手机网络连接的设备。
创建名为 addtagsandqueryapp 的新空文件夹。 在 addtagsandqueryapp 文件夹中,在命令提示符处使用以下命令创建新的 package.json 文件。 该
--yes参数接受所有默认值。npm init --yes在 addtagsandqueryapp 文件夹中的命令提示符处运行以下命令以安装 azure-iothub 包:
npm install azure-iothub --save使用文本编辑器,在 addtagsandqueryapp 文件夹中创建新的 AddTagsAndQuery.js 文件。
将以下代码添加到 AddTagsAndQuery.js 文件。 用在获取 IoT 中心连接字符串中复制的 IoT 中心连接字符串替换
{iot hub connection string}。'use strict'; var iothub = require('azure-iothub'); var connectionString = '{iot hub connection string}'; var registry = iothub.Registry.fromConnectionString(connectionString); registry.getTwin('myDeviceId', function(err, twin){ if (err) { console.error(err.constructor.name + ': ' + err.message); } else { var patch = { tags: { location: { region: 'US', plant: 'Redmond43' } } }; twin.update(patch, function(err) { if (err) { console.error('Could not update twin: ' + err.constructor.name + ': ' + err.message); } else { console.log(twin.deviceId + ' twin updated successfully'); queryTwins(); } }); } });注册表对象公开了与服务中的设备孪生交互所需的所有方法。 前面的代码首先初始化 注册表 对象,然后检索 myDeviceId 的设备孪生,最后使用所需的位置信息更新其标记。
更新标记后,它会调用 queryTwins 函数。
在 AddTagsAndQuery.js 末尾添加以下代码以实现 queryTwins 函数:
var queryTwins = function() { var query = registry.createQuery("SELECT * FROM devices WHERE tags.location.plant = 'Redmond43'", 100); query.nextAsTwin(function(err, results) { if (err) { console.error('Failed to fetch the results: ' + err.message); } else { console.log("Devices in Redmond43: " + results.map(function(twin) {return twin.deviceId}).join(',')); } }); query = registry.createQuery("SELECT * FROM devices WHERE tags.location.plant = 'Redmond43' AND properties.reported.connectivity.type = 'cellular'", 100); query.nextAsTwin(function(err, results) { if (err) { console.error('Failed to fetch the results: ' + err.message); } else { console.log("Devices in Redmond43 using cellular network: " + results.map(function(twin) {return twin.deviceId}).join(',')); } }); };前面的代码执行两个查询:第一个查询仅选择 位于 Redmond43 工厂的设备的设备孪生,第二个代码将优化查询以仅选择通过手机网络连接的设备。
当代码创建 查询 对象时,它会指定第二个参数中返回的文档的最大数目。 查询对象包含 hasMoreResults 布尔属性,可用于多次调用 nextAsTwin 方法来检索所有结果。 名为next的方法可用于不是设备孪生的结果,例如聚合查询的结果。
使用以下命令运行应用程序:
node AddTagsAndQuery.js应该会在查询结果中看到一个设备,询问 位于 Redmond43 中的所有设备,对于将结果限制为使用手机网络的设备的查询,不应看到任何设备。
本文内容:
- 从后端应用添加设备元数据作为标记
- 设备孪生中报告的设备连接信息
- 使用类似于 SQL 的 IoT 中心查询语言查询设备孪生信息
后续步骤
若要了解如何操作:
从设备发送遥测数据,请参阅 快速入门:将遥测数据从 IoT 即插即用设备发送到 Azure IoT 中心
使用设备孪生的期望属性来配置设备,具体操作,请参阅教程:从后端服务配置设备。
以交互方式控制设备,例如从用户控制的应用中打开风扇,请参阅 快速入门:控制连接到 IoT 中心的设备