教學課程:搭配裝置布建服務使用自定義配置原則 (DPS)

自定義配置原則可讓您更充分掌控如何將裝置指派給IoT中樞。 使用自訂配置原則時,當 Azure IoT 中樞 裝置佈建服務 (DPS) 所提供的原則不符合案例的需求時,您可以定義自己的配置原則。 自定義配置原則會在裝載於 Azure FunctionsWebhook 中實作,並在一或多個個別註冊和/或註冊群組上設定。 當裝置使用設定的註冊專案向 DPS 註冊時,DPS 會呼叫 Webhook,以找出裝置應該註冊到哪些 IoT 中樞,並選擇性地註冊其初始狀態。 若要深入瞭解,請參閱 瞭解自定義配置原則

本教學課程示範使用以 C# 撰寫的 Azure 函式來示範自定義配置原則。 裝置會指派給兩個IoT中樞之一 ,代表 Contoso 烤箱部門Contoso 熱泵部門。 要求布建的裝置必須具有下列其中一個後綴的註冊標識碼,才能接受布建:

  • -contoso-tstrsd-007 for the Contoso Toasters Division
  • -contoso-hpsd-088 for the Contoso Heat Pumps Division

裝置是使用 Azure IoT C SDK 中包含的布建範例來模擬。

在本教學課程中,您將執行下列動作:

  • 使用 Azure CLI 建立 DPS 實例,並建立兩個 Contoso 部門 IoT 中樞(Contoso 烤箱部門和 Contoso 熱泵部門)與其連結。
  • 建立實作自定義配置原則的 Azure 函式。
  • 建立新的註冊群組會針對自定義配置原則使用 Azure 函式。
  • 為兩個模擬裝置建立裝置對稱密鑰。
  • 設定 Azure IoT C SDK 的開發環境。
  • 模擬裝置,並確認它們已根據自定義配置原則中的範例程式代碼進行布建。

如果您沒有 Azure 訂閱,請在開始之前,先建立 Azure 免費帳戶

必要條件

下列必要條件適用於 Windows 開發環境。 針對 Linux 或 macOS,請參閱 SDK 檔中準備開發環境的適當章節

建立布建服務和兩個IoT中樞

在本節中,您會使用 Azure Cloud Shell 來建立布建服務和兩個 IoT 中樞,代表 Contoso 烤箱部門Contoso 熱泵部門

  1. 首先,在您的工作區中設定環境變數,以簡化本教學課程中的命令。

    DPS 和 IoT 中樞 名稱必須是全域唯一的。 將 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"
    

    提示

    本教學課程中使用的命令預設會在美國西部位置建立資源。 建議您在最接近支援裝置布建服務的區域中建立資源。 您可以移至 [Azure 狀態 ] 頁面並搜尋 「裝置布建服務」,以檢視可用位置的清單。 在命令中,可以單字或多字格式指定位置;例如:westus、美國西部、美國西部等。值不區分大小寫。

  2. 使用 az group create 命令來建立 Azure 資源群組。 Azure 資源群組是在其中部署與管理 Azure 資源的邏輯容器。

    下列範例會建立資源群組。 建議您針對本教學課程中建立的所有資源使用單一群組。 這個方法可讓您在完成之後更容易清除。

    az group create --name $RESOURCE_GROUP --location $LOCATION
    
  3. 使用 az iot dps create 命令來建立裝置布建服務 (DPS) 的實例。 布建服務會新增至 contoso-us-resource-group

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

    此命令可能需要幾分鐘的時間才能完成。

  4. 使用 az iot hub create 命令來建立 Contoso Toasters Division 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 Heat Pumps Division IoT 中樞。 此 IoT 中樞也會新增至 contoso-us-resource-group

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

    此命令可能需要幾分鐘的時間才能完成。

  6. 執行下列兩個命令,以取得您所建立中樞的 連接字串。

    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 函式。 此函式會根據裝置的註冊標識碼是否包含字串 -contoso-tstrsd-007-contoso-hpsd-088,決定裝置應該註冊的部門 IoT 中樞。 它也會根據裝置是烤箱或熱泵,設定裝置對應項的初始狀態。

  1. 登入 Azure 入口網站

  2. 在搜尋方塊中,搜尋並選取 [函式應用程式]。

  3. 選取 [建立] 或 [建立函數應用程式]。

  4. 在 [函式應用程式建立] 頁面的 [基本] 索引卷標底下,輸入新函式應用程式的下列設定,然後選取 [檢閱 + 建立]:

    參數
    訂用帳戶 請確定您已選取您為此教學課程建立資源的訂用帳戶。
    資源群組 選取您在上一節中建立的資源群組。 上一節中提供的預設值是 contoso-us-resource-group
    函數應用程式名稱 提供函式應用程式的名稱。
    您要部署程式碼或容器映像嗎? 程式碼
    執行階段堆疊 .NET
    版本 選取任何 進程內模型 版本。
    區域 選取接近您的區域。

    注意

    根據預設,會啟用Application Insights。 本教學課程不需要Application Insights,但可能有助於瞭解並調查您在自定義配置中遇到的任何問題。 如果您想要的話,您可以選取 [監視] 索引標籤,然後針對 [啟用 Application Insights] 選取 [] 來停用 Application Insights

    顯示 Azure 入口網站 中 [建立函式應用程式] 表單的螢幕快照。

  5. 在 [ 檢閱 + 建立] 索引標籤上,選取 [建立 ] 以建立函式應用程式。

  6. 部署可能需要幾分鐘的時間。 完成時,請選取 [移至資源]。

  7. 在函式應用程式 [概觀 ] 頁面的左窗格中,選取 [ 建立函式]。

    顯示選取選項以在 Azure 入口網站 中建立函式的螢幕快照。

  8. 在 [ 建立函式 ] 頁面上,選取 [HTTP 觸發程式 ] 範本,然後選取 [ 下一步]。

  9. 在 [範本詳細數據] 索引標籤上,選取 [匿名] 作為 [授權層級],然後選取 [建立]。

    顯示將授權層級設定為匿名的螢幕快照。

    提示

    如果您將授權層級保留為 式,則必須使用函式 API 金鑰來設定 DPS 註冊。 如需詳細資訊,請參閱 Azure Functions HTTP 觸發程式

  10. 當 HttpTrigger1 函式開啟時,請選取左窗格上的 [程序代碼 + 測試]。 這可讓您編輯函式的程序代碼。 應該開啟 run.csx 程式代碼檔案進行編輯。

  11. 參考必要的 NuGet 套件。 若要建立初始裝置對應項,自定義配置函式會使用必須在裝載環境中載入兩個 NuGet 套件中所定義的類別。 使用 Azure Functions 時,NuGet 套件會使用 function.proj 檔案來參考。 在此步驟中,您會儲存並上傳 必要元件的 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. 請確定已在程式代碼編輯器中選取 [HttpTrigger1] 的 run.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 入口網站 並流覽至您的裝置布建服務實例。

  2. 從導覽功能表的 [設定] 區段中選取 [管理註冊]。

  3. 選取 [ 新增註冊群組]。

  4. 在 [新增註冊群組] 頁面的 [註冊 + 布建] 索引卷標上,提供下列資訊來設定註冊群組詳細數據:

    欄位 描述
    認證 選取 [對稱金鑰 ] 作為 證明機制
    對稱金鑰設定 核取 [ 自動 產生對稱金鑰] 方塊。
    群組名稱 輸入 contoso-custom-allocated-devices 作為組名。
    布建狀態 核取 [ 啟用此註冊 ] 方塊。
  5. 選取 [ 下一步:IoT 中樞]。

  6. 在 [新增註冊群組] 頁面的 [IoT 中樞] 索引標籤上,提供下列資訊來判斷註冊群組可以布建裝置的 IoT 中樞:

    欄位 描述
    目標IoT中樞 選取一或多個連結的IoT中樞,或將新連結新增至IoT中樞。
    配置原則 選取 [自定義] [使用 Azure 函式]。 選取 [ 選取 Azure 函式],然後依照提示選取您為此教學課程建立的函式。
  7. 選取 [檢閱 + 建立]。

  8. 在 [ 檢閱 + 建立] 索引標籤上,確認您的所有值,然後選取 [ 建立]。

儲存註冊之後,請重新開啟它,並記下 主要密鑰。 您必須先儲存註冊,才能產生密鑰。 此金鑰用於在下一節中產生模擬裝置的唯一裝置金鑰。

衍生唯一裝置金鑰

裝置不會直接使用註冊群組的主要對稱密鑰。 相反地,您會使用主鍵來衍生每個裝置的裝置密鑰。 在本節中,您會建立兩個唯一的裝置密鑰。 仿真的烤箱裝置使用一個密鑰。 另一個金鑰用於模擬熱泵裝置。

若要衍生裝置密鑰,您可以使用您稍早注意到的註冊群組 主要密鑰 ,計算 每個裝置的裝置註冊標識碼 HMAC-SHA256 ,並將結果轉換成 Base 64 格式。 如需使用註冊群組建立衍生裝置密鑰的詳細資訊,請參閱對稱密鑰證明群組註冊一節。

在本教學課程的範例中,請使用下列兩個裝置註冊標識碼,並計算這兩個裝置的裝置密鑰。 這兩個註冊標識碼都有有效的後綴,可與自定義配置原則的範例程式代碼搭配使用:

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

Azure CLI 的IoT擴充功能提供 iot dps enrollment-group compute-device-key 用來產生衍生裝置密鑰的命令。 您可以從 PowerShell 或 Bash 殼層,在 Windows 或 Linux 系統上使用此命令。

將自變數的值取代為註冊群組的主--key

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

注意

您也可以提供註冊群組標識碼,而不是命令的 iot dps enrollment-group compute-device-key 對稱密鑰。 例如:

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

模擬裝置會使用具有每個註冊標識碼的衍生裝置密鑰來執行對稱密鑰證明。

準備 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 殼層。 執行下列命令來複製最新版的 Azure IoT 裝置 SDK for C 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
    

模擬裝置

在本節中,您會更新名為 prov_dev_client_sample 的布建範例,此範例位於您先前設定的 Azure IoT C SDK 中。

此範例程式代碼會模擬將布建要求傳送至裝置布建服務實例的裝置開機順序。 開機順序會導致使用自定義配置原則辨識和指派至IoT中樞的烤箱裝置。

  1. 在 Azure 入口網站 中,選取裝置布建服務的 [概觀] 索引標籤,並記下 [標識符範圍] 值。

    從入口網站刀鋒視窗擷取裝置布建服務端點資訊

  2. 在 Visual Studio 中 ,開啟稍早執行 CMake 所產生的azure_iot_sdks.sln 方案檔。 方案檔應位於下列位置: 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尋找常數,並將值取代為您稍早複製的標識符範圍值。

    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 承載。 這可用來提供自定義配置函式的詳細資訊。 這也可以用來傳遞裝置類型,而不是檢查註冊標識符。 如需使用 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>");
    

    取消批注函式呼叫,並將佔位元值(包括角括弧)取代為您先前產生的烤箱註冊標識碼和衍生裝置密鑰。 機碼值 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:
    

    下列輸出是針對烤箱裝置執行的自定義配置函式程式代碼記錄輸出範例。 請注意,已成功為烤箱裝置選取中樞。 另請注意 payload 屬性,其中包含您新增至程式代碼的自定義 JSON 內容。 這可供程式代碼在中使用 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.c 中的 呼叫prov_dev_set_symmetric_key_info()。 索引鍵值 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 會傳回回應中存在的 『iotHubHostName』 的 200 OK,但設定為空字串或 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 中樞 資源本身,而不是刪除資源群組。

若要依名稱移除資源群組:

  1. 登入 Azure 入口網站,然後選取 [資源群組]

  2. 在 [ 依名稱篩選... ] 文本框中,輸入包含您資源 的資源群組名稱 contoso-us-resource-group

  3. 在結果清單中的資源群組右側,選取 [...],然後刪除資源群組

  4. 系統會要求您確認刪除資源群組。 再次輸入您的資源組名以確認,然後選取 [ 刪除]。 幾分鐘后,資源群組及其所有自主資源都會被刪除。

下一步

若要深入瞭解自定義配置原則,請參閱