Files
coco df489d5640 a
2026-07-03 16:05:30 +08:00

615 lines
18 KiB
C++

// 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;
}
*/