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 auf untergeordneter Geräteebene, die über eine Kompositionsbeziehung mit dem Hostgerät verfügt.

In diesem Artikel wird ein Komponenten-Enumerator gezeigt, der ein virtuelles IoT-Gerät namens „Contoso Virtual Vacuum“ verwendet. Komponenten-Enumeratoren werden zum Implementieren des Features Proxy-Update verwendet.

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:

  • Festlegung bestimmter Updatedateien auf verschiedene Teilbereiche auf dem Gerät.
  • Festlegung bestimmter Updatedateien auf verschiedene Apps oder Komponenten auf dem 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 Proxy-Updates und Aktualisierung mehrerer Komponenten.

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 Geräteupdate-Agent selbst weiß zum Zeitpunkt des Updates 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 des Proxyupdateflusses.

Dies sind die Zuständigkeiten der einzelnen Teile des Proxyupdateflusses:

  • Geräteentwickler

    • 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 Proxyupdate mit mindestens einem untergeordneten Update, das mindestens auf eine Komponente auf dem Gerät (oder auf mindestens eine Komponente, die mit dem Gerät verbunden ist) 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äteupdate-Agent

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

    • Rufen Sie einen Schritthandler 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 das untergeordnete Update übersprungen.

    • Sammeln Sie alle Update-Ergebnisse aus über- und untergeordneten Updates, und melden Sie diese Ergebnisse dem IoT Hub.

  • Handler für untergeordnete Schritte

    • Durchlaufen Sie eine Liste von Komponenteninstanzen, die mit dem Inhalt des untergeordneten Updates kompatibel sind. Weitere Informationen finden Sie unter Schrittehandler.

In der Produktion können Geräteentwickler 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 How To Implement A Custom Content Handler Extension (Implementieren einer benutzerdefinierten Inhaltshandlererweiterung).

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:

  • Host-Firmware
  • Host-Boot-Dateisystem
  • Hoststammdateisystem
  • Drei Motoren (Left Wheel, Right Wheel und Vacuum)
  • Zwei Kameras (vorne und hinten)

Diagramm der Contoso Virtual Vacuum-Komponenten.

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. JSON-Beispieldateien sind firmware.json und diskimage.json.

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

Hier sehen Sie ein Beispiel für die Datei firmware.json:

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

Implementiert alle APIs, die in component_enumerator_extension.hpp deklariert sind:

Funktion Argumente Rückgabe
char* GetAllComponents() Keine Eine JSON-Zeichenfolge enthält ein Array aller ComponentInfo-Werte. 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. Keine

ComponentInfo

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

Name Typ Beschreibung
id Zeichenfolge Eindeutige Identität einer Komponente (Gerätebereich). Beispiele hierfür sind die Hardwareseriennummer, die Datenträgerpartitions-ID und der eindeutige Dateipfad der Komponente.
name Zeichenfolge 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 Linker Motor (left motor) als allgemeinen (logischen) Namen für diesen Motor zugewiesen, um einfach auf diese Komponente anstelle der Hardware-ID zu verweisen, die global eindeutig sein kann.
group Zeichenfolge Eine Gruppe, zu der diese Komponente gehört.

Beispielsweise könnten alle Motoren zu einer Motoren-Gruppe gehören.
manufacturer Zeichenfolge 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 Zeichenfolge 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 (object) 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 sehen Sie den Eingabeparameter für die Auswahl der Komponentengruppe Motoren:

{
    "group" : "motors"
}

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

{
    "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 für die Auswahl 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 Update motor-fw-2.0 für Vakuum-Motor (vacuum-motor) bereit, während Sie weiterhin für den linken Motor (left-motor) und rechten Motor (right-motor) bei motor-fw-1.0 verwenden.

Inventardateien

Die weiter oben gezeigte Beispielimplementierung für den Komponenten-Enumerator von Contoso Virtual Vacuum liest die Informationen der gerätespezifischen Komponenten aus der Datei component-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 der Datenbank 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 hostfwwird der Wert der Eigenschaft properties.version beispielsweise vom angegebenen (Mock)-Wert firmwareDataFile ausgefüllt (/usr/local/contoso-devices/vacuum-1/hostfw/firmware.json).

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

Unter Proxyupdate-Demo finden Sie verschiedene Beispielupdates für Komponenten, die mit dem Contoso Virtual Vacuum-Gerät verbunden sind.