認(rèn)證與連接
本文介紹如何進(jìn)行C LinkSDK Extended初始化,并建立設(shè)備與物聯(lián)網(wǎng)平臺(tái)的連接。
前提條件
使用流程
如下功能時(shí)序圖,以設(shè)備的應(yīng)用程序demos/device_basic_demo.c
為例,介紹設(shè)備的建連與消息收發(fā)。更多API的詳細(xì)信息,請(qǐng)參考aiot_device_api.h
。
步驟1:設(shè)備初始化
添加頭文件。
#include "aiot_device_api.h"
創(chuàng)建設(shè)備句柄。
void *device_client = aiot_device_create(product_key, device_name); if (device_client == NULL) { printf("device_client failed\n"); return -1; }
設(shè)置設(shè)備密鑰。
aiot_device_set_device_secret(device_client, device_secret);
步驟2:配置事件回調(diào)函數(shù)
編寫(xiě)消息回調(diào)函數(shù)。
該回調(diào)函數(shù)會(huì)在設(shè)備接收到任意消息時(shí)執(zhí)行,用于消息的監(jiān)聽(tīng)。該回調(diào)函數(shù)原型為aiot_device_msg_result_callback_t。
/* 設(shè)備的消息回調(diào)示例,默認(rèn)只做打印處理 */ void demo_msg_callback(void *device, const aiot_msg_t *message, void *userdata) { printf("[message] <<, topic: %s\n", message->topic); printf("[message] <<, payload: %.*s\n", message->payload_lenth, message->payload); }
編寫(xiě)狀態(tài)回調(diào)函數(shù)。
該回調(diào)函數(shù)會(huì)在設(shè)備連接狀態(tài)變化時(shí)執(zhí)行,用于監(jiān)聽(tīng)設(shè)備的狀態(tài)。該回調(diào)函數(shù)原型為aiot_device_status_callback_t。
void demo_status_callback(void *device, const aiot_device_status_t *status, void *userdata) { switch (status->type) { /* SDK因?yàn)橛脩粽{(diào)用了aiot_mqtt_connect()接口, 與mqtt服務(wù)器建立連接已成功 */ case AIOT_DEVICE_STATUS_CONNECT: { printf("AIOT_DEVICE_STATUS_CONNECT\n"); /* TODO: 處理SDK建連成功, 不可以在這里調(diào)用耗時(shí)較長(zhǎng)的阻塞函數(shù) */ } break; /* SDK因?yàn)榫W(wǎng)絡(luò)狀況被動(dòng)斷連后, 自動(dòng)發(fā)起重連已成功 */ case AIOT_DEVICE_STATUS_RECONNECT: { printf("AIOT_DEVICE_STATUS_CONNECT\n"); /* TODO: 處理SDK重連成功, 不可以在這里調(diào)用耗時(shí)較長(zhǎng)的阻塞函數(shù) */ } break; /* SDK因?yàn)榫W(wǎng)絡(luò)的狀況而被動(dòng)斷開(kāi)了連接, network是底層讀寫(xiě)失敗, heartbeat是沒(méi)有按預(yù)期得到服務(wù)端心跳應(yīng)答 */ case AIOT_DEVICE_STATUS_DISCONNECT: { printf("AIOT_DEVICE_STATUS_CONNECT: %d\n", status->error_code); /* TODO: 處理SDK被動(dòng)斷連, 不可以在這里調(diào)用耗時(shí)較長(zhǎng)的阻塞函數(shù) */ } break; } }
編寫(xiě)消息發(fā)送結(jié)果回調(diào)函數(shù)。
該函數(shù)會(huì)在設(shè)備主動(dòng)發(fā)送QoS 1消息,或執(zhí)行訂閱、取消訂閱、云端有返回時(shí)執(zhí)行。該回調(diào)函數(shù)的原型為aiot_device_msg_result_callback_t。
/* 主動(dòng)發(fā)送的消息,或者訂閱/取消訂閱消息有結(jié)果后會(huì)回調(diào)該消息 */ void demo_result_callback(void *device, const aiot_device_msg_result_t *result, void *userdata) { switch(result->type) { case AIOT_DEVICE_SEND_MESSAGE_RESULT: { printf("send message result, message id: %d, code -0x%04X\n", result->message_id, -result->code); } break; case AIOT_DEVICE_REGISTER_TOPIC_RESULT:{ printf("register, message id: %d, code code -0x%04X\n", result->message_id, -result->code); } break; default: break; } }
設(shè)置事件回調(diào)函數(shù)。
上述定義了回調(diào)函數(shù),執(zhí)行設(shè)置動(dòng)作才能生效,設(shè)置事件回調(diào)函數(shù)接口說(shuō)明,請(qǐng)參見(jiàn)aiot_device_set_event_callback,該接口可設(shè)置三種事件的監(jiān)聽(tīng),如果不需要監(jiān)聽(tīng)事件,可將對(duì)應(yīng)參數(shù)設(shè)置為NULL。
/* 設(shè)置設(shè)備消息回調(diào)及狀態(tài)變化回調(diào) */ aiot_device_set_event_callback(device_client, demo_msg_callback, demo_status_callback, demo_result_callback, NULL);
步驟3:配置連接參數(shù)
配置連接參數(shù),一般使用默認(rèn)設(shè)置,更多連接參數(shù)信息,請(qǐng)參考aiot_linkconfig_api.h。
/* 連接配置參數(shù)初始化 */
aiot_linkconfig_t* config = aiot_linkconfig_init(protocol);
/* 設(shè)置服務(wù)器的host、port */
aiot_linkconfig_host(config, host, port);
/* 設(shè)置設(shè)備連接參數(shù) */
aiot_device_set_linkconfig(device_client, config);
步驟4:設(shè)備建連
如下示例的連接為阻塞式的接口,SDK也支持異步建連,異步建連接口使用具體操作,請(qǐng)參考aiot_device_connect_async。
/* 設(shè)備建連 */
res = aiot_device_connect(device_client);
if (res < STATE_SUCCESS) {
/* 嘗試建立連接失敗, 銷毀MQTT實(shí)例, 回收資源 */
aiot_linkconfig_deinit(&config);
aiot_device_delete(&device_client);
printf("aiot_device_connect failed: -0x%04X\n\r\n", -res);
return -1;
}
設(shè)備建連成功后,如果網(wǎng)絡(luò)出現(xiàn)斷連,SDK會(huì)自動(dòng)進(jìn)行設(shè)備重連,無(wú)需再調(diào)用aiot_device_connect
接口。
步驟5:訂閱自定義消息
定義消息的回調(diào)函數(shù)。
回調(diào)函數(shù)原型為aiot_device_msg_result_callback_t。
/* 自定義topic下行消息處理示例, 示例只做打印處理 */ void demo_user_topic_callback(void *device, const aiot_msg_t *message, void *userdata) { printf("[thing_message] <<, topic: %s\n", message->topic); printf("[thing_message] <<, payload: %.*s\n", message->payload_lenth, message->payload); }
向物聯(lián)網(wǎng)平臺(tái)發(fā)起消息訂閱,并注冊(cè)消息回調(diào)。
注冊(cè)自定義消息回調(diào)的接口aiot_device_register_topic_filter,該接口有兩個(gè)功能:
(可選)向云平臺(tái)發(fā)起消息訂閱。
向SDK注冊(cè)接收到消息的回調(diào)。
/* 訂閱消息,設(shè)置該消息回調(diào)函數(shù) */ char sub_topic[128] = { 0 }; snprintf(sub_topic, sizeof(sub_topic), "/%s/%s/user/get", product_key, device_name); int32_t msg_id = aiot_device_register_topic_filter(device_client, sub_topic, demo_user_topic_callback, 1, NULL); if(msg_id >= 0){ printf("aiot_device_register_topic_filter topic %s msg_id %d\r\n", sub_topic, msg_id); }
如果需要取消已訂閱的Topic,可通過(guò)接口aiot_device_deregister_topic_filter取消訂閱。
步驟6:發(fā)送自定義消息
創(chuàng)建消息。
如下示例使用Topic和Payload創(chuàng)建消息。更多消息配置,請(qǐng)參考aiot_message_api.h。
char pub_topic[128] = { 0 }; snprintf(pub_topic, sizeof(pub_topic), "/%s/%s/user/update", product_key, device_name); char *pub_payload = "{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}"; aiot_msg_t *pub_message = aiot_msg_create_raw(pub_topic, (uint8_t *)pub_payload, strlen(pub_payload));
發(fā)送消息。
aiot_device_send_message(device_client, pub_message);
刪除消息。
aiot_msg_delete(pub_message);
步驟7:接收自定義消息
設(shè)備訂閱消息后,用戶可通過(guò)云端SDK給設(shè)備發(fā)消息;調(diào)試階段,也可通過(guò)OpenApi給設(shè)備發(fā)消息。通過(guò)OpenApi給設(shè)備發(fā)自定義消息步驟:
登錄控制臺(tái),打開(kāi)Pub接口鏈接。
輸入必選參數(shù):ProductKey、TopicFullName、MessageContent,若為企業(yè)實(shí)例,還需輸入IotInstanceId。
發(fā)起調(diào)用:?jiǎn)螜C(jī)發(fā)起調(diào)用,若執(zhí)行成功,即可看到設(shè)備端打印接收的消息。
步驟8:設(shè)備斷開(kāi)連接
設(shè)備和物聯(lián)網(wǎng)平臺(tái)斷開(kāi)連接。
res = aiot_device_disconnect(device_client);
if (res < STATE_SUCCESS) {
printf("aiot_mqtt_disconnect failed: -0x%04X\n", -res);
return -1;
}
步驟9:刪除設(shè)備句柄
程序退出時(shí),SDK執(zhí)行資源回收。
/* 銷毀設(shè)備實(shí)例, 一般不會(huì)運(yùn)行到這里 */
aiot_device_delete(&device_client);
aiot_linkconfig_deinit(&config);