Подключение устройства к предварительно настроенному решению для удаленного мониторинга (Windows)
Общие сведения о сценарии
В этом примере создается устройство, которое отправляет следующие данные телеметрии в предварительно настроенное решение для удаленного мониторинга:
- наружная температура;
- внутренняя температура;
- влажность.
В целях упрощения код на устройстве генерирует образцы значений, но мы рекомендуем расширить пример и подключить к устройству реальные датчики и отправить реальные данные телеметрии.
Устройство также может отвечать на методы, вызываемые из панели мониторинга решения, и значения требуемых свойств, заданные на панели мониторинга решения.
Для работы с этим руководством требуется активная учетная запись Azure. Если ее нет, можно создать бесплатную пробную учетную запись всего за несколько минут. Дополнительные сведения см. в разделе Бесплатная пробная версия Azure.
Перед началом работы
До написания кода для устройства необходимо подготовить свое предварительно настроенное решение для удаленного мониторинга, а затем подготовить в нем новое пользовательское устройство.
Подготовка предварительно настроенного решения для удаленного мониторинга
Созданное в этом руководстве устройство отправляет данные в экземпляр предварительно настроенного решения для удаленного мониторинга. Если вы еще не подготовили это решение в своей учетной записи Azure, то выполните следующие действия:
- Чтобы создать решение, на странице https://www.azureiotsolutions.com/ щелкните +.
- На панели Удаленный мониторинг щелкните Выбрать.
- На странице Create Remote monitoring solution (Создание решения для удаленного мониторинга) введите имя решения по своему усмотрению, выберите регион для развертывания и подписку Azure, которую нужно использовать. Затем щелкните Создать решение.
- Дождитесь завершения процесса подготовки.
Предупреждение
В предварительно настроенных решениях используются платные службы Azure. Закончив работу с предварительно настроенным решением, не забудьте удалить его из подписки, чтобы избежать ненужных расходов. На странице https://www.azureiotsolutions.com/ можно полностью удалить предварительно настроенное решение из подписки.
После завершения подготовки решения для удаленного мониторинга щелкните Запустить , чтобы открыть панель мониторинга этого решения в браузере.
Подготовка устройства в решении для удаленного мониторинга
Примечание
Если вы уже подготовили устройство в решении, пропустите этот шаг. При создании клиентского приложения необходимо знать учетные данные устройства.
Чтобы устройство смогло подключиться к предварительно настроенному решению, оно должно пройти идентификацию в Центре Интернета вещей с использованием допустимых учетных данных. Учетные данные устройства можно получить на панели мониторинга решения. Вы добавите их в клиентское приложение далее в этом учебнике.
Чтобы добавить устройство в решение для удаленного мониторинга, выполните следующие действия на панели мониторинга решения:
В левом нижнем углу панели мониторинга щелкните Добавить устройство.
На панели Пользовательское устройство нажмите кнопку Добавить.
Установите переключатель Позвольте мне определить собственный идентификатор устройства. Введите идентификатор устройства, например mydevice, и нажмите кнопку Проверить идентификатор, чтобы убедиться, что такое имя не используется. Затем нажмите кнопку Создать, чтобы подготовить устройство.
Запишите учетные данные (идентификатор устройства, имя узла в Центре Интернета вещей и ключ устройства). Эти значения потребуются клиентскому приложению при подключении к решению для удаленного мониторинга. Затем нажмите кнопку Done(Готово).
Выберите устройство в списке устройств на панели мониторинга решения. Затем на панели Сведения об устройстве щелкните Включить устройство. Теперь текущее состояние устройства — Работает. Решение для удаленного мониторинга теперь может получать данные телеметрии с устройства и вызывать методы на устройстве.
Создание примера решения на C в Windows
Описанные ниже действия показывают, как создать клиентское приложение, которое взаимодействует с предварительно настроенным решением для удаленного мониторинга. Это приложение на языке C, созданное и запущенное на устройстве Windows.
Создайте начальный проект в Visual Studio 2015 или Visual Studio 2017 и добавьте клиентские пакеты NuGet для устройства Центра Интернета вещей:
В Visual Studio создайте консольное приложение C, используя шаблон консольного приложения Win32 в Visual C++. Присвойте проекту имя RMDevice.
На странице Параметры приложения в мастере приложений Win32 необходимо установить флажок Консольное приложение и снять флажки Предкомпилированный заголовок и Жизненный цикл разработки безопасного ПО (SDL).
В обозревателе решенийудалите файлы stdafx.h, targetver.h и stdafx.cpp.
В обозревателе решенийпереименуйте файл RMDevice.cpp в RMDevice.c.
В обозревателе решений щелкните проект RMDevice правой кнопкой мыши и выберите пункт Управление пакетами NuGet. Щелкните Обзор, а затем найдите и установите следующие пакеты NuGet:
- Microsoft.Azure.IoTHub.Serializer
- Microsoft.Azure.IoTHub.IoTHubClient
- Microsoft.Azure.IoTHub.MqttTransport.
В обозревателе решений щелкните правой кнопкой мыши проект RMDevice, а затем щелкните Свойства, чтобы открыть диалоговое окно Страницы свойств проекта. Дополнительные сведения см. в статье, посвященной настройке свойств проекта Visual C++.
Выберите папку Компоновщик, затем щелкните страницу свойств Входные данные.
В свойство Дополнительные зависимости добавьте crypt32.lib. Нажмите кнопку ОК, а затем еще раз ОК, чтобы сохранить значения свойств проекта.
Добавьте библиотеку JSON Parson в проект RMDevice и добавьте обязательные инструкции #include
:
В подходящей папке на компьютере клонируйте репозиторий GitHub для Parson, используя следующую команду:
git clone https://github.com/kgabis/parson.git
Скопируйте файлы parson.h и parson.c из локальной копии репозитория Parson в папку проекта RMDevice.
В Visual Studio щелкните правой кнопкой мыши проект RMDevice, а затем выберите Добавить > Существующий элемент.
В диалоговом окне Добавление существующего элемента выберите файлы parson.h и parson.c в папке проекта RMDevice. Нажмите кнопку Добавить, чтобы добавить эти файлы в проект.
В Visual Studio откройте файл RMDevice.c. Замените имеющиеся инструкции
#include
в этом окне следующим кодом.#include "iothubtransportmqtt.h" #include "schemalib.h" #include "iothub_client.h" #include "serializer_devicetwin.h" #include "schemaserializer.h" #include "azure_c_shared_utility/threadapi.h" #include "azure_c_shared_utility/platform.h" #include "parson.h"
Примечание
Теперь вы можете создать проект, чтобы убедиться, что в нем настроены правильные зависимости.
Определение поведения устройства Интернета вещей
Клиентская библиотека сериализатора Центра Интернета вещей использует модель для указания формата сообщений, которыми устройство обменивается с Центром Интернета вещей.
После операторов
#include
добавьте указанные ниже объявления переменных. Замените значения заполнителей [Device ID] и [Device Key] ранее записанными значениями для своего устройства, отображенными на панели мониторинга решения для удаленного мониторинга. Замените [IoTHub Name] именем узла Центра Интернета вещей, отображенным на панели мониторинга решения. Например, если имя узла Центра Интернета вещей — contoso.azure-devices.net, замените [имя_Центра_Интернета_вещей] на contoso.static const char* deviceId = "[Device Id]"; static const char* connectionString = "HostName=[IoTHub Name].azure-devices.net;DeviceId=[Device Id];SharedAccessKey=[Device Key]";
Добавьте указанный ниже код для определения модели, позволяющей устройству взаимодействовать с Центром Интернета вещей. Эта модель указывает, что устройство может выполнять следующие действия:
- Передавать температуру, температуру окружающей среды, влажность и идентификатор устройства в виде телеметрических данных.
- Отправлять метаданные об устройстве в Центр Интернета вещей. При запуске устройство отправляет базовые метаданные в объекте DeviceInfo.
- Отправлять сообщаемые свойства на двойник устройства в Центре Интернета вещей. Эти сообщаемые свойства объединены в группы: конфигурация, устройство и системные свойства.
- Получать требуемые свойства, заданные в двойнике устройства в Центре Интернета вещей, и реагировать на них.
- Отвечать на прямые методы Reboot и InitiateFirmwareUpdate, вызываемые через портал решения. Устройство отправляет сведения о прямых методах, которые оно поддерживает, с помощью сообщаемых свойств.
// Define the Model BEGIN_NAMESPACE(Contoso); /* Reported properties */ DECLARE_STRUCT(SystemProperties, ascii_char_ptr, Manufacturer, ascii_char_ptr, FirmwareVersion, ascii_char_ptr, InstalledRAM, ascii_char_ptr, ModelNumber, ascii_char_ptr, Platform, ascii_char_ptr, Processor, ascii_char_ptr, SerialNumber ); DECLARE_STRUCT(LocationProperties, double, Latitude, double, Longitude ); DECLARE_STRUCT(ReportedDeviceProperties, ascii_char_ptr, DeviceState, LocationProperties, Location ); DECLARE_MODEL(ConfigProperties, WITH_REPORTED_PROPERTY(double, TemperatureMeanValue), WITH_REPORTED_PROPERTY(uint8_t, TelemetryInterval) ); /* Part of DeviceInfo */ DECLARE_STRUCT(DeviceProperties, ascii_char_ptr, DeviceID, _Bool, HubEnabledState ); DECLARE_DEVICETWIN_MODEL(Thermostat, /* Telemetry (temperature, external temperature and humidity) */ WITH_DATA(double, Temperature), WITH_DATA(double, ExternalTemperature), WITH_DATA(double, Humidity), WITH_DATA(ascii_char_ptr, DeviceId), /* DeviceInfo */ WITH_DATA(ascii_char_ptr, ObjectType), WITH_DATA(_Bool, IsSimulatedDevice), WITH_DATA(ascii_char_ptr, Version), WITH_DATA(DeviceProperties, DeviceProperties), /* Device twin properties */ WITH_REPORTED_PROPERTY(ReportedDeviceProperties, Device), WITH_REPORTED_PROPERTY(ConfigProperties, Config), WITH_REPORTED_PROPERTY(SystemProperties, System), WITH_DESIRED_PROPERTY(double, TemperatureMeanValue, onDesiredTemperatureMeanValue), WITH_DESIRED_PROPERTY(uint8_t, TelemetryInterval, onDesiredTelemetryInterval), /* Direct methods implemented by the device */ WITH_METHOD(Reboot), WITH_METHOD(InitiateFirmwareUpdate, ascii_char_ptr, FwPackageURI), /* Register direct methods with solution portal */ WITH_REPORTED_PROPERTY(ascii_char_ptr_no_quotes, SupportedMethods) ); END_NAMESPACE(Contoso);
Реализация поведения устройства
Теперь добавьте код, который будет реализовывать определенное в модели поведение.
Добавьте следующие функции, которые обрабатывают требуемые свойства, заданные на панели мониторинга решения. Эти требуемые свойства определяются в модели:
void onDesiredTemperatureMeanValue(void* argument) { /* By convention 'argument' is of the type of the MODEL */ Thermostat* thermostat = argument; printf("Received a new desired_TemperatureMeanValue = %f\r\n", thermostat->TemperatureMeanValue); } void onDesiredTelemetryInterval(void* argument) { /* By convention 'argument' is of the type of the MODEL */ Thermostat* thermostat = argument; printf("Received a new desired_TelemetryInterval = %d\r\n", thermostat->TelemetryInterval); }
Добавьте следующие функции, которые обрабатывают прямые методы, вызываемые через Центр Интернета вещей. Эти методы определяются в модели:
/* Handlers for direct methods */ METHODRETURN_HANDLE Reboot(Thermostat* thermostat) { (void)(thermostat); METHODRETURN_HANDLE result = MethodReturn_Create(201, "\"Rebooting\""); printf("Received reboot request\r\n"); return result; } METHODRETURN_HANDLE InitiateFirmwareUpdate(Thermostat* thermostat, ascii_char_ptr FwPackageURI) { (void)(thermostat); METHODRETURN_HANDLE result = MethodReturn_Create(201, "\"Initiating Firmware Update\""); printf("Recieved firmware update request. Use package at: %s\r\n", FwPackageURI); return result; }
Добавьте следующую функцию, которая отправляет сообщение в предварительно настроенное решение:
/* Send data to IoT Hub */ static void sendMessage(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const unsigned char* buffer, size_t size) { IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray(buffer, size); if (messageHandle == NULL) { printf("unable to create a new IoTHubMessage\r\n"); } else { if (IoTHubClient_SendEventAsync(iotHubClientHandle, messageHandle, NULL, NULL) != IOTHUB_CLIENT_OK) { printf("failed to hand over the message to IoTHubClient"); } else { printf("IoTHubClient accepted the message for delivery\r\n"); } IoTHubMessage_Destroy(messageHandle); } free((void*)buffer); }
Добавьте следующий обработчик обратных вызовов, который выполняется, когда устройство отправило новые значения сообщаемых свойств в предварительно настроенное решение:
/* Callback after sending reported properties */ void deviceTwinCallback(int status_code, void* userContextCallback) { (void)(userContextCallback); printf("IoTHub: reported properties delivered with status_code = %u\n", status_code); }
Добавьте следующую функцию для подключения устройства к предварительно настроенному решению в облаке и для обмена данными. Эта функция выполняет следующие действия:
- инициализирует платформу;
- регистрирует пространство имен Contoso с помощью библиотеки сериализации;
- инициализирует клиент с помощью строки подключения устройства;
- создает экземпляр модели термостата;
- создает и отправляет значения сообщаемых свойств;
- отправляет объект DeviceInfo;
- создает цикл для отправки данных телеметрии каждую секунду;
- деинициализирует все ресурсы.
void remote_monitoring_run(void) { if (platform_init() != 0) { printf("Failed to initialize the platform.\n"); } else { if (SERIALIZER_REGISTER_NAMESPACE(Contoso) == NULL) { printf("Unable to SERIALIZER_REGISTER_NAMESPACE\n"); } else { IOTHUB_CLIENT_HANDLE iotHubClientHandle = IoTHubClient_CreateFromConnectionString(connectionString, MQTT_Protocol); if (iotHubClientHandle == NULL) { printf("Failure in IoTHubClient_CreateFromConnectionString\n"); } else { #ifdef MBED_BUILD_TIMESTAMP // For mbed add the certificate information if (IoTHubClient_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK) { printf("Failed to set option \"TrustedCerts\"\n"); } #endif // MBED_BUILD_TIMESTAMP Thermostat* thermostat = IoTHubDeviceTwin_CreateThermostat(iotHubClientHandle); if (thermostat == NULL) { printf("Failure in IoTHubDeviceTwin_CreateThermostat\n"); } else { /* Set values for reported properties */ thermostat->Config.TemperatureMeanValue = 55.5; thermostat->Config.TelemetryInterval = 3; thermostat->Device.DeviceState = "normal"; thermostat->Device.Location.Latitude = 47.642877; thermostat->Device.Location.Longitude = -122.125497; thermostat->System.Manufacturer = "Contoso Inc."; thermostat->System.FirmwareVersion = "2.22"; thermostat->System.InstalledRAM = "8 MB"; thermostat->System.ModelNumber = "DB-14"; thermostat->System.Platform = "Plat 9.75"; thermostat->System.Processor = "i3-7"; thermostat->System.SerialNumber = "SER21"; /* Specify the signatures of the supported direct methods */ thermostat->SupportedMethods = "{\"Reboot\": \"Reboot the device\", \"InitiateFirmwareUpdate--FwPackageURI-string\": \"Updates device Firmware. Use parameter FwPackageURI to specify the URI of the firmware file\"}"; /* Send reported properties to IoT Hub */ if (IoTHubDeviceTwin_SendReportedStateThermostat(thermostat, deviceTwinCallback, NULL) != IOTHUB_CLIENT_OK) { printf("Failed sending serialized reported state\n"); } else { printf("Send DeviceInfo object to IoT Hub at startup\n"); thermostat->ObjectType = "DeviceInfo"; thermostat->IsSimulatedDevice = 0; thermostat->Version = "1.0"; thermostat->DeviceProperties.HubEnabledState = 1; thermostat->DeviceProperties.DeviceID = (char*)deviceId; unsigned char* buffer; size_t bufferSize; if (SERIALIZE(&buffer, &bufferSize, thermostat->ObjectType, thermostat->Version, thermostat->IsSimulatedDevice, thermostat->DeviceProperties) != CODEFIRST_OK) { (void)printf("Failed serializing DeviceInfo\n"); } else { sendMessage(iotHubClientHandle, buffer, bufferSize); } /* Send telemetry */ thermostat->Temperature = 50; thermostat->ExternalTemperature = 55; thermostat->Humidity = 50; thermostat->DeviceId = (char*)deviceId; while (1) { unsigned char*buffer; size_t bufferSize; (void)printf("Sending sensor value Temperature = %f, Humidity = %f\n", thermostat->Temperature, thermostat->Humidity); if (SERIALIZE(&buffer, &bufferSize, thermostat->DeviceId, thermostat->Temperature, thermostat->Humidity, thermostat->ExternalTemperature) != CODEFIRST_OK) { (void)printf("Failed sending sensor value\r\n"); } else { sendMessage(iotHubClientHandle, buffer, bufferSize); } ThreadAPI_Sleep(1000); } IoTHubDeviceTwin_DestroyThermostat(thermostat); } } IoTHubClient_Destroy(iotHubClientHandle); } serializer_deinit(); } } platform_deinit(); }
Для справки ниже приведен пример сообщения Telemetry, которое отправляется в предварительно настроенное решение.
{"DeviceId":"mydevice01", "Temperature":50, "Humidity":50, "ExternalTemperature":55}
Сборка и запуск примера
Добавьте код для вызова функции remote_monitoring_run , а затем выполните сборку и запуск приложения устройства.
Замените функцию main следующим кодом для вызова функции remote_monitoring_run:
int main() { remote_monitoring_run(); return 0; }
Щелкните Построить, а затем Построить решение, чтобы выполнить сборку приложения устройства.
В обозревателе решений щелкните правой кнопкой мыши проект RMDevice, нажмите кнопку Отладка, а затем щелкните Запустить новый экземпляр, чтобы запустить пример. В консоли отображаются сообщения, когда приложение отправляет пример данных телеметрии в предварительно настроенное решение, получает наборы значений требуемых свойств в панели мониторинга решения и отвечает на методы, вызываемые из панели мониторинга решения.
Просмотр данных телеметрии устройства на панели мониторинга
На панели мониторинга в решении для удаленного мониторинга можно просматривать данные телеметрии, отправляемые устройством в Центр Интернета вещей.
В браузере вернитесь на панель мониторинга решения для удаленного мониторинга, в левой панели щелкните Устройства, чтобы перейти к списку устройств.
В списке устройств отображается текущее состояние устройства — Работает. Если это не так, то на панели Сведения об устройстве щелкните Включить устройство.
Щелкните Панель мониторинга, чтобы вернуться на панель мониторинга, в раскрывающемся списке Device to View (Устройство для просмотра) выберите свое устройство, чтобы просмотреть его данные телеметрии. Телеметрия из примера приложения — 50 единиц данных о внутренней температуре, 55 единиц данных о наружной температуре и 50 единиц данных о влажности.
Вызов метода на устройстве
На панели мониторинга в решении для удаленного мониторинга можно вызывать методы на своих устройствах через Центр Интернета вещей. Например, в решении для удаленного мониторинга можно вызвать метод, имитирующий перезагрузку устройства.
На панели мониторинга решения для удаленного мониторинга в левой панели щелкните Устройства, чтобы перейти к списку устройств.
Щелкните Идентификатор устройства для устройства в списке устройств.
На панели Сведения об устройстве щелкните Методы.
В раскрывающемся списке Метод выберите InitiateFirmwareUpdate, а затем в поле FWPACKAGEURI введите фиктивный URL-адрес. Щелкните Вызвать метод, чтобы вызвать метод на устройстве.
Когда устройство обрабатывает метод, в консоли отображается сообщение о выполнении кода устройства. Результаты метода добавляются в журнал на портале решения:
Дальнейшие действия
В статье Настройка предварительно настроенного решения приведен ряд способов расширения этого примера. В их число входит использование реальных датчиков и реализация дополнительных команд.
Дополнительные сведения см. в статье Разрешения на сайте azureiotsuite.com.