计划和广播作业 (Node.js)Schedule and broadcast jobs (Node.js)

Azure IoT 中心是一项完全托管的服务,允许后端应用创建和跟踪用于计划和更新数百万台设备的作业。Azure IoT Hub is a fully managed service that enables a back-end app to create and track jobs that schedule and update millions of devices. 作业可以用于以下操作:Jobs can be used for the following actions:

  • 更新所需属性Update desired properties
  • 更新标记Update tags
  • 调用直接方法Invoke direct methods

从概念上讲,作业包装这些操作之一,并跟踪针对一组设备执行(由设备孪生查询定义)的进度。Conceptually, a job wraps one of these actions and tracks the progress of execution against a set of devices, which is defined by a device twin query. 例如,后端应用可使用作业重启 10,000 台设备(由设备孪生查询指定并计划在将来执行)。For example, a back-end app can use a job to invoke a reboot method on 10,000 devices, specified by a device twin query and scheduled at a future time. 该应用程序随后可以在其中每个设备接收和执行重新启动方法时跟踪进度。That application can then track progress as each of those devices receive and execute the reboot method.

可在以下文章中了解有关所有这些功能的详细信息:Learn more about each of these capabilities in these articles:

Note

本文介绍的功能仅在 IoT 中心的标准层中可用。The features described in this article are available only in the standard tier of IoT Hub. 有关基本和标准/免费 IoT 中心层的详细信息,请参阅选择合适的 IoT 中心层For more information about the basic and standard/free IoT Hub tiers, see Choose the right IoT Hub tier.

本教程演示如何:This tutorial shows you how to:

  • 创建一个具有直接方法的 Node.js 模拟设备应用,启用可由解决方案后端进行调用的 lockDoor 。Create a Node.js simulated device app that has a direct method, which enables lockDoor, which can be called by the solution back end.
  • 创建一个 Node.js 控制台应用,该应用使用作业调用模拟设备应用中的 lockDoor 直接方法,并使用设备作业更新所需属性。Create a Node.js console app that calls the lockDoor direct method in the simulated device app using a job and updates the desired properties using a device job.

在本教程结束时,会创建两个 Node.js 应用:At the end of this tutorial, you have two Node.js apps:

simDevice.js,它使用设备标识连接到 IoT 中心,并接收 lockDoor 直接方法。simDevice.js, which connects to your IoT hub with the device identity and receives a lockDoor direct method.

scheduleJobService.js,它调用模拟设备应用中的直接方法,并通过作业更新设备孪生的所需属性 。scheduleJobService.js, which calls a direct method in the simulated device app and updates the device twin's desired properties using a job.

先决条件Prerequisites

  • Node.js 版本 10.0.x 或更高版本。Node.js version 10.0.x or later. 准备开发环境介绍了如何在 Windows 或 Linux 上安装本教程所用的 Node.js。Prepare your development environment describes how to install Node.js for this tutorial on either Windows or Linux.

  • 有效的 Azure 帐户。An active Azure account. (如果没有帐户,只需几分钟即可创建一个试用帐户。)(If you don't have an account, you can create a trial account in just a couple of minutes.)

  • 确保已在防火墙中打开端口 8883。Make sure that port 8883 is open in your firewall. 本文中的设备示例使用 MQTT 协议,该协议通过端口 8883 进行通信。The device sample in this article uses MQTT protocol, which communicates over port 8883. 在某些公司和教育网络环境中,此端口可能被阻止。This port may be blocked in some corporate and educational network environments. 有关解决此问题的更多信息和方法,请参阅连接到 IoT 中心(MQTT)For more information and ways to work around this issue, see Connecting to IoT Hub (MQTT).

创建 IoT 中心Create an IoT hub

此部分介绍如何使用 Azure 门户创建 IoT 中心。This section describes how to create an IoT hub using the Azure portal.

  1. 登录到 Azure 门户Sign in to the Azure portal.

  2. 从 Azure 主页中选择“+ 创建资源”按钮,然后在“搜索市场”字段中输入“IoT 中心”。 From the Azure homepage, select the + Create a resource button, and then enter IoT Hub in the Search the Marketplace field.

  3. 在搜索结果中选择“IoT 中心”,然后选择“创建” 。Select IoT Hub from the search results, and then select Create.

  4. 在“基本信息”选项卡上,按如下所示填写字段: On the Basics tab, complete the fields as follows:

    • 订阅:选择要用于中心的订阅。Subscription: Select the subscription to use for your hub.

    • 资源组:选择一个资源组或新建一个资源组。Resource Group: Select a resource group or create a new one. 若要新建资源组,请选择“新建”并填写要使用的名称。 To create a new one, select Create new and fill in the name you want to use. 若要使用现有的资源组,请选择它。To use an existing resource group, select that resource group. 有关详细信息,请参阅管理 Azure 资源管理器资源组For more information, see Manage Azure Resource Manager resource groups.

    • 区域:选择中心所在的区域。Region: Select the region in which you want your hub to be located. 选择最靠近你的位置。Select the location closest to you.

    • IoT 中心名称:输入中心的名称。IoT Hub Name: Enter a name for your hub. 此名称必须全局唯一。This name must be globally unique. 如果输入的名称可用,会显示一个绿色复选标记。If the name you enter is available, a green check mark appears.

    Important

    IoT 中心将公开为 DNS 终结点,因此,命名时请务必避免包含任何敏感信息。The IoT hub will be publicly discoverable as a DNS endpoint, so make sure to avoid any sensitive information while naming it.

    在 Azure 门户中创建中心

  5. 在完成时选择“下一步: 大小和规模”,以继续创建中心。Select Next: Size and scale to continue creating your hub.

    使用 Azure 门户为新的中心设置大小和规模

    在此屏幕中可以设置以下值:This screen allows you to set the following values:

    • 定价和缩放层:选择的层。Pricing and scale tier: Your selected tier. 可以根据你需要的功能数以及每天通过解决方案发送的消息数从多个层级中进行选择。You can choose from several tiers, depending on how many features you want and how many messages you send through your solution per day. 免费层适用于测试和评估。The free tier is intended for testing and evaluation. 允许 500 台设备连接到中心,每天最多可传输 8,000 条消息。It allows 500 devices to be connected to the hub and up to 8,000 messages per day. 每个 Azure 订阅可以在免费层中创建一个 IoT 中心。Each Azure subscription can create one IoT Hub in the free tier.

    • IoT 中心单元:每个单位每日允许的消息数取决于中心的定价层。IoT Hub units: The number of messages allowed per unit per day depends on your hub's pricing tier. 例如,如果希望中心支持 700,000 条消息引入,请选择两个 S1 层单位。For example, if you want the hub to support ingress of 700,000 messages, you choose two S1 tier units. 有关其他层选项的详细信息,请参阅选择合适的 IoT 中心层For details about the other tier options, see Choosing the right IoT Hub tier.

    • 高级设置 > 设备到云的分区:此属性将设备到云消息与这些消息的同步读取器数目相关联。Advanced Settings > Device-to-cloud partitions: This property relates the device-to-cloud messages to the number of simultaneous readers of the messages. 大多数中心只需要 4 个分区。Most hubs need only four partitions.

  6. 对于本文,请接受默认选项,然后选择“查看 + 创建”以查看所做的选择。 For this article, accept the default choices, and then select Review + create to review your choices. 会显示类似于以下的屏幕。You see something similar to this screen.

    查看用于创建新中心的信息

  7. 选择“创建”以创建新的中心 。Select Create to create your new hub. 创建中心需要几分钟时间。Creating the hub takes a few minutes.

在 IoT 中心内注册新设备Register a new device in the IoT hub

在本部分中,将使用 Azure CLI 为本文创建设备标识。In this section, you use the Azure CLI to create a device identity for this article. 设备 ID 区分大小写。Device IDs are case sensitive.

  1. 运行以下命令以安装适用于 Azure CLI 的 Microsoft Azure IoT 扩展:Run the following command to install the Microsoft Azure IoT Extension for Azure CLI:

    az extension add --name azure-cli-iot-ext
    
  2. 使用以下命令创建一个名为 myDeviceId 的新设备标识并检索设备连接字符串:Create a new device identity called myDeviceId and retrieve the device connection string with these commands:

    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 用于客户支持和故障排除,因此,在为日志命名时,请务必避免包含任何敏感信息。The device ID may be visible in the logs collected for customer support and troubleshooting, so make sure to avoid any sensitive information while naming it.

记下结果中的设备连接字符串。Make a note of the device connection string from the result. 设备应用使用此设备连接字符串以设备身份连接到 IoT 中心。This device connection string is used by the device app to connect to your IoT Hub as a device.

创建模拟设备应用程序Create a simulated device app

本部分将创建一个 Node.js 控制台应用,用于响应通过云调用的方法,这会触发模拟 lockDoor 方法 。In this section, you create a Node.js console app that responds to a direct method called by the cloud, which triggers a simulated lockDoor method.

  1. 新建名为 simDevice的空文件夹。Create a new empty folder called simDevice. simDevice 文件夹的命令提示符处,使用以下命令创建 package.json 文件。In the simDevice folder, create a package.json file using the following command at your command prompt. 接受所有默认值:Accept all the defaults:

    npm init
    
  2. simDevice 文件夹的命令提示符处,运行下述命令以安装 azure-iot-device 设备 SDK 包和 azure-iot-device-mqtt 包:At your command prompt in the simDevice folder, run the following command to install the azure-iot-device Device SDK package and azure-iot-device-mqtt package:

    npm install azure-iot-device azure-iot-device-mqtt --save
    
  3. simDevice.js 文件夹中,利用文本编辑器创建新的 simDevice 文件。Using a text editor, create a new simDevice.js file in the simDevice folder.

  4. simDevice.js 文件的开头添加以下“require”语句:Add the following 'require' statements at the start of the simDevice.js file:

    'use strict';
    
    var Client = require('azure-iot-device').Client;
    var Protocol = require('azure-iot-device-mqtt').Mqtt;
    
  5. 添加 connectionString 变量,并使用它创建一个客户端实例。Add a connectionString variable and use it to create a Client instance. {yourDeviceConnectionString} 占位符值替换为之前复制的设备连接字符串。Replace the {yourDeviceConnectionString} placeholder value with the device connection string you copied previously.

    var connectionString = '{yourDeviceConnectionString}';
    var client = Client.fromConnectionString(connectionString, Protocol);
    
  6. 添加以下函数以处理 lockDoor 方法。Add the following function to handle the lockDoor method.

    var onLockDoor = function(request, response) {
    
        // Respond the cloud app for the direct method
        response.send(200, function(err) {
            if (err) {
                console.error('An error occurred when sending a method response:\n' + err.toString());
            } else {
                console.log('Response to method \'' + request.methodName + '\' sent successfully.');
            }
        });
    
        console.log('Locking Door!');
    };
    
  7. 添加以下代码以注册 lockDoor 方法的处理程序。Add the following code to register the handler for the lockDoor method.

    client.open(function(err) {
         if (err) {
             console.error('Could not connect to IotHub client.');
         }  else {
             console.log('Client connected to IoT Hub. Register handler for lockDoor direct method.');
             client.onDeviceMethod('lockDoor', onLockDoor);
         }
    });
    
  8. 保存并关闭 simDevice.js 文件。Save and close the simDevice.js file.

Note

为简单起见,本教程不实现任何重试策略。To keep things simple, this tutorial does not implement any retry policy. 在生产代码中,应该按文章 Transient Fault Handling(暂时性故障处理)中所述实施重试策略(例如指数性的回退)。In production code, you should implement retry policies (such as an exponential backoff), as suggested in the article, Transient Fault Handling.

获取 IoT 中心连接字符串Get the IoT hub connection string

在本文中,将创建一个后端服务,该服务调度作业以对设备调用直接方法,调度作业以更新设备孪生,并监视每个作业的进度。In this article, you create a backend service that schedules a job to invoke a direct method on a device, schedules a job to update the device twin, and monitors the progress of each job. 若要执行这些操作,你的服务需要“注册表读取” 和“注册表写入” 权限。To perform these operations, your service needs the registry read and registry write permissions. 默认情况下,每个 IoT 中心都使用名为 registryReadWrite 的共享访问策略创建,该策略授予这些权限。By default, every IoT Hub is created with a shared access policy named registryReadWrite that grants these permissions.

若要获取 registryReadWrite 策略的 IoT 中心连接字符串,请执行以下步骤:To get the IoT Hub connection string for the registryReadWrite policy, follow these steps:

  1. Azure 门户中,选择“资源组” 。In the Azure portal, select Resource groups. 选择中心所在的资源组,然后从资源列表中选择中心。Select the resource group where your hub is located, and then select your hub from the list of resources.

  2. 在中心的左侧窗格中,选择“共享访问策略” 。On the left-side pane of your hub, select Shared access policies.

  3. 从策略列表中选择“registryReadWrite” 策略。From the list of policies, select the registryReadWrite policy.

  4. 在“共享访问密钥” 下,选择“连接字符串 - 主密钥” 所对应的“复制”图标并保存该值。Under Shared access keys, select the copy icon for the Connection string -- primary key and save the value.

    显示如何检索连接字符串

有关 IoT 中心共享访问策略和权限的详细信息,请参阅访问控制和权限For more information about IoT Hub shared access policies and permissions, see Access control and permissions.

安排作业,用于调用直接方法和更新设备孪生的属性Schedule jobs for calling a direct method and updating a device twin's properties

在此部分中,会创建一个 Node.js 控制台应用,它使用直接方法对设备启动远程 lockDoor 并更新设备孪生的属性。In this section, you create a Node.js console app that initiates a remote lockDoor on a device using a direct method and update the device twin's properties.

  1. 新建名为 scheduleJobService的空文件夹。Create a new empty folder called scheduleJobService. scheduleJobService 文件夹的命令提示符处,使用以下命令创建 package.json 文件。In the scheduleJobService folder, create a package.json file using the following command at your command prompt. 接受所有默认值:Accept all the defaults:

    npm init
    
  2. 在 scheduleJobService 文件夹的命令提示符处,运行以下命令安装 azure-iothub 设备 SDK 包和 azure-iot-device-mqtt 包:At your command prompt in the scheduleJobService folder, run the following command to install the azure-iothub Device SDK package and azure-iot-device-mqtt package:

    npm install azure-iothub uuid --save
    
  3. scheduleJobService 文件夹中,利用文本编辑器创建新的 scheduleJobService.js 文件。Using a text editor, create a new scheduleJobService.js file in the scheduleJobService folder.

  4. scheduleJobService.js 文件的开头添加以下“require”语句:Add the following 'require' statements at the start of the scheduleJobService.js file:

    'use strict';
    
    var uuid = require('uuid');
    var JobClient = require('azure-iothub').JobClient;
    
  5. 添加以下变量声明。Add the following variable declarations. {iothubconnectionstring} 占位符值替换为在获取 IoT 中心连接字符串中复制的值。Replace the {iothubconnectionstring} placeholder value with the value you copied in Get the IoT hub connection string. 如果你注册的设备不是 myDeviceId,请确保在查询条件中对其进行更改。If you registered a device different than myDeviceId, be sure to change it in the query condition.

    var connectionString = '{iothubconnectionstring}';
    var queryCondition = "deviceId IN ['myDeviceId']";
    var startTime = new Date();
    var maxExecutionTimeInSeconds =  300;
    var jobClient = JobClient.fromConnectionString(connectionString);
    
  6. 添加以下用于监视作业执行的函数:Add the following function that is used to monitor the execution of the job:

    function monitorJob (jobId, callback) {
        var jobMonitorInterval = setInterval(function() {
            jobClient.getJob(jobId, function(err, result) {
            if (err) {
                console.error('Could not get job status: ' + err.message);
            } else {
                console.log('Job: ' + jobId + ' - status: ' + result.status);
                if (result.status === 'completed' || result.status === 'failed' || result.status === 'cancelled') {
                clearInterval(jobMonitorInterval);
                callback(null, result);
                }
            }
            });
        }, 5000);
    }
    
  7. 添加以下代码以安排调用设备方法的作业:Add the following code to schedule the job that calls the device method:

    var methodParams = {
        methodName: 'lockDoor',
        payload: null,
        responseTimeoutInSeconds: 15 // Timeout after 15 seconds if device is unable to process method
    };
    
    var methodJobId = uuid.v4();
    console.log('scheduling Device Method job with id: ' + methodJobId);
    jobClient.scheduleDeviceMethod(methodJobId,
                                queryCondition,
                                methodParams,
                                startTime,
                                maxExecutionTimeInSeconds,
                                function(err) {
        if (err) {
            console.error('Could not schedule device method job: ' + err.message);
        } else {
            monitorJob(methodJobId, function(err, result) {
                if (err) {
                    console.error('Could not monitor device method job: ' + err.message);
                } else {
                    console.log(JSON.stringify(result, null, 2));
                }
            });
        }
    });
    
  8. 添加以下代码以安排更新设备孪生的作业:Add the following code to schedule the job to update the device twin:

    var twinPatch = {
       etag: '*', 
       properties: {
           desired: {
               building: '43', 
               floor: 3
           }
       }
    };
    
    var twinJobId = uuid.v4();
    
    console.log('scheduling Twin Update job with id: ' + twinJobId);
    jobClient.scheduleTwinUpdate(twinJobId,
                                queryCondition,
                                twinPatch,
                                startTime,
                                maxExecutionTimeInSeconds,
                                function(err) {
        if (err) {
            console.error('Could not schedule twin update job: ' + err.message);
        } else {
            monitorJob(twinJobId, function(err, result) {
                if (err) {
                    console.error('Could not monitor twin update job: ' + err.message);
                } else {
                    console.log(JSON.stringify(result, null, 2));
                }
            });
        }
    });
    
  9. 保存并关闭 scheduleJobService.js 文件。Save and close the scheduleJobService.js file.

运行应用程序Run the applications

现在,已准备就绪,可以运行应用程序了。You are now ready to run the applications.

  1. 在 simDevice 文件夹的命令提示符处,运行以下命令以开始侦听重启直接方法。At the command prompt in the simDevice folder, run the following command to begin listening for the reboot direct method.

    node simDevice.js
    
  2. scheduleJobService 文件夹的命令提示符处运行以下命令,以便触发作业进行锁门和孪生项的更新At the command prompt in the scheduleJobService folder, run the following command to trigger the jobs to lock the door and update the twin

    node scheduleJobService.js
    
  3. 可以在控制台中看到设备对直接方法的响应和作业状态。You see the device response to the direct method and the job status in the console.

    下面显示了设备对直接方法的响应:The following shows the device response to the direct method:

    模拟设备应用输出

    下面显示了直接方法和设备孪生更新的服务计划作业,以及运行至完成的作业:The following shows the service scheduling jobs for the direct method and device twin update, and the jobs running to completion:

    运行模拟设备应用

后续步骤Next steps

在本教程中,使用了作业来安排用于设备的直接方法以及设备孪生属性的更新。In this tutorial, you used a job to schedule a direct method to a device and the update of the device twin's properties.

若要继续完成 IoT 中心和设备管理模式(如远程无线固件更新)的入门内容,请参阅教程:如何执行固件更新To continue getting started with IoT Hub and device management patterns such as remote over the air firmware update, see Tutorial: How to do a firmware update.

若要继续完成 IoT 中心入门内容,请参阅 Azure IoT Edge 入门To continue getting started with IoT Hub, see Getting started with Azure IoT Edge.