Поделиться через


Руководство. Написание кода с помощью пакета SDK для Azure Digital Twins

Разработчики, использующие Azure Digital Twins, часто создают клиентские приложения для взаимодействия со своим экземпляром службы Azure Digital Twins. Этот учебник предназначен для разработчиков и содержит вводные сведения о программировании для службы Azure Digital Twins с помощью пакета SDK Azure Digital Twins для .NET (C#). В нем пошагово описывается процесс написания консольного клиентского приложения на C# с самого начала.

  • Настройка проекта
  • Начало создания кода проекта
  • Полный пример кода
  • Очистка ресурсов
  • Следующие шаги

Необходимые компоненты

В этом учебнике по Azure Digital Twins настройка и работа над проектом выполняется в командной строке. Поэтому для выполнения упражнений вы можете использовать любой редактор кода.

Для начала работы вам потребуется следующее.

  • Любой редактор кода.
  • .NET Core 3.1 на вашем компьютере разработчика. Вы можете скачать эту версию пакета SDK .NET Core для нескольких платформ по этой ссылке: Загрузка .NET Core 3.1.

Подготовка экземпляра Azure Digital Twins

Для работы с Azure Digital Twins в этой статье требуется экземпляр Azure Digital Twins и необходимые разрешения для его использования. Если у вас уже настроен экземпляр Azure Digital Twins, этот экземпляр можно использовать и перейти к следующему разделу. В противном случае выполните инструкции по настройке экземпляра и аутентификации. Инструкции содержат сведения, помогающие убедиться, что каждый шаг выполнен успешно.

После настройки экземпляра запишите имя узла экземпляра. Вы можете найти имя хоста на портале Azure.

Настройка локальных учетных данных Azure

В этом примере используется DefaultAzureCredential (часть библиотеки Azure.Identity) для аутентификации пользователей с помощью экземпляра Azure Digital Twins, запускаемого на локальном компьютере. Дополнительные сведения о различных способах аутентификации клиентского приложения в Azure Digital Twins см. в статье о записи кода аутентификации приложения.

При использовании DefaultAzureCredential пример будет искать учетные данные в локальной среде, например имя для входа Azure в локальной версии Azure CLI, в Visual Studio либо Visual Studio Code. Поэтому вам нужно войти в Azure локально с помощью одного из этих механизмов, чтобы настроить учетные данные для примера.

Если вы используете Visual Studio или Visual Studio Code для выполнения примеров кода, убедитесь, что вы вошли в этот редактор с теми же учетными данными Azure, которые вы хотите использовать для доступа к экземпляру Azure Digital Twins. Если вы используете локальное окно CLI, выполните az login команду, чтобы войти в учетную запись Azure. После этого при запуске примера кода необходимо автоматически пройти проверку подлинности.

Настройка проекта

Когда вы будете готовы к работе со своим экземпляром Azure Digital Twins, начните с настройки проекта клиентского приложения.

Откройте окно консоли на компьютере и создайте пустой каталог проекта, в котором вы хотите сохранить работу в рамках этого руководства. Присвойте этому каталогу любое имя (например, DigitalTwinsCodeTutorial).

Перейдите в новый каталог.

В этом каталоге проекта создайте пустой проект консольного приложения .NET. В командном окне можно выполнить следующую команду, чтобы создать минимальный проект C# для консоли:

dotnet new console

Эта команда создает несколько файлов в каталоге, включая один вызывается Program.cs , где выполняется большая часть кода.

Откройте окно командной строки, так как по-прежнему будете использовать его во всем руководстве.

Затем добавьте две зависимости в проект, необходимые для работы с Azure Digital Twins. Первая зависимость — это пакет пакета для пакета SDK Azure Digital Twins для .NET. Вторая зависимость предоставляет инструменты для проверки подлинности в Azure.

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

Начало создания кода проекта

В этом разделе вы начнете писать код для нового проекта приложения для работы с Azure Digital Twins. Вы будете писать код для следующих действий:

  • проверки подлинности в службе;
  • отправки модели;
  • выявления ошибок;
  • создания цифровых двойников;
  • создания связей;
  • выполнения запросов цифровых двойников.

В конце руководства есть раздел, в котором приведен полный код. Вы можете использовать его в качестве справки для проверки своей программы по мере ее создания.

Для начала откройте файл Program.cs в любом редакторе кода. Вы увидите минимальный шаблон кода, который выглядит примерно так:

Снимок экрана: фрагмент образца кода в редакторе кода

В первую очередь добавьте несколько строк using в верхней части кода, чтобы включить необходимые зависимости.

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

Затем добавьте код в этот файл, чтобы заполнить некоторые функциональные возможности.

Проверка подлинности в службе

Первое, что необходимо сделать для приложения, — проверка подлинности в службе Azure Digital Twins. Затем можно создать класс клиента службы для доступа к функциям пакета SDK.

Для аутентификации требуется имя узла экземпляра Azure Digital Twins.

В Program.cs вставьте следующий код под строкой печати Hello, World!" в методе Main . Задайте значение для имени узла экземпляра adtInstanceUrl Azure Digital Twins.

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

Сохраните файл.

В командном окне запустите этот код с помощью следующей команды:

dotnet run

Эта команда восстанавливает зависимости при первом запуске, а затем выполняет программу.

  • Если ошибка не возникает, программа выводит сообщение "Клиент службы создан - готов к переходу".
  • Так как в этом проекте еще нет обработки ошибок, при возникновении каких-либо проблем возникает исключение, возникающее в коде.

Примечание.

В настоящее время существует известная проблема, влияющая на DefaultAzureCredential класс оболочки, которая может привести к ошибке при проверке подлинности. При возникновении этой проблемы можно попробовать создать экземпляр DefaultAzureCredential с помощью следующего необязательного параметра, чтобы устранить эту проблему: new DefaultAzureCredential(new DefaultAzureCredentialOptions { ExcludeSharedTokenCacheCredential = true });

Дополнительные сведения об этой проблеме см. в статье об известных проблемах Azure Digital Twins.

Отправка модели

В Azure Digital Twins отсутствует встроенный словарь домена. Модели используются для определения типов элементов в среде, которые можно представить в Azure Digital Twins. Модели похожи на классы в объектно-ориентированных языках программирования. Они предоставляют определяемые пользователем шаблоны для цифровых двойников, экземпляры которых будут затем создаваться на основе этих шаблонов. Они написаны на языке, подобном JSON, который называется DTDL.

При создании решения Azure Digital Twins в первую очередь необходимо определить хотя бы одну модель в файле DTDL.

В каталоге, в котором вы создали проект, создайте новый файл .json с именем SampleModel.json. Вставьте в этот файл следующий код:

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

Совет

Если вы используете Visual Studio для этого руководства, вы можете выбрать только что созданный JSON-файл и задать свойство Copy to Output Directory в инспекторе свойств, чтобы скопировать, если создать или копировать always. Это значение свойства позволяет Visual Studio найти JSON-файл с путем по умолчанию при запуске программы с помощью F5 во время работы с этим руководством.

Совет

Вы можете проверить документы модели, чтобы убедиться, что DTDL является допустимым с помощью библиотеки DTDLParser. Дополнительные сведения об использовании этой библиотеки см. в разделе "Анализ и проверка моделей".

Затем добавьте дополнительный код, чтобы Program.cs передать модель, созданную в экземпляр Azure Digital Twins.

Сначала добавьте несколько инструкций using в начало файла:

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

Затем подготовьте использование асинхронных методов в пакете SDK службы C#, изменив сигнатуру метода Main, чтобы разрешить асинхронное выполнение.

static async Task Main(string[] args)
{

Примечание.

Использование async не является строго обязательным, так как пакет SDK также предоставляет синхронные версии всех вызовов. В упражнениях этого учебника используется async.

Далее идет первый фрагмент кода, который взаимодействует со службой Azure Digital Twins. Этот код загружает с диска созданный вами файл DTDL и отправляет его в ваш экземпляр службы Azure Digital Twins.

Вставьте следующий код под кодом проверки подлинности, который вы добавили ранее.

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

В командном окне запустите программу с помощью следующей команды:

dotnet run

Отправка модели выводится в выходных данных, чтобы указать, что этот код достигнут. Однако нет выходных данных, чтобы указать, выполнена ли отправка успешно.

Чтобы добавить инструкцию печати, показывающую все модели, успешно отправленные в экземпляр, добавьте следующий код сразу после предыдущего раздела:

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

Прежде чем снова запустить программу для проверки этого нового кода, вспомните, что в последний раз, когда программа запускалась, вы уже отправили свою модель. Azure Digital Twins не позволяет отправлять одну и ту же модель дважды, поэтому при попытке повторной отправки той же модели программа должна вызвать исключение.

Учитывая эту информацию, запустите программу еще раз с помощью следующей команды в своем командном окне:

dotnet run

Программа должна выдать исключение. При попытке отправить модель, которая уже отправлена, служба возвращает ошибку "неправильный запрос" через REST API. В результате пакет SDK клиента Azure Digital Twins создает исключение для каждого кода возврата службы, отличного от успешного выполнения.

В следующем разделе говорится об исключениях, подобных этому, и о том, как обрабатывать их в вашем коде.

Перехват ошибок

Чтобы предотвратить сбой программы, можно добавить код исключения вокруг кода отправки модели. Заключите существующий клиентский вызов await client.CreateModelsAsync(typeList) в обработчик 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}");
}

Снова запустите программу в dotnet run командном окне. Вы увидите, что вы получите дополнительные сведения о проблеме отправки модели, включая код ошибки, указывающий на это ModelIdAlreadyExists.

С этого момента учебник упаковывает все вызовы методов службы в обработчики try/catch.

Создание цифровых двойников

После отправки модели в Azure Digital Twins можно использовать это определение модели для создания цифровых двойников. Цифровые двойники являются экземплярами модели и представляют сущности в вашей бизнес-среде — такие как датчики на ферме, комнаты в здании или фары автомобиля. В этом разделе создается несколько цифровых двойников на основе модели, которую вы отправили ранее.

Чтобы создать и инициализировать три цифровых двойника на основе этой модели, добавьте следующий код в конец Main метода.

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

В командном окне запустите программу с помощью команды dotnet run. В выходных данных найдите сообщения о том, что sampleTwin-0, sampleTwin-1 и sampleTwin-2 созданы.

Затем снова выполните программу.

Обратите внимание, что при повторном создании двойников ошибки не возникают, даже если двойники уже существуют после первого запуска. В отличие от создания модели, создание двойника — это вызов PUT с семантикой upsert на уровне REST. Использование такого вызова REST означает, что если двойник уже существует, попытка создать один и тот же двойник снова просто заменяет исходный двойник. Сообщение об ошибке при этом не выводится.

Создание отношений

Затем можно создать связи между созданными двойниками, чтобы подключить их к графу двойников. Графы двойников используются для представления всей вашей среды.

Добавьте новый статический метод в Program класс Main под методом (код теперь имеет два метода):

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

Затем добавьте следующий код в конец метода Main, чтобы вызвать метод CreateRelationship и использовать только что написанный код:

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

В командном окне запустите программу с помощью команды dotnet run. В выходных данных найдите сведения об успешном создании двух связей.

Azure Digital Twins не позволяет создавать связь, если другая связь с тем же идентификатором уже существует. В результате вы увидите исключения при создании связей при выполнении программы несколько раз. Этот код перехватывает исключения и игнорирует их.

Список связей

Следующий код, который вы добавите, позволяет просмотреть список созданных связей.

Добавьте в класс Program следующий новый метод.

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

Затем добавьте следующий код в конец метода Main для вызова кода ListRelationships:

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

В командном окне запустите программу с помощью команды dotnet run. Вы увидите список всех связей, созданных в выходной инструкции, которая выглядит следующим образом:

Снимок экрана консоли: выходные данные программы с сообщением со списком связей двойника

Запрашивание цифровых двойников

Главной особенностью Azure Digital Twins является возможность просто и эффективно запрашивать граф двойников, чтобы получать ответы о вашей среде.

В последнем разделе кода, который вы добавите в этом учебнике, выполняется запрос к экземпляру Azure Digital Twins. Запрос, используемый в этом примере, возвращает все цифровые двойники в экземпляре.

Добавьте этот оператор using, чтобы обеспечить использование класса JsonSerializer для представления сведений о цифровом двойнике:

using System.Text.Json;

Затем добавьте следующий код в конец метода Main:

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

В командном окне запустите программу с помощью команды dotnet run. В выходных данных должны быть указаны все цифровые двойники в этом экземпляре.

Примечание.

После внесения изменений в данные в графе может возникнуть задержка до 10 секунд, прежде чем изменения будут отражены в запросах.

API DigitalTwins отражает изменения немедленно, поэтому, если вам нужен мгновенный ответ, используйте запрос API (DigitalTwins GetById) или вызов пакета SDK (GetDigitalTwin) для получения данных двойника вместо запроса.

Полный пример кода

На этом этапе у вас есть готовое клиентское приложение, которое может выполнять базовые действия в Azure Digital Twins. Для справки в следующем примере приводится полный код программы в Program.cs:

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>
    }
}

Очистка ресурсов

По завершении работы с этим руководством вы можете выбрать ресурсы, которые нужно удалить, в зависимости от планируемых действий.

  • Если в планируете перейти к следующему руководству, экземпляр из текущего руководства можно использовать при работе со следующим. Вы можете оставить настроенные здесь ресурсы Azure Digital Twins и пропустить оставшуюся часть этого раздела.
  • Если вы хотите продолжить использование экземпляра Azure Digital Twins из этой статьи, но удалите все его модели, двойники и связи, выполните следующую команду az dt job deletion CLI:

    az dt job deletion create -n <name-of-Azure-Digital-Twins-instance> -y
    

    Если требуется удалить только некоторые из этих элементов, можно использовать az dt twin relationship delete, az dt twin delete и az dt model delete , чтобы выборочно удалить только те элементы, которые нужно удалить.

  • Если вам не нужен какой-либо из ресурсов, созданных в этом руководстве, можно удалить экземпляр Azure Digital Twins и все остальные ресурсы из этой статьи с помощью команды az group delete CLI. При этом будут удалены все ресурсы Azure в группе ресурсов, а также сама группа.

    Внимание

    Удаление группы ресурсов — процесс необратимый. Группа ресурсов и все содержащиеся в ней ресурсы удаляются без возможности восстановления. Будьте внимательны, чтобы случайно не удалить не ту группу ресурсов или не те ресурсы.

    Откройте Azure Cloud Shell или локальное окно CLI и выполните следующую команду, чтобы удалить группу ресурсов и все, что она содержит.

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

Вы также можете удалить папку проекта с локального компьютера.

Следующие шаги

В этом руководстве вы с нуля создали консольное клиентское приложение консоли .NET. Вы написали код для этого клиентского приложения, чтобы выполнять базовые действия в экземпляре Azure Digital Twins.

Перейдите к следующему учебнику, чтобы изучить действия, которые можно выполнять с помощью такого примера клиентского приложения: