チュートリアル:Device Provisioning Service (DPS) でカスタム割り当てポリシーを使用する

カスタム割り当てポリシーを使用すると、デバイスを IoT ハブに割り当てる方法をより細かくコントロールできます。 Azure IoT Hub Device Provisioning Service(DPS) で提供されるポリシーがご自身のシナリオの要件を満たしていない場合は、カスタム割り当てポリシーを使用して独自の割り当てポリシーを定義します。 カスタム割り当てポリシーは、Azure Functions でホストされる Webhook に実装され、1 つ以上の個別登録または登録グループで構成されます。 デバイスが構成された登録エントリを使用して DPS に登録されると、DPS は Webhook を呼び出して、デバイスを登録する必要がある IoT ハブと、必要に応じてその初期状態を確認します。 詳細については、「 カスタム割り当てポリシーを理解する」を参照してください。

このチュートリアルでは、C# で記述された Azure 関数を使用して、カスタム割り当てポリシーについて説明します。 デバイスは、 Contoso トースター部門Contosoヒート ポンプ部門を表す 2 つの IoT ハブのいずれかに割り当てられます。 プロビジョニングを必要とするデバイスには、プロビジョニングの要求が受け入れられるようにするために、次のいずれかのサフィックスを持つ登録 ID が必要です。

  • -contoso-tstrsd-007 Contoso トースター部門用
  • -contoso-hpsd-088 Contoso ヒート ポンプ部門用

デバイスは、Azure IoT C SDK に含まれるプロビジョニング サンプルを使ってシミュレートされます。

このチュートリアルでは、以下を行います:

  • Azure CLI を使って DPS インスタンスを作成し、2 つの Contoso 部門 IoT ハブ (Contoso トースター部門Contoso ヒート ポンプ部門) を作成してリンクし、DPS インスタンスにリンクします。
  • カスタム割り当てポリシーを実装する Azure 関数を作成します。
  • カスタム割り当てポリシー用に Azure 関数を使う新しい登録グループを作成します。
  • 2 つのシミュレートされたデバイスのデバイス対称キーを作成します。
  • Azure IoT C SDK の開発環境をセットアップします。
  • デバイスをシミュレートして、デバイスがカスタム割り当てポリシーのコード例に従ってプロビジョニングされていることを確認します。

Azure サブスクリプションをお持ちでない場合は、開始する前に Azure 無料アカウントを作成してください。

前提条件

Windows 開発環境の前提条件は次のとおりです。 Linux または macOS については、SDK ドキュメントの「開発環境を準備する」の該当するセクションを参照してください。

プロビジョニング サービスと 2 つの IoT ハブを作成する

このセクションでは、Azure Cloud Shell を使用して、プロビジョニング サービスと、Contoso トースター部門Contoso ヒート ポンプ部門を表す 2 つの IoT ハブを作成します。

  1. 最初に、ワークスペースに環境変数を設定して、このチュートリアルのコマンドを簡略化します。

    DPS と IoT Hub の名前はグローバルに一意である必要があります。 SUFFIX プレースホルダーは、実際の値に置き換えてください。

    また、このチュートリアルで後で作成する Azure 関数コードでは、名前に -toasters- または -heatpumps- のいずれかが含まれる IoT ハブが検索されます。 提案された値を変更する場合は、必要な部分文字列が含まれる名前を使います。

    #!/bin/bash
    export RESOURCE_GROUP="contoso-us-resource-group"
    export LOCATION="westus"
    export DPS="contoso-provisioning-service-SUFFIX"
    export TOASTER_HUB="contoso-toasters-hub-SUFFIX"
    export HEATPUMP_HUB="contoso-heatpumps-hub-SUFFIX"
    
    # PowerShell
    $env:RESOURCE_GROUP = "contoso-us-resource-group"
    $env:LOCATION = "westus"
    $env:DPS = "contoso-provisioning-service-SUFFIX"
    $env:TOASTER_HUB = "contoso-toasters-hub-SUFFIX"
    $env:HEATPUMP_HUB = "contoso-heatpumps-hub-SUFFIX"
    

    ヒント

    このチュートリアルで使うコマンドは、既定で米国西部の場所にリソースを作成します。 ご自分の場所から最も近い、Device Provisioning Service がサポートされているリージョンにリソースを作成することをお勧めします。 使用可能な場所の一覧を表示するには、Azure の状態ページに移動して "Device Provisioning Service" を検索します。 コマンドでは、場所は 1 単語または複数単語の形式で指定できます。たとえば、westus、West US、WEST US などです。この値で、大文字と小文字は区別されません。

  2. az group create コマンドを使って Azure リソース グループを作成します。 Azure リソース グループとは、Azure リソースのデプロイと管理に使用する論理コンテナーです。

    次の例では、リソース グループを作成します。 このチュートリアルで作成したすべてのリソースで、1 つのグループを使うことをお勧めします。 こうすることで、終わった後のクリーンアップが簡単になります。

    az group create --name $RESOURCE_GROUP --location $LOCATION
    
  3. az iot dps create コマンドを使って、Device Provisioning Service (DPS) インスタンスを作成します。 プロビジョニング サービスは、contoso-us-resource-group に追加されます。

    az iot dps create --name $DPS --resource-group $RESOURCE_GROUP --location $LOCATION
    

    このコマンドは、完了するまで数分かかることがあります。

  4. az iot hub create コマンドを使って、Contoso トースター部門 IoT ハブを作成します。 IoT ハブは、contoso-us-resource-group に追加されます。

    az iot hub create --name $TOASTER_HUB --resource-group $RESOURCE_GROUP --location $LOCATION --sku S1
    

    このコマンドは、完了するまで数分かかることがあります。

  5. az iot hub create コマンドを使って、Contoso ヒート ポンプ部門 IoT ハブを作成します。 この IoT ハブも、contoso-us-resource-group に追加されます。

    az iot hub create --name $HEATPUMP_HUB --resource-group $RESOURCE_GROUP --location $LOCATION --sku S1
    

    このコマンドは、完了するまで数分かかることがあります。

  6. 次の 2 つのコマンドを実行して、作成したハブの接続文字列を取得します。

    az iot hub connection-string show --hub-name $TOASTER_HUB --key primary --query connectionString -o tsv
    az iot hub connection-string show --hub-name $HEATPUMP_HUB --key primary --query connectionString -o tsv
    
  7. 次のコマンドを実行して、ハブを DPS リソースにリンクします。 プレースホルダーを、前の手順のハブ接続文字列に置き換えます。

    az iot dps linked-hub create --dps-name $DPS --resource-group $RESOURCE_GROUP --location $LOCATION --connection-string <toaster_hub_connection_string>
    az iot dps linked-hub create --dps-name $DPS --resource-group $RESOURCE_GROUP --location $LOCATION --connection-string <heatpump_hub_connection_string>
    

カスタム割り当て関数を作成する

