#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; 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; 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(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"); //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) { CatOne.Cat1Status = CAT_ONE_REG_SVR; } void ETHTriggerRegister(void) { CatOne.EthStatus = ETH_REG_SVR; } void ETHResetEx(void) { CatOne.EthStatus = ETH_RESET; } 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++] = 0x03; /* 命令类型: 写参数并保存到Flash */ 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++] = 0x03; /* 命令类型: 写参数并保存到Flash */ 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(500); /* 步骤3: 使用07命令重启模块使参数生效 * 07命令: 写参数+保存+重启。写入偏移0x1F(DevID),1字节0x00 * DevID不可修改,实际效果只是重启模块 */ 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++] = 0x07; /* 命令类型: 写参数+保存+重启 */ cmdBuf[idx++] = 0x1F; /* 偏移: 0x1F (DevID区域,不可修改) */ cmdBuf[idx++] = 0x01; /* 长度: 1字节 */ cmdBuf[idx++] = 0x00; /* 写入无效数据,仅触发重启 */ CAT1_DBG_LOG("ETH Restart module"); EthOrCat1UartSend(cmdBuf, idx); rt_thread_delay(2000); }