/** * @file menu.c * @author Chen Jihang (embedded@eseaoptics.com) * @brief 串口菜单 * @note 须配合对应版本的menu_builder使用 * @version 1.0 * @date 2023-01-04 * * @copyright ESEA (c) 2020 * */ #include #include "menu.h" #include "convert.h" /** * @brief 将指定的数据转换为字符串 * * @param pnode 菜单节点 * @param num 计数 * @param buf 字符串缓冲区 * @param size 缓冲区大小 * @return uint32_t 使用的缓冲区大小 */ static inline uint32_t menu_convert_data_to_str(const struct menu_tree_node *pnode,uint16_t num,char *buf,uint32_t size) { uint32_t i=0; switch(pnode->data_type) { case MENU_DATA_TYPE_CHAR: case MENU_DATA_TYPE_RO_CHAR: if(((char*)pnode->data)[num]!='\0'){ buf[i++]=((char*)pnode->data)[num]; } break; case MENU_DATA_TYPE_UINT8: case MENU_DATA_TYPE_RO_UINT8: i+=convert_u32_to_s(((uint8_t*)pnode->data)[num],buf,size); break; case MENU_DATA_TYPE_INT8: case MENU_DATA_TYPE_RO_INT8: i+=convert_i32_to_s(((int8_t*)pnode->data)[num],buf,size); break; case MENU_DATA_TYPE_UINT16: case MENU_DATA_TYPE_RO_UINT16: i+=convert_u32_to_s(((uint16_t*)pnode->data)[num],buf,size); break; case MENU_DATA_TYPE_INT16: case MENU_DATA_TYPE_RO_INT16: i+=convert_i32_to_s(((int16_t*)pnode->data)[num],buf,size); break; case MENU_DATA_TYPE_UINT32: case MENU_DATA_TYPE_RO_UINT32: i+=convert_u32_to_s(((uint32_t*)pnode->data)[num],buf,size); break; case MENU_DATA_TYPE_INT32: case MENU_DATA_TYPE_RO_INT32: i+=convert_i32_to_s(((int32_t*)pnode->data)[num],buf,size); break; case MENU_DATA_TYPE_IPV4: case MENU_DATA_TYPE_RO_IPV4: i+=convert_ip2ips(((uint32_t*)pnode->data)[num],buf,size); break; default: return 0; break; } return i; } /** * @brief 将字符串转换为数据 * * @param pnode 菜单节点 * @param num 计数 * @param buf 字符串 * @param size 字符串长度 * @return uint32_t 转换的字符串长度 */ static inline uint32_t menu_convert_str_to_data(const struct menu_tree_node *pnode,uint16_t num,char *buf,uint32_t size) { uint32_t i=0; uint32_t tmp_u32; int32_t tmp_i32; if(pnode->data_type==MENU_DATA_TYPE_UINT8 || pnode->data_type==MENU_DATA_TYPE_UINT16 || pnode->data_type==MENU_DATA_TYPE_UINT32){ i+=convert_s_to_u32(&tmp_u32,buf,size); if(tmp_u32<(uint32_t)pnode->min_value || tmp_u32>(uint32_t)pnode->max_value){ return 0; } } else if(pnode->data_type==MENU_DATA_TYPE_INT8 || pnode->data_type==MENU_DATA_TYPE_INT16 || pnode->data_type==MENU_DATA_TYPE_INT32){ i+=convert_s_to_i32(&tmp_i32,buf,size); if(tmp_i32<(int32_t)pnode->min_value || tmp_i32>(int32_t)pnode->max_value){ return 0; } } switch(pnode->data_type) { case MENU_DATA_TYPE_CHAR: ((char*)pnode->data)[num]=buf[i++]; break; case MENU_DATA_TYPE_UINT8: ((uint8_t*)pnode->data)[num]=tmp_u32; break; case MENU_DATA_TYPE_INT8: ((int8_t*)pnode->data)[num]=tmp_i32; break; case MENU_DATA_TYPE_UINT16: ((uint16_t*)pnode->data)[num]=tmp_u32; break; case MENU_DATA_TYPE_INT16: ((int16_t*)pnode->data)[num]=tmp_i32; break; case MENU_DATA_TYPE_UINT32: ((uint32_t*)pnode->data)[num]=tmp_u32; break; case MENU_DATA_TYPE_INT32: ((int32_t*)pnode->data)[num]=tmp_i32; break; case MENU_DATA_TYPE_IPV4: i+=convert_ips2ip((&((uint32_t*)pnode->data)[num]),buf,size); break; default: break; } return i; } /** * @brief 使用字符串中的数据设置菜单节点中的数据 * * @param pnode 菜单节点 * @param buf 字符串 * @param size 字符串长度 * @return uint32_t 转换的字符串长度 */ static inline uint32_t menu_set_data(const struct menu_tree_node *pnode,char *buf,uint32_t size) { uint32_t i,j; uint16_t num_con; num_con=0; i=0; if(pnode->data==NULL){ return 0; } do{ if(buf[i]==' '){ i++; } j=menu_convert_str_to_data(pnode,num_con,&buf[i],size-i); if(j==0){ return 0; } i+=j; num_con++; }while(num_connum); return i; } /** * @brief 从菜单节点中获取数据 * * @param pnode 菜单节点 * @param buf 字符串缓冲区 * @param size 缓冲区大小 * @return uint32_t 使用的缓冲区大小 */ static inline uint32_t menu_get_data(const struct menu_tree_node *pnode,char *buf,uint32_t size) { uint32_t i,j; uint16_t num_con; num_con=0; if(pnode->data==NULL){ return 0; } if(size<4){ return 0; } i=0; do{ j=menu_convert_data_to_str(pnode,num_con,&buf[i],size-i-4); if(j==0 && (pnode->data_type==MENU_DATA_TYPE_CHAR || pnode->data_type==MENU_DATA_TYPE_RO_CHAR)){ break; } if(j==0 || i+j>=size-5){ buf[i++]=' '; buf[i++]='.'; buf[i++]='.'; buf[i++]='.'; break; } i+=j; if(pnode->data_type!=MENU_DATA_TYPE_CHAR && pnode->data_type!=MENU_DATA_TYPE_RO_CHAR){ buf[i++]=' '; } num_con++; }while(num_connum); return i; } /** * @brief 从菜单节点中获取信息 * * @param pnode 菜单节点 * @param buf 缓冲区 * @param width 允许使用的宽度 * @param size 缓冲区大小 * @return uint32_t 使用的缓冲区大小 */ static inline uint32_t menu_get_info(const struct menu_tree_node *pnode,char *buf,uint32_t width,uint32_t size) { uint32_t i,j; uint32_t p_lc=0; if(size<4 || width<4){ return 0; } for(i=0,j=0;pnode->info_str[i]!='\0' && pnode->info_str[i]!='\r' && pnode->info_str[i]!='\n';i++){ if(j>width-5 || i>=size-5){ if((pnode->info_str[i]&0xc0)==0x80){ i=p_lc; j--; } buf[i++]=' '; buf[i++]='.'; buf[i++]='.'; buf[i++]='.'; j+=4; break; } if((pnode->info_str[i]&0x80)==0){ //普通字符 p_lc=i; j++; } if((pnode->info_str[i]&0xc0)==0xc0){ //多字节字符 p_lc=i; j+=MENU_CHINESE_CHARACTER_WIDTH; } buf[i]=pnode->info_str[i]; } for(;j<=width && iterminal_width*(uint32_t)5)/8; data_size=menu->terminal_width-info_size; i=0; menu->output_buf[i++]='\r'; menu->output_buf[i++]='\n'; menu->output_buf[i++]='['; j=convert_u2s(menu->child_con,&menu->output_buf[i],info_size-i-3); if(j==0){ return 0; } i+=j; menu->output_buf[i++]=']'; menu->output_buf[i++]=' '; if(menu->child_con==0){ if(menu->node==1){ memcpy(&menu->output_buf[i],"退出",6); i+=6; } else{ memcpy(&menu->output_buf[i],"返回上一级",15); i+=15; } return i; } j=menu_get_info(&menu->menu_tree[menu->child_node],&menu->output_buf[i],info_size+2-i,MENU_OUTPUT_BUF_SIZE-i); if(j==0){ return 0; } i+=j; j=menu_get_data(&menu->menu_tree[menu->child_node],&menu->output_buf[i],data_size); i+=j; return i; } /** * @brief 初始化菜单 * * @param menu struct menu 结构 * @param menu_tree 由程序生成的菜单树 * @param send_class send函数的第一个参数 * @param send send函数 * @return struct menu* 成功:menu 失败:NULL */ struct menu *menu_init(struct menu *menu,const struct menu_tree_node *menu_tree,void *send_class,menu_send_function_type send) { if(menu==NULL || menu_tree==NULL || send_class==NULL || send==NULL){ return NULL; } menu->menu_tree=menu_tree; menu->send_class=send_class; menu->send=send; menu->check_passwd=NULL; menu->node=0; menu->child_node=0; menu->child_con=0; menu->input_con=0; menu->flag_ready=0; menu->flag_flush=0; menu->terminal_width=MENU_TERMINAL_WIDTH; return menu; } /** * @brief 设置终端的宽度 * * @param menu struct menu 结构 * @param terminal_width 终端宽度 * @return int 成功:0 失败:负值 */ int menu_set_terminal_width(struct menu *menu,uint8_t terminal_width) { if(menu==NULL){ return -1; } menu->terminal_width=terminal_width; return 0; } /** * @brief 设置check_passwd钩子 * * @param menu struct menu 结构 * @param check_passwd check_passwd函数指针 * @return int 成功:0 失败:负值 */ int menu_set_hook_passwd(struct menu *menu,menu_check_passwd_function_type check_passwd) { if(menu==NULL || check_passwd==NULL){ return -1; } menu->check_passwd=check_passwd; return 0; } /** * @brief 使用menu结构中的发送函数发送 * * @param menu struct menu 结构 * @param buf 要发送的数据 * @param size 要发送数据的大小 * @return int 成功:0 失败:负值 */ int menu_send(struct menu *menu,char *buf,uint32_t size) { return menu->send(menu->send_class,buf,size); } /** * @brief 获取menu当前的状态 * @note menu在收到回车或密码后会使能 未使能的菜单不会主动发送信息 * @param menu struct menu 结构 * @return int 0:未使能 1:使能 */ int menu_get_state(struct menu *menu) { return menu->node==0?0:1; } /** * @brief 菜单打印函数 需要放在循环中,在send函数可用时执行 * * @param menu struct menu 结构 */ void menu_print_callback(struct menu *menu) { uint32_t len; uint32_t i,j; uint32_t tmp; if(menu->node==0){ if(menu->flag_ready!=1){ menu->flag_flush=0; return; } if(menu->check_passwd==NULL || menu->check_passwd(menu,menu->input_buf,menu->input_con)==1){ menu->send(menu->send_class,menu->menu_tree[menu->node].info_str,strlen(menu->menu_tree[menu->node].info_str)); menu->node=1; menu->flag_flush=1; menu->flag_ready=2; } else{ menu->flag_ready=2; return; } } if(menu->flag_flush==1){ menu->flag_flush=0; menu->send(menu->send_class,menu->menu_tree[menu->node].info_str,strlen(menu->menu_tree[menu->node].info_str)); if(menu->menu_tree[menu->node].child!=0){ menu->output_buf[0]='\r'; menu->output_buf[1]='\n'; menu->output_buf[menu->terminal_width+2]='\r'; menu->output_buf[menu->terminal_width+3]='\n'; memset(&menu->output_buf[2],MENU_FILL_CHARACTER,menu->terminal_width); menu->send(menu->send_class,menu->output_buf,menu->terminal_width+4); menu->child_con=0; menu->child_node=menu->menu_tree[menu->node].child; return; } menu->send(menu->send_class,"\r\n当前值:\r\n",14); i=menu_get_data(&menu->menu_tree[menu->node],menu->output_buf,menu->terminal_width); if(i==0){ return; // 错误 } menu->output_buf[i++]='\r'; menu->output_buf[i++]='\n'; menu->send(menu->send_class,menu->output_buf,i); if((menu->menu_tree[menu->node].data_type&1)==1){ menu->node=menu->menu_tree[menu->node].father; menu->flag_flush=1; return; } menu->send(menu->send_class,"请输入:\r\n",12); j=i; switch(menu->menu_tree[menu->node].data_type) { case MENU_DATA_TYPE_CHAR: break; case MENU_DATA_TYPE_UINT8: case MENU_DATA_TYPE_UINT16: case MENU_DATA_TYPE_UINT32: menu->output_buf[j++]='['; j+=convert_u2s(menu->menu_tree[menu->node].min_value,&menu->output_buf[j],MENU_OUTPUT_BUF_SIZE-j); menu->output_buf[j++]=','; j+=convert_u2s(menu->menu_tree[menu->node].max_value,&menu->output_buf[j],MENU_OUTPUT_BUF_SIZE-j); menu->output_buf[j++]=']'; break; case MENU_DATA_TYPE_INT8: case MENU_DATA_TYPE_INT16: case MENU_DATA_TYPE_INT32: menu->output_buf[j++]='['; j+=convert_i2s(menu->menu_tree[menu->node].min_value,&menu->output_buf[j],MENU_OUTPUT_BUF_SIZE-j); menu->output_buf[j++]=','; j+=convert_i2s(menu->menu_tree[menu->node].max_value,&menu->output_buf[j],MENU_OUTPUT_BUF_SIZE-j); menu->output_buf[j++]=']'; break; case MENU_DATA_TYPE_IPV4: break; default: break; } if(menu->menu_tree[menu->node].num!=0){ menu->output_buf[j++]=' '; menu->output_buf[j++]='X'; j+=convert_u2s(menu->menu_tree[menu->node].num,&menu->output_buf[j],MENU_OUTPUT_BUF_SIZE-j); } menu->output_buf[j++]='>'; menu->send(menu->send_class,&menu->output_buf[i],j-i); return; } if(menu->child_node!=0){ len=0; len+=menu_build_item(menu); if(len==0){ return; // 出现错误 } menu->send(menu->send_class,menu->output_buf,len); menu->child_con++; if(menu->child_con!=1){ menu->child_node=menu->menu_tree[menu->child_node].next; } return; } if(menu->child_con!=0){ menu->child_con=0; menu->output_buf[0]='\r'; menu->output_buf[1]='\n'; menu->output_buf[menu->terminal_width+2]='\n'; memset(&menu->output_buf[2],MENU_FILL_CHARACTER,menu->terminal_width); menu->send(menu->send_class,menu->output_buf,menu->terminal_width+2); menu->send(menu->send_class,"\r\n>",3); } if(menu->flag_ready!=1){ return; } menu->flag_ready=2; menu->send(menu->send_class,"\r\n",2); if(menu->menu_tree[menu->node].child!=0){ len=convert_s_to_u32(&tmp,menu->input_buf,menu->input_con); if(len==0){ menu->flag_flush=1; return; } if(tmp==0){ menu->node=menu->menu_tree[menu->node].father; menu->flag_flush=1; return; } menu->child_node=menu->menu_tree[menu->node].child; for(menu->child_con=1;menu->child_conchild_con++){ menu->child_node=menu->menu_tree[menu->child_node].next; if(menu->child_node==0){ menu->send(menu->send_class,"\r\n错误:没有这个选项!\r\n",30); menu->child_node=menu->node; break; } } menu->node=menu->child_node; menu->child_node=0; menu->child_con=0; menu->flag_flush=1; } else{ j=menu_set_data(&menu->menu_tree[menu->node],menu->input_buf,menu->input_con); if(j==0){ menu->send(menu->send_class,"\r\n不匹配的值!\r\n",20); menu->flag_flush=1; } else{ menu->node=menu->menu_tree[menu->node].father; menu->flag_flush=1; } } } /** * @brief 菜单用户输入回调 * * @param menu struct menu 结构 * @param buf 用户输入的数据 * @param size 用户输入数据长度 */ void menu_parse_callback(struct menu *menu,char *buf,uint32_t size) { int i; if(menu->flag_ready==2){ menu->flag_ready=0; menu->input_con=0; } if(menu->flag_ready!=0){ return; } #if MENU_ECHO==1 if(menu_get_state(menu)==1){ menu->send(menu->send_class,buf,size); } #endif for(i=0;iinput_con==MENU_INPUT_BUF_SIZE-1 || buf[i]=='\n' || buf[i]=='\r'){ menu->input_buf[menu->input_con]='\0'; menu->flag_ready=1; return; } menu->input_buf[menu->input_con++]=buf[i]; } } void menu_exit(struct menu *menu) { menu->node=0; menu->child_node=0; menu->child_con=0; menu->input_con=0; menu->flag_ready=0; menu->flag_flush=0; } // /** // * @file menu.c // * @author Chen Jihang (embedded@eseaoptics.com) // * @brief 串口菜单 // * @note 须配合对应版本的menu_builder使用 // * @version 1.0 // * @date 2023-01-04 // * // * @copyright ESEA (c) 2020 // * // */ // #include // #include // #include "menu.h" // #include "convert.h" // #include "cmsis_os2.h" // #include "FreeRTOSConfig.h" // extern UART_HandleTypeDef huart1; // extern osSemaphoreId_t elog_dma_lockHandle; // /** // * @brief 将指定的数据转换为字符串 // * // * @param pnode 菜单节点 // * @param num 计数 // * @param buf 字符串缓冲区 // * @param size 缓冲区大小 // * @return uint32_t 使用的缓冲区大小 // */ // static inline uint32_t menu_convert_data_to_str(const struct menu_tree_node *pnode,uint16_t num,char *buf,uint32_t size) // { // uint32_t i=0; // switch(pnode->data_type) // { // case MENU_DATA_TYPE_CHAR: // case MENU_DATA_TYPE_RO_CHAR: // if(((char*)pnode->data)[num]!='\0'){ // buf[i++]=((char*)pnode->data)[num]; // } // break; // case MENU_DATA_TYPE_UINT8: // case MENU_DATA_TYPE_RO_UINT8: // i+=convert_u32_to_s(((uint8_t*)pnode->data)[num],buf,size); // break; // case MENU_DATA_TYPE_INT8: // case MENU_DATA_TYPE_RO_INT8: // i+=convert_i32_to_s(((int8_t*)pnode->data)[num],buf,size); // break; // case MENU_DATA_TYPE_UINT16: // case MENU_DATA_TYPE_RO_UINT16: // i+=convert_u32_to_s(((uint16_t*)pnode->data)[num],buf,size); // break; // case MENU_DATA_TYPE_INT16: // case MENU_DATA_TYPE_RO_INT16: // i+=convert_i32_to_s(((int16_t*)pnode->data)[num],buf,size); // break; // case MENU_DATA_TYPE_UINT32: // case MENU_DATA_TYPE_RO_UINT32: // i+=convert_u32_to_s(((uint32_t*)pnode->data)[num],buf,size); // break; // case MENU_DATA_TYPE_INT32: // case MENU_DATA_TYPE_RO_INT32: // i+=convert_i32_to_s(((int32_t*)pnode->data)[num],buf,size); // break; // case MENU_DATA_TYPE_IPV4: // case MENU_DATA_TYPE_RO_IPV4: // i+=convert_ip2ips(((uint32_t*)pnode->data)[num],buf,size); // break; // default: // return 0; // break; // } // return i; // } // /** // * @brief 将字符串转换为数据 // * // * @param pnode 菜单节点 // * @param num 计数 // * @param buf 字符串 // * @param size 字符串长度 // * @return uint32_t 转换的字符串长度 // */ // static inline uint32_t menu_convert_str_to_data(const struct menu_tree_node *pnode,uint16_t num,char *buf,uint32_t size) // { // uint32_t i=0; // uint32_t tmp_u32; // int32_t tmp_i32; // if(pnode->data_type==MENU_DATA_TYPE_UINT8 || pnode->data_type==MENU_DATA_TYPE_UINT16 || pnode->data_type==MENU_DATA_TYPE_UINT32){ // i+=convert_s_to_u32(&tmp_u32,buf,size); // if(tmp_u32<(uint32_t)pnode->min_value || tmp_u32>(uint32_t)pnode->max_value){ // return 0; // } // } // else if(pnode->data_type==MENU_DATA_TYPE_INT8 || pnode->data_type==MENU_DATA_TYPE_INT16 || pnode->data_type==MENU_DATA_TYPE_INT32){ // i+=convert_s_to_i32(&tmp_i32,buf,size); // if(tmp_i32<(int32_t)pnode->min_value || tmp_i32>(int32_t)pnode->max_value){ // return 0; // } // } // switch(pnode->data_type) // { // case MENU_DATA_TYPE_CHAR: // ((char*)pnode->data)[num]=buf[i++]; // break; // case MENU_DATA_TYPE_UINT8: // ((uint8_t*)pnode->data)[num]=tmp_u32; // break; // case MENU_DATA_TYPE_INT8: // ((int8_t*)pnode->data)[num]=tmp_i32; // break; // case MENU_DATA_TYPE_UINT16: // ((uint16_t*)pnode->data)[num]=tmp_u32; // break; // case MENU_DATA_TYPE_INT16: // ((int16_t*)pnode->data)[num]=tmp_i32; // break; // case MENU_DATA_TYPE_UINT32: // ((uint32_t*)pnode->data)[num]=tmp_u32; // break; // case MENU_DATA_TYPE_INT32: // ((int32_t*)pnode->data)[num]=tmp_i32; // break; // case MENU_DATA_TYPE_IPV4: // i+=convert_ips2ip((&((uint32_t*)pnode->data)[num]),buf,size); // break; // default: // break; // } // return i; // } // /** // * @brief 使用字符串中的数据设置菜单节点中的数据 // * // * @param pnode 菜单节点 // * @param buf 字符串 // * @param size 字符串长度 // * @return uint32_t 转换的字符串长度 // */ // static inline uint32_t menu_set_data(const struct menu_tree_node *pnode,char *buf,uint32_t size) // { // uint32_t i,j; // uint16_t num_con; // num_con=0; // i=0; // if(pnode->data==NULL){ // return 0; // } // do{ // if(buf[i]==' '){ // i++; // } // j=menu_convert_str_to_data(pnode,num_con,&buf[i],size-i); // if(j==0){ // return 0; // } // i+=j; // num_con++; // }while(num_connum); // return i; // } // /** // * @brief 从菜单节点中获取数据 // * // * @param pnode 菜单节点 // * @param buf 字符串缓冲区 // * @param size 缓冲区大小 // * @return uint32_t 使用的缓冲区大小 // */ // static inline uint32_t menu_get_data(const struct menu_tree_node *pnode,char *buf,uint32_t size) // { // uint32_t i,j; // uint16_t num_con; // num_con=0; // if(pnode->data==NULL){ // return 0; // } // if(size<4){ // return 0; // } // i=0; // do{ // j=menu_convert_data_to_str(pnode,num_con,&buf[i],size-i-4); // if(j==0 && (pnode->data_type==MENU_DATA_TYPE_CHAR || pnode->data_type==MENU_DATA_TYPE_RO_CHAR)){ // break; // } // if(j==0 || i+j>=size-5){ // buf[i++]=' '; // buf[i++]='.'; // buf[i++]='.'; // buf[i++]='.'; // break; // } // i+=j; // if(pnode->data_type!=MENU_DATA_TYPE_CHAR && pnode->data_type!=MENU_DATA_TYPE_RO_CHAR){ // buf[i++]=' '; // } // num_con++; // }while(num_connum); // return i; // } // /** // * @brief 从菜单节点中获取信息 // * // * @param pnode 菜单节点 // * @param buf 缓冲区 // * @param width 允许使用的宽度 // * @param size 缓冲区大小 // * @return uint32_t 使用的缓冲区大小 // */ // static inline uint32_t menu_get_info(const struct menu_tree_node *pnode,char *buf,uint32_t width,uint32_t size) // { // uint32_t i,j; // uint32_t p_lc=0; // if(size<4 || width<4){ // return 0; // } // for(i=0,j=0;pnode->info_str[i]!='\0' && pnode->info_str[i]!='\r' && pnode->info_str[i]!='\n';i++){ // if(j>width-5 || i>=size-5){ // if((pnode->info_str[i]&0xc0)==0x80){ // i=p_lc; // j--; // } // buf[i++]=' '; // buf[i++]='.'; // buf[i++]='.'; // buf[i++]='.'; // j+=4; // break; // } // if((pnode->info_str[i]&0x80)==0){ //普通字符 // p_lc=i; // j++; // } // if((pnode->info_str[i]&0xc0)==0xc0){ //多字节字符 // p_lc=i; // j+=MENU_CHINESE_CHARACTER_WIDTH; // } // buf[i]=pnode->info_str[i]; // } // for(;j<=width && iterminal_width*(uint32_t)5)/8; // data_size=menu->terminal_width-info_size; // i=0; // menu->output_buf[i++]='\r'; // menu->output_buf[i++]='\n'; // menu->output_buf[i++]='['; // j=convert_u2s(menu->child_con,&menu->output_buf[i],info_size-i-3); // if(j==0){ // return 0; // } // i+=j; // menu->output_buf[i++]=']'; // menu->output_buf[i++]=' '; // if(menu->child_con==0){ // if(menu->node==1){ // memcpy(&menu->output_buf[i],"退出",6); // i+=6; // } // else{ // memcpy(&menu->output_buf[i],"返回上一级",15); // i+=15; // } // return i; // } // j=menu_get_info(&menu->menu_tree[menu->child_node],&menu->output_buf[i],info_size+2-i,MENU_OUTPUT_BUF_SIZE-i); // if(j==0){ // return 0; // } // i+=j; // j=menu_get_data(&menu->menu_tree[menu->child_node],&menu->output_buf[i],data_size); // i+=j; // return i; // } // /** // * @brief 初始化菜单 // * // * @param menu struct menu 结构 // * @param menu_tree 由程序生成的菜单树 // * @param send_class send函数的第一个参数 // * @param send send函数 // * @return struct menu* 成功:menu 失败:NULL // */ // // struct menu *menu_init(struct menu *menu,const struct menu_tree_node *menu_tree,void *send_class,menu_send_function_type send) // struct menu *menu_init(struct menu *menu,const struct menu_tree_node *menu_tree ) // { // // if(menu==NULL || menu_tree==NULL || send_class==NULL || send==NULL){ // if(menu==NULL || menu_tree==NULL ){ // return NULL; // } // menu->menu_tree=menu_tree; // // menu->send_class=send_class; // // menu->send=send; // menu->check_passwd=NULL; // menu->node=0; // menu->child_node=0; // menu->child_con=0; // menu->input_con=0; // menu->flag_ready=0; // menu->flag_flush=0; // menu->terminal_width=MENU_TERMINAL_WIDTH; // return menu; // } // /** // * @brief 设置终端的宽度 // * // * @param menu struct menu 结构 // * @param terminal_width 终端宽度 // * @return int 成功:0 失败:负值 // */ // int menu_set_terminal_width(struct menu *menu,uint8_t terminal_width) // { // if(menu==NULL){ // return -1; // } // menu->terminal_width=terminal_width; // return 0; // } // /** // * @brief 设置check_passwd钩子 // * // * @param menu struct menu 结构 // * @param check_passwd check_passwd函数指针 // * @return int 成功:0 失败:负值 // */ // int menu_set_hook_passwd(struct menu *menu,menu_check_passwd_function_type check_passwd) // { // if(menu==NULL || check_passwd==NULL){ // return -1; // } // menu->check_passwd=check_passwd; // return 0; // } // /** // * @brief 使用menu结构中的发送函数发送 // * // * @param menu struct menu 结构 // * @param buf 要发送的数据 // * @param size 要发送数据的大小 // * @return int 成功:0 失败:负值 // */ // int menu_send(struct menu *menu,char *buf,uint32_t size) // { // // return menu->send(menu->send_class,buf,size); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, buf, size ); // // printf( "%s", buf, size); // return 0; // return -1; // // return printf( "%s", buf, size); // } // /** // * @brief 获取menu当前的状态 // * @note menu在收到回车或密码后会使能 未使能的菜单不会主动发送信息 // * @param menu struct menu 结构 // * @return int 0:未使能 1:使能 // */ // int menu_get_state(struct menu *menu) // { // return menu->node==0?0:1; // } // /** // * @brief 菜单打印函数 需要放在循环中,在send函数可用时执行 // * // * @param menu struct menu 结构 // */ // void menu_print_callback(struct menu *menu) // { // uint32_t len; // uint32_t i,j; // uint32_t tmp; // if(menu->node==0){ /* 节点0 */ // if(menu->flag_ready!=1){ // menu->flag_flush=0; // return; // } // if(menu->check_passwd==NULL || menu->check_passwd(menu,menu->input_buf,menu->input_con)==1){ // // menu->send(menu->send_class,menu->menu_tree[menu->node].info_str,strlen(menu->menu_tree[menu->node].info_str)); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, (uint8_t *)(menu->menu_tree[menu->node].info_str),strlen(menu->menu_tree[menu->node].info_str) ); // menu->node=1; // menu->flag_flush=1; // menu->flag_ready=2; // } // else{ // menu->flag_ready=2; // return; // } // } // if(menu->flag_flush==1){ /* 输出当前节点info_str 及格式, 有字节的处理子节点,没有输出当前值等待输入*/ // menu->flag_flush=0; // // menu->send(menu->send_class,menu->menu_tree[menu->node].info_str,strlen(menu->menu_tree[menu->node].info_str)); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, menu->menu_tree[menu->node].info_str, strlen(menu->menu_tree[menu->node].info_str) ); // // printf( "%s", menu->menu_tree[menu->node].info_str, strlen(menu->menu_tree[menu->node].info_str)); // if(menu->menu_tree[menu->node].child!=0){ // menu->output_buf[0]='\r'; // menu->output_buf[1]='\n'; // menu->output_buf[menu->terminal_width+2]='\r'; // menu->output_buf[menu->terminal_width+3]='\n'; // memset(&menu->output_buf[2],MENU_FILL_CHARACTER,menu->terminal_width); // // menu->send(menu->send_class,menu->output_buf,menu->terminal_width+4); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, menu->output_buf,menu->terminal_width+4 ); // // printf( "%s", menu->output_buf, menu->terminal_width+4); // menu->child_con=0; // menu->child_node=menu->menu_tree[menu->node].child; // return; // } // // menu->send(menu->send_class,"\r\n当前值:\r\n",14); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, "\r\n当前值:\r\n",14 ); // // printf( "%s", "\r\n当前值:\r\n",14); // i=menu_get_data(&menu->menu_tree[menu->node],menu->output_buf,menu->terminal_width); // if(i==0){ // return; // 错误 // } // menu->output_buf[i++]='\r'; // menu->output_buf[i++]='\n'; // // menu->send(menu->send_class,menu->output_buf,i); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, menu->output_buf, i ); // // printf( "%s", menu->output_buf, i); // if((menu->menu_tree[menu->node].data_type&1)==1){ // menu->node=menu->menu_tree[menu->node].father; // menu->flag_flush=1; // return; // } // // menu->send(menu->send_class,"请输入:\r\n",12); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, "请输入:\r\n",12); // // printf( "%s", "请输入:\r\n",12); // j=i; // switch(menu->menu_tree[menu->node].data_type) // { // case MENU_DATA_TYPE_CHAR: // break; // case MENU_DATA_TYPE_UINT8: // case MENU_DATA_TYPE_UINT16: // case MENU_DATA_TYPE_UINT32: // menu->output_buf[j++]='['; // j+=convert_u2s(menu->menu_tree[menu->node].min_value,&menu->output_buf[j],MENU_OUTPUT_BUF_SIZE-j); // menu->output_buf[j++]=','; // j+=convert_u2s(menu->menu_tree[menu->node].max_value,&menu->output_buf[j],MENU_OUTPUT_BUF_SIZE-j); // menu->output_buf[j++]=']'; // break; // case MENU_DATA_TYPE_INT8: // case MENU_DATA_TYPE_INT16: // case MENU_DATA_TYPE_INT32: // menu->output_buf[j++]='['; // j+=convert_i2s(menu->menu_tree[menu->node].min_value,&menu->output_buf[j],MENU_OUTPUT_BUF_SIZE-j); // menu->output_buf[j++]=','; // j+=convert_i2s(menu->menu_tree[menu->node].max_value,&menu->output_buf[j],MENU_OUTPUT_BUF_SIZE-j); // menu->output_buf[j++]=']'; // break; // case MENU_DATA_TYPE_IPV4: // break; // default: // break; // } // if(menu->menu_tree[menu->node].num!=0){ // menu->output_buf[j++]=' '; // menu->output_buf[j++]='X'; // j+=convert_u2s(menu->menu_tree[menu->node].num,&menu->output_buf[j],MENU_OUTPUT_BUF_SIZE-j); // } // menu->output_buf[j++]='>'; // // menu->send(menu->send_class,&menu->output_buf[i],j-i); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, &menu->output_buf[i],j-i); // // printf( "%s", &menu->output_buf[i],j-i); // return; // } // if(menu->child_node!=0){ /*处理子节点- 处理一次return 一次直到为0 */ // len=0; // len+=menu_build_item(menu); // if(len==0){ // return; // 出现错误 // } // // menu->send(menu->send_class,menu->output_buf,len); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, menu->output_buf,len); // // printf( "%s", menu->output_buf,len); // menu->child_con++; // if(menu->child_con!=1){ // menu->child_node=menu->menu_tree[menu->child_node].next; // } // return; // } // if(menu->child_con!=0){ /* 一次处理 输出 填充字符*/ // menu->child_con=0; // menu->output_buf[0]='\r'; // menu->output_buf[1]='\n'; // menu->output_buf[menu->terminal_width+2]='\n'; // memset(&menu->output_buf[2],MENU_FILL_CHARACTER,menu->terminal_width); // // menu->send(menu->send_class,menu->output_buf,menu->terminal_width+2); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, menu->output_buf,menu->terminal_width+2); // // printf( "%s",menu->output_buf,menu->terminal_width+2); // // menu->send(menu->send_class,"\r\n>",3); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, "\r\n>", 3); // // printf( "%s", "\r\n>",3); // } // /* 处理完以上标记,进入数据输入 */ // if(menu->flag_ready!=1){ // return; // } // menu->flag_ready=2; // // menu->send(menu->send_class,"\r\n",2); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, "\r\n>",3); // // printf( "%s", "\r\n>",2); // if(menu->menu_tree[menu->node].child!=0){ // len=convert_s_to_u32(&tmp,menu->input_buf,menu->input_con); // if(len==0){ // menu->flag_flush=1; // return; // } // if(tmp==0){ // menu->node=menu->menu_tree[menu->node].father; // menu->flag_flush=1; // return; // } // menu->child_node=menu->menu_tree[menu->node].child; // for(menu->child_con=1;menu->child_conchild_con++){ // menu->child_node=menu->menu_tree[menu->child_node].next; // if(menu->child_node==0){ // // menu->send(menu->send_class,"\r\n错误:没有这个选项!\r\n",30); // if ( osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever) ) // HAL_UART_Transmit_DMA(&huart1, "\r\n错误:没有这个选项!\r\n",30); // // printf( "%s", "\r\n错误:没有这个选项!\r\n",30); // menu->child_node=menu->node; // break; // } // } // menu->node=menu->child_node; // menu->child_node=0; // menu->child_con=0; // menu->flag_flush=1; // } // else{ // j=menu_set_data(&menu->menu_tree[menu->node],menu->input_buf,menu->input_con); // if(j==0){ // // menu->send(menu->send_class,"\r\n不匹配的值!\r\n",20); // if ( osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever) ) // HAL_UART_Transmit_DMA( &huart1, "\r\n不匹配的值!\r\n", 20 ); // // printf( "%s", "\r\n不匹配的值!\r\n",20); // menu->flag_flush=1; // } // else{ // menu->node=menu->menu_tree[menu->node].father; // menu->flag_flush=1; // } // } // } // /** // * @brief 菜单用户输入回调 // * // * @param menu struct menu 结构 // * @param buf 用户输入的数据 // * @param size 用户输入数据长度 // */ // void menu_parse_callback(struct menu *menu,char *buf,uint32_t size) // { // int i; // if(menu->flag_ready==2){ // menu->flag_ready=0; // menu->input_con=0; // } // if(menu->flag_ready!=0){ // return; // } // #if MENU_ECHO==1 // if(menu_get_state(menu)==1){ // // menu->send(menu->send_class,buf,size); // if (osOK == osSemaphoreAcquire(elog_dma_lockHandle, osWaitForever)) // HAL_UART_Transmit_DMA(&huart1, buf, size); // // printf( "%s", buf, size); // } // #endif // for(i=0;iinput_con==MENU_INPUT_BUF_SIZE-1 || buf[i]=='\n' || buf[i]=='\r'){ // menu->input_buf[menu->input_con]='\0'; // menu->flag_ready=1; // return; // } // menu->input_buf[menu->input_con++]=buf[i]; // } // }