Synchronizacja modeli między usługą Azure Digital Twins i Time Series Insights Gen2

Uwaga

Usługa Time Series Insights (TSI) nie będzie już obsługiwana po marcu 2025 r. Rozważ migrację istniejących środowisk TSI do alternatywnych rozwiązań tak szybko, jak to możliwe. Aby uzyskać więcej informacji na temat wycofywania i migracji, odwiedź naszą dokumentację.

W tym artykule opisano najlepsze rozwiązania i narzędzia używane do tłumaczenia modelu zasobów w usłudze Azure Digital Twins (ADT) na model zasobów w usłudze Azure Time Series Insights (TSI). Ten artykuł jest drugą częścią dwuczęściowej serii samouczków wyjaśniających integrację usługi Azure Digital Twins z Azure Time Series Insights. Integracja usługi Azure Digital Twins z usługą Time Series Insights umożliwia archiwizowanie i śledzenie historii telemetrii i obliczonych właściwości usługi Digital Twins. Ta seria samouczków jest przeznaczona dla deweloperów pracujących nad integracją usługi Time Series Insights z usługą Azure Digital Twins. W części 1 wyjaśniono tworzenie potoku danych, który wprowadza rzeczywiste dane szeregów czasowych z usługi Azure Digital Twins do usługi Time Series Insights . Druga część serii samouczków wyjaśnia synchronizację modeli zasobów między usługami Azure Digital Twins i Time Series Insights. W tym samouczku wyjaśniono najlepsze rozwiązania dotyczące wybierania i ustanawiania konwencji nazewnictwa dla identyfikatora szeregów czasowych (TS ID) oraz ręcznego ustanawiania hierarchii w modelu szeregów czasowych (TSM).

Wybieranie identyfikatora szeregów czasowych

Identyfikator szeregów czasowych to unikatowy identyfikator używany do identyfikowania zasobów w usłudze Time Series Insights. Dane szeregów czasowych (telemetrie z pola, które są parami wartości czasowej) są reprezentowane przy użyciu zmiennych wymienionych w obszarze TSID. W usłudze Azure Digital Twins właściwości bliźniaczych reprezentacji bliźniaczych i telemetrii są używane do reprezentowania stanu reprezentacji bliźniaczej i pomiarów generowanych odpowiednio przez bliźniaczą reprezentację. Od bieżącego projektu TSM identyfikatory TSID muszą być unikatowe. Używanie identyfikatorów bliźniaczych reprezentacji bliźniaczych w usłudze Azure Digital Twins lub w połączeniu z nazwą właściwości lub telemetrii zawsze spowoduje, że unikatowy identyfikator TS w rozwiązaniu TSM. W typowym przypadku <Twin ID> będzie to TSID, a nazwy właściwości i telemetrii będą zmiennymi w programie TSM. Jednak istnieją przypadki użycia, w których preferowane jest, aby hierarchie zasobów w usłudze Time Series Insights były spłaszczone przy użyciu formatu kluczy złożonych, takich jak <Twin ID>+ <Delimiter of Choice> + <Name of the Property or Telemetry>. Przyjrzyjmy się przykładowi, aby wyjaśnić późniejszy przypadek. Rozważmy pokój w budynku modelowany jako bliźniak i ma bliźniaczą reprezentację o identyfikatorze Room22. Jego właściwość ustawienia temperatury ma zostać przetłumaczona jako Room22_TempSetting TSID i pomiar temperatury do przetłumaczenia na Room22_TempMea w rozwiązaniu TSM.

Wybieranie identyfikatora szeregów czasowych

Kontekstowanie szeregów czasowych

Kontekstyzacja danych (głównie przestrzennych) w usłudze Time Series Insights jest osiągana za pomocą hierarchii zasobów, a te same są używane do łatwego nawigacji danych za pośrednictwem widoku drzewa w Eksploratorze usługi Time Series Insights. Typy szeregów czasowych i hierarchie są definiowane przy użyciu modelu szeregów czasowych (TSM) w usłudze Time Series Insights. Typy w programie TSM ułatwiają definiowanie zmiennych, podczas gdy poziomy hierarchii i wartości pól wystąpienia są używane do konstruowania widoku drzewa w eksploratorze usługi Time Series Insights. Aby uzyskać więcej informacji na temat rozwiązania TSM, zapoznaj się z dokumentacją usługi Time Series Insights w trybie online.

