Dela via


Parsa och validera modeller med DTDL-parserbiblioteket

Den här artikeln beskriver hur du parsar och validerar Azure Digital Twins-modeller med hjälp av .

Modeller i Azure Digital Twins definieras med hjälp av det JSON-LD-baserade DTDL-språket (Digital Twins Definition).

När du har skapat en modell rekommenderar vi att du verifierar dina modeller offline innan du laddar upp dem till din Azure Digital Twins-instans.

För att hjälpa dig att verifiera dina modeller finns ett DTDL-parsningsbibliotek på .NET-klientsidan på NuGet: DTDLParser. Du kan använda parsningsbiblioteket direkt i C#-koden. Du kan också visa exempelanvändningen av parsern i DTDLParserResolveSample i GitHub.

Om .NET parser-biblioteket

Biblioteket DTDLParser ger modellåtkomst till DTDL-definitionerna och fungerar i princip som motsvarigheten till C#-reflektion för DTDL. Det här biblioteket kan användas oberoende av Azure Digital Twins SDK, särskilt för DTDL-validering i en visuell redigerare eller textredigerare. Det är användbart för att se till att dina modelldefinitionsfiler är giltiga innan du försöker ladda upp dem till tjänsten.

Om du vill använda parserbiblioteket anger du en uppsättning DTDL-dokument. Vanligtvis hämtar du dessa modelldokument från tjänsten, men du kan också ha dem tillgängliga lokalt, om klienten var ansvarig för att ladda upp dem till tjänsten från början.

Här är det allmänna arbetsflödet för att använda parsern:

  1. Hämta några eller alla DTDL-dokument från tjänsten.
  2. Skicka de returnerade, minnesinterna DTDL-dokumenten till parsern.
  3. Parsern validerar den uppsättning dokument som skickas till den och returnerar detaljerad felinformation. Den här möjligheten är användbar i redigeringsscenarier.
  4. Använd parser-API:erna för att fortsätta analysera de modeller som ingår i dokumentuppsättningen.

Funktionerna i parsern är:

  • Hämta alla implementerade modellgränssnitt (innehållet i gränssnittets extends avsnitt).
  • Hämta alla egenskaper, telemetri, kommandon, komponenter och relationer som deklarerats i modellen. Det här kommandot hämtar också alla metadata som ingår i dessa definitioner och tar hänsyn till arv (extends sections).
  • Hämta alla komplexa modelldefinitioner.
  • Bestäm om en modell kan tilldelas från en annan modell.

Anmärkning

IoT Plug and Play enheter använder en liten syntaxvariant för att beskriva sina funktioner. Den här syntaxvarianten är en semantiskt kompatibel delmängd av DTDL som används i Azure Digital Twins. När du använder parsningsbiblioteket behöver du inte veta vilken syntaxvariant som användes för att skapa DTDL för din digitala tvilling. Parsern returnerar alltid, som standard, samma modell för både IoT Plug and Play och Azure Digital Twins syntax.

Kod med parserbiblioteket

Du kan använda parserbiblioteket direkt, till exempel för att validera modeller i ditt eget program eller för att generera dynamiskt, modelldrivet användargränssnitt, instrumentpaneler och rapporter.

För att stödja följande exempel på parserkod bör du överväga flera modeller som definierats i en Azure Digital Twins instans:

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

Följande kod visar ett exempel på hur du använder parserbiblioteket för att reflektera över dessa definitioner i 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;                
                }
            }
        }
    }
}

Nästa steg

När du är klar med att skriva dina modeller kan du se hur du laddar upp dem (och utför andra hanteringsåtgärder) med API:erna för Azure Digital Twins-modeller: