Tutorial: Membuat dan menghubungkan aplikasi klien ke aplikasi Azure IoT Central Anda
Penting
Artikel ini menyertakan langkah-langkah untuk menyambungkan perangkat menggunakan tanda tangan akses bersama, juga disebut autentikasi kunci konten. Metode autentikasi ini mudah untuk pengujian dan evaluasi, tetapi mengautentikasi perangkat menggunakan sertifikat X.509 adalah pendekatan yang lebih aman. Untuk mempelajari lebih lanjut, lihat Keamanan koneksi praktik > terbaik keamanan.
Tutorial ini menunjukkan cara menghubungkan aplikasi klien ke aplikasi Azure IoT Central Anda. Aplikasi ini menyimulasikan perilaku perangkat pengontrol suhu. Ketika aplikasi terhubung ke IoT Central, aplikasi mengirimkan ID model dari model perangkat pengontrol suhu. IoT Central menggunakan ID model untuk mengambil model perangkat dan membuat templat perangkat untuk Anda. Anda menambahkan tampilan ke templat perangkat untuk memungkinkan operator berinteraksi dengan perangkat.
Dalam tutorial ini, Anda akan mempelajari cara:
- Buat dan jalankan kode perangkat, dan lihat kode perangkat tersebut terhubung ke aplikasi IoT Central Anda.
- Tampilkan simulasi telemetri yang dikirim dari perangkat.
- Tambahkan tampilan kustom ke templat perangkat.
- Menerbitkan templat perangkat.
- Gunakan tampilan untuk mengelola properti perangkat.
- Panggil perintah untuk mengontrol perangkat.
Prasyarat
Untuk menyelesaikan langkah-langkah dalam tutorial ini, Anda perlu:
Langganan Azure aktif. Jika Anda tidak memiliki langganan Azure, buat akun gratis sebelum Anda memulai.
Aplikasi IoT Central yang dibuat dari templat aplikasi Kustom. Untuk mempelajari lebih lanjut, lihat Membuat aplikasi IoT Central dan Tentang aplikasi Anda.
Anda dapat menjalankan tutorial ini di Linux atau Windows. Perintah shell dalam tutorial ini mengikuti konvensi Linux untuk pemisah jalur '/
', jika Anda mengikuti di Windows pastikan untuk menukar pemisah ini dengan '\
'.
Prasyarat berbeda menurut sistem operasi:
Linux
Tutorial ini mengasumsikan Anda menggunakan Ubuntu Linux. Langkah-langkah dalam tutorial ini diuji menggunakan Ubuntu 18.04.
Untuk menyelesaikan tutorial ini di Linux, instal perangkat lunak berikut di lingkungan Linux lokal Anda:
PasangGCC, Git, cmake, dan semua dependensi yang diperlukan menggunakan perintah apt-get
:
sudo apt-get update
sudo apt-get install -y git cmake build-essential curl libcurl4-openssl-dev libssl-dev uuid-dev
Verifikasi versi cmake
lebih besar dari 2.8.12 dan versi GCC lebih besar dari 4.4.7.
cmake --version
gcc --version
Windows
Untuk menyelesaikan tutorial ini di Windows, instal perangkat lunak berikut di lingkungan Windows lokal Anda:
- Visual Studio (Komunitas, Profesional, atau Perusahaan) - pastikan Anda menyertakan beban kerja Pengembangan Desktop dengan C++ saat Anda memasang Visual Studio.
- Git.
- CMake.
Unduh kode
Dalam tutorial ini, Anda menyiapkan lingkungan pengembangan yang dapat Anda gunakan untuk mengkloning dan membangun Azure IoT Hub Device C SDK.
Buka perintah di direktori pilihan Anda. Jalankan perintah berikut untuk mengkloning repositori GitHub Azure IoT C SDKs dan Libraries ke lokasi ini:
git clone https://github.com/Azure/azure-iot-sdk-c.git
cd azure-iot-sdk-c
git submodule update --init
Diperlukan waktu beberapa menit untuk menyelesaikan operasi ini.
Mengulas kode
Dalam salinan Microsoft Azure IoT SDK untuk C yang Anda unduh sebelumnya, buka azure-iot-sdk-c/iothub_client/samples/pnp/pnp_temperature_controller/pnp_temperature_controller.c dan azure-iot- sdk-c/iothub_client/samples/pnp/pnp_temperature_controller/pnp_thermostat_component.c file dalam editor teks.
Sampel mengimplementasikan model Temperature Controller Digital Twin Definition Language multi-komponen.
Saat Anda menjalankan sampel untuk terhubung ke IoT Central, sampel tersebut menggunakan Device Provisioning Service (DPS) untuk mendaftarkan perangkat dan menghasilkan string koneksi. Sampel mengambil informasi koneksi DPS yang dibutuhkan dari lingkungan baris perintah.
Di pnp_temperature_controller.c, fungsi main
pertama-tama memanggil CreateDeviceClientAndAllocateComponents
untuk:
- Setel
dtmi:com:example:Thermostat;1
ID model. IoT Central menggunakan ID model untuk mengidentifikasi atau membuat template perangkat untuk perangkat ini. Untuk mempelajari selengkapnya, lihat Menetapkan perangkat ke templat perangkat. - Gunakan DPS untuk menyediakan dan mendaftarkan perangkat.
- Buat pegangan klien perangkat, dan sambungkan ke aplikasi IoT Central Anda.
- Membuat handler untuk perintah dalam komponen pengontrol suhu.
- Membuat handler untuk pembaruan properti di komponen pengontrol suhu.
- Membuat dua komponen termostat.
Fungsi main
berikutnya:
- Melaporkan beberapa nilai properti awal untuk semua komponen.
- Memulai loop untuk mengirim telemetri dari semua komponen.
Fungsi main
kemudian memulai utas untuk mengirim telemetri secara berkala.
int main(void)
{
IOTHUB_DEVICE_CLIENT_LL_HANDLE deviceClient = NULL;
g_pnpDeviceConfiguration.modelId = g_temperatureControllerModelId;
g_pnpDeviceConfiguration.enableTracing = g_hubClientTraceEnabled;
// First determine the IoT Hub / credentials / device to use.
if (GetConnectionSettingsFromEnvironment(&g_pnpDeviceConfiguration) == false)
{
LogError("Cannot read required environment variable(s)");
}
// Creates the thermostat subcomponents defined by this model. Since everything
// is simulated, this setup stage just creates simulated objects in memory.
else if (AllocateThermostatComponents() == false)
{
LogError("Failure allocating thermostat components");
}
// Create a handle to device client handle. Note that this call may block
// for extended periods of time when using DPS.
else if ((deviceClient = CreateAndConfigureDeviceClientHandleForPnP()) == NULL)
{
LogError("Failure creating Iot Hub device client");
PnP_ThermostatComponent_Destroy(g_thermostatHandle1);
PnP_ThermostatComponent_Destroy(g_thermostatHandle2);
}
else
{
LogInfo("Successfully created device client. Hit Control-C to exit program\n");
int numberOfIterations = 0;
// During startup, send what DTDLv2 calls "read-only properties" to indicate initial device state.
PnP_TempControlComponent_ReportSerialNumber_Property(deviceClient);
PnP_DeviceInfoComponent_Report_All_Properties(g_deviceInfoComponentName, deviceClient);
PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property(g_thermostatHandle1, deviceClient);
PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property(g_thermostatHandle2, deviceClient);
while (true)
{
// Wake up periodically to poll. Even if we do not plan on sending telemetry, we still need to poll periodically in order to process
// incoming requests from the server and to do connection keep alives.
if ((numberOfIterations % g_sendTelemetryPollInterval) == 0)
{
PnP_TempControlComponent_SendWorkingSet(deviceClient);
PnP_ThermostatComponent_SendCurrentTemperature(g_thermostatHandle1, deviceClient);
PnP_ThermostatComponent_SendCurrentTemperature(g_thermostatHandle2, deviceClient);
}
IoTHubDeviceClient_LL_DoWork(deviceClient);
ThreadAPI_Sleep(g_sleepBetweenPollsMs);
numberOfIterations++;
}
// The remainder of the code is used for cleaning up our allocated resources. It won't be executed in this
// sample (because the loop above is infinite and is only broken out of by Control-C of the program), but
// it is included for reference.
// Free the memory allocated to track simulated thermostat.
PnP_ThermostatComponent_Destroy(g_thermostatHandle1);
PnP_ThermostatComponent_Destroy(g_thermostatHandle2);
// Clean up the IoT Hub SDK handle.
IoTHubDeviceClient_LL_Destroy(deviceClient);
// Free all IoT Hub subsystem.
IoTHub_Deinit();
}
return 0;
}
Di pnp_thermostat_component.c
, fungsi PnP_ThermostatComponent_SendCurrentTemperature
menunjukkan cara perangkat mengirim telemetri suhu dari komponen ke IoT Central:
void PnP_ThermostatComponent_SendCurrentTemperature(PNP_THERMOSTAT_COMPONENT_HANDLE pnpThermostatComponentHandle, IOTHUB_DEVICE_CLIENT_LL_HANDLE deviceClient)
{
PNP_THERMOSTAT_COMPONENT* pnpThermostatComponent = (PNP_THERMOSTAT_COMPONENT*)pnpThermostatComponentHandle;
IOTHUB_MESSAGE_HANDLE messageHandle = NULL;
IOTHUB_MESSAGE_RESULT messageResult;
IOTHUB_CLIENT_RESULT iothubClientResult;
char temperatureStringBuffer[CURRENT_TEMPERATURE_BUFFER_SIZE];
// Create the telemetry message body to send.
if (snprintf(temperatureStringBuffer, sizeof(temperatureStringBuffer), g_temperatureTelemetryBodyFormat, pnpThermostatComponent->currentTemperature) < 0)
{
LogError("snprintf of current temperature telemetry failed");
}
// Create the message handle and specify its metadata.
else if ((messageHandle = IoTHubMessage_CreateFromString(temperatureStringBuffer)) == NULL)
{
LogError("IoTHubMessage_PnP_CreateFromString failed");
}
else if ((messageResult = IoTHubMessage_SetContentTypeSystemProperty(messageHandle, g_jsonContentType)) != IOTHUB_MESSAGE_OK)
{
LogError("IoTHubMessage_SetContentTypeSystemProperty failed, error=%d", messageResult);
}
else if ((messageResult = IoTHubMessage_SetContentEncodingSystemProperty(messageHandle, g_utf8EncodingType)) != IOTHUB_MESSAGE_OK)
{
LogError("IoTHubMessage_SetContentEncodingSystemProperty failed, error=%d", messageResult);
}
else if ((messageResult = IoTHubMessage_SetComponentName(messageHandle, pnpThermostatComponent->componentName)) != IOTHUB_MESSAGE_OK)
{
LogError("IoTHubMessage_SetContentEncodingSystemProperty failed, error=%d", messageResult);
}
// Send the telemetry message.
else if ((iothubClientResult = IoTHubDeviceClient_LL_SendTelemetryAsync(deviceClient, messageHandle, NULL, NULL)) != IOTHUB_CLIENT_OK)
{
LogError("Unable to send telemetry message, error=%d", iothubClientResult);
}
IoTHubMessage_Destroy(messageHandle);
}
Di pnp_thermostat_component.c
, fungsi PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property
mengirimkan maxTempSinceLastReboot
pembaruan properti dari komponen ke IoT Central:
void PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property(PNP_THERMOSTAT_COMPONENT_HANDLE pnpThermostatComponentHandle, IOTHUB_DEVICE_CLIENT_LL_HANDLE deviceClient)
{
PNP_THERMOSTAT_COMPONENT* pnpThermostatComponent = (PNP_THERMOSTAT_COMPONENT*)pnpThermostatComponentHandle;
char maximumTemperatureAsString[MAX_TEMPERATURE_SINCE_REBOOT_BUFFER_SIZE];
IOTHUB_CLIENT_RESULT iothubClientResult;
if (snprintf(maximumTemperatureAsString, sizeof(maximumTemperatureAsString), g_maxTempSinceLastRebootPropertyFormat, pnpThermostatComponent->maxTemperature) < 0)
{
LogError("Unable to create max temp since last reboot string for reporting result");
}
else
{
IOTHUB_CLIENT_PROPERTY_REPORTED maxTempProperty;
maxTempProperty.structVersion = IOTHUB_CLIENT_PROPERTY_REPORTED_STRUCT_VERSION_1;
maxTempProperty.name = g_maxTempSinceLastRebootPropertyName;
maxTempProperty.value = maximumTemperatureAsString;
unsigned char* propertySerialized = NULL;
size_t propertySerializedLength;
// The first step of reporting properties is to serialize IOTHUB_CLIENT_PROPERTY_WRITABLE_RESPONSE into JSON for sending.
if ((iothubClientResult = IoTHubClient_Properties_Serializer_CreateReported(&maxTempProperty, 1, pnpThermostatComponent->componentName, &propertySerialized, &propertySerializedLength)) != IOTHUB_CLIENT_OK)
{
LogError("Unable to serialize reported state, error=%d", iothubClientResult);
}
// The output of IoTHubClient_Properties_Serializer_CreateReported is sent to IoTHubDeviceClient_LL_SendPropertiesAsync to perform network I/O.
else if ((iothubClientResult = IoTHubDeviceClient_LL_SendPropertiesAsync(deviceClient, propertySerialized, propertySerializedLength, NULL, NULL)) != IOTHUB_CLIENT_OK)
{
LogError("Unable to send reported state, error=%d", iothubClientResult);
}
else
{
LogInfo("Sending %s property to IoTHub for component %s", g_maxTempSinceLastRebootPropertyName, pnpThermostatComponent->componentName);
}
IoTHubClient_Properties_Serializer_Destroy(propertySerialized);
}
}
Di pnp_thermostat_component.c
, fungsi PnP_ThermostatComponent_ProcessPropertyUpdate
menangani pembaruan properti yang dapat ditulis dari IoT Central:
void PnP_ThermostatComponent_ProcessPropertyUpdate(PNP_THERMOSTAT_COMPONENT_HANDLE pnpThermostatComponentHandle, IOTHUB_DEVICE_CLIENT_LL_HANDLE deviceClient, const char* propertyName, const char* propertyValue, int version)
{
PNP_THERMOSTAT_COMPONENT* pnpThermostatComponent = (PNP_THERMOSTAT_COMPONENT*)pnpThermostatComponentHandle;
if (strcmp(propertyName, g_targetTemperaturePropertyName) != 0)
{
LogError("Property %s was requested to be changed but is not part of the thermostat interface definition", propertyName);
}
else
{
char* next;
double targetTemperature = strtod(propertyValue, &next);
if ((propertyValue == next) || (targetTemperature == HUGE_VAL) || (targetTemperature == (-1*HUGE_VAL)))
{
LogError("Property %s is not a valid number", propertyValue);
SendTargetTemperatureResponse(pnpThermostatComponent, deviceClient, propertyValue, PNP_STATUS_BAD_FORMAT, version, g_temperaturePropertyResponseDescriptionNotInt);
}
else
{
LogInfo("Received targetTemperature %f for component %s", targetTemperature, pnpThermostatComponent->componentName);
bool maxTempUpdated = false;
UpdateTemperatureAndStatistics(pnpThermostatComponent, targetTemperature, &maxTempUpdated);
// The device needs to let the service know that it has received the targetTemperature desired property.
SendTargetTemperatureResponse(pnpThermostatComponent, deviceClient, propertyValue, PNP_STATUS_SUCCESS, version, NULL);
if (maxTempUpdated)
{
// If the maximum temperature has been updated, we also report this as a property.
PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property(pnpThermostatComponent, deviceClient);
}
}
}
}
Di pnp_thermostat_component.c
, fungsi PnP_ThermostatComponent_ProcessCommand
menangani perintah yang dipanggil dari IoT Central:
void PnP_ThermostatComponent_ProcessCommand(PNP_THERMOSTAT_COMPONENT_HANDLE pnpThermostatComponentHandle, const char *pnpCommandName, JSON_Value* commandJsonValue, IOTHUB_CLIENT_COMMAND_RESPONSE* commandResponse)
{
PNP_THERMOSTAT_COMPONENT* pnpThermostatComponent = (PNP_THERMOSTAT_COMPONENT*)pnpThermostatComponentHandle;
const char* sinceStr;
if (strcmp(pnpCommandName, g_getMaxMinReportCommandName) != 0)
{
LogError("Command %s is not supported on thermostat component", pnpCommandName);
commandResponse->statusCode = PNP_STATUS_NOT_FOUND;
}
// See caveats section in ../readme.md; we don't actually respect this sinceStr to keep the sample simple,
// but want to demonstrate how to parse out in any case.
else if ((sinceStr = json_value_get_string(commandJsonValue)) == NULL)
{
LogError("Cannot retrieve JSON string for command");
commandResponse->statusCode = PNP_STATUS_BAD_FORMAT;
}
else if (BuildMaxMinCommandResponse(pnpThermostatComponent, commandResponse) == false)
{
LogError("Unable to build response for component %s", pnpThermostatComponent->componentName);
commandResponse->statusCode = PNP_STATUS_INTERNAL_ERROR;
}
else
{
LogInfo("Returning success from command request for component %s", pnpThermostatComponent->componentName);
commandResponse->statusCode = PNP_STATUS_SUCCESS;
}
}
Bangun kode
Anda menggunakan SDK perangkat untuk membuat kode contoh yang disertakan:
Buat subdirektori cmake di folder akar SDK perangkat, dan navigasikan ke folder itu:
cd azure-iot-sdk-c mkdir cmake cd cmake
Jalankan perintah berikut untuk membuat SDK dan sampel:
cmake -Duse_prov_client=ON -Dhsm_type_symm_key=ON -Drun_e2e_tests=OFF .. cmake --build .
Mendapatkan informasi koneksi
Ketika Anda menjalankan aplikasi perangkat sampel dalam tutorial ini nanti, Anda memerlukan nilai konfigurasi berikut:
- Cakupan ID: Di aplikasi IoT Central Anda, navigasikan ke grup koneksi Perangkat Izin>. Catat nilai lingkup ID.
- Kunci utama grup: Di aplikasi IoT Central Anda, navigasikan ke Grup > koneksi Perangkat Izin > SAS-IoT-Devices. Catat nilai Kunci primer tanda tangan akses bersama.
Gunakan Azure Cloud Shell untuk menghasilkan kunci perangkat dari kunci utama grup yang Anda ambil:
az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>
Catat kunci perangkat yang dihasilkan, Anda gunakan nanti dalam tutorial ini.
Catatan
Untuk menjalankan sampel ini, Anda tidak perlu mendaftarkan perangkat terlebih dahulu di aplikasi IoT Central Anda. Sampel menggunakan kemampuan IoT Central untuk mendaftarkan perangkat secara otomatis saat tersambung untuk pertama kalinya.
Menjalankan kode
Untuk menjalankan aplikasi contoh, buka lingkungan baris perintah dan navigasikan ke folder azure-iot-sdk-c\cmake.
Atur variabel lingkungan untuk mengonfigurasi sampel. Cuplikan berikut menunjukkan bagaimana mengatur variabel lingkungan pada perintah Windows. Jika Anda menggunakan shell bash, ganti perintah set
dengan perintah export
:
set IOTHUB_DEVICE_SECURITY_TYPE=DPS
set IOTHUB_DEVICE_DPS_ID_SCOPE=<The ID scope you made a note of previously>
set IOTHUB_DEVICE_DPS_DEVICE_ID=sample-device-01
set IOTHUB_DEVICE_DPS_DEVICE_KEY=<The generated device key you made a note of previously>
set IOTHUB_DEVICE_DPS_ENDPOINT=global.azure-devices-provisioning.net
Untuk menjalankan sampel:
# Bash
cd iothub_client/samples/pnp/pnp_temperature_controller/
./pnp_temperature_controller
REM Windows
cd iothub_client\samples\pnp\pnp_temperature_controller\Debug
.\pnp_temperature_controller.exe
Output berikut menunjukkan perangkat mendaftar dan menghubungkan ke IoT Central. Sampel mulai mengirimkan telemetri:
Info: Initiating DPS client to retrieve IoT Hub connection information
-> 09:43:27 CONNECT | VER: 4 | KEEPALIVE: 0 | FLAGS: 194 | USERNAME: 0ne0026656D/registrations/sample-device-01/api-version=2019-03-31&ClientVersion=1.6.0 | PWD: XXXX | CLEAN: 1
<- 09:43:28 CONNACK | SESSION_PRESENT: false | RETURN_CODE: 0x0
-> 09:43:29 SUBSCRIBE | PACKET_ID: 1 | TOPIC_NAME: $dps/registrations/res/# | QOS: 1
<- 09:43:30 SUBACK | PACKET_ID: 1 | RETURN_CODE: 1
-> 09:43:30 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_MOST_ONCE | TOPIC_NAME: $dps/registrations/PUT/iotdps-register/?$rid=1 | PAYLOAD_LEN: 102
<- 09:43:31 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: $dps/registrations/res/202/?$rid=1&retry-after=3 | PACKET_ID: 2 | PAYLOAD_LEN: 94
-> 09:43:31 PUBACK | PACKET_ID: 2
-> 09:43:33 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_MOST_ONCE | TOPIC_NAME: $dps/registrations/GET/iotdps-get-operationstatus/?$rid=2&operationId=4.2f792ade0a5c3e68.baf0e879-d88a-4153-afef-71aff51fd847 | PAYLOAD_LEN: 102
<- 09:43:34 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: $dps/registrations/res/202/?$rid=2&retry-after=3 | PACKET_ID: 2 | PAYLOAD_LEN: 173
-> 09:43:34 PUBACK | PACKET_ID: 2
-> 09:43:36 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_MOST_ONCE | TOPIC_NAME: $dps/registrations/GET/iotdps-get-operationstatus/?$rid=3&operationId=4.2f792ade0a5c3e68.baf0e879-d88a-4153-afef-71aff51fd847 | PAYLOAD_LEN: 102
<- 09:43:37 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: $dps/registrations/res/200/?$rid=3 | PACKET_ID: 2 | PAYLOAD_LEN: 478
-> 09:43:37 PUBACK | PACKET_ID: 2
Info: Provisioning callback indicates success. iothubUri=iotc-60a....azure-devices.net, deviceId=sample-device-01
-> 09:43:37 DISCONNECT
Info: DPS successfully registered. Continuing on to creation of IoTHub device client handle.
Info: Successfully created device client. Hit Control-C to exit program
Info: Sending serialNumber property to IoTHub
Info: Sending device information property to IoTHub. propertyName=swVersion, propertyValue="1.0.0.0"
Info: Sending device information property to IoTHub. propertyName=manufacturer, propertyValue="Sample-Manufacturer"
Info: Sending device information property to IoTHub. propertyName=model, propertyValue="sample-Model-123"
Info: Sending device information property to IoTHub. propertyName=osName, propertyValue="sample-OperatingSystem-name"
Info: Sending device information property to IoTHub. propertyName=processorArchitecture, propertyValue="Contoso-Arch-64bit"
Info: Sending device information property to IoTHub. propertyName=processorManufacturer, propertyValue="Processor Manufacturer(TM)"
Info: Sending device information property to IoTHub. propertyName=totalStorage, propertyValue=10000
Info: Sending device information property to IoTHub. propertyName=totalMemory, propertyValue=200
Info: Sending maximumTemperatureSinceLastReboot property to IoTHub for component=thermostat1
Info: Sending maximumTemperatureSinceLastReboot property to IoTHub for component=thermostat2
-> 09:43:44 CONNECT | VER: 4 | KEEPALIVE: 240 | FLAGS: 192 | USERNAME: iotc-60a576a2-eec7-48e2-9306-9e7089a79995.azure-devices.net/sample-device-01/?api-version=2020-09-30&DeviceClientType=iothubclient%2f1.6.0%20(native%3b%20Linux%3b%20x86_64)&model-id=dtmi%3acom%3aexample%3aTemperatureController%3b1 | PWD: XXXX | CLEAN: 0
<- 09:43:44 CONNACK | SESSION_PRESENT: false | RETURN_CODE: 0x0
-> 09:43:44 SUBSCRIBE | PACKET_ID: 2 | TOPIC_NAME: $iothub/twin/res/# | QOS: 0 | TOPIC_NAME: $iothub/methods/POST/# | QOS: 0
-> 09:43:44 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/sample-device-01/messages/events/ | PACKET_ID: 3 | PAYLOAD_LEN: 19
-> 09:43:44 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/sample-device-01/messages/events/%24.sub=thermostat1 | PACKET_ID: 4 | PAYLOAD_LEN: 21
-> 09:43:44 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/sample-device-01/messages/events/%24.sub=thermostat2 | PACKET_ID: 5 | PAYLOAD_LEN: 21
Sebagai operator di aplikasi Azure IoT Central, Anda dapat:
Melihat telemetri yang dikirim oleh dua komponen termostat pada halaman Gambaran Umum:
Lihat properti perangkat pada halaman Tentang. Halaman ini menampilkan properti dari komponen informasi perangkat dan dua komponen termostat:
Menyesuaikan templat perangkat
Sebagai pengembang solusi, Anda dapat menyesuaikan templat perangkat yang dibuat IoT Central secara otomatis ketika perangkat pengontrol suhu terhubung.
Untuk menambahkan properti cloud untuk menyimpan nama pelanggan yang terkait dengan perangkat:
Di aplikasi IoT Central Anda, navigasikan ke templat perangkat Pengontrol Suhu pada halaman Templat perangkat.
Dalam model Pengontrol Suhu, pilih +Tambahkan kemampuan.
Masukkan Nama pelanggan sebagai Nama tampilan, pilih Properti cloud sebagai jenis kemampuan, perluas entri dan pilih String sebagai Skema. Kemudian pilih Simpan.
Untuk menyesuaikan cara perintah Mendapatkan laporan Max-Min ditampilkan di aplikasi IoT Central Anda:
Navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .
Untuk getMaxMinReport (termostat1), ganti laporan Get Max-Min. dengan dapatkan laporan status termostat1.
Untuk getMaxMinReport (termostat2), ganti laporan Get Max-Min. dengan dapatkan laporan status termostat2.
Pilih Simpan.
Untuk mengkustomisasi cara Suhu Target properti yang dapat ditulis ditampilkan di aplikasi IoT Central Anda:
Navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .
Untuk targetTemperature (thermostat1), ganti Suhu Target dengan Suhu Target (1).
Untuk targetTemperature (thermostat2), ganti Suhu Target dengan Suhu Target (2).
Pilih Simpan.
Komponen termostat dalam model Pengontrol Suhu termasuk properti yang dapat ditulis Suhu Target, templat perangkat termasuk properti cloud Nama Pelanggan. Membuat tampilan yang dapat digunakan operator untuk mengedit properti ini:
Pilih Tampilan lalu pilih petak Pengeditan perangkat dan data cloud.
Masukkan Properti sebagai nama formulir.
Pilih properti Suhu Target (1), Suhu Target (2), dan Nama Pelanggan. Kemudian pilih Tambahkan bagian.
Simpan perubahan Anda.
Menerbitkan templat perangkat
Sebelum operator dapat melihat dan menggunakan kustomisasi yang Anda buat, Anda harus menerbitkan templat perangkat.
Dari templat perangkat Termostat, pilih Terbitkan. Pada halaman Terbitkan template perangkat ini ke panel aplikasi, pilih Terbitkan.
Operator sekarang dapat menggunakan tampilan Properti untuk memperbarui nilai properti, dan perintah panggilan yang disebut Get thermostat1 status report dan Get thermostat2 status report di halaman perintah perangkat:
Perbarui nilai properti yang dapat ditulis pada halaman Properti:
Panggil perintah dari halaman Perintah. Jika Anda menjalankan perintah laporan status, pilih tanggal dan waktu untuk parameter Sejak sebelum Anda menjalankannya:
Anda dapat melihat bagaimana perangkat merespons perintah dan pembaruan properti:
<- 09:49:03 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_MOST_ONCE | TOPIC_NAME: $iothub/methods/POST/thermostat1*getMaxMinReport/?$rid=1 | PAYLOAD_LEN: 26
Info: Received PnP command for component=thermostat1, command=getMaxMinReport
Info: Returning success from command request for component=thermostat1
-> 09:49:03 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_MOST_ONCE | TOPIC_NAME: $iothub/methods/res/200/?$rid=1 | PAYLOAD_LEN: 117
...
<- 09:50:04 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_MOST_ONCE | TOPIC_NAME: $iothub/twin/PATCH/properties/desired/?$version=2 | PAYLOAD_LEN: 63
Info: Received targetTemperature=67.000000 for component=thermostat2
Info: Sending acknowledgement of property to IoTHub for component=thermostat2
Prasyarat
Untuk menyelesaikan langkah-langkah dalam artikel ini, Anda memerlukan sumber daya berikut:
Langganan Azure aktif. Jika Anda tidak memiliki langganan Azure, buat akun gratis sebelum Anda memulai.
Aplikasi IoT Central yang dibuat dari templat aplikasi Kustom. Untuk mempelajari lebih lanjut, lihat Membuat aplikasi IoT Central dan Tentang aplikasi Anda.
Komputer pengembangan dengan Visual Studio (Komunitas, Profesional, atau Perusahaan).
Salinan lokal repositori GitHub Microsoft Azure IoT SDK for C# (.NET) yang berisi kode sampel. Gunakan tautan ini untuk mengunduh salinan repositori: Unduh ZIP. Kemudian unzip file ke lokasi yang sesuai di komputer lokal Anda.
Mengulas kode
Dalam salinan repositori Microsoft Azure IoT SDK for C# yang Anda unduh sebelumnya, buka file solusi azure-iot-sdk-csharp-main\azureiot.sln di Visual Studio. Di Penjelajah Solusi, perluas folder PnpDeviceSamples > TemperatureController dan buka file Program.cs dan TemperatureControllerSample.cs untuk melihat kode untuk sampel ini.
Sampel mengimplementasikan model Temperature Controller Digital Twin Definition Language multi-komponen.
Saat Anda menjalankan sampel untuk terhubung ke IoT Central, sampel tersebut menggunakan Device Provisioning Service (DPS) untuk mendaftarkan perangkat dan menghasilkan string koneksi. Sampel mengambil informasi koneksi DPS yang dibutuhkan dari lingkungan.
Pada Program.cs, metode Main
memanggil SetupDeviceClientAsync
untuk:
- Gunakan ID model
dtmi:com:example:TemperatureController;2
saat memprovisikan perangkat dengan DPS. IoT Central menggunakan ID model untuk mengidentifikasi atau membuat template perangkat untuk perangkat ini. Untuk mempelajari selengkapnya, lihat Menetapkan perangkat ke templat perangkat. - Buat instans DeviceClient untuk terhubung ke IoT Central.
private static async Task<DeviceClient> SetupDeviceClientAsync(Parameters parameters, CancellationToken cancellationToken)
{
DeviceClient deviceClient;
switch (parameters.DeviceSecurityType.ToLowerInvariant())
{
case "dps":
DeviceRegistrationResult dpsRegistrationResult = await ProvisionDeviceAsync(parameters, cancellationToken);
var authMethod = new DeviceAuthenticationWithRegistrySymmetricKey(dpsRegistrationResult.DeviceId, parameters.DeviceSymmetricKey);
deviceClient = InitializeDeviceClient(dpsRegistrationResult.AssignedHub, authMethod);
break;
case "connectionstring":
// ...
default:
// ...
}
return deviceClient;
}
Metode utama kemudian membuat instans TemperatureControllerSample dan memanggil metode PerformOperationsAsync
untuk menangani interaksi dengan IoT Central.
Pada TemperatureControllerSample.cs, metode PerformOperationsAsync
:
- Mengatur penangan untuk perintah reboot pada komponen default.
- Mengatur penangan untuk perintah getMaxMinReport pada dua komponen termostat.
- Mengatur penangan untuk menerima pembaruan properti suhu target pada dua komponen termostat.
- Mengirimkan pembaruan properti informasi perangkat awal.
- Secara berkala mengirimkan telemetri suhu dari dua komponen termostat.
- Secara berkala mengirimkan rangkaian aktif telemetri dari komponen default.
- Mengirimkan suhu maksimum sejak reboot terakhir setiap kali suhu maksimum baru tercapai di dua komponen termostat.
public async Task PerformOperationsAsync(CancellationToken cancellationToken)
{
await _deviceClient.SetMethodHandlerAsync("reboot", HandleRebootCommandAsync, _deviceClient, cancellationToken);
// For a component-level command, the command name is in the format "<component-name>*<command-name>".
await _deviceClient.SetMethodHandlerAsync("thermostat1*getMaxMinReport", HandleMaxMinReportCommand, Thermostat1, cancellationToken);
await _deviceClient.SetMethodHandlerAsync("thermostat2*getMaxMinReport", HandleMaxMinReportCommand, Thermostat2, cancellationToken);
await _deviceClient.SetDesiredPropertyUpdateCallbackAsync(SetDesiredPropertyUpdateCallback, null, cancellationToken);
_desiredPropertyUpdateCallbacks.Add(Thermostat1, TargetTemperatureUpdateCallbackAsync);
_desiredPropertyUpdateCallbacks.Add(Thermostat2, TargetTemperatureUpdateCallbackAsync);
await UpdateDeviceInformationAsync(cancellationToken);
await SendDeviceSerialNumberAsync(cancellationToken);
bool temperatureReset = true;
_maxTemp[Thermostat1] = 0d;
_maxTemp[Thermostat2] = 0d;
while (!cancellationToken.IsCancellationRequested)
{
if (temperatureReset)
{
// Generate a random value between 5.0°C and 45.0°C for the current temperature reading for each "Thermostat" component.
_temperature[Thermostat1] = Math.Round(s_random.NextDouble() * 40.0 + 5.0, 1);
_temperature[Thermostat2] = Math.Round(s_random.NextDouble() * 40.0 + 5.0, 1);
}
await SendTemperatureAsync(Thermostat1, cancellationToken);
await SendTemperatureAsync(Thermostat2, cancellationToken);
await SendDeviceMemoryAsync(cancellationToken);
temperatureReset = _temperature[Thermostat1] == 0 && _temperature[Thermostat2] == 0;
await Task.Delay(5 * 1000);
}
}
Metode SendTemperatureAsync
menunjukkan cara perangkat mengirim telemetri suhu dari komponen ke IoT Central. Metode SendTemperatureTelemetryAsync
menggunakan kelas PnpConvention
untuk membuat pesan:
private async Task SendTemperatureAsync(string componentName, CancellationToken cancellationToken)
{
await SendTemperatureTelemetryAsync(componentName, cancellationToken);
double maxTemp = _temperatureReadingsDateTimeOffset[componentName].Values.Max<double>();
if (maxTemp > _maxTemp[componentName])
{
_maxTemp[componentName] = maxTemp;
await UpdateMaxTemperatureSinceLastRebootAsync(componentName, cancellationToken);
}
}
private async Task SendTemperatureTelemetryAsync(string componentName, CancellationToken cancellationToken)
{
const string telemetryName = "temperature";
double currentTemperature = _temperature[componentName];
using Message msg = PnpConvention.CreateMessage(telemetryName, currentTemperature, componentName);
await _deviceClient.SendEventAsync(msg, cancellationToken);
if (_temperatureReadingsDateTimeOffset.ContainsKey(componentName))
{
_temperatureReadingsDateTimeOffset[componentName].TryAdd(DateTimeOffset.UtcNow, currentTemperature);
}
else
{
_temperatureReadingsDateTimeOffset.TryAdd(
componentName,
new Dictionary<DateTimeOffset, double>
{
{ DateTimeOffset.UtcNow, currentTemperature },
});
}
}
Metode UpdateMaxTemperatureSinceLastRebootAsync
mengirimkan pembaruan properti maxTempSinceLastReboot
ke IoT Central. Metode ini menggunakan PnpConvention
kelas untuk membuat patch:
private async Task UpdateMaxTemperatureSinceLastRebootAsync(string componentName, CancellationToken cancellationToken)
{
const string propertyName = "maxTempSinceLastReboot";
double maxTemp = _maxTemp[componentName];
TwinCollection reportedProperties = PnpConvention.CreateComponentPropertyPatch(componentName, propertyName, maxTemp);
await _deviceClient.UpdateReportedPropertiesAsync(reportedProperties, cancellationToken);
}
Metode TargetTemperatureUpdateCallbackAsync
menangani pembaruan properti suhu target bisa-tulis dari IoT Central. Metode ini menggunakan kelas PnpConvention
untuk membaca pesan pembaruan properti dan menyusun respons:
private async Task TargetTemperatureUpdateCallbackAsync(TwinCollection desiredProperties, object userContext)
{
const string propertyName = "targetTemperature";
string componentName = (string)userContext;
bool targetTempUpdateReceived = PnpConvention.TryGetPropertyFromTwin(
desiredProperties,
propertyName,
out double targetTemperature,
componentName);
if (!targetTempUpdateReceived)
{
return;
}
TwinCollection pendingReportedProperty = PnpConvention.CreateComponentWritablePropertyResponse(
componentName,
propertyName,
targetTemperature,
(int)StatusCode.InProgress,
desiredProperties.Version);
await _deviceClient.UpdateReportedPropertiesAsync(pendingReportedProperty);
// Update Temperature in 2 steps
double step = (targetTemperature - _temperature[componentName]) / 2d;
for (int i = 1; i <= 2; i++)
{
_temperature[componentName] = Math.Round(_temperature[componentName] + step, 1);
await Task.Delay(6 * 1000);
}
TwinCollection completedReportedProperty = PnpConvention.CreateComponentWritablePropertyResponse(
componentName,
propertyName,
_temperature[componentName],
(int)StatusCode.Completed,
desiredProperties.Version,
"Successfully updated target temperature");
await _deviceClient.UpdateReportedPropertiesAsync(completedReportedProperty);
}
Metode HandleMaxMinReportCommand
menangani perintah untuk komponen yang dipanggil dari IoT Central:
private Task<MethodResponse> HandleMaxMinReportCommand(MethodRequest request, object userContext)
{
try
{
string componentName = (string)userContext;
DateTime sinceInUtc = JsonConvert.DeserializeObject<DateTime>(request.DataAsJson);
var sinceInDateTimeOffset = new DateTimeOffset(sinceInUtc);
if (_temperatureReadingsDateTimeOffset.ContainsKey(componentName))
{
Dictionary<DateTimeOffset, double> allReadings = _temperatureReadingsDateTimeOffset[componentName];
Dictionary<DateTimeOffset, double> filteredReadings = allReadings.Where(i => i.Key > sinceInDateTimeOffset)
.ToDictionary(i => i.Key, i => i.Value);
if (filteredReadings != null && filteredReadings.Any())
{
var report = new
{
maxTemp = filteredReadings.Values.Max<double>(),
minTemp = filteredReadings.Values.Min<double>(),
avgTemp = filteredReadings.Values.Average(),
startTime = filteredReadings.Keys.Min(),
endTime = filteredReadings.Keys.Max(),
};
byte[] responsePayload = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(report));
return Task.FromResult(new MethodResponse(responsePayload, (int)StatusCode.Completed));
}
return Task.FromResult(new MethodResponse((int)StatusCode.NotFound));
}
return Task.FromResult(new MethodResponse((int)StatusCode.NotFound));
}
catch (JsonReaderException ex)
{
// ...
}
}
Mendapatkan informasi koneksi
Ketika Anda menjalankan aplikasi perangkat sampel dalam tutorial ini nanti, Anda memerlukan nilai konfigurasi berikut:
- Cakupan ID: Di aplikasi IoT Central Anda, navigasikan ke grup koneksi Perangkat Izin>. Catat nilai lingkup ID.
- Kunci utama grup: Di aplikasi IoT Central Anda, navigasikan ke Grup > koneksi Perangkat Izin > SAS-IoT-Devices. Catat nilai Kunci primer tanda tangan akses bersama.
Gunakan Azure Cloud Shell untuk menghasilkan kunci perangkat dari kunci utama grup yang Anda ambil:
az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>
Catat kunci perangkat yang dihasilkan, Anda gunakan nanti dalam tutorial ini.
Catatan
Untuk menjalankan sampel ini, Anda tidak perlu mendaftarkan perangkat terlebih dahulu di aplikasi IoT Central Anda. Sampel menggunakan kemampuan IoT Central untuk mendaftarkan perangkat secara otomatis saat tersambung untuk pertama kalinya.
Menjalankan kode
Catatan
Siapkan TemperatureController sebagai proyek startup sebelum Anda menjalankan kode.
Untuk menjalankan aplikasi sampel di Visual Studio:
Di Penjelajah Solusi, pilih file proyek PnpDeviceSamples > TemperatureController.
Navigasi ke Debug Properti > Pengontrol Suhu Proyek>. Kemudian, tambahkan variabel lingkungan berikut ke proyek:
Nama Nilai IOTHUB_DEVICE_SECURITY_TYPE DPS IOTHUB_DEVICE_DPS_ENDPOINT global.azure-devices-provisioning.net IOTHUB_DEVICE_DPS_ID_SCOPE Nilai cakupan ID yang Anda catat sebelumnya. IOTHUB_DEVICE_DPS_DEVICE_ID sample-device-01 IOTHUB_DEVICE_DPS_DEVICE_KEY Nilai kunci perangkat yang dibuat yang Anda catat sebelumnya.
Anda sekarang dapat menjalankan dan debug sampel di Visual Studio.
Output berikut menunjukkan perangkat mendaftar dan menghubungkan ke IoT Central. Sampel mulai mengirimkan telemetri:
[03/31/2021 14:43:17]info: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Press Control+C to quit the sample.
[03/31/2021 14:43:17]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Set up the device client.
[03/31/2021 14:43:18]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Initializing via DPS
[03/31/2021 14:43:27]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Set handler for 'reboot' command.
[03/31/2021 14:43:27]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Connection status change registered - status=Connected, reason=Connection_Ok.
[03/31/2021 14:43:28]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Set handler for "getMaxMinReport" command.
[03/31/2021 14:43:28]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Set handler to receive 'targetTemperature' updates.
[03/31/2021 14:43:28]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Property: Update - component = 'deviceInformation', properties update is complete.
[03/31/2021 14:43:28]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Property: Update - { "serialNumber": "SR-123456" } is complete.
[03/31/2021 14:43:29]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Telemetry: Sent - component="thermostat1", { "temperature": 34.2 } in °C.
[03/31/2021 14:43:29]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Property: Update - component="thermostat1", { "maxTempSinceLastReboot": 34.2 } in °C is complete.
[03/31/2021 14:43:29]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Telemetry: Sent - component="thermostat2", { "temperature": 25.1 } in °C.
[03/31/2021 14:43:29]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Property: Update - component="thermostat2", { "maxTempSinceLastReboot": 25.1 } in °C is complete.
[03/31/2021 14:43:29]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Telemetry: Sent - {"workingSet":31412} in KB.
Sebagai operator di aplikasi Azure IoT Central, Anda dapat:
Melihat telemetri yang dikirim oleh dua komponen termostat pada halaman Gambaran Umum:
Lihat properti perangkat pada halaman Tentang. Halaman ini menampilkan properti dari komponen informasi perangkat dan dua komponen termostat:
Menyesuaikan templat perangkat
Sebagai pengembang solusi, Anda dapat menyesuaikan templat perangkat yang dibuat IoT Central secara otomatis ketika perangkat pengontrol suhu terhubung.
Untuk menambahkan properti cloud untuk menyimpan nama pelanggan yang terkait dengan perangkat:
Di aplikasi IoT Central Anda, navigasikan ke templat perangkat Pengontrol Suhu pada halaman Templat perangkat.
Dalam model Pengontrol Suhu, pilih +Tambahkan kemampuan.
Masukkan Nama pelanggan sebagai Nama tampilan, pilih Properti cloud sebagai jenis kemampuan, perluas entri dan pilih String sebagai Skema. Kemudian pilih Simpan.
Untuk menyesuaikan cara perintah Mendapatkan laporan Max-Min ditampilkan di aplikasi IoT Central Anda:
Navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .
Untuk getMaxMinReport (termostat1), ganti laporan Get Max-Min. dengan dapatkan laporan status termostat1.
Untuk getMaxMinReport (termostat2), ganti laporan Get Max-Min. dengan dapatkan laporan status termostat2.
Pilih Simpan.
Untuk mengkustomisasi cara Suhu Target properti yang dapat ditulis ditampilkan di aplikasi IoT Central Anda:
Navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .
Untuk targetTemperature (thermostat1), ganti Suhu Target dengan Suhu Target (1).
Untuk targetTemperature (thermostat2), ganti Suhu Target dengan Suhu Target (2).
Pilih Simpan.
Komponen termostat dalam model Pengontrol Suhu termasuk properti yang dapat ditulis Suhu Target, templat perangkat termasuk properti cloud Nama Pelanggan. Membuat tampilan yang dapat digunakan operator untuk mengedit properti ini:
Pilih Tampilan lalu pilih petak Pengeditan perangkat dan data cloud.
Masukkan Properti sebagai nama formulir.
Pilih properti Suhu Target (1), Suhu Target (2), dan Nama Pelanggan. Kemudian pilih Tambahkan bagian.
Simpan perubahan Anda.
Menerbitkan templat perangkat
Sebelum operator dapat melihat dan menggunakan kustomisasi yang Anda buat, Anda harus menerbitkan templat perangkat.
Dari templat perangkat Termostat, pilih Terbitkan. Pada halaman Terbitkan template perangkat ini ke panel aplikasi, pilih Terbitkan.
Operator sekarang dapat menggunakan tampilan Properti untuk memperbarui nilai properti, dan perintah panggilan yang disebut Get thermostat1 status report dan Get thermostat2 status report di halaman perintah perangkat:
Perbarui nilai properti yang dapat ditulis pada halaman Properti:
Panggil perintah dari halaman Perintah. Jika Anda menjalankan perintah laporan status, pilih tanggal dan waktu untuk parameter Sejak sebelum Anda menjalankannya:
Anda dapat melihat bagaimana perangkat merespons perintah dan pembaruan properti:
[03/31/2021 14:47:00]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Command: Received - component="thermostat2", generating max, min and avg temperature report since 31/03/2021 06:00:00.
[03/31/2021 14:47:00]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Command: component="thermostat2", MaxMinReport since 31/03/2021 06:00:00: maxTemp=36.4, minTemp=36.4, avgTemp=36.4, startTime=31/03/2021 14:46:33, endTime=31/03/2021 14:46:55
...
[03/31/2021 14:46:36]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Property: Received - component="thermostat1", { "targetTemperature": 67°C }.
[03/31/2021 14:46:36]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Property: Update - component="thermostat1", {"targetTemperature": 67 } in °C is InProgress.
[03/31/2021 14:46:49]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Property: Update - component="thermostat1", {"targetTemperature": 67 } in °C is Completed
[03/31/2021 14:46:49]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
Telemetry: Sent - component="thermostat1", { "temperature": 67 } in °C.
Prasyarat
Untuk menyelesaikan langkah-langkah dalam artikel ini, Anda memerlukan sumber daya berikut:
Langganan Azure aktif. Jika Anda tidak memiliki langganan Azure, buat akun gratis sebelum Anda memulai.
Aplikasi IoT Central yang dibuat dari templat aplikasi Kustom. Untuk mempelajari lebih lanjut, lihat Membuat aplikasi IoT Central dan Tentang aplikasi Anda.
Mesin pengembangan dengan Java SE Development Kit 8 atau yang lebih baru. Untuk informasi selengkapnya, lihat Menginstal JDK.
Salinan lokal repositori GitHub Microsoft Azure IoT SDK for Java yang berisi kode contoh. Gunakan tautan ini untuk mengunduh salinan repositori: Unduh ZIP. Kemudian unzip file ke lokasi yang sesuai di komputer lokal Anda.
Mengulas kode
Dalam salinan Microsoft Azure IoT SDK untuk Java yang Anda unduh sebelumnya, buka file azure-iot-sdk-java/iothub/device/iot-device-samples/pnp-device-sample/temperature-controller-device-sample/src/main/java/samples/com/microsoft/azure/sdk/iot/device/TemperatureController.java di editor teks.
Sampel mengimplementasikan model Temperature Controller Digital Twin Definition Language multi-komponen.
Saat Anda menjalankan sampel untuk terhubung ke IoT Central, sampel tersebut menggunakan Device Provisioning Service (DPS) untuk mendaftarkan perangkat dan menghasilkan string koneksi. Sampel mengambil informasi koneksi DPS yang dibutuhkan dari lingkungan baris perintah.
Metode main
:
- Memanggil
initializeAndProvisionDevice
untuk menyeteldtmi:com:example:TemperatureController;2
model ID, menggunakan DPS untuk menyediakan dan mendaftarkan perangkat, membuat instance DeviceClient, dan menghubungkan ke aplikasi IoT Central Anda. IoT Central menggunakan ID model untuk mengidentifikasi atau membuat template perangkat untuk perangkat ini. Untuk mempelajari selengkapnya, lihat Menetapkan perangkat ke templat perangkat. - Membuat pengendali perintah untuk perintah
getMaxMinReport
danreboot
. - Membuat penangan pembaruan properti untuk properti
targetTemperature
yang dapat ditulis. - Mengirim nilai awal untuk properti di antarmuka Informasi Perangkat dan properti Memori Perangkat dan Nomor Seri.
- Memulai utas untuk mengirim telemetri suhu dari dua termostat dan memperbarui properti
maxTempSinceLastReboot
setiap lima detik.
public static void main(String[] args) throws Exception {
// ...
switch (deviceSecurityType.toLowerCase())
{
case "dps":
{
if (validateArgsForDpsFlow())
{
initializeAndProvisionDevice();
break;
}
throw new IllegalArgumentException("Required environment variables are not set for DPS flow, please recheck your environment.");
}
case "connectionstring":
{
// ...
}
default:
{
// ...
}
}
deviceClient.subscribeToMethods(new MethodCallback(), null);
deviceClient.subscribeToDesiredPropertiesAsync(
{
(twin, context) ->
TwinCollection desiredProperties = twin.getDesiredProperties();
for (String desiredPropertyKey : desiredProperties.keySet())
{
TargetTemperatureUpdateCallback.onPropertyChanged(new Property(desiredPropertyKey, desiredProperties.get(desiredPropertyKey)), null);
}
},
null,
(exception, context) ->
{
if (exception == null)
{
log.info("Successfully subscribed to desired properties. Getting initial state");
deviceClient.getTwinAsync(
(twin, getTwinException, getTwinContext) ->
{
log.info("Initial twin state received");
log.info(twin.toString());
},
null);
}
else
{
log.info("Failed to subscribe to desired properties. Error code {}", exception.getStatusCode());
System.exit(-1);
}
},
null);
updateDeviceInformation();
sendDeviceMemory();
sendDeviceSerialNumber();
final AtomicBoolean temperatureReset = new AtomicBoolean(true);
maxTemperature.put(THERMOSTAT_1, 0.0d);
maxTemperature.put(THERMOSTAT_2, 0.0d);
new Thread(new Runnable() {
@SneakyThrows({InterruptedException.class, IOException.class})
@Override
public void run() {
while (true) {
if (temperatureReset.get()) {
// Generate a random value between 5.0°C and 45.0°C for the current temperature reading for each "Thermostat" component.
temperature.put(THERMOSTAT_1, BigDecimal.valueOf(random.nextDouble() * 40 + 5).setScale(1, RoundingMode.HALF_UP).doubleValue());
temperature.put(THERMOSTAT_2, BigDecimal.valueOf(random.nextDouble() * 40 + 5).setScale(1, RoundingMode.HALF_UP).doubleValue());
}
sendTemperatureReading(THERMOSTAT_1);
sendTemperatureReading(THERMOSTAT_2);
temperatureReset.set(temperature.get(THERMOSTAT_1) == 0 && temperature.get(THERMOSTAT_2) == 0);
Thread.sleep(5 * 1000);
}
}
}).start();
}
Metode initializeAndProvisionDevice
menunjukkan bagaimana perangkat menggunakan DPS untuk mendaftar dan terhubung ke IoT Central. Payload mencakup ID model yang digunakan IoT Central untuk menetapkan perangkat ke templat perangkat:
private static void initializeAndProvisionDevice() throws Exception {
SecurityProviderSymmetricKey securityClientSymmetricKey = new SecurityProviderSymmetricKey(deviceSymmetricKey.getBytes(), registrationId);
ProvisioningDeviceClient provisioningDeviceClient;
ProvisioningStatus provisioningStatus = new ProvisioningStatus();
provisioningDeviceClient = ProvisioningDeviceClient.create(globalEndpoint, scopeId, provisioningProtocol, securityClientSymmetricKey);
AdditionalData additionalData = new AdditionalData();
additionalData.setProvisioningPayload(com.microsoft.azure.sdk.iot.provisioning.device.plugandplay.PnpHelper.createDpsPayload(MODEL_ID));
ProvisioningDeviceClientRegistrationResult registrationResult = provisioningDeviceClient.registerDeviceSync(additionalData);
ClientOptions options = ClientOptions.builder().modelId(MODEL_ID).build();
if (registrationResult.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_ASSIGNED) {
System.out.println("IotHUb Uri : " + registrationResult.getIothubUri());
System.out.println("Device ID : " + registrationResult.getDeviceId());
String iotHubUri = registrationResult.getIothubUri();
String deviceId = registrationResult.getDeviceId();
log.debug("Opening the device client.");
deviceClient = new DeviceClient(iotHubUri, deviceId, securityClientSymmetricKey, IotHubClientProtocol.MQTT, options);
deviceClient.open(true);
}
}
Metode sendTemperatureTelemetry
menunjukkan cara perangkat mengirim telemetri suhu dari komponen ke IoT Central. Metode ini menggunakan PnpConvention
kelas untuk membuat pesan:
private static void sendTemperatureTelemetry(String componentName) {
String telemetryName = "temperature";
double currentTemperature = temperature.get(componentName);
Message message = PnpConvention.createIotHubMessageUtf8(telemetryName, currentTemperature, componentName);
deviceClient.sendEventAsync(message, new MessageIotHubEventCallback(), message);
// Add the current temperature entry to the list of temperature readings.
Map<Date, Double> currentReadings;
if (temperatureReadings.containsKey(componentName)) {
currentReadings = temperatureReadings.get(componentName);
} else {
currentReadings = new HashMap<>();
}
currentReadings.put(new Date(), currentTemperature);
temperatureReadings.put(componentName, currentReadings);
}
Metode updateMaxTemperatureSinceLastReboot
mengirimkan maxTempSinceLastReboot
pembaruan properti dari komponen ke IoT Central. Metode ini menggunakan PnpConvention
kelas untuk membuat patch:
private static void updateMaxTemperatureSinceLastReboot(String componentName) throws IOException {
String propertyName = "maxTempSinceLastReboot";
double maxTemp = maxTemperature.get(componentName);
TwinCollection reportedProperty = PnpConvention.createComponentPropertyPatch(propertyName, maxTemp, componentName);
deviceClient.updateReportedPropertiesAsync(reportedProperty, sendReportedPropertiesResponseCallback, null);
log.debug("Property: Update - {\"{}\": {}°C} is {}.", propertyName, maxTemp, StatusCode.COMPLETED);
}
Kelas TargetTemperatureUpdateCallback
berisi metode onPropertyChanged
untuk menangani pembaruan properti yang dapat ditulis ke komponen dari IoT Central. Metode ini menggunakan PnpConvention
kelas untuk membuat respons:
private static class TargetTemperatureUpdateCallback
{
final static String propertyName = "targetTemperature";
@SneakyThrows(InterruptedException.class)
public static void onPropertyChanged(Property property, Object context) {
String componentName = (String) context;
if (property.getKey().equalsIgnoreCase(componentName)) {
double targetTemperature = (double) ((TwinCollection) property.getValue()).get(propertyName);
log.debug("Property: Received - component=\"{}\", {\"{}\": {}°C}.", componentName, propertyName, targetTemperature);
TwinCollection pendingPropertyPatch = PnpConvention.createComponentWritablePropertyResponse(
propertyName,
targetTemperature,
componentName,
StatusCode.IN_PROGRESS.value,
property.getVersion().longValue(),
null);
deviceClient.updateReportedPropertiesAsync(pendingPropertyPatch, sendReportedPropertiesResponseCallback, null);
log.debug("Property: Update - component=\"{}\", {\"{}\": {}°C} is {}", componentName, propertyName, targetTemperature, StatusCode.IN_PROGRESS);
// Update temperature in 2 steps
double step = (targetTemperature - temperature.get(componentName)) / 2;
for (int i = 1; i <=2; i++) {
temperature.put(componentName, BigDecimal.valueOf(temperature.get(componentName) + step).setScale(1, RoundingMode.HALF_UP).doubleValue());
Thread.sleep(5 * 1000);
}
TwinCollection completedPropertyPatch = PnpConvention.createComponentWritablePropertyResponse(
propertyName,
temperature.get(componentName),
componentName,
StatusCode.COMPLETED.value,
property.getVersion().longValue(),
"Successfully updated target temperature.");
deviceClient.updateReportedPropertiesAsync(completedPropertyPatch, sendReportedPropertiesResponseCallback, null);
log.debug("Property: Update - {\"{}\": {}°C} is {}", propertyName, temperature.get(componentName), StatusCode.COMPLETED);
} else {
log.debug("Property: Received an unrecognized property update from service.");
}
}
}
Kelas MethodCallback
berisi metode onMethodInvoked
untuk menangani perintah komponen yang dipanggil dari IoT Central:
private static class MethodCallback implements com.microsoft.azure.sdk.iot.device.twin.MethodCallback
{
final String reboot = "reboot";
final String getMaxMinReport1 = "thermostat1*getMaxMinReport";
final String getMaxMinReport2 = "thermostat2*getMaxMinReport";
@SneakyThrows(InterruptedException.class)
@Override
public DirectMethodResponse onMethodInvoked(String methodName, DirectMethodPayload methodData, Object context) {
String jsonRequest = methodData.getPayload(String.class);
switch (methodName) {
case reboot:
int delay = getCommandRequestValue(jsonRequest, Integer.class);
log.debug("Command: Received - Rebooting thermostat (resetting temperature reading to 0°C after {} seconds).", delay);
Thread.sleep(delay * 1000L);
temperature.put(THERMOSTAT_1, 0.0d);
temperature.put(THERMOSTAT_2, 0.0d);
maxTemperature.put(THERMOSTAT_1, 0.0d);
maxTemperature.put(THERMOSTAT_2, 0.0d);
temperatureReadings.clear();
return new DirectMethodResponse(StatusCode.COMPLETED.value, null);
case getMaxMinReport1:
case getMaxMinReport2:
String[] words = methodName.split("\\*");
String componentName = words[0];
if (temperatureReadings.containsKey(componentName)) {
Date since = getCommandRequestValue(jsonRequest, Date.class);
log.debug("Command: Received - component=\"{}\", generating min, max, avg temperature report since {}", componentName, since);
Map<Date, Double> allReadings = temperatureReadings.get(componentName);
Map<Date, Double> filteredReadings = allReadings.entrySet().stream()
.filter(map -> map.getKey().after(since))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
if (!filteredReadings.isEmpty()) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
double maxTemp = Collections.max(filteredReadings.values());
double minTemp = Collections.min(filteredReadings.values());
double avgTemp = filteredReadings.values().stream().mapToDouble(Double::doubleValue).average().orElse(Double.NaN);
String startTime = sdf.format(Collections.min(filteredReadings.keySet()));
String endTime = sdf.format(Collections.max(filteredReadings.keySet()));
String responsePayload = String.format(
"{\"maxTemp\": %.1f, \"minTemp\": %.1f, \"avgTemp\": %.1f, \"startTime\": \"%s\", \"endTime\": \"%s\"}",
maxTemp,
minTemp,
avgTemp,
startTime,
endTime);
log.debug("Command: MaxMinReport since {}: \"maxTemp\": {}°C, \"minTemp\": {}°C, \"avgTemp\": {}°C, \"startTime\": {}, \"endTime\": {}",
since,
maxTemp,
minTemp,
avgTemp,
startTime,
endTime);
return new DirectMethodResponse(StatusCode.COMPLETED.value, responsePayload);
}
log.debug("Command: component=\"{}\", no relevant readings found since {}, cannot generate any report.", componentName, since);
return new DirectMethodResponse(StatusCode.NOT_FOUND.value, null);
}
log.debug("Command: component=\"{}\", no temperature readings sent yet, cannot generate any report.", componentName);
return new DirectMethodResponse(StatusCode.NOT_FOUND.value, null);
default:
log.debug("Command: command=\"{}\" is not implemented, no action taken.", methodName);
return new DirectMethodResponse(StatusCode.NOT_FOUND.value, null);
}
}
}
Mendapatkan informasi koneksi
Ketika Anda menjalankan aplikasi perangkat sampel dalam tutorial ini nanti, Anda memerlukan nilai konfigurasi berikut:
- Cakupan ID: Di aplikasi IoT Central Anda, navigasikan ke grup koneksi Perangkat Izin>. Catat nilai lingkup ID.
- Kunci utama grup: Di aplikasi IoT Central Anda, navigasikan ke Grup > koneksi Perangkat Izin > SAS-IoT-Devices. Catat nilai Kunci primer tanda tangan akses bersama.
Gunakan Azure Cloud Shell untuk menghasilkan kunci perangkat dari kunci utama grup yang Anda ambil:
az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>
Catat kunci perangkat yang dihasilkan, Anda gunakan nanti dalam tutorial ini.
Catatan
Untuk menjalankan sampel ini, Anda tidak perlu mendaftarkan perangkat terlebih dahulu di aplikasi IoT Central Anda. Sampel menggunakan kemampuan IoT Central untuk mendaftarkan perangkat secara otomatis saat tersambung untuk pertama kalinya.
Di Windows, navigasikan ke folder akar repositori Azure IoT SDK untuk Java yang Anda unduh.
Jalankan perintah berikut untuk membangun aplikasi sampel:
mvn install -T 2C -DskipTests
Menjalankan kode
Untuk menjalankan aplikasi sampel, buka lingkungan baris perintah dan navigasikan ke folder azure-iot-sdk-java /iothub/device/iot-device-samples/pnp-device-sample/temperature-controller-device-sample folder yang berisi folder src dengan file sampel TemperatureController.java .
Atur variabel lingkungan untuk mengonfigurasi sampel. Cuplikan berikut menunjukkan bagaimana mengatur variabel lingkungan pada perintah Windows. Jika Anda menggunakan shell bash, ganti perintah set
dengan perintah export
:
set IOTHUB_DEVICE_SECURITY_TYPE=DPS
set IOTHUB_DEVICE_DPS_ID_SCOPE=<The ID scope you made a note of previously>
set IOTHUB_DEVICE_DPS_DEVICE_ID=sample-device-01
set IOTHUB_DEVICE_DPS_DEVICE_KEY=<The generated device key you made a note of previously>
set IOTHUB_DEVICE_DPS_ENDPOINT=global.azure-devices-provisioning.net
Jalankan sampel:
mvn exec:java -Dexec.mainClass="samples.com.microsoft.azure.sdk.iot.device.TemperatureController"
Output berikut menunjukkan perangkat mendaftar dan menghubungkan ke IoT Central. Sampel mulai mengirimkan telemetri:
2021-03-30 15:33:25.138 DEBUG TemperatureController:123 - Initialize the device client.
Waiting for Provisioning Service to register
Waiting for Provisioning Service to register
IotHUb Uri : iotc-60a.....azure-devices.net
Device ID : sample-device-01
2021-03-30 15:33:38.294 DEBUG TemperatureController:247 - Opening the device client.
2021-03-30 15:33:38.307 INFO ExponentialBackoffWithJitter:98 - NOTE: A new instance of ExponentialBackoffWithJitter has been created with the following properties. Retry Count: 2147483647, Min Backoff Interval: 100, Max Backoff Interval: 10000, Max Time Between Retries: 100, Fast Retry Enabled: true
2021-03-30 15:33:38.321 INFO ExponentialBackoffWithJitter:98 - NOTE: A new instance of ExponentialBackoffWithJitter has been created with the following properties. Retry Count: 2147483647, Min Backoff Interval: 100, Max Backoff Interval: 10000, Max Time Between Retries: 100, Fast Retry Enabled: true
2021-03-30 15:33:38.427 DEBUG MqttIotHubConnection:274 - Opening MQTT connection...
2021-03-30 15:33:38.427 DEBUG Mqtt:123 - Sending MQTT CONNECT packet...
2021-03-30 15:33:44.628 DEBUG Mqtt:126 - Sent MQTT CONNECT packet was acknowledged
2021-03-30 15:33:44.630 DEBUG Mqtt:256 - Sending MQTT SUBSCRIBE packet for topic devices/sample-device-01/messages/devicebound/#
2021-03-30 15:33:44.731 DEBUG Mqtt:261 - Sent MQTT SUBSCRIBE packet for topic devices/sample-device-01/messages/devicebound/# was acknowledged
2021-03-30 15:33:44.733 DEBUG MqttIotHubConnection:279 - MQTT connection opened successfully
2021-03-30 15:33:44.733 DEBUG IotHubTransport:302 - The connection to the IoT Hub has been established
2021-03-30 15:33:44.734 INFO IotHubTransport:1429 - Updating transport status to new status CONNECTED with reason CONNECTION_OK
2021-03-30 15:33:44.735 DEBUG IotHubTransport:1439 - Invoking connection status callbacks with new status details
2021-03-30 15:33:44.739 DEBUG IotHubTransport:394 - Client connection opened successfully
2021-03-30 15:33:44.740 INFO DeviceClient:438 - Device client opened successfully
2021-03-30 15:33:44.740 DEBUG TemperatureController:152 - Set handler for "reboot" command.
2021-03-30 15:33:44.742 DEBUG TemperatureController:153 - Set handler for "getMaxMinReport" command.
2021-03-30 15:33:44.774 INFO IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [029d30d4-acbd-462d-b155-82d53ce7786c] Message Id [1b2adf93-ba81-41e4-b8c7-7c90c8b0d6a1] Device Operation Type [DEVICE_OPERATION_METHOD_SUBSCRIBE_REQUEST] )
2021-03-30 15:33:44.774 DEBUG TemperatureController:156 - Set handler to receive "targetTemperature" updates.
2021-03-30 15:33:44.775 INFO IotHubTransport:1344 - Sending message ( Message details: Correlation Id [029d30d4-acbd-462d-b155-82d53ce7786c] Message Id [1b2adf93-ba81-41e4-b8c7-7c90c8b0d6a1] Device Operation Type [DEVICE_OPERATION_METHOD_SUBSCRIBE_REQUEST] )
2021-03-30 15:33:44.779 DEBUG Mqtt:256 - Sending MQTT SUBSCRIBE packet for topic $iothub/methods/POST/#
2021-03-30 15:33:44.793 INFO IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [f2f9ed95-9778-44f2-b9ec-f60c84061251] Message Id [0d5abdb2-6460-414c-a10e-786ee24cacff] Device Operation Type [DEVICE_OPERATION_TWIN_SUBSCRIBE_DESIRED_PROPERTIES_REQUEST] )
2021-03-30 15:33:44.794 INFO IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [417d659a-7324-43fa-84eb-8a3f3d07963c] Message Id [55532cad-8a5a-489f-9aa8-8f0e5bc21541] Request Id [0] Device Operation Type [DEVICE_OPERATION_TWIN_GET_REQUEST] )
2021-03-30 15:33:44.819 INFO IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [d46a0d8a-8a18-4014-abeb-768bd9b17ad2] Message Id [780abc81-ce42-4e5f-aa80-e4785883604e] Device Operation Type [DEVICE_OPERATION_TWIN_SUBSCRIBE_DESIRED_PROPERTIES_REQUEST] )
2021-03-30 15:33:44.881 DEBUG Mqtt:261 - Sent MQTT SUBSCRIBE packet for topic $iothub/methods/POST/# was acknowledged
2021-03-30 15:33:44.882 INFO IotHubTransport:1344 - Sending message ( Message details: Correlation Id [f2f9ed95-9778-44f2-b9ec-f60c84061251] Message Id [0d5abdb2-6460-414c-a10e-786ee24cacff] Device Operation Type [DEVICE_OPERATION_TWIN_SUBSCRIBE_DESIRED_PROPERTIES_REQUEST] )
2021-03-30 15:33:44.882 DEBUG Mqtt:256 - Sending MQTT SUBSCRIBE packet for topic $iothub/twin/res/#
2021-03-30 15:33:44.893 INFO IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [a77b1c02-f043-4477-b610-e31a774772c0] Message Id [2e2f6bee-c480-42cf-ac31-194118930846] Request Id [1] Device Operation Type [DEVICE_OPERATION_TWIN_UPDATE_REPORTED_PROPERTIES_REQUEST] )
2021-03-30 15:33:44.904 DEBUG TemperatureController:423 - Property: Update - component = "deviceInformation" is COMPLETED.
2021-03-30 15:33:44.915 INFO IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [bbb7e3cf-3550-4fdf-90f9-0787740f028a] Message Id [e06ac385-ae0d-46dd-857a-d9725707527a] )
2021-03-30 15:33:44.915 DEBUG TemperatureController:434 - Telemetry: Sent - {"workingSet": 1024.0KiB }
2021-03-30 15:33:44.915 INFO IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [6dbef765-cc9a-4e72-980a-2fe5b0cd77e1] Message Id [49bbad33-09bf-417a-9d6e-299ba7b7c562] Request Id [2] Device Operation Type [DEVICE_OPERATION_TWIN_UPDATE_REPORTED_PROPERTIES_REQUEST] )
2021-03-30 15:33:44.916 DEBUG TemperatureController:442 - Property: Update - {"serialNumber": SR-123456} is COMPLETED
2021-03-30 15:33:44.927 INFO IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [86787c32-87a5-4c49-9083-c7f2b17446a7] Message Id [0a45fa0c-a467-499d-b214-9bb5995772ba] )
2021-03-30 15:33:44.927 DEBUG TemperatureController:461 - Telemetry: Sent - {"temperature": 5.8°C} with message Id 0a45fa0c-a467-499d-b214-9bb5995772ba.
Sebagai operator di aplikasi Azure IoT Central, Anda dapat:
Melihat telemetri yang dikirim oleh dua komponen termostat pada halaman Gambaran Umum:
Lihat properti perangkat pada halaman Tentang. Halaman ini menampilkan properti dari komponen informasi perangkat dan dua komponen termostat:
Menyesuaikan templat perangkat
Sebagai pengembang solusi, Anda dapat menyesuaikan templat perangkat yang dibuat IoT Central secara otomatis ketika perangkat pengontrol suhu terhubung.
Untuk menambahkan properti cloud untuk menyimpan nama pelanggan yang terkait dengan perangkat:
Di aplikasi IoT Central Anda, navigasikan ke templat perangkat Pengontrol Suhu pada halaman Templat perangkat.
Dalam model Pengontrol Suhu, pilih +Tambahkan kemampuan.
Masukkan Nama pelanggan sebagai Nama tampilan, pilih Properti cloud sebagai jenis kemampuan, perluas entri dan pilih String sebagai Skema. Kemudian pilih Simpan.
Untuk menyesuaikan cara perintah Mendapatkan laporan Max-Min ditampilkan di aplikasi IoT Central Anda:
Navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .
Untuk getMaxMinReport (termostat1), ganti laporan Get Max-Min. dengan dapatkan laporan status termostat1.
Untuk getMaxMinReport (termostat2), ganti laporan Get Max-Min. dengan dapatkan laporan status termostat2.
Pilih Simpan.
Untuk mengkustomisasi cara Suhu Target properti yang dapat ditulis ditampilkan di aplikasi IoT Central Anda:
Navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .
Untuk targetTemperature (thermostat1), ganti Suhu Target dengan Suhu Target (1).
Untuk targetTemperature (thermostat2), ganti Suhu Target dengan Suhu Target (2).
Pilih Simpan.
Komponen termostat dalam model Pengontrol Suhu termasuk properti yang dapat ditulis Suhu Target, templat perangkat termasuk properti cloud Nama Pelanggan. Membuat tampilan yang dapat digunakan operator untuk mengedit properti ini:
Pilih Tampilan lalu pilih petak Pengeditan perangkat dan data cloud.
Masukkan Properti sebagai nama formulir.
Pilih properti Suhu Target (1), Suhu Target (2), dan Nama Pelanggan. Kemudian pilih Tambahkan bagian.
Simpan perubahan Anda.
Menerbitkan templat perangkat
Sebelum operator dapat melihat dan menggunakan kustomisasi yang Anda buat, Anda harus menerbitkan templat perangkat.
Dari templat perangkat Termostat, pilih Terbitkan. Pada halaman Terbitkan template perangkat ini ke panel aplikasi, pilih Terbitkan.
Operator sekarang dapat menggunakan tampilan Properti untuk memperbarui nilai properti, dan perintah panggilan yang disebut Get thermostat1 status report dan Get thermostat2 status report di halaman perintah perangkat:
Perbarui nilai properti yang dapat ditulis pada halaman Properti:
Panggil perintah dari halaman Perintah. Jika Anda menjalankan perintah laporan status, pilih tanggal dan waktu untuk parameter Sejak sebelum Anda menjalankannya:
Anda dapat melihat bagaimana perangkat merespons perintah dan pembaruan properti:
2021-03-30 15:43:57.133 DEBUG TemperatureController:309 - Command: Received - component="thermostat1", generating min, max, avg temperature report since Tue Mar 30 06:00:00 BST 2021
2021-03-30 15:43:57.153 DEBUG TemperatureController:332 - Command: MaxMinReport since Tue Mar 30 06:00:00 BST 2021: "maxTemp": 35.6°C, "minTemp": 35.6°C, "avgTemp": 35.6°C, "startTime": 2021-03-30T15:43:41Z, "endTime": 2021-03-30T15:43:56Z
2021-03-30 15:43:57.394 DEBUG TemperatureController:502 - Command - Response from IoT Hub: command name=null, status=OK_EMPTY
...
2021-03-30 15:48:47.808 DEBUG TemperatureController:372 - Property: Received - component="thermostat2", {"targetTemperature": 67.0°C}.
2021-03-30 15:48:47.837 DEBUG TemperatureController:382 - Property: Update - component="thermostat2", {"targetTemperature": 67.0°C} is IN_PROGRESS
Prasyarat
Untuk menyelesaikan langkah-langkah dalam artikel ini, Anda memerlukan sumber daya berikut:
Langganan Azure aktif. Jika Anda tidak memiliki langganan Azure, buat akun gratis sebelum Anda memulai.
Aplikasi IoT Central yang dibuat dari templat aplikasi Kustom. Untuk mempelajari lebih lanjut, lihat Membuat aplikasi IoT Central dan Tentang aplikasi Anda.
Komputer pengembangan dengan Node.js versi 6 atau yang lebih baru diinstal. Anda dapat menjalankan
node --version
di baris perintah untuk memeriksa versi Anda. Instruksi dalam tutorial ini mengasumsikan Anda menjalankan perintah node pada perintah Windows. Namun, Anda dapat menggunakan Node.js di banyak sistem operasi lain.Salinan lokal repositori GitHub Microsoft Azure IoT SDK untuk Node.js yang berisi kode sampel. Gunakan tautan ini untuk mengunduh salinan repositori: Unduh ZIP. Kemudian unzip file ke lokasi yang sesuai di komputer lokal Anda.
Mengulas kode
Dalam salinan Microsoft Azure IoT SDK untuk Node.js anda unduh sebelumnya, buka file azure-iot-sdk-node/device/samples/javascript/pnp_temperature_controller.js di editor teks.
Sampel mengimplementasikan model Temperature Controller Digital Twin Definition Language multi-komponen.
Saat Anda menjalankan sampel untuk terhubung ke IoT Central, sampel tersebut menggunakan Device Provisioning Service (DPS) untuk mendaftarkan perangkat dan menghasilkan string koneksi. Sampel mengambil informasi koneksi DPS yang dibutuhkan dari lingkungan baris perintah.
Metode main
:
- Membuat objek
client
dan mengatur ID modeldtmi:com:example:TemperatureController;2
sebelum membuka koneksi. IoT Central menggunakan ID model untuk mengidentifikasi atau membuat template perangkat untuk perangkat ini. Untuk mempelajari selengkapnya, lihat Menetapkan perangkat ke templat perangkat. - Membuat penangan perintah untuk tiga perintah.
- Memulai perulangan untuk setiap komponen termostat guna mengirimkan telemetri suhu setiap 5 detik.
- Memulai perulangan untuk komponen default guna mengirimkan rangkaian aktif telemetri ukuran setiap 6 detik.
- Mengirimkan properti
maxTempSinceLastReboot
untuk setiap komponen termostat. - Mengirimkan properti informasi perangkat.
- Membuat penangan properti bisa-tulis untuk tiga komponen.
async function main() {
// ...
// fromConnectionString must specify a transport, coming from any transport package.
const client = Client.fromConnectionString(deviceConnectionString, Protocol);
console.log('Connecting using connection string: ' + deviceConnectionString);
let resultTwin;
try {
// Add the modelId here
await client.setOptions(modelIdObject);
await client.open();
console.log('Enabling the commands on the client');
client.onDeviceMethod(commandNameGetMaxMinReport1, commandHandler);
client.onDeviceMethod(commandNameGetMaxMinReport2, commandHandler);
client.onDeviceMethod(commandNameReboot, commandHandler);
// Send Telemetry after some interval
let index1 = 0;
let index2 = 0;
let index3 = 0;
intervalToken1 = setInterval(() => {
const data = JSON.stringify(thermostat1.updateSensor().getCurrentTemperatureObject());
sendTelemetry(client, data, index1, thermostat1ComponentName).catch((err) => console.log('error ', err.toString()));
index1 += 1;
}, 5000);
intervalToken2 = setInterval(() => {
const data = JSON.stringify(thermostat2.updateSensor().getCurrentTemperatureObject());
sendTelemetry(client, data, index2, thermostat2ComponentName).catch((err) => console.log('error ', err.toString()));
index2 += 1;
}, 5500);
intervalToken3 = setInterval(() => {
const data = JSON.stringify({ workingset: 1 + (Math.random() * 90) });
sendTelemetry(client, data, index3, null).catch((err) => console.log('error ', err.toString()));
index3 += 1;
}, 6000);
// attach a standard input exit listener
exitListener(client);
try {
resultTwin = await client.getTwin();
// Only report readable properties
const patchRoot = helperCreateReportedPropertiesPatch({ serialNumber: serialNumber }, null);
const patchThermostat1Info = helperCreateReportedPropertiesPatch({
maxTempSinceLastReboot: thermostat1.getMaxTemperatureValue(),
}, thermostat1ComponentName);
const patchThermostat2Info = helperCreateReportedPropertiesPatch({
maxTempSinceLastReboot: thermostat2.getMaxTemperatureValue(),
}, thermostat2ComponentName);
const patchDeviceInfo = helperCreateReportedPropertiesPatch({
manufacturer: 'Contoso Device Corporation',
model: 'Contoso 47-turbo',
swVersion: '10.89',
osName: 'Contoso_OS',
processorArchitecture: 'Contoso_x86',
processorManufacturer: 'Contoso Industries',
totalStorage: 65000,
totalMemory: 640,
}, deviceInfoComponentName);
// the below things can only happen once the twin is there
updateComponentReportedProperties(resultTwin, patchRoot, null);
updateComponentReportedProperties(resultTwin, patchThermostat1Info, thermostat1ComponentName);
updateComponentReportedProperties(resultTwin, patchThermostat2Info, thermostat2ComponentName);
updateComponentReportedProperties(resultTwin, patchDeviceInfo, deviceInfoComponentName);
desiredPropertyPatchListener(resultTwin, [thermostat1ComponentName, thermostat2ComponentName, deviceInfoComponentName]);
} catch (err) {
console.error('could not retrieve twin or report twin properties\n' + err.toString());
}
} catch (err) {
console.error('could not connect Plug and Play client or could not attach interval function for telemetry\n' + err.toString());
}
}
Fungsi provisionDevice
menunjukkan bagaimana perangkat menggunakan DPS untuk mendaftar dan terhubung ke IoT Central. Payload mencakup ID model yang digunakan IoT Central untuk Menetapkan perangkat ke templat perangkat:
async function provisionDevice(payload) {
var provSecurityClient = new SymmetricKeySecurityClient(registrationId, symmetricKey);
var provisioningClient = ProvisioningDeviceClient.create(provisioningHost, idScope, new ProvProtocol(), provSecurityClient);
if (payload) {
provisioningClient.setProvisioningPayload(payload);
}
try {
let result = await provisioningClient.register();
deviceConnectionString = 'HostName=' + result.assignedHub + ';DeviceId=' + result.deviceId + ';SharedAccessKey=' + symmetricKey;
console.log('registration succeeded');
console.log('assigned hub=' + result.assignedHub);
console.log('deviceId=' + result.deviceId);
console.log('payload=' + JSON.stringify(result.payload));
} catch (err) {
console.error("error registering device: " + err.toString());
}
}
Fungsi sendTelemetry
menunjukkan cara perangkat mengirimkan telemetri suhu ke IoT Central. Untuk telemetri dari komponen, ia menambahkan properti yang disebut $.sub
dengan nama komponen:
async function sendTelemetry(deviceClient, data, index, componentName) {
if componentName) {
console.log('Sending telemetry message %d from component: %s ', index, componentName);
} else {
console.log('Sending telemetry message %d from root interface', index);
}
const msg = new Message(data);
if (componentName) {
msg.properties.add(messageSubjectProperty, componentName);
}
msg.contentType = 'application/json';
msg.contentEncoding = 'utf-8';
await deviceClient.sendEvent(msg);
}
Metode main
menggunakan metode bantuan yang disebut helperCreateReportedPropertiesPatch
untuk membuat pesan pembaruan properti. Metode ini mengambil parameter opsional untuk menentukan komponen yang mengirim properti:
const helperCreateReportedPropertiesPatch = (propertiesToReport, componentName) => {
let patch;
if (!!(componentName)) {
patch = { };
propertiesToReport.__t = 'c';
patch[componentName] = propertiesToReport;
} else {
patch = { };
patch = propertiesToReport;
}
if (!!(componentName)) {
console.log('The following properties will be updated for component: ' + componentName);
} else {
console.log('The following properties will be updated for root interface.');
}
console.log(patch);
return patch;
};
Metode main
menggunakan metode berikut untuk menangani pembaruan pada properti bisa-tulis dari IoT Central. Perhatikan bagaimana metode membangun respons dengan versi dan kode status:
const desiredPropertyPatchListener = (deviceTwin, componentNames) => {
deviceTwin.on('properties.desired', (delta) => {
console.log('Received an update for device with value: ' + JSON.stringify(delta));
Object.entries(delta).forEach(([key, values]) => {
const version = delta.$version;
if (!!(componentNames) && componentNames.includes(key)) { // then it is a component we are expecting
const componentName = key;
const patchForComponents = { [componentName]: {} };
Object.entries(values).forEach(([propertyName, propertyValue]) => {
if (propertyName !== '__t' && propertyName !== '$version') {
console.log('Will update property: ' + propertyName + ' to value: ' + propertyValue + ' of component: ' + componentName);
const propertyContent = { value: propertyValue };
propertyContent.ac = 200;
propertyContent.ad = 'Successfully executed patch';
propertyContent.av = version;
patchForComponents[componentName][propertyName] = propertyContent;
}
});
updateComponentReportedProperties(deviceTwin, patchForComponents, componentName);
}
else if (key !== '$version') { // individual property for root
const patchForRoot = { };
console.log('Will update property: ' + key + ' to value: ' + values + ' for root');
const propertyContent = { value: values };
propertyContent.ac = 200;
propertyContent.ad = 'Successfully executed patch';
propertyContent.av = version;
patchForRoot[key] = propertyContent;
updateComponentReportedProperties(deviceTwin, patchForRoot, null);
}
});
});
};
Metode main
menggunakan metode berikut untuk menangani perintah dari IoT Central:
const commandHandler = async (request, response) => {
helperLogCommandRequest(request);
switch (request.methodName) {
case commandNameGetMaxMinReport1: {
await sendCommandResponse(request, response, 200, thermostat1.getMaxMinReportObject());
break;
}
case commandNameGetMaxMinReport2: {
await sendCommandResponse(request, response, 200, thermostat2.getMaxMinReportObject());
break;
}
case commandNameReboot: {
await sendCommandResponse(request, response, 200, 'reboot response');
break;
}
default:
await sendCommandResponse(request, response, 404, 'unknown method');
break;
}
};
const sendCommandResponse = async (request, response, status, payload) => {
try {
await response.send(status, payload);
console.log('Response to method: ' + request.methodName + ' sent successfully.' );
} catch (err) {
console.error('An error occurred when sending a method response:\n' + err.toString());
}
};
Mendapatkan informasi koneksi
Ketika Anda menjalankan aplikasi perangkat sampel dalam tutorial ini nanti, Anda memerlukan nilai konfigurasi berikut:
- Cakupan ID: Di aplikasi IoT Central Anda, navigasikan ke grup koneksi Perangkat Izin>. Catat nilai lingkup ID.
- Kunci utama grup: Di aplikasi IoT Central Anda, navigasikan ke Grup > koneksi Perangkat Izin > SAS-IoT-Devices. Catat nilai Kunci primer tanda tangan akses bersama.
Gunakan Azure Cloud Shell untuk menghasilkan kunci perangkat dari kunci utama grup yang Anda ambil:
az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>
Catat kunci perangkat yang dihasilkan, Anda gunakan nanti dalam tutorial ini.
Catatan
Untuk menjalankan sampel ini, Anda tidak perlu mendaftarkan perangkat terlebih dahulu di aplikasi IoT Central Anda. Sampel menggunakan kemampuan IoT Central untuk mendaftarkan perangkat secara otomatis saat tersambung untuk pertama kalinya.
Menjalankan kode
Untuk menjalankan aplikasi sampel, buka lingkungan baris perintah dan navigasikan ke folder azure-iot-sdk-node /device/samples/javascript yang berisi file sampel pnp_temperature_controller.js .
Atur variabel lingkungan untuk mengonfigurasi sampel. Cuplikan berikut menunjukkan bagaimana mengatur variabel lingkungan pada perintah Windows. Jika Anda menggunakan shell bash, ganti perintah set
dengan perintah export
:
set IOTHUB_DEVICE_SECURITY_TYPE=DPS
set IOTHUB_DEVICE_DPS_ID_SCOPE=<The ID scope you made a note of previously>
set IOTHUB_DEVICE_DPS_DEVICE_ID=sample-device-01
set IOTHUB_DEVICE_DPS_DEVICE_KEY=<The generated device key you made a note of previously>
set IOTHUB_DEVICE_DPS_ENDPOINT=global.azure-devices-provisioning.net
Instal paket yang diperlukan:
npm install
Jalankan sampel:
node pnp_temperature_controller.js
Output berikut menunjukkan perangkat mendaftar dan menghubungkan ke IoT Central. Sampel kemudian mengirimkan properti maxTempSinceLastReboot
dari dua komponen termostat sebelum mulai mengirim telemetri:
registration succeeded
assigned hub=iotc-....azure-devices.net
deviceId=sample-device-01
payload=undefined
Connecting using connection string: HostName=iotc-....azure-devices.net;DeviceId=sample-device-01;SharedAccessKey=qdv...IpAo=
Enabling the commands on the client
Please enter q or Q to exit sample.
The following properties will be updated for root interface.
{ serialNumber: 'alwinexlepaho8329' }
The following properties will be updated for component: thermostat1
{ thermostat1: { maxTempSinceLastReboot: 1.5902294191855972, __t: 'c' } }
The following properties will be updated for component: thermostat2
{ thermostat2: { maxTempSinceLastReboot: 16.181771928614545, __t: 'c' } }
The following properties will be updated for component: deviceInformation
{ deviceInformation:
{ manufacturer: 'Contoso Device Corporation',
model: 'Contoso 47-turbo',
swVersion: '10.89',
osName: 'Contoso_OS',
processorArchitecture: 'Contoso_x86',
processorManufacturer: 'Contoso Industries',
totalStorage: 65000,
totalMemory: 640,
__t: 'c' } }
executed sample
Received an update for device with value: {"$version":1}
Properties have been reported for component: thermostat1
Properties have been reported for component: thermostat2
Properties have been reported for component: deviceInformation
Properties have been reported for root interface.
Sending telemetry message 0 from component: thermostat1
Sending telemetry message 0 from component: thermostat2
Sending telemetry message 0 from root interface
Sebagai operator di aplikasi Azure IoT Central, Anda dapat:
Melihat telemetri yang dikirim oleh dua komponen termostat pada halaman Gambaran Umum:
Lihat properti perangkat pada halaman Tentang. Halaman ini menampilkan properti dari komponen informasi perangkat dan dua komponen termostat:
Menyesuaikan templat perangkat
Sebagai pengembang solusi, Anda dapat menyesuaikan templat perangkat yang dibuat IoT Central secara otomatis ketika perangkat pengontrol suhu terhubung.
Untuk menambahkan properti cloud untuk menyimpan nama pelanggan yang terkait dengan perangkat:
Di aplikasi IoT Central Anda, navigasikan ke templat perangkat Pengontrol Suhu pada halaman Templat perangkat.
Dalam model Pengontrol Suhu, pilih +Tambahkan kemampuan.
Masukkan Nama pelanggan sebagai Nama tampilan, pilih Properti cloud sebagai jenis kemampuan, perluas entri dan pilih String sebagai Skema. Kemudian pilih Simpan.
Untuk menyesuaikan cara perintah Mendapatkan laporan Max-Min ditampilkan di aplikasi IoT Central Anda:
Navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .
Untuk getMaxMinReport (termostat1), ganti laporan Get Max-Min. dengan dapatkan laporan status termostat1.
Untuk getMaxMinReport (termostat2), ganti laporan Get Max-Min. dengan dapatkan laporan status termostat2.
Pilih Simpan.
Untuk mengkustomisasi cara Suhu Target properti yang dapat ditulis ditampilkan di aplikasi IoT Central Anda:
Navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .
Untuk targetTemperature (thermostat1), ganti Suhu Target dengan Suhu Target (1).
Untuk targetTemperature (thermostat2), ganti Suhu Target dengan Suhu Target (2).
Pilih Simpan.
Komponen termostat dalam model Pengontrol Suhu termasuk properti yang dapat ditulis Suhu Target, templat perangkat termasuk properti cloud Nama Pelanggan. Membuat tampilan yang dapat digunakan operator untuk mengedit properti ini:
Pilih Tampilan lalu pilih petak Pengeditan perangkat dan data cloud.
Masukkan Properti sebagai nama formulir.
Pilih properti Suhu Target (1), Suhu Target (2), dan Nama Pelanggan. Kemudian pilih Tambahkan bagian.
Simpan perubahan Anda.
Menerbitkan templat perangkat
Sebelum operator dapat melihat dan menggunakan kustomisasi yang Anda buat, Anda harus menerbitkan templat perangkat.
Dari templat perangkat Termostat, pilih Terbitkan. Pada halaman Terbitkan template perangkat ini ke panel aplikasi, pilih Terbitkan.
Operator sekarang dapat menggunakan tampilan Properti untuk memperbarui nilai properti, dan perintah panggilan yang disebut Get thermostat1 status report dan Get thermostat2 status report di halaman perintah perangkat:
Perbarui nilai properti yang dapat ditulis pada halaman Properti:
Panggil perintah dari halaman Perintah. Jika Anda menjalankan perintah laporan status, pilih tanggal dan waktu untuk parameter Sejak sebelum Anda menjalankannya:
Anda dapat melihat bagaimana perangkat merespons perintah dan pembaruan properti. Perintah getMaxMinReport
terdapat di komponen thermostat2
, perintah reboot
terdapat di komponen default. Properti targetTemperature
bisa-tulis disetel untuk thermostat2
komponen:
Received command request for command name: thermostat2*getMaxMinReport
The command request payload is:
2021-03-26T06:00:00.000Z
Response to method: thermostat2*getMaxMinReport sent successfully.
...
Received command request for command name: reboot
The command request payload is:
10
Response to method: reboot sent successfully.
...
Received an update for device with value: {"thermostat2":{"targetTemperature":76,"__t":"c"},"$version":2}
Will update property: targetTemperature to value: 76 of component: thermostat2
Properties have been reported for component: thermostat2
Prasyarat
Untuk menyelesaikan langkah-langkah dalam artikel ini, Anda memerlukan sumber daya berikut:
Langganan Azure aktif. Jika Anda tidak memiliki langganan Azure, buat akun gratis sebelum Anda memulai.
Aplikasi IoT Central yang dibuat dari templat aplikasi Kustom. Untuk mempelajari lebih lanjut, lihat Membuat aplikasi IoT Central dan Tentang aplikasi Anda.
Mesin pengembangan dengan Python terinstal. Periksa Azure IoT Python SDK untuk persyaratan versi Python saat ini. Anda dapat menjalankan
python --version
pada baris perintah untuk memeriksa versi Anda. Phyton tersedia untuk berbagai macam sistem operasi. Instruksi dalam tutorial ini mengasumsikan Anda menjalankan perintah python pada perintah Windows.Salinan lokal repositori GitHub Microsoft Azure IoT SDK untuk Python yang berisi kode sampel. Gunakan tautan ini untuk mengunduh salinan repositori: Unduh ZIP. Kemudian unzip file ke lokasi yang sesuai di komputer lokal Anda.
Mengulas kode
Dalam salinan Microsoft Azure IoT SDK untuk Python yang Anda unduh sebelumnya, buka file azure-iot-sdk-python/samples/pnp/temp_controller_with_thermostats.py di editor teks.
Sampel mengimplementasikan model Temperature Controller Digital Twin Definition Language multi-komponen.
Saat Anda menjalankan sampel untuk terhubung ke IoT Central, sampel tersebut menggunakan Device Provisioning Service (DPS) untuk mendaftarkan perangkat dan menghasilkan string koneksi. Sampel mengambil informasi koneksi DPS yang dibutuhkan dari lingkungan baris perintah.
Fungsi main
:
- Menggunakan DPS untuk memprovisikan perangkat. Informasi provisi menyertakan ID model. IoT Central menggunakan ID model untuk mengidentifikasi atau membuat template perangkat untuk perangkat ini. Untuk mempelajari selengkapnya, lihat Menetapkan perangkat ke templat perangkat.
- Membuat objek
Device_client
dan mengatur ID modeldtmi:com:example:TemperatureController;2
sebelum membuka koneksi. - Mengirim nilai properti awal ke IoT Central. Hal ini menggunakan
pnp_helper
untuk membuat patch. - Membuat pendengar untuk perintah
getMaxMinReport
danreboot
. Setiap komponen termostat memiliki perintahgetMaxMinReport
sendiri. - Membuat pendengar properti, untuk mendengarkan pembaruan properti bisa-tulis.
- Memulai perulangan untuk mengirim telemetri suhu dari dua komponen termostat dan bekerja mengatur telemetri dari komponen default setiap 8 detik.
async def main():
switch = os.getenv("IOTHUB_DEVICE_SECURITY_TYPE")
if switch == "DPS":
provisioning_host = (
os.getenv("IOTHUB_DEVICE_DPS_ENDPOINT")
if os.getenv("IOTHUB_DEVICE_DPS_ENDPOINT")
else "global.azure-devices-provisioning.net"
)
id_scope = os.getenv("IOTHUB_DEVICE_DPS_ID_SCOPE")
registration_id = os.getenv("IOTHUB_DEVICE_DPS_DEVICE_ID")
symmetric_key = os.getenv("IOTHUB_DEVICE_DPS_DEVICE_KEY")
registration_result = await provision_device(
provisioning_host, id_scope, registration_id, symmetric_key, model_id
)
if registration_result.status == "assigned":
print("Device was assigned")
print(registration_result.registration_state.assigned_hub)
print(registration_result.registration_state.device_id)
device_client = IoTHubDeviceClient.create_from_symmetric_key(
symmetric_key=symmetric_key,
hostname=registration_result.registration_state.assigned_hub,
device_id=registration_result.registration_state.device_id,
product_info=model_id,
)
else:
raise RuntimeError(
"Could not provision device. Aborting Plug and Play device connection."
)
elif switch == "connectionString":
# ...
# Connect the client.
await device_client.connect()
################################################
# Update readable properties from various components
properties_root = pnp_helper.create_reported_properties(serialNumber=serial_number)
properties_thermostat1 = pnp_helper.create_reported_properties(
thermostat_1_component_name, maxTempSinceLastReboot=98.34
)
properties_thermostat2 = pnp_helper.create_reported_properties(
thermostat_2_component_name, maxTempSinceLastReboot=48.92
)
properties_device_info = pnp_helper.create_reported_properties(
device_information_component_name,
swVersion="5.5",
manufacturer="Contoso Device Corporation",
model="Contoso 4762B-turbo",
osName="Mac Os",
processorArchitecture="x86-64",
processorManufacturer="Intel",
totalStorage=1024,
totalMemory=32,
)
property_updates = asyncio.gather(
device_client.patch_twin_reported_properties(properties_root),
device_client.patch_twin_reported_properties(properties_thermostat1),
device_client.patch_twin_reported_properties(properties_thermostat2),
device_client.patch_twin_reported_properties(properties_device_info),
)
################################################
# Get all the listeners running
print("Listening for command requests and property updates")
global THERMOSTAT_1
global THERMOSTAT_2
THERMOSTAT_1 = Thermostat(thermostat_1_component_name, 10)
THERMOSTAT_2 = Thermostat(thermostat_2_component_name, 10)
listeners = asyncio.gather(
execute_command_listener(
device_client, method_name="reboot", user_command_handler=reboot_handler
),
execute_command_listener(
device_client,
thermostat_1_component_name,
method_name="getMaxMinReport",
user_command_handler=max_min_handler,
create_user_response_handler=create_max_min_report_response,
),
execute_command_listener(
device_client,
thermostat_2_component_name,
method_name="getMaxMinReport",
user_command_handler=max_min_handler,
create_user_response_handler=create_max_min_report_response,
),
execute_property_listener(device_client),
)
################################################
# Function to send telemetry every 8 seconds
async def send_telemetry():
print("Sending telemetry from various components")
while True:
curr_temp_ext = random.randrange(10, 50)
THERMOSTAT_1.record(curr_temp_ext)
temperature_msg1 = {"temperature": curr_temp_ext}
await send_telemetry_from_temp_controller(
device_client, temperature_msg1, thermostat_1_component_name
)
curr_temp_int = random.randrange(10, 50) # Current temperature in Celsius
THERMOSTAT_2.record(curr_temp_int)
temperature_msg2 = {"temperature": curr_temp_int}
await send_telemetry_from_temp_controller(
device_client, temperature_msg2, thermostat_2_component_name
)
workingset_msg3 = {"workingSet": random.randrange(1, 100)}
await send_telemetry_from_temp_controller(device_client, workingset_msg3)
send_telemetry_task = asyncio.ensure_future(send_telemetry())
# ...
Fungsi provision_device
menggunakan DPS untuk memprovisikan perangkat dan mendaftarkannya ke IoT Central. Fungsi ini mencakup ID model perangkat, yang digunakan IoT Central untuk menetapkan perangkat ke templat perangkat, dalam payload provisi:
async def provision_device(provisioning_host, id_scope, registration_id, symmetric_key, model_id):
provisioning_device_client = ProvisioningDeviceClient.create_from_symmetric_key(
provisioning_host=provisioning_host,
registration_id=registration_id,
id_scope=id_scope,
symmetric_key=symmetric_key,
)
provisioning_device_client.provisioning_payload = {"modelId": model_id}
return await provisioning_device_client.register()
Fungsi execute_command_listener
menangani permintaan perintah, menjalankan fungsi max_min_handler
saat perangkat menerima perintah getMaxMinReport
untuk komponen termostat dan fungsi reboot_handler
saat perangkat menerima perintah reboot
. Hal ini menggunakan modul pnp_helper
untuk membuat respons:
async def execute_command_listener(
device_client,
component_name=None,
method_name=None,
user_command_handler=None,
create_user_response_handler=None,
):
while True:
if component_name and method_name:
command_name = component_name + "*" + method_name
elif method_name:
command_name = method_name
else:
command_name = None
command_request = await device_client.receive_method_request(command_name)
print("Command request received with payload")
values = command_request.payload
print(values)
if user_command_handler:
await user_command_handler(values)
else:
print("No handler provided to execute")
(response_status, response_payload) = pnp_helper.create_response_payload_with_status(
command_request, method_name, create_user_response=create_user_response_handler
)
command_response = MethodResponse.create_from_method_request(
command_request, response_status, response_payload
)
try:
await device_client.send_method_response(command_response)
except Exception:
print("responding to the {command} command failed".format(command=method_name))
async def execute_property_listener
menangani pembaruan properti bisa-tulis seperti targetTemperature
untuk komponen termostat dan membuat respons JSON. Hal ini menggunakan modul pnp_helper
untuk membuat respons:
async def execute_property_listener(device_client):
while True:
patch = await device_client.receive_twin_desired_properties_patch() # blocking call
print(patch)
properties_dict = pnp_helper.create_reported_properties_from_desired(patch)
await device_client.patch_twin_reported_properties(properties_dict)
Fungsi send_telemetry_from_temp_controller
mengirimkan pesan telemetri dari komponen termostat ke IoT Central. Hal ini menggunakan modul pnp_helper
untuk membuat pesan:
async def send_telemetry_from_temp_controller(device_client, telemetry_msg, component_name=None):
msg = pnp_helper.create_telemetry(telemetry_msg, component_name)
await device_client.send_message(msg)
print("Sent message")
print(msg)
await asyncio.sleep(5)
Mendapatkan informasi koneksi
Ketika Anda menjalankan aplikasi perangkat sampel dalam tutorial ini nanti, Anda memerlukan nilai konfigurasi berikut:
- Cakupan ID: Di aplikasi IoT Central Anda, navigasikan ke grup koneksi Perangkat Izin>. Catat nilai lingkup ID.
- Kunci utama grup: Di aplikasi IoT Central Anda, navigasikan ke Grup > koneksi Perangkat Izin > SAS-IoT-Devices. Catat nilai Kunci primer tanda tangan akses bersama.
Gunakan Azure Cloud Shell untuk menghasilkan kunci perangkat dari kunci utama grup yang Anda ambil:
az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>
Catat kunci perangkat yang dihasilkan, Anda gunakan nanti dalam tutorial ini.
Catatan
Untuk menjalankan sampel ini, Anda tidak perlu mendaftarkan perangkat terlebih dahulu di aplikasi IoT Central Anda. Sampel menggunakan kemampuan IoT Central untuk mendaftarkan perangkat secara otomatis saat tersambung untuk pertama kalinya.
Menjalankan kode
Untuk menjalankan aplikasi sampel, buka lingkungan baris perintah dan navigasikan ke folder azure-iot-sdk-python-2 /samples/pnp yang berisi file sampel temp_controller_with_thermostats.py .
Atur variabel lingkungan untuk mengonfigurasi sampel. Cuplikan berikut menunjukkan bagaimana mengatur variabel lingkungan pada perintah Windows. Jika Anda menggunakan shell bash, ganti perintah set
dengan perintah export
:
set IOTHUB_DEVICE_SECURITY_TYPE=DPS
set IOTHUB_DEVICE_DPS_ID_SCOPE=<The ID scope you made a note of previously>
set IOTHUB_DEVICE_DPS_DEVICE_ID=sample-device-01
set IOTHUB_DEVICE_DPS_DEVICE_KEY=<The generated device key you made a note of previously>
set IOTHUB_DEVICE_DPS_ENDPOINT=global.azure-devices-provisioning.net
Instal paket yang diperlukan:
pip install azure-iot-device
Jalankan sampel:
python temp_controller_with_thermostats.py
Output berikut menunjukkan perangkat mendaftar dan menghubungkan ke IoT Central. Sampel mengirimkan properti maxTempSinceLastReboot
dari dua komponen termostat sebelum mulai mengirim telemetri:
Device was assigned
iotc-60a.....azure-devices.net
sample-device-01
Updating pnp properties for root interface
{'serialNumber': 'alohomora'}
Updating pnp properties for thermostat1
{'thermostat1': {'maxTempSinceLastReboot': 98.34, '__t': 'c'}}
Updating pnp properties for thermostat2
{'thermostat2': {'maxTempSinceLastReboot': 48.92, '__t': 'c'}}
Updating pnp properties for deviceInformation
{'deviceInformation': {'swVersion': '5.5', 'manufacturer': 'Contoso Device Corporation', 'model': 'Contoso 4762B-turbo', 'osName': 'Mac Os', 'processorArchitecture': 'x86-64', 'processorManufacturer': 'Intel', 'totalStorage': 1024, 'totalMemory': 32, '__t': 'c'}}
Listening for command requests and property updates
Press Q to quit
Sending telemetry from various components
Sent message
{"temperature": 27}
Sent message
{"temperature": 17}
Sent message
{"workingSet": 13}
Sebagai operator di aplikasi Azure IoT Central, Anda dapat:
Melihat telemetri yang dikirim oleh dua komponen termostat pada halaman Gambaran Umum:
Lihat properti perangkat pada halaman Tentang. Halaman ini menampilkan properti dari komponen informasi perangkat dan dua komponen termostat:
Menyesuaikan templat perangkat
Sebagai pengembang solusi, Anda dapat menyesuaikan templat perangkat yang dibuat IoT Central secara otomatis ketika perangkat pengontrol suhu terhubung.
Untuk menambahkan properti cloud untuk menyimpan nama pelanggan yang terkait dengan perangkat:
Di aplikasi IoT Central Anda, navigasikan ke templat perangkat Pengontrol Suhu pada halaman Templat perangkat.
Dalam model Pengontrol Suhu, pilih +Tambahkan kemampuan.
Masukkan Nama pelanggan sebagai Nama tampilan, pilih Properti cloud sebagai jenis kemampuan, perluas entri dan pilih String sebagai Skema. Kemudian pilih Simpan.
Untuk menyesuaikan cara perintah Mendapatkan laporan Max-Min ditampilkan di aplikasi IoT Central Anda:
Navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .
Untuk getMaxMinReport (termostat1), ganti laporan Get Max-Min. dengan dapatkan laporan status termostat1.
Untuk getMaxMinReport (termostat2), ganti laporan Get Max-Min. dengan dapatkan laporan status termostat2.
Pilih Simpan.
Untuk mengkustomisasi cara Suhu Target properti yang dapat ditulis ditampilkan di aplikasi IoT Central Anda:
Navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .
Untuk targetTemperature (thermostat1), ganti Suhu Target dengan Suhu Target (1).
Untuk targetTemperature (thermostat2), ganti Suhu Target dengan Suhu Target (2).
Pilih Simpan.
Komponen termostat dalam model Pengontrol Suhu termasuk properti yang dapat ditulis Suhu Target, templat perangkat termasuk properti cloud Nama Pelanggan. Membuat tampilan yang dapat digunakan operator untuk mengedit properti ini:
Pilih Tampilan lalu pilih petak Pengeditan perangkat dan data cloud.
Masukkan Properti sebagai nama formulir.
Pilih properti Suhu Target (1), Suhu Target (2), dan Nama Pelanggan. Kemudian pilih Tambahkan bagian.
Simpan perubahan Anda.
Menerbitkan templat perangkat
Sebelum operator dapat melihat dan menggunakan kustomisasi yang Anda buat, Anda harus menerbitkan templat perangkat.
Dari templat perangkat Termostat, pilih Terbitkan. Pada halaman Terbitkan template perangkat ini ke panel aplikasi, pilih Terbitkan.
Operator sekarang dapat menggunakan tampilan Properti untuk memperbarui nilai properti, dan perintah panggilan yang disebut Get thermostat1 status report dan Get thermostat2 status report di halaman perintah perangkat:
Perbarui nilai properti yang dapat ditulis pada halaman Properti:
Panggil perintah dari halaman Perintah. Jika Anda menjalankan perintah laporan status, pilih tanggal dan waktu untuk parameter Sejak sebelum Anda menjalankannya:
Anda dapat melihat bagaimana perangkat merespons perintah dan pembaruan properti:
{'thermostat1': {'targetTemperature': 67, '__t': 'c'}, '$version': 2}
the data in the desired properties patch was: {'thermostat1': {'targetTemperature': 67, '__t': 'c'}, '$version': 2}
Values received are :-
{'targetTemperature': 67, '__t': 'c'}
Sent message
...
Command request received with payload
2021-03-31T05:00:00.000Z
Will return the max, min and average temperature from the specified time 2021-03-31T05:00:00.000Z to the current time
Done generating
{"avgTemp": 4.0, "endTime": "2021-03-31T12:29:48.322427", "maxTemp": 18, "minTemp": null, "startTime": "2021-03-31T12:28:28.322381"}
Menampilkan data mentah
Anda dapat menggunakan tampilan Data mentah untuk memeriksa data mentah yang dikirim perangkat Anda ke IoT Central:
Pada tampilan ini, Anda dapat memilih kolom yang akan ditampilkan dan mengatur rentang waktu untuk ditampilkan. Kolom Data yang tidak dimodifikasi memperlihatkan data perangkat yang tidak sesuai dengan definisi properti atau telemetri apa pun di templat perangkat.
Membersihkan sumber daya
Jika Anda tidak berencana untuk menyelesaikan mulai cepat atau tutorial IoT Central lebih lanjut, Anda dapat menghapus aplikasi IoT Central Anda:
- Di aplikasi IoT Central Anda, navigasikan ke Manajemen Aplikasi>.
- Pilih Hapus lalu konfirmasi tindakan Anda.
Langkah berikutnya
Jika Anda lebih suka melanjutkan melalui rangkaian tutorial IoT Central dan mempelajari lebih lanjut tentang membangun solusi IoT Central, lihat: