Tutorial: Uso de directivas de asignación personalizadas con Device Provisioning Service (DPS)

Las directivas de asignación personalizadas ofrece más control sobre la forma en que se asignan los dispositivos a los centro de IoT. Las directivas de asignación personalizadas le permiten definir sus propias directivas de asignación cuando las directivas proporcionadas por Azure IoT Hub Device Provisioning Service (DPS) no cumplan los requisitos de su escenario. Una directiva de asignación personalizada se implementa en un webhook hospedado en Azure Functions y se configura en una o varias inscripciones individuales o grupos de inscripción. Cuando un dispositivo se registra en DPS mediante una entrada de inscripción configurada, DPS llama al webhook para averiguar en qué centro de IoT se debe registrar el dispositivo y, opcionalmente, su estado inicial. Para más información, consulte Descripción de las directivas de asignación personalizadas.

En este tutorial se muestra una directiva de asignación personalizada mediante una función de Azure escrita en C#. Los dispositivos se asignan a uno de los dos centros de IoT que representan un departamento de tostadoras de Contoso y un departamento de bombas de calor de Contoso. Los dispositivos que soliciten aprovisionamiento deben tener un identificador de registro con uno de los siguientes sufijos para que se acepte el aprovisionamiento:

  • -contoso-tstrsd-007 para el departamento de tostadoras de Contoso
  • -contoso-hpsd-088 para el departamento de bombas de calor Contoso

Los dispositivos se simulan mediante un ejemplo de aprovisionamiento incluido en el SDK de Azure IoT para C.

En este tutorial, realizará las siguientes tareas:

  • Use la CLI de Azure para crear una instancia de DPS y para crear y vincular dos centros de IoT para departamentos de Contoso (Departamento de tostadoras de Contoso y Departamento de bombas de calor de Contoso).
  • Cree una función de Azure que implemente la directiva de asignación personalizada.
  • Cree un grupo de inscripciones que use la función de Azure para la directiva de asignación personalizada.
  • Cree claves simétricas de dispositivo para dos dispositivos simulados.
  • Configure el entorno de desarrollo del SDK de Azure IoT para C.
  • Simule los dispositivos y compruebe que están aprovisionados según el código de ejemplo de la directiva de asignación personalizada.

Si no tiene una suscripción a Azure, cree una cuenta gratuita de Azure antes de empezar.

Prerrequisitos

Los siguientes requisitos previos corresponden a un entorno de desarrollo de Windows. En el caso de Linux o macOS, consulte la sección correspondiente en Preparación del entorno de desarrollo en la documentación del SDK.

Creación del servicio de aprovisionamiento y dos centros de IoT

En esta sección, usará Azure Cloud Shell para crear un servicio de aprovisionamiento y dos centros de IoT que representan la división de tostadoras Contoso y la división de bombas de calor Contoso.

  1. En primer lugar, establezca variables de entorno en el área de trabajo para simplificar los comandos de este tutorial.

    Los nombres de DPS e IoT Hub deben ser únicos globalmente. Reemplace el marcador de posición SUFFIX por un valor propio.

    Además, el código de función de Azure que cree más adelante en este tutorial busca centros de IoT que tengan -toasters- o -heatpumps- en sus nombres. Si cambia los valores sugeridos, asegúrese de usar nombres que contengan las substrings necesarias.

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

    Sugerencia

    Los comandos usados en este tutorial crean recursos en la ubicación Oeste de EE. UU. de forma predeterminada. Se recomienda crear los recursos en la región más cercana que admita Device Provisioning Service. Para ver una lista de ubicaciones disponibles, vaya a la página Estado de Azure y busque "Device Provisioning Service". En los comandos, las ubicaciones se pueden especificar en formato de una palabra o de varias; por ejemplo, westus, West US, WEST US, etc. El valor no distingue mayúsculas de minúsculas.

  2. Use el comando az group create para crear un grupo de recursos de Azure. Un grupo de recursos de Azure es un contenedor lógico en el que se implementan y se administran los recursos de Azure.

    En el ejemplo siguiente se crea un grupo de recursos. Se recomienda usar este grupo para todos los recursos que se creen en este tutorial. De esta forma, se facilitará la limpieza al finalizar.

    az group create --name $RESOURCE_GROUP --location $LOCATION
    
  3. Use el comando az iot dps create para crear una instancia de Device Provisioning Service (DPS). El servicio de aprovisionamiento se agrega a contoso-us-resource-group.

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

    Este comando puede tardar unos minutos en completarse.

  4. Use el comando az iot hub create para crear el centro de IoT del Departamento de Tostadoras de Contoso. El centro de IoT se agregará al grupo contoso-us-resource-group.

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

    Este comando puede tardar unos minutos en completarse.

  5. Use el comando az iot hub create para crear el centro de IoT del Departamento de bombas de calor de Contoso. Este centro de IoT también se agrega a contoso-us-resource-group.

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

    Este comando puede tardar unos minutos en completarse.

  6. Ejecute los dos comandos siguientes para obtener las cadenas de conexión para los centros que ha creado.

    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. Ejecute los comandos siguientes para vincular los concentradores al recurso de DPS. Reemplace los marcadores de posición por las cadenas de conexión del centro de conectividad del paso 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>
    

Creación de la función de asignación personalizada

En esta sección, creará una función de Azure que implementa la directiva de asignación personalizada. Esta función decide en qué centro de IoT de división se debe registrar un dispositivo según contenga su identificador de registro la cadena -contoso-tstrsd-007 o -contoso-HPSD-088. También establece el estado inicial del dispositivo gemelo en función de si el dispositivo es una tostadora o una bomba de calor.

  1. Inicie sesión en Azure Portal.

  2. En el cuadro de búsqueda, busque y seleccione Aplicación de funciones.

  3. Seleccione Crear o Crear aplicación de funciones.

  4. En la página de creación de la aplicación de funciones, en la pestaña Datos básicos, escriba los siguientes valores para la nueva aplicación de función y seleccione Revisar y crear:

    Parámetro Valor
    Suscripción Asegúrese de que la suscripción en la que creó los recursos de este tutorial está seleccionada.
    Grupo de recursos Seleccione el grupo de recursos que creó en la sección anterior. El valor predeterminado proporcionado en la sección anterior es contoso-us-resource-group.
    Nombre de la aplicación de función Introduzca un nombre para su aplicación de funciones.
    ¿Desea implementar código o imágenes de contenedor? Código
    Pila de tiempo de ejecución .NET
    Versión Seleccione cualquier versión del modelo en proceso.
    Región Seleccione una región cercana.

    Nota:

    De forma predeterminada, está habilitado Application Insights. Aunque en este tutorial Application Insights no es necesario, puede ayudarle a entender y a investigar los problemas que encuentre con la asignación personalizada. Si lo prefiere, puede deshabilitar Application Insights; para ello, seleccione la pestaña Supervisión y, luego, seleccione No en Habilitar Application Insights.

    Captura de pantalla que muestra el formulario Crear aplicación de funciones en Azure Portal.

  5. En la pestaña Revisar y crear, seleccione Crear para crear la aplicación de funciones.

  6. La implementación puede tardar varios minutos. Cuando finalice, seleccione Ir al recurso.

  7. En el panel izquierdo de la página Información general de la aplicación de funciones, seleccione Crear función.

    Captura de pantalla que muestra la selección de la opción para crear la función en Azure Portal.

  8. En la página Crear función, seleccione la plantilla Desencadenador HTTP y, a continuación, seleccione Siguiente.

  9. En la pestaña Detalles de la plantilla, seleccione Anónimo como Nivel de autorización y, a continuación, seleccione Crear.

    Captura de pantalla que muestra cómo establecer el nivel de autorización como anónimo.

    Sugerencia

    Si mantiene el nivel de autorización como Función, deberá configurar las inscripciones de DPS con la clave de API de función. Para más información, consulte Desencadenador HTTP de Azure Functions.

  10. Cuando se abra la función HttpTrigger1, seleccione Código y prueba en el panel izquierdo. Esto le permite editar el código de la función. Se debe abrir el archivo de código run.csx para su edición.

  11. Haga referencia a los paquetes NuGet necesarios. Para crear el dispositivo gemelo inicial, la función de asignación personalizada usa las clases que se definen en dos paquetes NuGet que se deben cargar en el entorno de hospedaje. Con Azure Functions, se hace referencia a los paquetes NuGet mediante un archivo function.proj. En este paso, guardará y cargará un archivo function.proj para los ensamblados necesarios. Para obtener más información, vea Uso de paquetes NuGet con Azure Functions.

    1. Copie las siguientes líneas en su editor favorito y guarde el archivo en el equipo 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. Seleccione el botón Cargar situado encima del editor de código para cargar el archivo function.proj. Después de que se cargue, seleccione el archivo en el editor de código y use el cuadro desplegable para comprobar el contenido.

    3. Seleccione el archivo function.proj en el editor de código y compruebe su contenido. Si el archivo function.proj está vacío, copie las líneas anteriores en el archivo y guárdelo (A veces, la carga crea el archivo sin cargar el contenido).

  12. Asegúrese de que run.csx para HttpTrigger1 está seleccionado en el editor de código. Reemplace el código de la función HttpTrigger1 por el código siguiente y seleccione Guardar:

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

Creación de la inscripción

En esta sección, creará un nuevo grupo de inscripción que usa la directiva de asignación personalizada. Para que sea más sencillo, en este tutorial se usa la atestación de clave simétrica con la inscripción. Con el fin de obtener una solución más segura, considere la posibilidad de usar la atestación de certificado X.509 con una cadena de confianza.

  1. Inicie sesión en Azure Portal y vaya a la instancia de Device Provisioning Service.

  2. Seleccione Administrar inscripciones de la sección Configuración del menú de navegación.

  3. Seleccione Agregar grupo de inscripción.

  4. En la pestaña Registro y aprovisionamiento de la página Agregar grupo de inscripción, proporcione la siguiente información para configurar los detalles del grupo de inscripción:

    Campo Descripción
    Atestación Seleccione Clave simétrica como Mecanismo de atestación.
    Configuración de clave simétrica Active la casilla Generar claves simétricas automáticamente.
    Nombre de grupo Escriba contoso-custom-allocated-devices como nombre del grupo.
    Estado de aprovisionamiento Active la casilla Habilitar esta inscripción.
  5. Seleccione Siguiente: centros de IoT.

  6. En la pestaña Centros de IoT de la página Agregar grupo de inscripción, proporcione la siguiente información para determinar los centros de IoT a los que puede aprovisionar dispositivos el grupo de inscripción:

    Campo Descripción
    Centros de IoT de destino Seleccione uno o varios de los centros de IoT vinculados o agregue un nuevo vínculo a un centro de IoT.
    Directiva de asignación Seleccione Personalizado (use la función de Azure). Seleccione Seleccionar función de Azure y siga las indicaciones para seleccionar la función que creó para este tutorial.
  7. Seleccione Revisar + crear.

  8. En la pestaña Revisar y crear, compruebe todos los valores y seleccione Crear.

Después de guardar la inscripción, vuelva a abrirla y apunte la clave principal. Primero debe guardar la inscripción para que se generen las claves. Esta clave se usa para generar claves de dispositivo únicas para dispositivos simulados en la sección siguiente.

Derivación de las claves de dispositivo únicas

Los dispositivos no usan la clave simétrica principal del grupo directamente del grupo de inscripciones. En su lugar, use la clave principal para derivar una clave para cada dispositivo. En esta sección, creará dos claves de dispositivo únicas. Se usa una clave para un dispositivo de tostadora simulado. La otra clave se usa para un dispositivo simulado de bomba de calor.

Para derivar la clave de dispositivo, use el valor de Clave principal del grupo de inscripciones que anotó antes para calcular el HMAC-SHA256 del identificador de registro de cada dispositivo y convertirá el resultado en formato Base64. Para obtener más información sobre cómo crear claves de dispositivo derivadas con grupos de inscripción, consulte la sección de inscripciones de grupo de Atestación de clave simétrica.

Para el ejemplo de este tutorial, use los dos identificadores de registro de dispositivo que se muestran a continuación y calcule una clave de dispositivo para ambos. Ambos identificadores de registro tienen un sufijo válido para funcionar con el código de ejemplo de la directiva de asignación personalizada:

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

La extensión de IoT para la CLI de Azure proporciona el comando iot dps enrollment-group compute-device-key para generar claves de dispositivo derivadas. Este comando se puede usar en sistemas Windows o Linux, desde PowerShell o un shell de Bash.

Reemplace el valor del argumento --key por la clave principal de su grupo de inscripción.

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

Nota

También puede especificar el identificador del grupo de inscripción, en lugar de la clave simétrica, en el comando iot dps enrollment-group compute-device-key. Por ejemplo:

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

Los dispositivos simulados usan las claves de dispositivo derivadas con cada Id. de registro para realizar la atestación de clave simétrica.

Preparación de un entorno de desarrollo del SDK de Azure IoT para C

En esta sección, preparará un entorno de desarrollo para compilar el SDK de Azure IoT. El SDK incluye el código de ejemplo para el dispositivo simulado. Este dispositivo simulado tratará de aprovisionarse durante la secuencia de arranque del dispositivo.

En esta sección, nos enfocamos en una estación de trabajo basada en Windows. Para obtener un ejemplo en Linux, vea la configuración de las máquinas virtuales en Tutorial: Aprovisionamiento de la geolatencia.

  1. Descargue el sistema de compilación CMake.

    Antes de comenzar la instalación de CMake, es importante que los requisitos previos de Visual Studio (Visual Studio y la carga de trabajo "Desarrollo para el escritorio con C++") estén instalados en la máquina. Una vez que los requisitos previos están en su lugar, y se ha comprobado la descarga, instale el sistema de compilación de CMake.

  2. Busque el nombre de etiqueta de la versión más reciente del SDK.

  3. Abra un símbolo del sistema o el shell de Bash de Git. Ejecute los siguientes comandos para clonar la versión más reciente del repositorio de GitHub del SDK de dispositivo loT de Azure para C. Use la etiqueta que encontró en el paso anterior como valor del parámetro -b, por ejemplo: 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
    

    Esta operación puede tardar varios minutos en completarse.

  4. Cree un subdirectorio cmake en el directorio raíz del repositorio de Git y vaya a esa carpeta. Ejecute los siguientes comandos desde el directorio azure-iot-sdk-c:

    mkdir cmake
    cd cmake
    
  5. Ejecute el siguiente comando para compilar una versión del SDK específica para su plataforma de cliente de desarrollo. Se generará una solución de Visual Studio para el dispositivo simulado en el directorio cmake.

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

    Si cmake no puede encontrar el compilador de C++, es posible que aparezcan errores de compilación al ejecutarse el comando. Si eso sucede, pruebe a ejecutar este comando en el símbolo del sistema de Visual Studio.

    Una vez realizada la compilación, las últimas líneas de salida son similares a las siguientes:

    $ 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
    

Simulación de los dispositivos

En esta sección, actualizará el ejemplo de aprovisionamiento denominado prov_dev_client_sample que está ubicado en el SDK de Azure IoT para C que ha configurado antes.

El código de ejemplo simula una secuencia de arranque de dispositivo que envía la solicitud de aprovisionamiento a la instancia de Device Provisioning Service. La secuencia de arranque hace que el dispositivo de tostadora se reconozca y asigne al centro de IoT mediante la directiva de asignación personalizada.

  1. En Azure Portal, seleccione la pestaña Información general para la instancia de Device Provisioning Service y anote el valor de Ámbito de id.

    Extracción de información del punto de conexión del servicio Device Provisioning desde la hoja del portal

  2. En Visual Studio, abra el archivo de solución azure_iot_sdks.sln que se ha generado anteriormente al ejecutar CMake. El archivo de solución debe estar en la siguiente ubicación: azure-iot-sdk-c\cmake\azure_iot_sdks.sln.

  3. En la ventana del Explorador de soluciones de Visual Studio, desplácese hasta la carpeta Provision_Samples. Expanda el proyecto de ejemplo denominado prov_dev_client_sample. Expanda Archivos de origen y abra prov_dev_client_sample.c.

  4. Busque la constante id_scope y reemplace el valor por el valor de Ámbito de id. que copió anteriormente.

    static const char* id_scope = "0ne00002193";
    
  5. Busque la definición de la función main() en el mismo archivo. Asegúrese de que la variable hsm_type está establecida en SECURE_DEVICE_TYPE_SYMMETRIC_KEY, tal como se muestra a continuación:

    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. En la función main(), busque la llamada a Prov_Device_Register_Device(). Justo antes de esa llamada, agregue las siguientes líneas de código que usan Prov_Device_Set_Provisioning_Payload() para pasar una carga de JSON personalizada durante el aprovisionamiento. Esto permite proporcionar más información a las funciones de asignación personalizadas. También se puede usar para pasar el tipo de dispositivo en lugar de examinar el identificador de registro. Para más información sobre el envío y la recepción de cargas de datos personalizadas con DPS, consulte Transferencia de una carga útil entre un dispositivo y 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. Haga clic con el botón derecho en el proyecto prov_dev_client_sample y seleccione Establecer como proyecto de inicio.

Simulación de la tostadora de Contoso

  1. Para simular el dispositivo de tostadora, busque la llamada a prov_dev_set_symmetric_key_info() en prov_dev_client_sample.c que se ha marcado como comentario.

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

    Quite la marca del comentario de la llamada de función y reemplace los valores de marcador de posición (incluidos los corchetes angulares) por el identificador de registro de la tostadora y la clave de dispositivo derivada que ha generado antes. Solo se proporciona el valor de clave JC8F96eayuQwwz + PkE7IzjH2lIAjCUnAa61tDigBnSs = como ejemplo.

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

    Guarde el archivo.

  2. En el menú de Visual Studio, seleccione Depurar>Iniciar sin depurar para ejecutar la solución. En la solicitud para volver a compilar el proyecto, seleccione para recompilar el proyecto antes de ejecutarlo.

    La salida siguiente ejemplifica el arranque correcto de la tostadora simulada y su conexión a la instancia del servicio de aprovisionamiento para asignarse al centro de IoT de tostadoras según la directiva de asignación 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:
    

    Lo siguiente es un ejemplo de la salida del registro del código de la función de asignación personalizada que se ejecuta para la tostadora. Observe que hay un centro correctamente seleccionado para una tostadora. Observe también la propiedad payload que contiene el contenido JSON personalizado que agregó al código. Este miembro está disponible para su código para usarlo en deviceRuntimeContext.

    Este registro está disponible al hacer clic en Registros en el código de la función en el 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)
    

Simulación de la bomba de calor de Contoso

  1. Para simular el dispositivo de bomba de calor, vuelva a actualizar la llamada a prov_dev_set_symmetric_key_info() en prov_dev_client_sample.c con el identificador de registro de la bomba de calor y la clave de dispositivo derivada que ha generado antes. Solo se proporciona el valor de la clave 6uejA9PfkQgmYylj8Zerp3kcbeVrGZ172YLa7VSnJzg = como ejemplo.

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

    Guarde el archivo.

  2. En el menú de Visual Studio, seleccione Depurar>Iniciar sin depurar para ejecutar la solución. En la solicitud para volver a compilar el proyecto, haga clic en para recompilar el proyecto antes de ejecutarlo.

    La salida siguiente ejemplifica el arranque correcto de la bomba de calor simulada y su conexión a la instancia del servicio de aprovisionamiento para asignarse al centro de IoT de bombas de calor según la directiva de asignación 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:
    

Solución de problemas de directivas de asignación personalizadas

En la siguiente tabla se muestran los escenarios esperados y los códigos de error de resultados que puede recibir. Use esta tabla para ayudar a solucionar errores en las directivas de asignación personalizadas con Azure Functions.

Escenario Resultado del registro del servicio de aprovisionamiento Resultados del SDK de aprovisionamiento
El webhook devuelve 200 OK con el valor de 'iotHubHostName' establecido en un nombre de host de centro de IoT válido Estado del resultado: Asignado SDK devuelve PROV_DEVICE_RESULT_OK junto con información del centro
El webhook devuelve 200 OK con el valor de 'iotHubHostName' en la respuesta, pero se establece en una cadena vacía o null Estado del resultado: Con error

Código de error: CustomAllocationIotHubNotSpecified (400208)
SDK devuelve PROV_DEVICE_RESULT_HUB_NOT_SPECIFIED
El webhook devuelve 401 no autorizado Estado del resultado: Con error

Código de error: CustomAllocationUnauthorizedAccess (400209)
SDK devuelve PROV_DEVICE_RESULT_UNAUTHORIZED
Se ha creado una inscripción individual para deshabilitar el dispositivo Estado del resultado: Disabled SDK devuelve PROV_DEVICE_RESULT_DISABLED
El webhook devuelve el código de error >= 429 La orquestación de DPS volverá a intentarlo varias veces. La directiva de reintentos actual es:

  - Número de reintentos: 10
  - Intervalo inicial: 1 s
  - Incremento: 9 s
El SDK omitirá el error y enviará otro mensaje para obtener el estado en el tiempo especificado
El webhook devuelve cualquier otro código de estado Estado del resultado: Con error

Código de error: CustomAllocationFailed (400207)
SDK devuelve PROV_DEVICE_RESULT_DEV_AUTH_ERROR

Limpieza de recursos

Si tiene previsto seguir trabajando con los recursos creados en este tutorial, puede dejarlos. Si no, siga estos pasos para eliminar todos los recursos creados en este tutorial para evitar cargos innecesarios.

En estos pasos se supone que ha creado todos los recursos de este tutorial como se ha indicado en el mismo grupo de recursos denominado contoso-us-resource-group.

Importante

La eliminación de un grupo de recursos es irreversible. El grupo de recursos y todos los recursos contenidos en él se eliminan permanentemente. Asegúrese de no eliminar por accidente el grupo de recursos o los recursos equivocados. Si ha creado una instancia de IoT Hub en un grupo de recursos ya existente que contiene recursos que desea conservar, puede eliminar solo esa instancia en lugar de eliminar todo el grupo de recursos.

Para eliminar el grupo de recursos por nombre:

  1. Inicie sesión en Azure Portal y después seleccione Grupos de recursos.

  2. En el cuadro de texto Filtrar por nombre..., escriba el nombre del grupo de recursos que contiene los recursos: contoso-us-resource-group.

  3. A la derecha del grupo de recursos de la lista de resultados, seleccione ... y, a continuación, Eliminar grupo de recursos.

  4. Se le pedirá que confirme la eliminación del grupo de recursos. Escriba de nuevo el nombre del grupo de recursos para confirmar y, después, seleccione Eliminar. Transcurridos unos instantes, el grupo de recursos y todos los recursos que contiene se eliminan.

Pasos siguientes

Para más información sobre las directivas de asignación personalizadas, consulte