このセクションでは、カスタム割り当てポリシーを実装する Azure 関数を作成します。 この関数により、デバイスの登録 ID に文字列 -contoso-tstrsd-007 または -contoso-hpsd-088 が含まれているかどうかに基づいて、デバイスをどちら部門の IoT ハブに登録すべきかが決定されます。 また、デバイスがトースターであるかヒート ポンプであるかに基づいて、デバイス ツインの初期状態が設定されます。

  1. Azure portal にサインインします。

  2. 検索ボックスで、「関数アプリ」を検索して選択します。

  3. [作成] または [関数アプリの作成] を選択します。

  4. 関数アプリの作成ページの 基本 タブで、新しい関数アプリに次の設定を入力し、[確認と作成] を選択します:

    パラメーター
    サブスクリプション このチュートリアルのリソースを作成したサブスクリプションが選択されていることを確認します。
    リソース グループ 前のセクションで作成したリソース グループを選択します 前のセクションで指定した既定値は contoso-us-resource-group です。
    関数アプリ名 関数アプリの名前を指定します。
    コードまたはコンテナー イメージをデプロイしますか? コード
    ランタイム スタック .NET
    Version インプロセス モデルのバージョンを選択します。
    リージョン 近くのリージョンを選択します。

    Note

    既定では、Application Insights が有効になっています。 このチュートリアルでは Application Insights は必要ありませんが、カスタム割り当てで発生するイシューを理解し、調査するのに役立つ場合があります。 必要に応じて、 [監視] タブを選択し、 [Application Insights を有効にする][いいえ] に選択することで、Application Insights を無効にすることができます。

    Azure portal の [関数アプリの作成] フォームを示すスクリーンショット。

  5. [確認と作成] タブで [作成] を選択して関数アプリを作成します。

  6. デプロイには数分かかる場合があります。 完了したら、 [リソースに移動] を選択します。

  7. 関数アプリの [概要] ページの左側のウィンドウで、[関数の作成] を選択します。

    Azure portal で関数を作成するオプションの選択を示すスクリーンショット。

  8. [関数の作成] ページで、HTTP トリガー テンプレートを選択し、[次へ] を選択します。

  9. [テンプレートの詳細] タブで、[承認レベル] として [匿名] を選択し、[作成] を選択します。

    承認レベルを匿名として設定する方法を示すスクリーンショット。

    ヒント

    承認レベルを [関数] として保持する場合は、関数 API キーを使って DPS 登録を構成する必要があります。 詳細は、「Azure Functions の HTTP のトリガー」を参照してください

  10. HttpTrigger1 関数が開いたら、左側のウィンドウで [コード + テスト] を選択します。 これにより、関数のコードを編集できます。 run.csx コード ファイルを編集用に開く必要があります。

  11. 必須の NuGet パッケージを参照します。 初期デバイス ツインを作成するために、カスタム割り当て関数では、ホスティング環境に読み込む必要がある 2 つの NuGet パッケージで定義されているクラスが使用されます。 Azure Functions では、function.proj ファイルを使用して NuGet パッケージが参照されます。 この手順では、必要なアセンブリのための function.proj ファイルを保存してアップロードします。 詳細については、Azure Functions での NuGet パッケージの使用に関する記事を参照してください。

    1. 次の行を任意のエディターにコピーし、ファイルを function.proj としてご使用のコンピューターに保存します。

      <Project Sdk="Microsoft.NET.Sdk">  
          <PropertyGroup>  
              <TargetFramework>netstandard2.0</TargetFramework>  
          </PropertyGroup>  
          <ItemGroup>  
              <PackageReference Include="Microsoft.Azure.Devices.Provisioning.Service" Version="1.18.1" />
              <PackageReference Include="Microsoft.Azure.Devices.Shared" Version="1.30.1" />
          </ItemGroup>  
      </Project>
      
    2. コード エディターの上にある [アップロード] ボタンを選択して、function.proj ファイルをアップロードします。 アップロードした後、ドロップダウン ボックスを使用してコード エディターでファイルを選択し、内容を確認します。

    3. コード エディターで function.proj ファイルを選択し、その内容を確認します。 function.proj ファイルが空の場合は、上記の行をファイルにコピーして保存します。 (アップロードによって、コンテンツをアップロードせずにファイルが作成される場合があります)。

  12. コード エディターで HttpTrigger1run.csx が選択されていることを確認します。 HttpTrigger1 関数のコードを次のコードに置き換え、 [保存] を選択します。

    #r "Newtonsoft.Json"
    
    using System.Net;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Primitives;
    using Newtonsoft.Json;
    
    using Microsoft.Azure.Devices.Shared;               // For TwinCollection
    using Microsoft.Azure.Devices.Provisioning.Service; // For TwinState
    
    public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");
    
        // Get request body
        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        dynamic data = JsonConvert.DeserializeObject(requestBody);
    
        log.LogInformation("Request.Body:...");
        log.LogInformation(requestBody);
    
        // Get registration ID of the device
        string regId = data?.deviceRuntimeContext?.registrationId;
    
        string message = "Uncaught error";
        bool fail = false;
        ResponseObj obj = new ResponseObj();
    
        if (regId == null)
        {
            message = "Registration ID not provided for the device.";
            log.LogInformation("Registration ID : NULL");
            fail = true;
        }
        else
        {
            string[] hubs = data?.linkedHubs?.ToObject<string[]>();
    
            // Must have hubs selected on the enrollment
            if (hubs == null)
            {
                message = "No hub group defined for the enrollment.";
                log.LogInformation("linkedHubs : NULL");
                fail = true;
            }
            else
            {
                // This is a Contoso Toaster Model 007
                if (regId.Contains("-contoso-tstrsd-007"))
                {
                    //Find the "-toasters-" IoT hub configured on the enrollment
                    foreach(string hubString in hubs)
                    {
                        if (hubString.Contains("-toasters-"))
                            obj.iotHubHostName = hubString;
                    }
    
                    if (obj.iotHubHostName == null)
                    {
                        message = "No toasters hub found for the enrollment.";
                        log.LogInformation(message);
                        fail = true;
                    }
                    else
                    {
                        // Specify the initial tags for the device.
                        TwinCollection tags = new TwinCollection();
                        tags["deviceType"] = "toaster";
    
                        // Specify the initial desired properties for the device.
                        TwinCollection properties = new TwinCollection();
                        properties["state"] = "ready";
                        properties["darknessSetting"] = "medium";
    
                        // Add the initial twin state to the response.
                        TwinState twinState = new TwinState(tags, properties);
                        obj.initialTwin = twinState;
                    }
                }
                // This is a Contoso Heat pump Model 008
                else if (regId.Contains("-contoso-hpsd-088"))
                {
                    //Find the "-heatpumps-" IoT hub configured on the enrollment
                    foreach(string hubString in hubs)
                    {
                        if (hubString.Contains("-heatpumps-"))
                            obj.iotHubHostName = hubString;
                    }
    
                    if (obj.iotHubHostName == null)
                    {
                        message = "No heat pumps hub found for the enrollment.";
                        log.LogInformation(message);
                        fail = true;
                    }
                    else
                    {
                        // Specify the initial tags for the device.
                        TwinCollection tags = new TwinCollection();
                        tags["deviceType"] = "heatpump";
    
                        // Specify the initial desired properties for the device.
                        TwinCollection properties = new TwinCollection();
                        properties["state"] = "on";
                        properties["temperatureSetting"] = "65";
    
                        // Add the initial twin state to the response.
                        TwinState twinState = new TwinState(tags, properties);
                        obj.initialTwin = twinState;
                    }
                }
                // Unrecognized device.
                else
                {
                    fail = true;
                    message = "Unrecognized device registration.";
                    log.LogInformation("Unknown device registration");
                }
            }
        }
    
        log.LogInformation("\nResponse");
        log.LogInformation((obj.iotHubHostName != null) ? JsonConvert.SerializeObject(obj) : message);
    
        return (fail)
            ? new BadRequestObjectResult(message) 
            : (ActionResult)new OkObjectResult(obj);
    }
    
    public class ResponseObj
    {
        public string iotHubHostName {get; set;}
        public TwinState initialTwin {get; set;}
    }
    

登録を作成する

このセクションでは、カスタム割り当てポリシーを使った新しい登録グループを作成します。 わかりやすくするため、このチュートリアルでは対称キーの構成証明を登録で使用します。 ソリューションをさらに安全にするには、信頼チェーンで X.509 証明書構成証明を使用することを検討してください。

  1. Azure portal にサインインし、Device Provisioning Service インスタンスに移動します。

  2. ナビゲーション メニューの [設定] セクションから [Manage enrollments] (登録の管理) を選択します。

  3. [登録グループの追加] を選択します。

  4. [登録グループの追加] ページの [Registration + provisioning] (登録とプロビジョニング) タブで、次の情報を入力して登録グループの詳細を構成します。

    フィールド 説明
    構成証明 [Attestation mechanism] (構成証明メカニズム) として [対称キー] を選択します。
    Symmetric key settings (対称キーの設定) [Generate symmetric keys automatically] (対称キーを自動的に生成) ボックスをオンにします。
    グループ名 グループ名として 「contoso-custom-allocated-devices」と入力します。
    プロビジョニング状態 [この登録を有効にする] ボックスをオンにします。
  5. [次へ: IoT ハブ] を選択します。

  6. [登録グループの追加] ページの [IoT ハブ] タブで、次の情報を入力して、登録グループでデバイスをプロビジョニングできる IoT ハブを決定します。

    フィールド 説明
    Target IoT hubs (ターゲット IoT ハブ) リンクされた IoT ハブのうち 1 つ以上を選択するか、IoT ハブへの新しいリンクを追加します。
    割り当てポリシー [カスタム (Azure 関数を使用)] を選択します。 [Azure 関数の選択] を選択し、画面の指示に従って、このチュートリアル用に作成した関数を選択します。
  7. [Review + create](レビュー + 作成) を選択します。

  8. [確認と作成] タブで、すべての値を確認してから [作成] を選択します。

登録を保存した後、もう一度開き、[主キー] を書き留めておきます。 キーを生成するには、まず登録を保存する必要があります。 このキーは、シミュレートされたデバイスに対する一意のデバイス キーを生成するために次のセクションで使います。

一意のデバイス キーを派生させる

デバイスでは、登録グループのプライマリ対称キーは直接使用されません。 代わりに、プライマリ キーを使用して各デバイスのデバイス キーが派生されます。 このセクションでは、一意のデバイス キーを 2 つ作成します。 シミュレートされたトースター デバイスでは、1 つのキーを使います。 もう 1 つのキーは、シミュレートされたヒート ポンプ デバイスで使います。

デバイス キーを派生させるには、前に書き留めた登録グループ主キーを使って、デバイスごとにデバイス登録 ID の HMAC-SHA256 を計算し、その結果を Base 64 形式に変換します。 登録グループを使用して派生デバイス キーを作成する方法の詳細については、「Symmetric key attestation (対称キーの構成証明)」のグループ登録に関するセクションを参照してください。

このチュートリアルの例では、次の 2 つのデバイス登録 ID を使用して、両方のデバイスのデバイス キーを計算します。 両方の登録 ID に、カスタム割り当てポリシーのサンプル コードを操作するために有効なサフィックスが付いています。

  • breakroom499-contoso-tstrsd-007
  • mainbuilding167-contoso-hpsd-088

Azure CLI 用の IoT 拡張機能には、派生デバイス キーを生成するための iot dps enrollment-group compute-device-key コマンドが用意されています。 このコマンドは、Windows ベースのシステムまたは Linux システムで、PowerShell または Bash シェルから使用できます。

--key 引数の値を、登録グループの主キーに置き換えます。

az iot dps enrollment-group compute-device-key --key <ENROLLMENT_GROUP_KEY> --registration-id breakroom499-contoso-tstrsd-007
az iot dps enrollment-group compute-device-key --key <ENROLLMENT_GROUP_KEY> --registration-id mainbuilding167-contoso-hpsd-088

注意

また、iot dps enrollment-group compute-device-keyコマンドに対称キー ではなく登録グループ ID を指定することもできます。 次に例を示します。

az iot dps enrollment-group compute-device-key -g contoso-us-resource-group --dps-name contoso-provisioning-service-1098 --enrollment-id contoso-custom-allocated-devices --registration-id breakroom499-contoso-tstrsd-007

シミュレートされたデバイスは、派生デバイス キーと各登録 ID を使って、対称キーの構成証明を実行します。

Azure IoT C SDK の開発環境を準備する

このセクションでは、Azure IoT C SDK のビルドに使用する開発環境を準備します。 この SDK には、シミュレートされたデバイス用のサンプル コードが含まれています。 このシミュレートされたデバイスでは、デバイスのブート シーケンス中にプロビジョニングを試行します。

このセクションは、Windows ベースのワークステーション向けです。 Linux の例については、「チュートリアル: 地域待機時間のためのプロビジョニング」の VM のセットアップに関するセクションを参照してください。

  1. CMake ビルド システムをダウンロードします。

    CMake のインストールを開始する前に、Visual Studio の前提条件 (Visual Studio と "C++ によるデスクトップ開発" ワークロード) が マシンにインストールされていることが重要です。 前提条件を満たし、ダウンロードを検証したら、CMake ビルド システムをインストールします。

  2. SDK の最新リリースのタグ名を見つけます。

  3. コマンド プロンプトまたは Git Bash シェルを開きます。 次のコマンドを実行して、最新リリースの C 用 Azure IoT Device SDK の GitHub リポジトリを複製します。 -b パラメーターの値として、前の手順で見つけたタグを使用します (例: lts_01_2023)。

    git clone -b <release-tag> https://github.com/Azure/azure-iot-sdk-c.git
    cd azure-iot-sdk-c
    git submodule update --init
    

    この操作は、完了するまでに数分かかります。

  4. git リポジトリのルート ディレクトリに cmake サブディレクトリを作成し、そのフォルダーに移動します。 azure-iot-sdk-c ディレクトリから次のコマンドを実行します。

    mkdir cmake
    cd cmake
    
  5. 次のコマンドを実行して、開発クライアント プラットフォームに固有の SDK のバージョンをビルドします。 シミュレートされたデバイスの Visual Studio ソリューションが cmake ディレクトリに生成されます。

    cmake -Dhsm_type_symm_key:BOOL=ON -Duse_prov_client:BOOL=ON  ..
    

    cmake で C++ コンパイラが見つからない場合は、コマンドの実行中にビルド エラーが発生している可能性があります。 これが発生した場合は、Visual Studio コマンド プロンプトでコマンドを実行してください。

    ビルドが成功すると、最後のいくつかの出力行は次のようになります。

    $ cmake -Dhsm_type_symm_key:BOOL=ON -Duse_prov_client:BOOL=ON  ..
    -- Building for: Visual Studio 15 2017
    -- Selecting Windows SDK version 10.0.16299.0 to target Windows 10.0.17134.
    -- The C compiler identification is MSVC 19.12.25835.0
    -- The CXX compiler identification is MSVC 19.12.25835.0
    
    ...
    
    -- Configuring done
    -- Generating done
    -- Build files have been written to: E:/IoT Testing/azure-iot-sdk-c/cmake
    

デバイスをシミュレートする

このセクションでは、前にセットアップした Azure IoT C SDK にある prov_dev_client_sample という名前のプロビジョニング サンプルを更新します。

このサンプル コードでは、Device Provisioning Service のインスタンスにプロビジョニング要求を送信するデバイス ブート シーケンスがシミュレートされます。 ブート シーケンスにより、トースター デバイスが認識され、カスタム割り当てポリシーを使って IoT ハブに割り当てられます。

  1. Azure portal で、Device Provisioning Service の [概要] タブを選択し、 [ID スコープ] の値を書き留めます。

    ポータルのブレードから Device Provisioning サービスのエンドポイント情報を抽出

  2. 前に CMake を実行して生成された azure_iot_sdks.sln ソリューション ファイルを Visual Studio で開きます。 ソリューション ファイルは次の場所にあります: azure-iot-sdk-c\cmake\azure_iot_sdks.sln

  3. Visual Studio の [ソリューション エクスプローラー] ウィンドウで、Provision_Samples フォルダーに移動します。 prov_dev_client_sample という名前のサンプル プロジェクトを展開します。 [ソース ファイル] を展開して、prov_dev_client_sample.c を開きます。

  4. 定数 id_scope を探し、以前にコピーした ID スコープの値で置き換えます。

    static const char* id_scope = "0ne00002193";
    
  5. 同じファイル内で main() 関数の定義を探します。 以下に示すように hsm_type 変数が SECURE_DEVICE_TYPE_SYMMETRIC_KEY に設定されていることを確認します。

    SECURE_DEVICE_TYPE hsm_type;
    //hsm_type = SECURE_DEVICE_TYPE_TPM;
    //hsm_type = SECURE_DEVICE_TYPE_X509;
    hsm_type = SECURE_DEVICE_TYPE_SYMMETRIC_KEY;
    
  6. main() 関数で、Prov_Device_Register_Device() の呼び出しを見つけます。 その呼び出しの直前に、Prov_Device_Set_Provisioning_Payload() を使用する次のコード行を追加し、プロビジョニング中にカスタム JSON ペイロードを渡します。 カスタム割り当て関数に与える情報を増やすためにこれを利用できます。 登録 ID を調べる代わりに、デバイスの種類を渡す目的でこれを使用することもできます。 DPS を使用したカスタム データ ペイロードの送受信の詳細については、「デバイスと DPS の間でペイロードを転送する方法」を参照してください。

    // An example custom payload
    const char* custom_json_payload = "{\"MyDeviceFirmwareVersion\":\"12.0.2.5\",\"MyDeviceProvisioningVersion\":\"1.0.0.0\"}";
    
    prov_device_result = Prov_Device_Set_Provisioning_Payload(prov_device_handle, custom_json_payload);
    if (prov_device_result != PROV_DEVICE_RESULT_OK)
    {
        (void)printf("\r\nFailure setting provisioning payload: %s\r\n", MU_ENUM_TO_STRING(PROV_DEVICE_RESULT, prov_device_result));
    }
    
  7. prov_dev_client_sample プロジェクトを右クリックし、[スタートアップ プロジェクトに設定] を選択します。

Contoso トースター デバイスをシミュレートする

  1. トースター デバイスをシミュレートするには、prov_dev_client_sample.c で、コメントになっている prov_dev_set_symmetric_key_info() の呼び出しを探します。

    // Set the symmetric key if using they auth type
    //prov_dev_set_symmetric_key_info("<symm_registration_id>", "<symmetric_Key>");
    

    関数呼び出しのコメントを解除し、プレースホルダーの値 (山かっこを含む) を、前に生成したトースター登録 ID と派生デバイスキーに置き換えます。 以下に示したキーの値 JC8F96eayuQwwz+PkE7IzjH2lIAjCUnAa61tDigBnSs= は、あくまで一例です。

    // Set the symmetric key if using they auth type
    prov_dev_set_symmetric_key_info("breakroom499-contoso-tstrsd-007", "JC8F96eayuQwwz+PkE7IzjH2lIAjCUnAa61tDigBnSs=");
    

    ファイルを保存します。

  2. Visual Studio のメニューで [デバッグ]>[デバッグなしで開始] の順に選択して、ソリューションを実行します。 プロジェクトをリビルドするよう求められたら、 [はい] を選択して、プロジェクトをリビルドしてから実行します。

    次の出力は、シミュレートされたトースター デバイスが正常に起動し、プロビジョニング サービス インスタンスに接続して、カスタム割り当てポリシーによってトースター IoT ハブに割り当てられる例です。

    Provisioning API Version: 1.8.0
    
    Registering Device
    
    Provisioning Status: PROV_DEVICE_REG_STATUS_CONNECTED
    Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING
    Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING
    
    Registration Information received from service: contoso-toasters-hub-1098.azure-devices.net, deviceId: breakroom499-contoso-tstrsd-007
    
    Press enter key to exit:
    

    次の出力に示すのは、トースター デバイスのために実行されているカスタム割り当て関数コードからのログ記録の出力例です。 トースター デバイスに対してハブが適切に選択されていることに注目してください。 コードに追加したカスタム JSON コンテンツが含まれる payload プロパティにも注意してください。 これは deviceRuntimeContext 内でコードで使用する目的でも利用できます。

    このログ記録は、ポータルの関数コードの下にある [ログ] をクリックすると使用できます。

    2022-08-03T20:34:41.178 [Information] Executing 'Functions.HttpTrigger1' (Reason='This function was programmatically called via the host APIs.', Id=12950752-6d75-4f41-844b-c253a6653d4f)
    2022-08-03T20:34:41.340 [Information] C# HTTP trigger function processed a request.
    2022-08-03T20:34:41.341 [Information] Request.Body:...
    2022-08-03T20:34:41.341 [Information] {"enrollmentGroup":{"enrollmentGroupId":"contoso-custom-allocated-devices","attestation":{"type":"symmetricKey"},"capabilities":{"iotEdge":false},"etag":"\"0000f176-0000-0700-0000-62eaad1e0000\"","provisioningStatus":"enabled","reprovisionPolicy":{"updateHubAssignment":true,"migrateDeviceData":true},"createdDateTimeUtc":"2022-08-03T17:15:10.8464255Z","lastUpdatedDateTimeUtc":"2022-08-03T17:15:10.8464255Z","allocationPolicy":"custom","iotHubs":["contoso-toasters-hub-1098.azure-devices.net","contoso-heatpumps-hub-1098.azure-devices.net"],"customAllocationDefinition":{"webhookUrl":"https://contoso-function-app-1098.azurewebsites.net/api/HttpTrigger1?****","apiVersion":"2021-10-01"}},"deviceRuntimeContext":{"registrationId":"breakroom499-contoso-tstrsd-007","currentIotHubHostName":"contoso-toasters-hub-1098.azure-devices.net","currentDeviceId":"breakroom499-contoso-tstrsd-007","symmetricKey":{},"payload":{"MyDeviceFirmwareVersion":"12.0.2.5","MyDeviceProvisioningVersion":"1.0.0.0"}},"linkedHubs":["contoso-toasters-hub-1098.azure-devices.net","contoso-heatpumps-hub-1098.azure-devices.net"]}
    2022-08-03T20:34:41.382 [Information] Response
    2022-08-03T20:34:41.398 [Information] {"iotHubHostName":"contoso-toasters-hub-1098.azure-devices.net","initialTwin":{"properties":{"desired":{"state":"ready","darknessSetting":"medium"}},"tags":{"deviceType":"toaster"}}}
    2022-08-03T20:34:41.399 [Information] Executed 'Functions.HttpTrigger1' (Succeeded, Id=12950752-6d75-4f41-844b-c253a6653d4f, Duration=227ms)
    

Contoso ヒート ポンプ デバイスをシミュレートする

  1. ヒート ポンプ デバイスをシミュレートするには、prov_dev_client_sample.cprov_dev_set_symmetric_key_info() の呼び出しを、同じようにヒート ポンプの登録 ID とデバイス派生キー (先ほど生成したもの) で更新します。 以下に示したキーの値 6uejA9PfkQgmYylj8Zerp3kcbeVrGZ172YLa7VSnJzg= も、あくまで一例です。

    // Set the symmetric key if using they auth type
    prov_dev_set_symmetric_key_info("mainbuilding167-contoso-hpsd-088", "6uejA9PfkQgmYylj8Zerp3kcbeVrGZ172YLa7VSnJzg=");
    

    ファイルを保存します。

  2. Visual Studio のメニューで [デバッグ]>[デバッグなしで開始] の順に選択して、ソリューションを実行します。 プロジェクトをリビルドするよう求められたら、 [はい] を選択して、プロジェクトをリビルドしてから実行します。

    次の出力は、シミュレートされたヒート ポンプ デバイスが正常に起動し、プロビジョニング サービス インスタンスに接続して、カスタム割り当てポリシーによって Contoso ヒート ポンプ IoT ハブに割り当てられる例です。

    Provisioning API Version: 1.8.0
    
    Registering Device
    
    Provisioning Status: PROV_DEVICE_REG_STATUS_CONNECTED
    Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING
    Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING
    
    Registration Information received from service: contoso-heatpumps-hub-1098.azure-devices.net, deviceId: mainbuilding167-contoso-hpsd-088
    
    Press enter key to exit:
    

カスタム割り当てポリシーのトラブルシューティング

次の表に、想定されるシナリオと、表示される可能性のある結果のエラー コードを示します。 この表は、Azure Functions でのカスタム割り当てポリシーのエラーのトラブルシューティングに利用してください。

シナリオ プロビジョニング サービスでの登録結果 プロビジョニング SDK の結果
Webhook から "200 OK" が返され、"iotHubHostName" が有効な IoT ハブ ホスト名に設定されている 結果の状態: 割り当て済み SDK からハブの情報と共に PROV_DEVICE_RESULT_OK が返される
Webhook から "200 OK" が返され、応答に "iotHubHostName" が存在するが、空の文字列または null が設定されている 結果の状態: 失敗

エラー コード:CustomAllocationIotHubNotSpecified (400208)
SDK から PROV_DEVICE_RESULT_HUB_NOT_SPECIFIED が返される
Webhook から "401 権限がありません" が返される 結果の状態: 失敗

エラー コード:CustomAllocationUnauthorizedAccess (400209)
SDK から PROV_DEVICE_RESULT_UNAUTHORIZED が返される
デバイスを無効にする個々の登録が作成された 結果の状態: 無効 SDK から PROV_DEVICE_RESULT_DISABLED が返される
Webhook からエラー コード 429 以上が返される DPS のオーケストレーションが複数回再試行される。 再試行ポリシーは現在以下の通り。

  - 再試行回数: 10
  - 初期間隔: 1 秒
  - 増分: 9 秒
SDK では、エラーが無視され、特定の期間内に別の状態の取得メッセージが送信される
Webhook からその他の状態コードが返される 結果の状態: 失敗

エラー コード:CustomAllocationFailed (400207)
SDK から PROV_DEVICE_RESULT_DEV_AUTH_ERROR が返される

リソースをクリーンアップする

このチュートリアルで作成したリソースを引き続き使用する場合は、リソースをそのままにしておいてください。 これ以上リソースを使用しない場合は、不要な課金を避けるために、次のステップに従って、このチュートリアルで作成したすべてのリソースを削除してください。

このステップでは、このチュートリアルの説明に従って contoso-us-resource-group という名前の同じリソース グループにすべてのリソースが作成されていることを前提にしています。

重要

リソース グループを削除すると、元に戻すことができません。 リソース グループとそこに含まれるすべてのリソースは完全に削除されます。 間違ったリソース グループやリソースをうっかり削除しないようにしてください。 IoT ハブを、保持したいリソースが含まれている既存のリソース グループ内に作成した場合は、リソース グループを削除するのではなく、IoT Hub リソースだけを削除してください。

名前でリソース グループを削除するには

  1. Azure portal にサインインし、 [リソース グループ] を選択します。

  2. [名前でフィルター] テキスト ボックスに、リソースが含まれているリソース グループの名前 contoso-us-resource-group を入力します。

  3. 結果一覧のリソース グループの右側で、 [...][リソース グループの削除] の順に選択します。

  4. リソース グループの削除の確認を求めるメッセージが表示されます。 確認のためにもう一度リソース グループの名前を入力し、 [削除] を選択します。 しばらくすると、リソース グループとそこに含まれているすべてのリソースが削除されます。

次のステップ

詳細については、「 カスタム割り当てポリシー」を参照してください