// TransferCtrl.cpp: implementation of the CTransferCtrl class. // ////////////////////////////////////////////////////////////////////// #include "TransferCtrl.h" #include "FileOperTools.h" #include "GeoMative.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif extern BYTE BBCCalculate(const char *pData, int iSize,BYTE ucOrgRes); extern CGeoMativeApp theApp; extern int g_iTransFileMode; extern BOOL g_bIsOnlineTransfer; //extern BYTE g_byCurTestType; #define MODULE_NAME _T("CTransferCtrl") #define MAX_SKIP_ERR_BYTES 60 ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CTransferCtrl::CTransferCtrl() { // memset(&m_stCtrlRcvMsg, 0, sizeof(m_stCtrlRcvMsg)); m_bIsNeedSendCtrMsg = false; m_iLastErrNo = 0; m_bIsInitialed = false; m_ucCmd = 0; m_iSeriNo = 1; m_ucDevType =0; m_ucCtrlCmd = 0; m_iLastSeriNo = 0; m_uiPlcAddr = 0; } CTransferCtrl::~CTransferCtrl() { } bool CTransferCtrl::InitialClient() { return true; /* char chRcvBuf[MAX_RCV_CTRLBUF]={0}; int iCtrlLen = 0; int iRepeat = 100; while(iRepeat > 0) { int iCtrlRes = RecvCtrlMsg(chRcvBuf, &iCtrlLen, MAX_RCV_CTRLBUF, 100); if (EN_RECV_CTRL_CMD == iCtrlRes) { if (EN_FORCE_LOGIN == GetCurrCtrlCmd()) { } } } */ } bool CTransferCtrl::Initialize() { m_bIsInitialed = InitailTcp(); return m_bIsInitialed; } //DEL bool CTransferCtrl::ConnectToServer(CString strIP, WORD wPort) //DEL { //DEL if (ConnectServer(strIP,wPort)) //DEL { //DEL m_strIPAddr = strIP; //DEL m_wPort = wPort; //DEL return true; //DEL } //DEL return false; //DEL } //DEL bool CTransferCtrl::ReConnect() //DEL { //DEL return ConnectToServer(m_strIPAddr, m_wPort); //DEL } //DEL bool CTransferCtrl::SendCtrlInfo(BYTE ucCmd, WORD wTsn, const char* pData, WORD wLen, int iTimeOut) //DEL { //DEL EnterCriticalSection(&m_MutexSec); //DEL if (0 != m_stProCtrlInfo.ucCmd) //DEL { //DEL return false; //DEL } //DEL memset(&m_stProCtrlInfo, 0, sizeof(m_stProCtrlInfo)); //DEL if (wLen > 0) //DEL { //DEL if (wLen > MAX_CTRL_CONTENT) //DEL { //DEL CString str = _T(""); //DEL str.Format(_T("send ctrl cmd information overlength,value = %d, max_length = %d"), wLen, MAX_CTRL_CONTENT); //DEL AfxMessageBox(str); //DEL return false; //DEL } //DEL m_stProCtrlInfo.wLen = wLen; //DEL memcpy(m_stProCtrlInfo.chData, pData, wLen); //DEL } //DEL else //DEL m_stProCtrlInfo.wLen =0; //DEL m_stProCtrlInfo.ucCmd = ucCmd; //DEL m_stProCtrlInfo.wTsn = wTsn; //DEL m_stProCtrlInfo.iTimeOut = iTimeOut; //DEL // m_stProCtrlInfo.wRespLen = GetCtrlRspLength(ucCmd); //DEL m_bIsNeedSendCtrMsg = true; //DEL //DEL LeaveCriticalSection(&m_MutexSec); //DEL return true; //DEL } bool CTransferCtrl::SendCtrlInfo(const char*pCtrlHeader, const char* pData, WORD wDataLen,BYTE DataType) { STTransCtrlInfo *pTransCtrl = (STTransCtrlInfo*)pCtrlHeader; return SendCtrlInfoToDev(pTransCtrl,pData, wDataLen,DataType); } bool CTransferCtrl::SendCtrlInfoToDev(const STTransCtrlInfo * pTransInfo,const char* pData, WORD wDataLen, BYTE ucDataType) { BYTE ucBuf[4096]={0}; STCtrlProtoHeader* pHeader = (STCtrlProtoHeader*)ucBuf; pHeader->wIDCode = htonl(CTRL_GD10_CODE) ; pHeader->ucSrcAddr = htonl(theApp.m_uiUserID); pHeader->ucSrcType = 2; // if (0 == pTransInfo->ucCmd) // pHeader->ucDstAddr = 0xFFFFFFFF; // else pHeader->ucDstAddr = htonl(pTransInfo->uiDevID); pHeader->ucDstType = pTransInfo->ucDevType; pHeader->ucCMD = pTransInfo->ucCmd; pHeader->ucDataType = ucDataType; if (1 == ucDataType) pHeader->dwSeriNO = htonl(m_iSeriNo++); else pHeader->dwSeriNO = htonl(m_iLastSeriNo); pHeader->Status_code = 0; pHeader->ucPacketNum = 1; memset(pHeader->ucReverse, 0, sizeof(pHeader->ucReverse)); WORD wTotalLen = sizeof(STCtrlProtoHeader)+1; if (wDataLen > 0) { memcpy(ucBuf+sizeof(STCtrlProtoHeader), pData, wDataLen); wTotalLen += wDataLen; } pHeader->wTotalLen = htons(wTotalLen); *((BYTE*)(ucBuf+wTotalLen-1)) = BBCCalculate((const char*)(ucBuf), wTotalLen-1, 0); int iSendLen = SendData((const char*)ucBuf, wTotalLen); //如果发送成功,则设置接收数据相关的控制信息 if (iSendLen == wTotalLen) { m_ucCmd = pTransInfo->ucCmd; m_ucDevType = pTransInfo->ucDevType; // m_stCtrlRcvMsg.wTsn = wTsn; return true; } CString str = _T(""); str.Format(_T("[%s][%d]send data error, shoule_send_length = %d, actually_val = %d,error = %d"), MODULE_NAME, __LINE__, wTotalLen, iSendLen, GetLastError()); CFileOperTools::GetInstance()->WriteComLog(str); return false; } bool CTransferCtrl::RecvEnoughMsg(char* pData, int iLen, int iTimeOut) { DWORD dwTick = GetTickCount(); DWORD dwCostTick = 0; int iTmpLen = 0, iRcvLen = 0; CString str = _T(""); while(dwCostTick < iTimeOut) { iTmpLen = 0; if (!RecvData(pData+iRcvLen, iLen-iRcvLen, iTmpLen)) { str.Format(_T("[%s][%d]zm:CTransferCtrl::RecvEnoughMsg() !RecvData(pData+iRcvLen, iLen-iRcvLen, iTmpLen)"), MODULE_NAME, __LINE__); CFileOperTools::GetInstance()->WriteComLog(str); return false; } iRcvLen += iTmpLen; if (iRcvLen > iLen) { str.Format(_T("[%s][%d]zm: CTransferCtrl::RecvEnoughMsg() %s"), MODULE_NAME, __LINE__, str); CFileOperTools::GetInstance()->WriteComLog(str); return false; } else if (iRcvLen == iLen) { return true; } Sleep(100); dwCostTick = GetTickCount() - dwTick; } return false; } bool CTransferCtrl::IsCtrlMsg(BYTE ucCMd) { if (EN_TRANSFER_FILE_BY_WIFI == g_iTransFileMode) { if ( 0 == ucCMd) { return true; } } else if (EN_TRANSFER_FILE_BY_CLOUND == g_iTransFileMode) { if (ucCMd == EN_DEV_ONLINE || ucCMd == EN_FORCE_LOGIN ) { return true; } } return false; } bool CTransferCtrl::IsPlcStatusMsg(BYTE ucCmd, BYTE ucSrcType) { if ((5 == ucCmd) && (ucSrcType == EN_DEV_PLC) && (EN_TRANSFER_FILE_BY_CLOUND == g_iTransFileMode)) return true; else return false; } int CTransferCtrl::RecvCommRspMsg(char* pRcvData, int* pRcvLen, int iMaxRcvLen, int iRcvTimeout,bool bIsRcvCtrl) { // iRcvTimeout =5000; DWORD dwTick = GetTickCount(); DWORD dwCostTick = 0; //这里包括一个字节的CRC位置 int iHeaderSize = sizeof(STCtrlProtoHeader)+1; int iGetReceivedDataTime = 1000; CString strErr = _T(""); char chData[100]={0}; WORD wSkipByte = 0; while(dwCostTick < iRcvTimeout) { if (!RecvEnoughMsg(chData, iHeaderSize, iRcvTimeout-dwCostTick)) { if (GetTickCount()-dwTick >= iRcvTimeout) { if (!bIsRcvCtrl) { strErr.Empty(); strErr.Format(_T("[%s][%d]receive data(HeaderSize) timeout,max_time=%d"),MODULE_NAME, __LINE__,iRcvTimeout); CFileOperTools::GetInstance()->WriteComLog(strErr); } return EN_RECV_TIMEOUT; } return EN_RECV_TIMEOUT; } int i = 0; bool bIsFoundID = false; UINT dwIDCode = 0; for (i = 0; i <= iHeaderSize; i++) { dwIDCode = ntohl(*(UINT*)(chData+i)); if (dwIDCode == CTRL_GD10_CODE ) { bIsFoundID = true; break; } } //如果查找到 if (bIsFoundID) { //如果是在数据的中间部分查找到,则还需要在接收缓冲区里寻找数据控制协议的后半部分 if (i > 0) { char chTmpData[100]= {0}; //如果已经找到顺利在数据之间找到了起始标志,那么可以认为这个包的剩下信息也已经到数据缓冲区了 //所以此时可以设置1秒为最大延时 if (!RecvEnoughMsg(chTmpData+(iHeaderSize-i), i,iGetReceivedDataTime)) { strErr.Empty(); strErr.Format(_T("[%s][%d]receive data timeout when found pro_ctrl_id_code"),MODULE_NAME, __LINE__); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_RECV_TIMEOUT; } //将pRcvData起始位置到结束位置都拷贝到新的缓冲区里,形成一个新的PRO_CTRL_HEADER memcpy(chTmpData, chData+i, iHeaderSize-i); //再将新缓冲区的内容拷贝回来 memcpy(chData, chTmpData, iHeaderSize); } //进行数据控制协议的校验 STCtrlProtoHeader* pHeaderInfo = (STCtrlProtoHeader*)chData; WORD wLen = ntohs(pHeaderInfo->wTotalLen); //长度校验 if ((wLen-iHeaderSize) > iMaxRcvLen) { strErr.Empty(); strErr.Format(_T("[%s][%d]receive data len error, MaxRcvLen = %d, RecvDataLen = %d"),MODULE_NAME, __LINE__, iMaxRcvLen, wLen - iHeaderSize); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_RECV_DATA_ERROR; } if (wLen > iHeaderSize) { //由于可能存在超长报文而被分包,所以这里等待时间延长设置为原来等待已经到达数据的2倍时间 pRcvData[0] = chData[iHeaderSize-1];//因为此时数据的第一个个字节已经存储到控制报文中去了 if (!RecvEnoughMsg(pRcvData+1, wLen-iHeaderSize, 2*iGetReceivedDataTime)) { strErr.Empty(); strErr.Format(_T("[%s][%d]receive data timeout when found pro_ctrl_id_code"),MODULE_NAME, __LINE__); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_RECV_TIMEOUT; } } //如果这里收到的是云端发过来的强制登录信息,则直接忽略进行获取下一个报文 // if (0xFE == pHeaderInfo->ucCMD ) // { // //清空之间的数据 // if (wLen > iHeaderSize) // memset(pRcvData, 0, iMaxRcvLen); // return RecvCommRspMsg(pRcvData, pRcvLen, iMaxRcvLen, iRcvTimeout); // } if (pHeaderInfo->ucCMD == EN_CTRL_MEASURE_DATA && (g_bIsOnlineTransfer == TRUE)) { //校验CRC BYTE ucCRc = BBCCalculate(chData, iHeaderSize - 1, 0); if (wLen > iHeaderSize) ucCRc = BBCCalculate(pRcvData, wLen - iHeaderSize, ucCRc); BYTE ucRecvCRC = (wLen > iHeaderSize) ? *((BYTE*)(pRcvData + wLen - iHeaderSize)) : *(BYTE*)(chData + iHeaderSize - 1); if (ucCRc != *((BYTE*)(pRcvData + wLen - iHeaderSize))) { strErr.Empty(); strErr.Format(_T("[%s][%d]CRC error, calucate_crc = %d, org_data_crc = %d"), MODULE_NAME, __LINE__, ucCRc, *((BYTE*)(pRcvData + wLen - iHeaderSize - 1))); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_RECV_DATA_ERROR; } strErr.Format(_T("[%s][%d]:recv real time wnd %0x begin***************"), MODULE_NAME, __LINE__, pHeaderInfo->ucCMD); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_REAL_TIME_TESTING_DATA; } if (pHeaderInfo->ucCMD == EN_RECV_DEVICE_ONLINE) { //校验CRC BYTE ucCRc = BBCCalculate(chData, iHeaderSize - 1, 0); if (wLen > iHeaderSize) ucCRc = BBCCalculate(pRcvData, wLen - iHeaderSize, ucCRc); BYTE ucRecvCRC = (wLen > iHeaderSize) ? *((BYTE*)(pRcvData + wLen - iHeaderSize)) : *(BYTE*)(chData + iHeaderSize - 1); if (ucCRc != *((BYTE*)(pRcvData + wLen - iHeaderSize))) { strErr.Empty(); strErr.Format(_T("[%s][%d]CRC error, calucate_crc = %d, org_data_crc = %d"), MODULE_NAME, __LINE__, ucCRc, *((BYTE*)(pRcvData + wLen - iHeaderSize - 1))); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_RECV_DATA_ERROR; } return EN_RECV_NOTIFY_DEVICE_ONLINE; } else if (pHeaderInfo->ucCMD == EN_RECV_DEVICE_OFFLINE) { //校验CRC BYTE ucCRc = BBCCalculate(chData, iHeaderSize - 1, 0); if (wLen > iHeaderSize) ucCRc = BBCCalculate(pRcvData, wLen - iHeaderSize, ucCRc); BYTE ucRecvCRC = (wLen > iHeaderSize) ? *((BYTE*)(pRcvData + wLen - iHeaderSize)) : *(BYTE*)(chData + iHeaderSize - 1); if (ucCRc != *((BYTE*)(pRcvData + wLen - iHeaderSize))) { strErr.Empty(); strErr.Format(_T("[%s][%d]CRC error, calucate_crc = %d, org_data_crc = %d"), MODULE_NAME, __LINE__, ucCRc, *((BYTE*)(pRcvData + wLen - iHeaderSize - 1))); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_RECV_DATA_ERROR; } return EN_RECV_NOTIFY_DEVICE_OFFLINE; } int iRet = 0; if (IsCtrlMsg(pHeaderInfo->ucCMD)) { m_ucCtrlCmd = pHeaderInfo->ucCMD; strErr.Empty(); strErr.Format(_T("[%s][%d]receive ctrl msg.msg_cmd = %d"),MODULE_NAME, __LINE__,pHeaderInfo->ucCMD); CFileOperTools::GetInstance()->WriteComLog(strErr); *pRcvLen = wLen -iHeaderSize; iRet = EN_RECV_CTRL_CMD; m_iLastSeriNo = ntohl(pHeaderInfo->dwSeriNO); } else if (IsPlcStatusMsg(pHeaderInfo->ucCMD,pHeaderInfo->ucSrcType)) { iRet = EN_RECV_PLC_STATUS; m_uiPlcAddr = pHeaderInfo->ucSrcAddr; } else { if ((pHeaderInfo->ucCMD != EN_CTRL_MEASURE_DATA) && (pHeaderInfo->ucCMD != m_ucCmd)) { strErr.Empty(); strErr.Format(_T("[%s][%d]recv response's cmd(%d) is not equal to ctrl's cmd(%d)"),MODULE_NAME, __LINE__, pHeaderInfo->ucCMD, m_ucCmd); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_RECV_DATA_DISORDER; } if (pHeaderInfo->Status_code != 0) { strErr.Empty(); strErr.Format(_T("[%s][%d]recv send cmd (%d) failed info from clound "),MODULE_NAME, __LINE__, pHeaderInfo->ucCMD); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_CLOUND_SND_FAILED; } if (m_ucDevType != pHeaderInfo->ucSrcType) { strErr.Empty(); strErr.Format(_T("[%s][%d]recv response's type(%d) is not equal to ctrl's dstType(%d)"),MODULE_NAME, __LINE__, pHeaderInfo->ucSrcType, m_ucDevType); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_RECV_DATA_DISORDER; } } //校验CRC BYTE ucCRc = BBCCalculate(chData, iHeaderSize-1, 0); if (wLen > iHeaderSize) ucCRc = BBCCalculate(pRcvData, wLen -iHeaderSize, ucCRc); BYTE ucRecvCRC = (wLen > iHeaderSize) ? *((BYTE*)(pRcvData + wLen -iHeaderSize)) : *(BYTE*)(chData+iHeaderSize-1); if (ucCRc != *((BYTE*)(pRcvData + wLen -iHeaderSize))) { strErr.Empty(); strErr.Format(_T("[%s][%d]CRC error, calucate_crc = %d, org_data_crc = %d"), MODULE_NAME, __LINE__, ucCRc, *((BYTE*)(pRcvData + wLen -iHeaderSize-1))); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_RECV_DATA_ERROR; } if ((EN_TRANSFER_FILE_BY_WIFI == g_iTransFileMode) && ( 0 == pHeaderInfo->ucCMD)) { // memcpy(pRcvData, ) *((WORD*)pRcvData) = htons(1); pRcvData[2] = EN_DEV_GD10; *((UINT*)(pRcvData+3)) = pHeaderInfo->ucSrcAddr; *pRcvLen = 7; } else { *((BYTE*)(pRcvData + wLen -iHeaderSize)) = 0; *pRcvLen = wLen -iHeaderSize; } if (iRet > 0) { return iRet; } return EN_RECV_SUCCESS; } else { wSkipByte += iHeaderSize; if (wSkipByte > MAX_SKIP_ERR_BYTES) { strErr.Empty(); strErr.Format(_T("[%s][%d] can not fouund pro_ctrl_id when skip max error bytes"), MODULE_NAME, __LINE__); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_RECV_DATA_ERROR; } Sleep(100); dwCostTick = GetTickCount() - dwTick; } } strErr.Empty(); strErr.Format(_T("[%s][%d]receive data packer timeout,max_time=%d"),MODULE_NAME, __LINE__,iRcvTimeout); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_RECV_TIMEOUT; } int CTransferCtrl::RecvRspMsg(char* pData, int* pLen, int iMaxLen,int iTimeout) { // if (m_ucCmd < 1) // { // AfxMessageBox(_T("There is no need to recv response because of empty cmd")); // return EM_RECV_FAILED; // } if (!GetConnectStatus()) { return EN_RECV_LINK_INTERRUPT; } int iRet; DWORD dwTicket = GetTickCount(); DWORD dwCostTicket = 0; memset(pData, 0, iMaxLen); while(dwCostTicket < iTimeout) { iRet = RecvCommRspMsg(pData, pLen, iMaxLen,iTimeout-dwCostTicket); //只有这三种情况立即返回,其他的都在继续获取数据,直到成功或者超时 if (EN_RECV_CTRL_CMD == iRet || EN_CLOUND_SND_FAILED == iRet || EN_RECV_SUCCESS == iRet) { return iRet; } dwCostTicket = GetTickCount()-dwTicket; } CString strErr = _T(""); strErr.Format(_T("[%s][%d]receive total response data timeout,max_time=%d"),MODULE_NAME, __LINE__,iTimeout); CFileOperTools::GetInstance()->WriteComLog(strErr); return EN_RECV_TIMEOUT; } int CTransferCtrl::RecvCtrlMsg( char* pData, int* pLen, int iMaxLen, int iTimeout) { if (!GetConnectStatus()) { return EN_RECV_LINK_INTERRUPT; } return RecvCommRspMsg(pData, pLen, iMaxLen,iTimeout,true); } // void CTransferCtrl::ClearCtrlInfo() // { // if (m_vtProCtrl.empty()) // { // return; // } // for (int i = 0; i < m_vtProCtrl.size(); i++) // { // if (m_vtProCtrl[i].lpData) // { // delete []m_vtProCtrl[i].lpData; // } // } // m_vtProCtrl.clear(); // } //DEL bool CTransferCtrl::StartWork() //DEL { //DEL if (!m_bIsInitialed) //DEL { //DEL AfxMessageBox(_T("please initiallize firstly.")); //DEL return false; //DEL } //DEL m_bIsRunning = true; //DEL m_pThread = AfxBeginThread(StartProcFunc,(LPVOID)this); //DEL if (NULL == m_pThread) //DEL { //DEL AfxMessageBox(_T("Create process data thread failed.")); //DEL return false; //DEL } //DEL return true; //DEL } bool CTransferCtrl::IsNeedSendCtrl() { return m_bIsNeedSendCtrMsg; } //DEL void CTransferCtrl::ShowStatusInfo(WORD wMsg, WORD wStatus) //DEL { //DEL if (m_pShowInfoCwnd) //DEL { //DEL m_pShowInfoCwnd->PostMessage(wStatus, wStatus); //DEL } //DEL //DEL } /* UINT CTransferCtrl::StartProcFunc(LPVOID lParam) { CTransferCtrl* pTransfer = (CTransferCtrl*)lParam; InitializeCriticalSection(&(pTransfer->m_MutexSec)); while (pTransfer->m_bIsRunning) { if (!pTransfer->GetConnectStatus()) { pTransfer->ShowStatusInfo(WM_CONNECT_STATUS, EN_STATUS_DISCONNECT); //隔30秒进行重连操作 Sleep(30000); if (!pTransfer->ReConnect()) { pTransfer->ShowStatusInfo(WM_CONNECT_STATUS, EN_STATUS_RECONNECT_FAIL); Sleep(10000); continue; } pTransfer->ShowStatusInfo(WM_CONNECT_STATUS, EN_STATUS_CONNECT_SUCCESS); } if (pTransfer->IsNeedSendCtrl()) { if (pTransfer->SendCtrlInfoToDev()) { int iRet = pTransfer->RecvRspMsg() } } } return 0; } */