你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
使用 DTDL 分析程序库分析和验证模型
本文介绍如何使用 DTDL 验证程序示例或 .NET 分析器库来分析和验证 Azure 数字孪生模型。
Azure 数字孪生中的模型是使用基于 JSON-LD 的数字孪生定义语言 (DTDL) 定义的。 建议先离线验证你的模型,然后再将其上传到你的 Azure 数字孪生实例。
为帮助你验证模型,NuGet 上提供了一个 .NET 客户端 DTDL 分析库:Microsoft.Azure.DigitalTwins.Parser。
你可以直接在 C# 代码中使用分析程序库,也可以使用基于分析程序库构建的与语言无关的代码示例项目:DTDL 验证程序示例。
使用 DTDL 验证程序示例
DTDL 验证程序是一个示例项目,它可以对模型文档进行验证以确保 DTDL 有效。 它是基于 .NET 分析程序库构建的,与语言无关。
可以通过选择示例链接上的“浏览代码”按钮查看 GitHub 中的代码,也可以通过依次选择“代码”按钮和“下载 ZIP”从 GitHub 下载项目 。
源代码显示了有关如何使用分析程序库的示例。 可以将验证程序示例用作命令行实用工具来验证 DTDL 文件的目录树。 它还提供交互模式。
在 DTDL 验证程序示例的文件夹中查看 readme.md 文件,了解如何将示例打包为独立的可执行文件。
构建独立的程序包并将可执行文件添加到你的路径后,可以在计算机上的控制台中使用以下命令运行该验证程序:
DTDLValidator
示例将使用默认选项在当前目录和所有子目录中搜索 .json 文件。 你还可以添加以下选项,让示例在指定的目录和所有子目录中搜索扩展名为 .dtdl 的文件:
DTDLValidator -d C:\Work\DTDL -e dtdl
可以为示例添加 -i
选项以进入交互模式:
DTDLValidator -i
有关此示例的详细信息,请参阅源代码或运行 DTDLValidator --help
。
使用 .NET 分析程序库
Microsoft.Azure.DigitalTwins.Parser 库提供对 DTDL 定义的模型访问权限,本质上相当于 DTDL 的 C# 反射。 此库可独立于任何 Azure 数字孪生 SDK 使用,尤其适合在可视化编辑器或文本编辑器中进行 DTDL 验证。 使用它,可以在尝试将模型定义文件上传到服务之前确保这些文件有效。
若要使用分析程序库,请向其提供一组 DTDL 文档。 通常情况下,你将从服务中检索这些模型文档,但如果你的客户端从一开始就负责将它们上传到服务中,则也可在本地获取它们。
下面是使用分析程序的一般工作流:
- 从服务中检索部分或全部 DTDL 文档。
- 将返回的内存中 DTDL 文档传递到分析程序。
- 分析程序会验证传递给它的文档集,并返回详细的错误信息。 这种功能在编辑器场景中很有用。
- 使用分析程序 API 继续分析文档集中包括的模型。
分析程序的功能包括:
- 获取所实现的所有模型接口(接口的
extends
节的内容)。 - 获取在模型中声明的所有属性、遥测、命令、组件和关系。 此命令还获取这些定义中包括的所有元数据,并且会考虑到继承(
extends
节)。 - 获取所有复杂的模型定义。
- 确定模型是否可从另一个模型分配。
注意
IoT 即插即用设备使用小语法变体来描述其功能。 此语法变体是 Azure 数字孪生中使用的 DTDL 的一个子集,在语义上与其兼容。 使用分析程序库时,你不需要知道数字孪生体的 DTDL 是使用哪种语法变体创建的。 默认情况下,对于 IoT 即插即用语法和 Azure 数字孪生语法,分析程序会始终返回相同的模型。
包含分析程序库的代码
你可以直接将分析程序库用于下述用途:在你自己的应用程序中验证模型,或者生成动态的、模型驱动的 UI、仪表板和报表。
若要支持下面的分析程序代码示例,请考虑 Azure 数字孪生实例中定义的多个模型:
[
{
"@context": "dtmi:dtdl:context;2",
"@id": "dtmi:com:contoso:coffeeMaker;1",
"@type": "Interface",
"contents": [
{
"@type": "Component",
"name": "coffeeMaker",
"schema": "dtmi:com:contoso:coffeeMakerInterface;1"
}
]
},
{
"@context": "dtmi:dtdl:context;2",
"@id": "dtmi:com:contoso:coffeeMakerInterface;1",
"@type": "Interface",
"contents": [
{
"@type": "Property",
"name": "waterTemp",
"schema": "double"
}
]
},
{
"@context": "dtmi:dtdl:context;2",
"@id": "dtmi:com:contoso:coffeeBar;1",
"@type": "Interface",
"contents": [
{
"@type": "Relationship",
"name": "foo",
"target": "dtmi:com:contoso:coffeeMaker;1"
},
{
"@type": "Property",
"name": "capacity",
"schema": "integer"
}
]
}
]
以下代码显示的示例展示了如何在 C# 中使用分析程序库来反映这些定义:
using Azure;
using Azure.DigitalTwins.Core;
using Microsoft.Azure.DigitalTwins.Parser;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DigitalTwins_Samples
{
public class ParseModelsSample
{
public async Task ParseDemoAsync(DigitalTwinsClient client)
{
try
{
AsyncPageable<DigitalTwinsModelData> mdata = client.GetModelsAsync(new GetModelsOptions { IncludeModelDefinition = true });
var models = new List<string>();
await foreach (DigitalTwinsModelData md in mdata)
models.Add(md.DtdlModel);
var parser = new ModelParser();
IReadOnlyDictionary<Dtmi, DTEntityInfo> dtdlOM = await parser.ParseAsync(models);
var interfaces = new List<DTInterfaceInfo>();
IEnumerable<DTInterfaceInfo> ifenum =
from entity in dtdlOM.Values
where entity.EntityKind == DTEntityKind.Interface
select entity as DTInterfaceInfo;
interfaces.AddRange(ifenum);
foreach (DTInterfaceInfo dtif in interfaces)
{
PrintInterfaceContent(dtif, dtdlOM);
}
}
catch (RequestFailedException ex)
{
Console.WriteLine($"Failed due to {ex}");
throw;
}
}
public void PrintInterfaceContent(DTInterfaceInfo dtif, IReadOnlyDictionary<Dtmi, DTEntityInfo> dtdlOM, int indent = 0)
{
var sb = new StringBuilder();
for (int i = 0; i < indent; i++) sb.Append(" ");
Console.WriteLine($"{sb}Interface: {dtif.Id} | {dtif.DisplayName}");
Dictionary<string, DTContentInfo> contents = dtif.Contents;
foreach (DTContentInfo item in contents.Values)
{
switch (item.EntityKind)
{
case DTEntityKind.Property:
DTPropertyInfo pi = item as DTPropertyInfo;
Console.WriteLine($"{sb}--Property: {pi.Name} with schema {pi.Schema}");
break;
case DTEntityKind.Relationship:
DTRelationshipInfo ri = item as DTRelationshipInfo;
Console.WriteLine($"{sb}--Relationship: {ri.Name} with target {ri.Target}");
break;
case DTEntityKind.Telemetry:
DTTelemetryInfo ti = item as DTTelemetryInfo;
Console.WriteLine($"{sb}--Telemetry: {ti.Name} with schema {ti.Schema}");
break;
case DTEntityKind.Component:
DTComponentInfo ci = item as DTComponentInfo;
Console.WriteLine($"{sb}--Component: {ci.Id} | {ci.Name}");
DTInterfaceInfo component = ci.Schema;
PrintInterfaceContent(component, dtdlOM, indent + 1);
break;
}
}
}
}
}
后续步骤
编写完模型后,请了解如何通过 DigitalTwinsModels API 上传它们(以及执行其他管理操作):