Analizowanie i weryfikowanie modeli za pomocą biblioteki analizatora DTDL

W tym artykule opisano sposób analizowania i weryfikowania modeli usługi Azure Digital Twins przy użyciu biblioteki analizatora platformy .NET.

Modele w usłudze Azure Digital Twins są definiowane przy użyciu języka JSON-LD Digital Twins Definition Language (DTDL).

Po utworzeniu modelu zaleca się zweryfikowanie modeli w trybie offline przed przekazaniem ich do wystąpienia usługi Azure Digital Twins.

Aby ułatwić weryfikowanie modeli, biblioteka analizy DTDL po stronie klienta platformy .NET jest udostępniana w usłudze NuGet: DTDLParser. Bibliotekę analizatora można używać bezpośrednio w kodzie języka C#. Przykładowe użycie analizatora można również wyświetlić w pliku DTDLParserResolveSample w usłudze GitHub.

Informacje o bibliotece analizatora platformy .NET

Biblioteka DTDLParser zapewnia dostęp modelu do definicji DTDL, zasadniczo działając jako odpowiednik odbicia języka C# dla języka DTDL. Ta biblioteka może być używana niezależnie od dowolnego zestawu SDK usługi Azure Digital Twins, zwłaszcza w przypadku weryfikacji języka DTDL w edytorze wizualizacji lub tekstu. Warto upewnić się, że pliki definicji modelu są prawidłowe przed próbą przekazania ich do usługi.

Aby użyć biblioteki analizatora, należy podać go z zestawem dokumentów DTDL. Zazwyczaj te dokumenty modelu można pobrać z usługi, ale może być również dostępne lokalnie, jeśli klient był odpowiedzialny za przekazanie ich do usługi w pierwszej kolejności.

Oto ogólny przepływ pracy dotyczący korzystania z analizatora:

  1. Pobierz niektóre lub wszystkie dokumenty DTDL z usługi.
  2. Przekaż zwrócone dokumenty DTDL w pamięci do analizatora.
  3. Analizator zweryfikuje przekazany zestaw dokumentów i zwróci szczegółowe informacje o błędzie. Ta możliwość jest przydatna w scenariuszach edytora.
  4. Użyj interfejsów API analizatora, aby kontynuować analizowanie modeli zawartych w zestawie dokumentów.

Możliwości analizatora obejmują:

  • Pobierz wszystkie zaimplementowane interfejsy modelu (zawartość sekcji interfejsu extends ).
  • Pobierz wszystkie właściwości, dane telemetryczne, polecenia, składniki i relacje zadeklarowane w modelu. To polecenie pobiera również wszystkie metadane zawarte w tych definicjach i bierze pod uwagę dziedziczenie (extends sekcje).
  • Pobierz wszystkie złożone definicje modelu.
  • Ustal, czy model można przypisać z innego modelu.

Uwaga

Urządzenia IoT Plug and Play używają niewielkiego wariantu składni, aby opisać ich funkcjonalność. Ten wariant składni jest semantycznie zgodnym podzestawem dtDL używanym w usłudze Azure Digital Twins. W przypadku korzystania z biblioteki analizatora nie musisz wiedzieć, który wariant składni został użyty do utworzenia języka DTDL dla cyfrowej reprezentacji bliźniaczej. Analizator zawsze będzie domyślnie zwracał ten sam model dla składni IoT Plug and Play i Azure Digital Twins.

Kod z biblioteką analizatora

Bibliotekę analizatora można używać bezpośrednio w celu sprawdzania poprawności modeli we własnej aplikacji lub generowania dynamicznego, opartego na modelu interfejsu użytkownika, pulpitów nawigacyjnych i raportów.

Aby obsparować poniższy przykład kodu analizatora, rozważ kilka modeli zdefiniowanych w wystąpieniu usługi 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"
        }
      ]
    }
  ]

Poniższy kod przedstawia przykład użycia biblioteki analizatora do odzwierciedlenia tych definicji w języku 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;                
                }
            }
        }
    }
}

Następne kroki

Po zakończeniu pisania modeli zobacz, jak je przekazać (i wykonywać inne operacje zarządzania) za pomocą interfejsów API modeli usługi Azure Digital Twins: