Freigeben über


Registrieren von Komponenten mit Device Update

In diesem Artikel wird eine Beispielimplementierung eines Device Update for IoT Hub-Komponenten-Enumerators gezeigt. Sie können auf dieses Beispiel verweisen, um einen benutzerdefinierten Komponenten-Enumerator für Ihre IoT-Geräte zu implementieren. Eine Komponente ist eine Identität unter der Geräteebene, die eine Kompositionsbeziehung mit dem Hostgerät aufweist.

In diesem Artikel wird ein Komponenten-Enumerator gezeigt, der ein virtuelles IoT-Gerät namens „Contoso Virtual Vacuum“ verwendet. Komponentenumeratoren werden verwendet, um das Proxyupdatefeature zu implementieren.

Das Proxy-Update ermöglicht die Aktualisierung mehrerer Komponenten auf demselben IoT-Gerät oder mehrerer Sensoren, die mit dem IoT-Gerät mit einer einzelnen Over-the-Air-Bereitstellung verbunden sind. Proxyupdates unterstützen eine Installations-Reihenfolge zum Aktualisieren von Komponenten. Darüber hinaus wird die mehrstufige Aktualisierung mit Funktionen der Vorinstallation, Installation und Nachinstallation unterstützt.

Anwendungsbeispiele, in denen Proxy-Updates anwendbar sind:

  • Zielgerichtetes Auswählen bestimmter Updatedateien für Partitionen auf dem Gerät.
  • Zielgerichtete Bereitstellung spezifischer Update-Dateien für Apps oder Komponenten auf das Gerät.
  • Festlegung spezifischer Updatedateien auf Sensoren, die über ein Netzwerkprotokoll mit IoT-Geräten verbunden sind (z. B. USB oder CAN-Bus).

Weitere Informationen finden Sie unter Proxyupdates und Mehrkomponentenaktualisierungen.

Der Geräteupdate-Agent wird auf dem Hostgerät ausgeführt. Jedes Update kann an eine bestimmte Komponente oder eine Gruppe von Komponenten derselben Hardwareklasse gesendet werden (d. h., es ist das gleiche Software- oder Firmwareupdate erforderlich).

Was ist ein Komponenten-Enumerator?

Ein Komponenten-Enumerator ist eine Erweiterung des Geräteupdate-Agents. Er stellt Informationen zu jeder Komponente bereit, die Sie über die Azure IoT Hub-Verbindung eines Hostgeräts per Over-the-Air-Update aktualisieren müssen.

Der Geräteupdate-Agent ist geräte- und komponentenunabhängig. Der Agent weiß während des Updates selbst nichts über Komponenten auf einem Hostgerät oder über Komponenten, die mit einem Hostgerät verbunden sind.

Zum Aktivieren von Proxy-Updates müssen Geräteentwickler alle aktualisierbaren Komponenten auf dem Gerät identifizieren und jeder Komponente einen eindeutigen Namen zuweisen. Außerdem kann der Gruppenname Komponenten derselben Hardwareklasse zugewiesen werden, sodass das gleiche Update auf allen Komponenten in derselben Gruppe installiert werden kann. Dann kann der Handler für Update-Inhalte das Update installieren und auf die richtigen Komponenten anwenden.

Diagramm, das den Proxyaktualisierungsfluss zeigt.

Dies sind die Zuständigkeiten der einzelnen Teile des Proxy-Aktualisierungsablaufs:

  • Geräte-Generator

    • Entwerfen und erstellen Sie das Gerät.

    • Integrieren Sie den Geräteupdate-Agent und seine Abhängigkeiten.

    • Implementieren Sie eine gerätespezifische Erweiterung des Komponenten-Enumerators, und registrieren Sie es beim Geräteupdate-Agent.

      Der Komponenten-Enumerator verwendet die Informationen aus einem Komponentenbestand oder einer Konfigurationsdatei, um statische Komponentendaten (Geräteupdate erforderlich) mit dynamischen Daten (z. B. Firmwareversion, Verbindungsstatus und Hardwareidentität) zu vergrößern.

    • Erstellen Sie ein Proxy-Update, das mindestens ein untergeordnetes Update enthält und auf mindestens eine Komponente auf dem Gerät oder eine mit dem Gerät verbundene Komponente abzielt.

    • Senden Sie das Update an den Lösungsoperator.

  • Lösungsoperator

    • Importieren Sie das Update und das Manifest in den Geräteupdate-Dienst.

    • Stellen Sie das Update für eine Gruppe von Geräten zur Verfügung.

  • Geräteaktualisierungs-Agent

    • Rufen Sie Update-Informationen vom IoT Hub über den Geräte- oder Modulzwilling ab.

    • Rufen Sie einen Schrittehandler auf, um das Proxyupdate zu verarbeiten, das für eine oder mehrere Komponenten auf dem Gerät vorgesehen ist.

      Das Beispiel in diesem Artikel enthält zwei Updates: host-fw-1.1 und motors-fw-1.1. Für jedes untergeordnete Update ruft der Handler für übergeordnete Schritte einen Handler für untergeordnete Schritte auf, um alle Komponenten aufzählen zu können, die mit den in der Manifestdatei des untergeordneten Updates angegebenen Compatibilities Eigenschaften übereinstimmen. Als Nächstes lädt der Handler das untergeordnete Update herunter, installiert es und wendet es auf alle Zielkomponenten an.

      Um die übereinstimmenden Komponenten abzurufen, ruft das untergeordnete Update eine SelectComponents API auf, die vom Komponenten-Enumerator bereitgestellt wird. Wenn keine übereinstimmenden Komponenten vorhanden sind, wird die Kinderaktualisierung übersprungen.

    • Sammeln Sie alle Update-Ergebnisse von Parent- und Child-Updates und melden Sie diese Ergebnisse an den IoT Hub.

  • Handler für untergeordnete Schritte

    • Iterieren Sie durch eine Liste von Komponenteninstanzen, die mit dem Inhalt des untergeordneten Updates kompatibel sind. Weitere Informationen finden Sie im Schritte-Handler.

In der Produktion können Geräte-Generatoren vorhandene Handler verwenden oder einen benutzerdefinierten Handler implementieren, der alle Installationsprogramme aufruft, die für ein Over-the-Air-Update erforderlich sind. Weitere Informationen finden Sie unter Implementieren eines benutzerdefinierten Updateinhaltshandlers.

Virtual-Vacuum-Komponenten

Für diesen Artikel verwenden wir ein virtuelles IoT-Gerät, um die wichtigsten Konzepte und Features zu veranschaulichen. Das Contoso Virtual Vacuum-Gerät besteht aus fünf logischen Komponenten:

  • Firmware für den Host
  • Boot-Dateisystem des Hosts
  • Root-Dateisystem des Hosts
  • Drei Motoren (linkes Rad, rechtes Rad und Staubsauger)
  • Zwei Kameras (vorne und hinten)

Diagramm, das die Komponenten des virtuellen Vakuums von Contoso zeigt.

Die folgende Verzeichnisstruktur simuliert die Komponenten:

/usr/local/contoso-devices/vacuum-1/hostfw
/usr/local/contoso-devices/vacuum-1/bootfs
/usr/local/contoso-devices/vacuum-1/rootfs
/usr/local/contoso-devices/vacuum-1/motors/0   /* left motor */
/usr/local/contoso-devices/vacuum-1/motors/1   /* right motor */
/usr/local/contoso-devices/vacuum-1/motors/2   /* vacuum motor */
/usr/local/contoso-devices/vacuum-1/cameras/0  /* front camera */
/usr/local/contoso-devices/vacuum-1/cameras/1  /* rear camera */

Das Verzeichnis jeder Komponente enthält eine JSON-Datei, in der eine Modellversionsnummer der einzelnen Komponenten gespeichert wird. Beispiel-JSON-Dateien sind firmware.json und diskimage.json.

Für diese Demo, um die Firmware der Komponenten zu aktualisieren, kopieren wir firmware.json oder diskimage.json (Update-Payload) in das Verzeichnis der Zielkomponenten.

Hier ist ein Beispiel firmware.json Datei:

{
    "version": "0.5",
    "description": "This component is generated for testing purposes."
}

Hinweis

Das Contoso Virtual Vacuum enthält Software- oder Firmwareversionen zum Demonstrieren des Proxyupdates. Sie bietet keine weiteren Funktionen.

Implementieren eines Komponenten-Enumerators (Programmiersprache C)

Anforderungen

Implementieren Sie alle in component_enumerator_extension.hpp deklarierten APIs:

Funktion Argumente Rückgaben
char* GetAllComponents() Nichts Eine JSON-Zeichenfolge, die ein Array allerComponentInfo Werte enthält. Weitere Informationen finden Sie unter Beispiel für Rückgabewerte.
char* SelectComponents(char* selector) Eine JSON-Zeichenfolge mit einem oder mehreren Name-Wert-Paaren, die zum Auswählen von Updatezielkomponenten verwendet werden Eine JSON-Zeichenfolge enthält ein Array von ComponentInfo-Werten. Weitere Informationen finden Sie unter Beispiel für Rückgabewerte.
void FreeComponentsDataString(char* string) Ein Zeiger auf den Zeichenfolgenpuffer, der zuvor von den Funktionen GetAllComponents oder SelectComponents zurückgegeben wurde. Nichts

Komponenteninformationen

Darüber hinaus MUSS die JSON-Zeichenfolge ComponentInfo folgende Eigenschaften aufweisen:

Name Typ BESCHREIBUNG
id Schnur Eindeutige Identität einer Komponente (Gerätebereich). Beispiele hierfür sind die Hardwareseriennummer, die Datenträgerpartitions-ID und der eindeutige Dateipfad der Komponente.
name Schnur Der logische Name einer Komponente. Diese Eigenschaft ist der Name, den ein Geräteentwickler einer Komponente zuweist, die auf jedem Gerät derselben device-Klasse verfügbar ist.

Beispielsweise enthält jedes Contoso-Virtual-Vacuum-Gerät einen Motor, der das linke Rad (left wheel) steuert. Contoso hat dem linken Motor einen gemeinsamen (logischen) Namen für diesen Motor zugewiesen, um leicht auf diese Komponente zu verweisen, anstatt auf die Hardware-ID zu verweisen, die global eindeutig sein kann.
group Schnur Eine Gruppe, zu der diese Komponente gehört.

Beispielsweise könnten alle Motoren zu einer Motorengruppe gehören.
manufacturer Schnur Bei einer physischen Hardwarekomponente ist diese Eigenschaft ein Hersteller- oder Anbietername.

Bei logischen Komponenten, z. B. Datenträgerpartitionen oder -verzeichnisse, kann es sich um einen beliebigen definierten Wert des Geräte-Entwicklers handeln.
model Schnur Bei einer physischen Hardwarekomponente ist diese Eigenschaft ein Modellname.

Bei einer logischen Komponente, z. B. einer Datenträgerpartition oder einem Datenträgerverzeichnis, kann diese Eigenschaft ein beliebiger definierter Wert des Geräte-Entwicklers sein.
properties Objekt Ein JSON-Objekt, das optionale gerätespezifische Eigenschaften enthält.

Hier ist ein Beispiel für ComponentInfo-Code, der auf den Komponenten von Contoso Virtual Vacuum basiert:

{
    "id": "contoso-motor-serial-00000",
    "name": "left-motor",
    "group": "motors",
    "manufacturer": "contoso",
    "model": "virtual-motor",
    "properties": {
        "path": "\/usr\/local\/contoso-devices\/vacuum-1\/motors\/0",
        "firmwareDataFile": "firmware.json",
        "status": "connected",
        "version" : "motor-fw-1.0"
    }
}

Beispielrückgabewerte

Im Folgenden finden Sie ein JSON-Dokument, das von der Funktion GetAllComponents zurückgegeben wird. Es basiert auf der Beispielimplementierung des Komponenten-Enumerators von Contoso Virtual Vacuum.

{
    "components": [
        {
            "id": "hostfw",
            "name": "hostfw",
            "group": "firmware",
            "manufacturer": "contoso",
            "model": "virtual-firmware",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/hostfw",
                "firmwareDataFile": "firmware.json",
                "status": "ok",
                "version" : "host-fw-1.0"
            }
        },
        {
            "id": "bootfs",
            "name": "bootfs",
            "group": "boot-image",
            "manufacturer": "contoso",
            "model": "virtual-disk",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/bootfs",
                "firmwareDataFile": "diskimage.json",
                "status": "ok",
                "version" : "boot-fs-1.0"
            }
        },
        {
            "id": "rootfs",
            "name": "rootfs",
            "group": "os-image",
            "manufacturer": "contoso",
            "model": "virtual-os",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/rootfs",
                "firmwareDataFile": "diskimage.json",
                "status": "ok",
                "version" : "root-fs-1.0"
            }
        },
        {
            "id": "contoso-motor-serial-00000",
            "name": "left-motor",
            "group": "motors",
            "manufacturer": "contoso",
            "model": "virtual-motor",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/motors\/0",
                "firmwareDataFile": "firmware.json",
                "status": "ok",
                "version" : "motor-fw-1.0"
            }
        },
        {
            "id": "contoso-motor-serial-00001",
            "name": "right-motor",
            "group": "motors",
            "manufacturer": "contoso",
            "model": "virtual-motor",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/motors\/1",
                "firmwareDataFile": "firmware.json",
                "status": "ok",
                "version" : "motor-fw-1.0"
            }
        },
        {
            "id": "contoso-motor-serial-00002",
            "name": "vacuum-motor",
            "group": "motors",
            "manufacturer": "contoso",
            "model": "virtual-motor",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/motors\/2",
                "firmwareDataFile": "firmware.json",
                "status": "ok",
                "version" : "motor-fw-1.0"
            }
        },
        {
            "id": "contoso-camera-serial-00000",
            "name": "front-camera",
            "group": "cameras",
            "manufacturer": "contoso",
            "model": "virtual-camera",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/camera\/0",
                "firmwareDataFile": "firmware.json",
                "status": "ok",
                "version" : "camera-fw-1.0"
            }
        },
        {
            "id": "contoso-camera-serial-00001",
            "name": "rear-camera",
            "group": "cameras",
            "manufacturer": "contoso",
            "model": "virtual-camera",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/camera\/1",
                "firmwareDataFile": "firmware.json",
                "status": "ok",
                "version" : "camera-fw-1.0"
            }
        }
    ]
}

Das folgende JSON-Dokument wird von der Funktion SelectComponents zurückgegeben. Es basiert auf der Beispielimplementierung des Contoso-Komponenten-Enumerators.

Hier ist der Eingabeparameter für die Auswahl der Motorenkomponentengruppe :

{
    "group" : "motors"
}

Dies ist die Ausgabe des Parameters. Alle Komponenten gehören zur Motorengruppe .

{
    "components": [
        {
            "id": "contoso-motor-serial-00000",
            "name": "left-motor",
            "group": "motors",
            "manufacturer": "contoso",
            "model": "virtual-motor",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/motors\/0",
                "firmwareDataFile": "firmware.json",
                "status": "ok",
                "version" : "motor-fw-1.0"
            }
        },
        {
            "id": "contoso-motor-serial-00001",
            "name": "right-motor",
            "group": "motors",
            "manufacturer": "contoso",
            "model": "virtual-motor",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/motors\/1",
                "firmwareDataFile": "firmware.json",
                "status": "ok",
                "version" : "motor-fw-1.0"
            }
        },
        {
            "id": "contoso-motor-serial-00002",
            "name": "vacuum-motor",
            "group": "motors",
            "manufacturer": "contoso",
            "model": "virtual-motor",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/motors\/2",
                "firmwareDataFile": "firmware.json",
                "status": "ok",
                "version" : "motor-fw-1.0"
            }
        }
    ]
}

Hier ist der Eingabeparameter zum Auswählen einer einzelnen Komponente mit dem Namen "hostfw":

{
    "name" : "hostfw"
}

Dies ist die Ausgabe des Parameters für die Hostfw-Komponente :

{
    "components": [
        {
            "id": "hostfw",
            "name": "hostfw",
            "group": "firmware",
            "manufacturer": "contoso",
            "model": "virtual-firmware",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/hostfw",
                "firmwareDataFile": "firmware.json",
                "status": "ok",
                "version" : "host-fw-1.0"
            }
        }
    ]
}

Hinweis

Im obigen Beispiel wurde gezeigt, dass es bei Bedarf möglich ist, ein neueres Update an eine beliebige Instanz einer Komponente zu senden, wenn diese durch die name-Eigenschaft ausgewählt wird. Stellen Sie z. B. das motor-fw-2.0 Update auf Vakuummotor bereit, während motor-fw-1.0 weiterhin auf linken Motor und rechten Motor verwendet wird.

Inventardateien

Die weiter oben für den Contoso Virtual Vacuum-Komponentenumerator gezeigte Beispielimplementierung liest die gerätespezifischen Komponenteninformationen aus der Dateicomponent-inventory.json. Dieses Beispielimplementierung dient nur zu Demonstrationszwecken.

In einem Produktionsszenario sollten einige Eigenschaften direkt aus den eigentlichen Komponenten abgerufen werden. Zu diesen Eigenschaften zählen id, manufacturer und model.

Der Geräte-Builder definiert die Eigenschaften name und group. Diese Werte sollten sich nie ändern, nachdem sie definiert wurden. Die Eigenschaft name muss innerhalb des Geräts eindeutig sein.

Beispieldatei „component-inventory.json“

Hinweis

Der Inhalt in dieser Datei sieht fast genauso aus wie der von der Funktion GetAllComponents zurückgegebene Wert. In dieser ComponentInfo Datei sind jedoch die Eigenschaften version und status nicht enthalten. Der Komponenten-Enumerator füllt diese Eigenschaften zur Laufzeit aus.

Für hostfw wird der Wert der Eigenschaft properties.version beispielsweise aus dem angegebenen (Mock) firmwareDataFile -Wert (/usr/local/contoso-devices/vacuum-1/hostfw/firmware.json) aufgefüllt.

{
    "components": [
        {
            "id": "hostfw",
            "name": "hostfw",
            "group": "firmware",
            "manufacturer": "contoso",
            "model": "virtual-firmware",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/hostfw",
                "firmwareDataFile": "firmware.json",
            }
        },
        {
            "id": "bootfs",
            "name": "bootfs",
            "group": "boot-image",
            "manufacturer": "contoso",
            "model": "virtual-disk",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/bootfs",
                "firmwareDataFile": "diskimage.json",
            }
        },
        {
            "id": "rootfs",
            "name": "rootfs",
            "group": "os-image",
            "manufacturer": "contoso",
            "model": "virtual-os",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/rootfs",
                "firmwareDataFile": "diskimage.json",
            }
        },
        {
            "id": "contoso-motor-serial-00000",
            "name": "left-motor",
            "group": "motors",
            "manufacturer": "contoso",
            "model": "virtual-motor",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/motors\/0",
                "firmwareDataFile": "firmware.json",
            }
        },
        {
            "id": "contoso-motor-serial-00001",
            "name": "right-motor",
            "group": "motors",
            "manufacturer": "contoso",
            "model": "virtual-motor",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/motors\/1",
                "firmwareDataFile": "firmware.json",
            }
        },
        {
            "id": "contoso-motor-serial-00002",
            "name": "vacuum-motor",
            "group": "motors",
            "manufacturer": "contoso",
            "model": "virtual-motor",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/motors\/2",
                "firmwareDataFile": "firmware.json",
            }
        },
        {
            "id": "contoso-camera-serial-00000",
            "name": "front-camera",
            "group": "cameras",
            "manufacturer": "contoso",
            "model": "virtual-camera",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/camera\/0",
                "firmwareDataFile": "firmware.json",
            }
        },
        {
            "id": "contoso-camera-serial-00001",
            "name": "rear-camera",
            "group": "cameras",
            "manufacturer": "contoso",
            "model": "virtual-camera",
            "properties": {
                "path": "\/usr\/local\/contoso-devices\/vacuum-1\/camera\/1",
                "firmwareDataFile": "firmware.json",
            }
        }
    ]
}

Nächste Schritte

Für das Beispiel in diesem Artikel wurde die Programmiersprache C verwendet. Informationen zu Beispielquellcodes für C++ finden Sie unter:

Verschiedene Beispielupdates für Komponenten, die mit dem Virtuellen Vakuumgerät von Contoso verbunden sind, finden Sie unter Proxyupdate-Demo.