W usłudze Azure Digital Twins połączenie między zasobami jest wyrażane przy użyciu relacji bliźniaczych. Relacje bliźniaczych reprezentacji to po prostu graf połączonych zasobów. Jednak w usłudze Time Series Insight relacje między zasobami są hierarchiczne. Oznacza to, że zasoby współdzielą relację typu nadrzędny-podrzędny i są reprezentowane przy użyciu struktury drzewa. Aby przetłumaczyć informacje o relacji z usługi Azure Digital Twins na hierarchie usługi Time Series Insights, musimy wybrać odpowiednie relacje hierarchiczne z usługi Azure Digital Twins. Usługa Azure Digital Twins używa otwartego standardowego języka modelowania o nazwie Digital Twin Definition Language (DTDL). W modelach DTDL opisano użycie wariantu kodu JSON o nazwie JSON-LD. Aby uzyskać szczegółowe informacje na temat specyfikacji, zapoznaj się z dokumentacją języka DTDL .

Połączenie między zasobami

Tłumaczenie reprezentacji grafu w usłudze Azure Digital Twins na strukturę drzewa w usłudze Time Series Insights

W poniższych sekcjach samouczka przedstawiono kilka podstawowych scenariuszy ręcznego tłumaczenia struktury grafu w usłudze Azure Digital Twins na strukturę drzewa w usłudze Time Series Insights.

Przykładowy system: ten samouczek korzysta z poniższego przykładu w celu wyjaśnienia pojęć omówionych poniżej. Jest to prosty, fikcyjny system zarządzania budynkami z jednym piętrze i dwoma pokojami. Ma trzy termostaty, jeden w każdym z pomieszczeń, a drugi wspólny na podłodze. Ponadto ma również miernik przepływu wody pomiaru przepływu wody z Room21 do Room22 przez połączenie rurowe między pokojami. Patrząc na relację przestrzenną między bliźniaczymi reprezentacjami, ma oba typy relacji.

  1. Najczęściej spotykana, hierarchiczna relacja. Na przykład Building40 -> Floor01 -> FloorTS* -> Temperature

  2. Nie tak powszechna, cykliczna relacja. Na przykład, począwszy od budynku40, przepływMtr można śledzić za pomocą dwóch różnych ścieżek.

    1. Budynek40 -> Floor01 -> Room21 -> FlowMtr* -> Flow
    2. Budynek40 -> Floor01 -> Room22 -> FlowMtr* -> Flow
      Gdzie "Przepływ" to rzeczywista telemetria pomiaru przepływu wody między room21 i Room22

Uwaga

* FloorTS oznacza FloorThermoStat i FlowMtr skrót od Flow Meter i zazwyczaj wybierany jako TSID. Temperature and Flow to nieprzetworzone dane telemetryczne określane jako zmienne w usłudze Time Series Insights.

Biorąc pod uwagę bieżące ograniczenie w usłudze Time Series Insights, że jeden zasób nie może być reprezentowany w wielu gałęziach, w poniższych sekcjach wyjaśniono modelowanie relacji hierarchicznych i cyklicznych w usłudze Time Series Insights.

Przypadek 1: Relacja hierarchiczna (nadrzędny-podrzędny)

Jest to najczęstszy typ relacji między bliźniaczymi reprezentacjami. Modelowanie czystej relacji nadrzędny-podrzędny zostało wyjaśnione na poniższej ilustracji. Pola wystąpienia i identyfikator TSID pochodzą z identyfikatorów bliźniaczych reprezentacji, jak pokazano poniżej. Chociaż pola wystąpień można aktualizować ręcznie przy użyciu eksploratora usługi Time Series Insights, sekcja poniżej o nazwie "Aktualizowanie pól wystąpień przy użyciu interfejsów API" wyjaśnia nasłuchiwanie zmian modelu w usłudze Azure Digital Twins i aktualizowanie pól wystąpień w usłudze Time Series Insights przy użyciu funkcji platformy Azure.

Mapowanie identyfikatorów bliźniaczych reprezentacji

Mapowanie identyfikatorów bliźniaczych reprezentacji 2

Przypadek 2. Relacja cykliczna

Relacja cykliczna w usłudze Azure Digital Twins z jedną relacją hierarchii w usłudze Time Series Insights

Biorąc pod uwagę, że identyfikator TSID musi być unikatowy i może być reprezentowany tylko w jednej hierarchii, ten przypadek reprezentuje "FlowMtr" z telemetrią o nazwie "Flow" tuż poniżej bliźniaczej reprezentacji "Room21". W przyszłości, gdy usługa Time Series Insights może obsługiwać wiele reprezentacji szeregów czasowych w programie TSM, dane telemetryczne "Flow" będą reprezentowane w obszarze "Room 21" i "Room 22"

Poniższy zrzut ekranu przedstawia ręczne mapowanie identyfikatorów bliźniaczych reprezentacji bliźniaczych w polu Azure Digital Twins na wystąpienie w rozwiązaniu TSM oraz wynikową hierarchię w usłudze Time Series Insights.

Mapowanie identyfikatorów bliźniaczych reprezentacji bliźniaczych w usłudze Azure Digital Twins

Relacja cykliczna w usłudze Azure Digital Twins z wieloma hierarchiami w usłudze Time Series Insights przy użyciu duplikatów

W części 1 samouczka wyjaśniono, jak program kliencki (funkcja platformy Azure) pomaga przesyłać dane telemetryczne z IoT Hub lub innych źródeł zdarzeń do usługi Azure Digital Twins. Takie podejście sugeruje użycie tego samego programu klienckiego do wprowadzania aktualizacji odpowiednich właściwości nadrzędnych reprezentacji bliźniaczych. W danym przykładzie podczas odczytywania danych telemetrycznych FlowMtr z IoT Hub i aktualizowania właściwości "Flow" w bliźniaczej reprezentacji flowMtr program może również zaktualizować odpowiednie właściwości we wszystkich możliwych nadrzędnych bliźniaczych reprezentacjach źródła. W naszym przykładzie będzie to właściwość "outflowmea" (zidentyfikowana przy użyciu relacji "outflow") właściwości Room21 i "inflowmea" właściwości Room22. Poniższy zrzut ekranu przedstawia środowisko użytkownika końcowego w eksploratorze usługi Time Series Insights. Należy zauważyć, że mamy duplikaty danych, stosując to podejście.

Eksplorator usługi Time Series Insights

Poniższy fragment kodu pokazuje, jak aplikacja kliencka mogła nawigować po relacji bliźniaczej za pomocą interfejsów API usługi Azure Digital Twins.

Uwaga

W tym przykładzie fragmentu kodu założono, że czytelnicy znają część 01 samouczka, a ta zmiana kodu została wprowadzonych w funkcji "ProcessHubToDTEvents".

if (propertyPath.Equals("/Flow"))
{
//Update the flow value property of the flow meter
await AdtUtilities.UpdateTwinProperty(client, twinId, "replace",
propertyPath, "double", propertyValue, log);

//also update the sending end flow
string parentIdOutflow = await AdtUtilities.FindParent(client, twinId,
"outflow", log);
if (parentIdOutflow != null)
await AdtUtilities.UpdateTwinProperty(client, parentIdOutflow, "replace", "outflow", "double", propertyValue, log);
else
log.LogInformation("Unable to find Parent with outflow
relationship for " + twinId );
//and receiving end flow value
string parentIdinflow = await AdtUtilities.FindParent(client, twinId,
"inflow", log);
if (parentIdinflow != null)

await AdtUtilities.UpdateTwinProperty(client, parentIdinflow,
"replace", "inflow", "double", propertyValue, log);
else
log.LogInformation("Unable to find Parent with inflow
relationship for " + twinId);
}

Aktualizowanie pól wystąpienia przy użyciu interfejsów API

W tej sekcji samouczka wyjaśniono, jak nasłuchiwać zmian modelu w usłudze Azure Digital Twins, takich jak tworzenie, usuwanie reprezentacji bliźniaczych lub zmiana relacji między bliźniaczymi reprezentacjami oraz programowe aktualizowanie pól wystąpień i hierarchii przy użyciu interfejsów API modelu usługi Time Series Insights. Ta metoda aktualizowania modelu usługi Time Series Insights jest zwykle osiągana za pośrednictwem funkcji platformy Azure. W usłudze Azure Digital Twins powiadomienia o zdarzeniach, takie jak dodawanie lub usuwanie reprezentacji bliźniaczej, mogą być kierowane do usług podrzędnych, takich jak Event Hubs, które z kolei mogą być przekazywane do funkcji platformy Azure. Więcej szczegółowych informacji na temat routingu i filtrowania zdarzeń wyjaśniono tutaj. W pozostałej części tej sekcji opisano używanie interfejsów API modelu usługi Time Series Insights w usłudze Azure Functions w celu zaktualizowania modelu usługi Time Series Insights w odpowiedzi na dodanie bliźniaczej reprezentacji (jeden typ zmiany modelu) w usłudze Azure Digital Twins.

Odbieranie i identyfikowanie powiadomienia o zdarzeniu dodawania reprezentacji bliźniaczej

[FunctionName("RouteEventsToTsi")]
public async Task Run([EventGridTrigger]EventGridEvent eventGridEvent)
{
    try
    {
        if (eventGridEvent != null && eventGridEvent.Data != null)
        {
            logger.LogInformation($"EventType: {eventGridEvent.EventType}");
            logger.LogInformation($"EventGridEvent: {JsonConvert.SerializeObject(eventGridEvent)}");

            //Shape event and Send event data to event hub and tsi
            await SendEventToEventHubAsync(eventGridEvent).ConfigureAwait(false);

            //If a new twin was created, update the newly created instance in TSI with info retrieved from ADT
            if (eventGridEvent.EventType == Constants.TwinCreateEventType)
            {
                //retrieve building, floor and room of value twin
                var twinInfo = await RetrieveTwinInfoAsync(eventGridEvent).ConfigureAwait(false);
                //Update Tsi instance with type(sensor type), hierarchy(space hierarchy) and instance fields(twin info retrieved above)
                var instance = await CreateInstanceToSendAsync(twinInfo).ConfigureAwait(false);
                var instanceToUpdate = new List<TimeSeriesInstance>() { instance };
                var response = await tsiClient.TimeSeriesInstances.ExecuteBatchAsync(new InstancesBatchRequest(update: instanceToUpdate)).ConfigureAwait(false);
            }
        }
    }
    catch (Exception ex)
    {
        logger.LogError($"Exception: {ex.Message}");
    }
}

Tworzenie klienta usługi Time Series Insights i dodawanie szczegółów wystąpienia

private async Task<TimeSeriesInstance> CreateInstanceToSendAsync(Dictionary<string, string> twinInfo)
{
    try
    {
        tsiClient = await GetTSIClientAsync().ConfigureAwait(false);

        var timeSeriesId = new object[] { twinInfo[Constants.DtId] };
        var instances = await tsiClient.TimeSeriesInstances.ExecuteBatchAsync(
            new InstancesBatchRequest(
                get: new InstancesRequestBatchGetOrDelete(
                    new IList<object>[] { timeSeriesId }))).ConfigureAwait(false);
        var instance = instances.Get.First().Instance;

        if (instance != null)
        {
            instance = await AddHierarchyToInstanceAsync(instance).ConfigureAwait(false);
            instance = await AddTypeToInstanceAsync(instance, twinInfo[Constants.TwinType]).ConfigureAwait(false);

            instance.InstanceFields = new Dictionary<string, object>
                            {
                                { "Building", twinInfo[Constants.BuildingName] },
                                { "Floor", twinInfo[Constants.FloorName] },
                                { "Room", twinInfo[Constants.ParentName] }
                            };

            //If value twin is a sensor value twin, add sensor type instance field to diff from spatial value twin
            if (twinInfo[Constants.ParentType] == Constants.Sensor)
            {
                instance.InstanceFields.Add(Constants.SensorType, twinInfo[Constants.TwinType]);
            }
            return instance;
        }
        else
        {
            logger.LogError($"instance with id {twinInfo[Constants.DtId]} not found");
            return new TimeSeriesInstance();
        }
    }
    catch (Exception e)
    {
        logger.LogError(e.Message);
        throw;
    }
}

Stosowanie informacji o hierarchii do wystąpienia

private async Task<TimeSeriesInstance> AddHierarchyToInstanceAsync(TimeSeriesInstance instance)
{
    if (instance.HierarchyIds == null)
    {
        TimeSeriesHierarchy spacesHierarchy = null;
        try
        {
            var hierarchy = await RunGetHierarchiesAsync(Constants.SpaceHierarchy).ConfigureAwait(false);
            spacesHierarchy = hierarchy.First(h => h.Name.Equals(Constants.SpaceHierarchy));
            instance.HierarchyIds = new List<Guid?>();
            instance.HierarchyIds.Add(spacesHierarchy.Id);
        }
        catch (Exception ex)
        {
            logger.LogWarning($"Hierarchy 'space hierarchy' not found, {ex}");
            throw;
        }
    }
    return instance;
}

Następne kroki

Po trzecie w serii samouczków pokazano, jak wykonywać zapytania dotyczące danych historycznych z usługi Azure Digital Twins przy użyciu interfejsów API usługi Time Series Insights. Jest to praca w toku, a sekcja zostanie zaktualizowana, gdy wszystko będzie gotowe. W międzyczasie zachęcamy czytelników do korzystania z dokumentacji interfejsu API zapytań dotyczących danych usługi Time Series Insights.