你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

将 IoT 中心遥测引入 Azure 数字孪生

本指南逐步讲解如何编写一个函数,该函数可以从 IoT 中心引入设备遥测数据并将其发送到 Azure 数字孪生实例。

Azure 数字孪生由来自 IoT 设备和其他源的数据驱动。 Azure 数字孪生中使用的设备数据的常见源是 IoT 中心

将数据引入 Azure 数字孪生的过程是设置外部计算资源,例如使用 Azure Functions 生成的函数。 该函数接收数据,并使用 DigitalTwins API 相应地在 数字孪生 上设置属性或触发遥测事件。

本作指南文档逐步讲解如何编写可从 IoT 中心引入设备遥测数据的函数。

先决条件

在继续此示例之前,需要将以下资源设置为先决条件:

示例遥测方案

本作说明概述了如何使用 Azure 中的函数将消息从 IoT 中心发送到 Azure 数字孪生。 有许多可用于发送消息的可能配置和匹配策略,但本文的示例包含以下部分:

  • IoT 中心中的恒温器设备,具有已知设备 ID
  • 用于表示设备的数字孪生,具有匹配 ID

注释

此示例使用设备 ID 与相应的数字孪生 ID 之间的直接 ID 匹配,但可以提供从设备到其孪生的更复杂的映射(如映射表)。

每当恒温器设备发送温度遥测事件时,函数就会处理遥测数据, Temperature 数字孪生体的属性应更新。 下图概述了此方案:

IoT 中心设备将温度遥测数据发送至 Azure 中的某个函数示意图,该函数更新 Azure 数字孪生中孪生体上的温度属性。

添加模型和孪生体

在本节中,您将在 Azure 数字孪生平台上设置一个表示恒温器设备的数字孪生,并以 IoT 中心的信息进行更新。

若要创建恒温器类型孪生体,首先需要将恒温器模型上传到实例,该 模型 描述恒温器的属性,稍后将用于创建孪生体。

该模型如下所示:

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

若要将此模型上传到孪生实例,请运行以下 Azure CLI 命令,该命令将上一个模型作为内联 JSON 上传。 可以在浏览器中(使用 Bash 环境)或在计算机上安装 CLI 的情况下,在 Azure Cloud Shell 中运行命令。 有一个用于实例主机名的占位符(您也可以使用实例的易记名称,但这样做可能会导致性能略有下降)。

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

注释

如果你在 Bash 环境中使用 Cloud Shell 以外的任何内容,则可能需要转义内联 JSON 中的某些字符,以便对其进行正确解析。 有关详细信息,请参阅在不同的 shell 中使用特殊字符

然后,需要使用此模型创建一个孪生体。 使用以下命令创建名为 thermostat67 的恒温器孪生体,并将 0.0 设置为初始温度值。 有一个用于实例主机名的占位符(您也可以使用实例的易记名称,但这样做可能会导致性能略有下降)。

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

成功创建孪生体后,命令的 CLI 输出应如下所示:

{
  "$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
}

创建 Azure 函数

在本部分中,你将创建一个 Azure 函数,以访问 Azure 数字孪生组件,并根据接收到的 IoT 设备遥测事件更新其孪生状态。 执行以下步骤来创建和发布函数。

  1. 首先,创建事件网格触发器类型的新 Azure Functions 项目。

    可以使用 Visual Studio(相关说明,请参阅使用 Visual Studio 开发 Azure Functions)、Visual Studio Code(相关说明,请参阅在 Azure 中使用 Visual Studio Code 创建 C# 函数)或 Azure CLI(相关说明,请参阅在 Azure 中从命令行创建 C# 函数)来执行此操作

  2. 将以下包添加到项目(可以使用 Visual Studio NuGet 包管理器,或者使用命令行工具中的 dotnet add package 命令)。

  3. 在名为 IoTHubtoTwins.cs的项目中创建函数。 将以下代码粘贴到函数文件中:

    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}");
                }
            }
        }
    }
    

    保存函数代码。

  4. 使用 IoTHubtoTwins.cs 函数将项目发布到 Azure 中的函数应用。

    若要了解如何使用 Visual Studio 发布函数,请参阅使用 Visual Studio 开发 Azure Functions。 若要了解如何使用 Visual Studio Code 发布函数,请参阅使用 Visual Studio Code 在 Azure 中创建 C# 函数。 若要了解如何使用 Azure CLI 发布函数,请参阅在 Azure 中从命令行创建 C# 函数

完成发布函数过程后,可使用此 Azure CLI 命令来验证发布是否成功。 有资源组的占位符和函数应用的名称。 该命令输出有关 IoTHubToTwins 函数的信息。

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

配置函数应用

若要访问 Azure 数字孪生,函数应用需要具有访问 Azure 数字孪生实例的权限的系统 分配托管标识 。 在本部分中,通过为函数分配访问角色以及配置应用程序设置来进行设置,以便它可以访问您的 Azure 数字孪生体实例。

Azure Cloud Shell本地 Azure CLI 中运行以下命令。

注释

有权管理用户对 Azure 资源的访问权限(包括授予和委派权限)的 Azure 用户必须完成本部分。 满足此要求的常见角色包括“所有者”、“帐户管理员”或“用户访问管理员”和“参与者”的组合。 有关 Azure 数字孪生角色的权限要求的详细信息,请参阅 设置实例和身份验证

分配访问角色

Azure 函数需要将持有者令牌传递给它。 若要确保传递持有者令牌,请向函数应用授予 Azure 数字孪生实例的 Azure 数字孪生数据所有者 角色,该角色为函数应用授予对实例执行数据平面活动的权限。

  1. 使用以下命令为函数创建 系统托管标识 (如果该函数已有一个,此命令将输出其详细信息)。 记下输出中的 principalId 字段。 你将使用此 ID 来引用函数,以便可以在下一步中授予其权限。

    az functionapp identity assign --resource-group <your-resource-group> --name <your-function-app-name>	
    
  2. 使用以下命令中的 principalId 值为函数赋予 Azure 数字孪生实例的“Azure 数字孪生数据所有者”角色

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

配置应用程序设置

接下来,通过为其设置 环境变量 ,使 Azure 数字孪生实例的 URL 可供函数访问。

小窍门

通过将 https:// 添加到实例主机名的开头,创建 Azure 数字孪生实例的 URL。 若要查看主机名以及实例的所有属性,请运行 az dt show --dt-name <your-Azure-Digital-Twins-instance>

以下命令为实例的 URL 设置环境变量,函数在需要访问实例时使用该变量。

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>"

将函数连接到 IoT 中心

在本部分中,将函数设置为 IoT 中心设备数据的事件目标。 以这种方式设置函数可以确保 IoT 中心恒温器设备中的数据发送到 Azure 函数进行处理。

使用以下 CLI 命令创建 IoT 中心用于将事件数据发送到 IoTHubtoTwins 函数的事件订阅。 有一个占位符可用于输入事件订阅的名称,还有一些占位符可用于输入订阅 ID、资源组、IoT 中心名称和函数应用的名称。

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

输出显示有关新创建的事件订阅的信息。 可通过验证结果中的 provisioningState 值来确认操作已成功完成:

"provisioningState": "Succeeded",

使用模拟 IoT 数据进行测试

可以使用 连接端到端解决方案中的设备模拟器测试新的入口函数。 DeviceSimulator 项目包含发送样本温度数据的模拟恒温器设备。 若要设置设备模拟器,请执行以下步骤:

  1. 导航到 Azure 数字孪生端到端示例项目存储库。 通过选择标题下方的 “浏览代码 ”按钮获取计算机上的示例项目。 此按钮会带您前往样本的 GitHub 仓库,您可以通过选择 代码 按钮,然后选择 下载 ZIP 来下载它,作为 .zip。

    此选项会将 .zip 文件夹下载到您的计算机,并作为 digital-twins-samples-main.zip 使用。 解压缩文件夹并提取文件。 提取文件后,使用 DeviceSimulator 项目文件夹。

  2. 将模拟设备注册到 IoT 中心

  3. 配置并运行模拟

完成这些步骤后,应该会运行一个项目控制台窗口,并将模拟设备遥测数据发送到 IoT 中心。

设备模拟器项目的输出的屏幕截图。

验证结果

在控制台窗口中运行设备模拟器时,如前所述,恒温器数字孪生体的温度值会发生变化。 在 Azure CLI 中,运行以下命令以查看温度值。 有一个用于实例主机名的占位符(您也可以使用实例的易记名称,但这样做可能会导致性能略有下降)。

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

注释

如果在 Bash 环境中使用 Cloud Shell 以外的任何内容,则可能需要以不同的方式对查询中的 $ 字符进行转义,以便对其进行正确分析。 有关详细信息,请参阅在不同的 shell 中使用特殊字符

输出应显示恒温器 67 孪生体的详细信息,包括温度值,如下所示:

{
  "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
    }
  ]
}

Temperature若要查看值更改,请重复运行上一个查询命令。

后续步骤

使用 Azure 数字孪生了解数据流入和出口: