Share via


Automatisches Verwalten von Geräten in Azure Digital Twins mithilfe des Device Provisioning Service (DPS)

In diesem Artikel erfahren Sie, wie Sie Azure Digital Twins in den Device Provisioning Service (DPS) integrieren.

Mithilfe der in diesem Artikel beschriebenen Lösung können Sie den Prozess zum Bereitstellen und Außerbetriebnehmen von IoT Hub-Geräten in Azure Digital Twins mithilfe des Device Provisioning Service automatisieren.

Weitere Informationen zu den Bereitstellungs- und Einstellungsphasen und zum besseren Verständnis der allgemeinen Geräteverwaltungsphasen, die allen IoT-Projekten des Unternehmens gemeinsam sind, finden Sie im Abschnitt "Gerätelebenszyklus" der Geräteverwaltungsdokumentation von IoT Hub.

Voraussetzungen

Bevor Sie die Bereitstellung einrichten können, müssen Sie die folgenden Ressourcen einrichten:

  • Eine Azure Digital Twins-Instanz. Befolgen Sie zum Erstellen einer Azure Digital Twins-Instanz die Anweisungen unter Einrichten einer Instanz und der Authentifizierung. Erfassen Sie den Hostnamen der Instanz im Azure-Portal (Anweisungen).
  • Einen IoT Hub. Anweisungen finden Sie im Abschnitt „Erstellen eines IoT-Hubs“ des IoT Hub-Schnellstarts.
  • Eine Azure-Funktion, mit der Digital Twins-Informationen auf Grundlage von IoT-Hub-Daten aktualisiert werden. Befolgen Sie zum Erstellen dieser Azure-Funktion die Anweisungen in Erfassen von IoT-Hub-Daten. Erfassen Sie den Namen der Funktion, um ihn in diesem Artikel zu verwenden.

In diesem Beispiel wird auch ein Gerätesimulator verwendet, der die Bereitstellung mithilfe des Device Provisioning Service umfasst. Der Gerätesimulator befindet sich hier: Azure Digital Twins und IoT Hub Integration Sample. Rufen Sie das Beispielprojekt auf Ihrem Computer ab, indem Sie zum GitHub-Repository für das Beispiel navigieren, das Sie als ZIP-Datei herunterladen können, indem Sie die Schaltfläche "Code " und "ZIP herunterladen" auswählen.

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

Extrahieren Sie den heruntergeladenen Ordner.

Auf Ihrem Computer muss Node.js installiert sein. Der Gerätesimulator basiert auf Node.js-Version 10.0. x oder höher.

Lösungsarchitektur

Diese Lösung umfasst Schritte zum Bereitstellen und Außerbetriebnehmen eines Geräts in Azure Digital Twins unter Verwendung des Device Provisioning Service.

Um Geräte in der Lösung zuzuordnen, werden Daten zwischen einem Thermostatgerät und dem DPS übertragen. Die Daten fließen dann vom DPS in IoT Hub und über eine Azure-Funktion zu Azure Digital Twins.

Um ein Gerät außer Betrieb zu setzen, werden Daten aus einem manuellen Löschen von Geräten über IoT Hub, Event Hubs und eine Azure-Funktion in Azure Digital Twins übertragen.

Die folgende Abbildung veranschaulicht diese Architektur.

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

Dieser Artikel ist in zwei Abschnitte unterteilt, die sich jeweils auf einen Teil dieser vollständigen Architektur konzentrieren:

Automatisches Bereitstellen eines Geräts mithilfe des Device Provisioning Service

In diesem Abschnitt fügen Sie den Device Provisioning Service an Azure Digital Twins an, um Geräte automatisch über den unten beschriebenen Pfad bereitzustellen. Dieses Diagramm ist ein Auszug aus der oben dargestellten vollständigen Architektur.

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

Beschreibung des Prozessflusses:

  1. Das Gerät kontaktiert den DPS-Endpunkt und übergibt Informationen, um seine Identität zu bestätigen.
  2. DPS überprüft die Geräteidentität, indem die Registrierungs-ID und der Schlüssel anhand der Registrierungsliste überprüft werden, und ruft eine Azure-Funktion auf, um die Zuordnung durchzuführen.
  3. Die Azure-Funktion erstellt in Azure Digital Twins einen neuen Zwilling für das Gerät. Der Zwilling erhält denselben Namen wie die Registrierungs-ID des Geräts.
  4. DPS registriert das Gerät bei einem IoT-Hub und gibt den gewählten Zwillingsstatus des Geräts an.
  5. Der IoT-Hub gibt Informationen zur Geräte-ID und zur IoT-Hub-Verbindung an das Gerät zurück. Das Gerät kann nun eine Verbindung mit dem IoT-Hub herstellen.

In den folgenden Abschnitten werden die Schritte zum Einrichten dieses Ablaufs für die automatische Bereitstellung von Geräten erläutert.

Erstellen einer Device Provisioning Service-Instanz

Wenn ein neues Gerät mit dem Device Provisioning Service bereitgestellt wird, kann in Azure Digital Twins ein neuer Zwilling für dieses Gerät erstellt werden, dessen Name mit der Registrierungs-ID identisch ist.

Erstellen Sie eine Instanz des Device Provisioning Service, die zum Bereitstellen von IoT-Geräten verwendet wird. Sie können entweder die folgenden Anweisungen für die Azure-Befehlszeilenschnittstelle anwenden oder das Azure-Portal wie unter Einrichten des IoT Hub Device Provisioning Service über das Azure-Portal beschrieben verwenden.

Mit dem folgenden Azure CLI Befehl wird ein Device Provisioning Service erstellt. Sie müssen einen Namen, eine Ressourcengruppe und eine Region für den Device Provisioning Service angeben. Informationen zu Regionen mit Unterstützung des Device Provisioning Service finden Sie unter Verfügbare Produkte nach Region. Der Befehl kann in Cloud Shell oder lokal ausgeführt werden, wenn die Azure CLI auf dem Computer installiert ist.

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

Hinzufügen einer mit dem Device Provisioning Service zu verwendenden Funktion

Sie erstellen in der Funktions-App, die Sie im Abschnitt Voraussetzungen erstellt haben, eine neue Funktion für die Verwendung mit dem Device Provisioning Service. Diese Funktion wird vom Device Provisioning Service in einer benutzerdefinierten Zuweisungsrichtlinie zur Bereitstellung eines neuen Geräts verwendet.

Navigieren Sie auf dem Computer zum Funktions-App-Projekt, und führen Sie die folgenden Schritte aus.

  1. Erstellen Sie zuerst im Funktions-App-Projekt eine neue Funktion vom Typ HTTP-Trigger.

  2. Fügen Sie dem Projekt ein neues NuGet-Paket hinzu: Microsoft.Azure.Devices.Provisioning.Service. Möglicherweise müssen Sie dem Projekt weitere Pakete hinzufügen, wenn die im Code verwendeten Pakete nicht bereits Teil des Projekts sind.

  3. Fügen Sie in der neu erstellten Funktionscodedatei den folgenden Code ein, nennen Sie die Funktion DpsAdtAllocationFunc.cs, und speichern Sie die Datei.

    // 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. Veröffentlichen Sie das Projekt mit der Funktion DpsAdtAllocationFunc.cs in einer Funktions-App in Azure.

    Anweisungen zum Veröffentlichen der Funktion mithilfe von Visual Studio finden Sie unter Entwickeln von Azure Functions mithilfe von Visual Studio. Anweisungen zum Veröffentlichen der Funktion mithilfe von Visual Studio Code finden Sie unter Erstellen einer C#-Funktion in Azure mit Visual Studio Code. Anweisungen zum Veröffentlichen der Funktion mithilfe der Azure CLI finden Sie unter Erstellen einer C#-Funktion über die Befehlszeile in Azure.

Wichtig

Beim erstmaligen Erstellen der Funktions-App im Abschnitt Voraussetzungen haben Sie möglicherweise bereits eine Zugriffsrolle für die Funktion zugewiesen und die Anwendungseinstellungen für den Zugriff der App auf die Azure Digital Twins-Instanz konfiguriert. Diese Schritte müssen für die gesamte Funktions-App einmal ausgeführt werden. Vergewissern Sie sich daher, dass sie in der App durchgeführt wurden, bevor Sie fortfahren. Anweisungen finden Sie im Abschnitt Konfigurieren der veröffentlichten App des Artikels Schreiben von App-Authentifizierungscode.

Erstellen der Registrierung für den Device Provisioning Service

Als Nächstes müssen Sie eine Registrierung im Device Provisioning Service mithilfe einer benutzerdefinierten Zuweisungsfunktion erstellen. Befolgen Sie zum Erstellen einer Registrierung die Anweisungen im Abschnitt Erstellen der Registrierung des Artikels über benutzerdefinierte Zuordnungsrichtlinien in der Dokumentation zum Device Provisioning Service.

Achten Sie darauf, dass Sie beim Durchführen dieser Schritte die folgenden Optionen auswählen, um die Registrierung mit der Funktion zu verknüpfen, die Sie erstellt haben.

  • Wählen Sie, wie Geräte den Hubs zugewiesen werden sollen: Benutzerdefiniert (Azure-Funktion verwenden).
  • Wählen Sie die IoT-Hubs aus, denen diese Gruppe zugewiesen werden kann: Wählen Sie Ihren IoT-Hubnamen aus, oder wählen Sie die Schaltfläche "Link a new IoT hub " aus, und wählen Sie Ihren IoT-Hub aus den Optionen aus.

Klicken Sie als Nächstes auf die Schaltfläche Neue Funktion auswählen, um die Funktions-App mit der Registrierungsgruppe zu verknüpfen. Geben Sie anschließend die folgenden Werte ein:

  • Abonnement: Ihr Azure-Abonnement wird automatisch ausgefüllt. Stellen Sie sicher, dass es das richtige Abonnement ist.
  • Funktions-App: Wählen Sie den Namen Ihrer Funktions-App aus.
  • Funktion: Wählen Sie DpsAdtAllocationFunc aus.

Speichern Sie die Informationen.

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

Nachdem Sie die Registrierung erstellt haben, wählen Sie sie aus, um die zugehörigen Einstellungen anzuzeigen. Kopieren Sie den Primärschlüssel für die Registrierung, der später in diesem Artikel zum Konfigurieren des Gerätesimulators verwendet wird.

Einrichten des Gerätesimulators

In diesem Beispiel wird ein Gerätesimulator verwendet, der die Bereitstellung mithilfe des Device Provisioning Service umfasst. Der Gerätesimulator befindet sich im Integrationsbeispiel für Azure Digital Twins und IoT Hub, das Sie im Abschnitt Voraussetzungen heruntergeladen haben.

Hochladen des Modells

Der Gerätesimulator ist ein Gerät vom Typ „Thermostat“, von dem das Modell mit der folgenden ID verwendet wird: dtmi:contosocom:DigitalTwins:Thermostat;1. Sie müssen dieses Modell in Azure Digital Twins hochladen, bevor Sie einen Zwilling dieses Typs für das Gerät erstellen können.

Das Modell sieht so aus:

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

Führen Sie den folgenden Azure CLI-Befehl aus, der das obige Modell als Inline-JSON hochlädt, um dieses Modell in Ihre Twins-Instanz hochzuladen. Sie können den Befehl in Azure Cloud Shell in Ihrem Browser (verwenden Sie die Bash-Umgebung) oder auf Ihrem Computer ausführen, wenn die CLI lokal installiert ist. Es gibt einen Platzhalter für den Hostnamen der Instanz (Sie können auch den Anzeigenamen der Instanz mit einer leichten Verringerung der Leistung verwenden).

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"    }  ]}' 

Hinweis

Wenn Sie etwas anderes als die Cloud Shell in der Bash-Umgebung verwenden, müssen Sie möglicherweise bestimmte Zeichen im JSON-Inlinecode mit Escapezeichen versehen, damit sie ordnungsgemäß analysiert werden. Weitere Informationen finden Sie unter Verwenden von Sonderzeichen in verschiedenen Shells.

Weitere Informationen zu Modellen finden Sie unter Verwalten von Modellen.

Konfigurieren und Ausführen des Simulators

Navigieren Sie in einem Befehlsfenster auf Ihrem lokalen Computer zu dem heruntergeladenen Azure Digital Twins- und IoT Hub-Integration , die Sie zuvor entzippt haben, und wechseln Sie dann in das Gerätesimulatorverzeichnis . Installieren Sie dann die Abhängigkeiten für das Projekt, indem Sie den folgenden Befehl ausführen:

npm install

Kopieren Sie als Nächstes in Ihrem Gerätesimulatorverzeichnis die Datei mit der Erweiterung .env.template in eine neue Datei mit der Erweiterung .env, und erfassen Sie die folgenden Werte zum Festlegen der Einstellungen:

  • PROVISIONING_IDSCOPE: Um diesen Wert zu erhalten, navigieren Sie im Azure-Portal zum Device Provisioning Service, wählen Sie in den Menüoptionen Übersicht aus, und suchen Sie das Feld ID-Bereich.

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

  • PROVISIONING_REGISTRATION_ID: Sie können eine Registrierungs-ID für Ihr Gerät auswählen.

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

  • PROVISIONING_SYMMETRIC_KEY: Diese Umgebungsvariable ist der Primärschlüssel für die Registrierung, die Sie zuvor eingerichtet haben. Um diesen Wert erneut zu erhalten, navigieren Sie im Azure-Portal zum Device Provisioning Service, wählen Sie Registrierungen verwalten aus, wählen Sie dann die zuvor erstellte Registrierungsgruppe aus, und kopieren Sie den Primärschlüssel.

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

Verwenden Sie nun die oben aufgeführten Werte, um die Einstellungen für die ENV-Datei zu aktualisieren.

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

Speichern und schließen Sie die Datei.

Ausführen des Gerätesimulators

Starten Sie im Verzeichnis device-simulator den Gerätesimulator mit dem folgenden Befehl:

node .\adt_custom_register.js

Sie sollten sehen, dass das Gerät registriert und mit IoT Hub verbunden ist und Nachrichten sendet. Screenshot of the Command window showing device registration and sending messages.

Überprüfen

Der Flow, den Sie in diesem Artikel eingerichtet haben, führt dazu, dass das Gerät automatisch in Azure Digital Twins registriert wird. Suchen Sie mit dem folgenden Azure Digital Twins-CLI-Befehl den Zwilling des Geräts in der von Ihnen erstellten Azure Digital Twins-Instanz. Es gibt einen Platzhalter für den Hostnamen der Instanz (Sie können auch den Anzeigenamen der Instanz mit einer leichten Verringerung der Leistung verwenden) sowie einen Platzhalter für die Geräteregistrierungs-ID.

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

Sie sollten den Zwilling des Geräts in der Azure Digital Twins-Instanz sehen. Screenshot of the Command window showing newly created twin.

Automatisches Außerbetriebnehmen von Geräten mithilfe von IoT Hub-Lebenszyklusereignissen

In diesem Abschnitt fügen Sie IoT Hub-Lebenszyklusereignisse an Azure Digital Twins an, um Geräte automatisch über den folgenden Ablauf außer Betrieb zu nehmen. Dieses Diagramm ist ein Auszug aus der oben dargestellten vollständigen Architektur.

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

Beschreibung des Prozessflusses:

  1. Ein externer oder manueller Prozess löst das Löschen eines Geräts in IoT Hub aus.
  2. IoT Hub löscht das Gerät und generiert ein Gerätelebenszyklusereignis, das an einen Event Hub weitergeleitet wird.
  3. Eine Azure-Funktion löscht den Zwilling des Geräts in Azure Digital Twins.

In den folgenden Abschnitten werden die Schritte zum Einrichten dieses Ablaufs für die automatische Außerbetriebnahme von Geräten erläutert.

Erstellen eines Ereignis-Hubs

Als Nächstes erstellen Sie einen Azure Event Hub zum Empfangen von IoT Hub-Lebenszyklusereignissen.

Führen Sie die in der Schnellstartanleitung zum Erstellen eines Event Hubs beschriebenen Schritte aus. Benennen Sie den Event Hub mit lifecycleevents. Sie verwenden diesen Event Hub-Namen, wenn Sie in den nächsten Abschnitten eine IoT Hub-Route und eine Azure-Funktion einrichten.

Der folgende Screenshot veranschaulicht die Erstellung des Event Hubs. Screenshot of the Azure portal window showing how to create an event hub with the name lifecycleevents.

Erstellen einer SAS-Richtlinie für den Event Hub

Als Nächstes müssen Sie eine SAS-Richtlinie (Shared Access Signature) erstellen, um den Event Hub mit Ihrer Funktions-App zu konfigurieren. So erstellen Sie die SAS-Richtlinie

  1. Navigieren Sie zu dem Event Hub, die Sie im Azure-Portal erstellt haben, und wählen Sie in den Menüoptionen auf der linken Seite die Option Freigegebene Zugriffsrichtlinien aus.
  2. Klicken Sie auf Hinzufügen. Geben Sie im daraufhin geöffneten Fenster SAS-Richtlinie hinzufügen einen Richtliniennamen Ihrer Wahl ein, und aktivieren Sie das Kontrollkästchen Lauschen.
  3. Wählen Sie Erstellen aus.

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

Konfigurieren des Event Hubs mit der Funktions-App

Konfigurieren Sie als Nächstes die Azure-Funktions-App, die Sie im Abschnitt Voraussetzungen eingerichtet haben, für die Verwendung mit dem neuen Event Hub. Sie konfigurieren die Funktion, indem Sie in der Funktions-App mit der Verbindungszeichenfolge des Event Hubs eine Umgebungsvariable festlegen.

  1. Öffnen Sie die erstellte Richtlinie, und kopieren Sie den Wert von Verbindungszeichenfolge – Primärschlüssel.

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

  2. Fügen Sie mit dem folgenden Azure CLI-Befehl die Verbindungszeichenfolge als Variable in den Funktions-App-Einstellungen hinzu. Der Befehl kann in Cloud Shell oder lokal ausgeführt werden, wenn die Azure CLI auf dem Computer installiert ist.

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

Hinzufügen einer Funktion zur Außerbetriebnahme mit IoT Hub-Lebenszyklusereignissen

Sie erstellen in dem Funktions-App-Projekt, das Sie im Abschnitt Voraussetzungen erstellt haben, eine neue Funktion, um ein vorhandenes Gerät mithilfe von IoT Hub-Lebenszyklusereignissen außer Betrieb zu nehmen.

Weitere Informationen zu Lebenszyklusereignissen finden Sie unter Nicht telemetriebezogene Ereignisse in IoT Hub. Weitere Informationen zur Verwendung von Event Hubs mit Azure-Funktionen finden Sie unter Azure Event Hubs-Trigger für Azure Functions.

Navigieren Sie auf dem Computer zum Funktions-App-Projekt, und führen Sie die folgenden Schritte aus.

  1. Erstellen Sie zuerst im Funktions-App-Projekt eine neue Funktion vom Typ Event Hub-Trigger.

  2. Fügen Sie dem Projekt ein neues NuGet-Paket hinzu: Microsoft.Azure.Devices.Provisioning.Service. Möglicherweise müssen Sie dem Projekt weitere Pakete hinzufügen, wenn die im Code verwendeten Pakete nicht bereits Teil des Projekts sind.

  3. Fügen Sie in der neu erstellten Funktionscodedatei den folgenden Code ein, nennen Sie die Funktion DeleteDeviceInTwinFunc.cs, und speichern Sie die Datei.

    // 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. Veröffentlichen Sie das Projekt mit der Funktion DeleteDeviceInTwinFunc.cs in einer Funktions-App in Azure.

    Anweisungen zum Veröffentlichen der Funktion mithilfe von Visual Studio finden Sie unter Entwickeln von Azure Functions mithilfe von Visual Studio. Anweisungen zum Veröffentlichen der Funktion mithilfe von Visual Studio Code finden Sie unter Erstellen einer C#-Funktion in Azure mit Visual Studio Code. Anweisungen zum Veröffentlichen der Funktion mithilfe der Azure CLI finden Sie unter Erstellen einer C#-Funktion über die Befehlszeile in Azure.

Wichtig

Beim erstmaligen Erstellen der Funktions-App im Abschnitt Voraussetzungen haben Sie möglicherweise bereits eine Zugriffsrolle für die Funktion zugewiesen und die Anwendungseinstellungen für den Zugriff der App auf die Azure Digital Twins-Instanz konfiguriert. Diese Schritte müssen für die gesamte Funktions-App einmal ausgeführt werden. Vergewissern Sie sich daher, dass sie in der App durchgeführt wurden, bevor Sie fortfahren. Anweisungen finden Sie im Abschnitt Konfigurieren der veröffentlichten App des Artikels Schreiben von App-Authentifizierungscode.

Erstellen einer IoT Hub-Route für Lebenszyklusereignisse

Jetzt richten Sie eine IoT Hub-Route ein, um Lebenszyklusereignisse für das Gerät weiterzuleiten. In diesem Fall lauschen Sie speziell auf Ereignisse, bei denen ein Gerät gelöscht wird. Diese sind durch if (opType == "deleteDeviceIdentity") gekennzeichnet. Dieses Ereignis wird das Löschen des Elements für den digitalen Zwilling und den Außerbetriebnahmeprozess eines Geräts und des zugehörigen digitalen Zwillings auslösen.

Zunächst müssen Sie im IoT-Hub einen Event Hub-Endpunkt erstellen. Anschließend fügen Sie im IoT-Hub eine Route hinzu, um Lebenszyklusereignisse an diesen Event Hub-Endpunkt zu senden. Führen Sie die folgenden Schritte aus, um einen Event Hub-Endpunkt zu erstellen:

  1. Navigieren Sie im Azure-Portalzu dem IoT-Hub, den Sie im Abschnitt Voraussetzungen erstellt haben, und wählen Sie in den Menüoptionen auf der linken Seite Nachrichtenrouting aus.

  2. Wählen Sie die Registerkarte Benutzerdefinierte Endpunkte.

  3. Wählen Sie + Hinzufügen und dann Event Hubs aus, um einen Endpunkt vom Typ „Event Hubs“ hinzuzufügen.

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

  4. Wählen Sie im daraufhin geöffneten Fenster Event Hub-Endpunkt hinzufügen die folgenden Werte aus:

    • Endpunktname: Wählen Sie einen Endpunktnamen aus.
    • Event Hub-Namespace: Wählen Sie in der Dropdownliste den Event Hub-Namespace aus.
    • Event Hub-Instanz: Wählen Sie den Event Hub-Namen aus, den Sie im vorherigen Schritt erstellt haben.
  5. Wählen Sie Erstellen aus. Lassen Sie dieses Fenster geöffnet, um im nächsten Schritt eine Route hinzuzufügen.

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

Als Nächstes fügen Sie eine Route hinzu, die eine Verbindung mit dem im obigen Schritt erstellten Endpunkt herstellt, mit einer Routingabfrage, die die Löschereignisse sendet. Führen Sie zum Erstellen einer Route die folgenden Schritte aus:

  1. Navigieren Sie zur Registerkarte Routen, und wählen Sie Hinzufügen aus, um eine Route hinzuzufügen.

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

  2. Wählen Sie auf der daraufhin geöffneten Seite Route hinzufügen die folgenden Werte aus:

    • Name: Wählen Sie einen Namen für die Route aus.
    • Endpunkt: Wählen Sie in der Dropdownliste den Event Hubs-Endpunkt aus, den Sie zuvor erstellt haben.
    • Datenquelle: Wählen Sie Ereignisse im Gerätelebenszyklus aus.
    • Routingabfrage: Geben Sie opType='deleteDeviceIdentity' ein. Diese Abfrage schränkt das Senden der Gerätelebenszklusereignisse auf Löschereignisse ein.
  3. Wählen Sie Speichern aus.

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

