ESP32 命令行解析框架

  • Post author:
  • Post category:其他


命令行解析框架,使用链表将所有注册的信息串联起来,然后每个节点node包含了,keyword,help,数据类型描述,命令执行的回调函数,和参数存储的回调函数。主要的应用点是,

已知函数变量地址,类型,和地址宽度,然后强制转换后对变量读写操作

经过网友的提醒,在关键字匹配的时候采用for循环匹配对整个框架来讲不是最优的,所以嵌入了博主

http://www.cnblogs.com/skywang12345/p/3624177.html

的红黑树的C代码,于是有了新的版本。


源码地址:


https://download.csdn.net/download/seeker_zeroone/10743399

使用红黑树索引关键字的源代码:

https://download.csdn.net/download/seeker_zeroone/10776229

命令节点结构体如下;

typedef		struct  fun_node
{
	struct  fun_node *pNext;
	const		char	*pHelp;
	const		char	*pName;
	uint8_t	 	paraNum;
	FUN_CMD_BK  RunFun;
	uint8_t	 	EnableState;
}ST_FUN_NODE;

typedef		enum
{
	emCmdDataType_Dec		=1,
	emCmdDataType_Hex		=2,
	emCmdDataType_Str		=3,
	emCmdDataType_IP		=4,
	emCmdDataType_MAC		=5,
	
}EM_CMD_DATA_TYPE;


typedef		struct   cmd_para
{
	struct   cmd_para  *pNext;	
	const	char  *pName;
	void	 	*pDataAddr;	
	uint16_t	dataLen;
	EM_CMD_DATA_TYPE  dataType;
	uint8_t	 EnableState;
}ST_CMD_PARA;


typedef		struct	cmd_node
{
	const	char 	*pKeyword;
	const	char   *pHelp;
	ST_CMD_PARA  *pData;
	ST_FUN_NODE	 *pFuntion;
	FUN_STOR_BK   StorageFun;
}ST_CMD_NODE;

参数注册配置实例:

void	 cla_parametersConfig(void)
{
		cla_init();
		cla_regsister("uuid","uuid <only read>");
		cla_addParameter("uuid","uuid ",(void *)&uuid,emCmdDataType_Str,		sizeof(uuid));

		cla_regsister("wifi","wifi or wifi ssid=xxx password=xxx");
		cla_addParameter("wifi","ssid",(void *)ssid,emCmdDataType_Str,			sizeof(ssid));
		cla_addParameter("wifi","password",(void *)password,emCmdDataType_Str,	sizeof(password));

		cla_regsister("hex","hex or hex hex8=xx hex16=xx hex32=xx");
		cla_addParameter("hex","hex8",(void *)&hex8,emCmdDataType_Hex,			sizeof(data8));
		cla_addParameter("hex","hex16",(void *)&hex16,emCmdDataType_Hex,		sizeof(data16));
		cla_addParameter("hex","hex32",(void *)&hex32,emCmdDataType_Hex,		sizeof(data32));
		
		cla_regsister("data","data or data data8=xx data16=xx data32=xx");
		cla_addParameter("data","data8",(void *)&data8,emCmdDataType_Dec,		sizeof(data8));
		cla_addParameter("data","data16",(void *)&data16,emCmdDataType_Dec,		sizeof(data16));
		cla_addParameter("data","data32",(void *)&data32,emCmdDataType_Dec,		sizeof(data32));

		cla_regsister("ipconfig","ipconfig or ipconfig ipaddr=192.168.1.1");
		cla_addParameter("ipconfig","ipaddr",(void *)IPaddr,emCmdDataType_IP,	sizeof(IPaddr));
		cla_addParameter("ipconfig","mask",(void *)maskIP,emCmdDataType_IP,		sizeof(maskIP));
		cla_addParameter("ipconfig","dns",(void *)dnsIP,emCmdDataType_IP,		sizeof(dnsIP));
		cla_addParameter("ipconfig","mac",(void *)Mac,emCmdDataType_MAC,		sizeof(Mac));

		cla_regsister("run","<funtions>");
		cla_addRunFun("run",ptest_3fun_help,"test",test_3fun,3);
		cla_addRunFun("run",ptest_2fun_help,"test2",test_2fun,2);
}

参数注册,需要先申请一个Node

BOOLEAN cla_regsister(const char *pKeyword,const char *pHelp)
{
		ST_CMD_NODE  *pNode=NULL;		
		pNode =cla_getFreeNode();
		if(pNode !=NULL)
		{
			pNode->pKeyword	=pKeyword;
			pNode->pHelp		=pHelp;
			pNode->pData		=NULL;
			pNode->pFuntion	=NULL;
			pNode->StorageFun	=NULL;
			return TRUE;
		}
		Debug("%s regsiter failed\n",pKeyword);
		return FALSE;
}

为Node添加参数描述信息,Node的关键字,参数名称,参数地址,参数类型,参数宽度

BOOLEAN		cla_addParameter(const char *pKey,const char *pName,void *pDataAddr,EM_CMD_DATA_TYPE dataType,uint16_t dataLen)
{
		ST_CMD_NODE  *pNode=NULL;
		ST_CMD_PARA  *pData=NULL;
		pNode =cla_getNodeOfKey(pKey);
		if(pNode!=NULL)
		{
				pData =cla_getFreePara();
				if(pData !=NULL)
				{
						pData->pName 		=pName;
						pData->pDataAddr	=pDataAddr;
						pData->dataType		=dataType;
						pData->dataLen		=dataLen;
						pData->pNext		=NULL;
						
						cla_setParamete(pNode,pData);
						return TRUE;
				}
		}
		Debug("%s no support\n",pKey);
		return FALSE;
}

为node节点添加命令函数描述信息,node的关键字,帮助信息,函数名称,函数回调地址,函数入口参数个数

BOOLEAN		cla_addRunFun(const char *pKey,const char *pHelp,const char *pFunName,FUN_CMD_BK funcb,uint8_t paraNum)
{
		ST_CMD_NODE  *pNode=NULL;
		ST_FUN_NODE  *pFun=NULL;
		pNode =cla_getNodeOfKey(pKey);
		if(pNode!=NULL)
		{
				pFun =cla_getFreeFunNode();
				if(pFun !=NULL)
				{
						pFun->pName		=pFunName;
						pFun->paraNum =paraNum;
						pFun->RunFun	=funcb;
						pFun->pHelp		=pHelp;
						pFun->pNext		=NULL;
						
						cla_setFuntion(pNode,pFun);
						return TRUE;
				}
		}
		Debug("%s no support\n",pKey);
		return FALSE;
}

根据命令参数,打印相关的变量


static	uint16_t  cla_sprintfPara(ST_CMD_PARA *pData,char *pbuff,uint16_t buffLen)
{
		uint32_t  value=0,tmpLen,totalLen=0,i;
		uint32_t	ipaddr[4],macAddr[6];
		while((pData !=NULL)&&(buffLen > 0))
		{
				switch(pData->dataType)
				{
						case emCmdDataType_Dec:
						{
									value =cla_getValueOfAddrType(pData->pDataAddr,pData->dataLen);
									snprintf(pbuff,buffLen,"%s=%d ",pData->pName,value);
						}break;
						
						case emCmdDataType_Hex:
						{
								value =cla_getValueOfAddrType(pData->pDataAddr,pData->dataLen);
								snprintf(pbuff,buffLen,"%s=0x%x  ",pData->pName,value);
						}break;
						
						case emCmdDataType_Str:
						{
								snprintf(pbuff,buffLen,"%s=%s  ",pData->pName,(const char *)pData->pDataAddr);	
						}break;
						
						case emCmdDataType_IP:
						{
								if(pData->dataLen >= 4)
								{
									for(i=0;i<4;i++)
									{
										ipaddr[i] =cla_getValueOfAddrType((void *)((uint8_t *)(pData->pDataAddr) + i), sizeof(uint8_t));
									}
									
									snprintf(pbuff,buffLen,"%s=%d.%d.%d.%d ",pData->pName,
																				ipaddr[0],ipaddr[1],ipaddr[2],ipaddr[3]);
								}

						}break;
								
						case emCmdDataType_MAC:
						{
								if(pData->dataLen >= 6)
								{
									for(i=0;i<6;i++)
									{
											macAddr[i] =cla_getValueOfAddrType((void *)((uint8_t *)(pData->pDataAddr) + i), sizeof(uint8_t));
									}									
									snprintf(pbuff,buffLen,"%s=%02X-%02X-%02X-%02X-%02X-%02X ",pData->pName,
																					macAddr[0],macAddr[1],macAddr[2],macAddr[3],macAddr[4],macAddr[5]);
								}								
						}break;
								
						default:
						break;
				}
				pData		=pData->pNext;
				tmpLen	=strlen((const char *)pbuff);
				pbuff		+=tmpLen;	
				totalLen +=tmpLen;
				buffLen	-=tmpLen;
		}
		strcpy(pbuff,"\r\n");
		return  (totalLen + 3);
}

查找命令,为变量赋值


static	BOOLEAN  cla_scanfPara(ST_CMD_PARA *pData,ST_CMD_STR *pParaIn)
{
		BOOLEAN	 res;
		uint16_t  i,k;
		uint32_t	value;
		static	uint8_t	nmeBuff[32],dataBuff[32],Offset=0,pos=0;
		ST_CMD_PARA *pStorData;
		for(i=pParaIn->argPos;i<pParaIn->argCount;i++)
		{
				memset(nmeBuff,0,sizeof(nmeBuff));
				memset(dataBuff,0,sizeof(dataBuff));
				res =cla_takeNameData(pParaIn->pArgValue[i],nmeBuff,dataBuff);
				if(res)
				{
						Debug("name->%s data->%s\n",nmeBuff,dataBuff);
						pStorData =cla_getParaOfName(pData,(const char *)nmeBuff);
						if(pStorData)
						{
									switch(pStorData->dataType)
									{
										case emCmdDataType_Dec:
										{
													value =cla_atoi(dataBuff,&Offset);
													cla_setValueOfAddrType(pStorData->pDataAddr,pStorData->dataLen,value);
													
										}break;
										
										case emCmdDataType_Hex:
										{
													value =cla_atohex(dataBuff,&Offset);
													//Debug("hex-->0x%02x",value);
													cla_setValueOfAddrType(pStorData->pDataAddr,pStorData->dataLen,value);
										}break;
										
										case emCmdDataType_Str:
										{
												strncpy((char *)pStorData->pDataAddr,(const char *)dataBuff,pStorData->dataLen);
										}break;
										
										case emCmdDataType_IP:
										{
												if(pStorData->dataLen >=4)
												{
														for(pos=0,Offset=0,k=0;k<4;k++)
														{
															pos +=Offset;
															value =cla_atoi(dataBuff + pos,&Offset);
															cla_setValueOfAddrType(((uint8_t *)(pStorData->pDataAddr) + k),1,value);
														}
												}

										}break;
												
										case emCmdDataType_MAC:
										{												
												if(pStorData->dataLen >=6)
												{
														for(pos=0,Offset=0,k=0;k<6;k++)
														{
															pos +=Offset;
															value =cla_atohex(dataBuff + pos,&Offset);
															//Debug("mac%d-->%02x",k,value);
															cla_setValueOfAddrType(((uint8_t *)(pStorData->pDataAddr) + k),1,value);
														}
												}
										}break;
										default:
										break;
								}
						}
						else
						{
								Debug("no support %s\n",nmeBuff);
						}
				}
				else
				{
						Debug("parameter err\n");
				}
		}
		return TRUE;
}

void	cla_precess(uint8_t *pCmd,uint16_t cmdLen,FUN_PRINT_OUT printFun)
{
	uint16_t	 i,outlen;
	FUN_STOR_BK		storageFun=NULL;
	BOOLEAN	 res;
	static	ST_CMD_STR		cmdStr;
	static	char	outBuff[OUT_BUFF_MAX_LEN];
	if((pCmd !=NULL)&&(cmdLen > 2))
	{
			cla_cmdMake(&cmdStr,pCmd,cmdLen);	
			if((cla_CheckIn(&cmdStr,printFun))&&(cmdStr.argCount >= 1))
			{
				for(i=0;i<CMD_NODE_TOTAL;i++)
				{
					 if(CmdNodeGroup[i].pKeyword != NULL)
					 {						
					 	  if(strcmp((const char *)CmdNodeGroup[i].pKeyword,cmdStr.pArgValue[0]) == 0)
							{
									if(cmdStr.argCount  == 1)//查询参数
									{
											outlen =cla_sprintfPara(CmdNodeGroup[i].pData,outBuff,OUT_BUFF_MAX_LEN);
											if(printFun !=NULL)
											{
												 printFun(outBuff,outlen);
											}
											Debug("out done\n");
									}
									else if(strcmp("run",cmdStr.pArgValue[0]) == 0)
									{
											cmdStr.argPos		=1;
											res	=cla_runFuntion(CmdNodeGroup[i].pFuntion,&cmdStr);
											Debug("run done\n");											
									}
									else 
									{
											cmdStr.argPos		=1;
											res	 =cla_scanfPara(CmdNodeGroup[i].pData,&cmdStr);
											if(res)
											{
													Debug("cfg done\n");
													storageFun =CmdNodeGroup[i].StorageFun;
													if(storageFun !=NULL)
													{
															storageFun();
													} 
											}											
									}
									return ;
							}
							else if(strcmp("help",cmdStr.pArgValue[0]) == 0)
							{
									cla_help(printFun,outBuff,OUT_BUFF_MAX_LEN);
									return ;
							}
					 }
				}
			}
	}	
}


命令行解析进程

1,cmdMake对输入的命令行,进行格式化匹配,并得到输入命令行参数个数

2,命令行账户校验

3,匹配关键字

4,命令行参数个数为1,表示查询

5,令行参数为多个,表示参数配置

6,run xxFun param1 param2 ..  表示运行xx函数,然后传递参数为param1..



版权声明:本文为Seeker_ZeroOne原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。