Поделиться через


Подключение устройства Raspberry Pi к акселератору решения для удаленного мониторинга с помощью Node.js

В этом руководстве вы реализуете устройство Chiller, которое отправляет следующие данные телеметрии в акселератор решений для удаленного мониторинга:

  • температура;
  • Давление
  • влажность.

Чтобы упростить задачу, при помощи кода создаются примеры значений телеметрии для Chiller. Вы можете расширить пример, подключив к устройству физические датчики, которые будут отправлять реальные данные телеметрии.

Устройство в примере также:

  • отправляет в решение метаданные для описания его возможностей;
  • реагирует на действия, активированные на странице решения Устройства;
  • реагирует на изменения конфигурации, сведения о которых отправляются со страницы решения Устройства.

Для работы с этим руководством требуется активная учетная запись Azure. Если ее нет, можно создать бесплатную пробную учетную запись всего за несколько минут. Дополнительные сведения см. в разделе Бесплатная пробная версия Azure.

Перед началом работы

Прежде чем писать код для устройства, разверните акселератор решения для удаленного мониторинга и добавьте в решение новое реальное устройство.

Развертывание акселератора решения для удаленного мониторинга

Созданное в этом руководстве устройство Chiller отправляет данные в экземпляр акселератора решений для удаленного мониторинга. Если вы еще не подготовили этот акселератор решений в своей учетной записи Azure, изучите статью Развертывание акселератора решения для удаленного мониторинга.

После завершения развертывания решения для удаленного мониторинга нажмите кнопку Запустить, чтобы открыть панель мониторинга этого решения в браузере.

Панель мониторинга решения

Добавление устройства в решение для удаленного мониторинга

Примечание

Если вы уже добавили устройство в решение, пропустите этот шаг. Однако для следующего шага требуется строка подключения вашего устройства. Вы можете получить строку подключения устройства на портале Azure или с помощью средства CLI az iot.

Чтобы устройство смогло подключиться к акселератору решений, оно должно пройти идентификацию в Центре Интернета вещей с использованием допустимых учетных данных. При добавлении устройства в решение есть возможность сохранить строку подключения устройства, содержащую эти учетные данные. Вы добавите эту строку подключения в клиентское приложение далее в этом руководстве.

Чтобы добавить устройство в решение для удаленного мониторинга, выполните следующие действия на странице решения Обозреватель устройств:

  1. Щелкните + Новое устройство, а затем для параметра Тип устройства выберите значение Реальное:

    Добавление реального устройства

  2. Введите значение Physical-chiller в качестве идентификатора устройства. Выберите параметры Симметричный ключ и Автоматически создавать ключи:

    Выбор параметров устройства

  3. Нажмите кнопку Применить. Затем запишите значения параметров Идентификатор устройства, Первичный ключ и Строка подключения — первичный ключ:

    Получение учетных данных

Вы добавили реальное устройство в акселератор решения для удаленного мониторинга и записали его строку подключения. В следующих разделах реализуется клиентское приложение, которое использует строку подключения устройства для подключения к решению.

Клиентское приложение реализует встроенную модель устройства Chiller. Модель устройства с акселератором решений указывает следующие данные устройства:

  • Сведения о свойствах, которые устройство передает в решение. Например, устройство Chiller передает сведения о своей микропрограмме и расположении.
  • Сведения о типах данных телеметрии, которые устройство отправляет в решение. Например, устройство Chiller отправляет показатели температуры, влажности и давления.
  • Сведения о методах, запуск которых можно запланировать на устройстве при помощи решения. Например, устройство Chiller должно реализовать методы Reboot, FirmwareUpdate, EmergencyValveRelease и IncreasePressure.

В этом руководстве показано, как подключить реальное устройство к акселератору решения для удаленного мониторинга. В этом руководстве используется Node.js, поэтому оно подходит для сред с минимальными ограничениями ресурсов.

Если вы предпочитаете имитацию устройства, см. раздел Создание и тестирование нового имитированного устройства.

Необходимое оборудование

Настольный компьютер, чтобы иметь удаленный доступ к командной строке Raspberry Pi.

Начальный набор Microsoft IoT для Raspberry Pi 3 или эквивалентные компоненты. В этом руководстве используются следующие компоненты из набора:

  • Raspberry Pi 3;
  • карта MicroSD (с NOOBS);
  • кабель MiniUSB;
  • кабель Ethernet;

Необходимое ПО для настольного компьютера

На настольном компьютере необходимо установить клиент SSH, чтобы иметь удаленный доступ к командной строке Raspberry Pi.

  • Windows не предоставляет клиент SSH. Мы советуем использовать PuTTY.
  • Большинство дистрибутивов Linux и Mac OS содержат служебную программу командной строки SSH. Дополнительные сведения см. в статье SSH Using Linux or Mac OS (Подключение по протоколу SSH с помощью Linux или Mac OS).

Необходимое ПО для Raspberry Pi

Установите Node.js версии 4.0.0 или более поздней на устройстве Raspberry Pi, если вы этого еще не сделали. Ниже описывается установка Node.js версии 6 на устройстве Raspberry Pi.

  1. Подключитесь к Raspberry Pi с помощью ssh. Дополнительные сведения см. в разделе о SSH (Secure Shell) на веб-сайте Raspberry Pi.

  2. Чтобы обновить устройство Raspberry Pi, используйте следующую команду:

    sudo apt-get update
    
  3. Для удаления любой имеющейся установки Node.js со своего устройства Raspberry Pi используйте следующие команды:

    sudo apt-get remove nodered -y
    sudo apt-get remove nodejs nodejs-legacy -y
    sudo apt-get remove npm  -y
    
  4. Для скачивания и установки Node.js версии 6 на свое устройство Raspberry Pi используйте следующую команду:

    curl -sL https://deb.nodesource.com/setup_6.x | sudo bash -
    sudo apt-get install nodejs npm
    
  5. Чтобы убедиться в успешной установке Node.js версии 6.11.4, используйте следующую команду:

    node --version
    

Создание решения Node.js

Выполните следующие шаги, установив подключение по протоколу ssh к устройству Raspberry Pi.

  1. Создайте папку с именем remotemonitoring в домашней папке на Raspberry Pi. Перейдите к этой папке с помощью командной строки.

    cd ~
    mkdir remotemonitoring
    cd remotemonitoring
    
  2. Чтобы скачать и установить пакеты, необходимые для выполнения примера приложения, выполните следующие команды:

    npm install async azure-iot-device azure-iot-device-mqtt
    
  3. В папке remotemonitoring создайте файл с именем remote_monitoring.js. Откройте этот файл в текстовом редакторе. На устройстве Raspberry Pi можно использовать текстовый редактор nano или vi.

  4. Откройте файл remote-monitoring.js и добавьте следующие инструкции require:

    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. После операторов require добавьте указанные ниже объявления переменных. Замените значение заполнителя {device connection string} ранее записанным значением для своего устройства, подготовленного в решении для удаленного мониторинга:

    var connectionString = '{device connection string}';
    
  6. Чтобы определить базовые данные телеметрии, добавьте следующие переменные:

    var temperature = 50;
    var temperatureUnit = 'F';
    var humidity = 50;
    var humidityUnit = '%';
    var pressure = 55;
    var pressureUnit = 'psig';
    
  7. Чтобы определить некоторые значения свойств, добавьте следующие переменные:

    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. Добавьте следующую переменную, чтобы определить, какие передаваемые свойства должны отправляться в решение. Эти свойства содержат метаданные, отображаемые в пользовательском веб-интерфейсе.

    var reportedProperties = {
      "SupportedMethods": "Reboot,FirmwareUpdate,EmergencyValveRelease,IncreasePressure",
      "Telemetry": {
        [schema]: ""
      },
      "Type": deviceType,
      "Firmware": deviceFirmware,
      "FirmwareUpdateStatus": deviceFirmwareUpdateStatus,
      "Location": deviceLocation,
      "Latitude": deviceLatitude,
      "Longitude": deviceLongitude,
      "Online": deviceOnline
    }
    
  9. Добавьте следующую вспомогательную функцию для вывода результатов операции:

    function printErrorFor(op) {
        return function printError(err) {
            if (err) console.log(op + ' error: ' + err.toString());
        };
    }
    
  10. Добавьте следующую вспомогательную функцию для создания случайных значений телеметрии:

    function generateRandomIncrement() {
        return ((Math.random() * 2) - 1);
    }
    
  11. Добавьте приведенную ниже общую функцию для обработки вызовов прямого метода из решения. Функция отвечает за отображение сведений о вызванном прямом методе. В этом примере ее использование не приводит к каким-либо изменениям устройства. Решение использует прямые методы для выполнения действий на устройствах:

    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. Добавьте приведенную ниже функцию для обработки вызовов прямого метода FirmwareUpdate из решения. Функция отвечает за проверку параметров, переданных в полезные данные прямого метода, и асинхронный запуск моделирования для обновления встроенного ПО:

    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. Добавьте следующую функцию для моделирования длительного потока обновления встроенного ПО с передачей в решение сведений о ходе выполнения:

    // 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. Добавьте приведенный ниже код для отправки данных телеметрии в решение. Клиентское приложение добавляет свойства в сообщение, чтобы определить его схему:

    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. Добавьте следующий код для создания экземпляра клиента:

    var client = Client.fromConnectionString(connectionString, Protocol);
    
  16. Добавьте следующий код, который:

    • открывает подключение;

    • настраивает обработчик для требуемых свойств;

    • отправляет сообщаемые свойства;

    • регистрирует обработчики для прямых методов; В примере используется отдельный обработчик для прямого метода обновления встроенного ПО.

    • начинает отправку данных телеметрии.

      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. Сохраните изменения в файле remote_monitoring.js.

  18. Чтобы запустить пример приложения, выполните следующую команду в командной строке на устройстве Raspberry Pi:

    node remote_monitoring.js
    

Просмотр телеметрии устройства

Вы можете просмотреть данные телеметрии, отправленные с устройства, на странице Обозреватель устройств в решении.

  1. Выберите подготовленное устройство в списке устройств на странице Обозреватель устройств. На панели отображаются сведения об устройстве, включая график телеметрии устройства:

    Просмотр сведений об устройстве

  2. Выберите Pressure (Давление) для изменения порядка отображения телеметрии:

    Просмотр телеметрии по давлению

  3. Чтобы просмотреть диагностические сведения об устройстве, прокрутите вниз до раздела Diagnostics (Диагностика):

    Просмотр диагностики устройства

Действия на устройстве

Для вызова методов на устройствах используйте страницу Обозреватель устройств в решении для удаленного мониторинга. Например, в устройствах решения для удаленного мониторинга Chiller реализован метод перезагрузки.

  1. Выберите Устройства для перехода к странице Обозреватель устройств в решении.

  2. Выберите подготовленное устройство в списке устройств на странице Обозреватель устройств:

    Выбор реального устройства

  3. Чтобы отобразить список методов, которые можно вызвать на устройстве, выберите Задания > Методы. Чтобы запланировать выполнение задания на нескольких устройствах, можно выбрать несколько устройств в списке. На панели Jobs (Задания) отображаются типы метода, который является общим для всех выбранных устройств.

  4. Выберите Перезагрузка, задайте имя задания RebootPhysicalChiller и щелкните Применить:

    Планирование обновления встроенного ПО

  5. Когда имитированное устройство обрабатывает метод, в консоли отображается последовательность сообщений о выполнении кода устройства.

Примечание

Для отслеживания состояния задания в решении выберите Просмотреть состояние задания.

Дальнейшие действия

Способы настройки акселератора решений описаны в статье Настройка акселератора решения для удаленного мониторинга.