Wenn Sie diese Schritte durchlaufen haben, ist alles für die End-to-End-Außerbetriebnahme der Geräte vorbereitet.

Überprüfen

Um die Außerbetriebnahme auszulösen, müssen Sie das Gerät manuell aus IoT Hub löschen.

Sie können das Gerät mit einem Azure CLI-Befehl oder im Azure-Portal manuell aus IoT Hub löschen. Führen Sie die folgenden Schritte aus, um das Gerät im Azure Portal zu löschen:

  1. Navigieren Sie zum IoT-Hub, und wählen Sie in den Menüoptionen auf der linken Seite IoT-Geräte aus.
  2. Es wird ein Gerät mit der Geräteregistrierungs-ID angezeigt, die Sie in der ersten Hälfte dieses Artikels ausgewählt haben. Sie können auch ein beliebiges anderes Gerät zum Löschen auswählen, solange es über einen Zwilling in Azure Digital Twins verfügt, damit Sie überprüfen können, ob der Zwilling nach dem Löschen des Geräts automatisch gelöscht wird.
  3. Wählen Sie das Gerät aus, und klicken Sie auf Löschen.

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

Es kann einige Minuten dauern, bis die Änderungen in Azure Digital Twins angezeigt werden.

Mit dem folgenden Azure Digital Twins CLI-Befehl können Sie überprüfen, ob der Zwilling des Geräts in der Azure Digital Twins-Instanz gelöscht wurde. Es gibt einen Platzhalter für den Hostnamen der Instanz (Sie können auch den Anzeigenamen der Instanz mit einer leichten Verringerung der Leistung verwenden) sowie einen Platzhalter für die Geräteregistrierungs-ID.

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

Sie sollten sehen, dass der Zwilling des Geräts in der Azure Digital Twins-Instanz nicht mehr gefunden werden kann.

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

Bereinigen von Ressourcen

Wenn Sie die in diesem Artikel erstellten Ressourcen nicht mehr benötigen, folgen Sie den Schritten unten, um sie zu löschen.

Bei Verwendung von Azure Cloud Shell oder der lokalen Azure CLI können Sie alle Azure-Ressourcen in einer Ressourcengruppe mit dem Befehl az group delete löschen. Dieser Befehl entfernt Ressourcengruppe, die Azure Digital Twins-Instanz, den IoT-Hub und die Registrierung des Hubgeräts, das Event Grid-Thema und die zugehörigen Abonnements, den Event Hub-Namespace sowie beide Azure Functions-Apps (einschließlich zugeordneter Ressourcen, z. B. Speicher).

Wichtig

Das Löschen einer Ressourcengruppe kann nicht rückgängig gemacht werden. Die Ressourcengruppe und alle darin enthaltenen Ressourcen werden unwiderruflich gelöscht. Achten Sie daher darauf, dass Sie nicht versehentlich die falsche Ressourcengruppe oder die falschen Ressourcen löschen.

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

Löschen Sie dann den Beispielordner des Projekts, den Sie heruntergeladen haben, von Ihrem lokalen Computer.

Nächste Schritte

Die für die Geräte erstellten digitalen Zwillinge werden als flache Hierarchie in Azure Digital Twins gespeichert, können jedoch für die Organisation mit Modellinformationen und einer Hierarchie mit mehreren Ebenen erweitert werden. Weitere Informationen zu diesem Vorgang finden Sie hier:

Weitere Informationen zur Verwendung von HTTP-Anforderungen mit Azure-Funktionen finden Sie unter:

Sie können eine benutzerdefinierte Logik schreiben, um diese Informationen mithilfe der bereits in Azure Digital Twins gespeicherten Modell- und Diagrammdaten automatisch bereitzustellen. Weitere Informationen zum Verwalten, Aktualisieren und Abrufen von Informationen aus dem Zwillingsgraphen finden Sie in den folgenden Schrittanleitungen: