Share via


Analysieren und Validieren von Modellen mit der DTDL-Parserbibliothek

In diesem Artikel wird beschrieben, wie Sie Azure Digital Twins-Modelle mithilfe der .NET-Parserbibliothek analysieren und validieren.

Modelle in Azure Digital Twins werden mithilfe der auf JSON-LD basierenden Sprache DTDL (Digital Twins Definition Language) definiert.

Nachdem Sie ein Modell erstellt haben, sollten Sie Ihre Modelle offline validieren, bevor Sie sie in Ihre Azure Digital Twins-Instanz hochladen.

Um Ihre Modelle zu überprüfen, wird eine clientseitige DTDL-Analysebibliothek für .NET auf NuGet: DTDLParser bereitgestellt. Sie können die Parserbibliothek direkt in Ihrem C#-Code verwenden. Sie können auch die Beispielverwendung des Parsers im DTDLParserResolveSample in GitHub anzeigen.

Informationen zur .NET-Parserbibliothek

Die DTDLParser-Bibliothek bietet Modellzugriff auf die DTDL-Definitionen, die im Wesentlichen als Äquivalent der C#-Spiegelung für DTDL fungieren. Diese Bibliothek kann unabhängig von jedem Azure Digital Twins SDK verwendet werden, insbesondere für die DTDL-Validierung in einem grafischen- oder Texteditor. Sie ist nützlich, um sicherzustellen, dass Ihre Modelldefinitionsdateien gültig sind, ehe Sie versuchen, sie in den Dienst hochzuladen.

Um die Parserbibliothek verwenden zu können, müssen Sie ihr eine Gruppe von DTDL-Dokumenten zur Verfügung stellen. Normalerweise würden Sie diese Musterdokumente aus dem Dienst abrufen, aber Sie könnten sie auch lokal verfügbar haben, wenn Ihr Client in erster Linie für das Hochladen in den Dienst zuständig ist.

Dies ist der allgemeine Workflow für die Verwendung des Parsers:

  1. Rufen Sie einige oder alle DTDL-Dokumente aus dem Dienst ab.
  2. Übergeben Sie die zurückgegebenen, speicherinternen DTDL-Dokumente an den Parser.
  3. Der Parser überprüft die an ihn weitergegebene Dokumentgruppe und gibt detaillierte Fehlerinformationen zurück. Dies ist in Editorszenarien nützlich.
  4. Verwenden Sie die Parser-APIs, um die Analyse der in der Dokumentengruppe enthaltenen Modelle fortzusetzen.

Der Parser bietet die folgenden Funktionen:

  • Abrufen aller implementierten Modellschnittstellen (Inhalt des Abschnitts extends der Schnittstelle)
  • Abrufen sämtlicher im Modell deklarierter Eigenschaften, Telemetrie, Befehle, Komponenten und Beziehungen Dieser Befehl dient auch zum Abrufen aller Metadaten, die in diesen Definitionen enthalten sind, und berücksichtigt die Vererbung (extends-Abschnitte).
  • Abrufen aller komplexer Modelldefinitionen
  • Bestimmen, ob ein Modell aus einem anderen Modell zugewiesen werden kann

Hinweis

IoT Plug & Play-Geräte arbeiten mit einer geringfügig anderen Syntaxvariante, um ihre Funktionalität zu beschreiben. Diese Syntaxvariante ist eine semantisch kompatible Teilmenge der Sprache DTDL, die in Azure Digital Twins verwendet wird. Wenn Sie die Parserbibliothek nutzen, müssen Sie nicht wissen, welche Syntaxvariante zur Erstellung der DTDL für Ihren Digital Twin verwendet wurde. Der Parser gibt für die IoT Plug & Play- und Azure Digital Twins-Syntax standardmäßig stets dasselbe Modell zurück.

Codieren mit der Parserbibliothek

Sie können die Parserbibliothek direkt verwenden, z. B. für die Überprüfung von Modellen in Ihrer eigenen Anwendung oder für die Generierung dynamischer, modellgesteuerter Benutzeroberflächen, Dashboards und Berichte.

Zur Unterstützung des nachstehenden Parsercodebeispiels betrachten Sie mehrere Modelle, die in einer Azure Digital Twins-Instanz definiert sind:

[
    {
      "@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"
        }
      ]
    }
  ]

Der folgende Code zeigt ein Beispiel für die Verwendung der Parserbibliothek, um diese Definitionen in C# wiederzugeben:

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;                
                }
            }
        }
    }
}

Nächste Schritte

Nachdem Sie ihre Modelle geschrieben haben, erfahren Sie, wie Sie diese (und andere Verwaltungsvorgänge) mit den Azure Digital Twins Models-APIs hochladen: