デバイス ツインの概要 (Python)

デバイス ツインは、デバイスに関する情報 (メタデータ、構成、状態など) を格納する JSON ドキュメントです。 IoT Hub は、IoT Hub に接続する各デバイスにデバイス ツインを保持します。

Note

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

次の場合にデバイス ツインを使用します。

  • ソリューション バックエンドからデバイス メタデータを格納する。

  • デバイス アプリで利用できる機能や状態 (たとえば、使用される接続方法) などの現在の状態に関する情報をレポートする。

  • デバイス アプリとバックエンド アプリの間で実行時間の長いワークフロー (ファームウェアや構成の更新など) の状態を同期する。

  • デバイス メタデータ、構成、または状態を照会する。

デバイス ツインは、同期のほか、デバイスの構成と状態の照会に対応しています。 デバイス ツインの使用方法など、デバイス ツインの詳細については、デバイス ツインの理解に関するページを参照してください。

IoT ハブには、次の要素を含むデバイス ツインが格納されます。

  • タグ。 ソリューション バックエンドからのみアクセスできるデバイス メタデータです。

  • 必要なプロパティ。 ソリューション バックエンドから変更でき、デバイス アプリから監視できる JSON オブジェクトです。

  • 報告されるプロパティ。 デバイス アプリから変更でき、ソリューション バックエンドから読み取り可能な JSON オブジェクトです。

タグとプロパティには配列を含めることはできませんが、入れ子になったオブジェクトを含めることができます。

次の図は、デバイス ツイン組織を示しています。

デバイス ツインの概念図のスクリーンショット。

さらに、ソリューション バックエンドは、上記のすべてのデータに基づいてデバイス ツインに対してクエリを実行できます。 デバイス ツインの詳細については、デバイス ツインの理解に関するページを参照してください。 クエリ実行の詳細については、IoT Hub クエリ言語に関するページを参照してください。

この記事で取り上げるテクニック:

  • シミュレートされたデバイス アプリを使用して、その接続チャネルをデバイス ツインで報告されたプロパティとして報告します。

  • 以前に作成したタグとプロパティのフィルターを使用して、バックエンド アプリからデバイスに対してクエリを実行します。

この記事では、次の 2 つの Python コンソール アプリを作成します。

  • AddTagsAndQuery.py: タグの追加とデバイス ツインのクエリを実行するバックエンド アプリ。

  • ReportConnectivity.py: IoT ハブに接続してその接続状態を報告するシミュレートされたデバイス アプリ。

Note

デバイスとバックエンド アプリの両方の構築に使用できる 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 ハブ接続文字列を取得する

この記事では、デバイス ツインに必要なプロパティを追加した後、ID レジストリに対してクエリを実行し、適切に更新された報告されるプロパティを持つデバイスをすべて検索するバックエンド サービスを作成します。 そのサービスには、必要なデバイス ツインのプロパティを変更するためのサービス接続アクセス許可と、ID レジストリに対してクエリを実行するためのレジストリ読み取りアクセス許可が必要となります。 その 2 つのアクセス許可だけを含んだ既定の共有アクセス ポリシーは存在しないため、共有アクセス ポリシーを独自に作成する必要があります。

サービス接続レジストリ読み取りのアクセス許可を付与する共有アクセス ポリシーを作成し、そのポリシーの接続文字列を取得するには、次の手順を実行します。

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

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

  3. ポリシー一覧の上にある最初のメニューから、[共有アクセス ポリシーの追加] を選びます。

  4. 右側の [共有アクセス ポリシーの追加] ウィンドウで、serviceAndRegistryRead などのポリシーのわかりやすい名前を入力します。 [アクセス許可][レジストリ読み取り][サービス接続] を選び、[追加] を選びます。

    新しい共有アクセス ポリシーを追加する方法を示すスクリーン キャプチャ。

  5. ポリシーの一覧から、新しいポリシーを選択します。

  6. [プライマリ接続文字列] のコピー アイコンを選び、その値を保存します。

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

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

目的のプロパティおよびクエリ ツインを更新するサービス アプリを作成する

このセクションでは、{Device ID} に関連付けられたデバイス ツインに場所のメタデータを追加する Python コンソール アプリを作成します。 このアプリは、IoT ハブで米国内にあるデバイスのクエリを実行した後、携帯ネットワーク接続を報告しているデバイスのクエリを実行します。

  1. 作業ディレクトリでコマンド プロンプトを開き、Azure IoT Hub Service SDK for Python をインストールします。

    pip install azure-iot-hub
    
  2. テキスト エディターを使用して、新しい AddTagsAndQuery.py ファイルを作成します。

  3. Service SDK から必要なモジュールをインポートする次のコードを追加します。

    import sys
    from time import sleep
    from azure.iot.hub import IoTHubRegistryManager
    from azure.iot.hub.models import Twin, TwinProperties, QuerySpecification, QueryResult
    
  4. 次のコードを追加します。 [IoTHub Connection String] を、「IoT ハブ接続文字列を取得する」でコピーしておいた IoT ハブ接続文字列に置き換えます。 [Device Id] を、IoT ハブの登録済みデバイスのデバイス ID (名前) に置き換えます。

    IOTHUB_CONNECTION_STRING = "[IoTHub Connection String]"
    DEVICE_ID = "[Device Id]"
    
  5. 次のコードを AddTagsAndQuery.py ファイルに追加します。

    def iothub_service_sample_run():
        try:
            iothub_registry_manager = IoTHubRegistryManager(IOTHUB_CONNECTION_STRING)
    
            new_tags = {
                    'location' : {
                        'region' : 'US',
                        'plant' : 'Redmond43'
                    }
                }
    
            twin = iothub_registry_manager.get_twin(DEVICE_ID)
            twin_patch = Twin(tags=new_tags, properties= TwinProperties(desired={'power_level' : 1}))
            twin = iothub_registry_manager.update_twin(DEVICE_ID, twin_patch, twin.etag)
    
            # Add a delay to account for any latency before executing the query
            sleep(1)
    
            query_spec = QuerySpecification(query="SELECT * FROM devices WHERE tags.location.plant = 'Redmond43'")
            query_result = iothub_registry_manager.query_iot_hub(query_spec, None, 100)
            print("Devices in Redmond43 plant: {}".format(', '.join([twin.device_id for twin in query_result.items])))
    
            print()
    
            query_spec = QuerySpecification(query="SELECT * FROM devices WHERE tags.location.plant = 'Redmond43' AND properties.reported.connectivity = 'cellular'")
            query_result = iothub_registry_manager.query_iot_hub(query_spec, None, 100)
            print("Devices in Redmond43 plant using cellular network: {}".format(', '.join([twin.device_id for twin in query_result.items])))
    
        except Exception as ex:
            print("Unexpected error {0}".format(ex))
            return
        except KeyboardInterrupt:
            print("IoT Hub Device Twin service sample stopped")
    

    IoTHubRegistryManager オブジェクトに、サービスからデバイス ツインとやりとりするのに必要なすべてのメソッドが表示されます。 最初のコードで IoTHubRegistryManager オブジェクトを初期化した後、DEVICE_ID のデバイス ツインを更新し、最後に 2 つのクエリを実行します。 最初のものでは Redmond43 工場にあるデバイスのデバイス ツインのみを選択し、2 番目のものでは携帯ネットワーク経由で接続しているデバイスのみを選択します。

  6. 次のコードを AddTagsAndQuery.py の末尾に追加して、iothub_service_sample_run 関数を実装します。

    if __name__ == '__main__':
        print("Starting the Python IoT Hub Device Twin service sample...")
        print()
    
        iothub_service_sample_run()
    
  7. 以下を使用してアプリケーションを実行します。

    python AddTagsAndQuery.py
    

    Redmond43 にあるすべてのデバイスを照会するクエリの結果には、1 件のデバイスが表示され、携帯ネットワークを使用するデバイスに絞り込んだ結果には 0 件のデバイスが表示されます。 次のセクションでは、移動体通信ネットワークを使用するデバイス アプリを作成し、このクエリを再実行して、その変更を確認します。

    Redmond にあるすべてのデバイスを表示する最初のクエリのスクリーンショット。

