Självstudie: Kodning med Azure Digital Twins API:er

Utvecklare som arbetar Azure Digital Twins skriver ofta klientprogram för att interagera med sin instans av Azure Digital Twins tjänsten. Den här självstudien om utvecklare ger en introduktion till programmering mot Azure Digital Twins-tjänsten med hjälp av Azure Digital Twins SDK för .NET (C#). Den visar steg för steg hur du skriver en C#-konsolklientapp från början.

  • Konfigurera projekt
  • Kom igång med projektkod
  • Fullständigt kodexempel
  • Rensa resurser
  • Nästa steg

Förutsättningar

Den Azure Digital Twins självstudien använder kommandoraden för installation och projektarbete. Därför kan du använda valfri kodredigerare för att gå igenom övningarna.

Vad du behöver för att börja:

  • Valfri kodredigerare
  • .NET Core 3.1 på utvecklingsdatorn. Du kan hämta den här versionen av .NET Core SDK för flera plattformar från Ladda ned .NET Core 3.1.

Förbereda en Azure Digital Twins instans

Om du vill Azure Digital Twins den här artikeln måste du först konfigurera en Azure Digital Twins instans. Du behöver också de behörigheter som krävs för att använda den. Om du redan har Azure Digital Twins en instans kan du använda den i stället.

Annars följer du anvisningarna i Konfigurera en instans och autentisering. Anvisningarna innehåller information som hjälper dig att kontrollera att du har slutfört varje steg.

När du har ställt in din instans anteckning du följande värden. Du behöver dessa värden för att ansluta till instansen senare:

  • Instansens värdnamn. Du hittar värdnamnet i Azure Portal.
  • Den Azure-prenumeration som du använde för att skapa instansen. Antingen dess namn eller dess ID fungerar. Du hittar prenumerationen på sidan Översikt för din instans i Azure Portal.

Konfigurera lokala Azure-autentiseringsuppgifter

I det här exemplet används DefaultAzureCredential (en del av biblioteket) för att autentisera användare med Azure Digital Twins-instansen när du kör Azure.Identity den på den lokala datorn. Mer information om olika sätt som en klientapp kan autentisera med Azure Digital Twins finns i Skriva kod för appautentisering.

Med DefaultAzureCredential söker exemplet efter autentiseringsuppgifter i din lokala miljö, t. ex. en Azure-inloggning i ett lokalt Azure CLI eller i Visual Studio eller Visual Studio Code. Därför bör du Logga in på Azure lokalt via någon av dessa metoder för att ställa in autentiseringsuppgifter för exemplet.

Om du använder Visual Studio eller Visual Studio Code för att köra kod exemplet måste du kontrol lera att du är inloggad i redigeraren med samma Azure-autentiseringsuppgifter som du vill använda för att få åtkomst till Azure Digitals-instansen.

Annars kan du installera den lokala Azure CLI, starta en kommando tolk på datorn och köra az login kommandot för att logga in på ditt Azure-konto. När du har loggat in när du kör kod exemplet ska du logga in automatiskt.

Konfigurera projekt

När du är redo att sätta igång Azure Digital Twins instansen börjar du konfigurera klientappsprojektet.

Öppna en kommandotolk eller ett annat konsolfönster på datorn och skapa en tom projektkatalog där du vill lagra ditt arbete under den här självstudien. Namnge katalogen vad du vill (till exempel DigitalTwinsCodeTutorial).

Navigera till den nya katalogen.

När du är i projektkatalogen skapar du ett tomt .NET-konsolappsprojekt. I kommandofönstret kan du köra följande kommando för att skapa ett minimalt C#-projekt för konsolen:

dotnet new console

Det här kommandot skapar flera filer i din katalog, inklusive en som heter Program.cs, där du skriver merparten av din kod.

Håll kommandofönstret öppet eftersom du kommer att fortsätta att använda det under hela självstudien.

Lägg sedan till två beroenden i projektet som behövs för att arbeta med Azure Digital Twins. Det första är paketet för Azure Digital Twins SDK för .NET. Det andra är ett verktyg som hjälper dig med autentisering mot Azure.

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

Kom igång med projektkod

I det här avsnittet börjar du skriva koden för ditt nya appprojekt så att det fungerar med Azure Digital Twins. De åtgärder som omfattas är:

  • Autentisera mot tjänsten
  • Ladda upp en modell
  • Fånga fel
  • Skapa digitala tvillingar
  • Skapa relationer
  • Köra frågor mot digitala tvillingar

Det finns också ett avsnitt som visar den fullständiga koden i slutet av självstudien. Du kan använda det här avsnittet som referens för att kontrollera programmet allt eftersom.

Börja genom att öppna filen Program.cs i valfri kodredigerare. Du ser en minimal kodmall som ser ut ungefär så här:

Lägg först till using några rader överst i koden för att hämta nödvändiga beroenden.

using Azure.DigitalTwins.Core;
using Azure.Identity;

Nu ska du lägga till kod i den här filen för att fylla i några funktioner.

Autentisera mot tjänsten

Det första som din app behöver göra är att autentisera mot Azure Digital Twins tjänsten. Sedan kan du skapa en tjänstklientklass för att få åtkomst till SDK-funktionerna.

För att autentisera behöver du värdnamnet för din Azure Digital Twins instans.

I Program.cs klistrar du in följande kod under "Hello, World!" utskriftsrad i Main metoden . Ange värdet för till adtInstanceUrl din Azure Digital Twins instansens värdnamn.

string adtInstanceUrl = "https://<your-Azure-Digital-Twins-instance-hostName>"; 

var credential = new DefaultAzureCredential();
var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credential);
Console.WriteLine($"Service client created – ready to go");

Spara filen.

I kommandofönstret kör du koden med det här kommandot:

dotnet run

Det här kommandot återställer beroendena vid den första körningen och kör sedan programmet.

  • Om inget fel inträffar skriver programmet ut tjänstklienten som skapats – redo att börja.
  • Eftersom det ännu inte finns någon felhantering i det här projektet visas ett undantagsfel i koden om det uppstår några problem.

Upload en modell

Azure Digital Twins har ingen inbyggd domänvokabulär. De typer av element i din miljö som du kan representera i Azure Digital Twins definieras av dig med hjälp av modeller. Modeller liknar klasser i objektorienterade programmeringsspråk. De tillhandahåller användardefinierade mallar som digitala tvillingar kan följa och instansiera senare. De är skrivna i ett JSON-liknande språk som Digital Twins Definition Language (DTDL).

Det första steget i att skapa Azure Digital Twins lösning är att definiera minst en modell i en DTDL-fil.

Skapa en ny .json-fil med namnet SampleModel.json i katalogen där du skapade projektet. Klistra in följande filtext:

{
  "@id": "dtmi:example:SampleModel;1",
  "@type": "Interface",
  "displayName": "SampleModel",
  "contents": [
    {
      "@type": "Relationship",
      "name": "contains"
    },
    {
      "@type": "Property",
      "name": "data",
      "schema": "string"
    }
  ],
  "@context": "dtmi:dtdl:context;2"
}

Tips

Om du använder Visual Studio den här självstudien kanske du vill välja den nyligen skapade JSON-filen och ange egenskapen Kopiera till utdatakatalog i egenskapskontrollen till Kopiera om nyare eller Kopiera alltid. Detta gör att Visual Studio att hitta JSON-filen med standardsökvägen när du kör programmet med F5 under resten av självstudien.

Tips

Det finns ett exempel på språkoberoende DTDL-validerare som du kan använda för att kontrollera modelldokument för att kontrollera att DTDL är giltigt. Den bygger på DTDL-parserbiblioteket, som du kan läsa mer om i Parsa och validera modeller.

Lägg sedan till lite mer kod i Program.cs för att ladda upp modellen som du har skapat till din Azure Digital Twins instans.

Lägg först till några using -instruktioner överst i filen:

using System.Threading.Tasks;
using System.IO;
using System.Collections.Generic;
using Azure;

Förbered sedan användningen av asynkrona metoder i C#-tjänstens SDK genom att ändra metodsignaturen så att den tillåter Main asynkron körning.

static async Task Main(string[] args)
{

Anteckning

Det async är inte absolut nödvändigt att använda eftersom SDK:n även tillhandahåller synkrona versioner av alla anrop. Den här självstudien använder async .

Därefter kommer den första kodbiten som interagerar med Azure Digital Twins tjänsten. Den här koden läser in DTDL-filen som du skapade från disken och laddar sedan upp den till din Azure Digital Twins-tjänstinstans.

Klistra in följande kod under den auktoriseringskod som du lade till tidigare.

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

Kör programmet med det här kommandot i kommandofönstret:

dotnet run

"Upload en modell" skrivs ut i utdata, vilket anger att den här koden har nåtts, men det finns inga utdata ännu för att ange om uppladdningen lyckades.

Om du vill lägga till en utskriftsuttryck som visar alla modeller som har laddats upp till instansen lägger du till följande kod direkt efter föregående avsnitt:

// Read a list of models back from the service
AsyncPageable<DigitalTwinsModelData> modelDataList = client.GetModelsAsync();
await foreach (DigitalTwinsModelData md in modelDataList)
{
    Console.WriteLine($"Model: {md.Id}");
}

Innan du kör programmet igen för att testa den nya koden bör du komma ihåg att den senaste gången du körde programmet laddade du redan upp din modell. Azure Digital Twins inte låter dig ladda upp samma modell två gånger, så om du försöker ladda upp samma modell igen bör programmet utlösta ett undantag.

Med den här informationen i åtanke kör du programmet igen med det här kommandot i kommandofönstret:

dotnet run

Programmet bör utlösta ett undantag. När du försöker ladda upp en modell som redan har laddats upp returnerar tjänsten felet "felaktig begäran" via REST API. Det innebär att Azure Digital Twins klient-SDK i sin tur returnerar ett undantag för varje annan tjänstreturkod än lyckad.

I nästa avsnitt pratar vi om undantag som detta och hur du hanterar dem i din kod.

Fånga fel

Om du vill att programmet inte ska krascha kan du lägga till undantagskod runt modelluppladdningskoden. Omslut det befintliga await client.CreateModelsAsync(typeList) klient-anropet i en try/catch-hanterare så här:

try
{
    await client.CreateModelsAsync(models);
    Console.WriteLine("Models uploaded to the instance:");
}
catch (RequestFailedException e)
{
    Console.WriteLine($"Upload model error: {e.Status}: {e.Message}");
}

Om du nu kör programmet med i kommandofönstret ser dotnet run du att du får tillbaka en felkod. Utdata från koden för modellskapande visar det här felet:

Skärmbild av en konsol som visar programutdata, vilket resulterar i felet &quot;409:Tjänstbegäran misslyckades. Status: 409 (konflikt).'.

Från och med nu omsluter självstudien alla anrop till tjänstmetoder i try/catch-hanterare.

Skapa digitala tvillingar

Nu när du har laddat upp en modell till Azure Digital Twins kan du använda den här modelldefinitionen för att skapa digital twins. Digitala tvillingar är instanser av en modell och representerar entiteterna i din företagsmiljö – till exempel sensorer på en farm, rum i en byggnad eller lampor i en bil. I det här avsnittet skapas några digitala tvillingar baserat på modellen som du laddade upp tidigare.

Lägg till följande kod i slutet av metoden för Main att skapa och initiera tre digitala tvillingar baserat på den här modellen.

var twinData = new BasicDigitalTwin();
twinData.Metadata.ModelId = "dtmi:example:SampleModel;1";
twinData.Contents.Add("data", $"Hello World!");

string prefix = "sampleTwin-";
for (int i = 0; i < 3; i++)
{
    try
    {
        twinData.Id = $"{prefix}{i}";
        await client.CreateOrReplaceDigitalTwinAsync<BasicDigitalTwin>(twinData.Id, twinData);
        Console.WriteLine($"Created twin: {twinData.Id}");
    }
    catch(RequestFailedException e)
    {
        Console.WriteLine($"Create twin error: {e.Status}: {e.Message}");
    }
}

I kommandofönstret kör du programmet med dotnet run . Leta efter de utskriftsmeddelanden som sampleTwin-0, sampleTwin-1 och sampleTwin-2 har skapats i utdata.

Kör sedan programmet igen.

Observera att inget fel uppstår när tvillingarna skapas andra gången, även om tvillingarna redan finns efter den första körningen. Till skillnad från modellskapande är tvillingskapande på REST-nivå ett PUT-anrop med upsert-semantik. Med den här typen av REST-anrop innebär det att om det redan finns en tvilling ersätter ett försök att skapa samma tvilling igen bara den ursprungliga tvillingen. Inget fel uppstår.

Skapa relationer

Därefter kan du skapa relationer mellan de tvillingar som du har skapat för att ansluta dem till en tvillinggraf. Tvillingdiagram används för att representera hela miljön.

Lägg till en ny statisk metod i klassen under metoden Program Main (koden har nu två metoder):

public async static Task CreateRelationshipAsync(DigitalTwinsClient client, string srcId, string targetId)
{
    var relationship = new BasicRelationship
    {
        TargetId = targetId,
        Name = "contains"
    };

    try
    {
        string relId = $"{srcId}-contains->{targetId}";
        await client.CreateOrReplaceRelationshipAsync(srcId, relId, relationship);
        Console.WriteLine("Created relationship successfully");
    }
    catch (RequestFailedException e)
    {
        Console.WriteLine($"Create relationship error: {e.Status}: {e.Message}");
    }
}

Lägg sedan till följande kod i slutet av metoden Main för att anropa metoden och använda den kod som du nyss CreateRelationship skrev:

// Connect the twins with relationships
await CreateRelationshipAsync(client, "sampleTwin-0", "sampleTwin-1");
await CreateRelationshipAsync(client, "sampleTwin-0", "sampleTwin-2");

I kommandofönstret kör du programmet med dotnet run . I utdata letar du efter utskriftsuttryck som säger att de två relationerna har skapats.

Azure Digital Twins låter dig inte skapa en relation om det redan finns en annan relation med samma ID, så om du kör programmet flera gånger visas undantag när relationen skapas. Den här koden fångar upp undantagen och ignorerar dem.

Lista relationer

I nästa kod som du lägger till kan du se listan över relationer som du har skapat.

Lägg till följande nya metod i Program klassen :

public async static Task ListRelationshipsAsync(DigitalTwinsClient client, string srcId)
{
    try
    {
        AsyncPageable<BasicRelationship> results = client.GetRelationshipsAsync<BasicRelationship>(srcId);
        Console.WriteLine($"Twin {srcId} is connected to:");
        await foreach (BasicRelationship rel in results)
        {
            Console.WriteLine($" -{rel.Name}->{rel.TargetId}");
        }
    }
    catch (RequestFailedException e)
    {
        Console.WriteLine($"Relationship retrieval error: {e.Status}: {e.Message}");
    }
}

Lägg sedan till följande kod i slutet av metoden Main för att anropa ListRelationships koden:

//List the relationships
await ListRelationshipsAsync(client, "sampleTwin-0");

I kommandofönstret kör du programmet med dotnet run . Du bör se en lista över alla relationer som du har skapat i en utdata-instruktion som ser ut så här:

Skärmbild av en konsol som visar programutdata, vilket resulterar i ett meddelande som visar tvillingrelationerna.

Fråga digitala tvillingar

En viktig funktion i Azure Digital Twins är möjligheten att köra frågor mot tvillingdiagrammet enkelt och effektivt för att besvara frågor om din miljö.

Det sista kodavsnittet som ska läggas till i den här självstudien kör en fråga mot Azure Digital Twins instansen. Frågan som används i det här exemplet returnerar alla digital twins i instansen.

Lägg till using den här instruktionen för att aktivera användning JsonSerializer av klassen för att presentera digital twin-information:

using System.Text.Json;

Lägg sedan till följande kod i slutet av Main metoden :

// Run a query for all twins
string query = "SELECT * FROM digitaltwins";
AsyncPageable<BasicDigitalTwin> queryResult = client.QueryAsync<BasicDigitalTwin>(query);

await foreach (BasicDigitalTwin twin in queryResult)
{
    Console.WriteLine(JsonSerializer.Serialize(twin));
    Console.WriteLine("---------------");
}

I kommandofönstret kör du programmet med dotnet run . Du bör se alla digitala tvillingar i den här instansen i utdata.

Anteckning

När du har gjort en ändring av data i diagrammet kan det ta upp till 10 sekunder innan ändringarna återspeglas i frågorna.

DigitalTwins-API:et återspeglar ändringar omedelbart, så om du behöver ett omedelbart svar använder du en API-begäran (DigitalTwins GetById)eller ett SDK-anrop (GetDigitalTwin) för att hämta tvillingdata i stället för en fråga.

Fullständigt kodexempel

Nu i självstudien har du en komplett klientapp som kan utföra grundläggande åtgärder mot Azure Digital Twins. Som referens visas den fullständiga koden för programmet i Program.cs nedan:

using System;
// <Azure_Digital_Twins_dependencies>
using Azure.DigitalTwins.Core;
using Azure.Identity;
// </Azure_Digital_Twins_dependencies>
// <Model_dependencies>
using System.Threading.Tasks;
using System.IO;
using System.Collections.Generic;
using Azure;
// </Model_dependencies>
// <Query_dependencies>
using System.Text.Json;
// </Query_dependencies>

namespace DigitalTwins_Samples
{
    class DigitalTwinsClientAppSample
    {
        // <Async_signature>
        static async Task Main(string[] args)
        {
        // </Async_signature>
            Console.WriteLine("Hello World!");
            // <Authentication_code>
            string adtInstanceUrl = "https://<your-Azure-Digital-Twins-instance-hostName>"; 
            
            var credential = new DefaultAzureCredential();
            var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credential);
            Console.WriteLine($"Service client created – ready to go");
            // </Authentication_code>

            // <Model_code>
            Console.WriteLine();
            Console.WriteLine("Upload a model");
            string dtdl = File.ReadAllText("SampleModel.json");
            var models = new List<string> { dtdl };

            // Upload the model to the service
            // <Model_try_catch>
            try
            {
                await client.CreateModelsAsync(models);
                Console.WriteLine("Models uploaded to the instance:");
            }
            catch (RequestFailedException e)
            {
                Console.WriteLine($"Upload model error: {e.Status}: {e.Message}");
            }
            // </Model_try_catch>

            // <Print_model>
            // Read a list of models back from the service
            AsyncPageable<DigitalTwinsModelData> modelDataList = client.GetModelsAsync();
            await foreach (DigitalTwinsModelData md in modelDataList)
            {
                Console.WriteLine($"Model: {md.Id}");
            }
            // </Print_model>
            // </Model_code>

            // <Initialize_twins>
            var twinData = new BasicDigitalTwin();
            twinData.Metadata.ModelId = "dtmi:example:SampleModel;1";
            twinData.Contents.Add("data", $"Hello World!");
            
            string prefix = "sampleTwin-";
            for (int i = 0; i < 3; i++)
            {
                try
                {
                    twinData.Id = $"{prefix}{i}";
                    await client.CreateOrReplaceDigitalTwinAsync<BasicDigitalTwin>(twinData.Id, twinData);
                    Console.WriteLine($"Created twin: {twinData.Id}");
                }
                catch(RequestFailedException e)
                {
                    Console.WriteLine($"Create twin error: {e.Status}: {e.Message}");
                }
            }
            // </Initialize_twins>

            // <Use_create_relationship>
            // Connect the twins with relationships
            await CreateRelationshipAsync(client, "sampleTwin-0", "sampleTwin-1");
            await CreateRelationshipAsync(client, "sampleTwin-0", "sampleTwin-2");
            // </Use_create_relationship>

            // <Use_list_relationships>
            //List the relationships
            await ListRelationshipsAsync(client, "sampleTwin-0");
            // </Use_list_relationships>

            // <Query_twins>
            // Run a query for all twins
            string query = "SELECT * FROM digitaltwins";
            AsyncPageable<BasicDigitalTwin> queryResult = client.QueryAsync<BasicDigitalTwin>(query);
            
            await foreach (BasicDigitalTwin twin in queryResult)
            {
                Console.WriteLine(JsonSerializer.Serialize(twin));
                Console.WriteLine("---------------");
            }
            // </Query_twins>
        }

        // <Create_relationship>
        public async static Task CreateRelationshipAsync(DigitalTwinsClient client, string srcId, string targetId)
        {
            var relationship = new BasicRelationship
            {
                TargetId = targetId,
                Name = "contains"
            };
        
            try
            {
                string relId = $"{srcId}-contains->{targetId}";
                await client.CreateOrReplaceRelationshipAsync(srcId, relId, relationship);
                Console.WriteLine("Created relationship successfully");
            }
            catch (RequestFailedException e)
            {
                Console.WriteLine($"Create relationship error: {e.Status}: {e.Message}");
            }
        }
        // </Create_relationship>
        
        // <List_relationships>
        public async static Task ListRelationshipsAsync(DigitalTwinsClient client, string srcId)
        {
            try
            {
                AsyncPageable<BasicRelationship> results = client.GetRelationshipsAsync<BasicRelationship>(srcId);
                Console.WriteLine($"Twin {srcId} is connected to:");
                await foreach (BasicRelationship rel in results)
                {
                    Console.WriteLine($" -{rel.Name}->{rel.TargetId}");
                }
            }
            catch (RequestFailedException e)
            {
                Console.WriteLine($"Relationship retrieval error: {e.Status}: {e.Message}");
            }
        }
        // </List_relationships>
    }
}

Rensa resurser

När du har slutfört den här självstudien kan du välja vilka resurser du vill ta bort, beroende på vad du vill göra härnäst.

  • Om du planerar att fortsätta till nästa självstudie kan instansen som används i den här självstudien återanvändas i nästa. Du kan behålla de Azure Digital Twins resurser som du ställer in här och hoppa över resten av det här avsnittet.
  • Om du vill fortsätta att använda den Azure Digital Twins-instans som du konfigurerade i den här artikeln, men ta bort vissa eller alla dess modeller, tvillingar och relationer, kan du använda az dt CLI-kommandona i ett Azure Cloud Shell-fönster för att ta bort de element som du vill ta bort.
  • Om du inte behöver någon av de resurser som du skapade i den här självstudien kan du ta bort Azure Digital Twins-instansen och alla andra resurser från den här artikeln med kommandot az group delete. Detta tar bort alla Azure-resurser i en resursgrupp, samt själva resursgruppen.

    Viktigt

    Att ta bort en resursgrupp kan inte ångras. Resursgruppen och alla resurser som ingår i den tas bort permanent. Var noga så att du inte tar bort fel resursgrupp eller resurser av misstag.

    Öppna Azure Cloud Shelloch kör följande kommando för att ta bort resursgruppen och allt som den innehåller.

    az group delete --name <your-resource-group>
    

Du kanske också vill ta bort projektmappen från den lokala datorn.

Nästa steg

I den här självstudien skapade du ett .NET-konsolklientprogram från grunden. Du skrev kod för den här klientappen för att utföra de grundläggande åtgärderna på en Azure Digital Twins instans.

Fortsätt till nästa självstudie för att utforska vad du kan göra med en sådan exempelklientapp: