Connecter votre appareil Raspberry Pi à l’accélérateur de solution de supervision à distance (Node.js)

Dans ce tutoriel, vous allez implémenter un appareil Condenseur qui envoie les données de télémétrie ci-après à l’accélérateur de solution Monitoring à distance :

  • Température
  • Pression
  • Humidité

Par souci de simplicité, le code génère des exemples de valeurs de données de télémétrie pour le Condenseur. Vous pouviez étendre l’exemple en connectant des capteurs réels sur votre périphérique et envoyer les données de télémétrie réelles.

Le périphérique en exemple également :

  • Envoie des métadonnées à la solution pour décrire ses fonctionnalités.
  • Répond aux actions déclenchées à partir de la page Périphériques dans la solution.
  • Répond aux modifications de configuration envoyées à partir de la page Périphériques dans la solution.

Pour effectuer ce didacticiel, vous avez besoin d’un compte Azure actif. Si vous ne possédez pas de compte, vous pouvez créer un compte d’évaluation gratuit en quelques minutes. Pour plus d’informations, consultez Essai gratuit Azure.

Avant de commencer

Avant d’écrire du code pour votre appareil, déployez votre accélérateur de solution de supervision à distance, puis ajoutez un nouvel appareil réel à cette solution.

Déployer votre accélérateur de solution de supervision à distance

L’appareil Condenseur que vous créez dans le cadre de ce tutoriel envoie des données à une instance de l’accélérateur de solution Monitoring à distance. Si vous n’avez pas déjà provisionné l’accélérateur de solution de supervision à distance dans votre compte Azure, consultez Déployer l’accélérateur de solution de supervision à distance.

Au terme du processus de déploiement de la solution de supervision à distance, cliquez sur Lancer pour ouvrir le tableau de bord de la solution dans votre navigateur.

Tableau de bord de la solution

Ajouter votre appareil à la solution de supervision à distance

Notes

Si vous avez déjà ajouté un appareil dans votre solution, vous pouvez ignorer cette étape. Toutefois, l’étape suivante requiert la chaîne de connexion de votre appareil. Vous pouvez récupérer la chaîne de connexion d’un appareil à partir du portail Azure ou à l’aide de l’outil d’interface de ligne de commande (CLI) az iot.

Pour qu’un appareil puisse se connecter à l’accélérateur de solution, il doit s’identifier auprès d’IoT Hub à l’aide d’informations d’identification valides. Vous avez la possibilité d’enregistrer la chaîne de connexion de l’appareil qui contient ces informations d’identification lorsque vous ajoutez l’appareil à la solution. La chaîne de connexion de l’appareil sera ajoutée dans votre application cliente dans la suite de ce didacticiel.

Pour ajouter un appareil à votre solution de supervision à distance, procédez comme suit dans la page Explorateur d’appareils de la solution :

  1. Choisissez + Nouvel appareil, puis Réel comme Type d’appareil :

    Ajouter un appareil réel

  2. Entrez Physique-condenseur comme ID de périphérique. Choisissez les options Clé symétrique et Générer automatiquement des clés :

    Choisissez les options de périphérique

  3. Choisissez Appliquer. Notez quelque part les valeurs de l’ID de l’appareil, de la Clé primaire et de la Clé primaire de la chaîne de connexion :

    Récupérer les informations d’identification

Vous venez d’ajouter un appareil réel à l’accélérateur de solution de supervision à distance et de noter sa chaîne de connexion d’appareil. Dans les sections suivantes, vous allez implémenter l’application cliente qui utilise la chaîne de connexion de l’appareil pour se connecter à votre solution.

L’application cliente met en œuvre le modèle de périphérique Condenseur intégré. Un modèle d’appareil d’accélérateur de solution spécifie les éléments ci-après concernant un appareil :

  • Les propriétés que le périphérique signale à la solution. Par exemple, un périphérique Condenseur fournit des informations sur son microprogramme et son emplacement.
  • Les types de données de télémétrie envoyés par le périphérique à la solution. Par exemple, un périphérique Condenseur envoie des valeurs sur la température, l’humidité et la pression.
  • Les méthodes que vous pouvez planifier à partir de la solution pour s’exécuter sur le périphérique. Par exemple, un périphérique Condenseur doit mettre en œuvre des méthodes Redémarrer, FirmwareUpdate, EmergencyValveRelease et IncreasePressure.

Ce tutoriel vous montre comment connecter un appareil réel à l’accélérateur de solution de supervision à distance. Dans ce didacticiel, vous utilisez Node.js, qui est une bonne option pour les environnements avec des contraintes minimales en ressources.

Si vous préférez simuler un appareil, consultez Créer et tester un appareil simulé.

Matériel requis

Un ordinateur de bureau permettant de vous connecter à distance à la ligne de commande sur le Raspberry Pi.

Starter Kit Microsoft IoT pour Raspberry Pi 3 ou composants équivalents. Ce didacticiel utilise les éléments suivants du kit :

  • Raspberry Pi 3
  • Carte MicroSD (avec NOOBS)
  • Un câble mini USB
  • Un câble Ethernet

Logiciels de bureau requis

Vous devez installer le client SSH sur votre ordinateur de bureau afin de pouvoir accéder à distance à la ligne de commande sur le Raspberry Pi.

  • Windows n’inclut pas de client SSH. Nous vous recommandons d’utiliser PuTTY.
  • La plupart des distributions Linux et Mac OS incluent l’utilitaire de ligne de commande SSH. Pour plus d’informations, consultez SSH Using Linux or Mac OS (Utilisation de SSH avec Linux ou Mac OS).

Logiciels Raspberry Pi requis

Si ce n’est déjà fait, installez Node.js version 4.0.0 ou ultérieure sur votre appareil Raspberry Pi. Les étapes suivantes vous montrent comment installer Node.js v6 sur votre appareil Raspberry Pi :

  1. Connectez-vous à votre appareil Raspberry Pi avec ssh. Pour plus d’informations, consultez SSH (Secure Shell) sur le site web de Raspberry Pi.

  2. Pour mettre à jour votre Raspberry Pi, utilisez la commande suivante :

    sudo apt-get update
    
  3. Pour supprimer toute installation existante de Node.js de votre appareil Raspberry Pi, utilisez les commandes suivantes :

    sudo apt-get remove nodered -y
    sudo apt-get remove nodejs nodejs-legacy -y
    sudo apt-get remove npm  -y
    
  4. Pour télécharger et installer Node.js v6 sur votre appareil Raspberry Pi, utilisez la commande suivante :

    curl -sL https://deb.nodesource.com/setup_6.x | sudo bash -
    sudo apt-get install nodejs npm
    
  5. Pour vérifier que Node.js v6.11.4 a bien été installé, utilisez la commande suivante :

    node --version
    

Créer une solution Node.js

Effectuez les étapes suivantes en utilisant la connexion ssh à votre appareil Raspberry Pi :

  1. Créez un dossier appelé remotemonitoring dans votre dossier de base sur l’appareil Raspberry Pi. Accédez à ce dossier dans votre ligne de commande :

    cd ~
    mkdir remotemonitoring
    cd remotemonitoring
    
  2. Pour télécharger et installer les packages dont vous avez besoin pour accomplir l’exemple d’application, exécutez les commandes suivantes :

    npm install async azure-iot-device azure-iot-device-mqtt
    
  3. Dans le dossier remotemonitoring, créez un fichier nommé remote_monitoring.js. Ouvrez ce fichier dans un éditeur de texte. Sur l’appareil Raspberry Pi, vous pouvez utiliser l’éditeur de texte nano ou vi.

  4. Dans le fichier remote_monitoring.js, ajoutez les instructions require suivantes :

    var Protocol = require('azure-iot-device-mqtt').Mqtt;
    var Client = require('azure-iot-device').Client;
    var Message = require('azure-iot-device').Message;
    var async = require('async');
    
  5. Ajoutez les déclarations de variables suivantes après les instructions require . Remplacez la valeur d’espace réservé {device connection string} par la valeur que vous avez notée pour l’appareil provisionné dans la solution de supervision à distance :

    var connectionString = '{device connection string}';
    
  6. Pour définir des données de télémétrie de base, ajoutez les variables suivantes :

    var temperature = 50;
    var temperatureUnit = 'F';
    var humidity = 50;
    var humidityUnit = '%';
    var pressure = 55;
    var pressureUnit = 'psig';
    
  7. Pour définir des valeurs de propriété, ajoutez les variables suivantes :

    var schema = "real-chiller;v1";
    var deviceType = "RealChiller";
    var deviceFirmware = "1.0.0";
    var deviceFirmwareUpdateStatus = "";
    var deviceLocation = "Building 44";
    var deviceLatitude = 47.638928;
    var deviceLongitude = -122.13476;
    var deviceOnline = true;
    
  8. Ajoutez la variable suivante pour définir les propriétés déclarées à envoyer à la solution. Ces propriétés incluent les métadonnées à afficher dans l’interface utilisateur web :

    var reportedProperties = {
      "SupportedMethods": "Reboot,FirmwareUpdate,EmergencyValveRelease,IncreasePressure",
      "Telemetry": {
        [schema]: ""
      },
      "Type": deviceType,
      "Firmware": deviceFirmware,
      "FirmwareUpdateStatus": deviceFirmwareUpdateStatus,
      "Location": deviceLocation,
      "Latitude": deviceLatitude,
      "Longitude": deviceLongitude,
      "Online": deviceOnline
    }
    
  9. Pour imprimer les résultats de l’opération, ajoutez la fonction d’assistance suivante :

    function printErrorFor(op) {
        return function printError(err) {
            if (err) console.log(op + ' error: ' + err.toString());
        };
    }
    
  10. Ajoutez la fonction d’assistance suivante qui permet de rendre aléatoires les valeurs de télémétrie :

    function generateRandomIncrement() {
        return ((Math.random() * 2) - 1);
    }
    
  11. Ajoutez la fonction générique suivante pour gérer les appels de méthode directe à partir de la solution. La fonction affiche des informations sur la méthode directe appelée mais, dans cet exemple, ne modifie en aucune façon l’appareil. La solution utilise des méthodes directes pour agir sur les appareils :

    function onDirectMethod(request, response) {
      // Implement logic asynchronously here.
      console.log('Simulated ' + request.methodName);
    
      // Complete the response
      response.send(200, request.methodName + ' was called on the device', function (err) {
        if (err) console.error('Error sending method response :\n' + err.toString());
        else console.log('200 Response to method \'' + request.methodName + '\' sent successfully.');
      });
    }
    
  12. Ajoutez la fonction suivante pour gérer les appels de méthode directe FirmwareUpdate à partir de la solution. La fonction vérifie les paramètres passés dans la charge utile de la méthode directe, puis exécute de façon asynchrone une simulation de mise à jour du microprogramme :

    function onFirmwareUpdate(request, response) {
      // Get the requested firmware version from the JSON request body
      var firmwareVersion = request.payload.Firmware;
      var firmwareUri = request.payload.FirmwareUri;
    
      // Ensure we got a firmware values
      if (!firmwareVersion || !firmwareUri) {
        response.send(400, 'Missing firmware value', function(err) {
          if (err) console.error('Error sending method response :\n' + err.toString());
          else console.log('400 Response to method \'' + request.methodName + '\' sent successfully.');
        });
      } else {
        // Respond the cloud app for the device method
        response.send(200, 'Firmware update started.', function(err) {
          if (err) console.error('Error sending method response :\n' + err.toString());
          else {
            console.log('200 Response to method \'' + request.methodName + '\' sent successfully.');
    
            // Run the simulated firmware update flow
            runFirmwareUpdateFlow(firmwareVersion, firmwareUri);
          }
        });
      }
    }
    
  13. Ajoutez la fonction suivante pour simuler un flux de mise à jour de microprogramme long qui rend compte de la progression à la solution :

    // Simulated firmwareUpdate flow
    function runFirmwareUpdateFlow(firmwareVersion, firmwareUri) {
      console.log('Simulating firmware update flow...');
      console.log('> Firmware version passed: ' + firmwareVersion);
      console.log('> Firmware URI passed: ' + firmwareUri);
      async.waterfall([
        function (callback) {
          console.log("Image downloading from " + firmwareUri);
          var patch = {
            FirmwareUpdateStatus: 'Downloading image..'
          };
          reportUpdateThroughTwin(patch, callback);
          sleep(10000, callback);
        },
        function (callback) {
          console.log("Downloaded, applying firmware " + firmwareVersion);
          deviceOnline = false;
          var patch = {
            FirmwareUpdateStatus: 'Applying firmware..',
            Online: false
          };
          reportUpdateThroughTwin(patch, callback);
          sleep(8000, callback);
        },
        function (callback) {
          console.log("Rebooting");
          var patch = {
            FirmwareUpdateStatus: 'Rebooting..'
          };
          reportUpdateThroughTwin(patch, callback);
          sleep(10000, callback);
        },
        function (callback) {
          console.log("Firmware updated to " + firmwareVersion);
          deviceOnline = true;
          var patch = {
            FirmwareUpdateStatus: 'Firmware updated',
            Online: true,
            Firmware: firmwareVersion
          };
          reportUpdateThroughTwin(patch, callback);
          callback(null);
        }
      ], function(err) {
        if (err) {
          console.error('Error in simulated firmware update flow: ' + err.message);
        } else {
          console.log("Completed simulated firmware update flow");
        }
      });
    
      // Helper function to update the twin reported properties.
      function reportUpdateThroughTwin(patch, callback) {
        console.log("Sending...");
        console.log(JSON.stringify(patch, null, 2));
        client.getTwin(function(err, twin) {
          if (!err) {
            twin.properties.reported.update(patch, function(err) {
              if (err) callback(err);
            });      
          } else {
            if (err) callback(err);
          }
        });
      }
    
      function sleep(milliseconds, callback) {
        console.log("Simulate a delay (milleseconds): " + milliseconds);
        setTimeout(function () {
          callback(null);
        }, milliseconds);
      }
    }
    
  14. Ajoutez le code suivant pour envoyer les données de télémétrie à la solution. L’application cliente ajoute des propriétés au message pour identifier le schéma du message :

    function sendTelemetry(data, schema) {
      if (deviceOnline) {
        var d = new Date();
        var payload = JSON.stringify(data);
        var message = new Message(payload);
        message.properties.add('iothub-creation-time-utc', d.toISOString());
        message.properties.add('iothub-message-schema', schema);
    
        console.log('Sending device message data:\n' + payload);
        client.sendEvent(message, printErrorFor('send event'));
      } else {
        console.log('Offline, not sending telemetry');
      }
    }
    
  15. Ajoutez le code suivant pour créer une instance de client :

    var client = Client.fromConnectionString(connectionString, Protocol);
    
  16. Ajoutez le code suivant à :

    • Ouvrir la connexion.

    • Définir un gestionnaire pour les propriétés souhaitées.

    • Envoyer les propriétés signalées.

    • Inscrire des gestionnaires pour les méthodes directes. L’exemple utilise un gestionnaire distinct pour la méthode directe de mise à jour du microprogramme.

    • Démarrer l’envoi de la télémétrie.

      client.open(function (err) {
      if (err) {
        printErrorFor('open')(err);
      } else {
        // Create device Twin
        client.getTwin(function (err, twin) {
          if (err) {
            console.error('Could not get device twin');
          } else {
            console.log('Device twin created');
      
            twin.on('properties.desired', function (delta) {
              // Handle desired properties set by solution
              console.log('Received new desired properties:');
              console.log(JSON.stringify(delta));
            });
      
            // Send reported properties
            twin.properties.reported.update(reportedProperties, function (err) {
              if (err) throw err;
              console.log('Twin state reported');
            });
      
            // Register handlers for all the method names we are interested in.
            // Consider separate handlers for each method.
            client.onDeviceMethod('Reboot', onDirectMethod);
            client.onDeviceMethod('FirmwareUpdate', onFirmwareUpdate);
            client.onDeviceMethod('EmergencyValveRelease', onDirectMethod);
            client.onDeviceMethod('IncreasePressure', onDirectMethod);
          }
        });
      
        // Start sending telemetry
        var sendDeviceTelemetry = setInterval(function () {
          temperature += generateRandomIncrement();
          pressure += generateRandomIncrement();
          humidity += generateRandomIncrement();
          var data = {
            'temperature': temperature,
            'temperature_unit': temperatureUnit,
            'humidity': humidity,
            'humidity_unit': humidityUnit,
            'pressure': pressure,
            'pressure_unit': pressureUnit
          };
          sendTelemetry(data, schema)
        }, 5000);
      
        client.on('error', function (err) {
          printErrorFor('client')(err);
          if (sendTemperatureInterval) clearInterval(sendTemperatureInterval);
          if (sendHumidityInterval) clearInterval(sendHumidityInterval);
          if (sendPressureInterval) clearInterval(sendPressureInterval);
          client.close(printErrorFor('client.close'));
        });
      }
      });
      
  17. Enregistrez les modifications dans le fichier remote_monitoring.js.

  18. Pour démarrer l’exemple d’application, exécutez la commande suivante depuis l’invite de commande sur l’appareil Raspberry Pi :

    node remote_monitoring.js
    

Afficher la télémétrie d’appareil

Vous pouvez afficher les données de télémétrie envoyées à partir de votre périphérique sur la page Explorateur d’appareils dans la solution.

  1. Sélectionnez le périphérique que vous avez configuré dans la liste des périphériques sur la page Explorateur d’appareils. Un panneau affiche des informations sur votre périphérique, y compris un tracé de la télémétrie du périphérique :

    Consultez les détails du périphérique

  2. Choisissez Pression pour modifier l’affichage des données de télémétrie :

    Télémétrie les données de télémétrie de la pression

  3. Pour afficher les informations de diagnostic relatives à votre périphérique, faites défiler la liste jusqu'à Diagnostics :

    Afficher les diagnostics du périphérique

Agir sur votre périphérique

Pour appeler des méthodes sur vos appareils, utilisez la page Explorateur d’appareils dans la solution de supervision à distance. Par exemple, dans la solution de supervision à distance les périphériques Condenseur mettent en œuvre une méthode Redémarrer.

  1. Choisissez Appareils pour accéder à la page Explorateur d’appareils dans la solution.

  2. Sélectionnez le périphérique que vous avez configuré dans la liste des périphériques sur la page Explorateur d’appareils :

    Sélectionner votre appareil réel

  3. Pour afficher une liste des méthodes que vous pouvez appeler sur votre appareil, choisissez Travaux, puis Méthodes. Pour planifier un travail à exécuter sur plusieurs appareils, vous pouvez sélectionner plusieurs appareils dans la liste. Le volet Travaux affiche les types de méthodes communes à tous les appareils que vous avez sélectionnés.

  4. Choisissez Redémarrer, définissez le nom de la tâche RebootPhysicalChiller, puis choisissez Appliquer :

    Planifier la mise à jour du microprogramme

  5. Une série de messages s’affiche dans la console exécutant votre code de périphérique lorsque le périphérique simulé traite la méthode.

Notes

Pour suivre l’état de la tâche dans la solution, choisissez Afficher l’état de la tâche.

Étapes suivantes

L’article Personnaliser l’accélérateur de la solution de supervision à distance décrit quelques méthodes permettant de personnaliser l’accélérateur de solution.