Tutorial: Usar as políticas de alocação personalizadas com o DPS (Serviço de Provisionamento de Dispositivos)

Políticas de alocação personalizada proporcionam a você mais controle sobre como os dispositivos são atribuídos a seus hubs IoT. Por meio de políticas de alocação personalizadas, você define suas políticas de alocação quando as políticas fornecidas pelo DPS (Serviço de Provisionamento de Dispositivos) no Hub IoT do Azure não atendem aos requisitos do seu cenário. Uma política de alocação personalizada é implementada em um webhook hospedado no Azure Functions e configurado em um ou mais registros individuais e/ou grupos de registro. Quando um dispositivo se registra no DPS usando uma entrada de registro configurada, o DPS chama o webhook para descobrir em qual hub IoT o dispositivo deve ser registrado e, opcionalmente, o estado inicial dele. Para saber mais, confira Noções básicas sobre políticas de alocação personalizadas.

Este tutorial demonstra uma política de alocação personalizada usando uma função do Azure escrita em C#. Os dispositivos são atribuídos a um dos dois hubs IoT que representam uma Divisão de Torradeiras da Contoso e uma Divisão de Bombas Térmicas da Contoso. Dispositivos solicitando provisionamento devem ter uma ID de registro com um dos sufixos a seguir para serem aceitos para o provisionamento:

  • -contoso-tstrsd-007 para a Divisão de Torradeiras da Contoso
  • -contoso-hpsd-088 para a Divisão de Bombas Térmicas da Contoso

Os dispositivos são simulados usando um exemplo de provisionamento incluído no SDK do Azure IoT C.

Neste tutorial, você executará as seguintes tarefas:

  • Usar a CLI do Azure para criar uma instância do DPS e criar e vincular dois Hubs IoT da divisão da Contoso (Divisão de Torradeiras da Contoso e Divisão de Bombas Térmicas da Contoso) a ela.
  • Crie uma função do Azure que implemente a política de alocação personalizada.
  • Criar um novo grupo de registro usa a Função do Azure para a política de alocação personalizada.
  • Crie chaves simétricas do dispositivo para dois dispositivos simulados.
  • Configure o ambiente de desenvolvimento para o SDK do Azure IoT C.
  • Simule os dispositivos e verifique se eles são provisionados de acordo com o código de exemplo na política de alocação personalizada.

Caso você não tenha uma assinatura do Azure, crie uma conta gratuita do Azure antes de começar.

Pré-requisitos

Os pré-requisitos a seguir são para um ambiente de desenvolvimento do Windows. Para Linux ou macOS, confira a seção apropriada em Preparar seu ambiente de desenvolvimento na documentação do SDK.

Criar o serviço de provisionamento e dois hubs IoT

Nesta seção, você usará o Azure Cloud Shell para criar um serviço de provisionamento e dois hubs IoT representando a Divisão de Torradeiras da Contoso e a Divisão de Bombas Térmicas da Contoso.

  1. Primeiro, defina variáveis de ambiente em seu workspace para simplificar os comandos neste tutorial.

    Os nomes de Hub IoT e DPS devem ser globalmente exclusivos. Substitua os espaços reservados SUFFIX pelos seus próprios valores.

    Além disso, o código da Função do Azure que você criar posteriormente neste tutorial procura hubs IoT que tenham -toasters- ou -heatpumps- em seus nomes. Se você alterar os valores sugeridos, use os nomes que contêm as subcadeias de caracteres necessárias.

    #!/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"
    

    Dica

    Os comandos usados neste tutorial criam recursos na localização oeste dos EUA por padrão. Recomendamos que você crie seus recursos na região mais próxima que dê suporte ao serviço de provisionamento de dispositivos. Você pode exibir uma lista de locais disponíveis acessando a página Status do Azure e pesquisando "Serviço de Provisionamento de Dispositivos". Nos comandos, os locais podem ser especificados em formato de uma ou várias palavras, por exemplo, westus, West US, WEST US, etc. O valor não diferencia maiúsculas de minúsculas.

  2. Use o comando az group create para criar um grupo de recursos do Azure. Um grupo de recursos do Azure é um contêiner lógico no qual os recursos do Azure são implantados e gerenciados.

    O exemplo a seguir cria um grupo de recursos. Recomendamos que você use um único grupo para todos os recursos criados neste tutorial. Essa abordagem tornará a limpeza mais fácil depois que você terminar.

    az group create --name $RESOURCE_GROUP --location $LOCATION
    
  3. Use o comando az iot dps create para criar uma instância do DPS (Serviço de Provisionamento de Dispositivos). O serviço de provisionamento é adicionado ao contoso-us-resource-group.

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

    Esse comando pode levar alguns minutos para ser concluído.

  4. Use o comando az iot hub create para criar o hub IoT da Divisão de Resistências da Contoso. O hub IoT é adicionado ao contoso-us-resource-group.

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

    Esse comando pode levar alguns minutos para ser concluído.

  5. Use o comando az iot hub create para criar o hub IoT da Divisão de Bombas Térmicas da Contoso. Esse hub IoT também é adicionado ao contoso-us-resource-group.

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

    Esse comando pode levar alguns minutos para ser concluído.

  6. Execute os dois comandos a seguir para obter as cadeias de conexão dos hubs que criou.

    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. Execute os comandos a seguir para vincular os hubs ao recurso de DPS. Substitua os espaços reservados pelas cadeias de conexão do hub da etapa anterior.

    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>
    

Criar a função de alocação personalizada

Nesta seção, você criará uma função do Azure que implementa sua política de alocação personalizada. Essa função decide em qual hub IoT divisional um dispositivo deve ser registrado com base no fato de sua ID de registro conter a cadeia de caracteres -contoso-tstrsd-007 ou -contoso-hpsd-088. Ela também define o estado inicial do dispositivo gêmeo com base no fato de o dispositivo ser uma torradeira ou uma bomba térmica.

  1. Entre no portal do Azure.

  2. Na caixa de pesquisa, pesquise e selecione Aplicativo de Funções.

  3. Selecione Criar ou Criar Aplicativo de Funções.

  4. Na página de criação do Aplicativo de Funções, na guia Noções Básicas, insira as seguintes configurações para seu novo aplicativo de funções e selecione Examinar + criar:

    Parâmetro Valor
    Assinatura Verifique se a assinatura em que você criou os recursos para este tutorial está selecionada.
    Grupo de Recursos Selecione o grupo de recursos criado na seção anterior. O padrão fornecido na seção anterior é contoso-us-resource-group.
    Nome do aplicativo de funções Forneça um nome para o aplicativo de funções.
    Deseja implantar código ou imagem de contêiner? Código
    Pilha de Runtime .NET
    Versão Selecione qualquer versão do modelo em processo.
    Região Selecione uma região próxima a você.

    Observação

    Por padrão, o Application Insights está habilitado. O Application Insights não é necessário para este tutorial, mas pode ajudar você a entender e investigar os problemas encontrados com a alocação personalizada. Se preferir, você poderá desabilitar o Application Insights selecionando a guia Monitoramento e escolhendo Não para Habilitar o Application Insights.

    Captura de tela que mostra o formulário Criar Aplicativo de Funções no portal do Azure.

  5. Na guia Revisar + criar, selecione Criar para criar o aplicativo de funções.

  6. A implantação pode levar vários minutos. Quando ela for concluída, selecione Ir para o recurso.

  7. No painel esquerdo da página Visão geral do aplicativo de funções, selecioneCriar função.

    Captura de tela que mostra a seleção da opção para criar a função no portal do Azure.

  8. Na página Criar função, selecione o modelo de Gatilho HTTP e selecione Avançar.

  9. Na guia Detalhes do modelo, selecione Anônimo como o nível de Autorização e, em seguida, selecioneCriar.

    Captura de tela que mostra a definição do nível de autorização como anônimo.

    Dica

    Se você mantiver o nível de autorização como Função, precisará configurar seus registros DPS com a chave de API de função. Para obter mais informações, confira Gatilho HTTP do Azure Functions.

  10. Quando a função HttpTrigger1 for aberta, selecione Codificar + Testar no painel esquerdo. Isso permite que você edite o código da função. O arquivo de código run.csx deve ser aberto para edição.

  11. Faça referência aos pacotes necessários do NuGet. Para criar o dispositivo gêmeo inicial, a função de alocação personalizada usa classes definidas em dois pacotes NuGet que devem ser carregados no ambiente de hospedagem. Com o Azure Functions, os pacotes NuGet são referenciados usando um arquivo function.proj. Nesta etapa, você salva e carrega um arquivo function.proj para os assemblies necessários. Para obter mais informações, confira Usar pacotes NuGet com o Azure Functions.

    1. Copie as linhas a seguir em seu editor favorito e salve o arquivo em seu computador como 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. Selecione o botão Carregar, localizado acima do editor de código, para carregar seu arquivo function.proj. Após o upload, selecione o arquivo no editor de código usando a caixa suspensa para verificar o conteúdo.

    3. Selecione o arquivo function.proj no editor de código e verifique o conteúdo dele. Se o arquivo function.proj estiver vazio, copie as linhas acima no arquivo e salve-o. (Às vezes, o upload cria o arquivo sem carregar o conteúdo.)

  12. Lembre-se de selecionar run.csx para HttpTrigger1 no editor de código. Substitua o código da função HttpTrigger1 pelo seguinte código e selecione Salvar:

    #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;}
    }
    

Criar o registro

Nesta seção, você criará um novo grupo de registro que usa a política de alocação personalizada. Para simplificar, este tutorial usa o Atestado de chave simétrica com o registro. Para uma solução mais segura, considere usar o Atestado de certificado X.509 com uma cadeia de confiança.

  1. Entre no portal do Azure e navegue até instância do Serviço de Provisionamento de Dispositivos.

  2. Selecione Gerenciar registros na seção Configurações do menu de navegação.

  3. Selecione Adicionar grupo de registros.

  4. Na guia Registro + provisionamento da página Adicionar grupo de registro, forneça as seguintes informações para configurar os detalhes do grupo de registro:

    Campo Descrição
    Atestado Selecione Chave simétrica como o Mecanismo de atestado.
    Configurações de chave simétrica Marque a caixa Gerar chaves simétricas automaticamente.
    Nome do grupo Digitecontoso-custom-allocated-devices como nome do grupo.
    Status do provisionamento Marque a caixa Habilitar este registro.
  5. Selecione Próximo: hubs IoT.

  6. Na guia hubs IoT da página Adicionar grupo de registro, forneça as seguintes informações para determinar para quais hubs IoT o grupo de registro pode provisionar dispositivos:

    Campo Descrição
    Hubs IoT de destino Selecione um ou mais dos hubs IoT vinculados ou adicione um novo link a um hub IoT.
    Política de alocação Selecione Personalizado (Usar o Azure Functions) Selecione Selecionar função do Azure e siga os prompts para selecionar a função que você criou para este tutorial.
  7. Selecione Examinar + criar.

  8. Na guia Examinar e criar, verifique todas as suas entradas e selecione Criar.

Após salvar o registro, abra-o novamente e anote a Chave primária. Para que as chaves sejam geradas, é preciso primeiro salvar o registro. Essa chave é usada para gerar chaves de dispositivo exclusivas para dispositivos simulados na próxima seção.

Derivar chaves de dispositivo exclusivas

Os dispositivos não usam a chave simétrica primária do grupo de registros diretamente. Em vez disso, você usa a chave primária para derivar uma chave de dispositivo para cada dispositivo. Nesta seção, você criará duas chaves de dispositivo exclusivas. Uma chave é usada para um dispositivo de torradeira simulado. A outra chave é usada para um dispositivo de bomba de calor simulado.

Para derivar a chave do dispositivo, use a Chave Primária do grupo de registro que você anotou anteriormente para calcular o HMAC-SHA256 da ID de registro do dispositivo para cada dispositivo e converter o resultado no formato Base 64. Para obter mais informações sobre como criar chaves de dispositivo derivadas com grupos de registro, veja a seção de registros de grupo de Atestado de chave simétrica.

Para o exemplo neste tutorial, use as duas IDs de registro de dispositivo a seguir e compute uma chave de dispositivo para ambos os dispositivos. As duas IDs de registro têm um sufixo válido para trabalhar com o código de exemplo para a política de alocação personalizada:

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

A extensão de IoT para a CLI do Azure fornece o comando iot dps enrollment-group compute-device-key para gerar chaves de dispositivo derivadas. Esse comando pode ser usado em sistemas baseados no Windows ou no Linux, no PowerShell ou de um shell do Bash.

Substitua o valor do argumento --key pela Chave Primária do seu grupo de registro.

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

Observação

Você também pode fornecer a ID do grupo de registros em vez da chave simétrica para o comando iot dps enrollment-group compute-device-key. Por exemplo:

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

Os dispositivos simulados usam as chaves de dispositivo derivadas com cada ID de registro para executar o atestado de chave simétrica.

Preparar um ambiente de desenvolvimento do SDK de C do IoT do Azure

Nesta seção, você preparará o ambiente de desenvolvimento usado para criar o SDK de C do IoT do Azure. O SDK inclui o código de exemplo para o dispositivo simulado. Este dispositivo simulado tentará realizar provisionamento durante a sequência de inicialização do dispositivo.

Esta seção é voltada para uma estação de trabalho baseada em Windows. Para obter um exemplo do Linux, confira a preparação das VMs em Tutorial: provisionar para latência geográfica.

  1. Baixe o sistema de build CMake.

    É importante que os pré-requisitos do Visual Studio (Visual Studio e a carga de trabalho de "Desenvolvimento para Desktop com C++") estejam instalados no computador, antes da instalação de CMake. Após a instalação dos pré-requisitos e verificação do download, instale o sistema de compilação CMake.

  2. Localize o nome da tag para a versão mais recente do SDK.

  3. Abra um prompt de comando ou o shell Bash do Git. Execute os seguintes comandos para clonar a última versão do repositório do GitHub do SDK do dispositivo IoT do Azure para C: Use a tag que você encontrou na etapa anterior como o valor para o parâmetro -b, por exemplo: 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
    

    Essa operação deve demorar alguns minutos.

  4. Crie um subdiretório cmake no diretório raiz do repositório git e navegue até essa pasta. Execute os seguintes comandos do diretório azure-iot-sdk-c:

    mkdir cmake
    cd cmake
    
  5. Execute o comando a seguir, que cria uma versão do SDK específica para a plataforma cliente de desenvolvimento. Uma solução do Visual Studio para o dispositivo simulado será gerada no diretório cmake.

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

    Se cmake não conseguir encontrar o compilador do C++, você poderá obter erros de build ao executar o comando. Se isso acontecer, tente executar o comando no prompt de comando do Visual Studio.

    Após o sucesso do build, as últimas linhas de saída são semelhantes à seguinte saída:

    $ 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
    

Simular os dispositivos

Nesta seção, você atualizará um exemplo de provisionamento denominado prov_dev_client_sample localizado no SDK de C do IoT do Azure configurado anteriormente.

Esse código de exemplo simula uma sequência de inicialização do dispositivo que envia a solicitação de provisionamento à sua instância do Serviço de Provisionamento de Dispositivos. A sequência de inicialização faz com que o dispositivo da torradeira seja reconhecido e atribuído ao hub IoT usando a política de alocação personalizada.

  1. No portal do Azure, selecione a guia Visão Geral de seu Serviço de Provisionamento de Dispositivos e anote o valor de Escopo da ID.

    Extrair informações do ponto de extremidade do Serviço de Provisionamento de Dispositivo na folha do portal

  2. No Visual Studio, abra o arquivo de solução azure_iot_sdks.sln, que foi gerado pela execução de CMake anteriormente. O arquivo de solução deve estar no seguinte local: azure-iot-sdk-c\cmake\azure_iot_sdks.sln.

  3. Na janela Gerenciador de Soluções do Visual Studio, navegue até a pasta Provisionar_Exemplos. Expanda o projeto de exemplo chamado prov_dev_client_sample. Expanda Arquivos de Origem e abra prov_dev_client_sample.c.

  4. Localize a constante id_scope e substitua o valor pelo seu valor de Escopo de ID copiado anteriormente.

    static const char* id_scope = "0ne00002193";
    
  5. Encontre a definição da função main() no mesmo arquivo. Certifique-se de que a variável hsm_type está configurada para SECURE_DEVICE_TYPE_SYMMETRIC_KEY, conforme mostrado abaixo:

    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. Na função main(), localize a chamada para Prov_Device_Register_Device(). Logo antes dessa chamada, adicione as linhas de código a seguir que usam Prov_Device_Set_Provisioning_Payload() para passar um conteúdo JSON personalizado durante o provisionamento. Isso pode ser usado para fornecer mais informações às suas funções de alocação personalizadas. Isso também pode ser usado para passar o tipo de dispositivo em vez de examinar a ID de registro. Para obter mais informações sobre como enviar e receber cargas de dados personalizadas com o DPS, confira Como transferir cargas entre dispositivos e 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. Clique com botão direito do mouse no projeto prov_dev_client_sample e selecione Definir como Projeto de Inicialização.

Simular o dispositivo de resistência da Contoso

  1. Para simular o dispositivo de resistência, localize a chamada para prov_dev_set_symmetric_key_info() em prov_dev_client_sample.c que está comentado.

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

    Remova a marca de comentário da chamada de função e substitua os valores de espaço reservado (incluindo os colchetes angulares) pela ID de registro da resistência e a chave de dispositivo derivada gerada anteriormente. O valor da chave JC8F96eayuQwwz+PkE7IzjH2lIAjCUnAa61tDigBnSs= mostrado abaixo é fornecido apenas como um exemplo.

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

    Salve o arquivo.

  2. No menu do Visual Studio, selecione Depurar>Iniciar sem depuração para executar a solução. No prompt para recompilar o projeto, selecione Sim para recompilar o projeto antes da execução.

    A seguinte saída é um exemplo do dispositivo torradeira simulado sendo inicializado com sucesso e se conectando à instância do serviço de provisionamento a ser atribuído ao hub IoT da torradeira pela política de alocação personalizada:

    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:
    

    A saída a seguir é um exemplo de registro em log da saída do código da função de alocação personalizada em execução para o dispositivo torradeira. Observe que um hub foi selecionado com êxito para um dispositivo de resistência. Observe também a propriedade payload que contém o conteúdo JSON personalizado que você adicionou ao código. Ele está disponível para o seu código usar dentro do deviceRuntimeContext.

    Esse log está disponível clicando em Logs no código de função no portal:

    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)
    

Simular o dispositivo de bomba térmica da Contoso

  1. Para simular o dispositivo de bomba térmica, atualize a chamada para prov_dev_set_symmetric_key_info() em prov_dev_client_sample.c novamente com a ID de registro de bomba térmica e a chave do dispositivo derivada gerada anteriormente. O valor de chave 6uejA9PfkQgmYylj8Zerp3kcbeVrGZ172YLa7VSnJzg= mostrado abaixo também é fornecido apenas como um exemplo.

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

    Salve o arquivo.

  2. No menu do Visual Studio, selecione Depurar>Iniciar sem depuração para executar a solução. No prompt para recompilar o projeto, selecione Sim para recompilar o projeto antes da execução.

    A seguinte saída é um exemplo do dispositivo de bomba térmica simulado sendo inicializado com sucesso e se conectando à instância do serviço de provisionamento a ser atribuído ao Hub IoT de bombas térmicas pela política de alocação personalizada:

    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:
    

Solucionar problemas de políticas de alocação personalizadas

A tabela a seguir mostra cenários esperados e os códigos de erro de resultados que podem ser recebidos. Use esta tabela para ajudar a solucionar problemas de falhas de política de alocação personalizada com o Azure Functions.

Cenário Resultado de registro do serviço de provisionamento Resultados do SDK de provisionamento
O webhook retorna 200 OK com 'iotHubHostName' definido como um nome de host do Hub IoT válido Status do resultado: Atribuído O SDK retorna PROV_DEVICE_RESULT_OK juntamente com informações de hub
O webhook retorna 200 OK com 'iotHubHostName' presente na resposta, mas definido como uma cadeia de caracteres vazia ou nula Status do resultado: Com falha

Código de erro: CustomAllocationIotHubNotSpecified (400208)
O SDK retorna PROV_DEVICE_RESULT_HUB_NOT_SPECIFIED
O webhook retorna 401 Não Autorizado Status do resultado: Com falha

Código de erro: CustomAllocationUnauthorizedAccess (400209)
O SDK retorna PROV_DEVICE_RESULT_UNAUTHORIZED
Um registro individual foi criado para desabilitar o dispositivo Status do resultado: Desabilitado O SDK retorna PROV_DEVICE_RESULT_DISABLED
O webhook retorna o código de erro >= 429 A Orquestração do DPS tentará novamente várias vezes. A política de repetição atualmente é:

  - Contagem de repetições: 10
  – Intervalo inicial: 1 seg
  – Incremento: 9 s
O SDK ignorará o erro e enviará outra mensagem de obtenção de status no tempo especificado
O webhook retorna qualquer outro código de status Status do resultado: Com falha

Código de erro: CustomAllocationFailed (400207)
O SDK retorna PROV_DEVICE_RESULT_DEV_AUTH_ERROR

Limpar os recursos

Caso planeje continuar a trabalhar com recursos criados neste tutorial, você poderá mantê-los. Caso contrário, continue usando as etapas a seguir para excluir todos os recursos criados por este tutorial, a fim de evitar alterações desnecessárias.

As etapas aqui supõem que você criou todos os recursos neste tutorial, conforme instruído no mesmo grupo de recursos chamado contoso-us-resource-group.

Importante

A exclusão de um grupo de recursos é irreversível. O grupo de recursos e todos os recursos contidos nele são excluídos permanentemente. Não exclua acidentalmente grupo de recursos ou recursos incorretos. Caso tenha criado o Hub IoT dentro de um grupo de recursos existente que contém recursos que você deseja manter, exclua apenas o próprio recurso do Hub IoT em vez de excluir o grupo de recursos.

Para excluir o grupo de recursos por nome:

  1. Entre no portal do Azure e selecione Grupos de recursos.

  2. Na caixa de texto Filtrar por nome..., digite o nome do grupo de recursos que contém seus recursos, contoso-us-resource-group.

  3. À direita do seu grupo de recursos, na lista de resultados, selecione ... e Excluir grupo de recursos.

  4. Você receberá uma solicitação para confirmar a exclusão do grupo de recursos. Digite o nome do grupo de recursos novamente para confirmar e selecione Excluir. Após alguns instantes, o grupo de recursos, e todos os recursos contidos nele, serão excluídos.

Próximas etapas

Para saber mais sobre políticas de alocação personalizadas, confira