إدارة التوائم الرقمية

يتم تمثيل الكيانات في بيئتك بواسطة توائم رقمية. قد تتضمن إدارة توائم رقميك الإنشاء والتعديل والإزالة.

تركز هذه المقالة على إدارة التوائم الرقمية. للعمل مع العلاقات والرسم البياني المزدوج ككل، راجع إدارة الرسم البياني المزدوج والعلاقات.

تلميح

تأتي جميع وظائف SDK في إصدارات متزامنة وغير متزامنة.

المتطلبات الأساسية

للعمل مع Azure Digital Twins في هذه الوحدة، تحتاج أولاً إلى إعداد نمذجة Digital Twins. تحتاج أيضاً إلى الأذونات المطلوبة لاستخدامه. إذا كانت لديك بالفعل نمذجة لـ Azure Digital Twins تم إعدادها، فيمكنك استخدامه بدلاً من ذلك.

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

بعد إعداد النمذجة الخاصة بك، دون ملاحظة للقيم التالية. ستحتاج إلى هذه القيم للوصول لاحقاً إلى هذه النمذجة:

واجهات المطور

توضح هذه المقالة كيفية إكمال عمليات الإدارة المختلفة باستخدام .NET (C#) SDK. يمكنك أيضا صياغة استدعاءات الإدارة نفسها باستخدام مجموعات SDK باللغات الأخرى الموضحة في واجهات برمجة تطبيقات Azure Digital Twins ومجموعات SDK.

تتضمن واجهات المطورين الأخرى التي يمكن استخدامها لإكمال هذه العمليات ما يلي:

عرض البيانات بشكل بياني

Azure Digital Twins Explorer هو أداة مرئية لاستكشاف البيانات الموجودة في الرسم البياني لتوائم Azure الرقمية. يمكنك استخدام المستكشف لعرض النماذج والتوائم والعلاقات والاستعلام عنها وتحريرها.

للقراءة حول أداة Azure Digital Twins Explorer، راجع Azure Digital Twins Explorer. للحصول على خطوات مفصلة حول كيفية استخدام ميزاته، راجع استخدام Azure Digital Twins Explorer.

إليك الشكل الذي يبدو عليه التصور:

Screenshot of Azure Digital Twins Explorer showing sample models and twins.

إنشاء توأم رقمي

لإنشاء توأم، يمكنك استخدام طريقة CreateOrReplaceDigitalTwinAsync() على عميل الخدمة مثل هذا:

await client.CreateOrReplaceDigitalTwinAsync<BasicDigitalTwin>(twinId, initData);

لإنشاء توأم رقمي، عليك تقديم:

  • قيمة معرف تريد تعيينها للتوأم الرقمي (أنت تحدد هذا المعرف عند إنشاء التوأم)
  • النموذج الذي تريد استخدامه
  • أي تهيئة مطلوبة للبيانات التوأم ، بما في ذلك ...
    • الخصائص (اختيارية للتهيئة): يمكنك تعيين القيم الأولية لخصائص التوأم الرقمي إذا أردت. يتم التعامل مع الخصائص على أنها اختيارية ويمكن تعيينها لاحقا، ولكن لاحظ أنها لن تظهر كجزء من توأم حتى يتم تعيينها.
    • القياس عن بعد (يوصى بالتهيئة): يمكنك أيضا تعيين قيم أولية لحقول القياس عن بعد على التوأم. على الرغم من أن تهيئة القياس عن بعد ليست مطلوبة، إلا أن حقول القياس عن بعد لن تظهر أيضا كجزء من توأم حتى يتم تعيينها. وهذا يعني أنك لن تتمكن من تحرير قيم القياس عن بعد لتوأم ما لم تتم تهيئتها أولا.
    • المكونات (مطلوبة للتهيئة إذا كانت موجودة على التوأم): إذا كان التوأم يحتوي على أي مكونات، فيجب تهيئتها عند إنشاء التوأم. يمكن أن تكون كائنات فارغة ، ولكن المكونات نفسها يجب أن تكون موجودة.

يتم توفير النموذج وأي قيم خصائص أولية من خلال المعلمة initData ، وهي سلسلة JSON تحتوي على البيانات ذات الصلة. لمزيد من المعلومات حول هيكلة هذا الكائن، تابع إلى القسم التالي.

تلميح

بعد إنشاء توأم أو تحديثه، قد يكون هناك زمن انتقال يصل إلى 10 ثوان قبل أن تنعكس التغييرات في الاستعلامات. لا تواجه واجهة برمجة التطبيقات (الموضحة لاحقا في هذه المقالة) هذا التأخيرGetDigitalTwin، لذلك إذا كنت بحاجة إلى استجابة فورية، فاستخدم استدعاء واجهة برمجة التطبيقات بدلا من الاستعلام لرؤية التوائم التي تم إنشاؤها حديثا.

تهيئة النموذج والخصائص

يمكنك تهيئة خصائص التوأم في وقت إنشاء التوأم.

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

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

إنشاء توائم باستخدام البيانات التي تم إنشاؤها يدويا

بدون استخدام أي فئات مساعدة مخصصة ، يمكنك تمثيل خصائص التوأم في a ، حيث string يكون Dictionary<string, object>اسم الخاصية و object هو كائن يمثل الخاصية وقيمتها.

// Define a custom model type for the twin to be created

internal class CustomDigitalTwin
{
    [JsonPropertyName(DigitalTwinsJsonPropertyNames.DigitalTwinId)]
    public string Id { get; set; }

    [JsonPropertyName(DigitalTwinsJsonPropertyNames.DigitalTwinETag)]
    public string ETag { get; set; }

    [JsonPropertyName(DigitalTwinsJsonPropertyNames.DigitalTwinMetadata)]
    public MyCustomDigitalTwinMetadata Metadata { get; set; } = new MyCustomDigitalTwinMetadata();

    [JsonPropertyName("temperature")]
    public double Temperature { get; set; }

    [JsonPropertyName("humidity")]
    public double Humidity{ get; set; }
}

internal class MyCustomDigitalTwinMetadata
{
    [JsonPropertyName(DigitalTwinsJsonPropertyNames.MetadataModel)]
    public string ModelId { get; set; }

    [JsonPropertyName("temperature")]
    public DigitalTwinPropertyMetadata Temperature { get; set; }

    [JsonPropertyName("humidity")]
    public DigitalTwinPropertyMetadata Humidity { get; set; }
}

// Initialize properties and create the twin
public class TwinOperationsCreateTwin
{
    public async Task CreateTwinAsync(DigitalTwinsClient client)
    {
        // Initialize the twin properties
        var myTwin = new CustomDigitalTwin
        {
            Metadata = { ModelId = "dtmi:example:Room;1" },
            Temperature = 25.0,
            Humidity = 50.0,
        };

        // Create the twin
        const string twinId = "<twin-ID>";
        Response<CustomDigitalTwin> response = await client.CreateOrReplaceDigitalTwinAsync(twinId, myTwin);
        Console.WriteLine($"Temperature last updated on {response.Value.Metadata.Temperature.LastUpdatedOn}");
    }
}

إنشاء توائم مع فئة المساعد

تنيح لك فئة المساعد BasicDigitalTwin تخزين حقول الخصائص في كائن "مزدوج" مباشرةً. قد لا تزال ترغب في إنشاء قائمة الخصائص باستخدام ، والتي يمكن بعد Dictionary<string, object>ذلك إضافتها إلى الكائن التوأم ككائن مباشر لها CustomProperties .

string twinId = "myTwinID";
var initData = new BasicDigitalTwin
{
    Id = twinId,
    Metadata = { ModelId = "dtmi:example:Room;1" },
    // Initialize properties
    Contents =
    {
        { "Temperature", 25.0 },
        { "Humidity", 50.0 },
    },
};

await client.CreateOrReplaceDigitalTwinAsync<BasicDigitalTwin>(twinId, initData);

ملاحظة

BasicDigitalTwin الكائنات تأتي مع حقل Id . يمكنك ترك هذا الحقل فارغا، ولكن إذا قمت بإضافة قيمة معرف، فيجب أن تتطابق مع معلمة المعرف التي تم تمريرها إلى المكالمة CreateOrReplaceDigitalTwinAsync() . على سبيل المثال:

twin.Id = "myRoomId";

الحصول على البيانات لتوأم رقمي

يمكنك الوصول إلى تفاصيل أي توأم رقمي عن طريق استدعاء الطريقة GetDigitalTwin() على النحو التالي:

Response<BasicDigitalTwin> twinResponse = await client.GetDigitalTwinAsync<BasicDigitalTwin>(twinId);
twin = twinResponse.Value;

ترجع هذه المكالمة البيانات المزدوجة كنوع كائن مكتوب بقوة مثل BasicDigitalTwin. BasicDigitalTwin هي فئة مساعد تسلسل مضمنة في SDK، والتي ستعرض بيانات التعريف والخصائص الأساسية للتوأم في شكل تم تحليله مسبقا. يمكنك دائما إلغاء تسلسل البيانات المزدوجة باستخدام مكتبة JSON التي تختارها، مثل System.Text.Json أو Newtonsoft.Json. للوصول الأساسي إلى التوأم ، ومع ذلك ، يمكن لفئات المساعد أن تجعل هذا أكثر ملاءمة.

ملاحظة

BasicDigitalTwin يستخدم System.Text.Json السمات. للاستخدام BasicDigitalTwin مع DigitalTwinsClient، يجب عليك إما تهيئة العميل باستخدام المنشئ الافتراضي، أو، إذا كنت ترغب في تخصيص خيار serializer، استخدم JsonObjectSerializer.

تمنحك فئة المساعد أيضا إمكانية الوصول إلى الخصائص المحددة على التوأم BasicDigitalTwin ، من خلال Dictionary<string, object>. لسرد خصائص التوأم، يمكنك استخدام:

BasicDigitalTwin twin;
Response<BasicDigitalTwin> twinResponse = await client.GetDigitalTwinAsync<BasicDigitalTwin>(twinId);
twin = twinResponse.Value;
Console.WriteLine($"Model id: {twin.Metadata.ModelId}");
foreach (string prop in twin.Contents.Keys)
{
    if (twin.Contents.TryGetValue(prop, out object value))
        Console.WriteLine($"Property '{prop}': {value}");
}

يتم إرجاع الخصائص التي تم تعيينها مرة واحدة على الأقل فقط عند استرداد توأم باستخدام الطريقة GetDigitalTwin() .

تلميح

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

لاسترداد توائم متعددة باستخدام استدعاء واجهة برمجة تطبيقات واحد، راجع أمثلة واجهة برمجة تطبيقات الاستعلام في الاستعلام عن الرسم البياني المزدوج.

ضع في اعتبارك النموذج التالي ( المكتوب بلغة تعريف التوائم الرقمية (DTDL)) الذي يعرف القمر:

{
    "@id": "dtmi:example:Moon;1",
    "@type": "Interface",
    "@context": "dtmi:dtdl:context;2",
    "contents": [
        {
            "@type": "Property",
            "name": "radius",
            "schema": "double",
            "writable": true
        },
        {
            "@type": "Property",
            "name": "mass",
            "schema": "double",
            "writable": true
        }
    ]
}

قد تبدو نتيجة استدعاء object result = await client.GetDigitalTwinAsync("my-moon"); توأم من نوع القمر كما يلي:

{
  "$dtId": "myMoon-001",
  "$etag": "W/\"e59ce8f5-03c0-4356-aea9-249ecbdc07f9\"",
  "radius": 1737.1,
  "mass": 0.0734,
  "$metadata": {
    "$model": "dtmi:example:Moon;1",
    "radius": {
      "desiredValue": 1737.1,
      "desiredVersion": 5,
      "ackVersion": 4,
      "ackCode": 200,
      "ackDescription": "OK"
    },
    "mass": {
      "desiredValue": 0.0734,
      "desiredVersion": 8,
      "ackVersion": 8,
      "ackCode": 200,
      "ackDescription": "OK"
    }
  }
}

يتم إرجاع الخصائص المحددة للتوأم الرقمي كخصائص عالية المستوى على التوأم الرقمي. يتم إرجاع بيانات التعريف أو معلومات النظام التي ليست جزءا من تعريف DTDL ببادئة $ . تتضمن خصائص بيانات التعريف القيم التالية:

  • $dtIdمعرف التوأم الرقمي في مثيل Azure Digital Twins هذا:
  • $etagحقل HTTP قياسي تم تعيينه بواسطة خادم الويب.: يتم تحديث هذا إلى قيمة جديدة في كل مرة يتم فيها تحديث التوأم ، والذي قد يكون مفيدا لتحديد ما إذا كانت بيانات التوأم قد تم تحديثها على الخادم منذ الفحص السابق. يمكنك استخدامها If-Match لإجراء التحديثات والحذف التي لا تكتمل إلا إذا كانت العلامة الإلكترونية للكيان تتطابق مع العلامة الإلكترونية المقدمة. لمزيد من المعلومات حول هذه العمليات، راجع الوثائق الخاصة بتحديث DigitalTwins وحذف DigitalTwins.
  • $metadataمجموعة من الخصائص الأخرى، بما في ذلك:
    • DTMI من نموذج التوأم الرقمي.
    • حالة المزامنة لكل خاصية قابلة للكتابة. هذا هو الأكثر فائدة للأجهزة، حيث من الممكن أن يكون للخدمة والجهاز حالات متباينة (على سبيل المثال، عندما يكون الجهاز غير متصل بالإنترنت). حاليا، تنطبق هذه الخاصية فقط على الأجهزة الفعلية المتصلة ب IoT Hub. باستخدام البيانات الموجودة في قسم البيانات الوصفية ، من الممكن فهم الحالة الكاملة للموقع ، بالإضافة إلى آخر الطوابع الزمنية المعدلة. لمزيد من المعلومات حول حالة المزامنة، راجع هذا البرنامج التعليمي IoT Hub حول مزامنة حالة الجهاز.
    • بيانات التعريف الخاصة بالخدمة، مثل بيانات IoT Hub أو Azure Digital Twins.

يمكنك قراءة المزيد حول فئات مساعد التسلسل كما هو الحال BasicDigitalTwin في واجهات برمجة تطبيقات Azure Digital Twins ومجموعات SDK.

عرض جميع التوائم الرقمية

لعرض جميع التوائم الرقمية في المثيل الخاص بك، استخدم استعلاما. يمكنك تشغيل استعلام باستخدام واجهات برمجة تطبيقات الاستعلام أو أوامر CLI.

فيما يلي نص الاستعلام الأساسي الذي سيعرض قائمة بجميع التوائم الرقمية في المثيل:

SELECT * FROM DIGITALTWINS

تحديث التوأم الرقمي

لتحديث خصائص التوأم الرقمي، اكتب المعلومات التي تريد استبدالها بتنسيق JSON Patch . للحصول على قائمة كاملة بعمليات تصحيح JSON التي يمكن استخدامها، بما في ذلك replace، و remove، add راجع عمليات تصحيح JSON.

بعد صياغة مستند JSON Patch الذي يحتوي على معلومات التحديث، قم بتمرير المستند إلى UpdateDigitalTwin() الطريقة:

await client.UpdateDigitalTwinAsync(twinId, updateTwinData);

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

تلميح

بعد إنشاء توأم أو تحديثه، قد يكون هناك زمن انتقال يصل إلى 10 ثوان قبل أن تنعكس التغييرات في الاستعلامات. لا تواجه GetDigitalTwin واجهة برمجة التطبيقات (الموضحة سابقا في هذه المقالة) هذا التأخير، لذا استخدم استدعاء واجهة برمجة التطبيقات بدلا من الاستعلام لرؤية التوائم التي تم تحديثها حديثا إذا كنت بحاجة إلى استجابة فورية.

فيما يلي مثال على كود JSON Patch. يحل هذا المستند محل قيم خاصية الكتلة ونصف القطر للتوأم الرقمي الذي يتم تطبيقه عليه. يوضح هذا المثال عملية JSON Patch replace التي تحل محل قيمة خاصية موجودة.

[
    {
      "op": "replace",
      "path": "/mass",
      "value": 0.0799
    },
    {
      "op": "replace",
      "path": "/radius",
      "value": 0.800
    }
  ]

عند تحديث توأم من مشروع تعليمات برمجية باستخدام .NET SDK، يمكنك إنشاء تصحيحات JSON باستخدام JsonPatchDocument الخاص ب Azure .NET SDK. فيما يلي مثال على إنشاء مستند JSON Patch واستخدامه UpdateDigitalTwin() في التعليمات البرمجية للمشروع.

var updateTwinData = new JsonPatchDocument();
updateTwinData.AppendAdd("/Temperature", 25.0);
updateTwinData.AppendAdd("/myComponent/Property", "Hello");
// Un-set a property
updateTwinData.AppendRemove("/Humidity");

await client.UpdateDigitalTwinAsync("myTwin", updateTwinData).ConfigureAwait(false);

تلميح

يمكنك الحفاظ على الطوابع الزمنية للمصدر على توائم الرقمية الخاصة بك عن طريق تحديث الحقل $metadata.<property-name>.sourceTime بالعملية الموضحة في هذا القسم. لمزيد من المعلومات حول هذا الحقل والحقول الأخرى القابلة للكتابة على التوائم الرقمية، راجع تنسيق JSON التوأم الرقمي.

تحديث الخصائص الفرعية في المكونات الرقمية التوأم

تذكر أن النموذج قد يحتوي على مكونات ، مما يسمح له بأن يتكون من نماذج أخرى.

لتصحيح الخصائص في مكونات التوأم الرقمي، يمكنك استخدام بناء جملة المسار في تصحيح JSON:

[
  {
    "op": "replace",
    "path": "/mycomponentname/mass",
    "value": 0.0799
  }
]

تحديث الخصائص الفرعية في خصائص نوع الكائن

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

ضع في اعتبارك نموذجا يحتوي على خاصية من نوع الكائن ، ObjectProperty. ObjectProperty يحتوي على خاصية سلسلة باسم StringSubProperty.

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

يمكن القيام بذلك باستخدام عملية JSON Patch add ، مثل هذا:

[
  {
    "op": "add", 
    "path": "/ObjectProperty", 
    "value": {"StringSubProperty":"<string-value>"}
  }
]

ملاحظة

إذا كان لديك أكثر من خاصية واحدة، فيجب عليك تضمينها جميعا في value مجال هذه العملية، حتى إذا ObjectProperty كنت تقوم بتحديث موقع واحد فقط:

... "value": {"StringSubProperty":"<string-value>", "Property2":"<property2-value>", ...}

بعد الانتهاء من ذلك مرة واحدة ، يكون هناك مسار إلى StringSubProperty الوجود ، ويمكن تحديثه مباشرة من الآن فصاعدا باستخدام عملية نموذجية replace :

[
  {
    "op": "replace",
    "path": "/ObjectProperty/StringSubProperty",
    "value": "<string-value>"
  }
]

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

تحديث نموذج التوأم الرقمي

يمكن أيضًا استخدام الوظيفة UpdateDigitalTwin() لترحيل التوأم الرقمي إلى نموذج مختلف.

على سبيل المثال، ضع في اعتبارك مستند JSON Patch التالي الذي يحل محل حقل بيانات التعريف $model للتوأم الرقمي:

[
  {
    "op": "replace",
    "path": "/$metadata/$model",
    "value": "dtmi:example:foo;1"
  }
]

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

انظر في المثال التالي:

  1. تخيل توأماً رقمياً بنموذج foo_old. foo_old يحدد كتلة الخاصية المطلوبة.
  2. يحدد النموذج الجديد foo_new كتلة خاصية، ويضيف درجة حرارة خاصية جديدة مطلوبة.
  3. بعد التصحيح، يجب أن يتمتع التوأم الرقمي بخاصية الكتلة ودرجة الحرارة.

يحتاج التصحيح الخاص بهذا الموقف إلى تحديث كل من الطراز وخاصية درجة حرارة التوأم، مثل هذا:

[
  {
    "op": "replace",
    "path": "/$metadata/$model",
    "value": "dtmi:example:foo_new;1"
  },
  {
    "op": "add",
    "path": "/temperature",
    "value": 60
  }
]

تحديث مصدر الموقعالوقت

يمكنك اختياريا أن تقرر استخدام الحقل الموجود على الخصائص المزدوجة sourceTime لتسجيل الطوابع الزمنية عند ملاحظة تحديثات الخصائص في العالم الحقيقي. يدعم sourceTime Azure Digital Twins أصلا في بيانات التعريف لكل خاصية توأم. لمزيد من المعلومات حول هذا الحقل والحقول الأخرى على التوائم الرقمية، راجع تنسيق JSON التوأم الرقمي.

الحد الأدنى لإصدار REST API لدعم هذا الحقل هو إصدار معاينة 2021-06-30 . للعمل مع هذا الحقل باستخدام Azure Digital Twins SDKs، نوصي باستخدام أحدث إصدار من SDK للتأكد من تضمين هذا الحقل (ضع في اعتبارك أن أحدث إصدار من SDK قد يكون في الإصدار التجريبي أو المعاينة).

sourceTime يجب أن تتوافق القيمة مع تنسيق التاريخ والوقت ISO 8601.

في ما يلي مثال على مستند JSON Patch الذي يقوم بتحديث كل من قيمة الخاصية وحقلها sourceTimeTemperature :

[
  {
    "op": "replace",
    "path": "/Temperature",
    "value": "22.3"
  },
  {
    "op": "replace",
    "path": "/$metadata/Temperature/sourceTime",
    "value": "2021-11-30T18:47:53.7648958Z"
  }
]

تلميح

لتحديث الحقل على خاصية تشكل جزءا من مكون، قم بتضمين المكون في بداية المسار sourceTime . في المثال السابق ، هذا يعني تغيير المسار من /$metadata/Temperature/sourceTime إلى myComponent/$metadata/Temperature/sourceTime.

التعامل مع مكالمات التحديث المتعارضة

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

هذا السلوك على أساس كل توأم.

على سبيل المثال ، تخيل سيناريو تصل فيه هذه المكالمات الثلاثة في نفس الوقت:

  • كتابة الخاصية A على Twin1
  • كتابة الخاصية B على Twin1
  • كتابة الخاصية A على Twin2

يتم تنفيذ الاستدعاءين اللذين يعدلان Twin1 واحدا تلو الآخر، ويتم إنشاء رسائل التغيير لكل تغيير. قد يتم تنفيذ الدعوة لتعديل Twin2 في وقت واحد دون أي تعارض ، بمجرد وصولها.

حذف التوأم الرقمي

يمكنك حذف التوائم باستخدام طريقة DeleteDigitalTwin(). ومع ذلك، يمكنك حذف التوأم فقط عندما لا يكون لديه المزيد من العلاقات. لذا، احذف علاقات التوأم الواردة والصادرة أولاً.

فيما يلي مثال على رمز حذف التوائم وعلاقاتهم. يتم DeleteDigitalTwin تمييز استدعاء SDK لتوضيح أين يقع في سياق المثال الأوسع.

private static async Task CustomMethod_DeleteTwinAsync(DigitalTwinsClient client, string twinId)
{
    await CustomMethod_FindAndDeleteOutgoingRelationshipsAsync(client, twinId);
    await CustomMethod_FindAndDeleteIncomingRelationshipsAsync(client, twinId);
    try
    {
        await client.DeleteDigitalTwinAsync(twinId);
        Console.WriteLine("Twin deleted successfully");
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine($"*** Error:{ex.Message}");
    }
}

private static async Task CustomMethod_FindAndDeleteOutgoingRelationshipsAsync(DigitalTwinsClient client, string dtId)
{
    // Find the relationships for the twin

    try
    {
        // GetRelationshipsAsync will throw an error if a problem occurs
        AsyncPageable<BasicRelationship> rels = client.GetRelationshipsAsync<BasicRelationship>(dtId);

        await foreach (BasicRelationship rel in rels)
        {
            await client.DeleteRelationshipAsync(dtId, rel.Id).ConfigureAwait(false);
            Console.WriteLine($"Deleted relationship {rel.Id} from {dtId}");
        }
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} retrieving or deleting relationships for {dtId} due to {ex.Message}");
    }
}

private static async Task CustomMethod_FindAndDeleteIncomingRelationshipsAsync(DigitalTwinsClient client, string dtId)
{
    // Find the relationships for the twin

    try
    {
        // GetRelationshipsAsync will throw an error if a problem occurs
        AsyncPageable<IncomingRelationship> incomingRels = client.GetIncomingRelationshipsAsync(dtId);

        await foreach (IncomingRelationship incomingRel in incomingRels)
        {
            await client.DeleteRelationshipAsync(incomingRel.SourceId, incomingRel.RelationshipId).ConfigureAwait(false);
            Console.WriteLine($"Deleted incoming relationship {incomingRel.RelationshipId} from {dtId}");
        }
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} retrieving or deleting incoming relationships for {dtId} due to {ex.Message}");
    }
}

حذف جميع التوائم الرقمية

للحصول على مثال حول كيفية حذف جميع التوائم في وقت واحد، قم بتنزيل نموذج التطبيق المستخدم في استكشاف الأساسيات باستخدام تطبيق عميل نموذجي. يقوم ملف CommandLoop.cs بذلك في دالة CommandDeleteAllTwins() .

نموذج رمز التوأم الرقمي القابل للتشغيل

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

إعداد نماذج من ملفات المشروع

يستخدم المقتطف نموذج تعريف Room.json. لتنزيل ملف النموذج حتى تتمكن من استخدامه في التعليمات البرمجية الخاصة بك، استخدم هذا الرابط للانتقال مباشرة إلى الملف في GitHub. بعد ذلك، انقر بزر الماوس الأيمن فوق أي مكان على الشاشة، وحدد حفظ باسم في قائمة النقر بزر الماوس الأيمن في المستعرض، واستخدم نافذة حفظ باسم لحفظ الملف باسمRoom.json.

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

ثم قم بنسخ التعليمة البرمجية التالية من العينة القابلة للتشغيل إلى المشروع الخاص بك:

using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Azure;
using Azure.DigitalTwins.Core;
using Azure.Identity;
using System.IO;

namespace DigitalTwins_Samples
{
    class TwinOperationsSample
    {
        public static async Task Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            // Create the Azure Digital Twins client for API calls
            string adtInstanceUrl = "https://<your-instance-hostname>";
            var credentials = new DefaultAzureCredential();
            var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credentials);
            Console.WriteLine($"Service client created – ready to go");

            // Upload models
            Console.WriteLine($"Upload a model");
            string dtdl = File.ReadAllText("<path-to>/Room.json");
            var models = new List<string> { dtdl };
            // Upload the model to the service
            await client.CreateModelsAsync(models);

            // Create new digital twin
            // <CreateTwin_withHelper>
            string twinId = "myTwinID";
            var initData = new BasicDigitalTwin
            {
                Id = twinId,
                Metadata = { ModelId = "dtmi:example:Room;1" },
                // Initialize properties
                Contents =
                {
                    { "Temperature", 25.0 },
                    { "Humidity", 50.0 },
                },
            };

            // <CreateTwinCall>
            await client.CreateOrReplaceDigitalTwinAsync<BasicDigitalTwin>(twinId, initData);
            // </CreateTwinCall>
            // </CreateTwin_withHelper>
            Console.WriteLine("Twin created successfully");

            //Print twin
            Console.WriteLine("--- Printing twin details:");
            await CustomMethod_FetchAndPrintTwinAsync(twinId, client);
            Console.WriteLine("--------");

            //Update twin data
            var updateTwinData = new JsonPatchDocument();
            updateTwinData.AppendAdd("/Temperature", 30.0);
            // <UpdateTwinCall>
            await client.UpdateDigitalTwinAsync(twinId, updateTwinData);
            // </UpdateTwinCall>
            Console.WriteLine("Twin properties updated");
            Console.WriteLine();

            //Print twin again
            Console.WriteLine("--- Printing twin details (after update):");
            await CustomMethod_FetchAndPrintTwinAsync(twinId, client);
            Console.WriteLine("--------");
            Console.WriteLine();

            //Delete twin
            await CustomMethod_DeleteTwinAsync(client, twinId);
        }

        private static async Task<BasicDigitalTwin> CustomMethod_FetchAndPrintTwinAsync(string twinId, DigitalTwinsClient client)
        {
            // <GetTwin>
            BasicDigitalTwin twin;
            // <GetTwinCall>
            Response<BasicDigitalTwin> twinResponse = await client.GetDigitalTwinAsync<BasicDigitalTwin>(twinId);
            twin = twinResponse.Value;
            // </GetTwinCall>
            Console.WriteLine($"Model id: {twin.Metadata.ModelId}");
            foreach (string prop in twin.Contents.Keys)
            {
                if (twin.Contents.TryGetValue(prop, out object value))
                    Console.WriteLine($"Property '{prop}': {value}");
            }
            // </GetTwin>

            return twin;
        }

        // <DeleteTwin>
        private static async Task CustomMethod_DeleteTwinAsync(DigitalTwinsClient client, string twinId)
        {
            await CustomMethod_FindAndDeleteOutgoingRelationshipsAsync(client, twinId);
            await CustomMethod_FindAndDeleteIncomingRelationshipsAsync(client, twinId);
            try
            {
                await client.DeleteDigitalTwinAsync(twinId);
                Console.WriteLine("Twin deleted successfully");
            }
            catch (RequestFailedException ex)
            {
                Console.WriteLine($"*** Error:{ex.Message}");
            }
        }

        private static async Task CustomMethod_FindAndDeleteOutgoingRelationshipsAsync(DigitalTwinsClient client, string dtId)
        {
            // Find the relationships for the twin

            try
            {
                // GetRelationshipsAsync will throw an error if a problem occurs
                AsyncPageable<BasicRelationship> rels = client.GetRelationshipsAsync<BasicRelationship>(dtId);

                await foreach (BasicRelationship rel in rels)
                {
                    await client.DeleteRelationshipAsync(dtId, rel.Id).ConfigureAwait(false);
                    Console.WriteLine($"Deleted relationship {rel.Id} from {dtId}");
                }
            }
            catch (RequestFailedException ex)
            {
                Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} retrieving or deleting relationships for {dtId} due to {ex.Message}");
            }
        }

        private static async Task CustomMethod_FindAndDeleteIncomingRelationshipsAsync(DigitalTwinsClient client, string dtId)
        {
            // Find the relationships for the twin

            try
            {
                // GetRelationshipsAsync will throw an error if a problem occurs
                AsyncPageable<IncomingRelationship> incomingRels = client.GetIncomingRelationshipsAsync(dtId);

                await foreach (IncomingRelationship incomingRel in incomingRels)
                {
                    await client.DeleteRelationshipAsync(incomingRel.SourceId, incomingRel.RelationshipId).ConfigureAwait(false);
                    Console.WriteLine($"Deleted incoming relationship {incomingRel.RelationshipId} from {dtId}");
                }
            }
            catch (RequestFailedException ex)
            {
                Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} retrieving or deleting incoming relationships for {dtId} due to {ex.Message}");
            }
        }
        // </DeleteTwin>

    }
}

ملاحظة

توجد حاليا مشكلة معروفة تؤثر على DefaultAzureCredential فئة المجمع والتي قد تؤدي إلى حدوث خطأ أثناء المصادقة. إذا واجهت هذه المشكلة، يمكنك محاولة إنشاء DefaultAzureCredential مثيل باستخدام المعلمة الاختيارية التالية لحلها: new DefaultAzureCredential(new DefaultAzureCredentialOptions { ExcludeSharedTokenCacheCredential = true });

لمزيد من المعلومات حول هذه المشكلة، راجع استكشاف المشكلات المعروفة وإصلاحها.

تكوين المشروع

بعد ذلك، أكمل الخطوات التالية لتكوين التعليمات البرمجية للمشروع:

  1. أضف ملف Room.json الذي قمت بتنزيله مسبقا إلى مشروعك، واستبدل <path-to> العنصر النائب في التعليمة البرمجية لإخبار البرنامج بمكان العثور عليه.

  2. استبدل العنصر النائب <your-instance-hostname> باسم مضيف مثيل Azure Digital Twins.

  3. أضف تبعيتين إلى مشروعك ستكون هناك حاجة إليهما للعمل مع Azure Digital Twins. الأول هو حزمة Azure Digital Twins SDK ل .NET، والثاني يوفر أدوات للمساعدة في المصادقة ضد Azure.

    dotnet add package Azure.DigitalTwins.Core
    dotnet add package Azure.Identity
    

ستحتاج أيضا إلى إعداد بيانات الاعتماد المحلية إذا كنت تريد تشغيل العينة مباشرة. القسم التالي يمشي من خلال هذا.

إعداد بيانات اعتماد Azure المحلية

تستخدم هذه العينة DefaultAzureCredential (جزء من مكتبة Azure.Identity) لمصادقة المستخدمين مع مثيل Azure Digital Twins عند تشغيله على جهازك المحلي. لمزيد من المعلومات حول الطرق المختلفة التي يمكن لتطبيق العميل مصادقتها باستخدام Azure Digital Twins، راجع كتابة تعليمات برمجية لمصادقة التطبيق.

سيبحث النموذج باستخدام DefaultAzureCredential عن بيانات اعتماد في بيئتك المحلية، مثل تسجيل الدخول إلى Microsoft Azure في Azure CLI محلي أو في Visual Studio أو Visual Studio Code. ولهذا السبب، يجب تسجيل الدخول محلياً إلى Microsoft Azure من خلال أحد هذه الآليات المخصصة لإعداد بيانات الاعتماد للنموذج.

إذا كنت تستخدم Visual Studio أو Visual Studio Code لتشغيل نموذج التعليمات البرمجية، فتأكد من تسجيل الدخول إلى هذا المحرر باستخدام بيانات اعتماد Azure نفسها التي تريد استخدامها للوصول إلى مثيل Azure Digital Twins.

وخلاف ذلك، يمكنك تثبيت Azure CLI المحلي وبدء موجه الأوامر على جهازك وتشغيل الأمر az login لتسجيل الدخول إلى حسابك في Microsoft Azure. وبعد تسجيل الدخول وعند تشغيل نموذج التعليمات البرمجية، يجب تسجيل دخولك تلقائياً.

تشغيل النموذج

الآن بعد الانتهاء من الإعداد، يمكنك تشغيل نموذج مشروع التعليمات البرمجية.

فيما يلي إخراج وحدة التحكم للبرنامج أعلاه:

Screenshot of the console output showing that the twin is created, updated, and deleted.

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

تعرف على كيفية إنشاء وإدارة العلاقات بين توأمك الرقمي: