Bagikan melalui


Tutorial: Membuat dan menyambungkan aplikasi klien ke aplikasi Azure IoT Central Anda

Penting

Artikel ini mencakup langkah-langkah untuk menghubungkan perangkat menggunakan tanda tangan akses bersama, yang juga disebut autentikasi kunci simetris. Metode autentikasi ini mudah untuk pengujian dan evaluasi, tetapi mengautentikasi perangkat menggunakan sertifikat X.509 adalah pendekatan yang lebih aman. Untuk mempelajari selengkapnya, lihat Praktik terbaik keamanan untuk solusi > IoT Keamanan koneksi.

Tutorial ini menunjukkan kepada Anda cara menyambungkan aplikasi klien ke aplikasi Azure IoT Central Anda. Aplikasi ini mensimulasikan perilaku perangkat pengontrol suhu. Saat aplikasi terhubung ke IoT Central, aplikasi mengirimkan ID model 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 belajar cara:

  • Buat dan jalankan kode perangkat dan lihat terhubung ke aplikasi IoT Central Anda.
  • Lihat telemetri simulasi yang dikirim dari perangkat.
  • Tambahkan tampilan kustom ke templat perangkat.
  • Menerbitkan templat perangkat.
  • Gunakan tampilan untuk mengelola properti perangkat.
  • Panggil perintah untuk mengontrol perangkat.

Telusuri kode

Penting

Artikel ini mencakup langkah-langkah untuk menghubungkan perangkat menggunakan tanda tangan akses bersama, yang juga disebut autentikasi kunci simetris. Metode autentikasi ini mudah untuk pengujian dan evaluasi, tetapi mengautentikasi perangkat menggunakan sertifikat X.509 adalah pendekatan yang lebih aman. Untuk mempelajari selengkapnya, lihat Praktik terbaik keamanan untuk solusi > IoT Keamanan koneksi.

Prasyarat

Untuk menyelesaikan langkah-langkah dalam tutorial ini, Anda perlu:

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:

Instal GCC, Git, cmake, dan semua dependensi yang diperlukan menggunakan apt-get perintah:

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:

Mengunduh 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 SDK dan Pustaka ke lokasi ini:

git clone https://github.com/Azure/azure-iot-sdk-c.git
cd azure-iot-sdk-c
git submodule update --init

Perkirakan operasi ini akan memakan waktu beberapa menit untuk diselesaikan.

Meninjau kode

Dalam salinan Microsoft Azure IoT SDK untuk C yang Anda unduh sebelumnya, buka file 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 di editor teks.

Sampel ini mengimplementasikan model Bahasa Definisi Kembaran Digital Pengontrol Suhu dengan banyak komponen.

Saat Anda menjalankan sampel untuk menyambungkan ke IoT Central, sampel menggunakan Device Provisioning Service (DPS) untuk mendaftarkan perangkat dan menghasilkan string koneksi. Sampel mengambil informasi koneksi DPS yang diperlukan dari lingkungan baris perintah.

Di pnp_temperature_controller.c, fungsi tersebut pertama kali memanggil main untuk:

  • Atur ID model dtmi:com:example:Thermostat;1. IoT Central menggunakan ID model untuk mengidentifikasi atau menghasilkan templat perangkat untuk perangkat ini. Untuk mempelajari lebih lanjut, lihat Tetapkan perangkat ke template perangkat.
  • Gunakan DPS untuk menyediakan dan mendaftarkan perangkat.
  • Buat objek 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 selanjutnya:

  • Melaporkan beberapa nilai properti awal untuk semua komponen.
  • Memulai proses loop untuk mengirimkan data telemetri dari semua komponen.

Fungsi main kemudian memulai fungsi 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 bagaimana perangkat mengirimkan 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 pembaruan properti maxTempSinceLastReboot 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 dalam 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;
    }
}

Membangun kode

Anda menggunakan SDK perangkat untuk membuat kode sampel yang disertakan:

  1. Buat subdirektori cmake di folder root SDK perangkat, dan navigasikan ke folder tersebut:

    cd azure-iot-sdk-c
    mkdir cmake
    cd cmake
    
  2. Jalankan perintah berikut untuk membangun SDK dan sampel:

    cmake -Duse_prov_client=ON -Dhsm_type_symm_key=ON -Drun_e2e_tests=OFF ..
    cmake --build .
    

Mendapatkan informasi koneksi

Saat menjalankan aplikasi perangkat sampel nanti dalam tutorial ini, Anda memerlukan nilai konfigurasi berikut:

  • Cakupan ID: Di aplikasi IoT Central Anda, navigasikan ke Izin Grup koneksi perangkat.> Catat nilai cakupan ID .
  • Kunci utama grup: Di aplikasi IoT Central Anda, navigasikan ke Izin > Grup > koneksi perangkat SAS-IoT-Devices. Catat nilai kunci utama 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 menggunakannya nanti dalam tutorial ini.

Nota

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 terhubung untuk pertama kalinya.

Menjalankan kode

Untuk menjalankan aplikasi sampel, buka lingkungan baris perintah dan navigasikan ke folder azure-iot-sdk-c\cmake.

Atur variabel lingkungan untuk mengonfigurasi sampel. Cuplikan berikut menunjukkan cara mengatur variabel lingkungan pada prompt perintah Windows. Jika Anda menggunakan shell bash , ganti set perintah dengan export perintah:

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 yang mendaftar dan terhubung ke IoT Central. Sampel mulai mengirim 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 dalam aplikasi Azure IoT Central Anda, Anda dapat:

  • Lihat telemetri yang dikirim oleh dua komponen termostat di halaman Ikhtisar.

    Tangkapan layar yang menunjukkan halaman gambaran umum perangkat.

  • Lihat properti perangkat di halaman Tentang . Halaman ini menunjukkan properti dari komponen informasi perangkat dan dua komponen termostat:

    Cuplikan layar yang menunjukkan tampilan properti perangkat.

Menyesuaikan templat perangkat

Sebagai pengembang solusi, Anda dapat menyesuaikan templat perangkat yang dibuat IoT Central secara otomatis saat perangkat pengontrol suhu terhubung.

Untuk menambahkan properti cloud untuk menyimpan nama pelanggan yang terkait dengan perangkat:

  1. Di aplikasi IoT Central Anda, navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .

  2. Dalam model Pengontrol Suhu, pilih +Tambahkan kemampuan.

  3. Masukkan nama pelanggan sebagai Nama Tampilan, pilih properti Cloud sebagai jenis kemampuan, perluas entri dan pilih String sebagai Skema. Kemudian pilih Simpan.

Untuk menyesuaikan bagaimana perintah laporan Get Max-Min ditampilkan di aplikasi IoT Central Anda:

  1. Arahkan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .

  2. Untuk getMaxMinReport (thermostat1), ganti Dapatkan laporan Max-Min. dengan Dapatkan laporan status termostat1.

  3. Untuk getMaxMinReport (thermostat2), ganti Dapatkan laporan Max-Min. dengan Dapatkan laporan status thermostat2.

  4. Pilih Simpan.

Untuk menyesuaikan bagaimana properti yang dapat ditulis Suhu Target ditampilkan di aplikasi IoT Central Anda:

  1. Arahkan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .

  2. Untuk targetTemperature (thermostat1), ganti Target Temperature dengan Target Temperature (1).

  3. Untuk targetTemperature (thermostat2), ganti Target Temperature dengan Target Temperature (2).

  4. Pilih Simpan.

Komponen termostat dalam model Pengontrol Suhu menyertakan properti Suhu Target yang dapat ditulis, templat perangkat menyertakan properti cloud Nama Pelanggan . Buat tampilan yang dapat digunakan operator untuk mengedit properti berikut:

  1. Pilih Views lalu pilih ubin Mengedit perangkat dan data cloud.

  2. Masukkan Properti sebagai nama formulir.

  3. Pilih properti Suhu Target (1), Suhu Target (2), dan Nama Pelanggan . Kemudian pilih Tambahkan bagian.

  4. Simpan perubahan Anda.

Cuplikan layar yang menunjukkan tampilan untuk memperbarui nilai properti.

Menerbitkan templat perangkat

Sebelum operator dapat melihat dan menggunakan penyesuaian yang Anda buat, Anda harus menerbitkan templat perangkat.

Dari templat perangkat Termostat , pilih Terbitkan. Pada templat Terbitkan perangkat ini ke panel aplikasi , pilih Terbitkan.

Operator sekarang dapat menggunakan tampilan Properti untuk memperbarui nilai properti, dan memanggil perintah yang disebut Dapatkan laporan status termostat1 dan Dapatkan laporan status termostat2 di halaman perintah perangkat:

  • Perbarui nilai properti yang dapat ditulis di halaman Properti :

    Tangkapan layar yang menunjukkan pembaruan properti perangkat.

  • Panggil perintah dari halaman Perintah . Jika Anda menjalankan perintah laporan status, pilih tanggal dan waktu untuk parameter Since sebelum menjalankannya:

    Tangkapan layar yang menunjukkan pemanggilan perintah.

    Tangkapan layar yang menunjukkan respons perintah.

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

Telusuri kode

Penting

Artikel ini mencakup langkah-langkah untuk menghubungkan perangkat menggunakan tanda tangan akses bersama, yang juga disebut autentikasi kunci simetris. Metode autentikasi ini mudah untuk pengujian dan evaluasi, tetapi mengautentikasi perangkat menggunakan sertifikat X.509 adalah pendekatan yang lebih aman. Untuk mempelajari selengkapnya, lihat Praktik terbaik keamanan untuk solusi > IoT Keamanan koneksi.

Prasyarat

Untuk menyelesaikan langkah-langkah dalam artikel ini, Anda memerlukan sumber daya berikut:

Meninjau kode

Dalam salinan repositori Microsoft Azure IoT SDK untuk 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 ini mengimplementasikan model Bahasa Definisi Kembaran Digital Pengontrol Suhu dengan banyak komponen.

Saat Anda menjalankan sampel untuk menyambungkan ke IoT Central, sampel 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 ini Main memanggil SetupDeviceClientAsync :

  • Gunakan ID dtmi:com:example:TemperatureController;2 model saat mengonfigurasi perangkat dengan DPS. IoT Central menggunakan ID model untuk mengidentifikasi atau menghasilkan templat perangkat untuk perangkat ini. Untuk mempelajari lebih lanjut, lihat Tetapkan perangkat ke template 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 PerformOperationsAsync metode untuk menangani interaksi dengan IoT Central.

Pada TemperatureControllerSample.cs, PerformOperationsAsync metode tersebut:

  • Mengatur handler 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 mengirim telemetri set kerja 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 ini SendTemperatureAsync menunjukkan bagaimana perangkat mengirim telemetri suhu dari komponen ke IoT Central. Metode SendTemperatureTelemetryAsync menggunakan kelas PnpConvention untuk membangun 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 ini UpdateMaxTemperatureSinceLastRebootAsync mengirimkan maxTempSinceLastReboot pembaruan properti ke IoT Central. Metode ini menggunakan kelas PnpConvention 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 ini TargetTemperatureUpdateCallbackAsync menangani pembaruan properti suhu target yang dapat ditulis dari IoT Central. Metode ini menggunakan PnpConvention kelas untuk membaca pesan pembaruan properti dan membuat 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 ini 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

Saat menjalankan aplikasi perangkat sampel nanti dalam tutorial ini, Anda memerlukan nilai konfigurasi berikut:

  • Cakupan ID: Di aplikasi IoT Central Anda, navigasikan ke Izin Grup koneksi perangkat.> Catat nilai cakupan ID .
  • Kunci utama grup: Di aplikasi IoT Central Anda, navigasikan ke Izin > Grup > koneksi perangkat SAS-IoT-Devices. Catat nilai kunci utama 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 menggunakannya nanti dalam tutorial ini.

Nota

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 terhubung untuk pertama kalinya.

Menjalankan kode

Nota

Siapkan TemperatureController sebagai proyek startup sebelum Anda menjalankan kode.

Untuk menjalankan aplikasi sampel di Visual Studio:

  1. Di Penjelajah Solusi, pilih file proyek PnpDeviceSamples > TemperatureController .

  2. Navigasikan ke > Project TemperatureController Properties > Debug. 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 sampel-perangkat-01
    IOTHUB_DEVICE_DPS_DEVICE_KEY Nilai kunci perangkat yang dihasilkan yang Anda catat sebelumnya.

Anda sekarang dapat menjalankan dan men-debug sampel di Visual Studio.

Output berikut menunjukkan perangkat yang mendaftar dan terhubung ke IoT Central. Sampel mulai mengirim 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 dalam aplikasi Azure IoT Central Anda, Anda dapat:

  • Lihat telemetri yang dikirim oleh dua komponen termostat di halaman Ikhtisar.

    Tangkapan layar yang menunjukkan halaman gambaran umum perangkat.

  • Lihat properti perangkat di halaman Tentang . Halaman ini menunjukkan properti dari komponen informasi perangkat dan dua komponen termostat:

    Cuplikan layar yang menunjukkan tampilan properti perangkat.

Menyesuaikan templat perangkat

Sebagai pengembang solusi, Anda dapat menyesuaikan templat perangkat yang dibuat IoT Central secara otomatis saat perangkat pengontrol suhu terhubung.

Untuk menambahkan properti cloud untuk menyimpan nama pelanggan yang terkait dengan perangkat:

  1. Di aplikasi IoT Central Anda, navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .

  2. Dalam model Pengontrol Suhu, pilih +Tambahkan kemampuan.

  3. Masukkan nama pelanggan sebagai Nama Tampilan, pilih properti Cloud sebagai jenis kemampuan, perluas entri dan pilih String sebagai Skema. Kemudian pilih Simpan.

Untuk menyesuaikan bagaimana perintah laporan Get Max-Min ditampilkan di aplikasi IoT Central Anda:

  1. Arahkan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .

  2. Untuk getMaxMinReport (thermostat1), ganti Dapatkan laporan Max-Min. dengan Dapatkan laporan status termostat1.

  3. Untuk getMaxMinReport (thermostat2), ganti Dapatkan laporan Max-Min. dengan Dapatkan laporan status thermostat2.

  4. Pilih Simpan.

Untuk menyesuaikan bagaimana properti yang dapat ditulis Suhu Target ditampilkan di aplikasi IoT Central Anda:

  1. Arahkan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .

  2. Untuk targetTemperature (thermostat1), ganti Target Temperature dengan Target Temperature (1).

  3. Untuk targetTemperature (thermostat2), ganti Target Temperature dengan Target Temperature (2).

  4. Pilih Simpan.

Komponen termostat dalam model Pengontrol Suhu menyertakan properti Suhu Target yang dapat ditulis, templat perangkat menyertakan properti cloud Nama Pelanggan . Buat tampilan yang dapat digunakan operator untuk mengedit properti berikut:

  1. Pilih Views lalu pilih ubin Mengedit perangkat dan data cloud.

  2. Masukkan Properti sebagai nama formulir.

  3. Pilih properti Suhu Target (1), Suhu Target (2), dan Nama Pelanggan . Kemudian pilih Tambahkan bagian.

  4. Simpan perubahan Anda.

Cuplikan layar yang menunjukkan tampilan untuk memperbarui nilai properti.

Menerbitkan templat perangkat

Sebelum operator dapat melihat dan menggunakan penyesuaian yang Anda buat, Anda harus menerbitkan templat perangkat.

Dari templat perangkat Termostat , pilih Terbitkan. Pada templat Terbitkan perangkat ini ke panel aplikasi , pilih Terbitkan.

Operator sekarang dapat menggunakan tampilan Properti untuk memperbarui nilai properti, dan memanggil perintah yang disebut Dapatkan laporan status termostat1 dan Dapatkan laporan status termostat2 di halaman perintah perangkat:

  • Perbarui nilai properti yang dapat ditulis di halaman Properti :

    Tangkapan layar yang menunjukkan pembaruan properti perangkat.

  • Panggil perintah dari halaman Perintah . Jika Anda menjalankan perintah laporan status, pilih tanggal dan waktu untuk parameter Since sebelum menjalankannya:

    Tangkapan layar yang menunjukkan pemanggilan perintah.

    Tangkapan layar yang menunjukkan respons perintah.

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.

Telusuri kode

Penting

Artikel ini mencakup langkah-langkah untuk menghubungkan perangkat menggunakan tanda tangan akses bersama, yang juga disebut autentikasi kunci simetris. Metode autentikasi ini mudah untuk pengujian dan evaluasi, tetapi mengautentikasi perangkat menggunakan sertifikat X.509 adalah pendekatan yang lebih aman. Untuk mempelajari selengkapnya, lihat Praktik terbaik keamanan untuk solusi > IoT Keamanan koneksi.

Prasyarat

Untuk menyelesaikan langkah-langkah dalam artikel ini, Anda memerlukan sumber daya berikut:

  • Mesin 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 di command prompt Windows. Namun, Anda dapat menggunakan Node.js di banyak sistem operasi lainnya.

  • Salinan lokal dari repositori GitHub Microsoft Azure IoT SDK untuk Node.js yang berisi kode contoh. Gunakan tautan ini untuk mengunduh salinan repositori: Unduh ZIP. Kemudian buka zip file ke lokasi yang sesuai di mesin lokal Anda.

Meninjau kode

Dalam salinan Microsoft Azure IoT SDK untuk Node.js yang Anda unduh sebelumnya, buka file pnp_temperature_controller.jsazure-iot-sdk-node/device/samples/javascript/ di editor teks.

Sampel ini mengimplementasikan model Bahasa Definisi Kembaran Digital Pengontrol Suhu dengan banyak komponen.

Saat Anda menjalankan sampel untuk menyambungkan ke IoT Central, sampel menggunakan Device Provisioning Service (DPS) untuk mendaftarkan perangkat dan menghasilkan string koneksi. Sampel mengambil informasi koneksi DPS yang diperlukan dari lingkungan baris perintah.

Metode main:

  • Membuat client objek dan mengatur dtmi:com:example:TemperatureController;2 ID model sebelum membuka koneksi. IoT Central menggunakan ID model untuk mengidentifikasi atau menghasilkan templat perangkat untuk perangkat ini. Untuk mempelajari lebih lanjut, lihat Tetapkan perangkat ke template perangkat.
  • Membuat penangan perintah untuk tiga perintah.
  • Memulai loop pada setiap komponen termostat untuk mengirimkan telemetri suhu setiap 5 detik.
  • Memulai perulangan untuk komponen default untuk mengirim telemetri ukuran set kerja setiap 6 detik.
  • Mengirim maxTempSinceLastReboot properti untuk setiap komponen termostat.
  • Mengirim properti informasi perangkat.
  • Membuat pengendali properti yang dapat ditulis 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 ini 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 ini sendTelemetry menunjukkan bagaimana perangkat mengirimkan telemetri suhu ke IoT Central. Untuk telemetri dari komponen, ini menambahkan properti yang dipanggil $.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 ini main menggunakan metode pembantu yang dipanggil 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 pendekatan berikut untuk menangani pembaruan properti yang dapat ditulis 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 ini 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

Saat menjalankan aplikasi perangkat sampel nanti dalam tutorial ini, Anda memerlukan nilai konfigurasi berikut:

  • Cakupan ID: Di aplikasi IoT Central Anda, navigasikan ke Izin Grup koneksi perangkat.> Catat nilai cakupan ID .
  • Kunci utama grup: Di aplikasi IoT Central Anda, navigasikan ke Izin > Grup > koneksi perangkat SAS-IoT-Devices. Catat nilai kunci utama 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 menggunakannya nanti dalam tutorial ini.

Nota

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 terhubung 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 cara mengatur variabel lingkungan pada prompt perintah Windows. Jika Anda menggunakan shell bash , ganti set perintah dengan export perintah:

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 yang mendaftar dan terhubung ke IoT Central. Sampel kemudian mengirimkan maxTempSinceLastReboot properti dari dua buah 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 dalam aplikasi Azure IoT Central Anda, Anda dapat:

  • Lihat telemetri yang dikirim oleh dua komponen termostat di halaman Ikhtisar.

    Tangkapan layar yang menunjukkan halaman gambaran umum perangkat.

  • Lihat properti perangkat di halaman Tentang . Halaman ini menunjukkan properti dari komponen informasi perangkat dan dua komponen termostat:

    Cuplikan layar yang menunjukkan tampilan properti perangkat.

Menyesuaikan templat perangkat

Sebagai pengembang solusi, Anda dapat menyesuaikan templat perangkat yang dibuat IoT Central secara otomatis saat perangkat pengontrol suhu terhubung.

Untuk menambahkan properti cloud untuk menyimpan nama pelanggan yang terkait dengan perangkat:

  1. Di aplikasi IoT Central Anda, navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .

  2. Dalam model Pengontrol Suhu, pilih +Tambahkan kemampuan.

  3. Masukkan nama pelanggan sebagai Nama Tampilan, pilih properti Cloud sebagai jenis kemampuan, perluas entri dan pilih String sebagai Skema. Kemudian pilih Simpan.

Untuk menyesuaikan bagaimana perintah laporan Get Max-Min ditampilkan di aplikasi IoT Central Anda:

  1. Arahkan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .

  2. Untuk getMaxMinReport (thermostat1), ganti Dapatkan laporan Max-Min. dengan Dapatkan laporan status termostat1.

  3. Untuk getMaxMinReport (thermostat2), ganti Dapatkan laporan Max-Min. dengan Dapatkan laporan status thermostat2.

  4. Pilih Simpan.

Untuk menyesuaikan bagaimana properti yang dapat ditulis Suhu Target ditampilkan di aplikasi IoT Central Anda:

  1. Arahkan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .

  2. Untuk targetTemperature (thermostat1), ganti Target Temperature dengan Target Temperature (1).

  3. Untuk targetTemperature (thermostat2), ganti Target Temperature dengan Target Temperature (2).

  4. Pilih Simpan.

Komponen termostat dalam model Pengontrol Suhu menyertakan properti Suhu Target yang dapat ditulis, templat perangkat menyertakan properti cloud Nama Pelanggan . Buat tampilan yang dapat digunakan operator untuk mengedit properti berikut:

  1. Pilih Views lalu pilih ubin Mengedit perangkat dan data cloud.

  2. Masukkan Properti sebagai nama formulir.

  3. Pilih properti Suhu Target (1), Suhu Target (2), dan Nama Pelanggan . Kemudian pilih Tambahkan bagian.

  4. Simpan perubahan Anda.

Cuplikan layar yang menunjukkan tampilan untuk memperbarui nilai properti.

Menerbitkan templat perangkat

Sebelum operator dapat melihat dan menggunakan penyesuaian yang Anda buat, Anda harus menerbitkan templat perangkat.

Dari templat perangkat Termostat , pilih Terbitkan. Pada templat Terbitkan perangkat ini ke panel aplikasi , pilih Terbitkan.

Operator sekarang dapat menggunakan tampilan Properti untuk memperbarui nilai properti, dan memanggil perintah yang disebut Dapatkan laporan status termostat1 dan Dapatkan laporan status termostat2 di halaman perintah perangkat:

  • Perbarui nilai properti yang dapat ditulis di halaman Properti :

    Tangkapan layar yang menunjukkan pembaruan properti perangkat.

  • Panggil perintah dari halaman Perintah . Jika Anda menjalankan perintah laporan status, pilih tanggal dan waktu untuk parameter Since sebelum menjalankannya:

    Tangkapan layar yang menunjukkan pemanggilan perintah.

    Tangkapan layar yang menunjukkan respons perintah.

Anda dapat melihat bagaimana perangkat merespons perintah dan pembaruan properti. Perintah getMaxMinReport ada di thermostat2 komponen, reboot perintah ada di komponen default. Properti targetTemperature yang dapat ditulis diatur 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

Telusuri kode

Penting

Artikel ini mencakup langkah-langkah untuk menghubungkan perangkat menggunakan tanda tangan akses bersama, yang juga disebut autentikasi kunci simetris. Metode autentikasi ini mudah untuk pengujian dan evaluasi, tetapi mengautentikasi perangkat menggunakan sertifikat X.509 adalah pendekatan yang lebih aman. Untuk mempelajari selengkapnya, lihat Praktik terbaik keamanan untuk solusi > IoT Keamanan koneksi.

Prasyarat

Untuk menyelesaikan langkah-langkah dalam artikel ini, Anda memerlukan sumber daya berikut:

  • Mesin pengembangan dengan Python terinstal. Periksa Azure IoT Python SDK untuk persyaratan versi Python saat ini. Anda dapat menjalankan python --version di baris perintah untuk memeriksa versi Anda. Python tersedia untuk berbagai macam sistem operasi. Instruksi dalam tutorial ini mengasumsikan Anda menjalankan perintah python di prompt perintah Windows.

  • Salinan lokal repositori Microsoft Azure IoT SDK untuk Python GitHub yang berisi kode sampel. Gunakan tautan ini untuk mengunduh salinan repositori: Unduh ZIP. Kemudian buka zip file ke lokasi yang sesuai di mesin lokal Anda.

Meninjau 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 ini mengimplementasikan model Bahasa Definisi Kembaran Digital Pengontrol Suhu dengan banyak komponen.

Saat Anda menjalankan sampel untuk menyambungkan ke IoT Central, sampel menggunakan Device Provisioning Service (DPS) untuk mendaftarkan perangkat dan menghasilkan string koneksi. Sampel mengambil informasi koneksi DPS yang diperlukan dari lingkungan baris perintah.

Fungsi main :

  • Menggunakan DPS untuk menyediakan perangkat. Informasi provisi menyertakan ID model. IoT Central menggunakan ID model untuk mengidentifikasi atau menghasilkan templat perangkat untuk perangkat ini. Untuk mempelajari lebih lanjut, lihat Tetapkan perangkat ke template perangkat.
  • Membuat Device_client objek dan mengatur dtmi:com:example:TemperatureController;2 ID model sebelum membuka koneksi.
  • Mengirim nilai properti awal ke IoT Central. Ini menggunakan pnp_helper untuk membuat tambalan.
  • Membuat pendengar untuk perintah getMaxMinReport dan reboot. Setiap komponen termostat memiliki perintahnya sendiri getMaxMinReport .
  • Membuat pemroses properti, untuk mendengarkan pembaruan properti yang dapat ditulis.
  • Memulai loop untuk mengirimkan telemetri suhu dari dua komponen termostat dan telemetri kumpulan kerja 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 ini provision_device menggunakan DPS untuk menyediakan perangkat dan mendaftarkannya ke IoT Central. Fungsi ini mencakup ID model perangkat, yang digunakan IoT Central untuk menetapkan perangkat ke templat perangkat, dalam muatan penyediaan:

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 menangani execute_command_listener permintaan perintah, menjalankan max_min_handler fungsi saat perangkat menerima getMaxMinReport perintah untuk komponen termostat dan reboot_handler fungsi saat perangkat menerima reboot perintah. Ini menggunakan pnp_helper modul untuk membangun 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))

Memproses pembaruan properti yang dapat ditulis seperti async def execute_property_listener untuk komponen termostat dan menghasilkan respons JSON. Ini menggunakan pnp_helper modul untuk membangun 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 ini send_telemetry_from_temp_controller mengirimkan pesan telemetri dari komponen termostat ke IoT Central. Ini menggunakan pnp_helper modul untuk membangun 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

Saat menjalankan aplikasi perangkat sampel nanti dalam tutorial ini, Anda memerlukan nilai konfigurasi berikut:

  • Cakupan ID: Di aplikasi IoT Central Anda, navigasikan ke Izin Grup koneksi perangkat.> Catat nilai cakupan ID .
  • Kunci utama grup: Di aplikasi IoT Central Anda, navigasikan ke Izin > Grup > koneksi perangkat SAS-IoT-Devices. Catat nilai kunci utama 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 menggunakannya nanti dalam tutorial ini.

Nota

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 terhubung 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 cara mengatur variabel lingkungan pada prompt perintah Windows. Jika Anda menggunakan shell bash , ganti set perintah dengan export perintah:

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 yang mendaftar dan terhubung ke IoT Central. Sampel mengirimkan maxTempSinceLastReboot properti 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 dalam aplikasi Azure IoT Central Anda, Anda dapat:

  • Lihat telemetri yang dikirim oleh dua komponen termostat di halaman Ikhtisar.

    Tangkapan layar yang menunjukkan halaman gambaran umum perangkat.

  • Lihat properti perangkat di halaman Tentang . Halaman ini menunjukkan properti dari komponen informasi perangkat dan dua komponen termostat:

    Cuplikan layar yang menunjukkan tampilan properti perangkat.

Menyesuaikan templat perangkat

Sebagai pengembang solusi, Anda dapat menyesuaikan templat perangkat yang dibuat IoT Central secara otomatis saat perangkat pengontrol suhu terhubung.

Untuk menambahkan properti cloud untuk menyimpan nama pelanggan yang terkait dengan perangkat:

  1. Di aplikasi IoT Central Anda, navigasikan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .

  2. Dalam model Pengontrol Suhu, pilih +Tambahkan kemampuan.

  3. Masukkan nama pelanggan sebagai Nama Tampilan, pilih properti Cloud sebagai jenis kemampuan, perluas entri dan pilih String sebagai Skema. Kemudian pilih Simpan.

Untuk menyesuaikan bagaimana perintah laporan Get Max-Min ditampilkan di aplikasi IoT Central Anda:

  1. Arahkan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .

  2. Untuk getMaxMinReport (thermostat1), ganti Dapatkan laporan Max-Min. dengan Dapatkan laporan status termostat1.

  3. Untuk getMaxMinReport (thermostat2), ganti Dapatkan laporan Max-Min. dengan Dapatkan laporan status thermostat2.

  4. Pilih Simpan.

Untuk menyesuaikan bagaimana properti yang dapat ditulis Suhu Target ditampilkan di aplikasi IoT Central Anda:

  1. Arahkan ke templat perangkat Pengontrol Suhu di halaman Templat perangkat .

  2. Untuk targetTemperature (thermostat1), ganti Target Temperature dengan Target Temperature (1).

  3. Untuk targetTemperature (thermostat2), ganti Target Temperature dengan Target Temperature (2).

  4. Pilih Simpan.

Komponen termostat dalam model Pengontrol Suhu menyertakan properti Suhu Target yang dapat ditulis, templat perangkat menyertakan properti cloud Nama Pelanggan . Buat tampilan yang dapat digunakan operator untuk mengedit properti berikut:

  1. Pilih Views lalu pilih ubin Mengedit perangkat dan data cloud.

  2. Masukkan Properti sebagai nama formulir.

  3. Pilih properti Suhu Target (1), Suhu Target (2), dan Nama Pelanggan . Kemudian pilih Tambahkan bagian.

  4. Simpan perubahan Anda.

Cuplikan layar yang menunjukkan tampilan untuk memperbarui nilai properti.

Menerbitkan templat perangkat

Sebelum operator dapat melihat dan menggunakan penyesuaian yang Anda buat, Anda harus menerbitkan templat perangkat.

Dari templat perangkat Termostat , pilih Terbitkan. Pada templat Terbitkan perangkat ini ke panel aplikasi , pilih Terbitkan.

Operator sekarang dapat menggunakan tampilan Properti untuk memperbarui nilai properti, dan memanggil perintah yang disebut Dapatkan laporan status termostat1 dan Dapatkan laporan status termostat2 di halaman perintah perangkat:

  • Perbarui nilai properti yang dapat ditulis di halaman Properti :

    Tangkapan layar yang menunjukkan pembaruan properti perangkat.

  • Panggil perintah dari halaman Perintah . Jika Anda menjalankan perintah laporan status, pilih tanggal dan waktu untuk parameter Since sebelum menjalankannya:

    Tangkapan layar yang menunjukkan pemanggilan perintah.

    Tangkapan layar yang menunjukkan respons perintah.

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"}

Melihat data mentah

Anda dapat menggunakan tampilan data mentah untuk memeriksa data mentah yang dikirim perangkat Anda ke IoT Central:

Tangkapan layar yang menunjukkan tampilan data mentah.

Pada tampilan ini, Anda dapat memilih kolom yang akan ditampilkan dan mengatur rentang waktu untuk dilihat. Kolom Data Tidak Dimodelkan menampilkan data perangkat yang tidak cocok dengan definisi properti atau telemetri apa pun dalam templat perangkat.

Membersihkan sumber daya

Jika Anda tidak berencana untuk menyelesaikan panduan memulai cepat atau tutorial IoT Central yang lebih lanjut, Anda dapat menghapus aplikasi IoT Central Anda:

  1. Di aplikasi IoT Central Anda, navigasikan ke Manajemen Aplikasi>.
  2. Pilih Hapus , lalu konfirmasikan tindakan Anda.

Langkah selanjutnya

Jika Anda lebih suka melanjutkan melalui kumpulan tutorial IoT Central dan mempelajari selengkapnya tentang membangun solusi IoT Central, lihat: