外话:各位手头上没有esp8266的开发板注意了,目前开发快正在进行“免费开发板活动”,本人就是在他们那里申请到的开发板,开发快提供的不单单是开发板,还有他们强大的云端服务功能,实现了微信、云平台等物联网所需要的所有功能,其功能齐全,代码简洁,对于想用wifi作为产品和互联网沟通的桥梁的我们来说,确实是一个很好的选择,另外他们还有其他的模块,比如2G通信和GPS。目前论坛活动地址:http://bbs.kaifakuai.com/forum.php?mod=viewthread&tid=981&extra=page%3D1,开发快官网地址:http://www.kaifakuai.com/ 》》》》》》写于2017年1月12日
本文摘录于本人博客:http://bbs.elecfans.com/forum.php?mod=viewthread&tid=1101351&extra=
在上面关于判断是否获取IP的函数user_esp_platform_check_ip之中提到当连接到正确的IP的时候将调用et_user_main,这个属于用户应用程序了,上文:http://bbs.elecfans.com/forum.ph ... =1101320&extra=,这里将分析et_user_main函数,其内容如下:
void et_user_main(void *pvParameters)
{
et_int32 rc = -1;
id_info_t id;
et_server_info_t server_info;
et_net_addr_type g_cloud_addr_para = {NULL, 0};
os_printf("ET U-SDK var%s\n",et_sdk_ver());
to_stop_app = 0;
memset(&id, 0, sizeof(id_info_t));
if(get_uid(&id) != SPI_FLASH_RESULT_OK)
{
os_printf("et_user_main, get_uid error\n");
return ;
}
id.uid[UID_LEN - 1] = '\0';
id.appkey[APPKEY_LEN - 1] = '\0';
id.secretkey[SECRETKEY_LEN - 1] = '\0';
memset(&server_info, 0, sizeof(et_server_info_t));
if(get_server(&server_info) != SPI_FLASH_RESULT_OK)
{
os_printf("et_user_main, get_server error\n");
return ;
}
server_info.lb_addr[ET_LB_ADDR_MAX - 1] = '\0';
server_info.lb_port[ET_LB_PORT_MAX - 1] = '\0';
g_cloud_addr_para.name_ip = server_info.lb_addr;
g_cloud_addr_para.port = atoi(server_info.lb_port);
os_printf("uid : %s\n", id.uid);
os_printf("appkey : %s\n", id.appkey);
os_printf("secretkey : %s\n", id.secretkey);
os_printf("server information %s : %s\n", server_info.lb_addr, server_info.lb_port);
g_cloud_handle = et_create_context(id.uid, id.appkey, id.secretkey, g_cloud_addr_para);
if(NULL == g_cloud_handle)
{
os_printf("Init et account failed\n");
goto error;
}
if(et_set_callback(g_cloud_handle,et_message_process, et_event_process) < 0)
{
os_printf("%s et_set_callback failed.\n");
et_destroy_context(g_cloud_handle);
goto error;
}
rc = et_start_svr(g_cloud_handle);
if(rc != 0){
os_printf("%s et_start_svr fail.\n", __FUNCTION__);
et_destroy_context(g_cloud_handle);
return;
}
if(pdPASS != xTaskCreate(et_local_task, "local_task", 512, NULL, 2, NULL))
{
os_printf("%s et_local_task failed.\n", __FUNCTION__);
et_stop_srv(g_cloud_handle);
et_destroy_context(g_cloud_handle);
return;
}
do
{
rc = et_login_cloud(g_cloud_handle, g_cloud_con_para);
if(rc != 0)
{
os_printf("login_cloud fail\n");
}
vTaskDelay(2000 / portTICK_RATE_MS);
}while(rc != 0 && to_stop_app == 0);
if(pdPASS != xTaskCreate(et_ilink_task, "ilink_task", 768, NULL, 2, NULL))
{
os_printf("%s et_ilink_task failed.\n", __FUNCTION__);
et_logout_cloud(g_cloud_handle);
et_destroy_context(g_cloud_handle);
goto error;
}
error:
vTaskDelete(NULL);
return ;
}首先打印字符串“ET U-SDK var。。。。”,然后设置to_stop_app = 0;接下来配置id_info_t和et_server_info_t以及et_net_addr_type结构体,然后打印出相应信息,这三个结构体的内容如下:
typedef struct id_info {
et_uchar appkey[APPKEY_LEN];
et_uchar uid[UID_LEN];
et_uchar secretkey[SECRETKEY_LEN];
}id_info_t;
struct et_server_info {
et_uchar lb_port[ET_LB_PORT_MAX];
et_uchar lb_addr[ET_LB_ADDR_MAX];
};
typedef struct{
et_char *name_ip; ///< 域名或地址
et_uint16 port; ///< 端口
}et_net_addr_type;
下面是创建上下文,也就是根据前面的信息得到一个上下文句柄g_cloud_handle:
g_cloud_handle = et_create_context(id.uid, id.appkey, id.secretkey, g_cloud_addr_para);
if(NULL == g_cloud_handle)
{
os_printf("Init et account failed\n");
goto error;
}
上面的这个函数是封装起来的,下面的内容如下:
if(et_set_callback(g_cloud_handle,et_message_process, et_event_process) < 0)
{
os_printf("%s et_set_callback failed.\n");
et_destroy_context(g_cloud_handle);
goto error;
}回调函数分为消息回调et_message_process和事件回调et_event_process,这两个函数分别处理协议栈返回的消息类型和事件类型,如下:
/**
* 消息类型
*/
typedef enum{
MES_CHAT_TO_CHAT = 1, ///< 点对点消息
MES_FROM_GROUP_SUBTOPIC, ///< 群消息或主题消息
MES_FROM_LOCAL, ///< 本地消息
MES_FILE_TRANSFERS, ///< 文件消息
MES_USER_ONLINE, ///< 用户上线通知消息
MES_USER_OFFLINE, ///< 用户下线通知消息
MES_USER_STATUS, ///< 用户状态消息
MES_NOTICE_ADD_BUDDY, ///< 添加用户通知消息
MES_NOTICE_REMOVE_BUDDY, ///< 删除用户通知消息
MES_ONLINE_BUDDIES_LIST, ///< 在线好友列表消息
MES_CHAT_TO_CHAT_EX ///< 点对点扩展消息
}et_mes_type;
/**
* 事件类型
*/
typedef enum{
EVENT_CLOUD_CONNECT = 1, ///< iLink连接事件
EVENT_CLOUD_DISCONNECT, ///< iLink断连时间
EVENT_LOGIN_KICK, ///< 被踢下线事件
EVENT_CLOUD_SEND_FAILED, ///< iLink消息发送失败事件
EVENT_CLOUD_SEND_SUCCESS, ///< iLink消息发送成功事件
EVENT_LOCAL_SEND_FAILED, ///< 本地消息发送失败事件
EVENT_LOCAL_SEND_SUCCESS, ///< 本地消息发送成功事件
EVENT_LOCAL_CONNECT, ///< 本地连接事件
EVENT_LOCAL_DISCONNECT, ///< 本地断连事件
EVENT_HTTP_INIT_SUCCESS, ///< HTTP初始化成功事件
EVENT_HTTP_INIT_FAILED ///< HTTP初始化失败事件
}et_event_no_type;
另外这里如果设置回调函数不成功将销毁上下文句柄g_cloud_handle,et_user_main函数下来的内容:
rc = et_start_svr(g_cloud_handle);
if(rc != 0){
os_printf("%s et_start_svr fail.\n", __FUNCTION__);
et_destroy_context(g_cloud_handle);
return;
}这里启动内网服务,如果启动不成功也会销毁上下文句柄g_cloud_handle,接下来:
if(pdPASS != xTaskCreate(et_local_task, "local_task", 512, NULL, 2, NULL))
{
os_printf("%s et_local_task failed.\n", __FUNCTION__);
et_stop_srv(g_cloud_handle);
et_destroy_context(g_cloud_handle);
return;
}
这里创建一个et_local_task任务,该任务的回调函数如下:
void et_local_task(void *pvParameters)
{
while(1)
{
et_server_loop(g_cloud_handle);
taskYIELD();
}
vTaskDelete(NULL);
}这个函数主要的工作就是网内轮询,是WiFi运行机制的必要内容,还有就是上下文切换函数,一样如果这里不成功也会消除前面的上下文句柄。et_user_main函数下来的内容如下:
do
{
rc = et_login_cloud(g_cloud_handle, g_cloud_con_para);
if(rc != 0)
{
os_printf("login_cloud fail\n");
}
vTaskDelay(2000 / portTICK_RATE_MS);
}while(rc != 0 && to_stop_app == 0);
这里将调用et_login_cloud函数来连接网络,最终调用的函数是et_connect作为最终的连接,这里传入的第二个变量是连接参数et_cloud_connect_type,其结构体如下:
typedef struct{
et_bool clr_offline_mes;
et_bool auto_relogin;
et_uint16 alive_sec;
}et_cloud_connect_type;
这里不断的重连知道连接成功或者按下了airkiss按键设置to_stop_app为1.接下来的内容如下:
if(pdPASS != xTaskCreate(et_ilink_task, "ilink_task", 768, NULL, 2, NULL))
{
os_printf("%s et_ilink_task failed.\n", __FUNCTION__);
et_logout_cloud(g_cloud_handle);
et_destroy_context(g_cloud_handle);
goto error;
}这里创建了一个任务et_ilink_task该任务和上面的任务et_local_task有很大的相似性,刚才那个任务是服务调度,现在这个任务是连接调度,如果任务创建失败也会销毁前面所有的句柄。下来:
error:
vTaskDelete(NULL);
return ;
这里删除任务然后退出程序。
到这里这个函数也分析完成,最后整体的实验架构分析完成。