Łączenie urządzenia ze wstępnie skonfigurowanym rozwiązaniem do monitorowania zdalnego (Windows)
Omówienie scenariusza
W tym scenariuszu utworzysz urządzenie, które wysyła następujące dane telemetryczne do wstępnie skonfigurowanego rozwiązania do monitorowania zdalnego:
- Temperatura zewnętrzna
- Temperatura wewnętrzna
- Wilgotność
Dla uproszczenia kod na urządzeniu generuje przykładowe wartości, ale zachęcamy do rozszerzenia przykładu przez podłączenie rzeczywistych czujników do urządzenia i wysyłanie rzeczywistych danych telemetrycznych.
Urządzenie potrafi także odpowiadać na metody wywołane z poziomu pulpitu nawigacyjnego rozwiązania i wartości żądanych właściwości ustawione na pulpicie nawigacyjnym rozwiązania.
Do wykonania kroków tego samouczka jest potrzebne aktywne konto platformy Azure. Jeśli nie masz konta, możesz utworzyć bezpłatne konto próbne w zaledwie kilka minut. Aby uzyskać szczegółowe informacje, zobacz Bezpłatna wersja próbna platformy Azure.
Przed rozpoczęciem
Przed przystąpieniem do pisania jakiegokolwiek kodu dla urządzenia musisz przeprowadzić aprowizację wstępnie skonfigurowanego rozwiązania do monitorowania zdalnego i nowego niestandardowego urządzenia w ramach tego rozwiązania.
Aprowizowanie wstępnie skonfigurowanego rozwiązania do monitorowania zdalnego
Urządzenie, które utworzysz w ramach tego samouczka, będzie wysyłać dane do wystąpienia wstępnie skonfigurowanego rozwiązania do monitorowania zdalnego. Jeśli jeszcze nie przeprowadzono aprowizacji wstępnie skonfigurowanego rozwiązania do monitorowania zdalnego na Twoim koncie platformy Azure, wykonaj poniższe kroki:
- https://www.azureiotsolutions.com/ Na stronie kliknij+, aby utworzyć rozwiązanie.
- Kliknij pozycję Wybierz w panelu Monitorowanie zdalne, aby utworzyć rozwiązanie.
- Na stronie Tworzenie rozwiązania do monitorowania zdalnego w polu Nazwa rozwiązania wprowadź wybraną nazwę rozwiązania, w polu Region wybierz region, w którym chcesz przeprowadzić wdrożenie, a następnie wybierz subskrypcję platformy Azure, której chcesz użyć. Następnie kliknij pozycję Utwórz rozwiązanie.
- Zaczekaj na ukończenie procesu aprowizowania.
Ostrzeżenie
Wstępnie skonfigurowane rozwiązania korzystają z płatnych usług platformy Azure. Pamiętaj o usunięciu wstępnie skonfigurowanego rozwiązania ze swojej subskrypcji po zakończeniu pracy z nim, aby uniknąć wszelkich zbędnych opłat. Możesz całkowicie usunąć wstępnie skonfigurowane rozwiązanie z subskrypcji, odwiedzając https://www.azureiotsolutions.com/ stronę.
Po zakończeniu procesu aprowizowania rozwiązania do monitorowania zdalnego kliknij pozycję Uruchom, aby otworzyć pulpit nawigacyjny rozwiązania w przeglądarce.
Aprowizowanie urządzenia w ramach rozwiązania do monitorowania zdalnego
Uwaga
Jeśli już przeprowadzono aprowizację urządzenia w ramach rozwiązania, możesz pominąć ten krok. Podczas tworzenia aplikacji klienckiej musisz znać poświadczenia urządzenia.
Aby urządzenie mogło nawiązać połączenie ze wstępnie skonfigurowanym rozwiązaniem, musi ono zidentyfikować się względem usługi IoT Hub za pomocą prawidłowych poświadczeń. Poświadczenia urządzenia możesz pobrać z pulpitu nawigacyjnego rozwiązania. W dalszej części tego samouczka podasz te poświadczenia urządzenia w Twojej aplikacji klienckiej.
Aby dodać urządzenie do swojego rozwiązania do monitorowania zdalnego, wykonaj poniższe kroki na pulpicie nawigacyjnym rozwiązania:
W lewym dolnym rogu pulpitu nawigacyjnego kliknij pozycję Dodaj urządzenie.
W panelu Urządzenie niestandardowe kliknij pozycję Dodaj nowe.
Wybierz pozycję Pozwól mi zdefiniować własny identyfikator urządzenia. Wprowadź identyfikator urządzenia, na przykład moje_urządzenie, kliknij pozycję Sprawdź identyfikator, aby sprawdzić, czy dana nazwa nie jest już używana, a następnie kliknij pozycję Utwórz, aby przeprowadzić aprowizację urządzenia.
Zanotuj poświadczenia urządzenia (identyfikator urządzenia, nazwę hosta usługi IoT Hub i klucz urządzenia). Twoja aplikacja kliencka potrzebuje tych wartości, aby mogła nawiązać połączenie z rozwiązaniem do monitorowania zdalnego. Następnie kliknij przycisk Gotowe.
Wybierz urządzenie na liście urządzeń na pulpicie nawigacyjnym rozwiązania. Następnie w panelu Szczegóły urządzenia kliknij pozycję Włącz urządzenie. Stan Twojego urządzenia to teraz Uruchomione. Rozwiązanie do monitorowania zdalnego może teraz odbierać dane telemetryczne z Twojego urządzenia i wywoływać metody na tym urządzeniu.
Tworzenie przykładowego rozwiązania języka C w systemie Windows
W poniższych krokach pokazano, jak utworzyć aplikację kliencką, która komunikuje się ze wstępnie skonfigurowanym rozwiązaniem do monitorowania zdalnego. Ta aplikacja jest napisana w języku C i kompilowana i uruchamiana w systemie Windows.
Utwórz projekt startowy w programie Visual Studio 2015 lub Visual Studio 2017 i dodaj pakiety NuGet klienta urządzenia IoT Hub:
W programie Visual Studio utwórz aplikację konsolową języka C przy użyciu szablonu aplikacji konsolowej Win32 Visual C++. Nadaj projektowi nazwę RMDevice.
Na stronie Ustawienia aplikacji w Kreatorze aplikacji Win32 upewnij się, że aplikacja konsolowa jest zaznaczona, a następnie usuń zaznaczenie pola wyboru Prekompiled header (Precompiled header) i Security Development Lifecycle (SDL).
W Eksplorator rozwiązań usuń pliki stdafx.h, targetver.h i stdafx.cpp.
W Eksplorator rozwiązań zmień nazwę pliku RMDevice.cpp na RMDevice.c.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt RMDevice, a następnie kliknij polecenie Zarządzaj pakietami NuGet. Kliknij przycisk Przeglądaj, a następnie wyszukaj i zainstaluj następujące pakiety NuGet:
- Microsoft.Azure.IoTHub.Serializer
- Microsoft.Azure.IoTHub.IoTHubClient
- Microsoft.Azure.IoTHub.MqttTransport
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt RMDevice, a następnie kliknij polecenie Właściwości, aby otworzyć okno dialogowe Strony właściwości projektu. Aby uzyskać szczegółowe informacje, zobacz Ustawianie właściwości projektu Visual C++.
Kliknij folder Konsolidator , a następnie kliknij stronę Właściwości wejściowe .
Dodaj bibliotekę crypt32.lib do właściwości Dodatkowe zależności . Kliknij przycisk OK , a następnie ponownie ok , aby zapisać wartości właściwości projektu.
Dodaj bibliotekę Parson JSON do projektu RMDevice i dodaj wymagane #include
instrukcje:
W odpowiednim folderze na komputerze sklonuj repozytorium Parson GitHub przy użyciu następującego polecenia:
git clone https://github.com/kgabis/parson.git
Skopiuj pliki parson.h i parson.c z lokalnej kopii repozytorium Parson do folderu projektu RMDevice .
W programie Visual Studio kliknij prawym przyciskiem myszy projekt RMDevice , kliknij przycisk Dodaj, a następnie kliknij pozycję Istniejący element.
W oknie dialogowym Dodawanie istniejącego elementu wybierz pliki parson.h i parson.c w folderze projektu RMDevice . Następnie kliknij przycisk Dodaj, aby dodać te dwa pliki do projektu.
W programie Visual Studio otwórz plik RMDevice.c. Zastąp istniejące
#include
instrukcje następującym kodem:#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"
Uwaga
Teraz możesz sprawdzić, czy projekt ma skonfigurowane prawidłowe zależności, tworząc go.
Określanie zachowania urządzenia IoT
Biblioteka kliencka serializatora usługi IoT Hub korzysta z modelu do określania formatu komunikatów wymienianych między urządzeniem a usługą IoT Hub.
Dodaj następujące deklaracje zmiennych po instrukcji
#include
. Zastąp wartości zastępcze [Identyfikator urządzenia] i [Klucz urządzenia] wartościami zanotowymi dla urządzenia na pulpicie nawigacyjnym rozwiązania do monitorowania zdalnego. Użyj nazwy hosta usługi IoT Hub z pulpitu nawigacyjnego rozwiązania w celu zastąpienia wartości zastępczej [Nazwa usługi IoTHub]. Jeśli na przykład host usługi IoT Hub ma nazwę contoso.azure-devices.net, zastąp wartość zastępczą [Nazwa usługi IoTHub] ciągiem contoso:static const char* deviceId = "[Device Id]"; static const char* connectionString = "HostName=[IoTHub Name].azure-devices.net;DeviceId=[Device Id];SharedAccessKey=[Device Key]";
Dodaj następujący kod w celu zdefiniowania modelu umożliwiającego komunikację między urządzeniem a usługą IoT Hub. Ten model określa następujące właściwości urządzenia:
- Może wysyłać dane telemetryczne o temperaturze, temperaturze zewnętrznej, wilgotności i identyfikatorze urządzenia.
- Może wysyłać metadane dotyczące urządzenia do usługi IoT Hub. Podczas uruchamiania urządzenie wysyła podstawowe metadane w obiekcie DeviceInfo.
- Może wysyłać zgłaszane właściwości do bliźniaczej reprezentacji urządzenia w usłudze IoT Hub. Te zgłaszane właściwości są podzielone na następujące grupy: właściwości konfiguracji, urządzeń i systemu.
- Może odbierać i przetwarzać żądane właściwości ustawione w bliźniaczej reprezentacji urządzenia w usłudze IoT Hub.
- Może odpowiadać na bezpośrednie metody Reboot i InitiateFirmwareUpdate wywoływane za pośrednictwem portalu rozwiązania. Urządzenie wysyła informacje dotyczące obsługiwanych metod bezpośrednich za pomocą zgłaszanych właściwości.
// 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);
Implementowanie zachowania urządzenia
Teraz można dodać kod, który implementuje zachowanie zdefiniowane w modelu.
Dodaj następujące funkcje obsługujące żądane właściwości ustawione na pulpicie nawigacyjnym rozwiązania. Te żądane właściwości są zdefiniowane w modelu:
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); }
Dodaj następujące funkcje obsługujące bezpośrednie metody wywoływane za pośrednictwem usługi IoT Hub. Te metody bezpośrednie są zdefiniowane w modelu:
/* 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; }
Dodaj następującą funkcję, która wysyła komunikat do wstępnie skonfigurowanego rozwiązania:
/* 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); }
Dodaj następujący program obsługi wywołania zwrotnego, który jest uruchamiany, gdy urządzenie wyśle nowe wartości zgłaszanych właściwości do wstępnie skonfigurowanego rozwiązania:
/* 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); }
Dodaj następującą funkcję, aby połączyć urządzenie ze wstępnie skonfigurowanym rozwiązaniem w chmurze i rozpocząć wymianę danych. Ta funkcja wykonuje następujące działania:
- Inicjuje platformę.
- Rejestruje przestrzeń nazw Contoso z biblioteką serializacji.
- Inicjuje klienta za pomocą parametrów połączenia urządzenia.
- Tworzy wystąpienie modelu Thermostat.
- Tworzy i wysyła zgłaszane wartości właściwości.
- Wysyła obiekt DeviceInfo.
- Tworzy pętlę wysyłającą dane telemetryczne co sekundę.
- Wyłącza wszystkie zasoby.
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(); }
Do celów referencyjnych zamieszczono tutaj przykładowy komunikat z danymi telemetrycznymi wysłany do wstępnie skonfigurowanego rozwiązania:
{"DeviceId":"mydevice01", "Temperature":50, "Humidity":50, "ExternalTemperature":55}
Kompilowanie i uruchamianie przykładu
Dodaj kod, aby wywołać funkcję remote_monitoring_run , a następnie skompilować i uruchomić aplikację urządzenia.
Zastąp funkcję main następującym kodem, aby wywołać funkcję remote_monitoring_run :
int main() { remote_monitoring_run(); return 0; }
Kliknij pozycję Kompiluj , a następnie utwórz rozwiązanie , aby skompilować aplikację urządzenia.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt RMDevice, kliknij polecenie Debuguj, a następnie kliknij polecenie Uruchom nowe wystąpienie, aby uruchomić przykład. Konsola wyświetla komunikaty, gdy aplikacja wysyła przykładowe dane telemetryczne do wstępnie skonfigurowanego rozwiązania, odbiera żądane wartości właściwości ustawione na pulpicie nawigacyjnym rozwiązania i reaguje na metody wywoływane z pulpitu nawigacyjnego rozwiązania.
Wyświetlanie danych telemetrycznych z urządzeń na pulpicie nawigacyjnym
Pulpit nawigacyjny w rozwiązaniu do monitorowania zdalnego umożliwia wyświetlenie danych telemetrycznych wysyłanych z Twoich urządzeń do usługi IoT Hub.
W przeglądarce powróć do pulpitu nawigacyjnego rozwiązania do monitorowania zdalnego i kliknij pozycję Urządzenia w lewym panelu, aby przejść do listy urządzeń.
Na liście urządzeń powinien być widoczny stan urządzenia Uruchomione. W przeciwnym razie kliknij pozycję Włącz urządzenie w panelu Szczegóły urządzenia.
Kliknij pozycję Pulpit nawigacyjny, aby powrócić do pulpitu nawigacyjnego, a następnie wybierz swoje urządzenie z listy rozwijanej Urządzenie do wyświetlenia, aby wyświetlić z niego dane telemetryczne. Dane telemetryczne z przykładowej aplikacji to 50 jednostek temperatury wewnętrznej, 55 — temperatury zewnętrznej i 50 — wilgotności.
Wywoływanie metody na urządzeniu
Pulpit nawigacyjny w rozwiązaniu do monitorowania zdalnego umożliwia wywoływanie metod na urządzaniach za pomocą usługi IoT Hub. W rozwiązaniu do monitorowania zdalnego możesz na przykład wywołać metodę symulacji ponownego uruchomienia urządzenia.
Na pulpicie nawigacyjnym rozwiązania do monitorowania zdalnego kliknij pozycję Urządzenia w lewym panelu, aby przejść do listy urządzeń.
Kliknij pozycję Identyfikator urządzenia dla swojego urządzenia na liście urządzeń.
W panelu Szczegóły urządzenia kliknij pozycję Metody.
Na liście rozwijanej Metoda wybierz metodę InitiateFirmwareUpdate (inicjowanie aktualizacji oprogramowania układowego), a następnie w polu FWPACKAGEURI (identyfikator URI pakietu oprogramowania układowego) wprowadź zastępczy adres URL. Kliknij pozycję Wywołaj metodę, aby wywołać metodę na urządzeniu.
Gdy urządzenie obsłuży metodę, zostanie wyświetlony komunikat w konsoli uruchamiania kodu urządzenia. Wyniki metody zostaną dodane do historii w portalu rozwiązania:
Następne kroki
W artykule Dostosowywanie wstępnie skonfigurowanych rozwiązań opisano niektóre sposoby pozwalające rozszerzyć ten przykład. Możliwe rozszerzenia obejmują użycie rzeczywistych czujników i implementację dodatkowych poleceń.
Więcej informacji na temat uprawnień podano w witrynie azureiotsuite.com.