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

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

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

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

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

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

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

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

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

Необходимые компоненты

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

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

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

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

      node --version
      
  • Клонируйте или скачайте пример проекта Node.js из примеров Интернета вещей Azure для Node.js.

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

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

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

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

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

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

# 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

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

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

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

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

Вы можете структурировать требуемые свойства любым подходящим для вашего приложения способом. В этом примере используется одно свойство верхнего уровня с именем 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"
    }
  }
}

Получение требуемых свойств в приложении устройства

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

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

Для обновления требуемых свойств можно создавать обработчики, которые реагируют на такие обновления на разных уровнях иерархии 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 для этого руководства узел климата в компонентах содержит два свойства, 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();
    }
});

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

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

В приведенном ниже фрагменте кода показано, как имитированное устройство обрабатывает операции вставки, обновления и удаления в списке 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));
    }
  });
}

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

Внутреннее приложение получает сведения о состоянии с устройства как передаваемые свойства. Устройство задает передаваемые свойства и отправляет их в центр. Внутреннее приложение может считывать текущие значения передаваемых свойств 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}"

Наблюдение за обновлениями требуемого свойства

На следующем снимке экрана отображаются выходные данные приложения имитированного устройства и показано, как обрабатывается обновление требуемого свойства 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.

Наблюдение за обновлениями сообщаемого свойства

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

Screenshot that shows the simulated device updating its twin state.

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

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

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

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

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

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

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

Следующие шаги

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