#include "CatOneTask.h"
#include "Public.h"
#include "DebugCmd.h"

static rt_sem_t CatOneRev_Sem = RT_NULL;
static rt_sem_t CatOneIRQ_Sem = RT_NULL;
static rt_sem_t EthIRQ_Sem = RT_NULL;
static rt_thread_t Cat1Rev_Thread = RT_NULL;

static uint8_t CAT1DispEn = false;
static CatOne_t CatOne;

static char CatOneEthRxBuff[CAT_ONE_REV_LEN_MAX];
static uint16_t CatOneEthRxLen;

static uint8_t CatOneEthTxBuff[CAT_ONE_REV_LEN_MAX];
static uint16_t CatOneEthTxLen;

static uint8_t Payload[CAT_ONE_REV_LEN_MAX];
static char CommUnitSendASCII[CAT_ONE_REV_LEN_MAX * 2];
	
static uint8_t EthRevTimeOutCnt;

static uint16_t CatSendErrCnt = 0;

// ETH状态机相关变量已移至 CatOne_t 结构体中

#define	CAT1_DBG_LOG(...)									{ if(CAT1DispEn) Debug_Printf(__VA_ARGS__);}
//#define	CAT1_DBG_ARRAY(ARRAY, SIZE)			{ if(CAT1DispEn) {DBG_ARRAY(ARRAY,SIZE)}}

#define	CATONE_RESET_DELAY_TIME_MAX				(5 * 60 * 1000)

//const char *CatOneATCmdStr[16] = {
//	"NULL",
//	"AT\r\n",						//开机检测
//	"ATE0\r\n",					//关回显
//	"AT+CPIN?\r\n",			//识卡
////	"AT+CIMI\r\n",			//IMEI
//	"AT+CGSN=1\r\n",
//	"AT+LCCID\r\n",			//读卡号			
//	"AT+CEREG?\r\n",		//查询注册状态
//	"AT+CGPADDR=1\r\n",	//查询IP地址
//	"AT+CSQ\r\n",				//查询信号强度
//	"AT+LDNSGIP=gxjt.cui635.cn\r\n",
//	"AT+LBS=0\r\n",			//获取基站定位信息
//	"AT+LIPOPEN=",			//设置TCP服务器地址和端口，AT+LIPOPEN="TCP","114.55.52.96",6803
//	"AT+LIPSEND=",			//发送数据,	AT+LIPSEND=0,1,20,"31313131313131323232323232"
//	"AT+LIPCLOSE=0\r\n",//断开连接
//	"AT+LBSPARA=http://locator-aep.xiot.senthink.com:80/locator/v0.1/locate,B84E427D95B1DF4A3F49B18DDF714C72\r\n",
//	"AT+CCLK?\r\n",	//获取时间
//};

const char *CatOneATCmdStr[16] = {
	"NULL",
	"AT\r\n",						//开机检测
	"ATE0\r\n",					//关回显
	"AT+CPIN?\r\n",			//识卡
//	"AT+CIMI\r\n",			//IMEI
	"AT+CGSN=1\r\n",
	"AT+QCCID\r\n",			//读卡号			
	"AT+CEREG?\r\n",		//查询注册状态
	"AT+CGPADDR=1\r\n",	//查询IP地址
	"AT+CSQ\r\n",				//查询信号强度
	"AT+LDNSGIP=gxjt.cui635.cn\r\n",
	"AT+QLBS\r\n",			//获取基站定位信息
	"AT+QIOPEN=",			    //设置TCP服务器地址和端口，AT+LIPOPEN="TCP","114.55.52.96",6803
	"AT+QISEND=",			//发送数据,	AT+LIPSEND=0,1,20,"31313131313131323232323232"
	"AT+QICLOSE=0\r\n",//断开连接
	"AT+QLBSCFG=\"server\",http://locator-aep.xiot.senthink.com:80/locator/v0.1/locate\r\n",
  "AT+QLBSCFG=\"token\",45B516D3078467E84DD2CFBF3532A4CB\r\n",
  "AT+CCLK?\r\n",    //获取时间    
};

void Cat1DBGOnOff(bool OnOff)
{
	CAT1DispEn = OnOff;
	if(OnOff)
		Debug_Printf("\r\nCat1 Display Enable!\r\n\r\n");
	else
		Debug_Printf("\r\nCat1 Display Disable!\r\n\r\n");
}

const CatOneATCMD_m CatOneModeSetCmdArray[] = {
	CAT_ONE_AT_NULL, 
	CAT_ONE_AT, 
	CAT_ONE_ATE0, 
	//CAT_ONE_LBSPARA,
	CAT_ONE_LCCID,
	CAT_ONE_IMEI,
	CAT_ONE_CPIN, 
	CAT_ONE_CEREG, 
	CAT_ONE_CSQ,
	//CAT_ONE_LDNSGIP,
	//CAT_ONE_LBS,
	CAT_ONE_CCLK,
	CAT_ONE_AT_CMD_END
};

//CatOneRetStatus_m CatOneSend(uint8_t *sData, uint16_t sLen)
//{
//	rt_err_t result;
//	
//	if(CatOne.Cat1Status != CAT_ONE_IDEL && CatOne.Cat1Status != CAT_ONE_WAIT_SEND)
//		return CAT_ONE_RET_ERR;
//	
//	//CatOne.Cat1Status = CAT_ONE_RESET;
//	result = rt_mq_send(CatOneRev_MQ, sData, sLen);
//  if(result != RT_EOK) {
//		CAT1_DBG_LOG("CatOne MQ Send ERR...\r\n");
//		return CAT_ONE_RET_ERR;
//	}
//	CAT1_DBG_LOG("CatOne Send Message: \r\n", sData);
//	return CAT_ONE_RET_OK;
//}

