ジョブのスケジュールとブロードキャスト (Node.js)

Azure IoT Hub を使用して、数百万のデバイスを更新するジョブのスケジュールと追跡を行います。 ジョブを使用して、次の操作を行います。

  • 必要なプロパティを更新する
  • タグを更新する
  • ダイレクト メソッドを呼び出す

概念的には、ジョブはこれらのアクションのいずれかをラップし、デバイス ツイン クエリで定義される一連のデバイスに対して実行の進行状況を追跡します。 たとえば、バックエンド アプリでは、ジョブを使用して、10,000 台のデバイスに対して reboot メソッドを呼び出すことができます。これは、デバイス ツイン クエリで指定され、将来の時刻にスケジュールされます。 次に、このアプリケーションを使って、これらの各デバイスが reboot メソッドを受信し実行する進行状況を追跡できます。

これらの各機能について詳しくは、次の記事をご覧ください。

Note

この記事で説明されている機能は、Standard レベルの IoT Hub でのみ使用できます。 Basic および Standard または Free レベルの IoT Hub の詳細については、「ソリューションに適した IoT Hub のレベルを選択する」を参照してください。

この記事では、2 つの Node.js アプリを作成する方法について説明します。

  • バックエンド アプリから呼び出すことができる lockDoor というダイレクト メソッドを実装する Node.js のシミュレートされたデバイス アプリ simDevice.js

  • 2 つのジョブを作成する Node.js コンソール アプリ scheduleJobService.js。 1 つのジョブが lockDoor ダイレクト メソッドを呼び出し、別のジョブが必要なプロパティの更新を複数のデバイスに送信します。

注意

デバイスとバックエンド アプリの両方の構築に使用できる SDK ツールに関する詳細については、「Azure IoT Hub SDK」を参照してください。

前提条件

  • IoT Hub。 CLI または Azure portal を使って作成します。

  • 登録済みのデバイス。 Azure portal に登録してください。

  • Node.js バージョン 10.0.x 以降。 開発環境を準備するでは、このアーティクルのために Node.js を Windows または Linux にインストールする方法が説明されています。

  • ポート 8883 がファイアウォールで開放されていることを確認してください。 この記事のデバイス サンプルでは、ポート 8883 を介して通信する MQTT プロトコルを使用しています。 このポートは、企業や教育用のネットワーク環境によってはブロックされている場合があります。 この問題の詳細と対処方法については、「IoT Hub への接続 (MQTT)」を参照してください。

シミュレート対象デバイス アプリの作成

このセクションでは、クラウドによって呼び出されたダイレクト メソッドに応答する Node.js コンソール アプリを作成します。このアプリはシミュレートされた lockDoor メソッドをトリガーします。

  1. simDevice という名前の新しい空のフォルダーを作成します。 コマンド プロンプトで次のコマンドを使用して、simDevice フォルダー内に新しい package.json ファイルを作成します。 次の既定値をすべてそのまま使用します。

    npm init
    
  2. コマンド プロンプトで、simDevice フォルダーに移動し、次のコマンドを実行して、azure-iot-device Device SDK パッケージと azure-iot-device-mqtt パッケージをインストールします。

    npm install azure-iot-device azure-iot-device-mqtt --save
    
  3. テキスト エディターを使用して、simDevice フォルダーに新しい simDevice.js ファイルを作成します。

  4. simDevice.js ファイルの先頭に、次の 'require' ステートメントを追加します。

    'use strict';
    
    var Client = require('azure-iot-device').Client;
    var Protocol = require('azure-iot-device-mqtt').Mqtt;
    
  5. connectionString 変数を追加し、それを使用して Client インスタンスを作成します。 {yourDeviceConnectionString} プレースホルダーの値は、前にコピーしたデバイス接続文字列に置き換えてください。

    var connectionString = '{yourDeviceConnectionString}';
    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 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 メソッドのハンドラーを登録する次のコードを追加します。

    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

わかりやすくするために、この記事では再試行ポリシーは実装しません。 運用環境のコードでは、「一時的な障害の処理」の記事で推奨されているように、再試行ポリシー (指数関数的バックオフなど) を実装することをお勧めします。

IoT ハブ接続文字列を取得する

この記事では、デバイス上で直接メソッドを呼び出すようにジョブをスケジュールし、デバイス ツインを更新するようにジョブをスケジュールし、各ジョブの進行状況を監視するバックエンド サービスを作成します。 これらの操作を実行するには、サービスにレジストリ読み取りおよびレジストリ書き込みのアクセス許可が必要です。 既定では、すべての IoT ハブは、これらのアクセス許可を付与する registryReadWrite という名前の共有アクセス ポリシーがある状態で作成されます。

registryReadWrite ポリシーの IoT Hub 接続文字列を取得するには、次の手順を実行します。

  1. Azure portal で、 [リソース グループ] を選択します。 ハブが配置されているリソース グループを選択し、リソースの一覧からハブを選択します。

  2. ハブの左側のウィンドウで、 [共有アクセス ポリシー] を選択します。

  3. ポリシーの一覧から、 [registryReadWrite] ポリシーを選択します。

  4. [プライマリ接続文字列] をコピーし、値を保存します。

    接続文字列を取得する方法を示すスクリーン キャプチャ

IoT Hub の共有アクセス ポリシーとアクセス許可の詳細については、「アクセス制御とアクセス許可」を参照してください。

ダイレクト メソッドを呼び出し、デバイス ツインのプロパティを更新するジョブのスケジュール

このセクションでは、ダイレクト メソッドを使用してデバイスでリモート lockDoor を開始する Node.js コンソール アプリを作成し、デバイス ツインのプロパティを更新します。

  1. scheduleJobService という名前の新しい空のフォルダーを作成します。 コマンド プロンプトで次のコマンドを使用して、scheduleJobService フォルダー内に新しい package.json ファイルを作成します。 次の既定値をすべてそのまま使用します。

    npm init
    
  2. コマンド プロンプトで、scheduleJobService フォルダーに移動し、次のコマンドを実行して、azure-iothub Device SDK パッケージと azure-iot-device-mqtt パッケージをインストールします。

    npm install azure-iothub uuid --save
    
  3. テキスト エディターを使用して、scheduleJobService フォルダーに新しい scheduleJobService.js ファイルを作成します。

  4. scheduleJobService.js ファイルの先頭に、次の "require" ステートメントを追加します。

    'use strict';
    
    var uuid = require('uuid');
    var JobClient = require('azure-iothub').JobClient;
    
  5. 次の変数宣言を追加します。 {iothubconnectionstring} プレースホルダーの値を、先ほど「{iothubconnectionstring}」でコピーしておいた値に置き換えます。 myDeviceId とは異なるデバイスを登録した場合は、クエリ条件内の値を変更してください。

    var connectionString = '{iothubconnectionstring}';
    var queryCondition = "deviceId IN ['myDeviceId']";
    var startTime = new Date();
    var maxExecutionTimeInSeconds =  300;
    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: '*',
       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 ファイルを保存して閉じます。

アプリケーションの実行

これで、アプリケーションを実行する準備が整いました。

  1. コマンド プロンプトで、simDevice フォルダーに移動し、次のコマンドを実行して再起動のダイレクト メソッドのリッスンを開始します。

    node simDevice.js
    
  2. コマンド プロンプトで、scheduleJobService フォルダーに移動し、次のコマンドを実行して、ドアをロックしてツインを更新するジョブをトリガーします。

    node scheduleJobService.js
    
  3. ダイレクト メソッドに対するデバイスの応答とジョブの状態がコンソールに表示されます。

    ダイレクト メソッドに対するデバイスの応答を次に示します。

    シミュレートされたデバイス アプリの出力

    ダイレクト メソッドとデバイス ツインの更新に対するサービス スケジュール ジョブと、実行中のジョブ、および完了したジョブを次に示します。

    シミュレーション済みデバイス アプリを実行する

次の手順

この記事では、ダイレクト メソッドを実行してデバイス ツインのプロパティを更新するようにジョブをスケジュールしました。

IoT Hub とデバイス管理パターンの調査を続けるには、「Raspberry Pi 3 B+ 参照イメージを使用した Device Update for Azure IoT Hub のチュートリアル」でイメージを更新してください。