Руководство по Реализация обновления встроенного ПО устройстваTutorial: Implement a device firmware update process

Вам может потребоваться обновление встроенного ПО устройств, подключенных к Центру Интернета вещей.You may need to update the firmware on the devices connected to your IoT hub. Например, вы можете добавить новые функции во встроенное ПО или применить исправления безопасности.For example, you might want to add new features to the firmware or apply security patches. Во многих сценариях Интернета вещей нецелесообразно физически получать доступ, а затем вручную применять обновления встроенного ПО на устройствах.In many IoT scenarios, it's impractical to physically visit and then manually apply firmware updates to your devices. В этом руководстве показано, как можно удаленно запускать и контролировать процесс обновления встроенного ПО через внутреннее приложение, подключенное к центру.This tutorial shows how you can start and monitor the firmware update process remotely through a back-end application connected to your hub.

Чтобы создавать и отслеживать процесс обновления встроенного ПО, в рамках этого руководства внутреннее приложение создает конфигурацию в Центре Интернета вещей.To create and monitor the firmware update process, the back-end application in this tutorial creates a configuration in your IoT hub. Функция автоматического управление устройствами Центра Интернета вещей использует эту конфигурацию для обновления наборов требуемых свойств двойников устройств на всех устройствах chiller.IoT Hub automatic device management uses this configuration to update a set of device twin desired properties on all your chiller devices. В требуемых свойствах указаны подробности о требуемом обновлении встроенного ПО.The desired properties specify the details of the firmware update that's required. Во время выполнения процесса обновления встроенного ПО на устройствах chiller они сообщают о своем состоянии внутреннему приложению с помощью сообщаемых свойств двойников устройств.While the chiller devices are running the firmware update process, they report their status to the back-end application using device twin reported properties. Внутреннее приложение может использовать конфигурацию для отслеживания сообщаемых свойств, отправленных с устройства, и процесса обновления встроенного ПО:The back-end application can use the configuration to monitor the reported properties sent from the device and track the firmware update process to completion:

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

В этом руководстве выполняются следующие задачи:In this tutorial, you complete the following tasks:

  • создание Центра Интернета вещей и добавление тестового устройства в реестр удостоверений;Create an IoT hub and add a test device to the device identity registry.
  • создание конфигурации для определения обновлений встроенного ПО;Create a configuration to define the firmware update.
  • симуляция процесса обновления встроенного ПО на устройстве;Simulate the firmware update process on a device.
  • получение обновления состояния устройства в процессе обновления встроенного ПО.Receive status updates from the device as the firmware update progresses.

Открытие Azure Cloud ShellOpen Azure Cloud Shell

Azure Cloud Shell — это интерактивная оболочка среды, размещенная в Azure и работающая в браузере.Azure Cloud Shell is an interactive shell environment hosted in Azure and used through your browse. Azure Cloud Shell позволяет использовать оболочку bash или PowerShell, чтобы запускать разнообразные инструменты для работы со службами Azure.Azure Cloud Shell allows you to use either bash or PowerShell shells to run a variety of tools to work with Azure services. Azure Cloud Shell поставляется со встроенными командами, с помощью которых можно запускать код в данной статье, не устанавливая дополнительные компоненты в локальной среде.Azure Cloud Shell comes pre-installed with the commands to allow you to run the content of this article without having to install anything on your local environment.

Для выполнения кода из этой статьи в Azure Cloud Shell откройте сеанс Cloud Shell, скопируйте блок кода с помощью кнопки Копировать и вставьте его в сеанс Cloud Shell, нажав клавиши CTRL+SHIFT+V в Windows и Linux или CMD+SHIFT+V в macOS.To run any code contained in this article on Azure Cloud Shell, open a Cloud Shell session, use the Copy button on a code block to copy the code, and paste it into the Cloud Shell session with Ctrl+Shift+V on Windows and Linux, or Cmd+Shift+V on macOS. Вставленный текст не выполняется автоматически, поэтому нажмите клавишу ВВОД для выполнения кода.Pasted text is not automatically executed, so press Enter to run code.

Запустить Azure Cloud Shell можно следующим образом.You can launch Azure Cloud Shell with:

ПараметрOption Пример и ссылкаExample/Link
Нажмите кнопку Попробовать в правом верхнем углу блока с кодом.Select Try It in the upper-right corner of a code block. При этом не выполняется автоматическое копирование текста в Cloud Shell.This doesn't automatically copy text to Cloud Shell. Открытие Azure Cloud Shell с помощью кнопки "Попробовать"
Откройте Azure Cloud Shell в браузере.Open Azure Cloud Shell in your browser. <a href="https://shell.azure.com" title="Запуск Azure Cloud Shell
Нажмите кнопку меню Cloud Shell в правом верхнем углу окна портала Azure.Select the Cloud Shell button on the menu in the upper-right corner of the Azure portal. Кнопка "Cloud Shell" на портале Azure

Если у вас еще нет подписки Azure, создайте бесплатную учетную запись Azure, прежде чем начинать работу.If you don’t have an Azure subscription, create a free account before you begin.

Предварительные требованияPrerequisites

Примеры приложений, запускаемых в рамках этого краткого руководства, написаны на языке Node.js.The two sample applications you run in this quickstart are written using Node.js. Вам потребуется установить Node.js 10 x.x или более позднюю версию на компьютере для разработки.You need Node.js v10.x.x or later on your development machine.

Node.js, предназначенный для нескольких платформ, можно скачать здесь: nodejs.org.You can download Node.js for multiple platforms from nodejs.org.

Текущую версию Node.js на компьютере, на котором ведется разработка, можно проверить, используя следующую команду:You can verify the current version of Node.js on your development machine using the following command:

node --version

Скачайте пример проекта Node.js по адресу https://github.com/Azure-Samples/azure-iot-samples-node/archive/master.zip и извлеките ZIP-архив.Download the sample Node.js project from https://github.com/Azure-Samples/azure-iot-samples-node/archive/master.zip and extract the ZIP archive.

Настройка ресурсов AzureSet up Azure resources

Для выполнения задач из этого руководства в подписке Azure должен содержаться Центр Интернета вещей с устройством, добавленным в реестр удостоверений устройств.To complete this tutorial, your Azure subscription must have an IoT hub with a device added to the device identity registry. С помощью записи в реестре удостоверений устройств имитированное устройство, которое запускается в рамках этого руководства, подключается к центру.The entry in the device identity registry enables the simulated device you run in this tutorial to connect to your hub.

Если в вашей подписке еще не настроен Центр Интернета вещей, можно сделать это с помощью приведенного ниже скрипта CLI.If you don't already have an IoT hub set up in your subscription, you can set one up with following CLI script. В этом скрипте для Центра Интернета вещей используется имя tutorial-iot-hub. При запуске замените его своим уникальным именем.This script uses the name tutorial-iot-hub for the IoT hub, you should replace this name with your own unique name when you run it. С помощью скрипта создается группа ресурсов и центр в регионе Центральная часть США. Вы можете использовать регион, который находится ближе к вам.The script creates the resource group and hub in the Central US region, which you can change to a region closer to you. Скрипт получает строку подключения для службы Центра Интернета вещей. Эта строка используется в примере внутреннего приложения для подключения к Центру Интернета вещей:The script retrieves your IoT hub service connection string, which you use in the back-end sample application to connect to your IoT hub:

hubname=tutorial-iot-hub
location=centralus

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

# 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
az iot hub create --name $hubname --location $location --resource-group tutorial-iot-hub-rg --sku F1

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

В этом руководстве используется имитированное устройство с именем MyTwinDevice.This tutorial uses a simulated device called MyFirmwareUpdateDevice. С помощью следующего скрипта это устройство добавляется в реестр удостоверений, задает значение тега и извлекает строку подключения:The following script adds this device to your device identity registry, sets a tag value, and retrieves its connection string:

# Set the name of your IoT hub
hubname=tutorial-iot-hub

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

# Add a device type tag
az iot hub device-twin update --device-id MyFirmwareUpdateDevice --hub-name $hubname --set tags='{"devicetype":"chiller"}'

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

Совет

При запуске этих команд в командной строке Windows или Powershell ознакомьтесь со страницей azure-iot-cli-extension tips, чтобы получить сведения о том, как взять в кавычки строки JSON.If you run these commands at a Windows command prompt or Powershell prompt, see the azure-iot-cli-extension tips page for information about how to quote JSON strings.

Запуск обновления встроенного ПОStart the firmware update

Чтобы начать процесс обновления встроенного ПО на всех устройствах chiller с меткой devicetype, создайте в серверном приложении конфигурацию автоматического управления устройствами.You create an automatic device management configuration in the back-end application to begin the firmware update process on all devices tagged with a devicetype of chiller. Из этого раздела вы узнаете, как выполнять следующие действия:In this section, you see how to:

  • Создание конфигурации из внутреннего приложения.Create a configuration from a back-end application.
  • Мониторинг задания до его завершения.Monitor the job to completion.

Использование требуемых свойств для запуска обновления встроенного ПО с внутреннего приложенияUse desired properties to start the firmware upgrade from the back-end application

Чтобы просмотреть код внутреннего приложения, создающего конфигурацию, перейдите к папке iot-hub/Tutorials/FirmwareUpdate в скачанном примере проекта Node.js.To view the back-end application code that creates the configuration, navigate to the iot-hub/Tutorials/FirmwareUpdate folder in the sample Node.js project you downloaded. Затем в текстовом редакторе откройте файл ServiceClient.js.Then open the ServiceClient.js file in a text editor.

Внутреннее приложение создает следующую конфигурацию:The back-end application creates the following configuration:

var firmwareConfig = {
  id: sampleConfigId,
  content: {
    deviceContent: {
      'properties.desired.firmware': {
        fwVersion: fwVersion,
        fwPackageURI: fwPackageURI,
        fwPackageCheckValue: fwPackageCheckValue
      }
    }
  },

  // Maximum of 5 metrics per configuration
  metrics: {
    queries: {
      current: 'SELECT deviceId FROM devices WHERE configurations.[[firmware285]].status=\'Applied\' AND properties.reported.firmware.fwUpdateStatus=\'current\'',
      applying: 'SELECT deviceId FROM devices WHERE configurations.[[firmware285]].status=\'Applied\' AND ( properties.reported.firmware.fwUpdateStatus=\'downloading\' OR properties.reported.firmware.fwUpdateStatus=\'verifying\' OR properties.reported.firmware.fwUpdateStatus=\'applying\')',
      rebooting: 'SELECT deviceId FROM devices WHERE configurations.[[firmware285]].status=\'Applied\' AND properties.reported.firmware.fwUpdateStatus=\'rebooting\'',
      error: 'SELECT deviceId FROM devices WHERE configurations.[[firmware285]].status=\'Applied\' AND properties.reported.firmware.fwUpdateStatus=\'error\'',
      rolledback: 'SELECT deviceId FROM devices WHERE configurations.[[firmware285]].status=\'Applied\' AND properties.reported.firmware.fwUpdateStatus=\'rolledback\''
    }
  },

  // Specify the devices the firmware update applies to
  targetCondition: 'tags.devicetype = \'chiller\'',
  priority: 20
};

Конфигурация содержит следующие разделы:The configuration includes the following sections:

  • content указывает требуемые свойства встроенного ПО, отправляемые на выбранные устройства.content specifies the firmware desired properties sent to the selected devices.
  • metrics указывает выполняемые запросы, сообщающие о состоянии обновления встроенного ПО.metrics specifies the queries to run that report the status of the firmware update.
  • targetCondition выбирает устройства для получения обновления встроенного ПО.targetCondition selects the devices to receive the firmware update.
  • priorty задает приоритет этой конфигурации относительно других конфигураций.priorty sets the relative priority of this configuration to other configurations.

Внутреннее приложение использует следующий код для создания конфигурации, задающей требуемые свойства:The back-end application uses the following code to create the configuration to set the desired properties:

var createConfiguration = function(done) {
  console.log();
  console.log('Add new configuration with id ' + firmwareConfig.id + ' and priority ' + firmwareConfig.priority);

  registry.addConfiguration(firmwareConfig, function(err) {
    if (err) {
      console.log('Add configuration failed: ' + err);
      done();
    } else {
      console.log('Add configuration succeeded');
      done();
    }
  });
};

После создания конфигурации приложение будет отслеживать обновление встроенного ПО:After it creates the configuration, the application monitors the firmware update:

var monitorConfiguration = function(done) {
  console.log('Monitor metrics for configuration: ' + sampleConfigId);
  setInterval(function(){
    registry.getConfiguration(sampleConfigId, function(err, config) {
      if (err) {
        console.log('getConfiguration failed: ' + err);
      } else {
        console.log('System metrics:');
        console.log(JSON.stringify(config.systemMetrics.results, null, '  '));
        console.log('Custom metrics:');
        console.log(JSON.stringify(config.metrics.results, null, '  '));
      }
    });
  }, 20000);
  done();
};

Конфигурация сообщает о двух типах метрик:A configuration reports two types of metrics:

  • Системные метрики, которые сообщают, сколько устройств являются целевыми и на скольких устройствах было применено обновление.System metrics that report how many devices are targeted and how many devices have the update applied.
  • Настраиваемые метрики, создаваемые с помощью запросов, добавляемых в конфигурацию.Custom metrics generated by the queries you add to the configuration. В этом руководстве запросы сообщают о том, сколько устройств находятся на каждом шаге процесса обновления.In this tutorial, the queries report how many devices are at each stage of the update process.

Ответ на запрос обновления встроенного ПО на устройствеRespond to the firmware upgrade request on the device

Чтобы просмотреть код имитируемого устройства, который обрабатывает требуемые свойства встроенного ПО, отправленные из внутреннего приложения, перейдите к папке iot-hub/Tutorials/FirmwareUpdate в скачанном примере проекта Node.js.To view the simulated device code that handles the firmware desired properties sent from the back-end application, navigate to the iot-hub/Tutorials/FirmwareUpdate folder in the sample Node.js project you downloaded. Затем в текстовом редакторе откройте файл SimulatedDevice.js.Then open the SimulatedDevice.js file in a text editor.

Приложение имитированного устройства создает обработчик для обновлений требуемых свойств properties.desired.firmware в двойнике устройств.The simulated device application creates a handler for updates to the properties.desired.firmware desired properties in the device twin. В обработчике производятся некоторые базовые проверки требуемых свойств перед запуском процесса обновления:In the handler, it carries out some basic checks on the desired properties before launching the update process:

// Handle firmware desired property updates - this triggers the firmware update flow
twin.on('properties.desired.firmware', function(fwUpdateDesiredProperties) {
  console.log(chalk.green('\nCurrent firmware version: ' + twin.properties.reported.firmware.currentFwVersion));
  console.log(chalk.green('Starting firmware update flow using this data:'));
  console.log(JSON.stringify(fwUpdateDesiredProperties, null, 2));
  desiredFirmwareProperties = twin.properties.desired.firmware;

  if (fwUpdateDesiredProperties.fwVersion == twin.properties.reported.firmware.currentFwVersion) {
    sendStatusUpdate('current', 'Firmware already up to date', function (err) {
      if (err) {
        console.error(chalk.red('Error occured sending status update : ' + err.message));
      }
      return;
    });
  }
  if (fwUpdateInProgress) {
    sendStatusUpdate('current', 'Firmware update already running', function (err) {
      if (err) {
        console.error(chalk.red('Error occured sending status update : ' + err.message));
      }
      return;
    });
  }
  if (!fwUpdateDesiredProperties.fwPackageURI.startsWith('https')) {
    sendStatusUpdate('error', 'Insecure package URI', function (err) {
      if (err) {
        console.error(chalk.red('Error occured sending status update : ' + err.message));
      }
      return;
    });
  }

  fwUpdateInProgress = true;

  sendStartingUpdate(fwUpdateDesiredProperties.fwVersion, function (err) {
    if (err) {
      console.error(chalk.red('Error occured sending starting update : ' + err.message));
    }
    return;
  });
  initiateFirmwareUpdateFlow(function(err, result) {
    fwUpdateInProgress = false;
    if (!err) {
      console.log(chalk.green('Completed firmwareUpdate flow. New version: ' + result));
      sendFinishedUpdate(result, function (err) {
        if (err) {
          console.error(chalk.red('Error occured sending finished update : ' + err.message));
        }
        return;
      });
    }
  }, twin.properties.reported.firmware.currentFwVersion);
});

Обновление встроенного ПОUpdate the firmware

Функция initiateFirmwareUpdateFlow выполняет обновление.The initiateFirmwareUpdateFlow function runs the update. Эта функция использует функцию waterfall для последовательного выполнения этапов процесса обновления.This function uses the waterfall function to run the phases of the update process in sequence. В этом примере обновление встроенного ПО состоит из четырех этапов.In this example, the firmware update has four phases. На первом этапе скачивается образ, на втором этапе происходит его проверка с помощью контрольной суммы, на третьем этапе образ применяется, а на последнем выполняется перезагрузка устройства:The first phase downloads the image, the second phase verifies the image using a checksum, the third phase applies the image, and the last phase reboots the device:

// Implementation of firmwareUpdate flow
function initiateFirmwareUpdateFlow(callback, currentVersion) {

  async.waterfall([
    downloadImage,
    verifyImage,
    applyImage,
    reboot
  ], function(err, result) {
    if (err) {
      console.error(chalk.red('Error occured firmwareUpdate flow : ' + err.message));
      sendStatusUpdate('error', err.message, function (err) {
        if (err) {
          console.error(chalk.red('Error occured sending status update : ' + err.message));
        }
      });
      setTimeout(function() {
        console.log('Simulate rolling back update due to error');
        sendStatusUpdate('rolledback', 'Rolled back to: ' + currentVersion, function (err) {
          if (err) {
            console.error(chalk.red('Error occured sending status update : ' + err.message));
          }
        });
        callback(err, result);
      }, 5000);
    } else {
      callback(null, result);
    }
  });
}

Во время процесса обновления имитируемое устройство сообщает о ходе выполнения с помощью сообщаемых свойств:During the update process, the simulated device reports on progress using reported properties:

// Firmware update patch
//  currentFwVersion: The firmware version currently running on the device.
//  pendingFwVersion: The next version to update to, should match what's
//                    specified in the desired properties. Blank if there
//                    is no pending update (fwUpdateStatus is 'current').
//  fwUpdateStatus:   Defines the progress of the update so that it can be
//                    categorized from a summary view. One of:
//     - current:     There is no pending firmware update. currentFwVersion should
//                    match fwVersion from desired properties.
//     - downloading: Firmware update image is downloading.
//     - verifying:   Verifying image file checksum and any other validations.
//     - applying:    Update to the new image file is in progress.
//     - rebooting:   Device is rebooting as part of update process.
//     - error:       An error occurred during the update process. Additional details
//                    should be specified in fwUpdateSubstatus.
//     - rolledback:  Update rolled back to the previous version due to an error.
//  fwUpdateSubstatus: Any additional detail for the fwUpdateStatus . May include
//                     reasons for error or rollback states, or download %.
//
// var twinPatchFirmwareUpdate = {
//   firmware: {
//     currentFwVersion: '1.0.0',
//     pendingFwVersion: '',
//     fwUpdateStatus: 'current',
//     fwUpdateSubstatus: '',
//     lastFwUpdateStartTime: '',
//     lastFwUpdateEndTime: ''
//   }
// };

В следующем фрагменте кода показана реализация этапа скачивания.The following snippet shows the implementation of the download phase. Во время этапа скачивания имитируемое устройство использует переданные свойства для отправки информации о состоянии во внутреннее приложение:During the download phase, the simulated device uses reported properties to send status information to the back-end application:

// Simulate downloading an image
function downloadImage(callback) {
  console.log('Simulating image download from: ' + desiredFirmwareProperties.fwPackageURI);

  async.waterfall([
    function(callback) {
      sendStatusUpdate('downloading', 'Start downloading', function (err) {
        if (err) {
          console.error(chalk.red('Error occured sending status update : ' + err.message));
        }
      });
      callback(null);
    },
    function(callback) {
      // Simulate a delay downloading the image.
      setTimeout(function() {
        // Simulate some firmware image data
        var imageData = '[Fake firmware image data]';
        callback(null, imageData); 
      }, 30000);
    },
    function(imageData, callback) {
      console.log('Downloaded image data: ' + imageData);
      sendStatusUpdate('downloading', 'Finished downloading', function (err) {
        if (err) {
          console.error(chalk.red('Error occured sending status update : ' + err.message));
        }
      });
      callback(null, imageData);
    }
  ], function (err, result) {
    callback(err, result);
  });
}

Запуск примераRun the sample

В этом разделе вы запускаете два примера приложений для наблюдения за тем, как внутреннее приложение создает конфигурацию для управления процессом обновления встроенного ПО на имитируемом устройстве.In this section, you run two sample applications to observe as a back-end application creates the configuration to manage the firmware update process on the simulated device.

Чтобы запустить имитированное устройство и внутренние приложения, нужны строки подключения для устройства и службы.To run the simulated device and back-end applications, you need the device and service connection strings. Вы записали строки подключения при создании ресурсов в начале работы с этим руководством.You made a note of the connection strings when you created the resources at the start of this tutorial.

Чтобы запустить приложение имитированного устройства, откройте окно оболочки или командной строки и перейдите к папке iot-hub/Tutorials/FirmwareUpdate в скачанном проекте Node.js.To run the simulated device application, open a shell or command prompt window and navigate to the iot-hub/Tutorials/FirmwareUpdate folder in the Node.js project you downloaded. Затем выполните следующие команды:Then run the following commands:

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

Чтобы запустить внутреннее приложение, откройте еще одно окно оболочки или командной строки.To run the back-end application, open another shell or command prompt window. Затем перейдите к папке iot-hub/Tutorials/FirmwareUpdate в скачанном проекте Node.js.Then navigate to the iot-hub/Tutorials/FirmwareUpdate folder in the Node.js project you downloaded. Затем выполните следующие команды:Then run the following commands:

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

На следующем снимке экрана отображаются выходные данные приложения имитированного устройства и показано, как оно реагирует на обновление требуемых свойств встроенного ПО из встроенного приложения:The following screenshot shows the output from the simulated device application and shows how it responds to the firmware desired properties update from the back-end application:

Виртуальное устройство

На следующем снимке экрана отображаются выходные данные внутреннего приложения и показано, как создается конфигурация для обновления требуемых свойств встроенного ПО:The following screenshot shows the output from the back-end application and highlights how it creates the configuration to update the firmware desired properties:

Внутреннее приложение

На следующем снимке экрана отображаются выходные данные внутреннего приложения и показано, как отслеживаются метрики обновления встроенного ПО с имитированного устройства:The following screenshot shows the output from the back-end application and highlights how it monitors the firmware update metrics from the simulated device:

Внутреннее приложение

Из-за задержки в реестре удостоверений устройства Центра Интернета вещей вы можете не видеть каждое обновление состояния, отправленное во внутреннее приложение.Because of latency in the IoT Hub device identity registry, you may not see every status update sent to the back-end application. Метрики также можно просмотреть на портале в разделе Automatic device management (Автоматическое управление устройствами) -> IoT device configuration (Конфигурация устройства Интернета вещей) Центра Интернета вещей:You can also view the metrics in the portal in the Automatic device management -> IoT device configuration section of your IoT hub:

Просмотр конфигурации на портале

Очистка ресурсовClean up resources

Не удаляйте группу ресурсов и Центр Интернета вещей, так как они понадобятся вам при работе со следующим руководством.If you plan to complete the next tutorial, leave the resource group and IoT hub and reuse them later.

Если вам больше не требуется Центр Интернета вещей, удалите его и группу ресурсов на портале.If you don't need the IoT hub any longer, delete it and the resource group in the portal. Для этого выберите группу ресурсов tutorial-iot-hub-rg, содержащую Центр Интернета вещей, и щелкните Удалить.To do so, select the tutorial-iot-hub-rg resource group that contains your IoT hub and click Delete.

Или используйте CLI:Alternatively, use the CLI:

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

Дополнительная информацияNext steps

В этом руководстве вы узнали, как реализовать процесс обновления встроенного ПО для подключенных устройств.In this tutorial, you learned how to implement a firmware update process for your connected devices. Перейдите к следующему руководству, чтобы узнать, как применять инструменты на портале Центра Интернета вещей Azure и команды Azure CLI для проверки возможности подключения устройств.Advance to the next tutorial to learn how to use Azure IoT Hub portal tools and Azure CLI commands to test device connectivity.