Автоматическое управление устройствами в Azure Digital Twins с помощью службы подготовки устройств (DPS)

Из этой статьи вы узнаете, как интегрировать Azure Digital Twins со службой подготовки устройств (DPS).

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

Дополнительные сведения о этапах подготовки и выхода на пенсию, а также о наборе общих этапов управления устройствами, которые являются общими для всех корпоративных проектов Интернета вещей, см. в разделе жизненного цикла устройств Центр Интернета вещей документации по управлению устройствами.

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

Перед настройкой подготовки необходимо выполнить конфигурацию указанных далее ресурсов:

В этом примере также используется симулятор устройств, который включает подготовку с помощью службы подготовки устройств. Симулятор устройства расположен здесь: пример интеграции Azure Digital Twins и Центра Интернета вещей. Получите пример проекта на компьютере, перейдя в репозиторий GitHub для примера, который можно скачать как ZIP-файл, нажав кнопку "Код " и "Скачать ZIP-файл".

Screenshot of the digital-twins-iothub-integration repo on GitHub, highlighting the steps to download it as a zip.

Распакуйте загруженные файлы.

Кроме того, на компьютер необходимо установить платформу Node.js. Симулятор устройства основан на Node.js версии 10.0.x или более поздней.

Архитектура решения

Это решение включает шаги по подготовке и снятию с учета устройства в Azure Digital Twins с помощью службы подготовки устройств (DPS).

Для распределения устройств в решении осуществляется обмен данными между устройством термостата и DPS. Затем данные передаются из DPS в Центр Интернета вещей и в Azure Digital Twins с помощью функции Azure.

Чтобы снять устройство с учета, данные процедуры удаления устройства вручную поступают в Azure Digital Twins через Центр Интернета вещей, Центры событий и функцию Azure.

Эта архитектура показана на рисунке ниже.

Diagram of device and several Azure services in an end-to-end scenario showing the data flow.

Эта статья состоит из двух разделов, каждая из которых посвящена отдельной части этой архитектуры:

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

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

Diagram of Provision flow—an excerpt of the solution architecture diagram following data from a thermostat into Azure Digital Twins.

Вот описание процесса:

  1. Устройство связывается с конечной точкой DPS, передавая идентификационные данные для подтверждения своего удостоверения.
  2. Служба DPS проверяет удостоверение устройства, проверяя идентификатор регистрации и ключ в списке регистрации, и вызывает функцию Azure для выполнения выделения.
  3. Функция Azure создает для данного устройства новый двойник в Azure Digital Twins. Имя двойника будет совпадать с идентификатором регистрации устройства.
  4. DPS регистрирует устройство в Центре Интернета вещей и заполняет выбранное состояние двойника устройства.
  5. Центр Интернета вещей возвращает устройству сведения об идентификаторе устройства и подключении к Центру Интернета вещей. Теперь устройство может подключаться к Центру Интернета вещей.

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

Создание службы подготовки устройств

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

Создайте экземпляр службы подготовки устройств, который будет использоваться для подготовки устройств Интернета вещей. Можно использовать приведенные ниже инструкции для Azure CLI или портал Azure: Настройка Службы подготовки устройств к добавлению в Центр Интернета вещей на портале Azure.

Приведенная ниже команда Azure CLI создает службу подготовки устройств. Необходимо указать имя службы подготовки устройств, группу ресурсов и регион. Чтобы узнать, в каких регионах поддерживается служба подготовки устройств, посетите страницу Доступность продуктов Azure по регионам. Команду можно выполнить в Cloud Shell или локально, если на компьютере установлен Azure CLI.

az iot dps create --name <Device-Provisioning-Service-name> --resource-group <resource-group-name> --location <region>

Добавление функции для использования службой подготовки устройств

В проекте приложения-функции, созданном в разделе Предварительные требования, требуется создать новую функцию для использования службой подготовки устройств. Эта функция будет использоваться службой подготовки устройств в пользовательской политике выделения для подготовки нового устройства.

Перейдите к проекту приложения-функции на компьютере и выполните приведенные ниже действия.

  1. Сначала создайте новую функцию типа HTTP-триггера в проекте приложения-функции.

  2. Добавьте новый пакет NuGet в проект Microsoft.Azure.Devices.Provisioning.Service. Также может потребоваться добавить в проект дополнительные пакеты, если в коде используются пакеты, которые еще не входят в проект.

  3. В созданный файл кода функции вставьте следующий код, назовите функцию DpsAdtAllocationFunc.cs и сохраните файл.

    // Copyright (c) Microsoft. All rights reserved.
    // Licensed under the MIT license. See LICENSE file in the project root for full license information.
    
    using System;
    using System.IO;
    using System.Net;
    using System.Net.Http;
    using System.Threading.Tasks;
    using Azure;
    using Azure.Core.Pipeline;
    using Azure.DigitalTwins.Core;
    using Azure.Identity;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.Azure.Devices.Shared;
    using Microsoft.Azure.Devices.Provisioning.Service;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    
    namespace Samples.AdtIothub
    {
        public static class DpsAdtAllocationFunc
        {
            private static string adtInstanceUrl = Environment.GetEnvironmentVariable("ADT_SERVICE_URL");
            private static readonly HttpClient singletonHttpClientInstance = new HttpClient();
    
            [FunctionName("DpsAdtAllocationFunc")]
            public static async Task<IActionResult> Run(
                [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
            {
                // Get request body
                string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
                log.LogDebug($"Request.Body: {requestBody}");
                dynamic data = JsonConvert.DeserializeObject(requestBody);
    
                // Get registration ID of the device
                string regId = data?.deviceRuntimeContext?.registrationId;
    
                bool fail = false;
                string message = "Uncaught error";
                var response = new ResponseObj();
    
                // Must have unique registration ID on DPS request
                if (regId == null)
                {
                    message = "Registration ID not provided for the device.";
                    log.LogInformation("Registration ID: NULL");
                    fail = true;
                }
                else
                {
                    string[] hubs = data?.linkedHubs.ToObject<string[]>();
    
                    // Must have hubs selected on the enrollment
                    if (hubs == null
                        || hubs.Length < 1)
                    {
                        message = "No hub group defined for the enrollment.";
                        log.LogInformation("linkedHubs: NULL");
                        fail = true;
                    }
                    else
                    {
                        // Find or create twin based on the provided registration ID and model ID
                        dynamic payloadContext = data?.deviceRuntimeContext?.payload;
                        string dtmi = payloadContext.modelId;
                        log.LogDebug($"payload.modelId: {dtmi}");
                        string dtId = await FindOrCreateTwinAsync(dtmi, regId, log);
    
                        // Get first linked hub (TODO: select one of the linked hubs based on policy)
                        response.iotHubHostName = hubs[0];
    
                        // Specify the initial tags for the device.
                        var tags = new TwinCollection();
                        tags["dtmi"] = dtmi;
                        tags["dtId"] = dtId;
    
                        // Specify the initial desired properties for the device.
                        var properties = new TwinCollection();
    
                        // Add the initial twin state to the response.
                        var twinState = new TwinState(tags, properties);
                        response.initialTwin = twinState;
                    }
                }
    
                log.LogDebug("Response: " + ((response.iotHubHostName != null)? JsonConvert.SerializeObject(response) : message));
    
                return fail
                    ? new BadRequestObjectResult(message)
                    : (ActionResult)new OkObjectResult(response);
            }
    
            public static async Task<string> FindOrCreateTwinAsync(string dtmi, string regId, ILogger log)
            {
                // Create Digital Twins client
                var cred = new DefaultAzureCredential();
                var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred);
    
                // Find existing DigitalTwin with registration ID
                try
                {
                    // Get DigitalTwin with Id 'regId'
                    BasicDigitalTwin existingDt = await client.GetDigitalTwinAsync<BasicDigitalTwin>(regId).ConfigureAwait(false);
    
                    // Check to make sure it is of the correct model type
                    if (StringComparer.OrdinalIgnoreCase.Equals(dtmi, existingDt.Metadata.ModelId))
                    {
                        log.LogInformation($"DigitalTwin {existingDt.Id} already exists");
                        return existingDt.Id;
                    }
    
                    // Found DigitalTwin but it is not of the correct model type
                    log.LogInformation($"Found DigitalTwin {existingDt.Id} but it is not of model {dtmi}");
                }
                catch(RequestFailedException ex) when (ex.Status == (int)HttpStatusCode.NotFound)
                {
                    log.LogDebug($"Did not find DigitalTwin {regId}");
                }
    
                // Either the DigitalTwin was not found, or we found it but it is of a different model type
                // Create or replace it with what it needs to be, meaning if it was not found a brand new DigitalTwin will be created
                // and if it was of a different model, it will replace that existing DigitalTwin
                // If it was intended to only create the DigitalTwin if there is no matching DigitalTwin with the same Id,
                // ETag.All could have been used as the ifNonMatch parameter to the CreateOrReplaceDigitalTwinAsync method call.
                // Read more in the CreateOrReplaceDigitalTwinAsync documentation here:
                // https://docs.microsoft.com/en-us/dotnet/api/azure.digitaltwins.core.digitaltwinsclient.createorreplacedigitaltwinasync?view=azure-dotnet
                BasicDigitalTwin dt = await client.CreateOrReplaceDigitalTwinAsync(
                    regId, 
                    new BasicDigitalTwin
                    {
                        Metadata = { ModelId = dtmi },
                        Contents = 
                        {
                            { "Temperature", 0.0 }
                        }
                    }
                ).ConfigureAwait(false);
    
                log.LogInformation($"Digital Twin {dt.Id} created.");
                return dt.Id;
            }
        }
    
        /// <summary>
        /// Expected function result format
        /// </summary>
        public class ResponseObj
        {
            public string iotHubHostName { get; set; }
            public TwinState initialTwin { get; set; }
        }
    }
    
  4. С помощью функции DpsAdtAllocationFunc.cs опубликуйте проект в приложении-функции в Azure.

    Инструкции по публикации функции с помощью Visual Studio см. в статье "Разработка Функции Azure с помощью Visual Studio". Инструкции по публикации функции с помощью Visual Studio Code см. в статье "Создание функции C# в Azure с помощью Visual Studio Code". Инструкции по публикации функции с помощью Azure CLI см. в статье "Создание функции C# в Azure из командной строки".

Важно!

При первом создании приложения-функции согласно инструкциям в разделе Предварительные требования у вас может быть уже назначена роль доступа для данной функции и настроены параметры приложения для доступа к вашему экземпляру Azure Digital Twins. Эти действия необходимо выполнить один раз для всего приложения-функции, поэтому перед продолжением убедитесь, что сделали это в своем приложении. Инструкции см. в разделе Настройка опубликованного приложения статьи Написание кода проверки подлинности приложения.

Создание регистрации подготовки устройства

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

Двигаясь по этой последовательности, убедитесь, что выбраны указанные варианты, чтобы связать регистрацию с созданной функцией.

  • Выберите способ назначения устройств центрам: выберите Custom (Use Azure Function) (Пользовательский (функция Azure)).
  • Выберите центры Интернета вещей, которым может быть назначена эта группа: выберите имя центра Интернета вещей или нажмите кнопку "Связать новый центр Интернета вещей" и выберите центр Интернета вещей из параметров.

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

  • Подписка. Подписка Azure автоматически заполнена. Убедитесь, что это правильная подписка.
  • Приложение-функция: выберите имя своего приложения-функции.
  • Функция: выбор dpsAdtAllocationFunc.

Сохраните сведения.

Screenshot of the Customs enrollment group details window in the Azure portal.

После создания регистрации выберите его, чтобы просмотреть его параметры. Скопируйте первичный ключ для регистрации, который будет использоваться далее в этой статье для настройки симулятора устройства.

Настройка симулятора устройств

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

Передача модели

Симулятор устройства — это устройство типа термостата, которое использует модель с идентификатором dtmi:contosocom:DigitalTwins:Thermostat;1. Эту модель необходимо отправить платформе Azure Digital Twins, чтобы можно было создать для устройства двойник этого типа.

Модель выглядит следующим образом:

{
    "@id": "dtmi:contosocom:DigitalTwins:Thermostat;1",
    "@type": "Interface",
    "@context": "dtmi:dtdl:context;3",
    "contents": [
      {
        "@type": "Property",
        "name": "Temperature",
        "schema": "double"
      }
    ]
  }

Чтобы передать эту модель в экземпляр двойников, выполните следующую команду Azure CLI, которая передает указанную выше модель в виде встроенного JSON. Вы можете выполнить команду в Azure Cloud Shell в браузере (использовать среду Bash) или на компьютере, если у вас установлен интерфейс командной строки локально. Существует один заполнитель для имени узла экземпляра (можно также использовать понятное имя экземпляра с небольшим снижением производительности).

az dt model create --dt-name <instance-hostname-or-name> --models '{  "@id": "dtmi:contosocom:DigitalTwins:Thermostat;1",  "@type": "Interface",  "@context": "dtmi:dtdl:context;2",  "contents": [    {      "@type": "Property",      "name": "Temperature",      "schema": "double"    }  ]}' 

Примечание.

Если вы используете что-либо, отличное от Cloud Shell в среде Bash, может потребоваться экранировать определенные символы в встроенном формате JSON, чтобы он правильно был проанализирован. Дополнительные сведения см. в разделе "Использование специальных символов в разных оболочках".

Дополнительные сведения о моделях см. в разделе Управление моделями.

Настройка и запуск симулятора

В командном окне на локальном компьютере перейдите к скачанному примеру Azure Digital Twins и Центр Интернета вещей интеграции, которую вы распаковали ранее, а затем в каталог симулятора устройств. Затем установите зависимости для проекта с помощью следующей команды:

npm install

Затем в каталоге симулятора устройства скопируйте файл env.template в новый файл с именем ENV и соберите следующие значения, чтобы заполнить параметры:

  • PROVISIONING_IDSCOPE: чтобы получить это значение, перейдите к службе подготовки устройств на портале Azure, а затем в меню настроек выберите Обзор и найдите поле Область идентификатора.

    Screenshot of the Azure portal view of the device provisioning overview page highlighting the ID Scope value.

  • PROVISIONING_REGISTRATION_ID: вы можете выбрать идентификатор регистрации для своего устройства.

  • ADT_MODEL_ID: dtmi:contosocom:DigitalTwins:Thermostat;1

  • PROVISIONING_SYMMETRIC_KEY: эта переменная среды является настроенным ранее первичным ключом для регистрации. Чтобы снова получить это значение, перейдите к службе подготовки устройств на портале Azure, выберите Управление регистрациями, затем выберите созданную ранее группу регистрации и скопируйте первичный ключ.

    Screenshot of the Azure portal view of the device provisioning service manage enrollments page highlighting the SAS primary key value.

Теперь используйте приведенные выше значения для обновления параметров env-файла .

PROVISIONING_HOST = "global.azure-devices-provisioning.net"
PROVISIONING_IDSCOPE = "<Device-Provisioning-Service-Scope-ID>"
PROVISIONING_REGISTRATION_ID = "<Device-Registration-ID>"
ADT_MODEL_ID = "dtmi:contosocom:DigitalTwins:Thermostat;1"
PROVISIONING_SYMMETRIC_KEY = "<Device-Provisioning-Service-enrollment-primary-SAS-key>"

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

Начало работы симулятора устройства

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

node .\adt_custom_register.js

Вы должны увидеть, как устройство регистрируется и подключается к Центру Интернета вещей, а затем начинает отправлять сообщения. Screenshot of the Command window showing device registration and sending messages.

Проверить

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

az dt twin show --dt-name <instance-hostname-or-name> --twin-id "<device-registration-ID>"

Вы должны увидеть двойник устройства, найденный в экземпляре Azure Digital Twins. Screenshot of the Command window showing newly created twin.

Автоматическое повторение устройства с помощью событий жизненного цикла Центр Интернета вещей

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

Diagram of the Retire device flow—an excerpt of the solution architecture diagram, following data from a device deletion into Azure Digital Twins.

Вот описание процесса:

  1. Внешний или ручной процесс инициирует удаление устройства в Центре Интернета вещей.
  2. Центр Интернета вещей удаляет устройство и создает событие жизненного цикла устройства, которое будет направлено в концентратор событий.
  3. Для удаления двойника устройства в Azure Digital Twins используется функция Azure.

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

Создание концентратора событий

Далее потребуется создать концентратор событий Azure для получения событий жизненного цикла центра Интернета вещей.

Выполните действия, описанные в кратком руководстве Создание концентратора событий. Присвойте концентратору событий имя lifecycleevents. Это имя концентратора событий будет использоваться при настройке маршрута центра Интернета вещей и функции Azure в последующих разделах.

Следующий снимок экрана иллюстрирует создание концентратора событий: Screenshot of the Azure portal window showing how to create an event hub with the name lifecycleevents.

Создание политики SAS для концентратора событий

Далее необходимо создать политику подписанных URL-адресов (SAS) для настройки концентратора событий с помощью приложения-функции. Чтобы создать политику SAS:

  1. Перейдите к концентратору событий, который вы создали на портале Azure, и в меню настроек слева выберите Политики общего доступа.
  2. Выберите Добавить. В открывшемся окне Добавление политики SAS введите имя выбранной политики и установите флажок Listen (Слушать).
  3. Выберите Создать.

Screenshot of the Azure portal showing how to add an event hub SAS policy.

Настройка концентратора событий с помощью приложения-функции

Затем настройте приложение-функцию Azure, заданную в разделе Предварительные требования, для работы с новым концентратором событий. Это можно сделать, задав в приложении-функции переменную среды с помощью строки подключения концентратора событий.

  1. Откройте созданную политику и скопируйте значение параметра Строка подключения — первичный ключ.

    Screenshot of the Azure portal showing how to copy the connection string-primary key.

  2. Добавьте строку подключения в качестве переменной к параметрам приложения-функции с помощью следующей команды Azure CLI. Команду можно выполнить в Cloud Shell или локально, если на компьютере установлен Azure CLI.

    az functionapp config appsettings set --settings "EVENTHUB_CONNECTIONSTRING=<Event-Hubs-SAS-connection-string-Listen>" --resource-group <resource-group> --name <your-function-app-name>
    

Добавление функции для прекращения использования с помощью событий жизненного цикла Центра Интернета вещей

В проекте приложения-функции, созданном в разделе Предварительные требования, требуется создать функцию для снятия с учета существующего устройства с помощью событий жизненного цикла Центра Интернета вещей.

Дополнительные сведения о событиях жизненного цикла см. в статье о не связанных с телеметрией событиях Центра Интернета вещей. Дополнительные сведения об использовании концентраторов событий с помощью функций Azure см. в статье Триггер концентраторов событий Azure для функций Azure.

Перейдите к проекту приложения-функции на компьютере и выполните приведенные ниже действия.

  1. Сначала создайте новую функцию триггера концентратора событий в проекте приложения-функции.

  2. Добавьте новый пакет NuGet в проект Microsoft.Azure.Devices.Provisioning.Service. Также может потребоваться добавить в проект дополнительные пакеты, если в коде используются пакеты, которые еще не входят в проект.

  3. В созданном файле кода функции вставьте следующий код, назовите функцию DeleteDeviceInTwinFunc.cs и сохраните файл.

    // Copyright (c) Microsoft. All rights reserved.
    // Licensed under the MIT license. See LICENSE file in the project root for full license information.
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Threading.Tasks;
    using Azure;
    using Azure.Core.Pipeline;
    using Azure.DigitalTwins.Core;
    using Azure.Identity;
    using Microsoft.Azure.EventHubs;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Extensions.Logging;
    
    namespace Samples.AdtIothub
    {
        public static class DeleteDeviceInTwinFunc
        {
            private static string adtAppId = "https://digitaltwins.azure.net";
            private static readonly string adtInstanceUrl = Environment.GetEnvironmentVariable("ADT_SERVICE_URL", EnvironmentVariableTarget.Process);
            private static readonly HttpClient singletonHttpClientInstance = new HttpClient();
    
            [FunctionName("DeleteDeviceInTwinFunc")]
            public static async Task Run(
                [EventHubTrigger("lifecycleevents", Connection = "EVENTHUB_CONNECTIONSTRING")] EventData[] events, ILogger log)
            {
                var exceptions = new List<Exception>(events.Length);
    
                // Create Digital Twin client
                var cred = new ManagedIdentityCredential(adtAppId);
                var client = new DigitalTwinsClient(
                    new Uri(adtInstanceUrl),
                    cred,
                    new DigitalTwinsClientOptions
                    {
                        Transport = new HttpClientTransport(singletonHttpClientInstance)
                    });
    
                foreach (EventData eventData in events)
                {
                    try
                    {
                        //log.LogDebug($"EventData: {System.Text.Json.JsonSerializer.Serialize(eventData)}");
    
                        string opType = eventData.Properties["opType"] as string;
                        if (opType == "deleteDeviceIdentity")
                        {
                            string deviceId = eventData.Properties["deviceId"] as string;
    
                            try
                            {
                                // Find twin based on the original Registration ID
                                BasicDigitalTwin digitalTwin = await client.GetDigitalTwinAsync<BasicDigitalTwin>(deviceId);
    
                                // In order to delete the twin, all relationships must first be removed
                                await DeleteAllRelationshipsAsync(client, digitalTwin.Id, log);
    
                                // Delete the twin
                                await client.DeleteDigitalTwinAsync(digitalTwin.Id, digitalTwin.ETag);
                                log.LogInformation($"Twin {digitalTwin.Id} deleted in DT");
                            }
                            catch (RequestFailedException e) when (e.Status == (int)HttpStatusCode.NotFound)
                            {
                                log.LogWarning($"Twin {deviceId} not found in DT");
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        // We need to keep processing the rest of the batch - capture this exception and continue.
                        exceptions.Add(e);
                    }
                }
    
                if (exceptions.Count > 1)
                    throw new AggregateException(exceptions);
    
                if (exceptions.Count == 1)
                    throw exceptions.Single();
            }
    
            /// <summary>
            /// Deletes all outgoing and incoming relationships from a specified digital twin
            /// </summary>
            public static async Task DeleteAllRelationshipsAsync(DigitalTwinsClient client, string dtId, ILogger log)
            {
                AsyncPageable<BasicRelationship> relationships = client.GetRelationshipsAsync<BasicRelationship>(dtId);
                await foreach (BasicRelationship relationship in relationships)
                {
                    await client.DeleteRelationshipAsync(dtId, relationship.Id, relationship.ETag);
                    log.LogInformation($"Twin {dtId} relationship {relationship.Id} deleted in DT");
                }
    
                AsyncPageable<IncomingRelationship> incomingRelationships = client.GetIncomingRelationshipsAsync(dtId);
                await foreach (IncomingRelationship incomingRelationship in incomingRelationships)
                {
                    await client.DeleteRelationshipAsync(incomingRelationship.SourceId, incomingRelationship.RelationshipId);
                    log.LogInformation($"Twin {dtId} incoming relationship {incomingRelationship.RelationshipId} from {incomingRelationship.SourceId} deleted in DT");
                }
            }
        }
    }
    
  4. С помощью функции DeleteDeviceInTwinFunc.cs опубликуйте проект в приложении-функции в Azure.

    Инструкции по публикации функции с помощью Visual Studio см. в статье "Разработка Функции Azure с помощью Visual Studio". Инструкции по публикации функции с помощью Visual Studio Code см. в статье "Создание функции C# в Azure с помощью Visual Studio Code". Инструкции по публикации функции с помощью Azure CLI см. в статье "Создание функции C# в Azure из командной строки".

Важно!

При первом создании приложения-функции согласно инструкциям в разделе Предварительные требования у вас может быть уже назначена роль доступа для данной функции и настроены параметры приложения для доступа к вашему экземпляру Azure Digital Twins. Эти действия необходимо выполнить один раз для всего приложения-функции, поэтому перед продолжением убедитесь, что сделали это в своем приложении. Инструкции см. в разделе Настройка опубликованного приложения статьи Написание кода проверки подлинности приложения.

Создание маршрута Центра Интернета вещей для событий жизненного цикла

Теперь требуется настроить маршрут Центра Интернета вещей для маршрутизации событий жизненного цикла устройства. В этом случае вы будете отдельно прослушивать события удаления устройства, идентифицируемые с помощью выражения if (opType == "deleteDeviceIdentity"). Это событие инициирует удаление элемента цифрового двойника с прекращением использования устройства и его цифрового двойника.

Сначала необходимо создать конечную точку концентратора событий в Центре Интернета вещей. Затем необходимо добавить маршрут в Центр Интернета вещей для отправки событий жизненного цикла этой конечной точке концентратора событий. Чтобы создать конечную точку концентратора событий, выполните указанные ниже действия.

  1. На портале Azure перейдите к Центру Интернета вещей, созданному в разделе Предварительные требования, и в меню настроек слева выберите Маршрутизация сообщений.

  2. Выберите вкладку Пользовательские конечные точки.

  3. Нажмите кнопку +Добавить и выберите центры событий, чтобы добавить конечную точку типа Центров событий.

    Screenshot of the Azure portal showing how to add an Event Hubs custom endpoint.

  4. В открывающемся окне Добавление конечной точки концентратора событий выберите следующие значения.

    • Имя конечной точки: выберите имя конечной точки.
    • Пространство имен концентратора событий: в раскрывающемся списке выберите пространство имен концентратора событий.
    • Экземпляр концентратора событий: выберите имя концентратора событий, созданного на предыдущем шаге.
  5. Выберите Создать. Не закрывайте это окно, чтобы добавить маршрут на следующем шаге.

    Screenshot of the Azure portal showing how to add an event hub endpoint.

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

  1. Перейдите на вкладку Маршруты и выберите Добавить, чтобы добавить маршрут.

    Screenshot of the Azure portal showing how to add a route to send events.

  2. На открывшейся странице Добавление маршрута выберите следующие значения.

    • Имя: выберите имя маршрута.
    • Конечная точка: выберите конечную точку Центров событий, созданную ранее в раскрывающемся списке.
    • Источник данных: выберите События жизненного цикла устройства.
    • Маршрутный запрос: введите opType='deleteDeviceIdentity'. Этот запрос ограничивает события жизненного цикла устройства лишь отправкой событий удаления.
  3. Выберите Сохранить.

    Screenshot of the Azure portal showing how to add a route to send lifecycle events.

После выполнения этой последовательности будет полностью настроено прекращение использования устройств.

Проверить

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

Вы можете вручную удалить устройство из центра Интернета вещей с помощью команды Azure CLI или на портале Microsoft Azure. Чтобы удалить устройство на портале Azure, выполните следующие действия.

  1. Перейдите в Центр Интернета вещей и в меню настроек слева выберите Устройства Интернета вещей.
  2. Вы увидите устройство с идентификатором регистрации, выбранным в первой половине этой статьи. Можно выбрать для удаления любое другое устройство, если оно содержит двойник в Azure Digital Twins, чтобы можно было проверить автоматическое удаление двойника после удаления устройства.
  3. Выделите устройство и выберите Удалить.

Screenshot of the Azure portal showing how to delete device twin from the IoT devices.

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

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

az dt twin show --dt-name <instance-hostname-or-name> --twin-id "<device-registration-ID>"

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

Screenshot of the Command window showing that the twin can't be found anymore.

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

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

В Azure Cloud Shell или локальном интерфейсе Azure CLI можно удалить все ресурсы Azure в группе ресурсов с помощью команды az group delete. Эта команда удаляет группу ресурсов; экземпляр Azure Digital Twins; Центр Интернета вещей и регистрация центрального устройства; раздел "Сетка событий" и связанные подписки; пространство имен Центров событий и оба приложения Функции Azure, включая связанные ресурсы, такие как хранилище.

Важно!

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

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

Затем удалите с локального компьютера скачанную папку примера проекта.

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

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

Дополнительные сведения об использовании HTTP-запросов с помощью функций Azure

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