تحليل النماذج والتحقق من صحتها باستخدام مكتبة محلل DTDL

توضح هذه المقالة كيفية تحليل نماذج Azure Digital Twins والتحقق من صحتها باستخدام مكتبة محلل .NET.

يتم تعريف النماذج في Azure Digital Twins باستخدام لغة تعريف Digital Twins المستندة إلى JSON-LD (DTDL).

بعد إنشاء نموذج، يوصى بالتحقق من صحة نماذجك دون اتصال قبل تحميلها إلى مثيل Azure Digital Twins.

لمساعدتك في التحقق من صحة النماذج الخاصة بك، يتم توفير مكتبة تحليل DTDL من جانب عميل .NET على NuGet: DTDLParser. يمكنك استخدام مكتبة المحلل مباشرة في التعليمات البرمجية C#. يمكنك أيضا عرض نموذج استخدام المحلل في DTDLParserResolveSample في GitHub.

حول مكتبة محلل .NET

توفر مكتبة DTDLParser وصول النموذج إلى تعريفات DTDL، وتعمل بشكل أساسي كمكافئ لعكس C# ل DTDL. يمكن استخدام هذه المكتبة بشكل مستقل عن أي Azure Digital Twins SDK، خاصة للتحقق من صحة DTDL في محرر مرئي أو نص. من المفيد التأكد من أن ملفات تعريف النموذج صالحة قبل محاولة تحميلها إلى الخدمة.

لاستخدام مكتبة المحلل، يمكنك تزويدها بمجموعة من مستندات DTDL. عادة، يمكنك استرداد مستندات النموذج هذه من الخدمة، ولكن قد تكون متوفرة أيضا محليا، إذا كان العميل مسؤولا عن تحميلها إلى الخدمة في المقام الأول.

فيما يلي سير العمل العام لاستخدام المحلل:

  1. استرداد بعض مستندات DTDL أو كلها من الخدمة.
  2. مرر مستندات DTDL التي تم إرجاعها في الذاكرة إلى المحلل.
  3. سيقوم المحلل بالتحقق من صحة مجموعة المستندات التي تم تمريرها إليه، وإرجاع معلومات الخطأ التفصيلية. هذه القدرة مفيدة في سيناريوهات المحرر.
  4. استخدم واجهات برمجة تطبيقات المحلل لمتابعة تحليل النماذج المضمنة في مجموعة المستندات.

تتضمن قدرات المحلل ما يلي:

  • احصل على جميع واجهات النموذج المنفذة (محتويات قسم الواجهة extends ).
  • احصل على جميع الخصائص وبيانات تتبع الاستخدام والأوامر والمكونات والعلاقات المعلن عنها في النموذج. يحصل هذا الأمر أيضا على جميع بيانات التعريف المضمنة في هذه التعريفات، ويأخذ التوريث (extends المقاطع) في الاعتبار.
  • احصل على جميع تعريفات النموذج المعقدة.
  • تحديد ما إذا كان النموذج قابلا للتعيين من نموذج آخر.

إشعار

تستخدم أجهزة IoT أجهزة التوصيل و التشغيل متغير بناء جملة صغير لوصف وظائفها. متغير بناء الجملة هذا هو مجموعة فرعية متوافقة دلاليا من DTDL المستخدمة في Azure Digital Twins. عند استخدام مكتبة المحلل، لا تحتاج إلى معرفة متغير بناء الجملة الذي تم استخدامه لإنشاء DTDL للتوأم الرقمي الخاص بك. سيقوم المحلل دائما، بشكل افتراضي، بإرجاع نفس النموذج لكل من بناء جملة IoT أجهزة التوصيل و التشغيل وAzure Digital Twins.

التعليمات البرمجية مع مكتبة المحلل

يمكنك استخدام مكتبة المحلل مباشرة، لأشياء مثل التحقق من صحة النماذج في التطبيق الخاص بك أو لإنشاء واجهة مستخدم ديناميكية تستند إلى النموذج ولوحات المعلومات والتقارير.

لدعم مثال التعليمات البرمجية للموزع أدناه، ضع في اعتبارك العديد من النماذج المحددة في مثيل 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"
        }
      ]
    }
  ]

توضح التعليمات البرمجية التالية مثالا على كيفية استخدام مكتبة المحلل للتفكير في هذه التعريفات في 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;                
                }
            }
        }
    }
}

الخطوات التالية

بمجرد الانتهاء من كتابة النماذج الخاصة بك، راجع كيفية تحميلها (والقيام بعمليات إدارة أخرى) باستخدام واجهات برمجة تطبيقات نماذج Azure Digital Twins: