Tutoriel : Configurer vos appareils à partir d’un service backend

Dans le cadre du cycle de vie des appareils, vous devrez peut-être configurer vos appareils IoT à partir de votre service back-end. Lorsque vous envoyez une configuration souhaitée à vos appareils, vous pouvez choisir de recevoir des mises à jour d’état et de conformité de ces appareils. Par exemple, vous pouvez définir une plage de température de fonctionnement cible pour un appareil ou collecter des informations sur la version du microprogramme auprès de vos appareils.

Pour synchroniser les informations d’état entre un appareil et un hub IoT, vous pouvez utiliser des jumeaux d’appareil. Un jumeau d’appareil est un document JSON associé à un appareil spécifique et stocké par IoT Hub dans le cloud à partir duquel vous pouvez interroger le document. Un jumeau d’appareil contient des propriétés souhaitées, des propriétés rapportées et des balises.

  • Une propriété souhaitée est définie par une application back-end et lue par un appareil.
  • Une propriété rapportée est définie par un appareil et lue par une application back-end.
  • Une balise est définie par une application back-end et n’est jamais envoyée à un appareil. Les balises permettent d’organiser vos appareils.

Ce didacticiel vous explique comment utiliser les propriétés souhaitées et rapportées pour synchroniser les informations d’état.

Diagram of device twins on the device and in the cloud.

Dans ce didacticiel, vous allez effectuer les tâches suivantes :

  • Créer un hub IoT et ajouter un appareil de test dans le registre des identités.
  • Utiliser les propriétés souhaitées pour envoyer des informations d’état à votre appareil simulé.
  • Utiliser les propriétés rapportées pour recevoir des informations d’état de votre appareil simulé.

Si vous n’avez pas d’abonnement Azure, créez un compte gratuit avant de commencer.

Prérequis

  • Ce tutoriel utilise Azure CLI pour créer des ressources cloud. Si vous disposez déjà d’un hub IoT avec un appareil inscrit, vous pouvez ignorer ces étapes. Il existe deux façons d’exécuter des commandes CLI :

  • Les deux exemples d’applications que vous exécutez dans ce tutoriel sont écrits à l’aide de Node.js. Votre ordinateur de développement doit disposer de Node.js v10.x.x ou ultérieur.

    • Vous pouvez télécharger Node.js pour plusieurs plateformes sur nodejs.org.

    • Vous pouvez vérifier la version actuelle de Node.js sur votre machine de développement à l’aide de la commande suivante :

      node --version
      
  • Clonez ou téléchargez l’exemple de projet Node.js à partir d’exemples Azure IoT pour Node.js.

  • Assurez-vous que le port 8883 est ouvert dans votre pare-feu. L'exemple d’appareil de ce tutoriel utilise le protocole MQTT qui communique sur le port 8883. Dans certains environnements réseau professionnels et scolaires, ce port peut être bloqué. Pour plus d’informations sur les différentes façons de contourner ce problème, consultez Connexion à IoT Hub (MQTT).

Configurer les ressources Azure

Pour effectuer ce didacticiel, votre abonnement Azure doit contenir un hub IoT avec un appareil ajouté au registre des identités des appareils. L’entrée dans le registre des identités des appareils permet à l’appareil simulé que vous exécutez dans ce didacticiel de se connecter à votre hub.

Si vous n’avez pas encore défini de hub IoT dans votre abonnement, vous pouvez en définir un à l’aide du script d’interface de ligne de commande suivant. Ce script utilise le nom tutorial-iot-hub avec un nombre aléatoire ajouté pour le nom du hub IoT. Vous pouvez remplacer ce nom par votre propre nom global unique lorsque vous l’exécutez. Le script crée le groupe de ressources et le hub dans la région USA Centre que vous pouvez remplacer par une région plus proche de chez vous. Le script récupère la chaîne de connexion de service de votre hub IoT, qui vous permet de vous connecter à votre hub IoT depuis l’exemple d’application back-end :

let "randomIdentifier=$RANDOM*$RANDOM"  
hubname="tutorial-iot-hub-$randomIdentifier"
location=centralus

# Install the IoT extension if it's not already installed:
az extension add --name azure-iot

# Create a resource group:
az group create --name tutorial-iot-hub-rg --location $location

# Create your free-tier IoT hub. You can only have one free IoT hub per subscription.
# Change the sku to S1 to create a standard-tier hub if necessary.
az iot hub create --name $hubname --location $location --resource-group tutorial-iot-hub-rg --partition-count 2 --sku F1

# Make a note of the service connection string, you need it later:
az iot hub connection-string show --hub-name $hubname --policy-name service -o table

Ce didacticiel utilise un appareil simulé appelé MyTwinDevice. Le script suivant ajoute cet appareil dans le registre des identités et récupère sa chaîne de connexion :

# Create the device in the identity registry:
az iot hub device-identity create --device-id MyTwinDevice --hub-name $hubname --resource-group tutorial-iot-hub-rg

# Retrieve the device connection string, you need this later:
az iot hub device-identity connection-string show --device-id MyTwinDevice --hub-name $hubname --resource-group tutorial-iot-hub-rg -o table

Envoyer des informations d’état à un appareil

Vous utilisez les propriétés souhaitées pour envoyer des informations d’état à partir d’une application back-end vers un appareil. Dans cette section, vous allez apprendre à :

  • Configurez un appareil pour recevoir et traiter les propriétés souhaitées.
  • Envoyer les propriétés souhaitées à partir d’une application back-end à un appareil.

Exemples de propriétés souhaitées

Vous pouvez structurer vos propriétés souhaitées pour répondre aux besoins de votre application. Cet exemple utilise une propriété de niveau supérieur appelée fanOn et regroupe les autres propriétés dans des composants distincts. L’extrait de code JSON suivant illustre la structure des propriétés souhaitées utilisée dans ce tutoriel. Le code JSON se trouve dans le fichier desired.json.

{
  "fanOn": "true",
  "components": {
    "system": {
      "id": "17",
      "units": "farenheit",
      "firmwareVersion": "9.75"
    },
    "wifi" : { 
      "channel" : "6",
      "ssid": "my_network"
    },
    "climate" : {
      "minTemperature": "68",
      "maxTemperature": "76"
    }
  }
}

Recevoir les propriétés souhaitées dans une application d’appareil

Pour afficher l’exemple de code de l’appareil simulé qui reçoit les propriétés souhaitées, accédez au dossier iot-hub/Tutorials/DeviceTwins dans l’exemple de projet Node.js que vous avez téléchargé. Ouvrez ensuite le fichier SimulatedDevice.js dans un éditeur de texte.

Les sections suivantes décrivent le code qui s’exécute sur l’appareil simulé qui répond aux modifications de propriétés souhaitées envoyées à partir de l’application back end.

Récupérer l’objet de jumeau d’appareil

Lorsque vous avez inscrit votre appareil auprès du hub IoT, vous avez obtenu une chaîne de connexion d’appareil comme sortie. Une chaîne de connexion d’appareil est utilisée par l’appareil pour s’authentifier avec son identité inscrite dans le cloud. Le code suivant établit une connexion à votre hub IoT à l’aide d’une chaîne de connexion de l’appareil :

// Get the device connection string from a command line argument
var connectionString = process.argv[2];

Le code suivant permet d’obtenir un jumeau de l’objet client :

// Get the device twin
client.getTwin(function(err, twin) {
  if (err) {
    console.error(chalk.red('Could not get device twin'));
  } else {
    console.log(chalk.green('Device twin created'));

Créer des gestionnaires

Vous pouvez créer des gestionnaires pour les mises à jour de propriétés souhaitées qui répondent aux mises à jour effectuées à différents niveaux de la hiérarchie JSON. Par exemple, ce gestionnaire voit toutes les modifications de propriétés souhaitées envoyées à l’appareil à partir d’une application back-end. La variable delta contient les propriétés souhaitées envoyées depuis le serveur back-end de la solution :

// Handle all desired property updates
twin.on('properties.desired', function(delta) {
    console.log(chalk.yellow('\nNew desired properties received in patch:'));

Le gestionnaire suivant réagit uniquement aux modifications apportées à la propriété souhaitée fanOn :

// Handle changes to the fanOn desired property
twin.on('properties.desired.fanOn', function(fanOn) {
    console.log(chalk.green('\nSetting fan state to ' + fanOn));

    // Update the reported property after processing the desired property
    reportedPropertiesPatch.fanOn = fanOn ? fanOn : '{unknown}';
});

Gestionnaires pour propriétés multiples

Dans l’exemple de propriétés souhaitées JSON pour ce tutoriel, le nœud climat sous composants contient deux propriétés, minTemperature et maxTemperature.

Un objet jumeau local de l’appareil enregistre un ensemble complet de propriétés souhaitées et rapportées. La valeur delta envoyée par l’application back-end peut mettre à jour un seul sous-ensemble de propriétés souhaitées. Dans l’extrait de code suivant, si l’appareil simulé reçoit une mise à jour pour une seule des propriétés minTemperature et maxTemperature, il utilise la valeur contenue dans le jumeau local pour l’autre valeur afin de configurer l’appareil :

// Handle desired properties updates to the climate component
twin.on('properties.desired.components.climate', function(delta) {
    if (delta.minTemperature || delta.maxTemperature) {
      console.log(chalk.green('\nUpdating desired tempertures in climate component:'));
      console.log('Configuring minimum temperature: ' + twin.properties.desired.components.climate.minTemperature);
      console.log('Configuring maximum temperture: ' + twin.properties.desired.components.climate.maxTemperature);

      // Update the reported properties and send them to the hub
      reportedPropertiesPatch.minTemperature = twin.properties.desired.components.climate.minTemperature;
      reportedPropertiesPatch.maxTemperature = twin.properties.desired.components.climate.maxTemperature;
      sendReportedProperties();
    }
});

Gérer les opérations d’ajout, de mise à jour et de suppression

Les propriétés souhaitées envoyées depuis l’application back-end n’indiquent pas l’opération qui est effectuée sur une propriété souhaitée spécifique. Votre code doit identifier l’opération à partir de l’ensemble actuel de propriétés souhaitées stockées localement et des modifications envoyées par le hub.

L’extrait de code suivant montre comment l’appareil simulé gère les opérations d’ajout, de mise à jour et de suppression sur la liste de composants dans les propriétés souhaitées. Il explique comment utiliser les valeurs null pour indiquer qu’un composant doit être supprimé :

// Keep track of all the components the device knows about
var componentList = {};

// Use this componentList list and compare it to the delta to infer
// if anything was added, deleted, or updated.
twin.on('properties.desired.components', function(delta) {
  if (delta === null) {
    componentList = {};
  }
  else {
    Object.keys(delta).forEach(function(key) {

      if (delta[key] === null && componentList[key]) {
        // The delta contains a null value, and the
        // device has a record of this component.
        // Must be a delete operation.
        console.log(chalk.green('\nDeleting component ' + key));
        delete componentList[key];

      } else if (delta[key]) {
        if (componentList[key]) {
          // The delta contains a component, and the
          // device has a record of it.
          // Must be an update operation.
          console.log(chalk.green('\nUpdating component ' + key + ':'));
          console.log(JSON.stringify(delta[key]));
          // Store the complete object instead of just the delta
          componentList[key] = twin.properties.desired.components[key];

        } else {
          // The delta contains a component, and the
          // device has no record of it.
          // Must be an add operation.
          console.log(chalk.green('\nAdding component ' + key + ':'));
          console.log(JSON.stringify(delta[key]));
          // Store the complete object instead of just the delta
          componentList[key] = twin.properties.desired.components[key];
        }
      }
    });
  }
});

Envoyer les propriétés souhaitées à partir d’une application back-end

Vous avez vu comment un appareil implémente des gestionnaires pour recevoir des mises à jour de propriétés souhaitées. Cette section vous montre comment envoyer des modifications de propriétés souhaitées à un appareil à partir d’une application back-end.

Pour afficher l’exemple de code de l’appareil simulé qui reçoit les propriétés souhaitées, accédez au dossier iot-hub/Tutorials/DeviceTwins dans l’exemple de projet Node.js que vous avez téléchargé. Ouvrez ensuite le fichier ServiceClient.js dans un éditeur de texte.

L’extrait de code suivant montre comment établir la connexion au registre des identités des appareils et accéder au jumeau d’un appareil spécifique :

// Create a device identity registry object
var registry = Registry.fromConnectionString(connectionString);

// Get the device twin and send desired property update patches at intervals.
// Print the reported properties after some of the desired property updates.
registry.getTwin(deviceId, async (err, twin) => {
  if (err) {
    console.error(err.message);
  } else {
    console.log('Got device twin');

L’extrait de code suivant montre les différents correctifs de propriétés souhaitées que l’application back-end envoie à l’appareil :

// Turn the fan on
var twinPatchFanOn = {
  properties: {
    desired: {
      patchId: "Switch fan on",
      fanOn: "false",
    }
  }
};

// Set the maximum temperature for the climate component
var twinPatchSetMaxTemperature = {
  properties: {
    desired: {
      patchId: "Set maximum temperature",
      components: {
        climate: {
          maxTemperature: "92"
        }
      }
    }
  }
};

// Add a new component
var twinPatchAddWifiComponent = {
  properties: {
    desired: {
      patchId: "Add WiFi component",
      components: {
        wifi: { 
          channel: "6",
          ssid: "my_network"
        }
      }
    }
  }
};

// Update the WiFi component
var twinPatchUpdateWifiComponent = {
  properties: {
    desired: {
      patchId: "Update WiFi component",
      components: {
        wifi: { 
          channel: "13",
          ssid: "my_other_network"
        }
      }
    }
  }
};

// Delete the WiFi component
var twinPatchDeleteWifiComponent = {
  properties: {
    desired: {
      patchId: "Delete WiFi component",
      components: {
        wifi: null
      }
    }
  }
};

L’extrait de code suivant montre comment l’application back-end envoie une mise à jour de propriété souhaitée à un appareil :

// Send a desired property update patch
async function sendDesiredProperties(twin, patch) {
  twin.update(patch, (err, twin) => {
    if (err) {
      console.error(err.message);
    } else {
      console.log(chalk.green(`\nSent ${twin.properties.desired.patchId} patch:`));
      console.log(JSON.stringify(patch, null, 2));
    }
  });
}

Recevoir des informations d’état à partir d’un appareil

Votre application back-end reçoit des informations d’état d’un appareil sous la forme de propriétés rapportées. L’appareil définit les propriétés rapportées et les envoie à votre hub. Une application back-end peut lire les valeurs actuelles des propriétés rapportées à partir du jumeau d’appareil stocké dans votre hub.

Envoyer des propriétés rapportées depuis un appareil

Vous pouvez envoyer des mises à jour de propriétés rapportées sous la forme d’un correctif. L’extrait de code suivant montre un modèle de correctif envoyé par l’appareil simulé. L’appareil simulé met à jour les champs dans le correctif avant de l’envoyer au hub :

// Create a patch to send to the hub
var reportedPropertiesPatch = {
  firmwareVersion:'1.2.1',
  lastPatchReceivedId: '',
  fanOn:'',
  minTemperature:'',
  maxTemperature:''
};

L’appareil simulé utilise la fonction suivante pour envoyer le correctif contenant les propriétés rapportées au hub :

// Send the reported properties patch to the hub
function sendReportedProperties() {
  twin.properties.reported.update(reportedPropertiesPatch, function(err) {
    if (err) throw err;
    console.log(chalk.blue('\nTwin state reported'));
    console.log(JSON.stringify(reportedPropertiesPatch, null, 2));
  });
}

Traiter des propriétés rapportées

Une application back-end accède aux valeurs actuelles des propriétés rapportées d’un appareil via le jumeau d’appareil. L’extrait de code suivant montre comment l’application back-end lit les valeurs des propriétés rapportées pour l’appareil simulé :

// Display the reported properties from the device
function printReportedProperties(twin) {
  console.log("Last received patch: " + twin.properties.reported.lastPatchReceivedId);
  console.log("Firmware version: " + twin.properties.reported.firmwareVersion);
  console.log("Fan status: " + twin.properties.reported.fanOn);
  console.log("Min temperature set: " + twin.properties.reported.minTemperature);
  console.log("Max temperature set: " + twin.properties.reported.maxTemperature);
}

Exécution des applications

Dans cette section, vous allez exécuter deux exemples d’applications pour observer comment une application back-end envoie des mises à jour de propriétés souhaitées à une application d’appareil simulé.

Pour exécuter l’appareil simulé et les applications back-end, vous avez besoin des chaînes de connexion du service et de l’appareil. Vous avez noté ces chaînes de connexion lorsque vous avez créé les ressources au début de ce didacticiel.

Pour exécuter l’application d’appareil simulé, ouvrez une fenêtre d’interpréteur de commandes ou d’invite de commandes et accédez au dossier iot-hub/Tutorials/DeviceTwins dans le projet Node.js que vous avez téléchargé. Exécutez ensuite les commande suivantes :

npm install
node SimulatedDevice.js "{your device connection string}"

Pour exécuter l’application back-end, ouvrez une autre fenêtre d’interpréteur de commandes ou d’invite de commandes. Puis, accédez au dossier iot-hub/Tutorials/DeviceTwins dans le projet Node.js que vous avez téléchargé. Exécutez ensuite les commande suivantes :

npm install
node ServiceClient.js "{your service connection string}"

Observer les mises à jour des propriétés souhaitées

La capture d’écran suivante montre le résultat de l’application d’appareil simulé et comment celle-ci gère une mise à jour de la propriété souhaitée maxTemperature. Vous pouvez voir de quelle manière le gestionnaire de niveau supérieur et les gestionnaires du composant climat s’exécutent :

Screenshot that shows how both the top-level handler and the climate component handlers run.

La capture d’écran suivante montre le résultat de l’application back-end et comment celle-ci envoie une mise à jour de la propriété souhaitée maxTemperature :

Screenshot that shows the output from the back-end application and highlights how it sends an update.

Observer les mises à jour de propriétés signalées

La capture d’écran suivante montre le résultat de l’application d’appareil simulé et comment celle-ci envoie une mise à jour de propriété rapportée à votre hub :

Screenshot that shows the simulated device updating its twin state.

La capture d’écran suivante montre le résultat de l’application back-end et comment celle-ci reçoit et traite une mise à jour de propriété rapportée envoyée à partir d’un appareil :

Screenshot that shows the back-end application receiving the device reported properties.

Nettoyer les ressources

Si vous envisagez d’effectuer le didacticiel suivant, conservez le groupe de ressources et l’IoT Hub afin de les réutiliser ultérieurement.

Si vous n’avez plus besoin du hub IoT, supprimez-le ainsi que le groupe de ressources dans le portail. Pour ce faire, sélectionnez le groupe de ressources tutorial-iot-hub-rg qui contient votre hub IoT, puis sélectionnez Supprimer.

Vous pouvez également utiliser l’interface de ligne de commande :

# Delete your resource group and its contents
az group delete --name tutorial-iot-hub-rg

Étapes suivantes

Dans ce tutoriel vous avez appris à synchroniser les informations d’état entre vos appareils et votre hub IoT. Passez au tutoriel suivant pour découvrir comment utiliser des jumeaux d’appareil pour implémenter le processus de mise à jour d’appareil.