Ingerir telemetria do Hub IoT nos Gêmeos Digitais do Azure

Este guia percorre o processo de escrever uma função que pode ingerir telemetria de dispositivo do Hub IoT e enviá-la para uma instância de Gêmeos Digitais do Azure.

Os Gêmeos Digitais do Azure são orientados com dados de dispositivos IoT e outras fontes. Uma fonte comum de dados de dispositivo a ser usada nos Gêmeos Digitais do Azure é o Hub IoT.

O processo para ingerir dados nos Gêmeos Digitais do Azure é configurar um recurso de computação externo, como uma função feita usando o Azure Functions. A função recebe os dados e usa as APIs DigitalTwins para definir propriedades ou disparar eventos de telemetria nos gêmeos digitais adequadamente.

Este documento de instruções percorre o processo para escrever uma função que pode ingerir telemetria de dispositivo do Hub IoT.

Pré-requisitos

Antes de continuar com este exemplo, você precisa configurar os seguintes recursos como pré-requisitos:

Cenário de telemetria de exemplo

Este "como" descreve como enviar mensagens do Hub IoT para os Gêmeos Digitais do Azure usando uma função no Azure. Há muitas configurações possíveis e estratégias de correspondência que você pode usar para enviar mensagens, e o exemplo deste artigo contém os seguintes blocos:

  • Um dispositivo termostato no Hub IoT com uma ID de dispositivo conhecida
  • Um gêmeo digital para representar o dispositivo com uma ID correspondente

Observação

Este exemplo usa uma correspondência de ID direta entre a ID do dispositivo e a ID do gêmeo digital correspondente, mas é possível fornecer mapeamentos mais sofisticados do dispositivo para o gêmeo (como com uma tabela de mapeamento).

Sempre que um evento de telemetria de temperatura é enviado pelo dispositivo termostato, uma função processa a telemetria e a Temperature propriedade do gêmeo digital deve ser atualizada. Esse cenário é descrito no diagrama abaixo:

Diagram of IoT Hub device sending Temperature telemetry to a function in Azure, which updates a Temperature property on a twin in Azure Digital Twins.

Adicionar um modelo e um gêmeo

Nesta seção, você vai configurar um gêmeo digital nos Gêmeos Digitais do Azure que vai representar o dispositivo termostato e vai ser atualizado com as informações do Hub IoT.

Para criar um gêmeo do tipo termostato, você precisa primeiro carregar o modelo do termostato em sua instância, que descreve as propriedades de um termostato e será usado posteriormente para criar o gêmeo.

O modelo se parece com este:

{
    "@id": "dtmi:contosocom:DigitalTwins:Thermostat;1",
    "@type": "Interface",
    "@context": "dtmi:dtdl:context;3",
    "contents": [
      {
        "@type": "Property",
        "name": "Temperature",
        "schema": "double"
      }
    ]
  }

Para carregar esse modelo na instância de gêmeos, execute o seguinte comando CLI do Azure, que carrega o modelo acima como JSON embutido. Você pode executar o comando no Azure Cloud Shell em seu navegador (use o ambiente Bash) ou em seu computador se tiver a CLI instalada localmente. Há um espaço reservado para o nome do host da instância (você também pode usar o nome amigável da instância com uma pequena redução no desempenho).

az dt model create --dt-name <instance-hostname-or-name> --models '{  "@id": "dtmi:contosocom:DigitalTwins:Thermostat;1",  "@type": "Interface",  "@context": "dtmi:dtdl:context;2",  "contents": [    {      "@type": "Property",      "name": "Temperature",      "schema": "double"    }  ]}' 

Observação

Se você estiver usando algo diferente de Cloud Shell no ambiente do Bash, talvez seja necessário fazer escape de determinados caracteres no JSON em linha para que ele seja analisado corretamente. Para obter mais informações, consulte Usar caracteres especiais em diferentes shells.

Em seguida, você precisa criar um gêmeo usando este modelo. Use o comando a seguir para criar um gêmeo chamado thermostat67 e defina 0.0 como o valor de temperatura inicial. Há um espaço reservado para o nome do host da instância (você também pode usar o nome amigável da instância com uma pequena redução no desempenho).

az dt twin create  --dt-name <instance-hostname-or-name> --dtmi "dtmi:contosocom:DigitalTwins:Thermostat;1" --twin-id thermostat67 --properties '{"Temperature": 0.0}'

Quando o gêmeo for criado com sucesso, a saída da CLI do comando deverá ser semelhante a esta:

{
  "$dtId": "thermostat67",
  "$etag": "W/\"0000000-9735-4f41-98d5-90d68e673e15\"",
  "$metadata": {
    "$model": "dtmi:contosocom:DigitalTwins:Thermostat;1",
    "Temperature": {
      "lastUpdateTime": "2021-09-09T20:32:46.6692326Z"
    }
  },
  "Temperature": 0.0
}

Criar a função do Azure

Nesta seção, você criará uma função do Azure para acessar os Gêmeos Digitais do Azure e atualizar gêmeos com base nos eventos de telemetria de dispositivo IoT que ele recebe. Siga as etapas abaixo para criar e publicar a função.

  1. Primeiro, crie um novo projeto Azure Functions do tipo de gatilho da Grade de Eventos.

    Você pode fazer isso usando o Visual Studio (para obter instruções, confira Desenvolver Azure Functions usando o Visual Studio), Visual Studio Code (para obter instruções, confira Criar uma função C# no Azure usando o Visual Studio Code), ou a CLI do Azure (para obter instruções, confira Criar uma função C# no Azure por meio da linha de comando).

  2. Adicione os pacotes a seguir ao seu projeto (você pode usar gerenciador de pacotes NuGet do Visual Studio ou o comando dotnet add package em uma ferramenta de linha de comando).

  3. Crie uma função dentro do projeto chamado IoTHubtoTwins.cs. Cole o seguinte código no arquivo de função:

    using System;
    using Azure;
    using System.Net.Http;
    using Azure.Core.Pipeline;
    using Azure.DigitalTwins.Core;
    using Azure.Identity;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.EventGrid;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using Azure.Messaging.EventGrid;
    
    namespace IotHubtoTwins
    {
        public class IoTHubtoTwins
        {
            private static readonly string adtInstanceUrl = Environment.GetEnvironmentVariable("ADT_SERVICE_URL");
            private static readonly HttpClient httpClient = new HttpClient();
    
            [FunctionName("IoTHubtoTwins")]
            // While async void should generally be used with caution, it's not uncommon for Azure function apps, since the function app isn't awaiting the task.
    #pragma warning disable AZF0001 // Suppress async void error
            public async void Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log)
    #pragma warning restore AZF0001 // Suppress async void error
            {
                if (adtInstanceUrl == null) log.LogError("Application setting \"ADT_SERVICE_URL\" not set");
    
                try
                {
                    // Authenticate with Digital Twins
                    var cred = new DefaultAzureCredential();
                    var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred);
                    log.LogInformation($"ADT service client connection created.");
                
                    if (eventGridEvent != null && eventGridEvent.Data != null)
                    {
                        log.LogInformation(eventGridEvent.Data.ToString());
    
                        // <Find_device_ID_and_temperature>
                        JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString());
                        string deviceId = (string)deviceMessage["systemProperties"]["iothub-connection-device-id"];
                        var temperature = deviceMessage["body"]["Temperature"];
                        // </Find_device_ID_and_temperature>
    
                        log.LogInformation($"Device:{deviceId} Temperature is:{temperature}");
    
                        // <Update_twin_with_device_temperature>
                        var updateTwinData = new JsonPatchDocument();
                        updateTwinData.AppendReplace("/Temperature", temperature.Value<double>());
                        await client.UpdateDigitalTwinAsync(deviceId, updateTwinData);
                        // </Update_twin_with_device_temperature>
                    }
                }
                catch (Exception ex)
                {
                    log.LogError($"Error in ingest function: {ex.Message}");
                }
            }
        }
    }
    

    Salve o código da função.

  4. Publique o projeto com a função IoTHubtoTwins.cs em um aplicativo de funções no Azure.

    Para obter instruções sobre como publicar uma função usando o Visual Studio, confira Desenvolver Azure Functions com o Visual Studio. Para obter instruções sobre como publicar a função usando o Visual Studio Code, confira Criar uma função C# no Azure usando o Visual Studio Code. Para obter instruções sobre como publicar a função usando a CLI do Azure, confira Criar uma função C# no Azure da linha de comando.

Depois que o processo de publicação da função for concluído, você poderá usar este comando da CLI do Azure para verificar se a publicação foi bem-sucedida. Há espaços reservados para o grupo de recursos e o nome do aplicativo de funções. O comando imprimirá informações sobre a função IoTHubToTwins.

az functionapp function show --resource-group <your-resource-group> --name <your-function-app> --function-name IoTHubToTwins

Configurar o aplicativo de funções

Para acessar os Gêmeos Digitais do Azure, seu aplicativo de funções precisa de uma identidade gerenciada atribuída pelo sistema com permissões para acessar sua instância dos Gêmeos Digitais do Azure. Você configurará isso nesta seção, atribuindo uma função de acesso para a função e definindo as configurações do aplicativo para que ela possa acessar a instância dos Gêmeos Digitais do Azure.

Execute os comandos a seguir no Azure Cloud Shell ou em uma CLI do Azure local.

Observação

Esta seção precisa ser concluída por um usuário do Azure que tenha permissões para gerenciar o acesso do usuário aos recursos do Azure, incluindo concessão e delegação de permissões. Funções comuns que atendem a esse requisito são Proprietário, Administrador da conta ou a combinação de Colaborador e Administrador de Acesso do Usuário. Para obter mais informações sobre os requisitos de permissão para funções dos Gêmeos Digitais do Azure, confira Configurar uma instância e a autenticação.

Atribuir uma função de acesso

A função do Azure exige o recebimento de um token de portador. Para garantir que o token de portador seja recebido, conceda ao aplicativo de funções a função Proprietário de Dados dos Gêmeos Digitais do Azure à instância dos Gêmeos Digitais do Azure, que dará ao aplicativo de funções a permissão para executar atividades do plano de dados na instância.

  1. Use o comando a seguir para criar uma identidade gerenciada pelo sistema para sua função (se a função já tiver uma, esse comando imprimirá os respectivos detalhes). Anote o principalId campo na saída. Você usará essa ID para se referir à função a fim de conceder a ela as permissões na próxima etapa.

    az functionapp identity assign --resource-group <your-resource-group> --name <your-function-app-name>	
    
  2. Use o valor de principalId no comando a seguir para atribuir a função Proprietário de Dados dos Gêmeos Digitais do Azure à instância dos Gêmeos Digitais do Azure.

    az dt role-assignment create --dt-name <your-Azure-Digital-Twins-instance> --assignee "<principal-ID>" --role "Azure Digital Twins Data Owner"
    

Definir as configurações do aplicativo

Em seguida, torne a URL da sua instância do Gêmeos Digitais do Azure acessível à sua função definindo uma variável de ambiente para ela.

Dica

A URL da instância dos Gêmeos Digitais do Azure é criada adicionando https:// ao início do nome do host da instância do Azure. Para ver o nome do host, juntamente com todas as propriedades da instância, execute az dt show --dt-name <your-Azure-Digital-Twins-instance>.

O comando a seguir define uma variável de ambiente para a URL da instância que sua função usará sempre que precisar acessar a instância.

az functionapp config appsettings set --resource-group <your-resource-group> --name <your-function-app-name> --settings "ADT_SERVICE_URL=https://<your-Azure-Digital-Twins-instance-host-name>"

Conectar a função ao Hub IoT

Nesta seção, você vai configurar a função como um destino de evento para os dados do dispositivo do Hub IoT. Configurar a função dessa forma vai garantir que os dados do dispositivo termostato no Hub IoT sejam enviados para a função do Azure para processamento.

Use o comando da CLI a seguir para criar uma assinatura de evento que o Hub IoT usará para enviar dados de evento para a função IoTHubtoTwins. Há um espaço reservado para você inserir um nome para a assinatura do evento e também há espaços reservados para você inserir sua ID de assinatura, grupo de recursos, nome do hub IoT e o nome do aplicativo de funções.

az eventgrid event-subscription create --name <name-for-hub-event-subscription> --event-delivery-schema eventgridschema --source-resource-id /subscriptions/<your-subscription-ID>/resourceGroups/<your-resource-group>/providers/Microsoft.Devices/IotHubs/<your-IoT-hub> --included-event-types Microsoft.Devices.DeviceTelemetry --endpoint-type azurefunction --endpoint /subscriptions/<your-subscription-ID>/resourceGroups/<your-resource-group>/providers/Microsoft.Web/sites/<your-function-app>/functions/IoTHubtoTwins

A saída mostrará informações sobre a assinatura do evento que foi criada. Você pode confirmar que a operação foi concluída com êxito verificando o valor provisioningState no resultado:

"provisioningState": "Succeeded",

Testar com dados de IoT simulados

É possível testar a nova função de entrada usando o simulador de dispositivo de Conectar uma solução de ponta a ponta. O projeto DeviceSimulator contém um dispositivo termostato simulado que envia dados de temperatura de exemplo. Para configurar o simulador de dispositivo, siga estas etapas:

  1. Navegue até o repositório de projeto de exemplo de ponta a ponta dos Gêmeos Digitais do Azure. Obtenha um projeto de exemplo em seu computador selecionando o botão Procurar códigos abaixo do título. Isso levará você ao repositório do GitHub para obter exemplos que poderão ser baixados como um .zip clicando no botão Código e em Baixar ZIP.

    Isso baixará uma pasta .zip chamada digital-twins-samples-main.zip no computador. Descompacte a pasta e extraia os arquivos. Você vai usar a pasta do projeto DeviceSimulator.

  2. Registrar o dispositivo simulado com o Hub IoT

  3. Configurar e executar a simulação

Depois de concluir essas etapas, você deve ter uma janela do console do projeto executando e enviando dados de telemetria de dispositivo simulados para seu hub IoT.

Screenshot of the output from the device simulator project.

Validar resultados

Ao executar o simulador de dispositivo acima, o valor da temperatura do termostato do gêmeo digital vai ser alterado. Na CLI do Azure, execute o comando a seguir para ver o valor de temperatura. Há um espaço reservado para o nome do host da instância (você também pode usar o nome amigável da instância com uma pequena redução no desempenho).

az dt twin query --query-command "SELECT * FROM digitaltwins WHERE \$dtId = 'thermostat67'" --dt-name <instance-hostname-or-name>

Observação

Se você estiver usando algo diferente de Cloud Shell no ambiente do Bash, talvez seja necessário fazer escape do caractere $ na consulta de forma diferente para que ele seja analisado corretamente. Para obter mais informações, consulte Usar caracteres especiais em diferentes shells.

Sua saída deve mostrar os detalhes do gêmeo thermostat67, incluindo um valor de temperatura, dessa forma:

{
  "result": [
    {
      "$dtId": "thermostat67",
      "$etag": "W/\"dbf2fea8-d3f7-42d0-8037-83730dc2afc5\"",
      "$metadata": {
        "$model": "dtmi:contosocom:DigitalTwins:Thermostat;1",
        "Temperature": {
          "lastUpdateTime": "2021-06-03T17:05:52.0062638Z"
        }
      },
      "Temperature": 70.20518558807913
    }
  ]
}

Para ver a alteração do valor Temperature, execute repetidamente o comando de consulta acima.

Próximas etapas

Leia sobre entrada e saída de dados com os Gêmeos Digitais do Azure: