本文介紹子設備通過網關與物聯網平臺建立連接,以及消息收發的過程。
前提條件
使用流程
如下功能時序圖,以設備的應用程序demos/gateway_sync_demo.c
和demos/gateway_async_demo.c
為例,介紹網關模塊的基礎功能。
步驟1:初始化網關設備
添加頭文件。
#include "aiot_gateway_api.h" /* 配置SDK的底層依賴 */ aiot_sysdep_init(aiot_sysdep_get_portfile());
實現網關設備初始化函數。
該函數包含創建設備句柄、連接參數配置、網關設備建連。
static void* demo_gateway_device_init(char *product_key, char *device_name, char *device_secret, char *host, uint16_t port) { int32_t res = STATE_SUCCESS; /* 創建設備 */ void *device = aiot_device_create(product_key, device_name); if (device == NULL) { printf("device create failed\n"); return NULL; } /* 設置設備密鑰 */ aiot_device_set_device_secret(device, device_secret); /* 連接配置參數初始化 */ aiot_linkconfig_t* config = aiot_linkconfig_init(protocol); /* 設置服務器的host、port */ aiot_linkconfig_host(config, host, port); /* 設置設備連接參數 */ aiot_device_set_linkconfig(device, config); /* 設備建連 */ res = aiot_device_connect(device); if (res < STATE_SUCCESS) { /* 嘗試建立連接失敗, 銷毀MQTT實例, 回收資源 */ aiot_linkconfig_deinit(&config); aiot_device_delete(&device); printf("aiot_device_connect failed: -0x%04X\n\r\n", -res); return NULL; } /* 建連成功返回設備對象 */ aiot_linkconfig_deinit(&config); return device; }
實現網關模塊回調函數。
/* 網關模塊的消息回調 */ void demo_gateway_msg_callback(void *device, const aiot_gateway_msg_t *msg, void *userdata) { switch(msg->type){ case AIOT_GWRECV_CONNECT_REPLY:{ /* 子設備批量建連返回 */ } break; case AIOT_GWRECV_DISCONNECT_REPLY:{ /* 子設備批量斷連結果返回 */ } break; case AIOT_GWRECV_ADD_TOPO_REPLY:{ /* 子設備添加topo關系結果返回 */ } break; case AIOT_GWRECV_DELETE_TOPO_REPLY:{ /* 子設備刪除topo關系結果返回 */ } break; case AIOT_GWRECV_TOPO_CHANGE_NOTICE:{ printf("type[%d] subdev_num %d status %d\r\n", msg->type, msg->subdev_num, msg->data.topo_change.status); } break; } }
網關設備正常建連后,會設置網關模塊的回調函數。
/* 網關設備完成初始化,啟動建連,如果失敗返回NULL */ void *gateway_device = demo_gateway_device_init(gateway_product_key, gateway_device_name, gateway_device_secret, host, port); if(gateway_device == NULL) { return -1; } /* 設置網關消息回調 */ aiot_gateway_set_msg_callback(gateway_device, demo_gateway_msg_callback, NULL);
步驟2:批量添加拓撲關系
使用同步接口
aiot_gateway_batch_add_topo
添加拓撲關系,返回值為STATE_SUCCESS
表示添加成功。/* 子設備添加topo */ res = aiot_gateway_batch_add_topo(gateway_device, sub_device_meta, subdev_num); if(res >= STATE_SUCCESS) { printf("aiot_gateway_batch_add_topo success %d\r\n", res); } else { printf("aiot_gateway_batch_add_topo error %d\r\n", res); demo_gateway_device_deinit(gateway_device); return -1; }
使用異步接口
aiot_gateway_batch_add_topo_async
添加拓撲關系,需在網關模塊的回調函數中監聽類型為AIOT_GWRECV_ADD_TOPO_REPLY
的消息,msg->data.reply.code
為200表示添加成功。/* 子設備添加topo,異步調用 */ res = aiot_gateway_batch_add_topo_async(gateway_device, sub_device_meta, subdev_num); if(res >= STATE_SUCCESS && 0 == demo_wait_expect_resp(&resp.add_topo_resp, 200, timeout_ms)) { printf("aiot_gateway_batch_add_topo_async success %d\r\n", res); } else { printf("aiot_gateway_batch_add_topo_async error %d\r\n", res); demo_gateway_device_deinit(gateway_device); return -1; }
步驟3:初始化子設備
初始化子設備包含創建設備句柄、設置設備密鑰、設置子設備回調函數,可以通過回調參數userdata
區分具體設備。
void *demo_sub_device_init(aiot_subdev_meta_info_t *device)
{
/* 創建設備 */
void *sub_device = aiot_device_create(device->product_key, device->device_name);
if (sub_device == NULL) {
printf("subdev_device failed\n");
return NULL;
}
/* 設置設備密鑰 */
aiot_device_set_device_secret(sub_device, device->device_secret);
/* 設置設備消息回調及狀態變化回調
* demo中子設備與網關設備使用的相同回調函數,最后的參數userdata可設置不同參數以做區分
* */
aiot_device_set_event_callback(sub_device, demo_msg_callback, demo_status_callback, demo_result_callback, NULL);
return sub_device;
}
步驟4:子設備接入物聯網平臺
使用同步接口
aiot_gateway_batch_connect_subdev
接入物聯網平臺,返回值為STATE_SUCCESS
表示接入成功。/* 子設備建連,同步接口 */ res = aiot_gateway_batch_connect_subdev(gateway_device, subdev_table, subdev_num); if(res >= STATE_SUCCESS) { printf("aiot_gateway_batch_connect_subdev success %d\r\n", res); } else { printf("aiot_gateway_batch_connect_subdev error %d\r\n", res); demo_gateway_device_deinit(gateway_device); demo_sub_device_deinit(subdev_table, subdev_num); return -1; }
使用異步接口
aiot_gateway_batch_connect_subdev_async
接入物聯網平臺,需在網關模塊的回調函數中監聽類型為AIOT_GWRECV_CONNECT_REPLY
的消息,msg->data.reply.code
為200表示接入成功。/* 子設備建連,異步接口 */ res = aiot_gateway_batch_connect_subdev_async(gateway_device, subdev_table, subdev_num); if(res >= STATE_SUCCESS && 0 == demo_wait_expect_resp(&resp.connect_resp, 200, timeout_ms)) { printf("aiot_gateway_batch_connect_subdev_async success %d\r\n", res); } else { printf("aiot_gateway_batch_connect_subdev_async error %d\r\n", res); demo_gateway_device_deinit(gateway_device); demo_sub_device_deinit(subdev_table, subdev_num); return -1; }
步驟5:子設備發送物模型消息
char *property_params = "{\"LightSwitch\": 0}";
for(i = 0; i < sizeof(sub_device_meta) / sizeof(aiot_subdev_meta_info_t); i++) {
/* 子設備發送物模型消息 */
aiot_device_dm_property_post(subdev_table[i], property_params, 1);
}
/* 網關發送物模型消息 */
aiot_device_dm_property_post(gateway_device, property_params, 1);
步驟6:子設備退出物聯網平臺
使用同步接口
aiot_gateway_batch_disconnect_subdev
退出物聯網平臺,返回值為STATE_SUCCESS
表示退出成功。/* 子設備斷開連接 */ res = aiot_gateway_batch_disconnect_subdev(gateway_device, subdev_table, subdev_num); if(res >= STATE_SUCCESS) { printf("aiot_gateway_batch_disconnect_subdev success %d\r\n", res); } else { printf("aiot_gateway_batch_disconnect_subdev error %d\r\n", res); demo_gateway_device_deinit(gateway_device); demo_sub_device_deinit(subdev_table, subdev_num); return -1; }
使用異步接口
aiot_gateway_batch_disconnect_subdev_async
退出物聯網平臺,需在網關模塊的回調函數中監聽類型為AIOT_GWRECV_DISCONNECT_REPLY
的消息,msg->data.reply.code
為200表示退出成功。/* 子設備斷開連接 */ res = aiot_gateway_batch_disconnect_subdev_async(gateway_device, subdev_table, subdev_num); if(res >= STATE_SUCCESS && 0 == demo_wait_expect_resp(&resp.disconnect_resp, 200, timeout_ms)) { printf("aiot_gateway_batch_disconnect_subdev_async success %d\r\n", res); } else { printf("aiot_gateway_batch_disconnect_subdev_async error %d\r\n", res); demo_gateway_device_deinit(gateway_device); demo_sub_device_deinit(subdev_table, subdev_num); return -1; }
步驟7:批量刪除拓撲關系
使用同步接口
aiot_gateway_batch_delete_topo
刪除拓撲關系,返回值為STATE_SUCCESS
表示刪除成功。/* 子設備刪除topo */ res = aiot_gateway_batch_delete_topo(gateway_device, sub_device_meta, subdev_num); if(res >= STATE_SUCCESS) { printf("aiot_gateway_batch_delete_topo success %d\r\n", res); } else { printf("aiot_gateway_batch_delete_topo error %d\r\n", res); demo_gateway_device_deinit(gateway_device); demo_sub_device_deinit(subdev_table, subdev_num); return -1; }
使用異步接口
aiot_gateway_batch_delete_topo_async
刪除拓撲關系,需在網關模塊的回調函數中監聽類型為AIOT_GWRECV_DELETE_TOPO_REPLY
的消息,msg->data.reply.code
為200表示刪除成功。/* 子設備刪除topo */ res = aiot_gateway_batch_delete_topo_async(gateway_device, sub_device_meta, subdev_num); if(res >= STATE_SUCCESS && 0 == demo_wait_expect_resp(&resp.delete_topo_resp, 200, timeout_ms)) { printf("aiot_gateway_batch_delete_topo_async success %d\r\n", res); } else { printf("aiot_gateway_batch_delete_topo_async error %d\r\n", res); demo_gateway_device_deinit(gateway_device); demo_sub_device_deinit(subdev_table, subdev_num); return -1; }
步驟8:反初始化子設備
刪除子設備前,將子設備和網關中斷連接,否則會出現內存異常。
void demo_sub_device_deinit(void **subdev_table, int32_t num)
{
int i = 0;
for(i = 0; i < num; i++) {
aiot_device_delete(&subdev_table[i]);
}
free(subdev_table);
}
步驟9:反初始化網關設備
static void demo_gateway_device_deinit(void *device)
{
int32_t res = STATE_SUCCESS;
res = aiot_device_disconnect(device);
if (res < STATE_SUCCESS) {
printf("aiot_device_disconnect failed: -0x%04X\n", -res);
}
aiot_device_delete(&device);
}