Руководство по Настройка устройств из внутренней службы

Кроме получения данных телеметрии с устройств, вам, возможно, потребуется настроить устройства из внутренней службы. При отправке требуемой конфигурации на устройства вам могут понадобиться обновления состояния и соответствия с этих устройств. Например, вы можете задать целевой рабочий диапазон температур для устройства или получить сведения о версии встроенного ПО устройства.

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

Twin summary

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

  • создание Центра Интернета вещей и добавление тестового устройства в реестр удостоверений;
  • отправка сведений о состоянии на имитированное устройство с помощью требуемых свойств;
  • получение сведений о состоянии с имитированного устройства с помощью передаваемых свойств.

Если у вас еще нет подписки Azure, создайте бесплатную учетную запись, прежде чем начинать работу.

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

  • Используйте среду Bash в Azure Cloud Shell.

    Launch Cloud Shell in a new window

  • При необходимости установите Azure CLI, чтобы выполнять справочные команды CLI.

    • Если вы используете локальную установку, выполните вход в Azure CLI с помощью команды az login. Чтобы выполнить аутентификацию, следуйте инструкциям в окне терминала. Сведения о дополнительных возможностях, доступных при входе, см. в статье Вход с помощью Azure CLI.

    • Если появится запрос, установите расширения Azure CLI при первом использовании. Дополнительные сведения о расширениях см. в статье Использование расширений с Azure CLI.

    • Выполните команду az version, чтобы узнать установленную версию и зависимые библиотеки. Чтобы обновиться до последней версии, выполните команду az upgrade.

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

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

Текущую версию Node.js на компьютере, на котором ведется разработка, можно проверить, используя следующую команду:

node --version

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

Убедитесь, что в брандмауэре открыт порт 8883. Пример устройства в этом руководстве использует протокол MQTT, который передает данные через порт 8883. В некоторых корпоративных и академических сетях этот порт может быть заблокирован. Дополнительные сведения и способы устранения этой проблемы см. в разделе о подключении к Центру Интернета вещей по протоколу MQTT.

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

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

Если в вашей подписке еще не настроен Центр Интернета вещей, можно сделать это с помощью приведенного ниже скрипта CLI. В этом скрипте для Центра Интернета вещей используется имя tutorial-iot-hub. При запуске замените его своим уникальным именем. С помощью скрипта создается группа ресурсов и центр в регионе Центральная часть США. Вы можете использовать регион, который находится ближе к вам. Скрипт получает строку подключения для службы Центра Интернета вещей. Эта строка используется в примере внутреннего приложения для подключения к Центру Интернета вещей:

hubname=tutorial-iot-hub
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.
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 --name $hubname --policy-name service -o table

В этом руководстве используется имитированное устройство с именем MyTwinDevice. С помощью следующего скрипта это устройство добавляется в реестр удостоверений и извлекается строка подключения:

# 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 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

Отправка сведений о состоянии

Для отправки сведений о состоянии из внутреннего приложения на устройство используются требуемые свойства. Из этого раздела вы узнаете, как выполнять следующие действия:

  • получать и обрабатывать требуемые свойства на устройстве;
  • отправлять требуемые свойства из внутреннего приложения.

Чтобы просмотреть пример кода имитированного устройства для получения требуемых свойств, перейдите к папке iot-hub/Tutorials/DeviceTwins в скачанном примере проекта Node.js. Затем в текстовом редакторе откройте файл SimulatedDevice.js.

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

Получение объекта двойника устройства

Следующий код позволяет подключиться к Центру Интернета вещей с помощью строки подключения устройства:

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

С помощью следующего кода из объекта клиента извлекается двойник:

// 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'));

Пример требуемых свойств

Вы можете структурировать требуемые свойства любым подходящим для вашего приложения способом. В этом примере используется одно свойство верхнего уровня с именем fanOn. Остальные свойства группируются в отдельные компоненты. В следующем фрагменте JSON показана структура требуемых свойств, которая используется в этом руководстве. Фрагмент JSON содержится в файле desired.json.

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

Создание обработчиков

Для обновления требуемых свойств можно создавать обработчики, которые реагируют на такие обновления на разных уровнях иерархии JSON. Например, представленный ниже обработчик распознает все изменения требуемых свойств, отправленные на устройство из внутреннего приложения. Переменная delta содержит требуемые свойства, отправленные из серверной части решения:

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

Следующий обработчик реагирует только на изменения, внесенные в требуемое свойство 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}';
});

Обработчики для нескольких свойств

В приведенном ранее примере JSON для требуемых свойств узел climate в разделе components содержит два свойства — minTemperature и maxTemperature.

В локальном объекте устройства twin хранится полный набор требуемых и передаваемых свойств. С помощью переменной delta, отправленной из серверной части, можно обновить только подмножество требуемых свойств. В следующем фрагменте кода, если имитированное устройство получает обновление только для одного из свойств (minTemperature или maxTemperature), при настройке устройства для другого свойства используется значение с локального двойника:

// 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();
    }
});

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

Обработка операций вставки, обновления и удаления

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

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

// 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];
        }
      }
    });
  }
});

Отправка требуемых свойств на устройство из внутреннего приложения

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

Чтобы просмотреть пример кода имитированного устройства для получения требуемых свойств, перейдите к папке iot-hub/Tutorials/DeviceTwins в скачанном примере проекта Node.js. Затем в текстовом редакторе откройте файл ServiceClient.js.

В следующем фрагменте кода показано, как подключиться к реестру удостоверений устройства и получать доступ к двойнику конкретного устройства:

// 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');

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

// 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
      }
    }
  }
};

В следующем фрагменте кода показано, как внутреннее приложение отправляет обновление требуемого свойства на устройство:

// 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));
    }
  });
}

Запуск приложений

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

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

Чтобы запустить приложение имитированного устройства, откройте окно оболочки или командной строки и перейдите к папке iot-hub/Tutorials/DeviceTwins в скачанном проекте Node.js. Затем выполните следующие команды:

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

Чтобы запустить внутреннее приложение, откройте еще одно окно оболочки или командной строки. Затем перейдите к папке iot-hub/Tutorials/DeviceTwins в скачанном проекте Node.js. Затем выполните следующие команды:

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

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

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

На следующем снимке экрана отображаются выходные данные внутреннего приложения и показано, как отправляется обновление требуемого свойства maxTemperature:

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

Получение сведений о состоянии

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

Отправка передаваемых свойств с устройства

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

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

Имитированное устройство использует следующую функцию для отправки в центр исправлений, которые содержат передаваемые свойства:

// 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));
  });
}

Обработка передаваемых свойств

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

// 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);
}

Запуск приложений

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

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

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

Чтобы запустить приложение имитированного устройства, откройте окно оболочки или командной строки и перейдите к папке iot-hub/Tutorials/DeviceTwins в скачанном проекте Node.js. Затем выполните следующие команды:

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

Чтобы запустить внутреннее приложение, откройте еще одно окно оболочки или командной строки. Затем перейдите к папке iot-hub/Tutorials/DeviceTwins в скачанном проекте Node.js. Затем выполните следующие команды:

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

На следующем снимке экрана отображаются выходные данные приложения имитированного устройства и показано, как оно отправляет обновление передаваемого свойства в центр:

Simulated device

На следующем снимке экрана отображаются выходные данные внутреннего приложения и показано, как оно принимает и обрабатывает обновление передаваемого свойства, полученное с устройства:

Back-end application

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

Не удаляйте группу ресурсов и Центр Интернета вещей, так как они понадобятся вам при работе со следующим руководством.

Если вам больше не требуется Центр Интернета вещей, удалите его и группу ресурсов на портале. Для этого выберите группу ресурсов tutorial-iot-hub-rg, содержащую Центр Интернета вещей, и щелкните Удалить.

Или используйте CLI:

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

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

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