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

IoT 中心模块标识和模块孪生 (Node.js) 入门

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

注意

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

在本文结束时,你会获得两个 Node.js 应用:

  • CreateIdentities:创建设备标识、模块标识和相关的安全密钥,以连接设备和模块客户端。

  • UpdateModuleTwinReportedProperties:将更新的模块孪生、报告属性发送到 IoT 中心。

注意

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

先决条件

  • 一个 IoT 中心。 使用 CLIAzure 门户创建一个。

  • Node.js 版本 10.0.x 或更高版本。 准备开发环境介绍了如何在 Windows 或 Linux 上安装本文所用的 Node.js。

模块身份验证

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

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

获取 IoT 中心连接字符串

在本文中,将创建一个后端服务,该服务在标识注册表中添加一个设备,然后向该设备添加一个模块。 你的服务需要“注册表写入”权限。 默认情况下,每个 IoT 中心都使用名为 registryReadWrite 的共享访问策略创建,该策略授予此权限。

若要获取 registryReadWrite策略的 IoT 中心连接字符串,请执行以下步骤:

  1. Azure 门户中,选择“资源组”。 选择中心所在的资源组,然后从资源列表中选择中心。

  2. 在中心的左侧窗格上,选择“共享访问策略”。

  3. 在策略列表中,选择“registryReadWrite”策略。

  4. 复制“主连接字符串”并保存该值。

    显示如何检索连接字符串的屏幕截图

有关 IoT 中心共享访问策略和权限的详细信息,请参阅访问控制和权限

在 IoT 中心中创建设备标识和模块标识

本部分将创建一个 Node.js 应用,用于在 IoT 中心的标识注册表中创建设备标识和模块标识。 设备或模块无法连接到 IoT 中心,除非它在标识注册表中具有条目。 有关详细信息,请参阅了解 IoT 中心的标识注册表。 运行此控制台应用时,它会为设备和模块生成唯一的 ID 和密钥。 ID 和密钥区分大小写。 设备和模块在向 IoT 中心发送设备到云的消息时,使用这些值来标识自身。

  1. 创建目录以保存代码。

  2. 在该目录中,首先运行 npm init -y 使用默认值创建一个空的 package.json 。 这是代码的项目文件。

  3. 运行 npm install -S azure-iothub@modules-preview,以在 node_modules 子目录中安装服务 SDK。

    注意

    子目录名称 node_modules 使用字模块来表示“节点库”。 此处的术语与 IoT 中心模块无关。

  4. 在目录中创建以下 .js 文件。 将它命名为 add.js 。 复制并粘贴中心连接字符串和中心名称。

    var Registry = require('azure-iothub').Registry;
    var uuid = require('uuid');
    // Copy/paste your connection string and hub name here
    var serviceConnectionString = '<hub connection string from portal>';
    var hubName = '<hub name>.azure-devices.net';
    // Create an instance of the IoTHub registry
    var registry = Registry.fromConnectionString(serviceConnectionString);
    // Insert your device ID and moduleId here.
    var deviceId = 'myFirstDevice';
    var moduleId = 'myFirstModule';
    // Create your device as a SAS authentication device
    var primaryKey = new Buffer(uuid.v4()).toString('base64');
    var secondaryKey = new Buffer(uuid.v4()).toString('base64');
    var deviceDescription = {
      deviceId: deviceId,
      status: 'enabled',
      authentication: {
        type: 'sas',
        symmetricKey: {
          primaryKey: primaryKey,
          secondaryKey: secondaryKey
        }
      }
    };
    
    // First, create a device identity
    registry.create(deviceDescription, function(err) {
      if (err) {
        console.log('Error creating device identity: ' + err);
        process.exit(1);
      }
      console.log('device connection string = "HostName=' + hubName + ';DeviceId=' + deviceId + ';SharedAccessKey=' + primaryKey + '"');
    
      // Then add a module to that device
      registry.addModule({ deviceId: deviceId, moduleId: moduleId }, function(err) {
        if (err) {
          console.log('Error creating module identity: ' + err);
          process.exit(1);
        }
    
        // Finally, retrieve the module details from the hub so we can construct the connection string
        registry.getModule(deviceId, moduleId, function(err, foundModule) {
          if (err) {
            console.log('Error getting module back from hub: ' + err);
            process.exit(1);
          }
          console.log('module connection string = "HostName=' + hubName + ';DeviceId=' + foundModule.deviceId + ';ModuleId='+foundModule.moduleId+';SharedAccessKey=' + foundModule.authentication.symmetricKey.primaryKey + '"');
          process.exit(0);
        });
      });
    });
    
    

此应用在设备“myFirstDevice”下创建 ID 为“myFirstDevice”的设备标识,以及 ID 为“myFirstModule”的模块标识 。 (如果该模块 ID 已在标识注册表中,代码就只检索现有的模块信息。)然后,应用程序会显示该标识的主密钥。 在模拟模块应用中使用此密钥连接到 IoT 中心。

使用节点 add.js 运行它。 它将为设备标识提供一个连接字符串,并为模块标识提供另一个连接字符串。

注意

IoT 中心标识注册表只存储设备和模块标识,以启用对 IoT 中心的安全访问。 标识注册表存储用作安全凭据的设备 ID 和密钥。 标识注册表还为每个设备存储启用/禁用标志,该标志可以用于禁用对该设备的访问。 如果应用程序需要存储其他特定于设备的元数据,则应使用特定于应用程序的存储。 没有针对模块标识的“已启用/已禁用”标记。 有关详细信息,请参阅IoT 中心开发人员指南中的了解 IoT 中心的标识注册表

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

在本节中,将在更新模块孪生报告属性的模拟设备上创建 Node.js 应用。

  1. 获取模块连接字符串。 登录 Azure 门户。 导航到 IoT 中心并选择“IoT 设备”。 查找并打开 myFirstDevice,可以看到 myFirstModule 已成功创建。 复制模块连接字符串。 下一步将需要它。

    Azure 门户模块详细信息

  2. 与上面步骤中的操作类似,为设备代码创建一个目录,使用 NPM 对它进行初始化并安装设备 SDK (npm install -S azure-iot-device-amqp@modules-preview)。

    注意

    npm install 命令可能有点慢。 请耐心等待,它正在从包存储库中提取大量代码。

    注意

    如果看到错误 npm ERR! 分析 json 时出现注册表错误,可以安全忽略。 如果看到错误 npm ERR! 分析 json 时出现注册表错误,可以安全忽略。

  3. 创建名为 twin.js 的文件。 复制并粘贴模块标识字符串。

    var Client = require('azure-iot-device').Client;
    var Protocol = require('azure-iot-device-amqp').Amqp;
    // Copy/paste your module connection string here.
    var connectionString = '<insert module connection string here>';
    // Create a client using the Amqp protocol.
    var client = Client.fromConnectionString(connectionString, Protocol);
    client.on('error', function (err) {
      console.error(err.message);
    });
    // connect to the hub
    client.open(function(err) {
      if (err) {
        console.error('error connecting to hub: ' + err);
        process.exit(1);
      }
      console.log('client opened');
    // Create device Twin
      client.getTwin(function(err, twin) {
        if (err) {
          console.error('error getting twin: ' + err);
          process.exit(1);
        }
        // Output the current properties
        console.log('twin contents:');
        console.log(twin.properties);
        // Add a handler for desired property changes
        twin.on('properties.desired', function(delta) {
            console.log('new desired properties received:');
            console.log(JSON.stringify(delta));
        });
        // create a patch to send to the hub
        var patch = {
          updateTime: new Date().toString(),
          firmwareVersion:'1.2.1',
          weather:{
            temperature: 72,
            humidity: 17
          }
        };
        // send the patch
        twin.properties.reported.update(patch, function(err) {
          if (err) throw err;
          console.log('twin state reported');
        });
      });
    });
    
  4. 现在请使用命令 node twin.js 来运行它

    F:\temp\module_twin>node twin.js
    

    然后,你将看到:

    client opened
    twin contents:
    { reported: { update: [Function: update], '$version': 1 },
      desired: { '$version': 1 } }
    new desired properties received:
    {"$version":1}
    twin state reported
    

后续步骤

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