Поделиться через


Анализ и проверка моделей с помощью библиотеки синтаксического анализатора DTDL

В этой статье описывается анализ и проверка моделей Azure Digital Twins с помощью библиотеки синтаксического анализа .NET.

Модели для Azure Digital Twins определяются с помощью языка определения цифровых двойников с использованием JSON-LD (DTDL).

После создания моделей их рекомендуется проверить в автономном режиме перед отправкой в экземпляр Azure Digital Twins.

Чтобы помочь вам проверить модели, клиентская библиотека анализа DTDL на стороне клиента .NET предоставляется в NuGet: DTDLParser. Библиотеку синтаксического анализа можно использовать непосредственно в коде C#. Вы также можете просмотреть пример использования средства синтаксического анализа в DTDLParserResolveSample в GitHub.

Сведения о библиотеке синтаксического анализа .NET

Библиотека DTDLParser предоставляет доступ к определениям DTDL модели, в основном выступая в качестве эквивалента отражения C# для DTDL. Эту библиотеку можно использовать независимо от любого пакета SDK для Azure Digital Twins, особенно для проверки DTDL в визуальном или текстовом редакторе. Рекомендуется убедиться, что файлы определения модели действительны, прежде чем пытаться передать их в службу.

Чтобы использовать библиотеку синтаксического анализатора, предоставьте ей набор документов DTDL. Как правило, эти документы модели извлекаются из службы, но они также могут быть доступны локально, если клиент в первую очередь отвечал за их передачу в службу.

Ниже приведен общий рабочий процесс для использования средства синтаксического анализа:

  1. Извлеките некоторые или все документы DTDL из службы.
  2. Передайте возвращенные документы DTDL в памяти в средство синтаксического анализа.
  3. Средство синтаксического анализа проверяет набор документов, переданных в него, и возвращает подробные сведения об ошибках. Это полезно для сценариев редакторов.
  4. Используйте API средства синтаксического анализа, чтобы продолжить анализ моделей, входящих в набор документов.

Возможности средства синтаксического анализа

  • Получение всех реализованных интерфейсов модели (содержимое раздела extends интерфейса).
  • Возврат всех свойств, данных телеметрии, команд, компонентов и связей, объявленных в модели. Эта команда также получает все метаданные, содержащиеся в этих определениях, и учитывает наследование (разделы extends).
  • Получение всех определений сложных моделей.
  • Определите, может ли модель быть назначена другой модели.

Примечание.

В устройствах IoT Plug and Play используется небольшая вариация синтаксиса для описания их функциональности. Этот вариант синтаксиса является семантически совместимым подмножеством DTDL, которое используется в Azure Digital Twins. При использовании библиотеки синтаксического анализатора нет необходимости знать, какой вариант синтаксиса использовался для создания DTDL для цифрового двойника. Средство синтаксического анализатора по умолчанию всегда возвращает одну модель для синтаксиса IoT Plug and Play и Azure Digital Twins.

Код с библиотекой синтаксического анализатора

Библиотеку синтаксического анализатора можно использовать напрямую, например для проверки моделей в собственном приложении или для создания динамического, управляемого моделями пользовательского интерфейса, панелей мониторинга и отчетов.

Для поддержки приведенного ниже примера кода средства синтаксического анализа рассмотрим несколько моделей, определенных в экземпляре Azure Digital Twins.

[
    {
      "@context": "dtmi:dtdl:context;3",
      "@id": "dtmi:com:contoso:coffeeMaker;1",
      "@type": "Interface",
      "contents": [
        {
          "@type": "Component",
          "name": "coffeeMaker",
          "schema": "dtmi:com:contoso:coffeeMakerInterface;1"
        }
      ]
    },
    {
      "@context": "dtmi:dtdl:context;3",
      "@id": "dtmi:com:contoso:coffeeMakerInterface;1",
      "@type": "Interface",
      "contents": [
        {
          "@type": "Property",
          "name": "waterTemp",
          "schema": "double"
        }
      ]
    },
    {
      "@context": "dtmi:dtdl:context;3",
      "@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 DTDLParser;
using DTDLParser.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DigitalTwins_Samples
{
    public static class ListExtensions
    {
        public static async IAsyncEnumerable<T> AsAsyncEnumerable<T>(this IEnumerable<T> input)
        {
            foreach (var value in input)
            {
                yield return value;
            }
            await Task.Yield();
        }
    }

    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.AsAsyncEnumerable());

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

Следующие шаги

После написания моделей вы узнаете, как отправить их (и выполнять другие операции управления) с помощью API моделей Azure Digital Twins: