Partage via


Inscrire des composants auprès de Device Update

Cet article montre un exemple d’implémentation d’un énumérateur de composants Device Update pour IoT Hub. Vous pouvez référencer cet exemple pour implémenter un énumérateur de composants personnalisé pour vos appareils IoT. Un composant est une identité sous le niveau de l’appareil qui a une relation de composition avec l’appareil hôte.

Cet article illustre un énumérateur de composants qui utilise un appareil IoT virtuel appelé Contoso Virtual Vacuum. Les énumérateurs de composants sont utilisés pour implémenter la fonctionnalité de mise à jour de proxy.

La mise à jour de proxy permet de mettre à jour plusieurs composants sur le même appareil IoT ou sur plusieurs capteurs connectés à l’appareil IoT par le biais d’un seul déploiement OTA (over-the-air). La mise à jour de proxy prend en charge un ordre d’installation pour la mise à jour des composants. Elle prend également en charge la mise à jour en plusieurs étapes avec des fonctionnalités de préinstallation, d’installation et de post-installation.

Voici quelques cas d’usage dans lesquels les mises à jour de proxy sont applicables :

  • Ciblage de fichiers de mise à jour spécifiques sur des partitions sur l’appareil.
  • Ciblage de fichiers de mise à jour spécifiques sur des applications ou des composants sur l’appareil.
  • Ciblage de fichiers de mise à jour spécifiques sur des capteurs connectés à des appareils IoT sur un protocole réseau (par exemple, bus de données CAN ou USB).

Pour plus d’informations, consultez Mises à jour de proxy et mise à jour de plusieurs composants.

L’agent Device Update s’exécute sur l’appareil hôte. Il peut envoyer chaque mise à jour à un composant spécifique ou un groupe de composants de la même classe matérielle (nécessitant la même mise à jour de logiciel ou de microprogramme).

Qu’est-ce qu’un énumérateur de composants ?

Un énumérateur de composants est une extension de l’agent Device Update qui fournit des informations relatives à chaque composant dont vous avez besoin pour effectuer une mise à jour OTA par le biais de la connexion Azure IoT Hub d’un appareil hôte.

L’agent Device Update est indépendant des appareils et des composants. L’agent ne sait rien des composants qui sont installés sur un appareil hôte ou connectés à celui-ci au moment de la mise à jour.

Pour activer les mises à jour de proxy, les générateurs d’appareils doivent identifier tous les composants sur l’appareil pouvant être mis à jour et affecter un nom unique à chaque composant. En outre, un nom de groupe peut être affecté aux composants de la même classe matérielle, ce qui permet d’installer la même mise à jour sur tous les composants appartenant au même groupe. Le gestionnaire de contenu de mise à jour peut ensuite installer et appliquer la mise à jour aux composants appropriés.

Diagramme qui montre le flux de mise à jour de proxy.

Voici les responsabilités de chaque partie du processus de mise à jour de proxy :

  • Générateur d’appareils

    • Concevoir et générer l’appareil.

    • Intégrer l’agent Device Update et ses dépendances.

    • Implémenter l’extension de l’énumérateur de composants propre à l’appareil et l’inscrire auprès de l’agent Device Update.

      L’énumérateur de composants utilise les informations sur les composants issues d’un inventaire de composants ou d’un fichier config pour enrichir les données des composants statiques (Device Update obligatoire) de données dynamiques (par exemple, la version du microprogramme, l’état de la connexion et l’identité du matériel).

    • Créer une mise à jour de proxy contenant une ou plusieurs mises à jour enfants qui ciblent un ou plusieurs composants installés sur l’appareil ou connectés à celui-ci.

    • Envoyer la mise à jour à l’opérateur de solution.

  • Opérateur de solution

    • Importer la mise à jour et le manifeste dans le service Device Update.

    • Déployer la mise à jour sur un groupe d’appareils.

  • Agent Device Update

    • Obtenir les informations de mise à jour à partir d’IoT Hub par le biais du jumeau d’appareil ou du jumeau de module.

    • Appeler un gestionnaire d’étapes pour traiter la mise à jour de proxy ciblant un ou plusieurs composants sur l’appareil.

      L’exemple de cet article comporte deux mises à jour : host-fw-1.1 et motors-fw-1.1. Pour chaque mise à jour enfant, le gestionnaire d’étapes parent appelle un gestionnaire d’étapes enfant pour énumérer tous les composants qui correspondent aux propriétés Compatibilities spécifiées dans le fichier manifeste de la mise à jour enfant. Ensuite, le gestionnaire télécharge, installe et applique la mise à jour enfant à tous les composants ciblés.

      Pour obtenir les composants correspondants, la mise à jour enfant appelle une API SelectComponents fournie par l’énumérateur de composants. Si aucun composant correspondant n’est présent, la mise à jour enfant est ignorée.

    • Collecter tous les résultats de mise à jour de chaque mise à jour parent et enfant, et les envoyer à IoT Hub.

  • Gestionnaire d’étapes enfant

    • Itérer une liste des instances de composant qui sont compatibles avec le contenu de la mise à jour enfant. Pour plus d’informations, consultez Gestionnaire d’étapes.

En production, les générateurs d’appareils peuvent utiliser des gestionnaires existants ou implémenter un gestionnaire personnalisé qui appelle le programme d’installation nécessaire pour une mise à jour OTA. Pour plus d’informations, consultez Implémenter un gestionnaire de contenu de mise à jour personnalisé.

Composants de Virtual Vacuum

Pour cet article, nous utilisons un appareil IoT virtuel pour illustrer les concepts et fonctionnalités clés. L’appareil Contoso Virtual Vacuum est constitué de cinq composants logiques :

  • Un microprogramme hôte
  • Un système de fichiers de démarrage hôte
  • Un système de fichiers racine hôte
  • Trois moteurs (roue gauche, roue droite et aspiration)
  • Deux caméras (avant et arrière)

Diagramme montrant les composants Contoso Virtual Vacuum.

La structure de répertoires suivante simule les composants :

/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 */

Le répertoire de chaque composant contient un fichier JSON qui stocke un numéro de version logicielle factice de chaque composant. Les exemples de fichiers JSON sont firmware.json et diskimage.json.

Dans cette démonstration, pour mettre à jour le microprogramme des composants, nous allons copier firmware.json ou diskimage.json (charge utile de mise à jour) dans le répertoire des composants ciblés.

Voici un exemple de fichier firmware.json :

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

Notes

Contoso Virtual Vacuum contient des versions de logiciel ou de microprogramme dans le but de démontrer la mise à jour de proxy. Il ne fournit pas d’autres fonctionnalités.

Implémenter un énumérateur de composants (langage C)

Conditions requises

Implémentez toutes les API déclarées dans component_enumerator_extension.hpp :

Fonction Arguments Retours
char* GetAllComponents() None Chaîne JSON contenant un tableau de toutesComponentInfo les valeurs. Pour plus d’informations, consultez Exemples de valeurs de retour.
char* SelectComponents(char* selector) Chaîne JSON contenant une ou plusieurs paires nom-valeur utilisées pour sélectionner les composants cibles de la mise à jour. Chaîne JSON contenant un tableau de valeurs ComponentInfo. Pour plus d’informations, consultez Exemples de valeurs de retour.
void FreeComponentsDataString(char* string) Pointeur vers le tampon de chaînes retourné précédemment par les fonctions GetAllComponents ou SelectComponents. None

ComponentInfo

La chaîne JSON ComponentInfo doit inclure les propriétés suivantes :

Nom Type Description
id string Identité unique d’un composant (étendue de l’appareil). Citons par exemple le numéro de série du matériel, l’ID de partition du disque et le chemin de fichier unique du composant.
name string Nom logique d’un composant. Cette propriété est le nom qu’un générateur d’appareils affecte à un composant qui est disponible sur chaque appareil de la même classe device.

Par exemple, chaque appareil Contoso Virtual Vacuum contient un moteur qui fait tourner une roue gauche. Contoso a affecté le nom commun (logique) left motor à ce moteur. Il est ainsi plus facile de faire référence à ce composant qu’en utilisant l’ID de matériel, qui peut être globalement unique.
group string Groupe auquel appartient ce composant.

Par exemple, tous les moteurs peuvent appartenir à un groupe appelé motors.
manufacturer string Pour un composant matériel physique, cette propriété est un nom de fabricant ou de fournisseur.

Pour un composant logique, comme une partition de disque ou un répertoire, il peut s’agir de n’importe quelle valeur définie par le générateur d’appareils.
model string Pour un composant matériel physique, cette propriété est un nom de modèle.

Pour un composant logique, comme une partition de disque ou un répertoire, cette propriété peut être n’importe quelle valeur définie par le générateur d’appareils.
properties object Objet JSON contenant des propriétés facultatives propres à l’appareil.

Voici un exemple de code ComponentInfo basé sur les composants Contoso Virtual Vacuum :

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

Exemples de valeurs de retour

Voici un document JSON retourné par la fonction GetAllComponents. Il est basé sur l’exemple d’implémentation de l’énumérateur de composants 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"
            }
        }
    ]
}

Le document JSON est retourné par la fonction SelectComponents. Il est basé sur l’exemple d’implémentation de l’énumérateur de composants Contoso.

Voici le paramètre d’entrée permettant de sélectionner le groupe de composants motors :

{
    "group" : "motors"
}

Voici la sortie du paramètre. Tous les composants appartenant au groupe motors.

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

Voici le paramètre d’entrée permettant de sélectionner un seul composant nommé hostfw :

{
    "name" : "hostfw"
}

Voici la sortie du paramètre pour le composant hostfw :

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

Notes

L’exemple précédent démontre que, si nécessaire, il est possible d’envoyer une mise à jour plus récente à une instance d’un composant sélectionné par la propriété name. Vous pouvez par exemple déployer la mise à jour motor-fw-2.0 sur vacuum-motor tout en continuant à utiliser motor-fw-1.0 sur left-motor et right-motor.

Fichier d’inventaire

L’exemple d’implémentation illustré précédemment pour l’énumérateur de composants Contoso Virtual Vacuum lit les informations des composants propres à l’appareil à partir du fichier component-inventory.json. Cet exemple d’implémentation est uniquement fourni à des fins de démonstration.

Dans un scénario de production, certaines propriétés doivent être récupérées directement à partir des composants réels. Ces propriétés incluent id, manufacturer et model.

Le générateur d’appareils définit les propriétés name et group. Ces valeurs ne doivent plus changer une fois définies. La propriété name doit être unique sur l’appareil.

Exemple de fichier component-inventory.json

Notes

Le contenu de ce fichier ressemble presque à la valeur retournée par la fonction GetAllComponents. La différence est que, dans ce fichier, ComponentInfo ne contient pas les propriétés version et status. L’énumérateur de composants renseignera ces propriétés au moment de l’exécution.

Par exemple, pour hostfw, la valeur de la propriété properties.version sera renseignée à partir de la valeur firmwareDataFile (fictive) spécifiée (/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",
            }
        }
    ]
}

Étapes suivantes

L’exemple de cet article a utilisé C. Pour explorer les exemples de codes sources C++, consultez :

Pour voir différents exemples de mises à jour de composants connectés à l’appareil Contoso Virtual Vacuum, consultez Démonstration des mises à jour de proxy.