Azure Digital Twins に IoT Hub テレメトリを取り込む

このガイドでは、IoT Hub からデバイス テレメトリを取り込んで Azure Digital Twins のインスタンスに送信できる関数を記述するプロセスについて説明します。

Azure Digital Twins は、IoT デバイスやその他のソースからのデータに基づいています。 Azure Digital Twins で使用するデバイス データの一般的なソースは IoT Hub です。

Azure Digital Twins にデータを取り込むプロセスは、Azure Functions を使って作られた関数のような外部のコンピューティング リソースを設定することです。 この関数はデータを受け取り、必要に応じて DigitalTwins API を使用してプロパティを設定したり、デジタル ツインでテレメトリ イベントを発生させたりします。

このハウツー ドキュメントでは、IoT Hub からデバイス テレメトリを取り込むことができる関数を記述するプロセスについて説明します。

前提条件

この例を続行する前に、前提条件として次のリソースを設定する必要があります。

  • IoT Hub。 手順については、この IoT Hub クイック スタート「IoT Hub の作成」セクションを参照してください。
  • デバイス テレメトリを受信する Azure Digital Twins インスタンス。 手順については、Azure Digital Twins インスタンスと認証の設定に関するページを参照してください。

テレメトリのシナリオ例

このハウツーでは、Azure の関数を使用して、IoT Hub から Azure Digital Twins にメッセージを送信する方法の概要について説明します。 メッセージの送信に使用できる構成とマッチング戦略は多数ありますが、この記事の例には次のパーツが含まれています。

  • 既知のデバイス ID を持つ IoT Hub のサーモスタット デバイス
  • ID が一致するデバイスを表すデジタル ツイン

Note

この例では、デバイス ID と対応するデジタル ツインの ID の間の単純な ID 一致を使用していますが、(マッピング テーブルなどを使用して) デバイスからツインへのより高度なマッピングを用意することもできます。

温度テレメトリ イベントがサーモスタット デバイスによって送信されるたびに、関数によってテレメトリが処理され Temperature 、デジタル ツインのプロパティが更新されます。 このシナリオの概要を次の図に示します。

Diagram of IoT Hub device sending Temperature telemetry to a function in Azure, which updates a Temperature property on a twin in Azure Digital Twins.

モデルとツインの追加

このセクションでは、Azure Digital Twins 内でデジタル ツインを設定します。これは、サーモスタット デバイスを表し、IoT Hub からの情報で更新されます。

サーモスタット型ツインを作成するには、まず、サーモスタット モデル をご利用のインスタンスにアップロードする必要があります。これは、サーモスタットのプロパティを記述したもので、後でツインを作成するために使用されます。

モデルは次のようになります。

{
    "@id": "dtmi:contosocom:DigitalTwins:Thermostat;1",
    "@type": "Interface",
    "@context": "dtmi:dtdl:context;3",
    "contents": [
      {
        "@type": "Property",
        "name": "Temperature",
        "schema": "double"
      }
    ]
  }

このモデルをツイン インスタンスにアップロードするには、次の Azure CLI コマンドを実行します。これにより、上記のモデルがインライン JSON としてアップロードされます。 このコマンドは、ご利用のブラウザーで Azure Cloud Shell から実行できます (Bash 環境を使用)。CLI がローカルにインストールされている場合は、ご利用のコンピューター上でも実行できます。 インスタンスのホスト名にはプレースホルダーが 1 つあります (インスタンスのフレンドリ名を使用することもできますが、パフォーマンスが若干低下します)。

az dt model create --dt-name <instance-hostname-or-name> --models '{  "@id": "dtmi:contosocom:DigitalTwins:Thermostat;1",  "@type": "Interface",  "@context": "dtmi:dtdl:context;2",  "contents": [    {      "@type": "Property",      "name": "Temperature",      "schema": "double"    }  ]}' 

Note

Bash 環境で Cloud Shell 以外のものを使用している場合は、インライン JSON で特定の文字をエスケープして、正しく解析されるようにする必要があります。 詳細については、さまざまなシェルでの特殊文字の使用に関するページを参照してください。

次に、このモデルを使用して 1 つのツインを作成します。 次のコマンドを使用して thermostat67 という名前のサーモスタット ツインを作成して、初期温度値を 0.0 に設定します。 インスタンスのホスト名にはプレースホルダーが 1 つあります (インスタンスのフレンドリ名を使用することもできますが、パフォーマンスが若干低下します)。

az dt twin create  --dt-name <instance-hostname-or-name> --dtmi "dtmi:contosocom:DigitalTwins:Thermostat;1" --twin-id thermostat67 --properties '{"Temperature": 0.0}'

ツインが正常に作成されると、コマンドからの CLI 出力は次のようになります。

{
  "$dtId": "thermostat67",
  "$etag": "W/\"0000000-9735-4f41-98d5-90d68e673e15\"",
  "$metadata": {
    "$model": "dtmi:contosocom:DigitalTwins:Thermostat;1",
    "Temperature": {
      "lastUpdateTime": "2021-09-09T20:32:46.6692326Z"
    }
  },
  "Temperature": 0.0
}

Azure 関数を作成する

このセクションでは、Azure Digital Twins にアクセスし、受信した IoT デバイス テレメトリ イベントに基づいてツインを更新する Azure 関数を作成します。 関数を作成して発行するには、次の手順に従います。

  1. 最初に、Event Grid トリガー型の新規の Azure Functions プロジェクトを作成します。

    これを行うには、Visual Studio (手順については、「Visual Studioを使用する Azure Functions の開発」を参照)、Visual Studio Code (手順については、「Visual Studio Code を使用して Azure に C# 関数を作成する」を参照)、または Azure CLI (手順については、Azure でコマンド ラインから C# 関数を作成する」を参照) を使用します。

  2. 次のパッケージをプロジェクトに追加します (Visual Studio NuGet パッケージ マネージャー、またはコマンド ライン ツールの dotnet add package コマンドを使用できます)。

  3. IoTHubtoTwins.cs という名前の関数をプロジェクト内に作成します。 この関数ファイルに次のコードを貼り付けます。

    using System;
    using Azure;
    using System.Net.Http;
    using Azure.Core.Pipeline;
    using Azure.DigitalTwins.Core;
    using Azure.Identity;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.EventGrid;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using Azure.Messaging.EventGrid;
    
    namespace IotHubtoTwins
    {
        public class IoTHubtoTwins
        {
            private static readonly string adtInstanceUrl = Environment.GetEnvironmentVariable("ADT_SERVICE_URL");
            private static readonly HttpClient httpClient = new HttpClient();
    
            [FunctionName("IoTHubtoTwins")]
            // While async void should generally be used with caution, it's not uncommon for Azure function apps, since the function app isn't awaiting the task.
    #pragma warning disable AZF0001 // Suppress async void error
            public async void Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log)
    #pragma warning restore AZF0001 // Suppress async void error
            {
                if (adtInstanceUrl == null) log.LogError("Application setting \"ADT_SERVICE_URL\" not set");
    
                try
                {
                    // Authenticate with Digital Twins
                    var cred = new DefaultAzureCredential();
                    var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred);
                    log.LogInformation($"ADT service client connection created.");
                
                    if (eventGridEvent != null && eventGridEvent.Data != null)
                    {
                        log.LogInformation(eventGridEvent.Data.ToString());
    
                        // <Find_device_ID_and_temperature>
                        JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString());
                        string deviceId = (string)deviceMessage["systemProperties"]["iothub-connection-device-id"];
                        var temperature = deviceMessage["body"]["Temperature"];
                        // </Find_device_ID_and_temperature>
    
                        log.LogInformation($"Device:{deviceId} Temperature is:{temperature}");
    
                        // <Update_twin_with_device_temperature>
                        var updateTwinData = new JsonPatchDocument();
                        updateTwinData.AppendReplace("/Temperature", temperature.Value<double>());
                        await client.UpdateDigitalTwinAsync(deviceId, updateTwinData);
                        // </Update_twin_with_device_temperature>
                    }
                }
                catch (Exception ex)
                {
                    log.LogError($"Error in ingest function: {ex.Message}");
                }
            }
        }
    }
    

    関数コードを保存します。

  4. IoTHubtoTwins.cs 関数を使用して、プロジェクトを Azure の関数アプリに発行します。

    Visual Studio を使用して関数を発行する方法については、「Visual Studio を使用する Azure Functions の開発」を参照してください。 Visual Studio Code を使用して関数を発行する方法については、「Visual Studio Code を使用して Azure に C# 関数を作成する」を参照してください。 Azure CLI を使用して関数を発行する方法については、「Azure でコマンド ラインから C# 関数を作成する」を参照してください。

関数の発行プロセスが完了したら、この Azure CLI コマンドを使用して、発行が成功したことを確認できます。 リソース グループおよび関数アプリの名前のプレースホルダーがあります。 このコマンドでは、IoTHubToTwins 関数に関する情報を出力します。

az functionapp function show --resource-group <your-resource-group> --name <your-function-app> --function-name IoTHubToTwins

Function App を構成する

Azure Digital Twins にアクセスするには、関数アプリに、Azure Digital Twins インスタンスにアクセスできるアクセス許可を持つシステム割り当てマネージド ID が必要です。 このセクションでは、関数のアクセス ロールを割り当て、Azure Digital Twins インスタンスにアクセスできるようにアプリケーション設定を構成することで、この設定を行います。

Azure Cloud Shell またはローカル Azure CLI で次のコマンドを実行します。

Note

このセクションは、アクセス許可の付与や委任を含む、Azure リソースへのユーザー アクセスを管理するためのアクセス許可を持つ Azure ユーザーが行う必要があります。 この要件を満たす一般的なロールは、所有者アカウント管理者ユーザー アクセス管理者共同作成者の組み合わせです。 Azure Digital Twins のロールのアクセス許可要件の詳細については、インスタンスと認証の設定に関する記事を参照してください。

アクセス ロールを割り当てる

Azure 関数には、ベアラー トークンを渡す必要があります。 ベアラー トークンが確実に渡されるようにするには、関数アプリに Azure Digital Twins インスタンスの Azure Digital Twins データ所有者ロールを付与します。これにより、インスタンスでデータ プレーン アクティビティを実行するアクセス許可が関数アプリに付与されます。

  1. 次のコマンドを使用して、関数のシステム マネージド ID を作成します (関数に既に存在する場合、このコマンドはその詳細を出力します)。 出力内の principalId フィールドをメモします。 この ID は、次の手順でアクセス許可を付与できるように、関数を参照するために使用します。

    az functionapp identity assign --resource-group <your-resource-group> --name <your-function-app-name>	
    
  2. 次のコマンドで principalId 値を使用して、対象の Azure Digital Twins インスタンスの Azure Digital Twins データ所有者ロールを関数に付与します。

    az dt role-assignment create --dt-name <your-Azure-Digital-Twins-instance> --assignee "<principal-ID>" --role "Azure Digital Twins Data Owner"
    

アプリケーション設定の構成

次に、環境変数を設定することで、関数から Azure Digital Twins インスタンスの URL にアクセスできるようにします。

ヒント

Azure Digital Twins インスタンスの URL を作成するには、インスタンスのホスト名の先頭に https:// を追加します。 インスタンスのすべてのプロパティと共にホスト名を表示するには、az dt show --dt-name <your-Azure-Digital-Twins-instance> を実行します。

次のコマンドでは、関数がインスタンスにアクセスする必要があるときに必ず使用する、対象のインスタンスの URL の環境変数を設定します。

az functionapp config appsettings set --resource-group <your-resource-group> --name <your-function-app-name> --settings "ADT_SERVICE_URL=https://<your-Azure-Digital-Twins-instance-host-name>"

関数を IoT Hub に接続する

このセクションでは、IoT Hub デバイス データのイベントの宛先として関数を設定します。 この方法で関数を設定すると、IoT Hub のサーモスタット デバイスからのデータが処理のために Azure 関数に送信されます。

次の CLI コマンドを使用して、IoTHubtoTwins 関数にイベント データを送信するために IoT Hub で使用するイベント サブスクリプションを作成します。 イベント サブスクリプションの名前を入力するためのプレースホルダーだけでなく、サブスクリプション ID、リソース グループ、IoT ハブ名、関数アプリの名前を入力するためのプレースホルダーもあります。

az eventgrid event-subscription create --name <name-for-hub-event-subscription> --event-delivery-schema eventgridschema --source-resource-id /subscriptions/<your-subscription-ID>/resourceGroups/<your-resource-group>/providers/Microsoft.Devices/IotHubs/<your-IoT-hub> --included-event-types Microsoft.Devices.DeviceTelemetry --endpoint-type azurefunction --endpoint /subscriptions/<your-subscription-ID>/resourceGroups/<your-resource-group>/providers/Microsoft.Web/sites/<your-function-app>/functions/IoTHubtoTwins

出力には、作成されたイベント サブスクリプションに関する情報が表示されます。 結果の provisioningState 値を確認することで、操作が正常に完了したことを確認できます。

"provisioningState": "Succeeded",

シミュレートされた IoT データを使用してテストする

エンドツーエンドのソリューションの接続に関するページのデバイス シミュレーターを使用して、新しいイングレス機能をテストできます。 DeviceSimulator プロジェクトには、サンプルの温度データを送信するシミュレートされたサーモスタット デバイスが含まれています。 デバイス シミュレーターを設定するには、次の手順に従います。

  1. Azure Digital Twins のエンド ツー エンドのサンプル プロジェクト リポジトリに移動します。 タイトルの下にある [Browse Code](コードの参照) ボタンを選択して、お使いのマシン上でサンプル プロジェクトを取得します。 これにより、サンプル用の GitHub リポジトリに移動します。[Code](コード) ボタンと、[Download ZIP](ZIP のダウンロード) を選択することによって、.zip 形式でこれをダウンロードできます。

    これにより、.zip フォルダーが digital-twins-samples-main.zip としてお使いのマシンにダウンロードされます。 フォルダーを解凍し、ファイルを抽出します。 DeviceSimulator プロジェクト フォルダーを使用します。

  2. シミュレートされたデバイスを IoT Hub に登録する

  3. シミュレーションを構成して実行する

これらの手順を完了すると、プロジェクト コンソール ウィンドウが実行され、シミュレートされたデバイス テレメトリ データが IoT ハブに送信されます。

Screenshot of the output from the device simulator project.

結果を検証する

上記のデバイス シミュレーターを実行中に、サーモスタットのデジタル ツインの温度値が変化します。 Azure CLI で、次のコマンドを実行して、温度値を確認します。 インスタンスのホスト名にはプレースホルダーが 1 つあります (インスタンスのフレンドリ名を使用することもできますが、パフォーマンスが若干低下します)。

az dt twin query --query-command "SELECT * FROM digitaltwins WHERE \$dtId = 'thermostat67'" --dt-name <instance-hostname-or-name>

Note

Bash 環境で Cloud Shell 以外のものを使用している場合は、クエリ内の $ 文字を異なる方法でエスケープして、正しく解析されるようにする必要があります。 詳細については、さまざまなシェルでの特殊文字の使用に関するページを参照してください。

出力には、次のような温度値を含む thermostat67 のツインの詳細が表示されます。

{
  "result": [
    {
      "$dtId": "thermostat67",
      "$etag": "W/\"dbf2fea8-d3f7-42d0-8037-83730dc2afc5\"",
      "$metadata": {
        "$model": "dtmi:contosocom:DigitalTwins:Thermostat;1",
        "Temperature": {
          "lastUpdateTime": "2021-06-03T17:05:52.0062638Z"
        }
      },
      "Temperature": 70.20518558807913
    }
  ]
}

Temperature 値の変化を確認するには、上記のクエリ コマンドを繰り返し実行します。

次のステップ

Azure Digital Twins を使用したデータのイングレスとエグレスについて確認します。