void CatOneStop(void)
{
	CatOne.Cat1Status = CAT_ONE_OFF;
}

void ETHStop(void)
{
	CatOne.EthStatus = ETH_OFF;
}

void ETHReset(void)
{
	CatOne.EthStatus = ETH_RESET;
}

void CatOneGetLocationInfo(int *Longitude, int *Latitude)
{
	if(CatOne.LBSFlag) {
		*Longitude = CatOne.Longitude;
		*Latitude = CatOne.Latitude;
	}
	else {
		*Longitude = 0;
		*Latitude = 0;
	}
}

void CatOneGetIMEIAndSIM(char *Imei, char *Sim)
{
	memcpy(Imei, CatOne.IMEI, 15);
	memcpy(Sim, CatOne.SIM, 20);
}

//返回true-busy, false-Idle
bool CatOneGetStatus(void)
{
	if(CatOne.Cat1Status == CAT_ONE_IDEL)
		return false;
	return true;
}

void CatOneReset(void)
{
	CatOne.Cat1Status = CAT_ONE_RESET;
}

void CatTimeSync(char *Data) 
{
	struct tm sTimet;
	time_t sTime;
  char *p;
	
	p = strchr(Data, '\"');
	if(p == NULL)
		return;
	
	int ret = sscanf(p, "\"%d/%d/%d,%d:%d:%d+", 
										&sTimet.tm_year, &sTimet.tm_mon, &sTimet.tm_mday,
										&sTimet.tm_hour, &sTimet.tm_min, & sTimet.tm_sec);
	if(ret != 6) {
		int ret = sscanf(p, "\"%d/%d/%d,%d:%d:%d-", 
										&sTimet.tm_year, &sTimet.tm_mon, &sTimet.tm_mday,
										&sTimet.tm_hour, &sTimet.tm_min, & sTimet.tm_sec);
		if(ret != 6)
			return;
	}
	
	sTimet.tm_isdst = 0;
	if(sTimet.tm_year < 24 || sTimet.tm_year > 50)
		return;
	sTimet.tm_year += 100;
	
	if(sTimet.tm_mon > 12 || sTimet.tm_mon == 0)
		return;
	sTimet.tm_mon--;
	
	sTime = mktime(&sTimet);
	TimeSync(sTime);
	CAT1_DBG_LOG("Set Time:");
	TimeShow(TimeTs());
}

void CatOneAtCmdAnalyze(char *RxBuff)
{
	char *p;
	int ret;
	
	CatOne.ATCmdRet = CAT_ONE_RET_OK;
	CAT1_DBG_LOG(RxBuff);
	
	switch(CatOne.AtCmd) {
		case CAT_ONE_AT:
		case CAT_ONE_ATE0:
		case CAT_ONE_LIPSEND:
		case CAT_ONE_LDNSGIP:
		case CAT_ONE_LBSPARA:
			if(strstr(RxBuff, "OK") == NULL) {
				CatOne.ATCmdRet = CAT_ONE_RET_ERR;
			}
			break;
			
		case CAT_ONE_IMEI:
			if(strstr(RxBuff, "OK") == NULL) {
				CatOne.ATCmdRet = CAT_ONE_RET_ERR;
			}
			p = strstr(RxBuff, "+CGSN");
			if(p == NULL) {
				CatOne.ATCmdRet = CAT_ONE_RET_ERR;
			}
			p = strchr(p, '"');
			if(p != NULL) {
				memcpy(CatOne.IMEI, p+1, 15);
			}
			else {
				memset(CatOne.IMEI, 0, 15);
			}
//			ret = sscanf(p, "+CGSN: \"%s\"\r\n", CatOne.IMEI);
//			if(ret != 1) {
//				memset(CatOne.IMEI, 0, 15);
//			}
			CatOne.IMEI[15] = 0;
			break;
		
			case CAT_ONE_CCLK:
			if(strstr(RxBuff, "+CCLK") != NULL) {
				CatTimeSync(RxBuff);
			}
			break;
			
		case CAT_ONE_LCCID:
			if(strstr(RxBuff, "OK") == NULL) {
				CatOne.ATCmdRet = CAT_ONE_RET_ERR;
			}
			p = strstr(RxBuff, "+QCCID");
			if(p == NULL) {
				CatOne.ATCmdRet = CAT_ONE_RET_ERR;
			}
			memset(CatOne.SIM, 0, 32);
			ret = sscanf(p, "+QCCID: %s\r\n", CatOne.SIM);
			if(ret != 1) {
				memset(CatOne.SIM, 0, 32);
			}
			break;
			
		case CAT_ONE_LBS:
			p = strstr(RxBuff, "+QLBS");
			if(p != NULL) {
				double Longitude, Latitude;
				int ret = sscanf(p, "+QLBS: %lf,%lf\r\n", &Longitude, &Latitude);
				if(ret == 2) {
					CatOne.LBSFlag = true;
					CatOne.Longitude = Longitude * 100000;
					CatOne.Latitude = Latitude * 100000;
				}
			}
			break;

		case CAT_ONE_LIPOPEN:
			if(strstr(RxBuff, "OK") != NULL) {
				CatOne.Cat1Status = CatOne.NextStatus;
				CatOne.CatOne1mSDelayCnt = 10 * 1000;
				return;
			}
			else {
				if(strstr(RxBuff, "LIPOPEN: 0,1") != NULL) {
					CAT1_DBG_LOG("Cat1 successfully to connect to the server.\r\n\r\n");
					CatOne.TcpConnFlag = true;
					CatOne.Cat1Status = CatOne.NextStatus;
					rt_sem_release(CatOneRev_Sem);
				}
				else if(strstr(RxBuff, "LIPOPEN: 0,0") != NULL) {
					CAT1_DBG_LOG("Cat1 failed to connect to the server.\r\n\r\n");
					CatOne.TcpConnFlag = false;
					CatOne.Cat1Status = CAT_ONE_OFF;
				}
				return;
			}
			
		case CAT_ONE_CPIN:
			if(strstr(RxBuff, "READY") == NULL) {
				CatOne.ATCmdRet = CAT_ONE_RET_ERR;
			}
			break;
		
		case CAT_ONE_CEREG:
			if(strstr(RxBuff, "CEREG: 0,1") == NULL) {
				CatOne.CatOne1mSDelayCnt = 3000;
				CatOne.ATCmdRet = CAT_ONE_RET_ERR;
			}
			break;
		
		case CAT_ONE_CGPADDR:
			if(strstr(RxBuff, "+CGPADDR") == NULL) {
				CatOne.ATCmdRet = CAT_ONE_RET_ERR;
			}
			break;
		
		case CAT_ONE_CSQ:
			if(strstr(RxBuff, "+CSQ") == NULL) {
				CatOne.ATCmdRet = CAT_ONE_RET_ERR;
			}
			break;
		
		case CAT_ONE_LTPCLOSE:
			if(strstr(RxBuff, "CLOSE OK") != NULL) {
				break;
			}
			else if(strstr(RxBuff, "ERROR") != NULL) {
				break;
			}
			else if(strstr(RxBuff, "OK") != NULL){
				break;
			}
			CatOne.ATCmdRet = CAT_ONE_RET_ERR;
			break;
		case CAT_ONE_AT_NULL: 
			p = strstr(RxBuff, "+LIPURC");
			if(p != NULL) {
				char rData[120];
				uint8_t  hData[60];
				int rLen, hLen, ret;
				
				if(strstr(p, "+LIPURC: 0,0") != NULL) {
					CAT1_DBG_LOG("TCP connection disconnected.\r\n\r\n");
					CatOne.TcpConnFlag = false;
					CatOne.Cat1Status = CAT_ONE_OFF;
					return;
				}
				
				ret = sscanf(p, "+LIPURC: 0,1,%d,%s\r\n", &rLen, rData);
				if(ret == 2) {
					if(rLen < 24)
						return;
					memset(hData, 0x00, 60);
					hLen = AsciiToHex(rData, hData, rLen);
					CatSendErrCnt = 0;
					CatOne.GateWay->SvrRevCallBack(CatOne.GateWay, hData, hLen);
				}
				else {
					return;
				}
				//CatOne.Cat1Status = CAT_ONE_CLOSE_TCP;
				rt_sem_release(CatOneRev_Sem);//接收任务
				return;
			}
		default:
			CatOne.ATCmdRet = CAT_ONE_RET_ERR;
			
	}
	if(CatOne.ATCmdRet == CAT_ONE_RET_OK) {
		CatOne.Cat1Status = CatOne.NextStatus;
		if(CatOne.AtCmd == CAT_ONE_LIPSEND)
			CatOne.CatOne1mSDelayCnt = 5 * 1000;
		else
			CatOne.CatOne1mSDelayCnt = 10;
		CatOne.AtCmd = CAT_ONE_AT_NULL;
		rt_sem_release(CatOneRev_Sem);
	}
}

void CatOneAtCmdSend(CatOneATCMD_m Cmd, uint32_t Dly, CatOneStatus_m NextStatus)
{
	CatOne.AtCmd = Cmd;
	if(CatOne.AtCmd == CAT_ONE_LIPSEND) {
		HexToAscii(CatOneEthTxBuff, CommUnitSendASCII, CatOneEthTxLen);
		sprintf(CatOne.CatOneSendBuff,"AT+LIPSEND=0,1,%d,\"%s\"\r\n",CatOneEthTxLen * 2, CommUnitSendASCII);
		CatOne.GateWay->BatteryReadDlyCnt = 30;
	}
	else if(CatOne.AtCmd == CAT_ONE_LIPOPEN) {
		sprintf(CatOne.CatOneSendBuff,"AT+LIPOPEN=\"TCP\",\"%d.%d.%d.%d\",%d\r\n", 
						CatOne.GateWay->ConfigPara.LTENet.DestAddr[0], 
						CatOne.GateWay->ConfigPara.LTENet.DestAddr[1], 
						CatOne.GateWay->ConfigPara.LTENet.DestAddr[2],
						CatOne.GateWay->ConfigPara.LTENet.DestAddr[3], 
						CatOne.GateWay->ConfigPara.LTENet.DestPort);
	}
	else {
		strcpy(CatOne.CatOneSendBuff, CatOneATCmdStr[CatOne.AtCmd]);
	}
	CAT1_DBG_LOG(CatOne.CatOneSendBuff);
	EthRevTimeOutCnt = 0;
	EthOrCat1UartSend((uint8_t *)CatOne.CatOneSendBuff, strlen(CatOne.CatOneSendBuff));
	CatOne.CatOne1mSDelayCnt = Dly;
	CatOne.Cat1Status = CAT_ONE_WAIT_REV;
	CatOne.NextStatus = NextStatus;
}

int GateWayRegister(uint8_t *TxBuff)
{
	uint16_t UnitCommCnt = 0;
	uint8_t *p = &TxBuff[0];
	uint16_t len = 5;
	
	if(CatOne.GateWay->ConfigPara.Rs485Ch1.CommUnitEnable == true && CatOne.GateWay->ConfigPara.Rs485Ch1.Enable == true) {
		UnitCommCnt++;
		memcpy(&p[len], CatOne.GateWay->ConfigPara.Rs485Ch1.CUPara.Para.Mac[0], 6);
		len += 6;
	}
	if(CatOne.GateWay->ConfigPara.Rs485Ch2.CommUnitEnable == true && CatOne.GateWay->ConfigPara.Rs485Ch2.Enable == true) {
		UnitCommCnt++;
		memcpy(&p[len], CatOne.GateWay->ConfigPara.Rs485Ch2.CUPara.Para.Mac[0], 6);
		len += 6;
	}
	for(int i = 0; i < COMMUNIT_NUM_MAX; i++) {
		if(CatOne.GateWay->ConfigPara.CommUnitArray[i].RegFlag == true) {
			for(int j = 0; j < CatOne.GateWay->ConfigPara.CommUnitArray[i].SensorN; j++)
			{
				memcpy(&p[len], CatOne.GateWay->ConfigPara.CommUnitArray[i].Mac[j], 6);
				len += 6;
				UnitCommCnt++;
			}
		}
	}
	TxBuff[0] = (len - 3) & 0x00ff;
	TxBuff[1] = ((len - 3) >> 8) & 0x00ff;
	TxBuff[2] = NET_COMM_CMD_REG;
	TxBuff[3] = UnitCommCnt & 0x00ff;
	TxBuff[4] = (UnitCommCnt >> 8) & 0x00ff;
	return len;
}

void CatOneLoopHandler(void)
{
	static rt_err_t result;
	uint16_t ret;
	static uint8_t Cat1RevErrCnt = 0;
	
	switch(CatOne.Cat1Status){
		case CAT_ONE_IDEL:
			rt_thread_delay(1);
			if(CatOne.ResetDelayCnt > 0) {
				CatOne.ResetDelayCnt--;
			}
			else {
				CatOne.Cat1Status = CAT_ONE_RESET;
			}
			break;
		
		case CAT_ONE_WAIT_REV:
			result = rt_sem_take(CatOneRev_Sem, CatOne.CatOne1mSDelayCnt);
			if(result != RT_EOK) {
				if(CatOne.AtCmdResendCnt > 0) {
					CatOne.AtCmdResendCnt--;
					CatOneAtCmdSend(CatOne.AtCmd, 2000, CatOne.NextStatus);
					CAT1_DBG_LOG("Cat1 Ret TimeOut, ReSend(%d)...\r\n", CatOne.AtCmdResendCnt);
				}
				else {		//3次错误，关机
					CAT1_DBG_LOG("Cat1 error, Close!\r\n");
					if(CatOne.AtCmd == CAT_ONE_LIPSEND)
						CatOne.Cat1Status = CAT_ONE_CLOSE_TCP;
					else
						CatOne.Cat1Status = CAT_ONE_OFF;
				}
			}
			break;
				
		case CAT_ONE_INIT:
			CatOne.AtCmdIdx++;
			if(CatOneModeSetCmdArray[CatOne.AtCmdIdx] != CAT_ONE_AT_CMD_END) {
				if(CatOneModeSetCmdArray[CatOne.AtCmdIdx] == CAT_ONE_CEREG)
					CatOne.AtCmdResendCnt = 30;
				else
					CatOne.AtCmdResendCnt = 3;
				CatOneAtCmdSend(CatOneModeSetCmdArray[CatOne.AtCmdIdx], 1000, CAT_ONE_INIT);
			}
			else {
				CatOne.Cat1Status = CAT_ONE_TCP_CONN;
				CatOne.CatOne1mSDelayCnt = 0;
				CatOne.AtCmdIdx = 0;
				CatOne.AtCmd = CAT_ONE_AT_NULL;
			}
			break;

		case CAT_ONE_TCP_CONN:
			CatOneAtCmdSend(CAT_ONE_LIPOPEN, 2000, CAT_ONE_WAIT_CONN);
			break;
		
		case CAT_ONE_WAIT_CONN:
			if(CatOne.TcpConnFlag) {
				if(CatOne.GateWay->SvrRegFlag == false)
					CatOne.Cat1Status = CAT_ONE_REG_SVR;
				else 
					CatOne.Cat1Status = CAT_ONE_WAIT_SEND;
			}
			break;
		
		case CAT_ONE_REG_SVR:		//注册服务器	
			ret = GateWayRegister(CatOneEthTxBuff);
			rt_mq_send(CatOne.GateWay->NetSendData_MQ, CatOneEthTxBuff, ret);
			CatOne.Cat1Status = CAT_ONE_WAIT_SEND;
			break;
		
		case CAT_ONE_WAIT_SEND:
			result = rt_mq_recv(CatOne.GateWay->NetSendData_MQ, Payload, CAT_ONE_REV_LEN_MAX, 1000);
			if(result == RT_EOK) {
				CatOneEthTxLen = NetCommOrgData(CatOne.GateWay, Payload, CatOneEthTxBuff);
				CatOne.Cat1Status = CAT_ONE_SEND_DATA;
			}
			else {
				if(CatOne.Cat1Status == CAT_ONE_RESET || CatOne.Cat1Status == CAT_ONE_OFF)		//外部命令执行，状态改变
					return;
				if(!CatOne.TcpConnFlag) {
					CatOne.Cat1Status = CAT_ONE_OFF;
				}
				else {
					CatSendErrCnt++;
					if(CatSendErrCnt > CAT1_ERR_RESET_DLY_MAX) {
						CatOne.Cat1Status = CAT_ONE_RESET;
						CAT1_DBG_LOG("Cat1 has no data for a long time, Reset!\r\n");
						CatSendErrCnt = 0;
						break;
					}
					CatOne.Cat1Status = CAT_ONE_WAIT_SEND;
				}
			}
			break;
		
		case CAT_ONE_SEND_DATA: 
			CatOne.AtCmdResendCnt = 3;
			Cat1RevErrCnt++;
			if(Cat1RevErrCnt > 10) {
				CatOne.Cat1Status = CAT_ONE_RESET;
				CAT1_DBG_LOG("Cat1 has no receive data for a long time, Reset!\r\n");
				Cat1RevErrCnt = 0;
				break;
			}
			CatOneAtCmdSend(CAT_ONE_LIPSEND, 5000, CAT_ONE_REV_DATA);
			break;
			
		case CAT_ONE_REV_DATA:
			result = rt_sem_take(CatOneRev_Sem, CatOne.CatOne1mSDelayCnt);
			if(result != RT_EOK) {
				if(CatOne.TcpConnFlag == false) {
					CAT1_DBG_LOG("Cat1 Rec Server Data Timeout!\r\n");
					break;
				}
			}
			else {
				Cat1RevErrCnt = 0;
			}
			if(CatOne.GateWay->SvrRegFlag == false)		//设备没注册，关闭4G，等待下一次重新注册
				CatOne.Cat1Status = CAT_ONE_OFF;
			else
				CatOne.Cat1Status = CAT_ONE_WAIT_SEND;
			break;

		case CAT_ONE_CLOSE_TCP:
			CatOne.AtCmdResendCnt = 3;
			CatOneAtCmdSend(CAT_ONE_LTPCLOSE, 1000, CAT_ONE_OFF);
			break;
		
		case CAT_ONE_OFF:
			//CAT1_POW_OFF();
			CAT1_RESET_SET();
			CAT1_PWR_KEY_CLR();
			rt_thread_delay(3000);
			CAT1_PWR_KEY_SET();
			CatSendErrCnt = 0;
			CatOne.GateWay->SvrRegFlag = false;
			CAT1_DBG_LOG("Cat1 Power Off!\r\n");
			CatOne.Cat1Status = CAT_ONE_IDEL;
			CatOne.ResetDelayCnt = CATONE_RESET_DELAY_TIME_MAX;
			break;
			
		case CAT_ONE_RESET:
			CatSendErrCnt = 0;
			CatOne.GateWay->SvrRegFlag = false;
			CAT1_DBG_LOG("Cat1 Reset!\r\n");
			CAT1_RESET_CLR();
			CAT1_PWR_KEY_SET();
			//CAT1_POW_ON();
			rt_thread_delay(50);
			CAT1_RESET_SET();
			CAT1_PWR_KEY_CLR();
			rt_thread_delay(1000);
			CAT1_PWR_KEY_SET();
			CatOne.Cat1Status = CAT_ONE_INIT;
			CatOne.AtCmdIdx = 0;
			rt_thread_delay(1000);
			CatOne.GateWay->BatteryReadDlyCnt = 60;
			break;	
	}
}

void EthLoopHandler(void)
{
	rt_err_t result;
	
	switch(CatOne.EthStatus) {
		case ETH_IDEL:
			rt_thread_delay(1);
			if(CatOne.EthResetDelayCnt > 0) {
				CatOne.EthResetDelayCnt--;
			}
			else {
				CatOne.EthStatus = ETH_RESET;
			}
			break;
		
		case ETH_RESET:
			CAT1_DBG_LOG("ETH Reset!\r\n");
			ETH_RESET_CLR();
			rt_thread_delay(10);
			ETH_RESET_SET();
			rt_thread_delay(2000);  // 延长复位后稳定时间到2秒
			ETHApplyNetPara();  // 配置EthNet网络参数
			CatOne.EthStatus = ETH_WAIT_LINK;
			CatOne.EthLinkWaitCnt = 0;
			CatOne.EthFirstRegFlag = true;  // 重置首次注册标志
			break;
		
		case ETH_WAIT_LINK:
			if(CatOne.EthLinkWaitCnt == 0) {
				/* 首次进入等待链路状态,等待模块完全启动 */
				CAT1_DBG_LOG("ETH Waiting for module ready...\r\n");
				rt_thread_delay(2000);
			}
			if(ETH_LINK_GET() == Reset) {
				CAT1_DBG_LOG("ETH Link OK!\r\n");
				if(CatOne.GateWay->SvrRegFlag == false) {
					CatOne.EthStatus = ETH_REG_SVR;
				}
				else {
					CatOne.EthStatus = ETH_WAIT_SEND;
				}
			}
			else {
				CatOne.EthLinkWaitCnt++;
				if(CatOne.EthLinkWaitCnt >= ETH_LINK_WAIT_TIME_MAX) {
					CAT1_DBG_LOG("ETH Link Timeout, Reset!\r\n");
					CatOne.EthStatus = ETH_OFF;
				}
				rt_thread_delay(1);
			}
			break;
		
		case ETH_REG_SVR:
			{
				// 首次注册时添加延迟，等待系统稳定
				if(CatOne.EthFirstRegFlag) {
					CAT1_DBG_LOG("ETH First Register, waiting for system stable...\r\n");
					rt_thread_delay(ETH_FIRST_REG_DELAY);
					CatOne.EthFirstRegFlag = false;
				}
				
				uint8_t ret = GateWayRegister(CatOneEthTxBuff);
				rt_mq_send(CatOne.GateWay->NetSendData_MQ, CatOneEthTxBuff, ret);
				CAT1_DBG_LOG("ETH Register Server...\r\n");
				CatOne.EthStatus = ETH_WAIT_SEND;
				CatOne.EthSendRetryCnt = 0;  // 重置重试计数器
			}
			break;
		
		case ETH_WAIT_SEND:
			result = rt_mq_recv(CatOne.GateWay->NetSendData_MQ, Payload, CAT_ONE_REV_LEN_MAX, 100);
			if(result == RT_EOK) {
				CatOneEthTxLen = NetCommOrgData(CatOne.GateWay, Payload, CatOneEthTxBuff);
				CatOne.EthStatus = ETH_SEND_DATA;
			}
			else {
				if(CatOne.EthStatus == ETH_RESET || CatOne.EthStatus == ETH_OFF)
					return;
				if(ETH_LINK_GET() != Reset) {
					CAT1_DBG_LOG("ETH Link Lost!\r\n");
					CatOne.EthStatus = ETH_OFF;
				}
				else {
					rt_thread_delay(1);
				}
			}
			break;
		
		case ETH_SEND_DATA:
			HexToAscii(CatOneEthTxBuff, CommUnitSendASCII, CatOneEthTxLen);
			EthRevTimeOutCnt = 0;
			EthOrCat1UartSend((uint8_t *)CommUnitSendASCII, CatOneEthTxLen * 2);
			CommUnitSendASCII[CatOneEthTxLen * 2] = 0;
			CAT1_DBG_LOG("Eth Send: %s\r\n", CommUnitSendASCII);
			
			CatOne.EthStatus = ETH_WAIT_RECV;
			CatOne.EthRecvTimeoutCnt = 0;
			CatOne.EthSendRetryCnt = 0;
			break;
		
		case ETH_WAIT_RECV:
			rt_thread_delay(1);
			CatOne.EthRecvTimeoutCnt++;
			
			if(CatOne.EthRecvTimeoutCnt >= ETH_RECV_TIMEOUT_MAX) {
				CAT1_DBG_LOG("ETH Recv Timeout!\r\n");
				CatOne.EthSendRetryCnt++;
				if(CatOne.EthSendRetryCnt >= ETH_SEND_RETRY_MAX) {
					CAT1_DBG_LOG("ETH Send Retry Max, Reset!\r\n");
					CatOne.EthStatus = ETH_OFF;
				}
				else {
					if(CatOne.GateWay->SvrRegFlag == false) {
						CatOne.EthStatus = ETH_REG_SVR;
					}
					else {
						CatOne.EthStatus = ETH_WAIT_SEND;
					}
				}
			}
			
			if(ETH_LINK_GET() != Reset) {
				CAT1_DBG_LOG("ETH Link Lost During Wait!\r\n");
				CatOne.EthStatus = ETH_OFF;
			}
			
			if(CatOne.GateWay->SvrRegFlag == true) {
				CAT1_DBG_LOG("ETH Register Success!\r\n");
				CatOne.EthStatus = ETH_WAIT_SEND;
				CatOne.EthRecvTimeoutCnt = 0;
				CatOne.EthSendRetryCnt = 0;
			}
			
			break;
		
		case ETH_OFF:
			CAT1_DBG_LOG("ETH Power Off!\r\n");
			CatOne.GateWay->SvrRegFlag = false;
			//ETH_RESET_CLR();
			//rt_thread_delay(3000);
			//ETH_RESET_SET();
			CatOne.EthStatus = ETH_IDEL;
			CatOne.EthResetDelayCnt = ETH_RESET_DELAY_TIME_MAX;
			break;
		
		default:
			CatOne.EthStatus = ETH_RESET;
			break;
	}
}

bool CatOneEthSendQueue(uint8_t *sData, uint16_t sLen)
{
	if(CatOne.GateWay->SvrRegFlag == false)
		return false;
	rt_mq_send(CatOne.GateWay->NetSendData_MQ, sData, sLen);
	return true;
}

static void CatOneInit(GateWayPara GateWay)
{
	memset(&CatOne, 0x00, sizeof(CatOne_t));
	CatOne.Cat1Status = CAT_ONE_RESET;
	CatOne.GateWay = GateWay;
	CatOne.CatOneRevCallBack = GateWay->SvrRevCallBack;
}

void CatOneEthRev_Thread_Entry(void *parameter)
{
	rt_err_t result;
	char RxBuffTemp[CAT_ONE_REV_LEN_MAX];
	uint8_t HexData[CAT_ONE_REV_LEN_MAX / 2];
	
	GateWayPara GateWay = (GateWayPara)parameter;
	
	rt_kprintf("CatOneTthRev Thread is running!\r\n");
	
	while(1) {
		if(GateWay->ConfigPara.Comm == CATONE_COMM) {
			result = rt_sem_take(CatOneIRQ_Sem, 500);
			if(result == RT_EOK) {
				memcpy(RxBuffTemp, CatOneEthRxBuff, CatOneEthRxLen);
				RxBuffTemp[CatOneEthRxLen] = 0;
				CatOneAtCmdAnalyze(RxBuffTemp);
				memset(CatOneEthRxBuff, 0x00, CAT_ONE_REV_LEN_MAX);
				CatOneEthRxLen  = 0;
			}
			//CatOneEthRxLen  = 0;
		}
		else if(GateWay->ConfigPara.Comm == ETH_COMM) {
			result = rt_sem_take(EthIRQ_Sem, 500);
			if(result == RT_EOK) {
				memcpy(RxBuffTemp, CatOneEthRxBuff, CatOneEthRxLen);
				RxBuffTemp[CatOneEthRxLen] = 0;
				CAT1_DBG_LOG("Eth Rev: %s\r\n",RxBuffTemp);
				memset(HexData, 0x00, CatOneEthRxLen / 2);
				uint8_t ret = AsciiToHex(RxBuffTemp, HexData, CatOneEthRxLen);
				if(ret > 0)
					GateWay->SvrRevCallBack(GateWay, HexData,  ret);
				memset(CatOneEthRxBuff, 0x00, CAT_ONE_REV_LEN_MAX);
				CatOneEthRxLen = 0;
			}
			//CatOneEthRxLen = 0;
		}
	}
}

void CatOne_Eth_Thread_Entry(void *parameter)
{
	GateWayPara GateWay = (GateWayPara)parameter;
	
	CatOneRev_Sem  = rt_sem_create("cat1r_sem",	0, RT_IPC_FLAG_FIFO);
	if(CatOneRev_Sem == RT_NULL) {
		rt_kprintf("CatOne Sem Create Failed!\r\n");
	}
	
	EthIRQ_Sem  = rt_sem_create("eth_sem",	0, RT_IPC_FLAG_FIFO);
	if(EthIRQ_Sem == RT_NULL) {
		rt_kprintf("Eth Sem Create Failed!\r\n");
	}
	
	CatOneIRQ_Sem  = rt_sem_create("cat1_sem",	0, RT_IPC_FLAG_FIFO);
	if(CatOneIRQ_Sem == RT_NULL) {
		rt_kprintf("CatOneIRQ Sem Create Failed!\r\n");
	}
	
	CatOneInit(GateWay);
	ETH_RESET_CLR();
	rt_thread_delay(10);
	ETH_RESET_SET();	
	Cat1Rev_Thread = rt_thread_create("Cat1Rev", CatOneEthRev_Thread_Entry, parameter, 3000, 3, 20);
	if (Cat1Rev_Thread != RT_NULL) {
		rt_thread_startup(Cat1Rev_Thread);
	}
	else {
		rt_kprintf("CatOneRev Thread Create Failed! Exit...\r\n");
		return;
	}
	rt_kprintf("CatOne Thread is running！\r\n");

	while(1) {
		//rt_mutex_take(GateWay->UartRevMutex, RT_WAITING_FOREVER);
		if(GateWay->ConfigPara.Comm == CATONE_COMM)
			CatOneLoopHandler();
		else if(GateWay->ConfigPara.Comm == ETH_COMM)
			EthLoopHandler();
		else
			rt_thread_delay(1);
		//rt_mutex_release(GateWay->UartRevMutex);
	}
}


void EthOrCat1RxIrqCallback(uint8_t rData)
{	
	if(EthRevTimeOutCnt == 0) 
		CatOneEthRxLen = 0;
	
	if(CatOneEthRxLen < CAT_ONE_REV_LEN_MAX) {
		CatOneEthRxBuff[CatOneEthRxLen++] = rData;
	}
	
	EthRevTimeOutCnt = 3;
}

void EthRxOverhandler(void)
{
	if(EthRevTimeOutCnt > 0)
		EthRevTimeOutCnt--;

	if(CatOneEthRxLen > 5 && EthRevTimeOutCnt == 0) {
		EthRevTimeOutCnt = 20;
		if(CatOne.GateWay->ConfigPara.Comm == CATONE_COMM)
			rt_sem_release(CatOneIRQ_Sem);
		else
			rt_sem_release(EthIRQ_Sem);
	}
}

void CatReadImeiOrSim(char *Imei, char *Sim)
{
	if(Imei != NULL) {
		memcpy(Imei, CatOne.IMEI, 15);
		Imei[15] = 0x00;
	}
	if(Sim != NULL) {
		memcpy(Sim, CatOne.SIM, 20);
		Sim[20] = 0x00;
	}
}

void CatOneTriggerRegister(void)
{
	ETHStop();
  CAT1_ON();
  CatOneReset();
}

void ETHTriggerRegister(void)
{
	CatOne.EthStatus = ETH_REG_SVR;
}

void ETHApplyNetPara(void)
{
	uint8_t cmdBuf[128];
	uint16_t idx = 0;
	GWConfigPara_t *pCfg = (GWConfigPara_t *)&CatOne.GateWay->ConfigPara;

	/* EthNet模块二进制命令协议:
	 * 识别流(10B): ED F2 A3 56 CA DB 91 84 B0 D7
	 * 命令类型00: 读参数/状态
	 * 命令类型03: 写参数并保存到Flash
	 * 命令类型07: 写参数+保存+重启模块
	 *
	 * 参数偏移: 0x00=LocalIP(4B), 0x04=NetMask(4B), 0x08=Gateway(4B),
	 *           0x0C=DestIP(4B), 0x10=LocalPort(2B), 0x12=DestPort(2B),
	 *           0x14=WorkMode(1B: 0=TCP Server,1=TCP Client,2=UDP),
	 *           0x38=DHCP(1B: 0=静态,1=DHCP)
	 */

	/* 步骤0: 检查系统是否初始化完毕
	 * 发送命令: ed f2 a3 56 ca db 91 84 b0 d7 00 3d 01
	 * 如果返回00或01则表示初始化完成,可以进行写参数
	 */
	CAT1_DBG_LOG("ETH Check init...");
	for(int waitCnt = 0; waitCnt < 50; waitCnt++) {
		idx = 0;
		cmdBuf[idx++] = 0xED; cmdBuf[idx++] = 0xF2; cmdBuf[idx++] = 0xA3; cmdBuf[idx++] = 0x56;
		cmdBuf[idx++] = 0xCA; cmdBuf[idx++] = 0xDB; cmdBuf[idx++] = 0x91; cmdBuf[idx++] = 0x84;
		cmdBuf[idx++] = 0xB0; cmdBuf[idx++] = 0xD7;
		cmdBuf[idx++] = 0x00;   /* 读参数 */
		cmdBuf[idx++] = 0x3D;   /* 偏移: 0x3D (Status) */
		cmdBuf[idx++] = 0x01;   /* 长度: 1字节 */
		EthOrCat1UartSend(cmdBuf, idx);
		rt_thread_delay(100);
		/* 实际应该检查返回值,这里简单等待后继续 */
	}
	CAT1_DBG_LOG("ETH Init check done");

	/* 步骤1: 一次性写入从0x00开始的网络参数(LocalIP~WorkMode, 共0x15字节)
	 * 偏移0x00~0x14: LocalIP(4) + NetMask(4) + Gateway(4) + DestIP(4) + LocalPort(2) + DestPort(2) + WorkMode(1)
	 */
	idx = 0;
	cmdBuf[idx++] = 0xED; cmdBuf[idx++] = 0xF2; cmdBuf[idx++] = 0xA3; cmdBuf[idx++] = 0x56;
	cmdBuf[idx++] = 0xCA; cmdBuf[idx++] = 0xDB; cmdBuf[idx++] = 0x91; cmdBuf[idx++] = 0x84;
	cmdBuf[idx++] = 0xB0; cmdBuf[idx++] = 0xD7;
	cmdBuf[idx++] = 0x01;   /* 命令类型: 写参数,部分参数修改后会自动重启 */
	cmdBuf[idx++] = 0x00;   /* 偏移: 0x00 */
	cmdBuf[idx++] = 0x15;   /* 长度: 21字节 */

	/* Local IP */
	cmdBuf[idx++] = pCfg->EthNet.IpAddr[0];
	cmdBuf[idx++] = pCfg->EthNet.IpAddr[1];
	cmdBuf[idx++] = pCfg->EthNet.IpAddr[2];
	cmdBuf[idx++] = pCfg->EthNet.IpAddr[3];
	/* Net Mask */
	cmdBuf[idx++] = pCfg->EthNet.SubnetMask[0];
	cmdBuf[idx++] = pCfg->EthNet.SubnetMask[1];
	cmdBuf[idx++] = pCfg->EthNet.SubnetMask[2];
	cmdBuf[idx++] = pCfg->EthNet.SubnetMask[3];
	/* Gateway */
	cmdBuf[idx++] = pCfg->EthNet.Gateway[0];
	cmdBuf[idx++] = pCfg->EthNet.Gateway[1];
	cmdBuf[idx++] = pCfg->EthNet.Gateway[2];
	cmdBuf[idx++] = pCfg->EthNet.Gateway[3];
	/* Dest IP */
	cmdBuf[idx++] = pCfg->EthNet.DestIp[0];
	cmdBuf[idx++] = pCfg->EthNet.DestIp[1];
	cmdBuf[idx++] = pCfg->EthNet.DestIp[2];
	cmdBuf[idx++] = pCfg->EthNet.DestIp[3];
	/* Local Port (大端) */
	cmdBuf[idx++] = (uint8_t)(pCfg->EthNet.IpPort >> 8);
	cmdBuf[idx++] = (uint8_t)(pCfg->EthNet.IpPort & 0xFF);
	/* Dest Port (大端) */
	cmdBuf[idx++] = (uint8_t)(pCfg->EthNet.DestPort >> 8);
	cmdBuf[idx++] = (uint8_t)(pCfg->EthNet.DestPort & 0xFF);
	/* Work Mode: 0=TCP Server, 1=TCP Client, 2=UDP */
	if(pCfg->EthNet.WorkMode == ETH_MODE_TCP_SERVER) {
		cmdBuf[idx++] = 0x00;
	} else if(pCfg->EthNet.WorkMode == ETH_MODE_TCP_CLIENT) {
		cmdBuf[idx++] = 0x01;
	} else {
		cmdBuf[idx++] = 0x02;
	}

	CAT1_DBG_LOG("ETH Write IP/Mode, len=%d", idx);
	EthOrCat1UartSend(cmdBuf, idx);
	rt_thread_delay(500);

	/* 步骤2: 写入DHCP/IP模式 (偏移0x38, 1字节)
	 * 0=静态IP, 1=DHCP
	 */
	idx = 0;
	cmdBuf[idx++] = 0xED; cmdBuf[idx++] = 0xF2; cmdBuf[idx++] = 0xA3; cmdBuf[idx++] = 0x56;
	cmdBuf[idx++] = 0xCA; cmdBuf[idx++] = 0xDB; cmdBuf[idx++] = 0x91; cmdBuf[idx++] = 0x84;
	cmdBuf[idx++] = 0xB0; cmdBuf[idx++] = 0xD7;
	cmdBuf[idx++] = 0x01;   /* 命令类型: 写参数,DHCP修改后会自动重启 */
	cmdBuf[idx++] = 0x38;   /* 偏移: 0x38 (DHCP en) */
	cmdBuf[idx++] = 0x01;   /* 长度: 1字节 */
	cmdBuf[idx++] = (pCfg->EthNet.IpMode == ETH_IP_DHCP) ? 0x01 : 0x00;

	CAT1_DBG_LOG("ETH Write DHCP=%d", cmdBuf[idx - 1]);
	EthOrCat1UartSend(cmdBuf, idx);
	rt_thread_delay(3000);  /* 等待模块重启 */

	/* 注意：不要向DevID(偏移0x1F)区域写入任意数据，否则根据手册说明，
	 * 如果写入的ID不正确，设备会丢弃所有其他写入的参数
	 * 模块会在下次上电时自动使用Flash中保存的参数工作
	 */
}
