不含stm32 底层的代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MyStm32Code/libraries/menu.c

1167 lines
37 KiB

2 years ago
/**
* @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 <string.h>
#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_con<pnode->num);
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_con<pnode->num);
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 && i<size;j++,i++){
buf[i]=' ';
}
return i;
}
/**
* @brief
*
* @param menu struct menu
* @return uint32_t 使
*/
static inline uint32_t menu_build_item(struct menu *menu)
{
uint32_t i,j;
uint32_t info_size;
uint32_t data_size;
info_size=(menu->terminal_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_con<tmp;menu->child_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;i<size;i++){
if(menu->input_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 <stdio.h>
// #include <string.h>
// #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_con<pnode->num);
// 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_con<pnode->num);
// 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 && i<size;j++,i++){
// buf[i]=' ';
// }
// return i;
// }
// /**
// * @brief 构建菜单条目
// *
// * @param menu struct menu 结构
// * @return uint32_t 使用的缓冲区大小
// */
// static inline uint32_t menu_build_item(struct menu *menu)
// {
// uint32_t i,j;
// uint32_t info_size;
// uint32_t data_size;
// info_size=(menu->terminal_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_con<tmp;menu->child_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;i<size;i++){
// if(menu->input_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];
// }
// }