Udostępnij przez


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 zalecamy 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 składni, należy dostarczyć jej zestaw dokumentów DTDL. Zazwyczaj pobierasz te dokumenty modelu z usługi, ale mogą być również dostępne lokalnie, jeśli klient był odpowiedzialny za przesłanie ich do usługi na początku.

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 weryfikuje zestaw przekazanych dokumentów i zwraca 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 DTDL dla twojego cyfrowego bliźniaka. 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 wesprzeć poniższy przykład kodu analizatora, rozważ kilka modeli zdefiniowanych w instancji 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 tworzenia modeli, dowiedz się, jak je przesłać (i wykonywać inne operacje zarządzania) za pomocą API Modeli usługi Azure Digital Twins.