设备孪生入门 (Node)

设备孪生是存储设备状态信息(元数据、配置和条件)的 JSON 文档。 IoT 中心为连接到它的每台设备保留一个设备孪生。

Note

本文中所述的功能仅可在 IoT 中心的标准层中使用。 有关基本和标准 IoT 中心层的详细信息,请参阅如何选择合适的 IoT 中心层

使用设备孪生可以:

  • 存储来自解决方案后端的设备元数据。
  • 通过设备应用报告当前状态信息,例如可用功能和条件(例如,使用的连接方法)。
  • 同步设备应用和后端应用之间的长时间运行的工作流的状态(例如固件和配置更新)。
  • 查询设备的元数据、配置或状态。

设备孪生旨在执行同步以及查询设备的配置和条件。 了解设备孪生中提供了有关何时使用设备孪生的详细信息。

设备孪生存储在 IoT 中心内,其中包含:

  • 标记,仅可由解决方案后端访问的设备元数据;
  • 所需属性,可以由解决方案后端修改以及由设备应用观察的 JSON 对象;以及
  • 报告属性,可由设备应用修改以及由解决方案后端读取的 JSON 对象。 标记和属性不能包含数组,但可以嵌套对象。

此外,解决方案后端可以根据上述所有数据查询设备孪生。 有关设备孪生的详细信息,请参阅了解设备孪生,有关查询的参考,请参阅 IoT 中心查询语言

本教程演示如何:

  • 创建将标记添加到设备孪生的后端应用,以及将其连接通道作为设备孪生上的报告属性进行报告的模拟设备应用。
  • 使用标记上的筛选器和之前创建的属性通过后端应用查询设备。

在本教程结束时,你将拥有两个 Node.js 控制台应用:

  • AddTagsAndQuery.js(Node.js 后端应用),用于添加标记和查询设备孪生。
  • TwinSimulatedDevice.js(Node.js 应用),用于模拟使用早先创建的设备标识连接到 IoT 中心的设备,并报告其连接状况。

Note

Azure IoT SDK 文章介绍了可用于构建设备和后端应用的 Azure IoT SDK。

若要完成本教程,需要满足以下条件:

  • Node.js 版本 4.0.x 或更高版本。

  • 有效的 Azure 帐户。(如果没有帐户,只需花费几分钟就能创建一个帐户。)

创建 IoT 中心

创建模拟设备应用要连接到的 IoT 中心。 以下步骤说明如何使用 Azure 门户来完成此任务。

  1. 登录到 Azure 门户

  2. 选择“创建资源” > “物联网” > “IoT 中心”。

    Azure 门户跳转栏

  3. 在“IoT 中心”窗格中,输入 IoT 中心的以下信息:

    • 订阅:选择需要将其用于创建此 IoT 中心的订阅。

    • 资源组:创建用于托管 IoT 中心的资源组,或使用现有的资源组。 有关详细信息,请参阅使用资源组管理 Azure 资源

    • 区域:选择最近的位置。

    • 名称:创建 IoT 中心的名称。 如果输入的名称可用,会显示一个绿色复选标记。

    Important

    IoT 中心将公开为 DNS 终结点,因此,命名时请务必避免包含任何敏感信息。

    IoT 中心基本信息窗口

  4. 选择“下一步: 大小和规模”,以便继续创建 IoT 中心。

  5. 选择“定价和缩放层”。 就本文来说,请选择“F1 - 免费”层(前提是此层在订阅上仍然可用)。 有关详细信息,请参阅定价和缩放层

    IoT 中心大小和规模窗口

  6. 选择“查看 + 创建”。

  7. 查看 IoT 中心信息,然后单击“创建”。 创建 IoT 中心可能需要数分钟的时间。 可在“通知”窗格中监视进度。

  8. 新的 IoT 中心就绪以后,请在 Azure 门户中单击其磁贴,打开其属性窗口。 创建 IoT 中心以后,即可找到将设备和应用程序连接到 IoT 中心时需要使用的重要信息。 单击“共享访问策略”。

  9. 在“共享访问策略”中,选择 iothubowner 策略。 复制 IoT 中心连接字符串 ---主密钥供以后使用。 有关详细信息,请参阅“IoT 中心开发人员指南”中的访问控制

    共享访问策略

创建设备标识

在本部分中,将使用 Azure CLI 为本教程创建设备标识。设备 ID 区分大小写。

  1. 在使用 Azure CLI 安装 IoT 扩展的命令行环境中运行以下命令:

    az extension add --name azure-cli-iot-ext
    
  2. 如果要在本地运行 Azure CLI,请使用以下命令登录 Azure 帐户(如果使用的是 Cloud Shell,则表示你已自动登录,并且无需运行此命令):

    az login
    
  3. 最后,使用以下命令创建一个名为 myDeviceId 的新设备标识并检索设备连接字符串:

    az iot hub device-identity create --device-id myDeviceId --hub-name {Your IoT Hub name}
    az iot hub device-identity show-connection-string --device-id myDeviceId --hub-name {Your IoT Hub name} -o table
    

    Important

    收集的日志中可能会显示设备 ID 用于客户支持和故障排除,因此,在为日志命名时,请务必避免包含任何敏感信息。

记下结果中的设备连接字符串。 设备应用使用此设备连接字符串以设备身份连接到 IoT 中心。

创建服务应用

在本部分中,将创建一个 Node.js 控制台应用,该应用将位置元数据添加到与 myDeviceId 关联的设备孪生。 然后,该应用将选择位于中国的设备来查询存储在 IoT 中心的设备孪生,然后查询报告移动电话网络连接的设备孪生。

  1. 新建名为 addtagsandqueryapp 的空文件夹。在命令提示符下的 addtagsandqueryapp 文件夹中,使用以下命令创建新的 package.json 文件。接受所有默认值:

    npm init
    
  2. addtagsandqueryapp 文件夹的命令提示符下,运行以下命令以安装 azure-iothub 包:

    npm install azure-iothub --save
    
  3. 使用文本编辑器,在 addtagsandqueryapp 文件夹中创建一个新的 AddTagsAndQuery.js 文件。
  4. 将以下代码添加到 AddTagsAndQuery.js 文件,并将 {iot hub connection string} 占位符替换为创建中心时复制的 IoT 中心连接字符串:

    '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: 'CN',
                        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();
              }
            });
        }
    });
    

    Registry 对象公开从服务与设备孪生进行交互所需的所有方法。 前面的代码首先初始化 Registry 对象,然后检索 myDeviceId 的设备孪生,最后使用所需位置信息更新其标记。

    更新标记后,它将调用 queryTwins 函数。

  5. 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 工厂中的设备的设备孪生,第二个会优化查询以只选择还通过手机网络连接的设备。

    上面的代码创建 query 对象时,会指定返回的最大文档数。 query 对象包含 hasMoreResults 布尔值属性,可以使用它多次调用 nextAsTwin 方法来检索所有结果。 名为 next 的方法可用于非设备孪生的结果(例如聚合查询的结果)。

  6. 使用以下内容运行应用程序:

    node AddTagsAndQuery.js
    

    在查询位于 Redmond43 的所有设备的查询结果中,应该会看到一个设备,而在将结果限制为使用蜂窝网络的设备的查询结果中没有任何设备。

在下一部分中,创建的设备应用会报告连接信息,并更改上一部分中查询的结果。

创建设备应用

在此部分,会创建一个 Node.js 控制台应用作为 myDeviceId连接到中心,并更新其设备孪生的报告属性,说明它是使用手机网络进行连接的。

  1. 新建名为 reportconnectivity 的空文件夹。在 reportconnectivity 文件夹的命令提示符处,使用以下命令创建新的 package.json 文件。接受所有默认值:

    npm init
    
  2. reportconnectivity 文件夹中,在命令提示符下运行以下命令以安装 azure-iot-device 包和 azure-iot-device-mqtt 包:

    npm install azure-iot-device azure-iot-device-mqtt --save
    
  3. 使用文本编辑器,在 reportconnectivity 文件夹中创建一个新的 ReportConnectivity.js 文件。
  4. 将以下代码添加到 ReportConnectivity.js 文件,并将 {device connection string} 占位符替换为创建 myDeviceId 设备标识时复制的设备连接字符串:

    '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 的设备孪生,并使用连接信息更新其报告属性。

  5. 运行设备应用

    node ReportConnectivity.js
    

    此时会显示消息twin state reported

  6. 现在设备报告了其连接信息,应出现在两个查询中。 返回到 addtagsandqueryapp 文件夹,再次运行查询:

    node AddTagsAndQuery.js
    

    这次 myDeviceId 应出现在两个查询结果中。

后续步骤

本教程中,在 Azure 门户中配置了新的 IoT 中心,并在 IoT 中心的标识注册表中创建了设备标识。 已从后端应用以标记形式添加了设备元数据,并编写了模拟的设备应用,用于报告设备孪生中的设备连接信息。 还学习了如何使用类似 SQL 的 IoT 中心查询语言来查询此信息。

充分利用以下资源: