计划和广播作业 (Node)

Azure IoT 中心是一项完全托管的服务,允许后端应用创建和跟踪用于计划和更新数百万台设备的作业。 作业可以用于以下操作:

  • 更新所需属性
  • 更新标记
  • 调用直接方法

从概念上讲,作业包装这些操作之一,并跟踪针对一组设备执行(由设备孪生查询定义)的进度。 例如,后端应用可使用作业重启 10,000 台设备(由设备孪生查询指定并计划在将来执行)。 该应用程序随后可以在其中每个设备接收和执行重新启动方法时跟踪进度。

可在以下文章中了解有关所有这些功能的详细信息:

本教程演示如何:

  • 创建一个模拟设备应用,该应用具有可由解决方法后端调用来实现 lockDoor 的直接方法。
  • 创建一个 Node.js 控制台应用,该应用使用作业调用模拟设备应用中的 lockDoor 直接方法,并使用设备作业更新所需属性。

在本教程结束时,会创建两个 Node.js 控制台应用:

simDevice.js,它使用设备标识连接到 IoT 中心,并接收 lockDoor 直接方法。

scheduleJobService.js:调用模拟设备应用中的直接方法,并使用作业更新设备孪生的所需属性。

要完成本教程,需要具备以下先决条件:

  • Node.js 版本 0.12.x 或更高版本,
    准备开发环境介绍了如何在 Windows 或 Linux 上安装本教程所用的 Node.js。
  • 有效的 Azure 帐户。 如果没有帐户,可以创建一个试用帐户,只需几分钟即可完成。

创建 IoT 中心

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

  1. 登录到 Azure 门户
  2. 在“跳转栏”中,依次单击“新建” > “物联网” > “IoT 中心”。

    Azure 门户跳转栏

  3. 在“IoT 中心”边栏选项卡中,选择 IoT 中心的配置。

    IoT 中心边栏选项卡

    • 在“名称”框中,输入 IoT 中心的名称。 如果该“名称”有效且可用,“名称”框中会出现绿色的勾选标记。 > [!IMPORTANT] > IoT 中心将公开为 DNS 终结点,因此,命名时请务必避免包含任何敏感信息。 >
    • 选择 定价和缩放层。 本教程不需要特定的层。 对于本教程,请使用免费 F1 层。
    • 在“资源组”中,创建资源组或选择现有的资源组。 有关详细信息,请参阅使用资源组管理 Azure 资源
    • 在“位置”中,选择托管 IoT 中心的位置。 对于本教程,请选择最近位置。
  4. 选择 IoT 中心配置选项后,单击“创建”。 Azure 可能需要几分钟时间来创建 IoT 中心。 若要检查状态,可以在“启动板”或“通知”面板中监视进度。

    新的 IoT 中心状态

  5. 成功创建 IoT 中心后,请在 Azure 门户中单击 IoT 中心对应的新磁贴,以打开新 IoT 中心的边栏选项卡。 记下“主机名”,并单击“共享访问策略”。

    新的 IoT 中心边栏选项卡

  6. 在“共享访问策略”边栏选项卡中,单击“iothubowner”策略,并复制并记下“iothubowner”边栏选项卡中的 IoT 中心连接字符串。 有关详细信息,请参阅“IoT 中心开发人员指南”中的访问控制

    共享访问策略边栏选项卡

创建设备标识

本部分使用名为 iothub-explorer 的 Node.js 工具为本教程创建设备标识。 设备 ID 区分大小写。

  1. 在命令行环境中运行以下命令:

    npm install -g iothub-explorer@latest

  2. 然后,运行以下命令登录到中心。 将 {iot hub connection string} 替换为前面复制的 IoT 中心连接字符串:

    iothub-explorer login "{iot hub connection string}"

  3. 最后,以下使用命令创建名为 myDeviceId 的新设备标识:

    iothub-explorer create myDeviceId --connection-string

    Important

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

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

若要以编程方式创建设备标识,请参阅 IoT 中心入门

创建模拟设备应用程序

在本部分中,创建响应云调用的直接方法的 Node.js 控制台应用,这会触发模拟的设备重新启动并使用报告属性启用设备孪生查询,以标识设备和及其上次重新启动的时间。

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

    npm init
    
  2. simDevice 文件夹的命令提示符处,运行下述命令以安装 azure-iot-device 设备 SDK 包和 azure-iot-device-mqtt 包:

    npm install azure-iot-device azure-iot-device-mqtt --save
    
  3. simDevice.js 文件夹中,利用文本编辑器创建新的 simDevice 文件。
  4. simDevice.js 文件的开头添加以下“require”语句:

    'use strict';
    
    var Client = require('azure-iot-device').Client;
    var Protocol = require('azure-iot-device-mqtt').Mqtt;
    
  5. 添加 connectionString 变量,并使用它创建一个客户端实例。

    var connectionString = 'HostName={youriothostname};DeviceId={yourdeviceid};SharedAccessKey={yourdevicekey}';
    var client = Client.fromConnectionString(connectionString, Protocol);
    
  6. 添加以下函数以处理 lockDoor 方法。

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

    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 文件。

Note

为简单起见,本教程不实现任何重试策略。 在生产代码中,应该按 MSDN 文章 Transient Fault Handling(暂时性故障处理)中所述实施重试策略(例如指数性的回退)。

安排作业,用于调用直接方法和更新设备孪生的属性

在此部分中,会创建一个 Node.js 控制台应用,它使用直接方法对设备启动远程 lockDoor 并更新设备孪生的属性。

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

    npm init
    
  2. 在 scheduleJobService 文件夹的命令提示符处,运行以下命令安装 azure-iothub 设备 SDK 包和 azure-iot-device-mqtt 包:

    npm install azure-iothub uuid --save
    
  3. scheduleJobService 文件夹中,利用文本编辑器创建新的 scheduleJobService.js 文件。
  4. dmpatterns_gscheduleJobServiceetstarted_service.js 文件开头添加以下“require”语句:

    'use strict';
    
    var uuid = require('uuid');
    var JobClient = require('azure-iothub').JobClient;
    
  5. 添加以下变量声明并替换占位符值:

    var connectionString = '{iothubconnectionstring}';
    var queryCondition = "deviceId IN ['myDeviceId']";
    var startTime = new Date();
    var maxExecutionTimeInSeconds =  3600;
    var jobClient = JobClient.fromConnectionString(connectionString);
    
  6. 添加用于监视作业执行的以下函数:

    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. 添加以下代码以安排调用设备方法的作业:

    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. 添加以下代码以安排更新设备孪生的作业:

    var twinPatch = {
        etag: '*',
        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 文件。

运行应用程序

现在,已准备就绪,可以运行应用程序了。

  1. 在 simDevice 文件夹的命令提示符处,运行以下命令以开始侦听重启直接方法。

    node simDevice.js
    
  2. scheduleJobService 文件夹的命令提示符处运行以下命令,以便触发作业进行锁门和孪生项的更新

    node scheduleJobService.js
    
  3. 可以在控制台中看到设备对直接方法的响应。

后续步骤

在本教程中,使用了作业来安排用于设备的直接方法以及设备孪生属性的更新。

若要继续完成 IoT 中心和设备管理模式(如远程无线固件更新)的入门内容,请参阅:

教程:如何进行固件更新

若要继续完成 IoT 中心入门内容,请参阅 Azure IoT Edge 入门