Mengurai dan memvalidasi model dengan pustaka pengurai DTDL

Artikel ini menjelaskan cara mengurai dan memvalidasi model Azure Digital Twins menggunakan pustaka pengurai .NET.

Model di Azure Digital Twins ditentukan menggunakan bahasa Digital Twins Definition (DTDL) berbasis JSON-LD.

Setelah membuat model, disarankan untuk memvalidasi model Anda secara offline sebelum mengunggahnya ke instans Azure Digital Twins Anda.

Untuk membantu Anda memvalidasi model, pustaka penguraian DTDL sisi klien .NET disediakan di NuGet: DTDLParser. Anda dapat menggunakan pustaka pengurai langsung dalam kode C#Anda. Anda juga dapat melihat penggunaan sampel pengurai di DTDLParserResolveSample di GitHub.

Tentang pustaka pengurai .NET

Pustaka DTDLParser menyediakan akses model ke definisi DTDL, pada dasarnya bertindak sebagai setara dengan refleksi C# untuk DTDL. Pustaka ini dapat digunakan secara terpisah dari Azure Digital Twins SDK, terutama untuk validasi DTDL dalam editor visual atau teks. Berguna untuk memastikan file definisi model Anda valid sebelum Anda mencoba mengunggahnya ke layanan.

Untuk menggunakan pustaka pengurai, Anda menyediakannya dengan satu set dokumen DTDL. Biasanya, Anda akan mengambil dokumen model ini dari layanan, tetapi Anda mungkin juga menyediakannya secara lokal, jika klien Anda bertanggung jawab untuk mengunggahnya ke layanan sejak awal.

Berikut adalah alur kerja umum untuk menggunakan pengurai:

  1. Mengambil beberapa atau semua dokumen DTDL dari layanan.
  2. Menerukskan dokumen DTDL dalam memori yang dikembalikan ke pengurai.
  3. Pengurai akan memvalidasi kumpulan dokumen yang diteruskan ke sana, dan mengembalikan informasi kesalahan terperinci. Kemampuan ini berguna dalam skenario editor.
  4. Gunakan API pengurai untuk terus menganalisis model yang disertakan dalam kumpulan dokumen.

Kemampuan pengurai meliputi:

  • Dapatkan semua antarmuka model yang diterapkan (isi dari bagian extends antarmuka).
  • Dapatkan semua properti, telemetri, perintah, komponen, dan hubungan yang dideklarasikan dalam model. Perintah ini juga memasukkan semua metadata dalam definisi ini, dan memperhitungkan warisan (extends bagian).
  • Mendapatkan semua definisi model yang kompleks.
  • Menentukan apakah suatu model dapat dialihkan dari model lain.

Catatan

Perangkat IoT Plug and Play menggunakan varian sintaks kecil untuk menjelaskan fungsinya. Varian sintaks ini adalah subset DTDL kompatibel secara semantik yang digunakan di Azure Digital Twins. Saat menggunakan pustaka pengurai, Anda tidak perlu mengetahui varian sintaksis mana yang digunakan untuk membuat DTDL untuk kembar digital Anda. Pengurai akan selalu, secara default, mengembalikan model yang sama untuk sintaks IoT Plug and Play dan Azure Digital Twins.

Kode dengan pustaka pengurai

Anda dapat menggunakan pustaka pengurai secara langsung, untuk hal-hal seperti memvalidasi model dalam aplikasi Anda sendiri atau untuk menghasilkan UI, dasbor, dan laporan yang dinamis berdasarkan model.

Untuk mendukung contoh kode pengurai di bawah ini, pertimbangkan beberapa model yang ditentukan dalam instans 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"
        }
      ]
    }
  ]

Kode berikut menunjukkan contoh cara menggunakan pustaka pengurai untuk merefleksikan definisi ini di 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;                
                }
            }
        }
    }
}

Langkah berikutnya

Setelah selesai menulis model, lihat cara mengunggahnya (dan melakukan operasi manajemen lainnya) dengan API Model Azure Digital Twins: