完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 城东 于 2016-12-13 23:26 编辑
在前面的分析中我们知道et_user_main函数结束的时候可以说所有的初始化所有的配置已经结束了,在这里一共注册了几个回调函数: 1.airkiss按键轮询函数:airkiss_key_poll_task,该函数负责监测按键airkiss的操作,如果按下该按键就会重新配置wifi(云配置) 2.wifi事件回调函数: et_wifi_event_cb,该函数负责处理wifi事件,比如wif扫描AP完成和连接到AP以及获取到IP等事件回调 3.wifi协议栈信息回调函数:et_message_process,该函数负责处理协议栈返回的信息 5.wifi协议栈事件回调函数:et_event_process,该函数负责处理协议栈返回的事件回调信息 6.服务轮询函数:et_local_task和链路轮询函数et_ilink_task,这两个函数在本文中不做分析 可以参看之前的文章以做更多的了解:https://bbs.elecfans.com/forum.ph ... &tid=1101351&extra= 下面我们来分析et_message_process和et_event_process,这里就不再主题帖贴上这两个函数的具体内容了,将在后面的回复内容中贴上具体的代码。下面分析et_message_process: 从整体来看,et_message_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; 这里针对一些有用的消息,除此之外的消息处理只是通过串口发送信息,没有什么特别的操作,现在先看点对点信息处理: case MES_CHAT_TO_CHAT: { os_printf("mes chat to chat: %sn", send_userid); memset(g_user_id, 0, sizeof(g_user_id)); snprintf(g_user_id, sizeof(g_user_id), "%s",send_userid); parse_msg_from_mqtt(message->payload, message->payload_len); } 这里首先把传入的发送方ID:send_userid存放到g_user_id数组,然后调用parse_msg_from_mqtt函数解析发送过来的数据,这个函数是十分重要的一个函数-他对微信或者APP发送过来的数据进行解析然后做出相应的操作,下面将具体分析这个函数: if(msg_buf[pos] != 0xFF ||msg_buf[pos + 1] != 0xFF) { os_printf("parse packet head errorn"); return rc; } pos += 2; len = (msg_buf[pos] << 8) | msg_buf[pos + 1]; if(len < 3 || len != data_len - 2 - 2) { os_printf("parse packet length errorn"); return rc; }这里首先判断发送过来的数据包是否正确,如果不正确将直接退出这个函数,下来: bcc = check_sum(&msg_buf[pos], len + 2 - 1); if(bcc != msg_buf[data_len - 1]) { msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_BCC_ERROR); os_printf("bcc errorn"); rc = et_chat_to(g_cloud_handle,msg.buf, msg.len, g_user_id, SEND_TO_ALL); return rc; }这里计算出发送过来的检验和bcc,如果检验和不对将用et_chat_to函数向远端发送点对点信息,这里用 ack_to_mqtt函数填充要发送过去的数组。接下来: pos += 2; cmd = msg_buf[pos]; pos += 1; seq += msg_buf[pos]; pos += 1; type = msg_buf[pos]; pos += 1; mode = user_get_run_mode(); //get board mode from adc 这里取出cmd、seq和 type这三个微信发送过来的内容,之后从拨码开关获取目前的工作模型mode,接下来根据发送过来的命令做出相应的响应,这里命令一共有:CMD_VER_UPDATE_NOTE、CMD_CONTROL、CMD_QUERY这三种类型,其中第一个命令类型是用来启动网络更新固件使用,与目前的分析无关,下面分析CMD_CONTROL命令,这是微信发过来控制开发板的命令,这里根据微信发送过来的命令类型type做出相应的响应,这里分为TYPE_RGB_LIGHT_DEV和TYPE_OLED_DEV两种类型,也就是说这里只能够控制OLED和RGB灯,先分析RGB灯: case TYPE_RGB_LIGHT_DEV: { if(mode == WORK_MODE_RGB) { //code undefine et_uchar red; et_uchar gre; et_uchar blu; red = msg_buf[pos]; pos += 1; gre = msg_buf[pos]; pos += 1; blu = msg_buf[pos]; RGB_light_set_color(red, gre, blu); //set rgb color msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_SUCCESS); rc = msg.len; } else { printf("mode error, mode = %un", mode); msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_MODE_ERR); rc = msg.len; } }首先这里先判断本地是否是RGB模式,如果是RGB模式则根据传送回来的值通过 RGB_light_set_color函数设置RGB灯,该函数最终设置RGB三个灯所在的PWM通道: RGB_light_set_duty(RGB_TO_DUTY((et_uint8)~r, max_duty), LIGHT_RED); RGB_light_set_duty(RGB_TO_DUTY((et_uint8)~g, max_duty), LIGHT_GREEN); RGB_light_set_duty(RGB_TO_DUTY((et_uint8)~b, max_duty), LIGHT_BLUE); #endif RGB_light_start(); 回到parse_msg_from_mqtt函数继续往下分析微信对OLED的操作,这里和RGB一样先判断当前模式是否是OLED模式,如果是则继续往下分析,分析如下: num = (len - 4) / 2; //numbers of characters if(num == 0) break; if(num > 32) num = 32; line = (num - 1) /8 + 1; for(i = 0; i < line - 1; i++) //0 to line -1 is 8 characters { colum = 8; } colum = num % 8; //the last line if(colum == 0) colum = 8; OLED_clear(); //clear oled 这里先根据传送回来的数据得到num、line和 colum这三个数据,这三个只是组织OLED的整体布局,OLED每行能够显示128/8=16个英文,能显示64/16四行8X16的英文。但是有一定要注意这里在OLED上显示的数据均为汉字也就是16X16,那么每行能显示128/16也就是8个汉字,最多也是4行。这样上面的算法也就不难分析了,最后上面清除了屏幕,下来: for(i = 0; i < line; i++) { for(j = 0; j < colum ; j++) { z_code = msg_buf[pos++]; b_code = msg_buf[pos++]; gb_code = (z_code << 8) | b_code; if(gb_code > 0x3759) //after 0xd7f9 ,five space { gb_code -= 5; if(b_code >= 0x01 && b_code <= 0x04) gb_code -= 0xa2; } z_code = (gb_code >> 8) & 0xff; b_code = gb_code & 0xff; offset = ((et_uint32)94 * (z_code - 0x10) + b_code - 0x01)*(16 * 2); spi_flash_read(GB_DZK_START_SECTOR * SPI_FLASH_SEC_SIZE + offset, (et_uint *)code , 32); oled_show_gb_chn(16 * j, 2 * i, code); } }这里一个字一个字显示数据,但是值得注意的一点是这里的字库点阵是存放到flash的,这里的flash应该封装在金属罩里面,这里看不到了,最后调用 oled_show_gb_chn显示汉字。控制命令分析完毕,现在退出一格分析请求命令CMD_QUERY,在该命令分支中分为读取温湿度请求TYPE_TEMP_HUM_SENSOR和读取气压请求TYPE_BAROMETRIC_SENSOR,先看温湿度传感器: et_uchar temp_hum[HUM_DATA_SIZE]={0}; if(DHT11_read_temp_hum(temp_hum, HUM_DATA_SIZE) != RETURN_OK) { os_printf("DHT11_read_temp_hum errorn"); msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_DEV_FAILED); rc = msg.len; break; }这里首先读取到当前环境下的温湿度存放到数组temp_hum中,接下来: msg.len = ack_temp_hum_to_mqtt(msg_buf, temp_hum, msg.buf, ACK_SUCCESS); rc = msg.len; 这里通过ack_temp_hum_to_mqtt函数填充要发送会给微信的数组msg_buf,接下来: if(mode == WORK_MODE_OLED) { et_uchar display_temp[7]={0}; et_uchar display_hum[8]={0}; sprintf(display_temp, ":%d.%d", temp_hum[2], temp_hum[3]); sprintf(display_hum, ":%d.%d%%", temp_hum[0], temp_hum[1]); OLED_clear(); //clear oled switch(type & 0x0F) { case TEMP_AND_HUM: { //display tempeature and hummity, such as: //温度:20.08℃ //湿度:60.89% OLED_show_chn(0, 0, 15); //show 小e: OLED_show_str(18, 0, "e:", 2); OLED_show_chn(0, 2, 0); //温 OLED_show_chn(18, 2, 1); //度 OLED_show_str(36, 2, display_temp, 2); //such as :20.08 OLED_show_chn(86, 2, 2); //℃ OLED_show_chn(0, 4, 3); //湿 OLED_show_chn(18, 4, 4); //度 OLED_show_str(36, 4, display_hum, 2);//such as :80.05% } break; case TEMPERATUR: { OLED_show_chn(0, 0, 15); //show 小e: OLED_show_str(18, 0, "e:",2 ); OLED_show_chn(0, 2, 0); //温 OLED_show_chn(18, 2, 1); //度 OLED_show_str(36, 2, display_temp, 2); //such as :20.08 OLED_show_chn(86, 2, 2); //℃ } break; case HUMMITY: { OLED_show_chn(0, 0, 15); //show 小e: OLED_show_str(18, 0, "e:", 2); OLED_show_chn(0, 2, 3); //湿 OLED_show_chn(18, 2, 4); //度 OLED_show_str(36, 2, display_hum, 2);//such as :80.05% } break; } }这里根据发送过来的命令在OLED上显示读回来的温湿度。接下来我们继续分析读取气压请求TYPE_BAROMETRIC_SENSOR: case TYPE_BAROMETRIC_SENSOR: { et_long32 barometric=0, temperature=0; if(mode == WORK_MODE_BAROMETRIC) { barometric = barometric_collect(&temperature); if(barometric == -1) { os_printf("barometric_collect errorn"); msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_DEV_FAILED); rc = msg.len; break; } msg.len = ack_barometric_to_mqtt(msg_buf, (et_int32)barometric, (et_int32)temperature, msg.buf, ACK_SUCCESS); rc = msg.len; } else { os_printf("mode error, mode = %dn", mode); msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_MODE_ERR); rc = msg.len; } }这里只是填充msg结构体,并没有显示OLED操作,到这里命令分析就结束了,最后当结束完所有的命令之后就调用函数:rc = et_chat_to(g_cloud_handle,msg.buf, msg.len, g_user_id, SEND_TO_CLOUD_FIRST);把开发板采集到的信息发送到云端。到这类MES_CHAT_TO_CHAT分支分析结束,下面回到et_message_process函数中继续往下分析,我们可以看到: case MES_FROM_GROUP_SUBTOPIC: { os_printf("Group mes from %sn", topic_name); parse_msg_from_mqtt(message->payload, message->payload_len); } break; case MES_FROM_LOCAL: { os_printf("Local mes from %s:%sn", send_userid, topic_name); memset(g_user_id, 0, sizeof(g_user_id)); snprintf(g_user_id, sizeof(g_user_id), "%s",send_userid); parse_msg_from_mqtt(message->payload, message->payload_len); }经过上面对点对点的消息类型的分析,这两个消息类型也就自然而然的知道了,最后还剩MES_FILE_TRANSFERS消息类型,时间很晚了,这个消息类型就放到明天吧,今天就到这里2016-12-12 继续分析,首先MES_FILE_TRANSFERS消息只是针对于音频模式,也就是语音留言功能等,如下: if(user_get_run_mode() != WORK_MODE_AUDIO) { printf("run in mode %d ,errorn", user_get_run_mode()); break; } 接下来: os_printf("File trans mes from %s:%sn", send_userid, topic_name); memset(&i_file_info, 0, sizeof(et_dfs_file_info_type)); rc = et_file_info(g_cloud_handle,message->payload, &i_file_info); if(rc == -1) { os_printf("file info parse failedn"); break; } 这里获取文件信息,也就是填充i_file_info结构体,该结构体如下: /** * 文件信息结构 */ typedef struct { et_file_msg_type type; ///< 文件消息类型,5 bytes et_uint32 crc32; ///< CRC32校验码,10 bytes et_long32 file_size; ///< 文件大小,20 bytes et_char source_ip_addr[ET_NET_IP_LEN_MAX]; ///< 文件存储IP et_char port[ET_NET_PORT_LEN_MAX]; ///< 端口 et_char file_id[ET_FILE_ID_LEN_MAX]; ///< 文件ID et_char file_name[ET_FILE_NAME_LEN_MAX]; ///< 文件名 et_char descn[ET_FILE_DESCN_LEN_MAX]; ///< 异常信息 } et_dfs_file_info_type; 接下来: if(file_server_ip_addr == NULL) { file_server_ip_addr = gethostbyname(i_file_info.source_ip_addr); if(file_server_ip_addr == NULL) { os_printf("failed, get ip from im servern"); break; } } memset(i_file_info.source_ip_addr, 0, sizeof(i_file_info.source_ip_addr)); strcpy(i_file_info.source_ip_addr, inet_ntoa(*(file_server_ip_addr->h_addr))); 这里首先获取file_server_ip_addr文件服务器ip地址,然后把得到的地址经过变换存回i_file_info.source_ip_addr中,接下来: while(write_flash_end) { os_delay_us(500); } rc = et_down_file(g_cloud_handle,&i_file_info, write_flash_callback); 这里write_flash_end默认为0,其为1表示目前正在写flash,最终调用et_down_file函数,这里传入上面计算出来的文件信息,当文件下载完成的时候最终调用write_flash_callback函数处理下载完成之后的信息,我们继续看 write_flash_callback这个回调函数,这个函数最终调用flash写函数把下载到的文件烧写到flash中: result = spi_flash_write(sector * SPI_FLASH_SEC_SIZE, (et_uint32 *)data, current_size); 下载文件使用的是分段下载,并不是一下子把文件的所有信息下载到flash中,起码回调函数是分段的,回调函数的定义如下:et_int32 write_flash_callback (void *arg, const et_int64 file_size, const et_char *data, const et_int32 current_size) 其中file_size代表总的文件长度,current_size代表目前的文件长度 但是这里还是有一个疑惑,这里只是把文件下载下来而已,怎么通过IIS发送这些下载下来的数据呢?这点暂时不可知。 到这里整个et_message_process函数分析完成,下面看看et_event_process事件回调函数,这里除了 case EVENT_CLOUD_CONNECT: { disARM_wifi_spark_timer(); wifi_led_on(); os_printf("You are connect:0x%xn", event.event_no); } break; case EVENT_CLOUD_DISCONNECT: { set_wifi_spark_timer(1000); os_printf("You are disconnect:0x%xn", event.event_no); //et_logout_cloud(g_cloud_handle); //et_stop_srv(g_cloud_handle); }这两个其他只有一些打印信息,到了这里我们知道了整个程序的流程了。相对而言这个微信程序是比较复杂的。 |
|
相关推荐
1 个讨论
|
|
这里补充et_message_process、et_event_process两个函数的具体内容:
void et_message_process(et_int32 type, et_char *send_userid, et_char *topic_name, et_int32 topic_len, et_context_mes_type *message) { int rc = -1; switch(type) { case MES_CHAT_TO_CHAT: { os_printf("mes chat to chat: %sn", send_userid); memset(g_user_id, 0, sizeof(g_user_id)); snprintf(g_user_id, sizeof(g_user_id), "%s",send_userid); parse_msg_from_mqtt(message->payload, message->payload_len); } break; case MES_FILE_TRANSFERS: { if(user_get_run_mode() != WORK_MODE_AUDIO) { printf("run in mode %d ,errorn", user_get_run_mode()); break; } os_printf("File trans mes from %s:%sn", send_userid, topic_name); memset(&i_file_info, 0, sizeof(et_dfs_file_info_type)); rc = et_file_info(g_cloud_handle,message->payload, &i_file_info); if(rc == -1) { os_printf("file info parse failedn"); break; } if(file_server_ip_addr == NULL) { file_server_ip_addr = gethostbyname(i_file_info.source_ip_addr); if(file_server_ip_addr == NULL) { os_printf("failed, get ip from im servern"); break; } } memset(i_file_info.source_ip_addr, 0, sizeof(i_file_info.source_ip_addr)); strcpy(i_file_info.source_ip_addr, inet_ntoa(*(file_server_ip_addr->h_addr))); while(write_flash_end) { os_delay_us(500); } rc = et_down_file(g_cloud_handle,&i_file_info, write_flash_callback); } break; case MES_FROM_GROUP_SUBTOPIC: { os_printf("Group mes from %sn", topic_name); parse_msg_from_mqtt(message->payload, message->payload_len); } break; case MES_FROM_LOCAL: { os_printf("Local mes from %s:%sn", send_userid, topic_name); memset(g_user_id, 0, sizeof(g_user_id)); snprintf(g_user_id, sizeof(g_user_id), "%s",send_userid); parse_msg_from_mqtt(message->payload, message->payload_len); } break; case MES_NOTICE_ADD_BUDDY: os_printf("You are be add buddy by %s:%sn", send_userid, topic_name); break; case MES_NOTICE_REMOVE_BUDDY: os_printf("You are be remove buddy by %s:%sn", send_userid, topic_name); break; case MES_USER_OFFLINE: os_printf("%s Offline:%sn", send_userid, topic_name); break; case MES_USER_ONLINE: os_printf("%s Online:%sn", send_userid, topic_name); break; case MES_USER_STATUS: os_printf("%s Status:%sn", send_userid, topic_name); break; case MES_ONLINE_BUDDIES_LIST: os_printf("Get online buddies list%s:%sn", send_userid, topic_name); break; } } void et_event_process(et_event_type event) { et_int32 rc = -1; switch(event.event_no) { case EVENT_CLOUD_CONNECT: { disarm_wifi_spark_timer(); wifi_led_on(); os_printf("You are connect:0x%xn", event.event_no); } break; case EVENT_CLOUD_DISCONNECT: { set_wifi_spark_timer(1000); os_printf("You are disconnect:0x%xn", event.event_no); //et_logout_cloud(g_cloud_handle); //et_stop_srv(g_cloud_handle); } break; case EVENT_LOGIN_KICK: kick_out = 1; os_printf("Your account was login by others:0x%xn", event.event_no); //et_stop_srv(g_cloud_handle); //et_logout_cloud(g_cloud_handle); break; case EVENT_CLOUD_SEND_FAILED: os_printf("Cloud send failedn"); break; case EVENT_CLOUD_SEND_SUCCESS: os_printf("Cloud send successn"); break; case EVENT_LOCAL_SEND_FAILED: os_printf("Local send failedn"); break; case EVENT_LOCAL_SEND_SUCCESS: os_printf("Local send successn"); break; } } |
|
|
|
|
|
只有小组成员才能发言,加入小组>>
[小e体验板] 【小体积大智慧】关于体验板的技术问题,看这一篇就够了
2881 浏览 4 评论
【小e1开发板试用体验】分析程序架构四~/Share/SDK/makefile分析
3648 浏览 1 评论
6767 浏览 19 评论
29276 浏览 59 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-28 10:56 , Processed in 0.347246 second(s), Total 40, Slave 33 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号