文章目录
一、Azure数字孪生在解决方案架构中的角色
Azure 数字孪生通常与其他 Azure 服务一起使用,是更大型 IoT 解决方案的一部分。一个完整的解决方案使用 Azure 数字孪生可能包括以下几个关键组成部分:
(1) Azure 数字孪生服务实例:此服务存储孪生模型、孪生图及其状态,并协调事件处理。请注意,在公共预览版中,此服务可能存在一些使用限制。
(2) 客户端应用程序:一个或多个应用程序,用于配置模型、创建拓扑,并从孪生图中提取见解,从而推动 Azure 数字孪生实例的应用。
(3) 外部计算资源:用于处理由 Azure 数字孪生或连接的数据源(例如设备)生成的事件。常见的计算资源提供方式是通过 Azure Functions。
(4) IoT中心:提供设备管理和 IoT 数据流处理功能。
(5) 下游服务:处理工作流集成(如逻辑应用)、冷存储、时序集成或分析等任务。
以下图示展示了 Azure 数字孪生在更广泛的 Azure IoT 解决方案中的位置和作用。
二、使用Azure数字孪生API编写代码
在开发过程中,使用 Azure 数字孪生来编写客户端应用程序以与 Azure 数字孪生服务实例进行交互是一种常见做法。本教程专为开发人员设计,旨在介绍如何使用适用于 .NET 的 Azure IoT 数字孪生客户端库(C#)来编程操作 Azure 数字孪生服务。
接下来将详细介绍如何从零开始编写一个 C# 控制台客户端应用,为开发人员提供一个清晰的步骤指导,帮助您有效地利用 Azure 数字孪生技术。
1. 教程先决条件与环境设置
本教程主要通过命令行来执行设置和管理项目工作,因此,你可以选择任何喜欢的代码编辑器来完成以下练习。
在开始之前,请确保你的开发环境已经准备就绪:
- 代码编辑器:任何你喜欢的代码编辑器均可。
- .NET Core 3.1:确保开发电脑已安装 .NET Core 3.1。你可以从.NET 官网下载适用于多个平台的 .NET Core 3.1 SDK。
2. 设置 Azure 数字孪生实例
要顺利完成本教程,你需要一个可编程的 Azure 数字孪生实例。如果你之前已经设置过一个实例,可以继续使用。否则,请按照以下步骤创建和配置一个新的实例:
(1) 创建实例:参考官方文档 “如何:创建 Azure 数字孪生实例”。
(2) 设置应用注册:按照 “如何:对客户端应用程序进行身份验证” 中的步骤为你的实例配置 Azure Active Directory 应用注册。
3. 设置项目环境
准备好使用 Azure 数字孪生实例后,按照以下步骤设置客户端应用项目:
(1) 创建项目目录:在计算机上打开命令提示符或其他控制台窗口,创建一个空的项目目录,如 DigitalTwinsCodeTutorial
。
(2) 初始化项目:导航至新目录,运行以下命令创建一个空的 .NET 控制台应用项目:
dotnet new console
这会在目录中生成必要的文件,包括用于编写大部分代码的 Program.cs
文件。
(3) 添加依赖项:为了使用 Azure 数字孪生服务,需要添加两个关键的依赖项:
dotnet add package Azure.DigitalTwins.Core --version 1.0.0-preview.2
dotnet add package Azure.Identity
其中第一个包是针对 .NET 的 Azure IoT 数字孪生客户端库,第二个包提供了 Azure 身份验证所需的工具。
保持命令窗口打开,因为我们将在整个教程中使用它进行进一步的操作和命令执行。
4. 开始使用项目代码
在本教程的这一部分,我们将开始编写代码,以利用 Azure 数字孪生的功能。以下是你将要实现的关键操作:
(1) 对服务进行身份验证:这是与 Azure 数字孪生服务交互的首要步骤,确保只有授权用户可以访问服务。
(2) 上传模型:定义数字孪生的结构和行为。
(3) 捕获错误:有效处理可能发生的运行时错误。
(4) 创建数字孪生:在 Azure 数字孪生中实例化模型。
(5) 创建关系:定义不同数字孪生之间的连接和交互。
(6) 查询数字孪生:检索关于数字孪生的特定信息。
在教程的末尾,我们将提供完整的代码示例,你可以用它来参考和验证你的工作。
5. 设置基础代码
打开你的代码编辑器,并加载 Program.cs
文件。你将看到如下的基础代码模板:
using System;
namespace DigitalTwinsCodeTutorial
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
首先,在文件顶部添加必要的 using
语句来引入 Azure 数字孪生和身份验证相关的依赖项:
using Azure.DigitalTwins.Core;
using Azure.Identity;
实现身份验证功能
为了安全地与 Azure 数字孪生服务交互,必须首先进行身份验证。这需要准备以下三项信息:
- 订阅的目录(租户)ID:标识你的 Azure 订阅的目录。
- 应用程序(客户端)ID:在之前设置 Azure 数字孪生实例时创建的,用于标识你的应用程序。
- Azure 数字孪生实例的 hostName:你的数字孪生服务实例的网络地址。
可以通过以下 Azure CLI 命令查找你的租户 ID:
az account show --query tenantId
接下来,将下面的代码片段添加到 Main
函数中,以创建一个连接到 Azure 数字孪生实例的服务客户端。这段代码使用 Azure 身份验证库中的 DefaultAzureCredential
方法自动解决身份验证凭据。
// Replace <your-hostname> with your Digital Twins instance hostname.
string adtInstanceUrl = "https://<your-hostname>";
var credential = new DefaultAzureCredential();
var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credential);
Console.WriteLine("Successfully authenticated to Azure Digital Twins.");
这段代码帮助确保你的应用能够安全地与 Azure 数字孪生服务进行通信,为后续操作打下基础。
在 C# 程序中集成 Azure 数字孪生
本节将指导你如何在 Program.cs
中设置和初始化 Azure 数字孪生服务客户端,并准备上传一个模型。首先,确保你已经将适当的代码添加到 Main 方法中,并设置了必要的变量。
初始化 Azure 数字孪生客户端
打开 Program.cs
文件,并在 “Hello, World!” 输出行下方粘贴以下代码。这段代码会设置 Azure 数字孪生实例的连接,并创建服务客户端。
string clientId = "<your-application-ID>";
string tenantId = "<your-directory-ID>";
string adtInstanceUrl = "https://<your-Azure-Digital-Twins-instance-hostName>";
var credentials = new InteractiveBrowserCredential(tenantId, clientId);
DigitalTwinsClient client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credentials);
Console.WriteLine($"Service client created – ready to go");
这段代码使用了 InteractiveBrowserCredential
类,它会在首次运行时打开一个浏览器窗口,要求你输入 Azure 凭证。这种认证方式适用于开发和测试,但在生产环境中,你可能需要使用更适合自动化的凭证类型。更多关于凭证的信息可以在 Microsoft 标识平台身份验证库文档 中找到。
上传模型
数字孪生模型是定义环境中可实例化元素的结构和行为的模板。模型以数字孪生定义语言(DTDL)编写,类似于面向对象编程语言中的类。创建 Azure 数字孪生解决方案的第一步通常是定义至少一个模型。
创建和填充 DTDL 文件
- 创建模型文件:在项目目录中创建一个名为
SampleModel.json
的新 JSON 文件。 - 定义模型内容:粘贴以下内容到
SampleModel.json
文件中:
{
"@id": "dtmi:com:contoso:SampleModel;1",
"@type": "Interface",
"displayName": "SampleModel",
"contents": [
{
"@type": "Relationship",
"name": "contains"
},
{
"@type": "Property",
"name": "data",
"schema": "string"
}
],
"@context": "dtmi:dtdl:context;2"
}
这个模型定义了一个简单的数字孪生,具有一个包含关系和一个数据属性。
运行和测试
在命令窗口中使用以下命令运行代码:
dotnet run
首次运行会还原依赖项并执行程序。如果一切顺利,程序将输出“Service client created - ready to go”。如果出现问题,没有任何错误处理机制,你将看到代码抛出的异常。这提醒我们,在实际项目中添加适当的错误处理是非常重要的。
上传模型到 Azure 数字孪生实例
本节将引导你如何将自定义的数字孪生模型上传到 Azure 数字孪生服务。这一过程涉及从文件中读取模型定义,然后使用 Azure SDK 的异步方法将其上传到云。
准备程序代码
首先,确保你的 Program.cs
文件顶部已经包含了必要的 using
语句:
using System;
using System.Threading.Tasks;
using System.IO;
using System.Collections.Generic;
using Azure;
using Azure.DigitalTwins.Core;
using Azure.DigitalTwins.Core.Models;
接下来,更改 Main
方法的签名以支持异步操作,允许使用 C# 服务 SDK 中的异步方法进行编程:
static async Task Main(string[] args)
上传模型的实现
在文件中,找到之前添加的身份验证代码块,并在其下方添加以下代码以上传模型:
Console.WriteLine();
Console.WriteLine($"Upload a model");
var typeList = new List<string>();
string dtdl = File.ReadAllText("SampleModel.json");
typeList.Add(dtdl);
try
{
// Upload the model to the service
await client.CreateModelsAsync(typeList);
Console.WriteLine("Model uploaded successfully.");
}
catch (Exception ex)
{
Console.WriteLine($"Error uploading model: {ex.Message}");
}
此代码段首先从项目目录中读取 SampleModel.json
文件内容,然后将其添加到要上传的类型列表中。通过 CreateModelsAsync
方法上传模型,并在控制台输出结果。
确保 JSON 文件可访问
如果你使用 Visual Studio,确保新创建的 JSON 文件被设置为“复制到输出目录”,选择“有更新时才复制”或“始终复制”。这样,当你使用 F5 或 dotnet run
命令执行程序时,Visual Studio 能够在默认路径找到 JSON 文件。
验证 DTDL 模型
还有独立于语言的 DTDL 验证工具可用于检查你的模型文件,确保其遵循正确的 DTDL 格式。这些工具基于 DTDL 解析器库构建,具体操作方法可参阅文档:如何分析和验证模型。
执行和验证
在命令窗口中,使用以下命令运行你的程序:
dotnet run
程序运行后,将在输出中看到 “Upload a model” 消息,如果上传成功,将显示 “Model uploaded successfully.”。如果发生错误,将输出具体的错误信息,帮助你快速定位问题。这种反馈机制对于确保模型准确上传至服务至关重要。
管理和处理 Azure 数字孪生模型上传
在开发过程中,与 Azure 数字孪生服务的交互包括上传模型、捕获错误,以及在此基础上创建数字孪生实例。以下是一步步指导,帮助你有效地实现这些操作并处理可能遇到的异常。
捕获并处理上传错误
当尝试上传已存在的模型时,Azure 数字孪生服务会返回错误,防止重复上传相同的模型。为确保程序健壮性,我们需要在代码中适当捕获并处理这些错误。
try {
// Attempt to upload the model to the service
await client.CreateModelsAsync(typeList);
Console.WriteLine("Model uploaded successfully.");
} catch (RequestFailedException rex) {
Console.WriteLine($"Load model failed: {rex.Status}:{rex.Message}");
if (rex.Status == 409) {
Console.WriteLine("A model with the same identifier already exists.");
}
}
在上述代码中,我们尝试上传模型,并在发生异常时捕获 RequestFailedException
。特别地,如果错误代码为409(冲突),程序会输出已存在相同模型的提示。
读取并显示模型列表
一旦模型上传至 Azure 数字孪生服务,我们可以查询并显示所有已上传的模型,以验证上传是否成功:
AsyncPageable<ModelData> modelDataList = client.GetModelsAsync();
await foreach (ModelData md in modelDataList)
{
Console.WriteLine($"Model Display Name: {md.DisplayName}, ID: {md.Id}");
}
创建数字孪生实例
上传模型后,下一步是利用这些模型创建实体的数字孪生,这些实体可以是传感器、房间或任何业务环境中的对象。首先,需要添加对 JSON 序列化的支持,因为数字孪生的创建涉及到数据的序列化和反序列化。
using System.Text.Json;
在模型基础上创建数字孪生的示例代码如下:
string dtId = "myDigitalTwinId";
var digitalTwinData = new BasicDigitalTwin
{
Id = dtId,
Metadata = { ModelId = "dtmi:com:contoso:SampleModel;1" },
Contents = {
{ "data", "Sample data value" }
}
};
try {
await client.CreateOrReplaceDigitalTwinAsync<BasicDigitalTwin>(dtId, digitalTwinData);
Console.WriteLine($"Digital twin '{dtId}' created successfully.");
} catch (Exception ex) {
Console.WriteLine($"Error creating digital twin: {ex.Message}");
}
这段代码创建了一个基于之前上传的模型的数字孪生,并尝试将其添加到 Azure 数字孪生服务中。使用 CreateOrReplaceDigitalTwinAsync
方法可以确保如果同名的数字孪生已存在,它将被替换。
实现 Azure 数字孪生中的数字孪生和关系管理
在本教程中,我们将详细探讨如何在 Azure 数字孪生中创建和管理数字孪生实例及其关系,并利用查询功能来获取环境信息。以下步骤将带你完成创建数字孪生实例,建立关系,以及查询数字孪生的过程。
创建和初始化数字孪生
首先,你需要在 Main
方法中添加代码来初始化和创建几个数字孪生实例。这个过程包括设置数字孪生的基础数据和元数据,以及在 Azure 数字孪生服务中注册这些实例。
using System.Text.Json;
using Azure.DigitalTwins.Core.Serialization;
// Initialize twin data
BasicDigitalTwin twinData = new BasicDigitalTwin();
twinData.Metadata.ModelId = "dtmi:com:contoso:SampleModel;1";
twinData.CustomProperties.Add("data", $"Hello World!");
string prefix = "sampleTwin-";
for (int i = 0; i < 3; i++) {
string twinId = $"{prefix}{i}";
await client.CreateOrReplaceDigitalTwinAsync(twinId, twinData);
}
在这段代码中,我们创建了三个数字孪生实例。由于使用了 upsert 语义,即使这些孪生已经存在,重新运行此代码也不会引起错误,而是会更新已有的实例。
创建关系
数字孪生实例之间的关系是通过连接操作建立的。这些连接表达了实例之间的逻辑或物理关联。
public async static Task CreateRelationship(DigitalTwinsClient client, string srcId, string targetId) {
var relationship = new BasicRelationship {
TargetId = targetId,
Name = "contains"
};
try {
string relId = $"{srcId}-contains->{targetId}";
await client.CreateRelationshipAsync(srcId, relId, JsonSerializer.Serialize(relationship));
Console.WriteLine("Created relationship successfully");
} catch (RequestFailedException rex) {
Console.WriteLine($"Create relationship error: {rex.Status}:{rex.Message}");
}
}
// Connect the twins with relationships
await CreateRelationship(client, "sampleTwin-0", "sampleTwin-1");
await CreateRelationship(client, "sampleTwin-0", "sampleTwin-2");
列出关系
了解数字孪生之间的关系可以帮助我们更好地理解整个环境的结构。
public async static Task ListRelationships(DigitalTwinsClient client, string srcId) {
try {
AsyncPageable<string> results = client.GetRelationshipsAsync(srcId);
Console.WriteLine($"Twin {srcId} is connected to:");
await foreach (var rel in results) {
var brel = JsonSerializer.Deserialize<BasicRelationship>(rel);
Console.WriteLine($" -{brel.Name}->{brel.TargetId}");
}
} catch (RequestFailedException rex) {
Console.WriteLine($"Relationship retrieval error: {rex.Status}:{rex.Message}");
}
}
// List the relationships
await ListRelationships(client, "sampleTwin-0");
查询数字孪生
Azure 数字孪生服务提供了强大的查询功能,允许用户检索有关数字孪生图中实体的详细信息。
// Run a query
AsyncPageable<string> result = client.QueryAsync("Select * From DigitalTwins");
await foreach (var twin in result) {
var jsonObj = JsonSerializer.Deserialize<object>(twin);
string prettyTwin = JsonSerializer.Serialize(jsonObj, new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(prettyTwin);
Console.WriteLine("---------------");
}
这段代码将查询并显示服务中所有数字孪生的详细信息,以美观的格式输出。
通过上述步骤,你可以在 Azure 数字孪生平台上有效地管理数字孪生及其关系,利用查询功能进行深入分析。这些操作为构建复杂的 IoT 解决方案提供了坚实的基础。
6. 完整代码示例
到本教程的此阶段,你已有一个完整的客户端应用,能够对 Azure 数字孪生执行基本操作。 下面列出了Program.cs 中的程序的完整代码供你参考:
using System;
using Azure.DigitalTwins.Core;
using Azure.Identity;
using System.Threading.Tasks;
using System.IO;
using System.Collections.Generic;
using Azure;
using Azure.DigitalTwins.Core.Models;
using Azure.DigitalTwins.Core.Serialization;
using System.Text.Json;
namespace minimal
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("Hello World!");
string clientId = "<your-application-ID>";
string tenantId = "<your-directory-ID>";
string adtInstanceUrl = "https://<your-Azure-Digital-Twins-instance-hostName>";
var credentials = new InteractiveBrowserCredential(tenantId, clientId);
DigitalTwinsClient client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credentials);
Console.WriteLine($"Service client created – ready to go");
Console.WriteLine();
Console.WriteLine($"Upload a model");
var typeList = new List<string>();
string dtdl = File.ReadAllText("SampleModel.json");
typeList.Add(dtdl);
// Upload the model to the service
try {
await client.CreateModelsAsync(typeList);
} catch (RequestFailedException rex) {
Console.WriteLine($"Load model: {rex.Status}:{rex.Message}");
}
// Read a list of models back from the service
AsyncPageable<ModelData> modelDataList = client.GetModelsAsync();
await foreach (ModelData md in modelDataList)
{
Console.WriteLine($"Type name: {md.DisplayName}: {md.Id}");
}
// Initialize twin data
BasicDigitalTwin twinData = new BasicDigitalTwin();
twinData.Metadata.ModelId = "dtmi:com:contoso:SampleModel;1";
twinData.CustomProperties.Add("data", $"Hello World!");
string prefix="sampleTwin-";
for(int i=0; i<3; i++) {
try {
twinData.Id = $"{prefix}{i}";
await client.CreateDigitalTwinAsync($"{prefix}{i}", JsonSerializer.Serialize(twinData));
Console.WriteLine($"Created twin: {prefix}{i}");
} catch(RequestFailedException rex) {
Console.WriteLine($"Create twin error: {rex.Status}:{rex.Message}");
}
}
// Connect the twins with relationships
await CreateRelationship(client, "sampleTwin-0", "sampleTwin-1");
await CreateRelationship(client, "sampleTwin-0", "sampleTwin-2");
//List the relationships
await ListRelationships(client, "sampleTwin-0");
// Run a query
AsyncPageable<string> result = client.QueryAsync("Select * From DigitalTwins");
await foreach (string twin in result)
{
object jsonObj = JsonSerializer.Deserialize<object>(twin);
string prettyTwin = JsonSerializer.Serialize(jsonObj, new JsonSerializerOptions {
WriteIndented = true });
Console.WriteLine(prettyTwin);
Console.WriteLine("---------------");
}
}
public async static Task CreateRelationship(DigitalTwinsClient client, string srcId, string targetId)
{
var relationship = new BasicRelationship
{
TargetId = targetId,
Name = "contains"
};
try
{
string relId = $"{srcId}-contains->{targetId}";
await client.CreateRelationshipAsync(srcId, relId, JsonSerializer.Serialize(relationship));
Console.WriteLine("Created relationship successfully");
}
catch (RequestFailedException rex) {
Console.WriteLine($"Create relationship error: {rex.Status}:{rex.Message}");
}
}
public async static Task ListRelationships(DigitalTwinsClient client, string srcId)
{
try {
AsyncPageable<string> results = client.GetRelationshipsAsync(srcId);
Console.WriteLine($"Twin {srcId} is connected to:");
await foreach (string rel in results)
{
var brel = JsonSerializer.Deserialize<BasicRelationship>(rel);
Console.WriteLine($" -{brel.Name}->{brel.TargetId}");
}
} catch (RequestFailedException rex) {
Console.WriteLine($"Relationship retrieval error: {rex.Status}:{rex.Message}");
}
}
}
}
清理 Azure 数字孪生教程资源
完成本教程后,你可能需要决定是否保留资源以用于未来的学习或进行清理。这里将指导你如何根据需求删除或保留在 Azure 数字孪生教程中创建的资源。
保留资源
如果你计划继续学习更多关于 Azure 数字孪生的教程,如“使用示例客户端应用了解基础知识”,建议保留这些资源。这样,你可以在后续教程中重用已配置的 Azure 数字孪生实例和相关的 Azure 资源,避免重复配置的工作。
删除资源
如果你不打算再使用本教程中创建的资源,建议按照以下步骤进行清理,以避免不必要的费用:
-
删除资源组:
使用 Azure Cloud Shell 或 Azure CLI,你可以删除包含所有相关 Azure 资源的资源组。这是一个彻底的清理步骤,将移除资源组及其内所有的资源,包括 Azure 数字孪生实例。az group delete --name <your-resource-group> --yes --no-wait
在运行此命令前,请确保指定正确的资源组名称,以防误删其他重要资源。
-
删除 Azure Active Directory 应用注册:
如果为本教程创建了特定的 Azure AD 应用程序注册,且不再需要,应将其删除。这步骤有助于清理未使用的凭证和配置。az ad app delete --id <your-application-ID>
确保你输入正确的应用程序 ID,以避免删除错误的应用注册。
-
删除本地项目文件:
如果你在本地计算机上创建了项目文件夹用于本教程,并决定不再需要这些文件,可以安全地将其删除。这有助于保持你的开发环境整洁。rm -rf /path/to/your/project-folder
注意事项
-
删除资源组和 Azure AD 应用注册是不可逆的操作,一旦执行,所有相关资源将被永久删除。执行这些操作前,请确保你已备份必要数据并验证资源是否可以安全删除。
-
在删除任何资源前,仔细检查是否有其他依赖或项目可能受到影响。如果不确定,可以暂时保留资源或咨询技术支持。
通过以上步骤,你可以有效地管理你的 Azure 资源,确保在不需要时进行适当的清理,同时也准备好资源以支持未来的学习和开发需求。