بدء استخدام الهوية الخاصة بوحدة IoT Hub والوحدة النمطية المزدوجة (C)

تتشابه هويات الوحدة وتوائم الوحدة النمطيةمع هوية معرف جهاز Azure IoT Hub وجهاز التوأم، ولكنها توفر دقة فائقة. في حين أن هوية معرف جهاز Azure IoT Hub وتوائم الجهاز تمكن التطبيق الخلفي من تكوين جهاز وتوفر رؤية على ظروف الجهاز، توفر هوية الوحدة النمطية والوحدة المزدوجة هذه الإمكانات للمكونات الفردية للجهاز. على الأجهزة القادرة ذات المكونات المتعددة، مثل أجهزة نظام التشغيل أو أجهزة البرامج الثابتة، فإنه يسمح بتكوينات وشروط معزولة لكل مكون.

ملاحظة

الميزات الموضحة في هذه المقالة متوفرة فقط في المستوى القياسي لـ IoT Hub. لمزيد من المعلومات حول مستويات IoT Hub الأساسية والقياسية/المجانية، راجع اختيار طبقة IoT Hub المناسبة للحل الخاص بك.

في نهاية هذه المقالة، لديك اثنين من تطبيقات C:

  • CreateIdentities: يُنشئ هوية جهاز وهوية الوحدة ومفتاح أمان مرتبط لتوصيل جهازك الخاص وعملاء الوحدة.

  • UpdateModuleTwinReportedProperties: يرسل خصائص وحدة مزدوجة مُحدَّثة والخصائص المُبلَّغ عنها إلى IoT Hub خاصتك.

ملاحظة

راجع Azure IoT SDKs لمزيد من المعلومات حول أدوات SDK المتوفرة لإنشاء كل من الجهاز والتطبيقات الخلفية.

المتطلبات الأساسية

الحصول على سلسلة اتصال لوحة الوصل لـIoT

في هذه المقالة، يتوفر إنشاء خدمة خلفية تضيف جهازًا في سجل الهوية ثم تضيف وحدة نمطية إلى هذا الجهاز. تتطلب خدمتك إذن كتابة سجل. بطريقة افتراضية، يتم إنشاء كافة مراكز IoT باستخدام نهج الوصول المشترك يسمى registryReadWrite التي تمنح هذا الإذن.

للحصول على سلسلة اتصال IoT Hub لنهج registryReadWrite، اتبع الخطوات التالية:

  1. في مدخل Microsoft Azure، حدد Resource groups. حدد مجموعة الموارد حيث يوجد المركز الخاص بك، ثم حدد المركز الخاص بك من قائمة الموارد.

  2. في الجزء الأيسر من مركزك، قم بتحديد سياسات الوصول المشترك.

  3. من قائمة النهج، حدد نهج registryReadWrite.

  4. انسخ سلسلة الاتصال الأساسية واحفظ القيمة.

    لقطة شاشة تعرض الطريقة لاستعادة سلسلة الاتصال

لمزيد من المعلومات حول نهج الوصول المشترك لمركز IoT والأذونات، راجع التحكم بالوصول وأذونات الوصول.

إنشاء هوية الجهاز وهوية الوحدة النمطية في IoT Hub

في هذا القسم، يمكنك إنشاء تطبيق C يعمل على إنشاء هوية جهاز وهوية الوحدة النمطية في سجل الهوية في مركز IoT الخاص بك. لا يمكن لجهاز أو وحدة نمطية الاتصال بلوحة وصلIoT ما لم يكن بها إدخال في سجل الهوية. للمزيد من المعلومات، راجع فهم تسجيل الهوية في مركز IoT في دليل مطور IoT Hub. عند تشغيل تطبيق وحدة التحكم هذا، فإنه ينشئ معرفًا فريدًا ومفتاحًا لكل من الجهاز والوحدة النمطية. يستخدم الجهاز الخاص بك والوحدة النمطية هذه القيم لتعريف نفسه عندما يرسل رسائل من جهاز إلى سحابة إلى IoT Hub. المعرفات الخاصة بالجهاز حساسة لحالة الأحرف.

أضف التعليمة البرمجية التالية إلى ملف C الخاص بك:

#include <stdio.h>
#include <stdlib.h>

#include "azure_c_shared_utility/crt_abstractions.h"
#include "azure_c_shared_utility/threadapi.h"
#include "azure_c_shared_utility/platform.h"

#include "iothub_service_client_auth.h"
#include "iothub_registrymanager.h"

static const char* hubConnectionString ="[your hub's connection string]"; // modify

static void createDevice(IOTHUB_REGISTRYMANAGER_HANDLE 
  iotHubRegistryManagerHandle, const char* deviceId)
{
    IOTHUB_REGISTRY_DEVICE_CREATE_EX deviceCreateInfo;
    IOTHUB_REGISTRYMANAGER_RESULT result;
    
    (void)memset(&deviceCreateInfo, 0, sizeof(deviceCreateInfo));
    deviceCreateInfo.version = 1;
    deviceCreateInfo.deviceId = deviceId;
    deviceCreateInfo.primaryKey = "";
    deviceCreateInfo.secondaryKey = "";
    deviceCreateInfo.authMethod = IOTHUB_REGISTRYMANAGER_AUTH_SPK;
    
    IOTHUB_DEVICE_EX deviceInfoEx;
    memset(&deviceInfoEx, 0, sizeof(deviceInfoEx));
    deviceInfoEx.version = 1;
    
    // Create device
    result = IoTHubRegistryManager_CreateDevice_Ex(iotHubRegistryManagerHandle, 
      &deviceCreateInfo, &deviceInfoEx);
    if (result == IOTHUB_REGISTRYMANAGER_OK)
    {
        (void)printf("IoTHubRegistryManager_CreateDevice: Device has been created successfully: deviceId=%s, primaryKey=%s\n", deviceInfoEx.deviceId, deviceInfoEx.primaryKey);
    }
    else if (result == IOTHUB_REGISTRYMANAGER_DEVICE_EXIST)
    {
        (void)printf("IoTHubRegistryManager_CreateDevice: Device already exists\n");
    }
    else if (result == IOTHUB_REGISTRYMANAGER_ERROR)
    {
        (void)printf("IoTHubRegistryManager_CreateDevice failed\n");
    }
    // You will need to Free the returned device information after it was created
    IoTHubRegistryManager_FreeDeviceExMembers(&deviceInfoEx);
}

static void createModule(IOTHUB_REGISTRYMANAGER_HANDLE iotHubRegistryManagerHandle, const char* deviceId, const char* moduleId)
{
    IOTHUB_REGISTRY_MODULE_CREATE moduleCreateInfo;
    IOTHUB_REGISTRYMANAGER_RESULT result;    
    
    (void)memset(&moduleCreateInfo, 0, sizeof(moduleCreateInfo));
    moduleCreateInfo.version = 1;
    moduleCreateInfo.deviceId = deviceId;
    moduleCreateInfo.moduleId = moduleId;
    moduleCreateInfo.primaryKey = "";
    moduleCreateInfo.secondaryKey = "";
    moduleCreateInfo.authMethod = IOTHUB_REGISTRYMANAGER_AUTH_SPK;
    
    IOTHUB_MODULE moduleInfo;
    memset(&moduleInfo, 0, sizeof(moduleInfo));
    moduleInfo.version = 1;
    
    // Create module
    result = IoTHubRegistryManager_CreateModule(iotHubRegistryManagerHandle, &moduleCreateInfo, &moduleInfo);
    if (result == IOTHUB_REGISTRYMANAGER_OK)
    {
        (void)printf("IoTHubRegistryManager_CreateModule: Module has been created successfully: deviceId=%s, moduleId=%s, primaryKey=%s\n", moduleInfo.deviceId, moduleInfo.moduleId, moduleInfo.primaryKey);
    }
    else if (result == IOTHUB_REGISTRYMANAGER_DEVICE_EXIST)
    {
        (void)printf("IoTHubRegistryManager_CreateModule: Module already exists\n");
    }
    else if (result == IOTHUB_REGISTRYMANAGER_ERROR)
    {
        (void)printf("IoTHubRegistryManager_CreateModule failed\n");
    }
    // You will need to Free the returned module information after it was created
    IoTHubRegistryManager_FreeModuleMembers(&moduleInfo);
}

int main(void)
{
    (void)platform_init();

    const char* deviceId = "myFirstDevice";
    const char* moduleId = "myFirstModule";
    IOTHUB_SERVICE_CLIENT_AUTH_HANDLE iotHubServiceClientHandle = NULL;
    IOTHUB_REGISTRYMANAGER_HANDLE iotHubRegistryManagerHandle = NULL;

    if ((iotHubServiceClientHandle = IoTHubServiceClientAuth_CreateFromConnectionString(hubConnectionString)) == NULL)
    {
        (void)printf("IoTHubServiceClientAuth_CreateFromConnectionString failed\n");
    }
    else if ((iotHubRegistryManagerHandle = IoTHubRegistryManager_Create(iotHubServiceClientHandle)) == NULL)
    {
        (void)printf("IoTHubServiceClientAuth_CreateFromConnectionString failed\n");
    }
    else
    {
        createDevice(iotHubRegistryManagerHandle, deviceId);
        createModule(iotHubRegistryManagerHandle, deviceId, moduleId);
    }

    if (iotHubRegistryManagerHandle != NULL)
    {
        (void)printf("Calling IoTHubRegistryManager_Destroy...\n");
        IoTHubRegistryManager_Destroy(iotHubRegistryManagerHandle);
    }

    if (iotHubServiceClientHandle != NULL)
    {
        (void)printf("Calling IoTHubServiceClientAuth_Destroy...\n");
        IoTHubServiceClientAuth_Destroy(iotHubServiceClientHandle);
    }
    
    platform_deinit();
    return 0;
}

ينشئ هذا التطبيق هوية جهاز بمعرف myFirstDevice وهوية الوحدة النمطية مع ID myFirstModule ضمن الجهاز myFirstDevice. (في حالة كان معرف الوحدة النمطية هذا موجودًا بالفعل في سجل الهوية، فإن التعليمات البرمجية تسترد ببساطة معلومات الوحدة النمطية الموجودة.) ثم يعرض التطبيق المفتاح الأساس لتلك الهوية. يمكنك استخدام هذا المفتاح في التطبيق الخاص بالوحدة النمطية المحاكاة للاتصال بمركز IoT الخاص بك.

ملاحظة

يخزن سجل الهوية الخاص بمركز IoT هويات الجهاز والوحدة فحسب لتمكين الوصول الآمن إلى مركز IoT. يخزن سجل الهوية معرفات الجهاز والمفاتيح لاستخدامها بصفتها بيانات اعتماد أمان. يخزن السجل الخاص بالهوية أيضا علامة ممكنة/معطلة لكل جهاز يمكنك استخدامه لتعطيل الوصول لهذا الجهاز. في حالة كان التطبيق الخاص بك يحتاج إلى تخزين بيانات تعريف أخرى خاصة بالجهاز، فيجب أن يستخدم مخزنًا خاصًا بالتطبيق. لا توجد علامة ممكنة/معطلة للهويات الخاصة بالوحدة النمطية. لمزيد من المعلومات، راجع دليل مطور مركز إنترنت الأشياء.

تحديث الوحدة المزدوجة باستخدام SDK الخاص بجهاز C

في هذا القسم، يمكنك إنشاء تطبيق C على جهاز المحاكاة الذي يقوم بتحديث الخصائص الخاصة بالوحدة النمطية المزدوجة التي تم الإبلاغ عنها.

  1. يمكنك الحصول على سلسلة اتصال الوحدة الخاصة بك. في مدخل Microsoft Azure، انتقل إلى مركز IoT وحدد أجهزة IoT. ابحث عن myFirstDevice وافتحه وسترى أن myFirstModule قد تم إنشاؤه بنجاح. انسخ سلسلة اتصال الخاصة بالوحدة النمطية. توجد حاجة إليها في الخطوة التالية.

    تفاصيل وحدة مدخل Microsoft Azure

  2. عملية إنشاء تطبيق UpdateModuleTwinReportedProperties

    أضف ما يلي إلى ملف C الخاص بك:

    #include <stdio.h>
    #include <stdlib.h>
    
    #include "azure_c_shared_utility/crt_abstractions.h"
    #include "azure_c_shared_utility/threadapi.h"
    #include "azure_c_shared_utility/platform.h"
    
    #include "iothub_service_client_auth.h"
    #include "iothub_devicetwin.h"
    
    const char* deviceId = "bugbash-test-2";
    const char* moduleId = "module-id-1";
    static const char* hubConnectionString ="[your hub's connection string]"; // modify
    const char* testJson = "{\"properties\":{\"desired\":{\"integer_property\": b-1234, \"string_property\": \"abcd\"}}}";
    
    int main(void)
    {
        (void)platform_init();
    
        IOTHUB_SERVICE_CLIENT_AUTH_HANDLE iotHubServiceClientHandle = NULL;
        IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE iothubDeviceTwinHandle = NULL;
    
        if ((iotHubServiceClientHandle = IoTHubServiceClientAuth_CreateFromConnectionString(moduleConnectionString)) == NULL)
        {
            (void)printf("IoTHubServiceClientAuth_CreateFromConnectionString failed\n");
        }
        else if ((iothubDeviceTwinHandle = IoTHubDeviceTwin_Create(iotHubServiceClientHandle)) == NULL)
        {
            (void)printf("IoTHubServiceClientAuth_CreateFromConnectionString failed\n");
        }
        else
        {
            char *result = IoTHubDeviceTwin_UpdateModuleTwin(iothubDeviceTwinHandle, deviceId, moduleId, testJson);
            printf("IoTHubDeviceTwin_UpdateModuleTwin returned %s\n", result);
        }
    
        if (iothubDeviceTwinHandle != NULL)
        {
            (void)printf("Calling IoTHubDeviceTwin_Destroy...\n");
            IoTHubDeviceTwin_Destroy(iothubDeviceTwinHandle);
        }
    
        if (iotHubServiceClientHandle != NULL)
        {
            (void)printf("Calling IoTHubServiceClientAuth_Destroy...\n");
            IoTHubServiceClientAuth_Destroy(iotHubServiceClientHandle);
        }
    
        platform_deinit();
        return 0;
    }
    

توضح لك عينة التعليمات البرمجية هذا كيفية استرداد الوحدة المزدوجة وتحديث الخصائص المبلغ عنها.

عملية الحصول على التحديثات على جانب الجهاز

بالإضافة إلى التعليمات البرمجية السابقة، يمكنك إضافة كتلة التعليمات البرمجية التالية للحصول على رسالة التحديث المزدوج على جهازك:

#include <stdio.h>
#include <stdlib.h>

#include "azure_c_shared_utility/crt_abstractions.h"
#include "azure_c_shared_utility/macro_utils.h"
#include "azure_c_shared_utility/threadapi.h"
#include "azure_c_shared_utility/platform.h"
#include "iothub_module_client_ll.h"
#include "iothub_client_options.h"
#include "iothub_message.h"

// The protocol you wish to use should be uncommented
//
//#define SAMPLE_MQTT
//#define SAMPLE_MQTT_OVER_WEBSOCKETS
#define SAMPLE_AMQP
//#define SAMPLE_AMQP_OVER_WEBSOCKETS
//#define SAMPLE_HTTP

#ifdef SAMPLE_MQTT
    #include "iothubtransportmqtt.h"
#endif // SAMPLE_MQTT
#ifdef SAMPLE_MQTT_OVER_WEBSOCKETS
    #include "iothubtransportmqtt_websockets.h"
#endif // SAMPLE_MQTT_OVER_WEBSOCKETS
#ifdef SAMPLE_AMQP
    #include "iothubtransportamqp.h"
#endif // SAMPLE_AMQP
#ifdef SAMPLE_AMQP_OVER_WEBSOCKETS
    #include "iothubtransportamqp_websockets.h"
#endif // SAMPLE_AMQP_OVER_WEBSOCKETS
#ifdef SAMPLE_HTTP
    #include "iothubtransporthttp.h"
#endif // SAMPLE_HTTP

/* Paste in the your iothub connection string  */
static const char* connectionString = "[Fill in connection string]";

static bool g_continueRunning;
#define DOWORK_LOOP_NUM     3

static void deviceTwinCallback(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* userContextCallback)
{
    (void)userContextCallback;

    printf("Device Twin update received (state=%s, size=%zu): %s\r\n", 
        MU_ENUM_TO_STRING(DEVICE_TWIN_UPDATE_STATE, update_state), size, payLoad);
}

static void reportedStateCallback(int status_code, void* userContextCallback)
{
    (void)userContextCallback;
    printf("Device Twin reported properties update completed with result: %d\r\n", status_code);

    g_continueRunning = false;
}

void iothub_module_client_sample_device_twin_run(void)
{
    IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol;
    IOTHUB_MODULE_CLIENT_LL_HANDLE iotHubModuleClientHandle;
    g_continueRunning = true;

    // Select the Protocol to use with the connection
#ifdef SAMPLE_MQTT
    protocol = MQTT_Protocol;
#endif // SAMPLE_MQTT
#ifdef SAMPLE_MQTT_OVER_WEBSOCKETS
    protocol = MQTT_WebSocket_Protocol;
#endif // SAMPLE_MQTT_OVER_WEBSOCKETS
#ifdef SAMPLE_AMQP
    protocol = AMQP_Protocol;
#endif // SAMPLE_AMQP
#ifdef SAMPLE_AMQP_OVER_WEBSOCKETS
    protocol = AMQP_Protocol_over_WebSocketsTls;
#endif // SAMPLE_AMQP_OVER_WEBSOCKETS
#ifdef SAMPLE_HTTP
    protocol = HTTP_Protocol;
#endif // SAMPLE_HTTP

    if (platform_init() != 0)
    {
        (void)printf("Failed to initialize the platform.\r\n");
    }
    else
    {
        if ((iotHubModuleClientHandle = IoTHubModuleClient_LL_CreateFromConnectionString(connectionString, protocol)) == NULL)
        {
            (void)printf("ERROR: iotHubModuleClientHandle is NULL!\r\n");
        }
        else
        {
            bool traceOn = true;
            const char* reportedState = "{ 'device_property': 'new_value'}";
            size_t reportedStateSize = strlen(reportedState);

            (void)IoTHubModuleClient_LL_SetOption(iotHubModuleClientHandle, OPTION_LOG_TRACE, &traceOn);

            // Check the return of all API calls when developing your solution. Return checks omitted for sample simplification.

            (void)IoTHubModuleClient_LL_SetModuleTwinCallback(iotHubModuleClientHandle, deviceTwinCallback, iotHubModuleClientHandle);
            (void)IoTHubModuleClient_LL_SendReportedState(iotHubModuleClientHandle, (const unsigned char*)reportedState, reportedStateSize, reportedStateCallback, iotHubModuleClientHandle);

            do
            {
                IoTHubModuleClient_LL_DoWork(iotHubModuleClientHandle);
                ThreadAPI_Sleep(1);
            } while (g_continueRunning);

            for (size_t index = 0; index < DOWORK_LOOP_NUM; index++)
            {
                IoTHubModuleClient_LL_DoWork(iotHubModuleClientHandle);
                ThreadAPI_Sleep(1);
            }

            IoTHubModuleClient_LL_Destroy(iotHubModuleClientHandle);
        }
        platform_deinit();
    }
}

int main(void)
{
    iothub_module_client_sample_device_twin_run();
    return 0;
}

الخطوات التالية

لمتابعة عملية بدء استخدام IoT Hub واستكشاف سيناريوهات IoT الأخرى، راجع: