如何使用自定义分配策略

自定义分配策略让你能够对设备分配到 IoT 中心的方式进行更多地控制。 它是通过使用 Azure 函数中的自定义代码将设备分配到 IoT 中心来实现的。 设备预配服务将调用 Azure 函数代码,提供有关设备和注册的所有相关信息。 将执行函数代码并返回用于预配设备的 IoT 中心信息。

当设备预配服务提供的策略不能满足你的方案的要求时,通过使用自定义分配策略,可以定义你自己的分配策略。

例如,你可能想要检查设备在预配过程中所使用的证书,并根据证书属性将该设备分配到 IoT 中心。 或者,你可能在数据库中存储了设备的信息,并需要查询数据库以确定应将该设备分配到哪个 IoT 中心。

本文演示使用 C# 编写的 Azure 函数的自定义分配策略。 创建了两个新的 IoT 中心,分别表示 Contoso 烤箱分区 和 Contoso 热泵分区 。 请求预配的设备必须具有含以下后缀之一的注册 ID 才能被接受进行预配:

  • -contoso-tstrsd-007:Contoso 烤箱分区
  • -contoso-hpsd-088:Contoso 热泵分区

将基于注册 ID 上这些所需的后缀之一对设备进行预配。 将使用 Azure IoT C SDK 中包含的预配示例对这些设备进行模拟。

你将在本文中执行以下步骤:

  • 使用 Azure CLI 创建两个 Contoso 分区 IoT 中心(Contoso 烤箱分区 和 Contoso 热泵分区 )
  • 使用 Azure 函数为自定义分配策略创建新的组注册
  • 为两个设备模拟创建设备密钥。
  • 为 Azure IoT C SDK 设置开发环境
  • 模拟设备,以验证其是否根据自定义分配策略的示例代码进行预配。

如果没有 Azure 订阅,可在开始前创建一个试用帐户

先决条件

以下先决条件适用于 Windows 开发环境。 对于 Linux 或 macOS,请参阅 SDK 文档的准备开发环境中的相应部分。

可以使用本地 Azure CLI。

  • 如果需要,请安装 Azure CLI 来运行 CLI 参考命令。

  • 本地 Azure CLI,请了解如何安装 Azure CLI。 如果在 Windows 或 macOS 上运行,请考虑在 Docker 容器中运行 Azure CLI。 有关详细信息,请参阅如何在 Docker 容器中运行 Azure CLI

    • 通过使用 az login 命令登录到 Azure CLI。 若要完成身份验证过程,请遵循终端中显示的步骤。 有关其他登录选项,请参阅使用 Azure CLI 登录

    • 出现提示时,请在首次使用时安装 Azure CLI 扩展。 有关扩展详细信息,请参阅使用 Azure CLI 的扩展

    • 运行 az version 以查找安装的版本和依赖库。 若要升级到最新版本,请运行 az upgrade

创建预配服务和两个部门 IoT 中心

在本部分,使用 Azure CLI 创建预配服务和表示“Contoso 烤箱分区”和“Contoso 热泵分区”的两个 IoT 中心 。

提示

本文中使用的命令将在“中国北部”位置创建预配服务和其他资源。 我们建议在与你最靠近的区域中创建支持设备预配服务的资源。 若要查看可用位置的列表,可以运行 az provider show --namespace Microsoft.Devices --query "resourceTypes[?resourceType=='ProvisioningServices'].locations | [0]" --out table 命令,也可以转到Azure 状态页,在其中搜索“设备预配服务”。 在命令中,可以使用一个单词或多个单词的格式来指定位置,例如:chinanorth、chinaeast2 等。该值不区分大小写。 如果使用多个单词的格式来指定位置,请将值置于引号中,例如 -- location "China North"

  1. 在 Azure CLI 中,使用 az group create 命令创建资源组。 Azure 资源组是在其中部署和管理 Azure 资源的逻辑容器。

    以下示例在 chinanorth 区域中创建一个名为“contoso-us-resource-group”的资源组。 建议对本文中创建的所有资源使用该组。 此方法使你能够在完成后更为轻松地进行清理。

    az group create --name contoso-us-resource-group --location chinanorth
    
  2. 使用 Azure CLI 通过 az iot dps create 命令创建设备预配服务 (DPS)。 该预配服务将添加到 contoso-us-resource-group

    以下示例在 chinanorth 位置创建名为 contoso-provisioning-service-1098 的预配服务 。 必须使用唯一的服务名称。 在服务名称中的 1098 位置构成你自己的后缀。

    az iot dps create --name contoso-provisioning-service-1098 --resource-group contoso-us-resource-group --location chinanorth
    

    此命令可能需要花费几分钟时间完成。

  3. 在 Azure CLI 中,使用 az iot hub create 命令创建 Contoso 烤箱分区 IoT 中心。 IoT 中心将被添加到 contoso-us-resource-group 。

    以下示例在 chinanorth 位置创建名为 contoso-toasters-hub-1098 的 IoT 中心 。 必须使用唯一的中心名称。 在中心名称中的 1098 位置构成你自己的后缀。

    注意

    自定义分配策略的示例 Azure 函数代码需要中心名称中的子字符串 -toasters-。 请确保使用包含必需的 toasters 子字符串的名称。

    az iot hub create --name contoso-toasters-hub-1098 --resource-group contoso-us-resource-group --location chinanorth --sku S1
    

    此命令可能需要花费几分钟时间完成。

  4. 在 Azure CLI 中,使用 az iot hub create 命令创建 Contoso 热泵分区 IoT 中心。 此 IoT 中心也将被添加到 contoso-us-resource-group 。

    以下示例在 chinanorth 位置创建名为 contoso-heatpumps-hub-1098 的 IoT 中心 。 必须使用唯一的中心名称。 在中心名称中的 1098 位置构成你自己的后缀。

    注意

    自定义分配策略的示例 Azure 函数代码需要中心名称中的子字符串 -heatpumps-。 请确保使用包含必需的 heatpumps 子字符串的名称。

    az iot hub create --name contoso-heatpumps-hub-1098 --resource-group contoso-us-resource-group --location chinanorth --sku S1
    

    此命令可能需要花费几分钟时间完成。

  5. IoT 中心必须链接到 DPS 资源。

    运行下面的两个命令来获取你刚才创建的中心的连接字符串。 在每个命令中,将中心资源名称替换为你选择的名称:

    hubToastersConnectionString=$(az iot hub connection-string show --hub-name contoso-toasters-hub-1098 --key primary --query connectionString -o tsv)
    hubHeatpumpsConnectionString=$(az iot hub connection-string show --hub-name contoso-heatpumps-hub-1098 --key primary --query connectionString -o tsv)
    

    运行以下命令来将中心链接到 DPS 资源。 在每个命令中,将 DPS 资源名称替换为你选择的名称:

    az iot dps linked-hub create --dps-name contoso-provisioning-service-1098 --resource-group contoso-us-resource-group --connection-string $hubToastersConnectionString --location chinanorth
    az iot dps linked-hub create --dps-name contoso-provisioning-service-1098 --resource-group contoso-us-resource-group --connection-string $hubHeatpumpsConnectionString --location chinanorth
    

创建自定义分配函数

在本部分,你将创建一个实现自定义分配策略的 Azure 函数。 此函数根据设备的注册 ID 是包含字符串 -contoso-tstrsd-007 还是 -contoso-hpsd-088,来确定要将该设备注册到哪个部门 IoT 中心。 它还根据设备是烤箱还是热泵,来设置设备孪生的初始状态。

  1. 登录到 Azure 门户。 在主页中选择“+ 创建资源”。

  2. 在“搜索市场”搜索框中键入“函数应用”。 从下拉列表中选择“函数应用”,然后选择“创建”。

  3. 在“函数应用”创建页上的“基本信息”选项卡下,输入新函数应用的以下设置,然后选择“查看 + 创建”:

    资源组:选择“contoso-us-resource-group”以将本文中创建的所有资源保留在一起。

    函数应用名称:输入唯一函数应用名称。 本示例使用 contoso-function-app-1098

    发布:确认已选择“代码”。

    运行时堆栈:从下拉列表中选择“.NET Core”。

    版本:从下拉列表中选择“3.1”。

    区域:选择你的资源组所在的同一区域。 此示例使用“中国北部”。

    注意

    默认已启用 Application Insights。 本文不需要 Application Insights,但它可以帮助你了解和调查处理自定义分配时遇到的任何问题。 如果需要,可以禁用 Application Insights,方法是选择“监视”选项卡,然后对“启用 Application Insights”选择“否”。

    Create an Azure Function App to host the custom allocation function

  4. 在“摘要”页上,选择“创建”以创建函数应用。 部署可能需要几分钟的时间。 完成后,选择“转到资源”。

  5. 在函数应用“概述”页的左窗格中,单击“函数”,然后选择“+ 添加”以添加新函数。

  6. 在“添加函数”页上,单击“HTTP 触发器”,然后单击“添加”按钮。

  7. 在下一页中,单击“代码 + 测试”。 这允许你编辑名为 HttpTrigger1 的函数的代码。 run.csx 代码文件应该会打开供编辑。

  8. 引用所需的 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.16.3" />
              <PackageReference Include="Microsoft.Azure.Devices.Shared" Version="1.27.0" />
          </ItemGroup>  
      </Project>
      
    2. 单击位于代码编辑器上方的“上传”按钮,以上传“function.proj”文件。 上传后,在代码编辑器中使用下拉框选择该文件来验证内容。

  9. 请确保在代码编辑器中为 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. 在“添加注册组”中输入以下信息,然后选择“保存”按钮。

    组名称:输入 contoso-custom-allocated-devices

    证明类型:选择“对称密钥” 。

    自动生成密钥:此复选框应已处于选中状态。

    选择要如何将设备分配到中心:选择“自定义(使用 Azure Function)”。

    订阅:选择你在其中创建了 Azure 函数的订阅。

    函数应用:通过名称选择你的函数应用。 此示例中使用了 contoso-function-app-1098

    函数:选择 HttpTrigger1 函数。

    Add custom allocation enrollment group for symmetric key attestation

  4. 保存注册后,重新打开它,并记录“主键”。 必须先保存注册,才能生成密钥。 此密钥稍后将用于为模拟设备生成唯一设备密钥。

派生唯一设备密钥

在本部分,你将创建两个唯一的设备密钥。 一个密钥将用于模拟的烤箱设备。 另一个密钥将用于模拟的热泵设备。

若要生成设备密钥,请使用前面记下的“主密钥”来计算每个设备的设备注册 ID 的 HMAC-SHA256,并将结果转换为 Base64 格式。 有关使用注册组创建派生设备密钥的详细信息,请参阅对称密钥证明的组注册部分。

对于本文中的示例,使用以下两个设备注册 ID 并计算这两个设备的设备密钥。 这两个注册 ID 都具有有效的后缀,以与自定义分配策略的示例代码结合使用:

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

如果使用的是基于 Windows 的工作站,可以使用 PowerShell 生成派生的设备密钥,如以下示例中所示。

将“键” 值替换为前面记录的“主键” 。

$KEY='oiK77Oy7rBw8YB6IS6ukRChAw+Yq6GC61RMrPLSTiOOtdI+XDu0LmLuNm11p+qv2I+adqGUdZHm46zXAQdZoOA=='

$REG_ID1='breakroom499-contoso-tstrsd-007'
$REG_ID2='mainbuilding167-contoso-hpsd-088'

$hmacsha256 = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha256.key = [Convert]::FromBase64String($KEY)
$sig1 = $hmacsha256.ComputeHash([Text.Encoding]::ASCII.GetBytes($REG_ID1))
$sig2 = $hmacsha256.ComputeHash([Text.Encoding]::ASCII.GetBytes($REG_ID2))
$derivedkey1 = [Convert]::ToBase64String($sig1)
$derivedkey2 = [Convert]::ToBase64String($sig2)

echo "`n`n$REG_ID1 : $derivedkey1`n$REG_ID2 : $derivedkey2`n`n"
breakroom499-contoso-tstrsd-007 : JC8F96eayuQwwz+PkE7IzjH2lIAjCUnAa61tDigBnSs=
mainbuilding167-contoso-hpsd-088 : 6uejA9PfkQgmYylj8Zerp3kcbeVrGZ172YLa7VSnJzg=

模拟设备将使用含有每个注册 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 shell。 运行以下命令以克隆最新版本的 Azure IoT C SDK GitHub 存储库。 使用在上一步找到的标记作为 -b 参数的值:

    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 版本。 将在 cmake 目录中生成模拟设备的 Visual Studio 解决方案。

    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”的预配示例。

此示例代码模拟将预配请求发送到你的设备预配服务实例的设备启动序列。 启动序列将导致烤箱设备被识别,且使用自定义分配策略将其配置到 IoT 中心。

  1. 在 Azure 门户中,选择设备预配服务的“概述”选项卡,记下“ID 范围”的值 。

    Extract Device Provisioning Service endpoint information from the portal blade

  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 常量,将值替换为前面复制的“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. 右键单击“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.3.6
    
    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.cn, deviceId: breakroom499-contoso-tstrsd-007
    
    Press enter key to exit:
    

模拟 Contoso 热泵设备

  1. 若要模拟热泵设备,请使用热泵注册 ID 和之前生成的派生设备密钥更新 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.3.6
    
    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.cn, deviceId: mainbuilding167-contoso-hpsd-088
    
    Press enter key to exit:
    

自定义分配策略疑难解答

下表显示了预期场景以及可能遇到的结果错误代码。 使用此表来帮助你解决使用 Azure 函数时自定义分配策略失败的问题。

方案 预配服务的注册结果 预配 SDK 结果
Webhook 返回“200 正常”,其中“iotHubHostName”设置为有效的 IoT 中心主机名 结果状态:已分配 SDK 返回 PROV_DEVICE_RESULT_OK 和中心信息
Webhook 返回“200 正常”,响应中存在“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 中心资源本身,而不要删除资源组。

若要按名称删除资源组:

  1. 登录到 Azure 门户,然后选择“资源组”。

  2. 在“按名称筛选...”文本框中,键入包含资源的资源组名称“contoso-us-resource-group”

  3. 在结果列表中的资源组右侧,选择“...”,然后选择“删除资源组” 。

  4. 系统会要求确认是否删除该资源组。 再次键入资源组的名称进行确认,然后选择“删除” 。 片刻之后,将会删除该资源组及其包含的所有资源。

后续步骤