📄 abcomms.cpp
字号:
break;
case ENG_STATE_RECEIVE :
// DLE STX ---> DST SRC CMD STS TNS TNS FNC CNT FIL ADDR ADDR [ADDR] .... DLE ETX CRC CRC
{
BYTE nodleBuffer[MAX_ABPORT_MESSAGELEN];
DWORD nodleLen;
BOOL valid;
if (m_noiseLength >= 2)
{
if (( m_noiseBuffer[0] == ALLENBRADLEY_DLE)&&
(m_noiseBuffer[1] == ALLENBRADLEY_ACK ))
{
RSDataMessage("GOT ACK: await remaining response.");
// strip these 2 chars
m_noiseLength-= 2;
memmove(m_noiseBuffer, &m_noiseBuffer[2], m_noiseLength);
memset(&m_noiseBuffer[m_noiseLength], 0xAA, 2);
}
}
// strip double DLE's
RemoveDLE(m_noiseBuffer, m_noiseLength, nodleBuffer, &nodleLen);
valid= (nodleLen >= minFrameLength);
if ((nodleLen >= minRESP_FrameLength/*12*/) && ((nodleBuffer[AB_COMMANDBYTEOFF] & 0x40)==0x40)) // command response
valid = TRUE;
if (valid)
{
CHAR ETXBuff[2];
BYTE *crcStartPtr;
WORD crc = 0;
WORD *crcPtr;
BYTE bccCode;
BYTE *bccPtr;
BOOL checksummingOK = FALSE;
//memcpy(&nodleBuffer[nodleLen], &m_receivedBuffer[m_noiseLength-2],2);
crcPtr = (WORD*)&nodleBuffer[nodleLen-2]; //skip the DLE STX
bccPtr = (BYTE*)&nodleBuffer[nodleLen-1];
crcStartPtr = (BYTE*)&nodleBuffer[2];
crc = 0;
CalcCRC(crcStartPtr, nodleLen-6, &crc); // Only one buffer to calc crc of
bccCode = CalcBCC(crcStartPtr, nodleLen-5);
// include the ETX, remember that the DLE gets ignored
ETXBuff[0] = 0x03;
CalcCRC((BYTE*)&ETXBuff[0], 1, &crc); // include the ETX
if (!m_useBCCchecks)
checksummingOK = (crc == *crcPtr);
else
checksummingOK = (bccCode == *bccPtr);
if (checksummingOK)
{
CABMessage msg(&nodleBuffer[2], nodleLen-2-4, FALSE);
ActivateStation((BYTE)nodleBuffer[AB_SOURCEBYTEOFF]);
ActivateStation((BYTE)nodleBuffer[AB_DESTINATIONBYTEOFF]);
if (pGlobalDialog->StationEnabled(msg.stationIDDest))
{
DWORD dataLength = nodleLen-2-4; // exclude the STX, ETX and CRC portions
// send an ACK, and process the message
RSDataMessage("ACK device message.");
Send(2, txDLE_ACK, FALSE, NULL);
if (pGlobalDialog->m_useBCC)
dataLength++;
BOOL result = OnMessageReceived(&nodleBuffer[2], dataLength ); //(-2-4)
// will do it's own SetEngineState(ENG_STATE_FINALACK);
}
else
{
CString message;
message.Format("Station %d is off-line, no response will be sent", msg.stationIDDest);
RSDataMessage(message);
SetEngineState(ENG_STATE_IDLE);
}
m_noiseLength = 0;
return (TRUE);
}
else
{
DWORD etxPos=-1;
DWORD stxPos = -1;
// try find a DLE-ETX
if (FindFragment(nodleBuffer, nodleLen, txDLE_ETX, 2, &etxPos))
if (etxPos+4 <= nodleLen)
{
FindFragment(nodleBuffer, nodleLen, txDLE_STX, 2, &stxPos);
if (stxPos < etxPos)
{ // prevent parsing of an STX occuring after an ETX
RSDataMessage("Cannot match STX-ETX framing, removing DLE-ETX.");
m_noiseLength-= etxPos+2;
// swallow all chars up to & including the DLE-ETX
memmove(m_noiseBuffer, &m_noiseBuffer[etxPos+2], m_noiseLength);
memset(&m_noiseBuffer[m_noiseLength], 0xAA, sizeof(m_noiseBuffer)-m_noiseLength);
SetEngineState(ENG_STATE_IDLE);
return(TRUE);
}
crcStartPtr = (BYTE*)&nodleBuffer[stxPos + 2];
crcPtr = (WORD*)&nodleBuffer[etxPos+2]; //skip the DLE STX
crc = 0;
bccCode = 0;
ASSERT(stxPos > etxPos); // Fix this possible - number
CalcCRC(crcStartPtr, etxPos-2- stxPos, &crc); // Only one buffer to calc crc of
bccCode = CalcBCC(crcStartPtr, etxPos-2- stxPos);
// include the ETX, remember that the DLE gets ignored
ETXBuff[0] = 0x03;
CalcCRC((BYTE*)&ETXBuff[0], 1, &crc); // include the ETX
if (!m_useBCCchecks)
checksummingOK = (crc == *crcPtr);
else
checksummingOK = (bccCode == *bccPtr);
if (checksummingOK)
{
ActivateStation((BYTE)nodleBuffer[AB_SOURCEBYTEOFF]);
ActivateStation((BYTE)nodleBuffer[AB_DESTINATIONBYTEOFF]);
// send an ACK, and process the message
RSDataMessage("ACK device message.");
Send(2, txDLE_ACK, FALSE, NULL);
BOOL result = OnMessageReceived(&nodleBuffer[2], nodleLen-2-4); //(-2-4) exclude the STX, ETX and CRC portions
// will do it's own SetEngineState(ENG_STATE_FINALACK);
//m_noiseLength = 0;
return (TRUE);
}
else
{ // kill this frame, I cannot match a CRC for it
if (FindFragment(m_noiseBuffer, m_noiseLength, txDLE_ETX, 2, &etxPos))
{
RSDataMessage("Skipping frame, cannot match the CRC.");
m_noiseLength-= etxPos+4;
memmove(m_noiseBuffer, &m_noiseBuffer[etxPos+4], m_noiseLength);
SetEngineState(ENG_STATE_IDLE);
return(TRUE);
}
}
}
}
}
}
return(TRUE);
break;
case ENG_STATE_FINALACK :
if (m_noiseLength >= 2)
{
if (( m_noiseBuffer[0] == ALLENBRADLEY_DLE)&&
(m_noiseBuffer[1] == ALLENBRADLEY_ACK ))
{
// strip these 2 chars
m_noiseLength-= 2;
memmove(m_noiseBuffer, &m_noiseBuffer[2], m_noiseLength);
// determine next state
SetEngineState(ENG_STATE_IDLE); //return to idle state
RSDataMessage("SEND: completed OK:");
if (m_noiseLength)
{
// process the leftover data/next request in our buffer
return(OnProcessData((char*)m_noiseBuffer, 0, discardData));
}
return TRUE;
}
// NAK
if (( m_noiseBuffer[0] == ALLENBRADLEY_DLE)&&
(m_noiseBuffer[1] == ALLENBRADLEY_NAK ))
{
m_messageNAKs++;
if (m_messageNAKs >= AB_MAXIMUM_NAKS)
{
RSDataMessage("Too many NAKs, will abort:");
Send(2, txDLE_ENQ, FALSE, NULL);
SetEngineState(ENG_STATE_IDLE); // wait for ACK again
m_noiseLength = 0;
return TRUE;
}
RSDataMessage("NAK, will re-send:");
SendPLCMessage(m_lastAppBuffer, m_lastAppLength);
SetEngineState(ENG_STATE_FINALACK); // wait for ACK again
m_noiseLength = 0;
return TRUE;
}
// strip the leading char from the noise buffer
RSDataMessage("Bad device final ACK response, restarting interpreter:");
SetEngineState(ENG_STATE_IDLE); //return to idle state
m_noiseLength = 0;
return(TRUE);
}
//wait for more data
return(FALSE);
break;
default:
return(TRUE);
break;
}
return(TRUE);
}
// ----------------------------- LoadRegisters -----------------------------
// load binary dump of the register values from file.
BOOL CABCommsProcessor::LoadRegisters()
{
CFileException ex;
CFile dat;
LONG area;
DWORD wordIndex;
if (!dat.Open("ABDATA.DAT", CFile::modeRead|CFile::shareDenyRead, &ex) )
{
// complain if an error happened
// no need to delete the exception object
TCHAR szError[1024];
ex.GetErrorMessage(szError, 1024);
OutputDebugString( "Couldn't open source file: ");
OutputDebugString( szError);
return FALSE;
}
// read it in
for (area=0;area < MAX_AB_MEMFILES ; area++)
{
DWORD numRead,totalRead=0;
WORD dataWord;
DWORD maxIndex = PLCMemory[area].GetSize();
// lock the memory for reading
// CMemWriteLock lk(pGlobalDialog->m_pMemWriteSync);
CMemWriteLock lk(PLCMemory.GetMutex());
// loop thru all registers (WORD)
if (!lk.IsLocked())
{
for (wordIndex=0; wordIndex < maxIndex/*MAX_MOD_MEMWORDS*/; wordIndex++)
{
numRead = dat.Read((BYTE*)&dataWord, sizeof(WORD));
PLCMemory.SetAt(area, wordIndex, dataWord);
totalRead +=numRead;
if (numRead != sizeof(WORD))
return FALSE;
}
// Read past the rest of the block
while (wordIndex < MAX_MOD_MEMWORDS)
{
numRead = dat.Read((BYTE*)&dataWord, sizeof(WORD));
totalRead +=numRead;
if (numRead != sizeof(WORD))
return FALSE;
wordIndex++;
}
}
else
{
CString errorMsg;
//error
errorMsg = "an error occured!";//errorMsg.LoadString(IDS_SYNC_READING);
AfxMessageBox(errorMsg, MB_ICONEXCLAMATION);
return FALSE;
}
}
return TRUE;
} // LoadRegisters
// --------------------------------------- SaveRegisters ---------------------------
// save a binary dump of the values to file.
BOOL CABCommsProcessor::SaveRegisters()
{
CFileException ex;
CFile dat;
LONG area;
DWORD wordIndex;
if (!dat.Open("ABDATA.DAT", CFile::modeWrite | CFile::shareExclusive | CFile::modeCreate, &ex) )
{
// complain if an error happened
// no need to delete the ex object
TCHAR szError[1024];
ex.GetErrorMessage(szError, 1024);
OutputDebugString( "Couldn't open source file: ");
OutputDebugString( szError);
return FALSE;
}
// read it in
for (area=0;area < MAX_AB_MEMFILES; area++)
{
WORD wordData;
DWORD maxIndex = PLCMemory[area].GetSize();
// lock the memory for writting
CMemWriteLock lk(PLCMemory.GetMutex());
// loop thru all registers (WORD)
if (!lk.IsLocked())
{
for (wordIndex=0; wordIndex < maxIndex/*MAX_MOD_MEMWORDS*/; wordIndex++)
{
wordData = PLCMemory[area][wordIndex];
dat.Write((BYTE*)&wordData, sizeof(WORD));
}
// Fill the rest with NULLs
while (wordIndex < maxIndex)
{
wordData = 0;
dat.Write((BYTE*)&wordData, sizeof(WORD));
wordIndex++;
}
}
else
{
CString errorMsg;
errorMsg = "an error occured!";//.LoadString(IDS_SYNC_WRITTING);
AfxMessageBox(errorMsg, MB_ICONEXCLAMATION);
// error
return FALSE;
}
}
return TRUE;
} // SaveRegisters
// ------------------------------------------ TestReceiveMessage -----------------------------
BOOL CABCommsProcessor::TestReceiveMessage()
{
return(FALSE);
}
// ----------------------------------------- OnMessageReceived -------------------------------
BOOL CABCommsProcessor::OnMessageReceived(BYTE * pAppMessage, DWORD length)
{
return(FALSE);
}
// --------------------------- RemoveDLE ----------------------------------
LONG CABCommsProcessor::RemoveDLE(const BYTE * buffer, DWORD len, BYTE * destBuff, DWORD *destLen)
{
DWORD dleCount=0;
BYTE *pSource, *pDest;
DWORD i=0;
pSource = (BYTE*)buffer;
pDest = destBuff;
*destLen = len;
while( i < len)
{
if ((*pSource == ALLENBRADLEY_DLE) && // Detect first DLE and post inc Ptr
// check if it's a double
(pSource[1] == ALLENBRADLEY_DLE))
{ // copy one of the doubled chars only
pSource++;
i++;
if (i < len)
{ // verify this was not the buffer end
*pDest++ = *pSource++;
i++;
dleCount++;
}
}
else
{ // copy char
*pDest++ = *pSource++;
i++;
}
}
// subtract the # of double-DLEs actually removed
*destLen -= dleCount;
return(dleCount);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -