Verstehen und Verwenden von Modulzwillingen in IoT Hub

In diesem Artikel wird vorausgesetzt, dass Sie bereits den Artikel Verstehen und Verwenden von Gerätezwillingen in IoT Hub gelesen haben. In IoT Hub können unter jeder Geräteidentität bis zu 50 Modulidentitäten erstellt werden. Jede Modulidentität generiert implizit einen Modulzwilling. Modulzwillinge weisen Ähnlichkeiten mit Gerätezwillingen auf und stellen JSON-Dokumente dar, in denen Modulstatusinformationen wie Metadaten, Konfigurationen und Zustände gespeichert werden. Azure IoT Hub pflegt einen Modulzwilling für jedes Modul, das Sie mit IoT Hub verbinden.

Auf der Geräteseite können Sie mithilfe der IoT Hub-Geräte-SDKs Module erstellen, die jeweils eine unabhängige Verbindung mit IoT Hub herstellen. Durch diese Funktionalität können Sie separate Namespaces für unterschiedliche Komponenten auf Ihrem Gerät verwenden. Ein Beispiel: Angenommen, Sie verfügen über einen Verkaufsautomaten mit drei verschiedene Sensoren. Jeder Sensor wird von einer anderen Abteilung in Ihrem Unternehmen gesteuert. Sie können für jeden Sensor jeweils ein eigenes Modul erstellen. Dadurch kann jede Abteilung nur Aufträge oder direkte Methoden an den Sensor senden, den sie steuert, was zur Vermeidung von Konflikten und Benutzerfehlern beiträgt.

Modulidentität und Modulzwilling bieten die gleichen Funktionen wie Geräteidentität und Gerätezwilling, aber mit einer höheren Granularität. Dank dieser höheren Granularität können geeignete Geräte (etwa betriebssystembasierte Geräte oder Firmwaregeräte, die mehrere Komponenten verwalten) Konfigurationen und Zustände für die einzelnen Komponenten isolieren. Modulidentität und Modulzwillinge ermöglichen die Trennung von Verwaltungszuständigkeiten bei Verwendung von IoT-Geräten mit modularen Softwarekomponenten. Wir arbeiten daran, bis zur allgemeinen Verfügbarkeit von Modulzwillingen alle Funktionen für Gerätezwillinge auf der Modulzwillingsebene zu unterstützen.

Hinweis

Die in diesem Artikel beschriebenen Features stehen nur im Standard-Tarif von IoT Hub zur Verfügung. Weitere Informationen zu den IoT Hub-Tarifen „Basic“ und „Standard/Free“ finden Sie unter Wählen des richtigen IoT Hub-Tarifs für Ihre Lösung.

Dieser Artikel beschreibt Folgendes:

  • Die Struktur des Modulzwillings: Tags, gewünschte Eigenschaften und gemeldete Eigenschaften.
  • Die Vorgänge, die Module und Back-Ends für Modulzwillinge ausführen können.

Weitere Informationen zur Verwendung von gemeldeten Eigenschaften, D2C-Nachrichten und Dateiuploads finden Sie bei Bedarf im Leitfaden zur D2C-Kommunikation.

Weitere Informationen zu gewünschten Eigenschaften, direkten Methoden und C2D-Nachrichten finden Sie im Leitfaden zur C2D-Kommunikation.

Modulzwillinge

Modulzwillinge speichern modulspezifische Informationen, auf die Folgendes zutrifft:

  • Module auf dem Gerät und IoT Hub können damit Modulzustände und -konfigurationen synchronisieren.

  • Das Lösungs-Back-End kann mit ihnen lang andauernde Vorgänge abfragen und als Ziel verwenden.

Der Lebenszyklus eines Modulzwillings ist mit der entsprechenden Modulidentität verknüpft. Modulzwillinge werden implizit erstellt und gelöscht, wenn in IoT Hub eine Modulidentität erstellt oder gelöscht wird.

Ein Modulzwilling ist ein JSON-Dokument, das Folgendes enthält:

  • Tags. Ein Abschnitt des JSON-Dokuments, in dem das Lösungs-Back-End Lese- und Schreibvorgänge ausführen kann. Tags sind für Module auf dem Gerät nicht sichtbar. Tags werden zu Abfragezwecken festgelegt.

  • Gewünschte Eigenschaften Werden in Verbindung mit gemeldeten Eigenschaften zum Synchronisieren von Modulkonfigurationen oder -zuständen verwendet. Das Lösungs-Back-End kann gewünschte Eigenschaften festlegen, die von der Modul-App gelesen werden können. Die Modul-App kann auch Benachrichtigungen über Änderungen an den gewünschten Eigenschaften erhalten.

  • Gemeldete Eigenschaften Werden in Verbindung mit gewünschten Eigenschaften zum Synchronisieren von Modulkonfigurationen oder -zuständen verwendet. Die Modul-App kann gemeldete Eigenschaften festlegen, die vom Lösungs-Back-End gelesen und abgefragt werden können.

  • Modulidentitätseigenschaften: Der Stamm des JSON-Dokuments für einen Modulzwilling enthält die schreibgeschützten Eigenschaften der dazugehörigen Modulidentität aus der Identitätsregistrierung.

Architectural representation of device twin

Das folgende Beispiel zeigt das JSON-Dokument für einen Modulzwilling:

{
    "deviceId": "devA",
    "moduleId": "moduleA",
    "etag": "AAAAAAAAAAc=", 
    "status": "enabled",
    "statusReason": "provisioned",
    "statusUpdateTime": "0001-01-01T00:00:00",
    "connectionState": "connected",
    "lastActivityTime": "2015-02-30T16:24:48.789Z",
    "cloudToDeviceMessageCount": 0, 
    "authenticationType": "sas",
    "x509Thumbprint": {     
        "primaryThumbprint": null, 
        "secondaryThumbprint": null 
    }, 
    "version": 2, 
    "tags": {
        "deploymentLocation": {
            "building": "43",
            "floor": "1"
        }
    },
    "properties": {
        "desired": {
            "telemetryConfig": {
                "sendFrequency": "5m"
            },
            "$metadata" : {...},
            "$version": 1
        },
        "reported": {
            "telemetryConfig": {
                "sendFrequency": "5m",
                "status": "success"
            },
            "batteryLevel": 55,
            "$metadata" : {...},
            "$version": 4
        }
    }
}

Im Stammobjekt befinden sich die Modulidentitätseigenschaften, Containerobjekte für tags sowie die Eigenschaften reported und desired. Der Container properties enthält einige schreibgeschützte Elemente ($metadata und $version), die weiter unten in den Abschnitten Metadaten des Modulzwillings und Optimistische Parallelität beschrieben werden.

Beispiel für eine gemeldete Eigenschaft

Im vorherigen Beispiel enthält der Modulzwilling eine batteryLevel-Eigenschaft, die von der Modul-App gemeldet wird. Mit dieser Eigenschaft können Module abgefragt und Aktionen auf der Grundlage des letzten gemeldeten Akkustands ausgeführt werden. Ein weiteres Beispiel wären von der Modul-App gemeldete Modulfunktionen oder Konnektivitätsoptionen.

Hinweis

Gemeldete Eigenschaften tragen zur Vereinfachung von Szenarien bei, in denen das Lösungs-Back-End den letzten bekannten Wert einer Eigenschaft abfragen soll. Verwenden Sie Gerät-zu-Cloud-Nachrichten, wenn das Lösungs-Back-End Modultelemetriedaten in Form einer Reihe von Ereignissen mit Zeitstempel abfragen muss (beispielsweise eine Zeitreihe).

Beispiel für eine gewünschte Eigenschaft

Im vorherigen Beispiel werden die gewünschten und gemeldeten Eigenschaften des Modulzwillings telemetryConfig vom Lösungs-Back-End und von der Modul-App verwendet, um die Telemetriekonfiguration für dieses Modul zu synchronisieren. Beispiel:

  1. Das Lösungs-Back-End legt die gewünschte Eigenschaft mit dem gewünschten Konfigurationswert fest. Hier sehen Sie den Teil des Dokuments mit der festgelegten gewünschten Eigenschaft:

    ...
    "desired": {
        "telemetryConfig": {
            "sendFrequency": "5m"
        },
        ...
    },
    ...
    
  2. Die Modul-App wird sofort über die Änderung benachrichtigt, wenn das Modul verbunden ist. Wenn es nicht verbunden ist, folgt die Modul-App beim Herstellen der Verbindung dem Ablauf zur Wiederherstellung der Modulverbindung. Anschließend meldet die Modul-App die aktualisierte Konfiguration (oder einen Fehler unter Verwendung der Eigenschaft status). Dies ist der Teil mit den gemeldeten Eigenschaften:

    "reported": {
        "telemetryConfig": {
            "sendFrequency": "5m",
            "status": "success"
        }
        ...
    }
    
  3. Das Lösungs-Back-End kann die Ergebnisse des Konfigurationsvorgangs auf vielen Modulen durch Abfragen des Modulzwillings nachverfolgen.

Hinweis

Die obigen Codeausschnitte sind Beispiele mit optimierter Lesbarkeit und zeigen eines der möglichen Verfahren zum Codieren einer Modulkonfiguration und des dazugehörigen Status. IoT Hub gibt kein bestimmtes Schema für die gewünschten und gemeldeten Eigenschaften in den Modulzwillingen vor.

Wichtig

IoT Plug & Play definiert ein Schema, das mehrere zusätzliche Eigenschaften verwendet, um Änderungen an gewünschten und gemeldeten Eigenschaften zu synchronisieren. Wenn Ihre Lösung IoT Plug & Play verwendet, müssen Sie beim Aktualisieren von Zwillingseigenschaften die Plug & Play-Konventionen befolgen. Weitere Informationen und ein Beispiel finden Sie unter Beschreibbare Eigenschaften in IoT Plug & Play.

Back-End-Vorgänge

Das Lösungs-Back-End greift mithilfe folgender atomischer Vorgänge, die über HTTPS verfügbar gemacht werden, auf den Modulzwilling zu:

  • Abrufen des Modulzwillings anhand der ID: Dieser Vorgang gibt das Dokument für den Modulzwilling zurück (einschließlich Tags sowie gewünschter und gemeldeter Systemeigenschaften).

  • Partielles Aktualisieren des Modulzwillings: Dieser Vorgang ermöglicht es dem Lösungs-Back-End, einen Teil der Tags oder gewünschten Eigenschaften in einem Modulzwilling zu aktualisieren. Bei der partiellen Aktualisierung handelt es sich um ein JSON-Dokument, das eine beliebige Eigenschaft hinzufügt oder aktualisiert. Auf null festgelegte Eigenschaften werden entfernt. Im folgenden Beispiel wird eine neue gewünschte Eigenschaft mit dem Wert {"newProperty": "newValue"} erstellt, der vorhandene Wert von existingProperty wird mit "otherNewValue" überschrieben, und otherOldProperty wird entfernt. Ansonsten werden an vorhandenen Eigenschaften oder Tags keine weiteren Änderungen vorgenommen:

    {
        "properties": {
            "desired": {
                "newProperty": {
                    "nestedProperty": "newValue"
                },
                "existingProperty": "otherNewValue",
                "otherOldProperty": null
            }
        }
    }
    
  • Ersetzen gewünschter Eigenschaften. Dieser Vorgang ermöglicht dem Lösungs-Back-End, alle vorhandenen gewünschten Eigenschaften vollständig zu überschreiben und ein neues JSON-Dokument für properties/desired bereitzustellen.

  • Ersetzen von Tags. Dieser Vorgang ermöglicht es dem Lösungs-Back-End, alle vorhandenen Tags vollständig zu überschreiben und ein neues JSON-Dokument für tags bereitzustellen.

  • Zwillingsbenachrichtigungen empfangen. Mit diesem Vorgang kann das Lösungs-Back-End benachrichtigt werden, wenn der Zwilling geändert wird. Zu diesem Zweck muss Ihre IoT-Lösung eine Route erstellen die Datenquelle auf twinChangeEvents festlegen. Weil es solche Routen standardmäßig nicht gibt, werden keine Zwillingsbenachrichtigungen gesendet. Wenn die Änderungsrate zu hoch ist, oder andere Gründe wie interne Fehler vorliegen, sendet der IoT Hub möglicherweise nur eine Benachrichtigung, die alle Änderungen enthält. Wenn Ihre Anwendung zuverlässige Prüfungen und Protokolle aller Zwischenzustände benötigt, sollten Sie D2C-Nachrichten verwenden. Weitere Informationen zu den Eigenschaften und den Texten, die in der Zwillingsbenachrichtigungsmeldung zurückgegeben werden, finden Sie unter Schemas für nicht telemetriebezogene Ereignisse.

Alle oben genannten Vorgänge unterstützen die optimistische Nebenläufigkeit und erfordern die Berechtigung ServiceConnect, wie im Artikel Steuern des Zugriffs auf IoT Hub definiert.

Zusätzlich zu diesen Vorgängen kann das Lösungs-Back-End die Modulzwillinge über eine SQL-ähnliche IoT Hub-Abfragesprache abfragen.

Modulvorgänge

Die Modul-App führt mithilfe folgender atomarer Vorgänge Aktionen für den Modulzwilling aus:

  • Abrufen des Modulzwillings: Dieser Vorgang gibt das Dokument zum Modulzwilling (einschließlich gewünschter und gemeldeter Systemeigenschaften) für das zurzeit verbundene Modul zurück.

  • Teilweises Aktualisieren gemeldeter Eigenschaften. Dieser Vorgang ermöglicht die partielle Aktualisierung der gemeldeten Eigenschaften des derzeit verbundenen Moduls. Dabei wird das gleiche JSON-Updateformat wie bei der partiellen Aktualisierung der gewünschten Eigenschaften durch das Lösungs-Back-End verwendet.

  • Beobachten gewünschter Eigenschaften. Das derzeit verbundene Modul kann auf Wunsch benachrichtigt werden, sobald die gewünschten Eigenschaften aktualisiert werden. Das Modul erhält die gleiche Form der Aktualisierung (partielle oder vollständige Ersetzung), die durch das Lösungs-Back-End ausgeführt wird.

Alle oben beschriebenen Vorgänge erfordern die Berechtigung DeviceConnect, wie im Artikel Steuern des Zugriffs auf IoT Hub definiert.

Die Azure IoT-Geräte-SDKs vereinfachen die Verwendung der oben beschriebenen Vorgänge, die mit vielen Sprachen und Plattformen erstellt wurden.

Format von Tags und Eigenschaften

Tags, gewünschte Eigenschaften und gemeldete Eigenschaften sind JSON-Objekte mit den folgenden Einschränkungen:

  • Schlüssel: Alle Schlüssel in JSON-Objekten sind UTF-8-codiert, die Groß-/Kleinschreibung muss beachtet werden, und ihre Länge beträgt bis zu 1 KB. UNICODE-Steuerzeichen (Segmente C0 und C1) sowie ., $ und „SP“ gehören nicht zu den zulässigen Zeichen.

  • Werte: Alle Werte in JSON-Objekten können die folgenden JSON-Typen aufweisen: boolescher Wert, Zahl, Zeichenfolge, Objekt. Arrays werden ebenfalls unterstützt.

    • Ganze Zahlen können den Minimalwert „-4503599627370496“ und den Maximalwert „4503599627370495“ haben.

    • Zeichenfolgenwerte sind UTF-8-codiert und können eine maximale Länge von 4 Bytes haben.

  • Tiefe: Die maximale Tiefe von JSON-Objekten in Tags, gewünschten Eigenschaften und gemeldeten Eigenschaften ist „10“. Das folgende Objekt beispielsweise ist gültig:

    {
         ...
         "tags": {
             "one": {
                 "two": {
                     "three": {
                         "four": {
                             "five": {
                                 "six": {
                                     "seven": {
                                         "eight": {
                                             "nine": {
                                                 "ten": {
                                                     "property": "value"
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         },
         ...
    }
    

Größe des Modulzwillings

IoT Hub erzwingt eine Größenbeschränkung von 8 KB auf den Wert tags und eine Größenbeschränkung von jeweils 32 KB auf die Werte properties/desired und properties/reported. In diesen Summen sind keine schreibgeschützten Elemente wie $version und $metadata/$lastUpdated enthalten.

Die Größe von Zwillingen wird folgendermaßen berechnet:

  • Für jede Eigenschaft im JSON-Dokument berechnet IoT Hub kumulativ und addiert die Länge des Eigenschaftenschlüssels und Eigenschaftswerts.

  • Eigenschaftenschlüssel werden als UTF8-codierte Zeichenfolgen betrachtet.

  • Einfache Eigenschaftswerte werden als UTF8-codierte Zeichenfolgen, numerische Werte (8 Bytes) oder boolesche Werte (4 Bytes) betrachtet.

  • Die Größe der UTF8-codierten Zeichenfolgen wird berechnet, indem alle Zeichen gezählt werden – ausgenommen UNICODE-Steuerzeichen (Segmente C0 und C1).

  • Komplexe Eigenschaftswerte (geschachtelte Objekte) werden basierend auf der Aggregatgröße der darin enthaltenen Eigenschaftenschlüssel und Eigenschaftswerte berechnet.

IoT Hub gibt für alle Vorgänge, die die Größe dieser Dokumente über den Grenzwert hinaus erhöhen würden, einen Fehler zurück.

Metadaten des Modulzwillings

IoT Hub verwaltet den Zeitstempel der letzten Aktualisierung für jedes JSON-Objekt in den gewünschten und gemeldeten Eigenschaften des Modulzwillings. Zeitstempel verwenden UTC und sind im ISO8601-Format codiert: YYYY-MM-DDTHH:MM:SS.mmmZ. Beispiel:

{
    ...
    "properties": {
        "desired": {
            "telemetryConfig": {
                "sendFrequency": "5m"
            },
            "$metadata": {
                "telemetryConfig": {
                    "sendFrequency": {
                        "$lastUpdated": "2016-03-30T16:24:48.789Z"
                    },
                    "$lastUpdated": "2016-03-30T16:24:48.789Z"
                },
                "$lastUpdated": "2016-03-30T16:24:48.789Z"
            },
            "$version": 23
        },
        "reported": {
            "telemetryConfig": {
                "sendFrequency": "5m",
                "status": "success"
            },
            "batteryLevel": "55%",
            "$metadata": {
                "telemetryConfig": {
                    "sendFrequency": "5m",
                    "status": {
                        "$lastUpdated": "2016-03-31T16:35:48.789Z"
                    },
                    "$lastUpdated": "2016-03-31T16:35:48.789Z"
                },
                "batteryLevel": {
                    "$lastUpdated": "2016-04-01T16:35:48.789Z"
                },
                "$lastUpdated": "2016-04-01T16:24:48.789Z"
            },
            "$version": 123
        }
    }
    ...
}

Diese Informationen werden auf jeder Ebene (nicht nur die Zweige der JSON-Struktur) gespeichert, um Aktualisierungen beizubehalten, bei denen Objektschlüssel entfernt werden.

Optimistische Parallelität

Tags, gewünschte Eigenschaften und gemeldete Eigenschaften unterstützen die optimistische Parallelität. Wenn Sie die Reihenfolge von Updates der Zwillingseigenschaften garantieren müssen, sollten Sie eine Synchronisierung auf Anwendungsebene implementieren, indem Sie auf den Rückruf von gemeldeten Eigenschaften warten, bevor Sie das nächste Update senden.

Modulzwillinge haben ein ETag (Eigenschaft etag), gemäß RFC7232, das für die JSON-Darstellung des Zwillings steht. Sie können die Eigenschaft etag bei bedingten Aktualisierungsvorgängen über das Lösungs-Back-End verwenden, um Konsistenz sicherzustellen. Dies ist die einzige Option zur Sicherstellung der Konsistenz bei Vorgängen, die den Container tags umfassen.

Gewünschte und gemeldete Eigenschaften des Modulzwillings enthalten außerdem einen $version-Wert, der garantiert inkrementell ist. Zur Gewährleistung der Konsistenz von Updates kann von der aktualisierenden Partei die Version genutzt werden (ähnlich wie ein ETag). Beispiele wären etwa eine Modul-App für eine gemeldete Eigenschaft oder das Lösungs-Back-End für eine gewünschte Eigenschaft.

Versionen sind auch nützlich, wenn ein beobachtender Agent (beispielsweise die Modul-App, die die gewünschten Eigenschaften beobachtet) Racebedingungen zwischen dem Ergebnis eines Abrufvorgangs und einer Aktualisierungsbenachrichtigung beheben muss. Der Abschnitt Ablauf zur Wiederherstellung der Modulverbindung enthält weitere Informationen.

Ablauf zur Wiederherstellung der Modulverbindung

IoT Hub behält keine Aktualisierungsbenachrichtigungen für gewünschte Eigenschaften für nicht verbundene Module bei. Ein Modul, das eine Verbindung herstellt, muss daher zusätzlich zum Abonnieren von Aktualisierungsbenachrichtigungen das gesamte Dokument der gewünschten Eigenschaften abrufen. Wenn die Gefahr von Racebedingungen zwischen Aktualisierungsbenachrichtigungen und dem vollständigen Abruf besteht, muss der folgende Ablauf sichergestellt werden:

  1. Modul-App stellt eine Verbindung mit einem IoT Hub her.
  2. Modul-App abonniert Aktualisierungsbenachrichtigungen für gewünschte Eigenschaften.
  3. Modul-App ruft das vollständige Dokument für gewünschte Eigenschaften ab.

Die Modul-App kann alle Benachrichtigungen ignorieren, bei denen $version kleiner oder gleich der Version des vollständigen abgerufenen Dokuments ist. Diese Herangehensweise ist möglich, da IoT Hub sicherstellt, dass die Versionsnummern immer erhöht werden.

Nächste Schritte

Um einige der in diesem Artikel beschriebenen Konzepte auszuprobieren, sehen Sie sich die folgenden IoT Hub-Tutorials an: