設備認證分為一機一密和一型一密兩種方式,本文介紹這兩種方式的使用場景。
認證方式
-
一機一密:在設備上燒寫設備的ProductKey、DeviceName、DeviceSecret,然后適配相應的HAL并調用SDK提供的函數連接物聯網平臺。這種方式要求對設備的產線工具進行一定的修改,需要對每個設備燒寫不同的DeviceName和DeviceSecret。
-
一型一密:設備上燒寫設備的ProductKey、ProductSecret,每個設備需要具備自己的唯一標識并將該標識預先上傳到阿里云物聯網平臺,然后調用SDK提供的函數連接云端。這種方式每個設備上燒寫的信息是固定的ProductKey和ProductSecret。
獲取Link SDK
不同版本的Link SDK下載,請參見SDK獲取。
一機一密編程
需要根據不用版本的Link SDK設置設備認證信息。- 在Link SDK v3.0.1中,需要實現下文認證信息的配置:
- HAL_GetProductKey
- HAL_GetDeviceName
- HAL_GetDeviceSecret
- 在Link SDK v3.1.0/v3.2.0中,通過IOT_Ioctl設置認證信息:
- IOT_Ioctl(IOTX_IOCTL_SET_PRODUCT_KEY, g_product_key)
- IOT_Ioctl(IOTX_IOCTL_SET_DEVICE_NAME, g_device_name)
- IOT_Ioctl(IOTX_IOCTL_SET_DEVICE_SECRET, g_device_secret)
以Link SDK v3.0.1版本為例,IOT_MQTT_Construct()會調用HAL_GetProductKey()等三個HAL函數去獲取設備的身份信息,示例文件參考
src\mqtt\examples\mqtt_example.c
,代碼如下:int main(int argc, char *argv[])
{
void *pclient = NULL;
int res = 0;
int loop_cnt = 0;
iotx_mqtt_param_t mqtt_params;
memset(&mqtt_params, 0x0, sizeof(mqtt_params));
mqtt_params.handle_event.h_fp = example_event_handle;
pclient = IOT_MQTT_Construct(&mqtt_params);
if (NULL == pclient) {
EXAMPLE_TRACE("MQTT construct failed");
return -1;
}
...
}
一型一密編程
一型一密認證方法使用的流程示意圖:
實現流程簡述:
- 設備使用ProductKey、ProductSecret和DeviceName到阿里云物聯網平臺獲取該設備對應的DeviceSecret。
- 物聯網平臺的動態注冊服務將查找該設備的DeviceName是否在該ProductKey對應的設備列表,如果該設備在列表中則返回該設備的DeviceSecret。
- 設備收到DeviceSecret之后,將使用一機一密的方式計算MQTT連接參數以及簽名。
- 設備使用計算出來的MQTT連接參數連接物聯網平臺。
注意
- 您需要將獲取的DeviceSecret持久化到設備,以備后續使用。若獲取的DeviceSecret丟失可能導致設備無法上線等嚴重后果,物聯網平臺不接受已激活設備重復的動態注冊請求。
- 使用一型一密功能,您必須對每個設備進行預注冊,即在阿里云物聯網平臺的控制臺上傳每個設備的DeviceName,并且在控制臺上打開對應產品的動態注冊功能。
實現流程簡述步驟中涉及的API如下:
- 第1步和第2步對應用戶接口:
IOT_Dynamic_Register()
。 - 第3步對應用戶接口:
IOT_Sign_MQTT()
。 - 第4步對應用戶接口:
IOT_MQTT_Construct()
。
說明
- 當設備獲取到DeviceSecret之后再次調用
IOT_Dynamic_Register()
將會返回失敗,因此用戶編程時獲取到DeviceSecret之后需要將其保存到設備本地的存儲介質中。 - 您的程序在調用
IOT_Dynamic_Register()
之前應該先調用HAL_GetDeviceSecret()
查看設備是否已經獲取到了DeviceSecret,如果已經獲取到,則無需再次調用IOT_Dynamic_Register()
。 - 詳細參數內容,請參見功能API接口。
案例說明
以Link SDK v3.0.1版本為例,一型一密功能的案例程序參考src/dynamic_register/examples/dynreg_example.c
文件。
下文對其進行逐段講解:
- 使用一型一密功能,需要包含其頭文件
dynreg_api.h
:#include <stdio.h> #include <string.h> #include "infra_types.h" #include "infra_defs.h" #include "dynreg_api.h"
- 準備輸入參數
region
和出入參結構體meta
:iotx_http_region_types_t region = IOTX_HTTP_REGION_SHANGHAI; HAL_Printf("dynreg example\n"); memset(&meta,0,sizeof(iotx_dev_meta_info_t)); HAL_GetProductKey(meta.product_key); HAL_GetProductSecret(meta.product_secret); HAL_GetDeviceName(meta.device_name);
說明- 入參
region = IOTX_CLOUD_REGION_SHANGHAI
表示用華東2(上海)作為演示連接站點的場景,您可根據自身需要替換為您的使用站點,詳細信息,請參見地域和可用區。 - 入參
meta
表示從本地獲取的ProductKey、ProductSecret和DeviceName。
- 入參
- 調用一型一密的
IOT_Dynamic_Register()
接口獲取DeviceSecret,此接口是一型一密功能點唯一提供的用戶接口,若執行成功,在參數meta
中將填上從物聯網平臺成功獲取到的DeviceSecret。res = IOT_Dynamic_Register(region, &meta); if (res < 0) { HAL_Printf("IOT_Dynamic_Register failed\n"); return -1; } HAL_Printf("\nDevice Secret: %s\n\n", meta.device_secret);
功能API接口
IOT_Dynamic_Register
- 原型:
int32_t IOT_Dynamic_Register(iotx_http_region_types_t region, iotx_dev_meta_info_t *meta);
- 接口說明:根據輸入參數中指定的站點區域,以及ProductKey和ProductSecret,請求物聯網平臺為DeviceName指定的設備申請DeviceSecret。
- 參數說明:
參數 數據類型 方向 說明 region iotx_http_region_types_t 輸入 設備將要工作的區域,例如華東2(上海)、亞太東北1(東京)、美國西部1(硅谷)、亞太東南1(新加坡)等,完整內容,請參見地域和可用區。 meta iotx_dev_meta_info_t * 輸入輸出 輸入的時候帶入設備的ProductKey、ProductSecret和DeviceName,輸出的時候返回從物聯網平臺獲取到的DeviceSecret。 - 返回結果:
返回結果 說明 =0 請求成功。 <0 請求失敗。
IOT_MQTT_Construct
- 原型:
void *IOT_MQTT_Construct(iotx_mqtt_param_t *pInitParams);
- 接口說明:初始化MQTT建連參數,建立MQTT連接。
- 參數說明:
參數 數據類型 方向 說明 pInitParams iotx_mqtt_param_t * 輸入 MQTT建連參數。 - 返回結果:
返回結果 說明 非空對象 請求成功。 NULL(空對象) 請求失敗。
IOT_Sign_MQTT
- 原型:
int32_t IOT_Sign_MQTT(iotx_mqtt_region_types_t region, iotx_dev_meta_info_t *meta, iotx_sign_mqtt_t *signout)
- 接口說明:計算MQTT簽名。
- 參數說明:
參數 數據類型 方向 說明 region iotx_http_region_types_t 輸入 設備所屬的區域。 meta iotx_dev_meta_info_t * 輸入 簽名所需的信息,存放設備的標識字符串,包括ProductKey、DeviceName等。 signout iotx_sign_mqtt_t * 輸出 簽名結果,包括username、password、clientid、hostname等。 - 返回結果:
返回結果 說明 =0 請求成功。 <0 請求失敗。