wow-shell文件说明
- 项目地址:https://gitee.com/wow-iot/wow-iot7
- 本文件的的功能主要用于shell相关操作,实现串口控制台与网口控制台对程序运行操作进行相关控制,如代码运行中开启调试信息;
shell实现过程
1) 程序代码中添加预处理指令,包含指令名称与操作函数;
2) 设备程序启动后,我们通过调试串口/网口与设备相连接;
3) 控制台输入回车后,程序响应可以使用的shell指令;
4) 控制台输入需要执行的指令;
5) 程序接收控制台指令,匹配输入指令与代码预处理的指令,随后
进行相应接口的操作
shell指令声明
typedef int (*ShellDeal_F)(int argc, char *argv[]);
typedef struct{
const char *cmd;
ShellDeal_F pfunc;
const char *info;
const char *priv;
}__data_aligned__ ShellDesc_T;
#define WOW_DECLARE_SHELL_CMD(cmdname, func, helpinfo) \
static ShellDesc_T _shellcmd_##func \
__attribute__((used,section("_shell_ex_cmd")))={ \
.cmd = cmdname,.pfunc = func,.info = helpinfo\
};
help接口声明
static int shell_help(int argc, char *argv[])
{
int i = 0;
char buf[512] = {0};
ShellDesc_T* tmp = NULL;
CHECK_RET_VAL(gpt_sheelList, -1);
for(i=0; i < wow_slist_size(gpt_sheelList); i++)
{
tmp = wow_slist_peek_by_index(gpt_sheelList,i);
CHECK_RET_CONTINUE(tmp);
int size = snprintf(buf,511,"%s: \t%s\n",tmp->cmd, tmp->info);
#if WOW_SHELL_TTY_SUPPORT
wow_shell_tty_write(buf,size);
#endif
#if WOW_SHELL_ETH_SUPPORT
wow_shell_eth_write(buf,size);
#endif
}
return 0;
}
WOW_DECLARE_SHELL_IN("help",shell_help,"help");
串口控制台实现:
void wow_shell_tty_write(const char *pcStr,size_t len)
{
printf("%s",pcStr);
}
/*brief 串口后台获取输入方式 */
static void* shell_tty_thread(void *arg)
{
int argc = 0;
int size = 0;
char** argv = NULL;
ShellDeal_F fun;
char command[SHELL_BUFFER_SIZE];
char wBuf[SHELL_BUFFER_SIZE];
while(gt_ttyThread.run){
printf("##:");
/*获取一行内容 阻塞操作 */
/*标准输入需要有回车键或者CTRL+D退出*/
fgets(command, SHELL_BUFFER_SIZE-1, stdin);
CHECK_RET_CONTINUE(strlen(command) > 1);
//删除最后一字节换行符
command[strlen(command)-1]='\0';
//将命令与参数分离
argv = wow_str_split(command," ",&argc);
CHECK_RET_CONTINUE(argc > 0 && argv);
//查询是否存在此shell命令
fun = shell_find_func(argv[0]);
if(NULL != fun) {
//存在 调用此命令函数
if(-1 == (*fun)(argc, argv)){
size = snprintf(wBuf,SHELL_BUFFER_SIZE-1,"exec %s command errer!\r\n##:",argv[0]);
}
else{
size = snprintf(wBuf,SHELL_BUFFER_SIZE-1,"exec %s command succeeful!\r\n##:",argv[0]);
}
}
else{
size = snprintf(wBuf,SHELL_BUFFER_SIZE-1,"can not find %s command\r\n##:",argv[0]);
}
wow_shell_tty_write(wBuf,size);
wow_str_split_free(argv);
}
return NULL;
}
static int shell_tty_init(void)
{
memset(>_ttyThread,0,sizeof(TtyThread_T));
gt_ttyThread.run = 1;
gt_ttyThread.tid = wow_thread_create("shell_tty",shell_tty_thread, NULL);
CHECK_RET_VAL_P(gt_ttyThread.tid > 0, -1, "wow_thread_create failed!\n");
return 0;
}
static void shell_tty_exit(void)
{
gt_ttyThread.run = 0;
wow_thread_cancel(gt_ttyThread.tid);
usleep(100*1000);
}
网口控制台实现
void wow_shell_eth_write(const char *pcStr,size_t snLen)
{
CHECK_RET_VOID(gt_ethThread.sktfd > 0 && gt_ethThread.cliPort > 0);
wow_socket_usend(gt_ethThread.sktfd,gt_ethThread.cliAddr,gt_ethThread.cliPort,(const uint8_t*)pcStr,snLen);
}
static void* shell_eth_thread(void *arg)
{
int serverfd = *(int*)arg;
int argc = 0;
int size = 0;
char** argv = NULL;
ShellDeal_F pfunc;
char wBuf[SHELL_BUFFER_SIZE];
char rBuf[SHELL_BUFFER_SIZE];
while(gt_ethThread.run)
{
usleep(100000);
size = wow_socket_urecv(serverfd,gt_ethThread.cliAddr,>_ethThread.cliPort,
(uint8_t*)rBuf,SHELL_BUFFER_SIZE);
CHECK_RET_CONTINUE(size > 0);
//dprintf("recv data(%d):%s\n",size,rBuf);
//将命令与参数分离
argv = wow_str_split(rBuf," ",&argc);
CHECK_RET_CONTINUE(argc > 0);
//查询是否存在此shell命令
pfunc = shell_find_func(argv[0]);
if(NULL != pfunc) {
//存在 调用此命令函数
if(-1 == (*pfunc)(argc, argv)){
size = snprintf(wBuf,SHELL_BUFFER_SIZE-1,"exe %s command errer!\r\n##:",argv[0]);
}
else{
size = snprintf(wBuf,SHELL_BUFFER_SIZE-1,"exe %s command succeeful!\r\n##:",argv[0]);
}
}
else{
size = snprintf(wBuf,SHELL_BUFFER_SIZE-1,"can not find %s command\r\n##:",argv[0]);
}
wow_shell_eth_write(wBuf,size);
wow_str_split_free(argv);
memset(wBuf,0,SHELL_BUFFER_SIZE);
memset(rBuf,0,SHELL_BUFFER_SIZE);
}
wow_socket_close(gt_ethThread.sktfd);
return NULL;
}
static int shell_eth_init(void)
{
memset(>_ethThread,0,sizeof(TtyThread_T));
gt_ethThread.sktfd = wow_socket_open(SOCKET_TYPE_UDP);
CHECK_RET_VAL_P(gt_ethThread.sktfd > 0,-1,"wow_socket_open failed!\n");
int ret = wow_socket_bind(gt_ethThread.sktfd,NULL,ETH_SHELL_PORT);
CHECK_RET_GOTO_P(ret == 0,out, "wow_socket_bind failed!\n");
/*创建线程 实现服务器接收多客户端*/
gt_ethThread.run = 1;
gt_ethThread.tid = wow_thread_create("shell_eth",shell_eth_thread, (void *)>_ethThread.sktfd);
CHECK_RET_GOTO_P(gt_ttyThread.tid > 0, out, "wow_thread_create failed!\n");
return 0;
out:
wow_socket_close(gt_ethThread.sktfd);
return -1;
}
static void shell_eth_exit(void)
{
gt_ethThread.run = 0;
wow_thread_cancel(gt_ethThread.tid);
usleep(100*1000);
}