Tutorial: Mengembangkan modul IoT Edge berbasis C menggunakan kontainer Windows

Berlaku untuk:yes icon Tepi IoT 1.1

Artikel ini akan menunjukkan cara menggunakan Visual Studio untuk mengembangkan kode C dan menyebarkannya ke perangkat Windows yang menjalankan Azure IoT Edge.

Catatan

IoT Edge 1.1 LTS adalah saluran rilis terakhir yang mendukung kontainer Windows. Mulai versi 1.2, kontainer Windows tidak lagi didukung. Pertimbangkan untuk menggunakan atau beralih ke IoT Edge untuk Linux di Windows untuk menjalankan IoT Edge di perangkat Windows.

Anda dapat menggunakan modul Azure IoT Edge untuk menyebarkan kode yang mengimplementasikan logika bisnis Anda secara langsung di perangkat IoT Edge. Tutorial ini akan memandu Anda membuat dan menyebarkan modul IoT Edge yang memfilter data sensor.

Dalam tutorial ini, Anda akan mempelajari cara:

  • Menggunakan Visual Studio untuk membuat modul IoT Edge berdasarkan SDK C.
  • Menggunakan Visual Studio dan Docker untuk membuat file salinan Docker dan menerbitkannya ke registri Anda.
  • Menyebarkan modul ke perangkat IoT Edge Anda.
  • Menampilkan data yang dibuat.

Modul IoT Edge yang dibuat dalam tutorial ini akan memfilter data suhu yang dihasilkan oleh perangkat Anda. Modul hanya akan mengirim pesan ke upstream jika suhu melebihi ambang batas yang ditentukan. Jenis analisis di tepi ini berguna untuk mengurangi jumlah data yang dikirim ke dan disimpan di cloud.

Jika Anda tidak memiliki langganan Azure, buatlah akun gratis sebelum Anda memulai.

Prasyarat

Tutorial ini menunjukkan cara mengembangkan modul dalam C menggunakan Visual Studio 2019, lalu menyebarkannya ke perangkat Windows. Jika Anda mengembangkan modul menggunakan kontainer Linux, buka Mengembangkan modul IoT Edge berbasis C menggunakan kontainer Linux sebagai gantinya.

Untuk memahami opsi Anda untuk mengembangkan dan menyebarkan modul C menggunakan kontainer Windows, lihat tabel berikut:

C Visual Studio Code Visual Studio 2017 dan 2019
Windows AMD64 Develop C modules for WinAMD64 in Visual Studio

Sebelum memulai tutorial ini, siapkan lingkungan pengembangan Anda dengan mengikuti petunjuk dalam tutorial Mengembangkan modul IoT Edge menggunakan kontainer Windows. Setelah menyelesaikannya, lingkungan Anda akan berisi prasyarat berikut:

Instal SDK C Azure IoT untuk Windows x64 melalui vcpkg dengan menjalankan perintah berikut:

git clone https://github.com/Microsoft/vcpkg
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg install azure-iot-sdk-c:x64-windows
.\vcpkg --triplet x64-windows integrate install

Tip

Jika Anda menggunakan Visual Studio 2017 (versi 15.7 atau yang lebih baru), unduh dan pasang Azure IoT Edge Tools untuk Visual Studio 2017 dari Visual Studio Marketplace.

Membuat proyek modul

Di bagian ini, Anda akan membuat proyek modul IoT Edge berdasarkan SDK C menggunakan Visual Studio dan ekstensi Azure IoT Edge Tools. Setelah membuat templat proyek, Anda akan menambahkan kode baru agar modul memfilter pesan berdasarkan properti yang dilaporkan.

Membuat proyek baru

Buat templat solusi C yang dapat Anda sesuaikan dengan kode Anda.

  1. Buka Visual Studio 2019, lalu pilih Buat Proyek Baru.

  2. Pada panel Buat proyek baru, cari IoT Edge, lalu pilih proyek Azure IoT Edge (Windows amd64) dalam daftar hasil.

    Screenshot of the IoT Edge

  3. Pilih Selanjutnya.

    Panel Konfigurasi proyek baru Anda akan terbuka.

    Screenshot of the

  4. Pada panel Konfigurasi proyek baru Anda, ganti nama proyek dan solusi menjadi nama yang lebih deskriptif, misalnya CTutorialApp.

  5. Pilih Buat untuk membuat proyek.

    Panel Tambahkan Modul akan terbuka.

    Screenshot of the

  6. Pada halaman Konfigurasi proyek Anda, ikuti langkah-langkah berikut ini:

    a. Di panel kiri, pilih templat Modul C.
    b. Dalam kotak Nama Modul, masukkan CModule.
    c. Dalam kotak Url Repositori, ganti localhost:5000 dengan nilai server Login dari registri kontainer Azure Anda, dalam format berikut:

    Catatan

    Repositori gambar mencakup nama registri kontainer dan nama citra kontainer Anda. Citra kontainer Anda telah diisi dengan nilai nama proyek modul. Anda dapat mengambil server masuk dari halaman ringkasan registri kontainer di portal Azure.

  7. Pilih Tambahkan untuk membuat proyek.

Menambahkan info masuk registri

Manifes penyebaran akan berbagi info masuk registri kontainer Anda dengan runtime IoT Edge. Runtime memerlukan info masuk ini untuk menarik citra privat pribadi Anda di perangkat IoT Edge. Gunakan info masuk dari bagian Kunci akses di registri kontainer Azure Anda.

  1. Di Penjelajah Solusi Visual Studio, buka file deployment.template.json.

  2. Cari properti registryCredentials dalam properti $edgeAgent yang diinginkan. Alamat registri properti akan terisi otomatis dengan informasi yang telah Anda berikan saat membuat proyek. Bidang nama pengguna dan kata sandi harus berisi nama variabel. Contohnya:

    "registryCredentials": {
      "<registry name>": {
        "username": "$CONTAINER_REGISTRY_USERNAME_<registry name>",
        "password": "$CONTAINER_REGISTRY_PASSWORD_<registry name>",
        "address": "<registry name>.azurecr.io"
      }
    }
    
  3. Buka file lingkungan (ENV) di solusi modul Anda. Secara default, file tersembunyi di Penjelajah Solusi, sehingga Anda mungkin perlu memilih tombol Perlihatkan Semua File untuk menampilkannya. File ENV harus berisi variabel nama pengguna dan kata sandi yang sama seperti yang Anda lihat dalam file deployment.template.json.

  4. Tambahkan nilai Nama Pengguna dan Kata Sandi dari registri kontainer Azure Anda.

  5. Simpan perubahan ke file ENV.

Memperbarui modul dengan kode kustom

Kode modul default akan menerima pesan dalam antrean input dan mengirimkannya melalui antrean output. Kita akan menambahkan beberapa kode lagi agar modul memproses pesan di tepi sebelum meneruskannya ke hub IoT Anda. Perbarui modul agar modul menganalisis data suhu di setiap pesan dan mengirimkan pesan ke hub IoT hanya jika suhu melebihi ambang batas tertentu.

  1. Data dari sensor dalam skenario ini tersedia dalam format JSON. Untuk memfilter pesan dalam format JSON, impor pustaka JSON untuk C. Tutorial ini menggunakan Parson.

    a. Unduh repositori GitHub Parson.
    b. Salin file parson.c dan parson.h ke proyek CModule.
    c. Di Visual Studio, buka file CMakeLists.txt dari folder proyek CModule.
    d. Di bagian atas file, impor file Parson sebagai pustaka bernama my_parson.

    add_library(my_parson
        parson.c
        parson.h
    )
    

    e. Tambahkan my_parson ke daftar pustaka di bagian "target_link_libraries" dari file my_parson
    f. Simpan file CMakeLists.txt.
    g. Pilih CModuleutama.c. Di bagian bawah daftar pernyataan include, tambahkan pernyataan baru untuk menyertakan parson.h untuk dukungan JSON:

    #include "parson.h"
    
  2. Dalam file utama.c, tambahkan variabel global yang disebut di samping messagesReceivedByInput1Queue variabel. Variabel ini menetapkan nilai ambang batas suhu yang diukur untuk data yang akan dikirim ke hub IoT Anda.

    static double temperatureThreshold = 25;
    
  3. Temukan CreateMessageInstance fungsinya di CreateMessageInstance. Ganti pernyataan di dalam if-else dengan kode berikut, yang menambahkan baris fungsionalitas baru:

    if ((messageInstance->messageHandle = IoTHubMessage_Clone(message)) == NULL)
    {
        free(messageInstance);
        messageInstance = NULL;
    }
    else
    {
        messageInstance->messageTrackingId = messagesReceivedByInput1Queue;
        MAP_HANDLE propMap = IoTHubMessage_Properties(messageInstance->messageHandle);
        if (Map_AddOrUpdate(propMap, "MessageType", "Alert") != MAP_OK)
        {
           printf("ERROR: Map_AddOrUpdate Failed!\r\n");
        }
    }
    

    Baris kode baru dalam pernyataan else menambahkan properti baru ke pesan, yang akan melabeli pesan sebagai peringatan. Kode ini melabeli semua pesan sebagai peringatan, karena kita akan menambahkan fungsionalitas yang mengirim pesan ke hub IoT hanya jika fungsi melaporkan suhu tinggi.

  4. Temukan fungsi InputQueue1Callback, lalu ganti seluruh kode dengan kode berikut. Fungsi ini mengimplementasikan filter olahpesan aktual. Ketika pesan diterima, fungsi akan memeriksa apakah suhu yang dilaporkan melebihi ambang batas. Jika suhu melebihi ambang batas, fungsi akan meneruskan pesan melalui antrean outputnya. Jika suhu tidak melebihi ambang batas, fungsi akan mengabaikan pesan.

    static unsigned char *bytearray_to_str(const unsigned char *buffer, size_t len)
    {
        unsigned char *ret = (unsigned char *)malloc(len + 1);
        memcpy(ret, buffer, len);
        ret[len] = '\0';
        return ret;
    }
    
    static IOTHUBMESSAGE_DISPOSITION_RESULT InputQueue1Callback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
    {
        IOTHUBMESSAGE_DISPOSITION_RESULT result;
        IOTHUB_CLIENT_RESULT clientResult;
        IOTHUB_MODULE_CLIENT_LL_HANDLE iotHubModuleClientHandle = (IOTHUB_MODULE_CLIENT_LL_HANDLE)userContextCallback;
    
        unsigned const char* messageBody;
        size_t contentSize;
    
        if (IoTHubMessage_GetByteArray(message, &messageBody, &contentSize) == IOTHUB_MESSAGE_OK)
        {
            messageBody = bytearray_to_str(messageBody, contentSize);
        } else
        {
            messageBody = "<null>";
        }
    
        printf("Received Message [%zu]\r\n Data: [%s]\r\n",
                messagesReceivedByInput1Queue, messageBody);
    
        // Check whether the message reports temperatures that exceed the threshold
        JSON_Value *root_value = json_parse_string(messageBody);
        JSON_Object *root_object = json_value_get_object(root_value);
        double temperature;
    
        // If temperature exceeds the threshold, send to output1
        if (json_object_dotget_value(root_object, "machine.temperature") != NULL && (temperature = json_object_dotget_number(root_object, "machine.temperature")) > temperatureThreshold)
        {
            printf("Machine temperature %f exceeds threshold %f\r\n", temperature, temperatureThreshold);
            // This message should be sent to next stop in the pipeline, namely "output1".  What happens at "outpu1" is determined
            // by the configuration of the Edge routing table setup.
            MESSAGE_INSTANCE *messageInstance = CreateMessageInstance(message);
            if (NULL == messageInstance)
            {
                result = IOTHUBMESSAGE_ABANDONED;
            }
            else
            {
                printf("Sending message (%zu) to the next stage in pipeline\n", messagesReceivedByInput1Queue);
    
                clientResult = IoTHubModuleClient_LL_SendEventToOutputAsync(iotHubModuleClientHandle, messageInstance->messageHandle, "output1", SendConfirmationCallback, (void *)messageInstance);
                if (clientResult != IOTHUB_CLIENT_OK)
                {
                    IoTHubMessage_Destroy(messageInstance->messageHandle);
                    free(messageInstance);
                    printf("IoTHubModuleClient_LL_SendEventToOutputAsync failed on sending msg#=%zu, err=%d\n", messagesReceivedByInput1Queue, clientResult);
                    result = IOTHUBMESSAGE_ABANDONED;
                }
                else
                {
                    result = IOTHUBMESSAGE_ACCEPTED;
                }
            }
        }
        // If message does not exceed the threshold, do not forward
        else
        {
            printf("Not sending message (%zu) to the next stage in pipeline.\r\n", messagesReceivedByInput1Queue);
            result = IOTHUBMESSAGE_ACCEPTED;
        }
    
        messagesReceivedByInput1Queue++;
        return result;
    }
    
  5. Tambahkan fungsi moduleTwinCallback. Metode ini menerima pembaruan terkait properti yang diinginkan dari dokumen modulnya, dan memperbarui variabel temperatureThreshold agar sesuai. Semua modul memiliki dokumen modulnya masing-masing, yang memungkinkan Anda mengonfigurasi kode yang berjalan di dalam modul langsung dari cloud.

    static void moduleTwinCallback(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* userContextCallback)
    {
        printf("\r\nTwin callback called with (state=%s, size=%zu):\r\n%s\r\n",
            MU_ENUM_TO_STRING(DEVICE_TWIN_UPDATE_STATE, update_state), size, payLoad);
        JSON_Value *root_value = json_parse_string(payLoad);
        JSON_Object *root_object = json_value_get_object(root_value);
        if (json_object_dotget_value(root_object, "desired.TemperatureThreshold") != NULL) {
            temperatureThreshold = json_object_dotget_number(root_object, "desired.TemperatureThreshold");
        }
        if (json_object_get_value(root_object, "TemperatureThreshold") != NULL) {
            temperatureThreshold = json_object_get_number(root_object, "TemperatureThreshold");
        }
    }
    
  6. Cari fungsi SetupCallbacksForModule. Ganti fungsi dengan kode berikut, yang menambahkan pernyataan else-if untuk memeriksa apakah dokumen modul telah diperbarui.

    static int SetupCallbacksForModule(IOTHUB_MODULE_CLIENT_LL_HANDLE iotHubModuleClientHandle)
    {
        int ret;
    
        if (IoTHubModuleClient_LL_SetInputMessageCallback(iotHubModuleClientHandle, "input1", InputQueue1Callback, (void*)iotHubModuleClientHandle) != IOTHUB_CLIENT_OK)
        {
            printf("ERROR: IoTHubModuleClient_LL_SetInputMessageCallback(\"input1\")..........FAILED!\r\n");
            ret = MU_FAILURE;
        }
        else if (IoTHubModuleClient_LL_SetModuleTwinCallback(iotHubModuleClientHandle, moduleTwinCallback, (void*)iotHubModuleClientHandle) != IOTHUB_CLIENT_OK)
        {
            printf("ERROR: IoTHubModuleClient_LL_SetModuleTwinCallback(default)..........FAILED!\r\n");
            ret = MU_FAILURE;
        }
        else
        {
            ret = 0;
        }
    
        return ret;
    }
    
  7. Simpan file main.c.

  8. Buka file deployment.template.json.

  9. Tambahkan dokumen modul CModule ke manifes penyebaran. Sisipkan konten JSON di bawah bagian moduleContent, setelah dokumen modul $edgeHub:

    "CModule": {
        "properties.desired":{
            "TemperatureThreshold":25
        }
    }
    

    Screenshot showing the module twin being added to the deployment template.

  10. Simpan file deployment.template.json.

Membangun dan mengirimkan modul Anda

Di bagian sebelumnya, Anda telah membuat solusi IoT Edge dan menambahkan kode ke CModule untuk memfilter pesan dengan suhu perangkat yang dilaporkan berada di bawah ambang batas yang dapat diterima. Sekarang Anda perlu membangun solusi sebagai file kontainer dan mengirimkannya ke registri kontainer.

Masuk ke Docker

Masukkan kredensial registri kontainer Anda ke Docker pada mesin pengembangan agar mesin dapat mengirimkan file kontainer untuk disimpan di registri.

  1. Buka PowerShell atau jendela Prompt Perintah.

  2. Masuk ke Docker dengan kredensial registri kontainer Azure yang Anda simpan setelah membuat registri.

    docker login -u <ACR username> -p <ACR password> <ACR login server>
    

    Anda mungkin akan menerima peringatan keamanan yang merekomendasikan penggunaan --password-stdin. Meskipun kami merekomendasikannya sebagai praktik terbaik untuk skenario produksi, rekomendasi tersebut di luar cakupan tutorial ini. Untuk informasi selengkapnya, lihat referensi masuk docker.

Membangun dan mendorong

komputer pengembangan kini memiliki akses ke registri kontainer, dan perangkat Azure IoT Edge Anda juga akan memilikinya. Kini saatnya untuk mengubah kode proyek menjadi file kontainer.

  1. Di Penjelajah Solusi Visual Studio, klik kanan nama proyek yang ingin Anda bangun. Nama defaultnya adalah AzureIotEdgeApp1. Untuk tutorial ini, kami memilih nama CTutorialApp dan karena Anda sedang membangun modul Windows, ekstensi harus menggunakan Windows.Amd64.

  2. Pilih Bangun dan Kirim Modul IoT Edge.

    Perintah bangun dan dorong akan memulai tiga operasi:

    • Pertama, perintah ini akan membuat folder baru dalam solusi bernama config, yang menyimpan seluruh manifes penyebaran. Manifes ini dibangun dari informasi dalam template penyebaran dan file solusi lainnya.
    • Kedua, perintah menjalankan docker build untuk membangun citra kontainer, berdasarkan Dockerfile yang sesuai untuk arsitektur target Anda.
    • Terakhir, perintah menjalankan docker push untuk mendorong repositori citra ke registri kontainer Anda.

    Proses ini mungkin akan memakan waktu beberapa menit saat dijalankan pertama kali, tetapi pada kali berikutnya Anda menjalankan perintah, proses ini akan menjadi lebih cepat.

Menyebarkan modul ke perangkat

Gunakan Visual Studio Cloud Explorer dan ekstensi Azure IoT Edge Tools untuk menyebarkan proyek modul ke perangkat IoT Edge Anda. Anda telah menyiapkan manifes penyebaran untuk skenario Anda, yaitu file deployment.windows-amd64.json dalam folder config. Sekarang Anda hanya perlu memilih perangkat untuk menerima penyebaran.

Pastikan perangkat IoT Edge Anda sudah siap.

  1. Di Visual Studio Cloud Explorer, perluas sumber daya untuk menampilkan daftar perangkat IoT Anda.

  2. Klik kanan nama perangkat IoT Edge penerima penyebaran.

  3. Pilih Buat Penyebaran.

  4. Di Visual Studio File Explorer, pilih file deployment.windows-amd64.json dalam folder config di solusi Anda.

  5. Refresh Cloud Explorer untuk melihat modul yang disebarkan yang tercantum di bawah perangkat Anda.

Melihat data yang dihasilkan

Setelah manifes penyebaran diterapkan di perangkat IoT Edge Anda, runtime IoT Edge pada perangkat akan mengumpulkan informasi penyebaran baru dan mulai mengeksekusinya. Setiap modul yang dijalankan di perangkat tetapi tidak disertakan dalam manifes penyebaran akan dihentikan. Setiap modul yang tidak tersedia di perangkat akan dimulai.

Anda dapat menggunakan ekstensi IoT Edge Tools untuk menampilkan pesan saat pesan masuk di hub IoT.

  1. Di Visual Studio Cloud Explorer, pilih nama perangkat IoT Edge Anda.

  2. Dalam daftar Tindakan, pilih Mulai Pemantauan Titik Akhir Peristiwa Bawaan.

  3. Tampilkan pesan yang masuk di hub IoT Anda. Mungkin diperlukan waktu beberapa saat untuk menerima pesan karena perangkat IoT Edge harus menerima penyebaran barunya dan memulai semua modul. Perubahan pada kode CModule harus menunggu hingga suhu mesin mencapai 25 derajat sebelum pesan dapat dikirim. Kode ini juga menambahkan tipe pesan Peringatan ke setiap pesan yang mencapai ambang batas suhu tersebut.

    Screenshot of the Output window displaying messages that are arriving at the IoT hub.

Mengedit dokumen modul

Anda menggunakan dokumen modul CModule untuk mengatur ambang suhu pada 25 derajat. Anda dapat menggunakan dokumen modul untuk mengubah fungsionalitas tanpa perlu memperbarui kode modul.

  1. Di Visual Studio, buka file deployment.windows-amd64.json.

    Jangan buka file deployment.template. Jika Anda tidak melihat manifes penyebaran dalam file config di Penjelajah Solusi, pilih ikon Perlihatkan semua file di toolbar Solution Explorer.

  2. Cari dokumen CModule, lalu ubah nilai parameter temperatureThreshold menjadi suhu baru antara 5 hingga 10 derajat lebih tinggi dibandingkan suhu yang dilaporkan terakhir.

  3. Simpan file deployment.windows-amd64.json.

  4. Ikuti lagi petunjuk penyebaran untuk menerapkan manifes penyebaran yang diperbarui ke perangkat Anda.

  5. Pantau pesan perangkat ke cloud yang masuk. Pesan akan berhenti hingga ambang batas suhu baru tercapai.

Membersihkan sumber daya

Jika berencana untuk melanjutkan ke rekomendasi artikel berikutnya, Anda dapat menyimpan dan menggunakan kembali sumber daya dan konfigurasi yang Anda buat dalam tutorial ini. Anda juga dapat tetap menggunakan perangkat IoT Edge yang sama sebagai perangkat uji.

Atau, agar tidak dikenai biaya, Anda dapat menghapus konfigurasi lokal dan sumber daya Azure yang digunakan di sini.

Menghapus sumber daya Azure

Menghapus sumber daya Azure dan grup sumber daya tidak dapat diubah. Pastikan Anda tidak menghapus grup sumber daya atau sumber daya yang salah secara tidak sengaja. Jika Anda membuat hub IoT di dalam grup sumber daya yang sudah ada yang berisi sumber daya yang ingin Anda simpan, hapus hanya sumber daya hub IoT itu sendiri, bukan grup sumber daya.

Untuk menghapus sumber daya:

  1. Masuk ke portal Microsoft Azure, lalu pilih Grup sumber daya.

  2. Pilih nama grup sumber daya yang berisi sumber daya pengujian IoT Edge Anda.

  3. Tinjau daftar sumber daya yang terdapat dalam grup sumber daya Anda. Jika ingin menghapus semuanya, Anda dapat memilih Hapus grup sumber daya. Jika hanya ingin menghapus beberapa sumber daya, Anda dapat mengklik setiap sumber daya untuk menghapusnya satu per satu.

Langkah berikutnya

Dalam tutorial ini, Anda telah membuat modul IoT Edge dengan kode untuk memfilter data mentah yang dibuat oleh perangkat IoT Edge.

Untuk mempelajari bagaimana Azure IoT Edge dapat membantu Anda menyebarkan layanan awan Azure untuk memproses dan menganalisis data di tepi, lanjutkan ke tutorial berikutnya.