デバイス管理の開始 (Node.js)

バックエンド アプリでは、Azure IoT Hub プリミティブ (デバイス ツインダイレクト メソッドなど) を使用して、デバイス上のデバイス管理アクションをリモートで開始および監視できます。 この記事では、バックエンド アプリとデバイス アプリをどのように連携させると、IoT Hub を使用してデバイスの再起動をリモートで開始して監視できるかについて示します。

Note

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

ダイレクト メソッドを使用して、クラウド内のバックエンド アプリケーションからデバイス管理操作 (再起動、出荷時の設定に戻す、ファームウェアの更新など) を開始します。 デバイスは次の操作を担当します。

  • IoT Hub から送信されたメソッド要求の処理。

  • デバイスでの対応するデバイス固有の操作の開始。

  • "報告されるプロパティ" を介した IoT Hub への状態更新の提供。

クラウドでバックエンド アプリを使用してデバイス ツインのクエリを実行することで、デバイス管理操作の進行状況を報告できます。

この記事では、次のものを作成する方法について説明します。

  • dmpatterns_getstarted_device.js: デバイスを再起動し、最後の再起動時刻を報告するダイレクト メソッドを含むシミュレートされたデバイス アプリ。 ダイレクト メソッドは、クラウドから呼び出されます。

  • dmpatterns_getstarted_service.js: シミュレートされたデバイス アプリのダイレクト メソッドを IoT Hub から呼び出す .NET コンソール アプリ。 応答と更新されて報告されたプロパティを表示します。

前提条件

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

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

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

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

ダイレクト メソッドを使用してデバイス アプリを作成する

このセクションでは、次の作業を行います。

  • クラウドによって呼び出されたダイレクト メソッドに応答する Node.js コンソール アプリを作成します。

  • シミュレート対象デバイスの再起動をトリガーします。

  • 報告されたプロパティを使用して、デバイス ツイン クエリで、デバイスと、それらが最後に再起動された時間を特定できるようにします。

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

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

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

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

    'use strict';
    
    var Client = require('azure-iot-device').Client;
    var Protocol = require('azure-iot-device-mqtt').Mqtt;
    
  5. connectionString 変数を追加し、それを使用して Client インスタンスを作成します。 {yourdeviceconnectionstring} プレースホルダーの値を、IoT Hub でデバイスを登録した時に表示されたデバイス接続文字列に置き換えます。

    var connectionString = '{yourdeviceconnectionstring}';
    var client = Client.fromConnectionString(connectionString, Protocol);
    
  6. デバイスにダイレクト メソッドを実装する次の関数を追加します。

    var onReboot = function(request, response) {
    
        // Respond the cloud app for the direct method
        response.send(200, 'Reboot started', 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.');
            }
        });
    
        // Report the reboot before the physical restart
        var date = new Date();
        var patch = {
            iothubDM : {
                reboot : {
                    lastReboot : date.toISOString(),
                }
            }
        };
    
        // Get device Twin
        client.getTwin(function(err, twin) {
            if (err) {
                console.error('could not get twin');
            } else {
                console.log('twin acquired');
                twin.properties.reported.update(patch, function(err) {
                    if (err) throw err;
                    console.log('Device reboot twin state reported')
                });  
            }
        });
    
        // Add your device's reboot API for physical restart.
        console.log('Rebooting!');
    };
    
  7. IoT Hub への接続を開き、ダイレクト メソッド リスナーを開始します。

    client.open(function(err) {
        if (err) {
            console.error('Could not open IotHub client');
        }  else {
            console.log('Client opened.  Waiting for reboot method.');
            client.onDeviceMethod('reboot', onReboot);
        }
    });
    
  8. dmpatterns_getstarted_device.js ファイルを保存して閉じます。

Note

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

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

この記事では、デバイス上で直接メソッドを呼び出すバックエンド サービスを作成します。 IoT Hub を介してデバイス上で直接メソッドを呼び出すには、サービスにサービス接続アクセス許可が必要です。 既定では、どの IoT Hub も、このアクセス許可を付与する service という名前の共有アクセス ポリシーがある状態で作成されます。

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

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

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

  3. ポリシーの一覧から、サービス ポリシーを選択します。

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

Azure portal で IoT ハブから接続文字列を取得する方法を示すスクリーンショット。

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

再起動をトリガーするサービス アプリを作成する

このセクションでは、ダイレクト メソッドを使用してデバイスでのリモート再起動を開始する Node.js コンソール アプリケーションを作成します。 このアプリは、デバイス ツイン クエリを使用して、そのデバイスの前回の再起動時刻を検出します。

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

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

    npm install azure-iothub --save
    
  3. テキスト エディターを使用して、trigger-reboot-on-device フォルダー内に dmpatterns_getstarted_service.js ファイルを作成します。

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

    'use strict';
    
    var Registry = require('azure-iothub').Registry;
    var Client = require('azure-iothub').Client;
    
  5. 次の変数宣言を追加し、{iothubconnectionstring} プレースホルダーの値を、先ほど「IoT ハブ接続文字列を取得する」でコピーしておいた IoT Hub 接続文字列に置き換えます。

    var connectionString = '{iothubconnectionstring}';
    var registry = Registry.fromConnectionString(connectionString);
    var client = Client.fromConnectionString(connectionString);
    var deviceToReboot = 'myDeviceId';
    
  6. ターゲット デバイスを再起動するダイレクトメソッドを呼び出す次の関数を追加します。

    var startRebootDevice = function(twin) {
    
        var methodName = "reboot";
    
        var methodParams = {
            methodName: methodName,
            payload: null,
            timeoutInSeconds: 30
        };
    
        client.invokeDeviceMethod(deviceToReboot, methodParams, function(err, result) {
            if (err) {
                console.error("Direct method error: "+err.message);
            } else {
                console.log("Successfully invoked the device to reboot.");  
            }
        });
    };
    
  7. デバイスを照会して最後の再起動時間を取得する次の関数を追加します。

    var queryTwinLastReboot = function() {
    
        registry.getTwin(deviceToReboot, function(err, twin){
    
            if (twin.properties.reported.iothubDM != null)
            {
                if (err) {
                    console.error('Could not query twins: ' + err.constructor.name + ': ' + err.message);
                } else {
                    var lastRebootTime = twin.properties.reported.iothubDM.reboot.lastReboot;
                    console.log('Last reboot time: ' + JSON.stringify(lastRebootTime, null, 2));
                }
            } else 
                console.log('Waiting for device to report last reboot time.');
        });
    };
    
  8. 再起動ダイレクト メソッドをトリガーする関数と最後の再起動時間のクエリを実行する関数を呼び出す次のコードを追加します。

    startRebootDevice();
    setInterval(queryTwinLastReboot, 2000);
    
  9. dmpatterns_getstarted_service.js ファイルを保存して閉じます。

アプリの実行

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

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

    node dmpatterns_getstarted_device.js
    
  2. コマンド プロンプトで、trigger-reboot-on-device フォルダーに移動し、次のコマンドを実行してデバイス ツインのリモート再起動とクエリをトリガーして最後の再起動時刻を検索します。

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

    サービスによって送信された再起動ダイレクト メソッドに対するデバイスの応答を次に示します。

    manageddevice アプリの出力

    再起動をトリガーしてデバイス ツインの前回の再起動時刻をポーリングするサービスを次に示します。

    triggerrebootondevice アプリの出力

デバイス管理操作のカスタマイズと拡張を行う

IoT ソリューションでは、定義された一連のデバイス管理パターンを拡張したり、デバイス ツインと cloud-to-device メソッド プリミティブを使用してカスタム パターンを作成したりできます。 デバイス管理操作の他の例には、出荷時の設定への復帰、ファームウェアの更新、ソフトウェアの更新、電源管理、ネットワークと接続の管理、データの暗号化などがあります。

デバイスのメンテナンス期間

通常、デバイスは、中断やダウンタイムを最小限に抑えることができる時間に操作を実行するように構成します。 デバイスのメンテナンス期間は、デバイスがその構成を更新する必要がある時間を定義する一般的に使用されるパターンです。 バックエンド ソリューションは、デバイス ツインの必要なプロパティを使用して、メンテナンス期間を可能にするデバイスのポリシーを定義してアクティブにすることができます。 デバイスは、メンテナンス期間ポリシーを受信したときに、デバイス ツインの報告されたプロパティを使用してポリシーの状態を報告することができます。 その後、バックエンド アプリケーションは、デバイス ツインのクエリを使用して、デバイスが各ポリシーに対応していることを確認できます。

次のステップ

この記事では、ダイレクト メソッドを使用して、デバイスのリモート再起動をトリガーしました。 報告されるプロパティを使用してデバイスの最後の再起動時間を報告し、デバイス ツインのクエリを実行してクラウドからデバイスの最後の再起動時間を検出しました。

Raspberry Pi 3 B+ 参照イメージを使用した Azure IoT Hub のデバイス アップデートのアーティクル」でエンドツーエンドのイメージベースの更新など、IoT Hub とデバイス管理パターンの使用を続けます。

IoT ソリューションの拡張と複数のデバイスでのメソッドの呼び出しをスケジュールする方法については、ジョブのスケジュールとブロードキャストに関するページを参照してください。