報告されたプロパティを更新するデバイス アプリを作成する

このセクションでは、{Device ID} としてハブに接続される Python コンソール アプリを作成し、報告されたデバイス ツインのプロパティを更新して、接続に携帯ネットワークが使用されていることを確認します。

  1. 作業ディレクトリのコマンド プロンプトから、Azure IoT Hub Device SDK for Python をインストールします。

    pip install azure-iot-device
    
  2. テキスト エディターを使用して、新しい ReportConnectivity.py ファイルを作成します。

  3. Device SDK から必要なモジュールをインポートする次のコードを追加します。

    import time
    from azure.iot.device import IoTHubModuleClient
    
  4. 次のコードを追加します。 [IoTHub Device Connection String] プレースホルダーの値を、IoT Hub でデバイスを登録した時に表示されたデバイス接続文字列に置き換えます。

    CONNECTION_STRING = "[IoTHub Device Connection String]"
    
  5. 次のコードを ReportConnectivity.py ファイルに追加して、クライアントのインスタンスを作成し、デバイス ツインの機能を実装します。

    def create_client():
        # Instantiate client
        client = IoTHubModuleClient.create_from_connection_string(CONNECTION_STRING)
    
        # Define behavior for receiving twin desired property patches
        def twin_patch_handler(twin_patch):
            print("Twin patch received:")
            print(twin_patch)
    
        try:
            # Set handlers on the client
            client.on_twin_desired_properties_patch_received = twin_patch_handler
        except:
            # Clean up in the event of failure
            client.shutdown()
    
        return client
    
  6. ReportConnectivity.py の最後に以下のコードを追加して、アプリケーションを実行します。

    def main():
        print ( "Starting the Python IoT Hub Device Twin device sample..." )
        client = create_client()
        print ( "IoTHubModuleClient waiting for commands, press Ctrl-C to exit" )
    
        try:
            # Update reported properties with cellular information
            print ( "Sending data as reported property..." )
            reported_patch = {"connectivity": "cellular"}
            client.patch_twin_reported_properties(reported_patch)
            print ( "Reported properties updated" )
    
            # Wait for program exit
            while True:
                time.sleep(1000000)
        except KeyboardInterrupt:
            print ("IoT Hub Device Twin device sample stopped")
        finally:
            # Graceful exit
            print("Shutting down IoT Hub Client")
            client.shutdown()
    
    if __name__ == '__main__':
        main()
    
  7. デバイス アプリを実行する:

    python ReportConnectivity.py
    

    デバイス ツインの報告されるプロパティが更新されたこと示す確認メッセージが表示されます。

    デバイス アプリから報告されたプロパティを更新する

  8. これで、デバイスが接続情報を報告したため、両方のクエリで表示されるようになります。 戻って、クエリをもう一度実行します。

    python AddTagsAndQuery.py
    

    今回は、 {Device ID} が両方のクエリ結果に表示されるはずです。

    サービス アプリに対する 2 番目のクエリ

    デバイス アプリで、サービス アプリによって送信された必要なプロパティ ツイン パッチが受信されたことを確認するメッセージが表示されます。

    デバイス アプリ上で必要なプロパティを受信する

この記事では、次の内容について説明します。

  • バックエンド アプリからタグとしてデバイス メタデータを追加しました
  • デバイス ツインでデバイス接続情報を報告しました
  • IoT Hub クエリ言語を使用して、デバイス ツイン情報のクエリを実行しました

次のステップ

参照: