デバイス管理の開始 (Python)

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

Note

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

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

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

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

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

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

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

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

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

注意

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

前提条件

  • アクティブな Azure アカウントアカウントがない場合、Azure 試用版にサインアップして、最大 10 件の無料 Mobile Apps を入手できます。 (アカウントがない場合は、無料アカウント を数分で作成できます)。

  • Azure サブスクリプション内の IoT ハブ。 ハブがまだない場合は、「IoT ハブの作成」の手順に従うことができます。

  • お使いの IoT ハブに登録されているデバイス。 IoT ハブにデバイスがない場合は、「デバイスを登録する」の手順に従います。

  • Python バージョン 3.7 以降をお勧めします。 必ず、セットアップに必要な 32 ビットまたは 64 ビットのインストールを使用してください。 インストール中に求められた場合は、プラットフォーム固有の環境変数に Python を追加します。

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

IoT ハブに新しいデバイスを登録する

このセクションでは、Azure CLI を使用して、この記事用のデバイス ID を作成します。 デバイス ID には大文字と小文字の区別があります。

  1. Azure Cloud Shell を開きます。

  2. Azure Cloud Shell で次のコマンドを実行して、Microsoft Azure IoT Extension for Azure CLI をインストールします。

    az extension add --name azure-iot
    
  3. 次のコマンドを実行して、myDeviceId という新しいデバイス ID を作成し、デバイス接続文字列を取得します。

    az iot hub device-identity create --device-id myDeviceId --hub-name {Your IoT Hub name} --resource-group {Resource group of the Hub}
    az iot hub device-identity connection-string show --device-id myDeviceId --hub-name {Your IoT Hub name} --resource-group {Resource group of the Hub} -o table
    

    重要

    デバイス ID は、カスタマー サポートとトラブルシューティング目的で収集されたログに表示される場合があります。そのため、名前を付ける際は機密情報を含めないようにしてください。

結果として得られたデバイスの接続文字列をメモしておきます。 このデバイス接続文字列は、デバイス アプリからデバイスとして IoT Hub に接続する際に使用します。

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

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

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

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

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

以前に使用した Azure Cloud Shell、または Python を使用した他の環境で、デバイス コードを作成します。

  1. コマンド プロンプトで次のコマンドを実行して azure-iot-device パッケージをインストールします。

    pip install azure-iot-device
    
  2. テキスト エディターを使用して、dmpatterns_getstarted_device.py というファイルを作業ディレクトリに作成します。

  3. dmpatterns_getstarted_device.py ファイルの先頭に、次の import ステートメントを追加します。

    import time
    import datetime
    from azure.iot.device import IoTHubDeviceClient, MethodResponse
    
  4. CONNECTION_STRING 変数を追加します。 {deviceConnectionString} プレースホルダーの値をデバイスの接続文字列に置き換えます。 この接続文字列は、先ほど「IoT ハブに新しいデバイスを登録する」でコピーしたものです。

    CONNECTION_STRING = "{deviceConnectionString}"
    
  5. 次の関数を追加して、デバイスでダイレクト メソッド用に構成されたクライアントのインスタンスを作成します。

    def create_client():
        # Instantiate the client
        client = IoTHubDeviceClient.create_from_connection_string(CONNECTION_STRING)
    
        # Define the handler for method requests
        def method_request_handler(method_request):
            if method_request.name == "rebootDevice":
                # Act on the method by rebooting the device
                print("Rebooting device")
                time.sleep(20)
                print("Device rebooted")
    
                # ...and patching the reported properties
                current_time = str(datetime.datetime.now())
                reported_props = {"rebootTime": current_time}
                client.patch_twin_reported_properties(reported_props)
                print( "Device twins updated with latest rebootTime")
    
                # Create a method response indicating the method request was resolved
                resp_status = 200
                resp_payload = {"Response": "This is the response from the device"}
                method_response = MethodResponse(method_request.request_id, resp_status, resp_payload)
    
            else:
                # Create a method response indicating the method request was for an unknown method
                resp_status = 404
                resp_payload = {"Response": "Unknown method"}
                method_response = MethodResponse(method_request.request_id, resp_status, resp_payload)
    
            # Send the method response
            client.send_method_response(method_response)
    
        try:
            # Attach the handler to the client
            client.on_method_request_received = method_request_handler
        except:
            # In the event of failure, clean up
            client.shutdown()
    
        return client
    
  6. ダイレクト メソッドのサンプルを開始し、待機します。

    def main():
        print ("Starting the IoT Hub Python sample...")
        client = create_client()
    
        print ("Waiting for commands, press Ctrl-C to exit")
        try:
            # Wait for program exit
            while True:
                time.sleep(1000)
        except KeyboardInterrupt:
            print("IoTHubDeviceClient sample stopped")
        finally:
            # Graceful exit
            print("Shutting down IoT Hub Client")
            client.shutdown()
    
    if __name__ == '__main__':
        main()
    
  7. dmpatterns_getstarted_device.py ファイルを保存して閉じます。

Note

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

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

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

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

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

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

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

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

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

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

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

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

Azure Cloud Shell または Python を使用した他の環境で、コンソール コードを作成します。

  1. コマンド プロンプトで次のコマンドを実行して azure-iot-hub パッケージをインストールします。

    pip install azure-iot-hub
    
  2. テキスト エディターを使用して、dmpatterns_getstarted_service.py というファイルを作業ディレクトリに作成します。

  3. dmpatterns_getstarted_service.py ファイルの先頭に、次の import ステートメントを追加します。

    import sys, time
    
    from azure.iot.hub import IoTHubRegistryManager
    from azure.iot.hub.models import CloudToDeviceMethod, CloudToDeviceMethodResult, Twin
    
  4. 次の変数宣言を追加します。 {IoTHubConnectionString} プレースホルダーの値を、先ほど「IoT ハブ接続文字列を取得する」でコピーしておいた IoT ハブ接続文字列に置き換えます。 {deviceId} プレースホルダーの値を、「IoT ハブに新しいデバイスを登録する」で登録したデバイス ID に置き換えます。

    CONNECTION_STRING = "{IoTHubConnectionString}"
    DEVICE_ID = "{deviceId}"
    
    METHOD_NAME = "rebootDevice"
    METHOD_PAYLOAD = "{\"method_number\":\"42\"}"
    TIMEOUT = 60
    WAIT_COUNT = 10
    
  5. 次の関数を追加して、ターゲット デバイスを再起動するためのデバイス メソッドを起動した後、デバイス ツインを照会し、前回の再起動時刻を取得します。

    def iothub_devicemethod_sample_run():
        try:
            # Create IoTHubRegistryManager
            registry_manager = IoTHubRegistryManager(CONNECTION_STRING)
    
            print ( "" )
            print ( "Invoking device to reboot..." )
    
            # Call the direct method.
            deviceMethod = CloudToDeviceMethod(method_name=METHOD_NAME, payload=METHOD_PAYLOAD)
            response = registry_manager.invoke_device_method(DEVICE_ID, deviceMethod)
    
            print ( "" )
            print ( "Successfully invoked the device to reboot." )
    
            print ( "" )
            print ( response.payload )
    
            while True:
                print ( "" )
                print ( "IoTHubClient waiting for commands, press Ctrl-C to exit" )
    
                status_counter = 0
                while status_counter <= WAIT_COUNT:
                    twin_info = registry_manager.get_twin(DEVICE_ID)
    
                    if twin_info.properties.reported.get("rebootTime") != None :
                        print ("Last reboot time: " + twin_info.properties.reported.get("rebootTime"))
                    else:
                        print ("Waiting for device to report last reboot time...")
    
                    time.sleep(5)
                    status_counter += 1
    
        except Exception as ex:
            print ( "" )
            print ( "Unexpected error {0}".format(ex) )
            return
        except KeyboardInterrupt:
            print ( "" )
            print ( "IoTHubDeviceMethod sample stopped" )
    
    if __name__ == '__main__':
        print ( "Starting the IoT Hub Service Client DeviceManagement Python sample..." )
        print ( "    Connection string = {0}".format(CONNECTION_STRING) )
        print ( "    Device ID         = {0}".format(DEVICE_ID) )
    
        iothub_devicemethod_sample_run()
    
  6. dmpatterns_getstarted_service.py ファイルを保存して閉じます。

アプリの実行

これで、デバイス コードと、デバイスの再起動を開始するサービス コードを実行する準備ができました。

  1. デバイスを作成したコマンド プロンプトで、次のコマンドを実行して再起動のダイレクト メソッドのリッスンを開始します。

    python dmpatterns_getstarted_device.py
    
  2. サービスを作成したコマンド プロンプトで、次のコマンドを実行してデバイス ツインのリモート再起動とクエリをトリガーして最後の再起動時刻を検索します。

    python dmpatterns_getstarted_service.py
    
  3. ダイレクト メソッドに対するデバイスの応答がコンソールに表示されます。

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

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

    再起動ダイレクト メソッドを呼び出してデバイス ツインの状態をポーリングするサービスを次に示します。

    再起動サービスの出力のトリガー

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

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

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

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

次のステップ

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

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

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