Zarządzanie usługą Digital Twins

Jednostki w twoim środowisku są reprezentowane przez cyfrowe reprezentacje bliźniacze. Zarządzanie cyfrowymi reprezentacjami bliźniaczymi może obejmować tworzenie, modyfikowanie i usuwanie.

Ten artykuł koncentruje się na zarządzaniu cyfrowymi reprezentacjami bliźniaczymi; aby pracować z relacjami i grafem bliźniaczej reprezentacji jako całości, zobacz Zarządzanie grafem i relacjami bliźniaczych reprezentacji.

Napiwek

Wszystkie funkcje zestawu SDK są dostępne w wersjach synchronicznych i asynchronicznych.

Wymagania wstępne

Aby pracować z usługą Azure Digital Twins w tym artykule, musisz mieć wystąpienie usługi Azure Digital Twins i wymagane uprawnienia do korzystania z niego. Jeśli masz już skonfigurowane wystąpienie usługi Azure Digital Twins, możesz użyć tego wystąpienia i przejść do następnej sekcji. W przeciwnym razie postępuj zgodnie z instrukcjami w temacie Konfigurowanie wystąpienia i uwierzytelniania. Instrukcje zawierają informacje ułatwiające sprawdzenie, czy każdy krok został ukończony pomyślnie.

Po skonfigurowaniu wystąpienia zanotuj nazwę hosta wystąpienia. Nazwę hosta można znaleźć w witrynie Azure Portal.

Interfejsy deweloperskie

W tym artykule opisano sposób wykonywania różnych operacji zarządzania przy użyciu zestawu SDK platformy .NET (C#). Możesz również utworzyć te same wywołania zarządzania przy użyciu innych zestawów SDK języka opisanych w interfejsach API i zestawach SDK usługi Azure Digital Twins.

Inne interfejsy deweloperskie, których można użyć do wykonania tych operacji, to:

Wizualizacja

Azure Digital Twins Explorer to wizualne narzędzie do eksplorowania danych na grafie usługi Azure Digital Twins. Eksplorator umożliwia wyświetlanie, wykonywanie zapytań i edytowanie modeli, reprezentacji bliźniaczych i relacji.

Aby dowiedzieć się więcej o narzędziu Azure Digital Twins Explorer, zobacz Azure Digital Twins Explorer. Aby uzyskać szczegółowe instrukcje dotyczące korzystania z jej funkcji, zobacz Korzystanie z eksploratora usługi Azure Digital Twins.

Oto jak wygląda wizualizacja:

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

Tworzenie cyfrowej reprezentacji bliźniaczej

Aby utworzyć bliźniacze reprezentację, użyj CreateOrReplaceDigitalTwinAsync() metody na kliencie usługi w następujący sposób:

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

Aby utworzyć cyfrową reprezentację bliźniaczą, należy podać następujące elementy:

  • Wartość identyfikatora, którą chcesz przypisać do cyfrowej reprezentacji bliźniaczej (definiujesz ten identyfikator po utworzeniu reprezentacji bliźniaczej)
  • Model, którego chcesz użyć
  • Wszelkie żądane inicjowanie danych reprezentacji bliźniaczej, w tym...
    • Właściwości (inicjowanie opcjonalne): możesz ustawić początkowe wartości właściwości cyfrowej reprezentacji bliźniaczej, jeśli chcesz. Właściwości są traktowane jako opcjonalne i można je ustawić później, ale należy pamiętać, że nie będą wyświetlane jako część bliźniaczej reprezentacji, dopóki nie zostaną ustawione.
    • Składniki (wymagane inicjowanie, jeśli są obecne w bliźniaczej reprezentacji): jeśli reprezentacja bliźniacze zawiera jakiekolwiek składniki, należy je zainicjować podczas tworzenia reprezentacji bliźniaczej. Mogą być pustymi obiektami, ale same składniki muszą istnieć.

Model i wszystkie początkowe wartości właściwości są udostępniane za pośrednictwem parametru initData , który jest ciągiem JSON zawierającym odpowiednie dane. Aby uzyskać więcej informacji na temat struktury tego obiektu, przejdź do następnej sekcji.

Napiwek

Po utworzeniu lub zaktualizowaniu bliźniaczej reprezentacji może wystąpić opóźnienie do 10 sekund, zanim zmiany zostaną odzwierciedlone w zapytaniach. Interfejs GetDigitalTwin API (opisany w dalszej części tego artykułu) nie ma tego opóźnienia, więc jeśli potrzebujesz natychmiastowej odpowiedzi, użyj wywołania interfejsu API zamiast wykonywania zapytań, aby zobaczyć nowo utworzone reprezentacje bliźniacze.

Inicjowanie modelu i właściwości

Właściwości bliźniaczej reprezentacji bliźniaczej można zainicjować podczas tworzenia reprezentacji bliźniaczej.

Interfejs API tworzenia reprezentacji bliźniaczej akceptuje obiekt, który jest serializowany w prawidłowy opis JSON właściwości bliźniaczej reprezentacji. Aby uzyskać opis formatu JSON dla bliźniaczej reprezentacji bliźniaczej, zobacz Cyfrowe reprezentacje bliźniacze i graf bliźniaczych reprezentacji.

Najpierw można utworzyć obiekt danych reprezentujący reprezentację bliźniaczą i jego dane właściwości. Obiekt parametru można utworzyć ręcznie lub przy użyciu podanej klasy pomocniczej. Oto przykład każdego z nich.

Tworzenie reprezentacji bliźniaczych przy użyciu ręcznie utworzonych danych

Bez użycia żadnych niestandardowych klas pomocnika można reprezentować właściwości bliźniaczej reprezentacji w Dictionary<string, object>obiekcie , gdzie string jest nazwą właściwości, a object obiekt jest obiektem reprezentującym właściwość i jej wartość.

// 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("temperature")]
    public double Temperature { get; set; }

    [JsonPropertyName("humidity")]
    public double 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
        {
            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 value: {response.Value.Temperature}");
    }
}

Tworzenie bliźniaczych reprezentacji z klasą pomocnika

Klasa BasicDigitalTwin pomocnika klasy umożliwia przechowywanie pól właściwości bezpośrednio w obiekcie "bliźniaczej reprezentacji". Nadal możesz utworzyć listę właściwości przy użyciu Dictionary<string, object>obiektu , który następnie można dodać do obiektu bliźniaczej reprezentacji jako bezpośrednio 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);

Uwaga

BasicDigitalTwin obiekty są dostarczane z polem Id . Możesz pozostawić to pole puste, ale jeśli dodasz wartość identyfikatora, musi być zgodny z parametrem ID przekazanym do wywołania CreateOrReplaceDigitalTwinAsync() . Na przykład:

twin.Id = "myRoomId";

Zbiorcze tworzenie bliźniaczych reprezentacji za pomocą interfejsu API importowania zadań

Interfejs API importowania zadań umożliwia tworzenie wielu bliźniaczych reprezentacji jednocześnie w jednym wywołaniu interfejsu API. Ta metoda wymaga użycia usługi Azure Blob Storage i uprawnień do zapisu w wystąpieniu usługi Azure Digital Twins dla bliźniaczych reprezentacji bliźniaczych i zadań zbiorczych.

Napiwek

Interfejs API zadań importu umożliwia również importowanie modeli i relacji w tym samym wywołaniu w celu utworzenia wszystkich części grafu jednocześnie. Aby uzyskać więcej informacji na temat tego procesu, zobacz Przekazywanie modeli, reprezentacji bliźniaczych i relacji zbiorczo za pomocą interfejsu API importowania zadań.

Aby importować zbiorcze reprezentacje bliźniacze, należy sstrukturę bliźniaczych reprezentacji (i wszystkich innych zasobów zawartych w zadaniu importu zbiorczego ) jako pliku NDJSON . Sekcja Twins znajduje się po Models sekcji (i przed sekcją Relationships ). Bliźniacze reprezentacje zdefiniowane w pliku mogą odwoływać się do modeli zdefiniowanych w tym pliku lub już obecnych w wystąpieniu. Opcjonalnie mogą również obejmować inicjowanie właściwości bliźniaczej reprezentacji.

Przykładowy plik importu i przykładowy projekt służą do tworzenia tych plików w temacie Wprowadzenie do interfejsu API importu zadań.

Następnie należy przekazać plik do uzupełnialnych obiektów blob w usłudze Azure Blob Storage. Aby uzyskać instrukcje dotyczące tworzenia kontenera usługi Azure Storage, zobacz Tworzenie kontenera. Następnie przekaż plik przy użyciu preferowanej metody przekazywania (niektóre opcje to polecenie AzCopy, interfejs wiersza polecenia platformy Azure lub witryna Azure Portal).

Po przekazaniu pliku NDJSON do kontenera pobierz jego adres URL w kontenerze obiektów blob. Użyjesz tej wartości w dalszej części treści wywołania interfejsu API importu zbiorczego.

Oto zrzut ekranu przedstawiający wartość adresu URL pliku obiektu blob w witrynie Azure Portal:

Screenshot of the Azure portal showing the URL of a file in a storage container.

Następnie plik można użyć w wywołaniu interfejsu API importu zadań. Podaj adres URL magazynu obiektów blob w pliku wejściowym i nowy adres URL magazynu obiektów blob, aby wskazać, gdzie ma być przechowywany dziennik wyjściowy po jego utworzeniu.

Pobieranie danych dla cyfrowej reprezentacji bliźniaczej

Aby uzyskać dostęp do szczegółów dowolnej cyfrowej reprezentacji bliźniaczej, wywołaj metodę GetDigitalTwin() w następujący sposób:

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

To wywołanie zwraca dane bliźniaczej reprezentacji jako silnie typ obiektu, taki jak BasicDigitalTwin. BasicDigitalTwin to klasa pomocnika serializacji dołączona do zestawu SDK, która zwraca podstawowe metadane reprezentacji bliźniaczej i właściwości w postaci wstępnie utworzonej. Zawsze można deserializować dane reprezentacji bliźniaczej przy użyciu wybranej biblioteki JSON, takiej jak System.Text.Json lub Newtonsoft.Json. Aby uzyskać podstawowy dostęp do bliźniaczej reprezentacji, klasy pomocnicze mogą sprawić, że będzie to wygodniejsze.

Uwaga

BasicDigitalTwin używa System.Text.Json atrybutów. Aby można było używać elementu BasicDigitalTwin DigitalTwinsClient, należy zainicjować klienta przy użyciu konstruktora domyślnego lub, jeśli chcesz dostosować opcję serializatora, użyj inicjatora JsonObjectSerializer.

Klasa BasicDigitalTwin pomocnika zapewnia również dostęp do właściwości zdefiniowanych na bliźniaczej reprezentacji za pośrednictwem elementu Dictionary<string, object>. Aby wyświetlić listę właściwości bliźniaczej reprezentacji bliźniaczej, możesz użyć:

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

Tylko właściwości, które zostały ustawione co najmniej raz, są zwracane podczas pobierania bliźniaczej reprezentacji z GetDigitalTwin() metodą .

Napiwek

Element displayName dla bliźniaczej reprezentacji jest częścią metadanych modelu, więc nie będzie wyświetlany podczas pobierania danych dla wystąpienia reprezentacji bliźniaczej. Aby wyświetlić tę wartość, możesz pobrać ją z modelu.

Aby pobrać wiele reprezentacji bliźniaczych przy użyciu jednego wywołania interfejsu API, zobacz Przykłady interfejsu API zapytań w temacie Wykonywanie zapytań względem grafu bliźniaczej reprezentacji.

Rozważmy następujący model (napisany w języku Digital Twins Definition Language ( DTDL), który definiuje Księżyc:

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

Wynik wywołania object result = await client.GetDigitalTwinAsync("my-moon"); bliźniaczej reprezentacji księżyca może wyglądać następująco:

{
  "$dtId": "myMoon-001",
  "$etag": "W/\"e59ce8f5-03c0-4356-aea9-249ecbdc07f9\"",
  "radius": 1737.1,
  "mass": 0.0734,
  "$metadata": {
    "$model": "dtmi:example:Moon;1",
    "radius": {
      "lastUpdateTime": "2022-12-06T20:00:32.8209188Z"
    },
    "mass": {
      "lastUpdateTime": "2022-12-04T12:04:43.3859361Z"
    }
  }
}

Zdefiniowane właściwości cyfrowej reprezentacji bliźniaczej są zwracane jako właściwości najwyższego poziomu w cyfrowej reprezentacji bliźniaczej. Metadane lub informacje systemowe, które nie są częścią definicji DTDL, są zwracane z prefiksem $ . Właściwości metadanych obejmują następujące wartości:

  • $dtId: identyfikator cyfrowej reprezentacji bliźniaczej w tym wystąpieniu usługi Azure Digital Twins
  • $etag: standardowe pole HTTP przypisane przez serwer internetowy. Ta wartość jest aktualizowana do nowej wartości za każdym razem, gdy bliźniacze reprezentacja jest aktualizowana, co może być przydatne do określenia, czy dane bliźniaczej reprezentacji zostały zaktualizowane na serwerze od czasu poprzedniego sprawdzenia. Za pomocą If-Match polecenia można wykonywać aktualizacje i usuwać je tylko wtedy, gdy element etag jednostki jest zgodny z podanym tagiem etag. Aby uzyskać więcej informacji na temat tych operacji, zobacz dokumentację dotyczącą funkcji DigitalTwins Update i DigitalTwins Delete.
  • $metadata: Zestaw właściwości metadanych, które mogą obejmować następujące elementy:
    • $model, dtMI modelu cyfrowej reprezentacji bliźniaczej.
    • lastUpdateTime dla właściwości bliźniaczej reprezentacji. Jest to znacznik czasu wskazujący datę i godzinę przetworzenia komunikatu aktualizacji właściwości przez usługę Azure Digital Twins
    • sourceTime dla właściwości bliźniaczej reprezentacji. Jest to opcjonalna, zapisywalna właściwość reprezentująca sygnaturę czasową obserwowanej aktualizacji właściwości w świecie rzeczywistym.

Więcej informacji na temat pól zawartych w cyfrowej reprezentacji bliźniaczej można przeczytać w formacie JSON cyfrowej reprezentacji bliźniaczej. Więcej informacji na temat klas pomocników serializacji, takich jak BasicDigitalTwin w interfejsach API i zestawach SDK usługi Azure Digital Twins.

Wyświetlanie wszystkich cyfrowych reprezentacji bliźniaczych

Aby wyświetlić wszystkie cyfrowe reprezentacje bliźniacze w twoim wystąpieniu, użyj zapytania. Zapytanie można uruchomić za pomocą interfejsów API zapytań lub poleceń interfejsu wiersza polecenia.

Oto treść podstawowego zapytania, które zwraca listę wszystkich cyfrowych reprezentacji bliźniaczych w wystąpieniu:

SELECT * FROM DIGITALTWINS

Aktualizowanie cyfrowej reprezentacji bliźniaczej

Aby zaktualizować właściwości cyfrowej reprezentacji bliźniaczej, zapisz informacje, które chcesz zamienić w formacie poprawki JSON. Aby uzyskać pełną listę operacji poprawek JSON, które mogą być używane, w tym replaceadd , i remove, zobacz Operacje dla poprawki JSON.

Po spreparowaniu dokumentu poprawki JSON zawierającego informacje o aktualizacji przekaż dokument do UpdateDigitalTwin() metody :

await client.UpdateDigitalTwinAsync(twinId, updateTwinData);

Jedno wywołanie poprawki może zaktualizować dowolną liczbę właściwości pojedynczej reprezentacji bliźniaczej (nawet wszystkich). Jeśli musisz zaktualizować właściwości w wielu reprezentacjach bliźniaczych, potrzebujesz oddzielnego wywołania aktualizacji dla każdej reprezentacji bliźniaczej.

Napiwek

Po utworzeniu lub zaktualizowaniu bliźniaczej reprezentacji może wystąpić opóźnienie do 10 sekund, zanim zmiany zostaną odzwierciedlone w zapytaniach. Interfejs GetDigitalTwin API (opisany wcześniej w tym artykule) nie ma tego opóźnienia, dlatego użyj wywołania interfejsu API zamiast wykonywania zapytań, aby zobaczyć nowo zaktualizowane reprezentacje bliźniacze, jeśli potrzebujesz natychmiastowej odpowiedzi.

Oto przykład kodu poprawki JSON. Ten dokument zastępuje wartości właściwości masy i promienia cyfrowej reprezentacji bliźniaczej, do których jest stosowana. W tym przykładzie pokazano operację JSON Patch replace , która zastępuje wartość istniejącej właściwości.

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

Podczas aktualizowania bliźniaczej reprezentacji z projektu kodu przy użyciu zestawu .NET SDK można utworzyć poprawki JSON przy użyciu narzędzia JsonPatchDocument zestawu .NET SDK platformy Azure. Oto przykład tworzenia dokumentu poprawki JSON i używania go UpdateDigitalTwin() w kodzie projektu.

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

Napiwek

Znaczniki czasu źródłowego dla cyfrowych reprezentacji bliźniaczych można zachować, aktualizując $metadata.<property-name>.sourceTime pole przy użyciu procesu opisanego w tej sekcji. Aby uzyskać więcej informacji na temat tego pola i innych pól zapisywalnych w cyfrowych reprezentacjach bliźniaczych, zobacz Format JSON reprezentacji cyfrowej reprezentacji bliźniaczej.

Aktualizowanie właściwości podrzędnych w składnikach cyfrowej reprezentacji bliźniaczej

Pamiętaj, że model może zawierać składniki, dzięki czemu może składać się z innych modeli.

Aby zastosować poprawki właściwości składników cyfrowej reprezentacji bliźniaczej, możesz użyć składni ścieżki w poprawce JSON:

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

Aktualizowanie właściwości podrzędnych we właściwościach typu obiektu

Modele mogą zawierać właściwości typu obiektu. Te obiekty mogą mieć własne właściwości i można zaktualizować jedną z tych właściwości podrzędnych należących do właściwości typu obiektu. Ten proces jest podobny do procesu aktualizowania właściwości podrzędnych w składnikach, ale może wymagać wykonania pewnych dodatkowych kroków.

Rozważmy model z właściwością typu obiektu , ObjectProperty. ObjectProperty ma właściwość ciągu o nazwie StringSubProperty.

Po utworzeniu bliźniaczej reprezentacji przy użyciu tego modelu nie jest konieczne utworzenie wystąpienia ObjectProperty w tym czasie. Jeśli właściwość obiektu nie jest tworzona podczas tworzenia reprezentacji bliźniaczej, nie ma ścieżki domyślnej utworzonej do uzyskiwania dostępu ObjectProperty i jej StringSubProperty dla operacji poprawki. Musisz dodać ścieżkę do ObjectProperty siebie, zanim będzie można zaktualizować jej właściwości.

Można to zrobić za pomocą operacji JSON Patch add , w następujący sposób:

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

Uwaga

Jeśli ObjectProperty ma więcej niż jedną właściwość, należy uwzględnić wszystkie z nich w value polu tej operacji, nawet jeśli aktualizujesz tylko jedną:

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

Po wykonaniu tej czynności ścieżka do istnieje i można ją zaktualizować StringSubProperty bezpośrednio od teraz za pomocą typowej replace operacji:

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

Mimo że pierwszy krok nie jest konieczny w przypadkach, w których ObjectProperty utworzono wystąpienie bliźniaczej reprezentacji, zaleca się jej użycie za każdym razem, gdy aktualizujesz właściwość podrzędną po raz pierwszy, ponieważ nie zawsze wiesz, czy właściwość obiektu została początkowo utworzona, czy nie.

Aktualizowanie modelu cyfrowej reprezentacji bliźniaczej

Funkcja UpdateDigitalTwin() może również służyć do migrowania cyfrowej reprezentacji bliźniaczej do innego modelu.

Rozważmy na przykład następujący dokument poprawki JSON, który zastępuje pole metadanych $model cyfrowej reprezentacji bliźniaczej:

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

Ta operacja powiedzie się tylko wtedy, gdy cyfrowa reprezentacja bliźniaczej jest modyfikowana przez poprawkę zgodną z nowym modelem.

Rozważmy następujący przykład:

  1. Wyobraź sobie cyfrową reprezentację bliźniaczą z modelem foo_old. foo_old definiuje wymaganą masę właściwości.
  2. Nowy model foo_new definiuje masę właściwości i dodaje nową wymaganą temperaturę właściwości.
  3. Po wprowadzeniu poprawki cyfrowa reprezentacja bliźniaka musi mieć zarówno właściwość masy, jak i temperatury.

Poprawka dla tej sytuacji musi zaktualizować zarówno model, jak i właściwość temperatury bliźniaczej reprezentacji bliźniaczej, w następujący sposób:

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

Aktualizowanie właściwości sourceTime

Opcjonalnie możesz zdecydować się na użycie sourceTime pola we właściwościach reprezentacji bliźniaczej, aby rejestrować znaczniki czasu, gdy aktualizacje właściwości są obserwowane w świecie rzeczywistym. Usługa Azure Digital Twins natywnie obsługuje sourceTime metadane dla każdej właściwości bliźniaczej reprezentacji. Wartość musi być zgodna sourceTime z formatem daty i godziny ISO 8601. Aby uzyskać więcej informacji na temat tego pola i innych pól dotyczących cyfrowych reprezentacji bliźniaczych, zobacz Format JSON reprezentacji cyfrowej reprezentacji bliźniaczej.

Minimalna stabilna wersja interfejsu API REST do obsługi tego pola to wersja 2022-05-31 . Aby pracować z tym polem przy użyciu zestawów SDK usługi Azure Digital Twins, zalecamy użycie najnowszej wersji zestawu SDK, aby upewnić się, że to pole jest uwzględnione.

Oto przykład dokumentu poprawki JSON, który aktualizuje zarówno wartość, jak i sourceTime pole Temperature właściwości:

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

Aby zaktualizować sourceTime pole we właściwości będącej częścią składnika, dołącz składnik na początku ścieżki. W powyższym przykładzie można to zrobić, zmieniając wartość ścieżki z /$metadata/Temperature/sourceTime na myComponent/$metadata/Temperature/sourceTime.

Uwaga

Jeśli zaktualizujesz zarówno wartość , jak sourceTime i we właściwości, a następnie zaktualizujesz tylko wartość właściwości, sourceTime sygnatura czasowa z pierwszej aktualizacji pozostanie.

Obsługa wywołań aktualizacji powodującej konflikt

Usługa Azure Digital Twins zapewnia, że wszystkie żądania przychodzące są przetwarzane jeden po drugim. Oznacza to, że nawet jeśli wiele funkcji próbuje zaktualizować tę samą właściwość w bliźniaczej reprezentacji w tym samym czasie, nie ma potrzeby pisania jawnego kodu blokującego w celu obsługi konfliktu.

To zachowanie jest oparte na bliźniaczej reprezentacji.

Załóżmy na przykład scenariusz, w którym te trzy wywołania docierają w tym samym czasie:

  • Zapis właściwości A w usłudze Twin1
  • Zapis właściwości B w usłudze Twin1
  • Zapis właściwości A w bliźniaczej reprezentacji Bliźniaczej 2

Dwa wywołania modyfikujące reprezentację Twin1 są wykonywane jeden po drugim, a komunikaty o zmianie są generowane dla każdej zmiany. Wywołanie modyfikowania usługi Twin2 można wykonać jednocześnie bez konfliktu, gdy tylko nadejdzie.

Usuwanie cyfrowej reprezentacji bliźniaczej

Bliźniacze reprezentacje można usunąć przy użyciu DeleteDigitalTwin() metody . Można jednak usunąć bliźniacze reprezentację tylko wtedy, gdy nie ma więcej relacji. Dlatego najpierw usuń relacje przychodzące i wychodzące bliźniaczej reprezentacji bliźniaczej.

Oto przykład kodu do usuwania bliźniaczych reprezentacji i ich relacji. Wywołanie DeleteDigitalTwin zestawu SDK zostało wyróżnione, aby wyjaśnić, gdzie znajduje się w szerszym kontekście przykładu.

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

Usuń wszystkie cyfrowe reprezentacje bliźniacze

Aby zapoznać się z przykładem usuwania wszystkich bliźniaczych reprezentacji jednocześnie, pobierz przykładową aplikację używaną w sekcji Eksploruj podstawy z przykładową aplikacją kliencką. Plik CommandLoop.cs wykonuje to w CommandDeleteAllTwins() funkcji.

Uwaga

Jeśli chcesz usunąć wszystkie modele, reprezentacje bliźniacze i relacje w wystąpieniu jednocześnie, użyj interfejsu API usuwania zadań.

Przykładowy kod z możliwością uruchamiania cyfrowej reprezentacji bliźniaczej

Poniższy przykładowy kod możliwy do uruchomienia umożliwia utworzenie bliźniaczej reprezentacji, zaktualizowanie jej szczegółów i usunięcie bliźniaczej reprezentacji.

Konfigurowanie przykładowych plików projektu

Fragment kodu używa przykładowej definicji modelu Room.json. Aby pobrać plik modelu, aby można było go użyć w kodzie, użyj tego linku, aby przejść bezpośrednio do pliku w usłudze GitHub. Następnie kliknij prawym przyciskiem myszy w dowolnym miejscu na ekranie, wybierz polecenie Zapisz w menu prawym przyciskiem myszy przeglądarki i użyj okna Zapisz jako, aby zapisać plik w formacie Room.json.

Następnie utwórz nowy projekt aplikacji konsolowej w programie Visual Studio lub wybranym edytorze.

Następnie skopiuj następujący kod przykładu możliwego do uruchomienia do projektu:

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>

    }
}

Uwaga

Obecnie występuje znany problem dotyczący DefaultAzureCredential klasy otoki, który może spowodować błąd podczas uwierzytelniania. Jeśli wystąpi ten problem, możesz spróbować utworzyć wystąpienie DefaultAzureCredential za pomocą następującego opcjonalnego parametru, aby rozwiązać ten problem: new DefaultAzureCredential(new DefaultAzureCredentialOptions { ExcludeSharedTokenCacheCredential = true });

Aby uzyskać więcej informacji na temat tego problemu, zobacz Znane problemy usługi Azure Digital Twins.

Konfigurowanie projektu

Następnie wykonaj następujące kroki, aby skonfigurować kod projektu:

  1. Dodaj pobrany wcześniej plik Room.json do projektu i zastąp <path-to> symbol zastępczy w kodzie, aby poinformować program, gdzie go znaleźć.

  2. Zastąp symbol zastępczy <your-instance-hostname> nazwą hosta wystąpienia usługi Azure Digital Twins.

  3. Dodaj dwie zależności do projektu, które są potrzebne do pracy z usługą Azure Digital Twins. Pierwszy to pakiet zestawu SDK usługi Azure Digital Twins dla platformy .NET, a drugi udostępnia narzędzia ułatwiające uwierzytelnianie na platformie Azure.

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

Należy również skonfigurować poświadczenia lokalne, jeśli chcesz uruchomić przykład bezpośrednio. W następnej sekcji opisano to.

Konfigurowanie lokalnych poświadczeń platformy Azure

W tym przykładzie użyto wartości DefaultAzureCredential (część Azure.Identity biblioteki) do uwierzytelniania użytkowników przy użyciu wystąpienia usługi Azure Digital Twins podczas uruchamiania go na komputerze lokalnym. Aby uzyskać więcej informacji na temat różnych sposobów uwierzytelniania aplikacji klienckiej za pomocą usługi Azure Digital Twins, zobacz Pisanie kodu uwierzytelniania aplikacji.

W programie DefaultAzureCredentialprzykład wyszuka poświadczenia w środowisku lokalnym, takie jak logowanie się platformy Azure w lokalnym interfejsie wiersza polecenia platformy Azure lub w programie Visual Studio lub Visual Studio Code. Z tego powodu należy zalogować się do platformy Azure lokalnie za pomocą jednego z tych mechanizmów, aby skonfigurować poświadczenia dla przykładu.

Jeśli używasz programu Visual Studio lub Visual Studio Code do uruchamiania przykładów kodu, upewnij się, że zalogowaliśmy się do tego edytora przy użyciu tych samych poświadczeń platformy Azure, których chcesz użyć do uzyskania dostępu do wystąpienia usługi Azure Digital Twins. Jeśli używasz lokalnego okna interfejsu wiersza polecenia, uruchom az login polecenie , aby zalogować się do konta platformy Azure. Następnie po uruchomieniu przykładowego kodu powinno nastąpić automatyczne uwierzytelnienie.

Uruchamianie aplikacji przykładowej

Po zakończeniu instalacji możesz uruchomić przykładowy projekt kodu.

Oto dane wyjściowe konsoli powyższego programu:

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

Następne kroki

Zobacz, jak tworzyć relacje między bliźniaczymi reprezentacjami bliźniaczymi i zarządzać nimi: