⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 message.cpp

📁 mod_RSsim
💻 CPP
字号:
/////////////////////////////////////////////////////////////////////////////
//
// FILE: Message.cpp : file
//
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "abcommsprocessor.h"
#include "message.h"

// English meanings for Allen-Bradley (Exception) error codes
PCHAR plcErrorLocal[9] =     // local STS (low nibble)
{
   "No error",                            // 0x0
   "DST node out of buffer space",        // 0x1
   "Cannot guarantee delivery",           // 0x2
   "Duplicate token holder detected",     // 0x3
   "Local port is disconnected",          // 0x4
   "Application layer timed out waiting for response",             // 0x5
   "Duplicate node detected",             // 0x6
   "Station is offline",                  // 0x7
   "Hardware fault"                       // 0x8
};  

PCHAR plcErrorRemote[16] =     // remote STS (high nibble)
{
   "No error",                               // 0x00
   "Illegal command or format",              // 0x10
   "Host has a problem and will not comm.",                       // 0x20
   "Remote node host is missing,",                                // 0x30
   "Host could not complete function due to h/w fault",           // 0x40
   "Addressing problem or memory protect rungs",                  // 0x50
   "Function not allowed due to command protection selection",    // 0x60
   "Processor is in program mode",                                // 0x70
   "Compatibility mode file missing or comm. zone problem",       // 0x80
   "Remote node cannot buffer command",              // 0x90
   "xxxx",              // 0xA0
   "Remote node problem due to download",              // 0xB0
   "xxxx",              // 0xC0
   "unused",              // 0xD0
   "unused",              // 0xE0
   "Error code is in EXT-STS"              // 0xF0
};  


// Global - Global data
BYTE txDLE_STX[SIZEOF_TAIL] =
{
   ALLENBRADLEY_DLE,
   ALLENBRADLEY_STX
};

BYTE txDLE_ACK[SIZEOF_TAIL] =
{
   ALLENBRADLEY_DLE,
   ALLENBRADLEY_ACK
};

BYTE txDLE_NAK[SIZEOF_TAIL] =
{
   ALLENBRADLEY_DLE,
   ALLENBRADLEY_NAK
};

BYTE txDLE_ETX[SIZEOF_TAIL] =
{
   ALLENBRADLEY_DLE,
   ALLENBRADLEY_ETX
};

BYTE txDLE_ENQ[SIZEOF_TAIL] =
{
   ALLENBRADLEY_DLE,
   ALLENBRADLEY_ENQ
};

// -------------------------------- CalcBCC ----------------------------
// Calculate Allen-Bradley specified BCC code
// the BCC is a 2'scomp sum of all bytes in the message frame excluding DLE-STX and DLE-ETX
BYTE CalcBCC(BYTE * lrcBuffPtr,    //  -> pointer to buffer at start of BCC
             DWORD  buffLen        //  -> 
            )
{
BYTE bcc=0;

   CalcLRC(lrcBuffPtr,    //  -> pointer to buffer at start of LRC
           buffLen,       //  -> 
           FALSE,     //  -> Calc 2's Compliment also (last call)
           &bcc            // <-> 
            );
   bcc = 256-bcc;
   return(bcc);
} // CalcBCC


/////////////////////////////////////////////////////////////////////////////////
// CProtocolMessage implementation
/////////////////////////////////////////////////////////////////////////////////
CProtocolMessage::CProtocolMessage(const BYTE * pMessageRX, DWORD len)
{

}
CProtocolMessage::CProtocolMessage(const CProtocolMessage & oldProtMessage)
{ //copy constructor

}



/////////////////////////////////////////////////////////////////////////////////
// CABMessage implementation
/////////////////////////////////////////////////////////////////////////////////


// ----------------------- constructor -----------------------------------
CABMessage::CABMessage(const BYTE * pMessageRX, DWORD len, BOOL dataLayer) 
      : CProtocolMessage(pMessageRX, len)
{
BYTE *crcStartPtr = (BYTE*)pMessageRX;
WORD  crc = 0;
BYTE bcc;
WORD *crcPtr;
WORD *bccPtr;
DWORD appStartOffset = 2; // data layer telegram
DWORD addressWidth, elementWidth;

   transactionID = -1;
   transmissionStatus = 0;
   transmissionStatusEXT = 0;
   if (!dataLayer)
   {
      appStartOffset=0; // this is an app layer telegram
      len+=2;
   }
   ASSERT(len > 2);
   ASSERT(len < sizeof(buffer)); 
   memset(buffer, 0xCD, sizeof(buffer));
   memcpy(&buffer[2], &pMessageRX[appStartOffset], len);

   // double DLE stripping here
   if (dataLayer)
      StripDLEs(buffer, &len);
   totalLen = (WORD)len;

   // at this point we have a data layer message
   crcCheckedOK = FALSE;

   // break down the msg
   count = 0;
   if ((len>2) && (dataLayer))
   {
      if (buffer[0] != ALLENBRADLEY_DLE)
         return;
      if ((buffer[1] != ALLENBRADLEY_SOH )&&
          (buffer[1] != ALLENBRADLEY_STX )&&
          (buffer[1] != ALLENBRADLEY_ACK )&&
          (buffer[1] != ALLENBRADLEY_NAK )&&
          (buffer[1] != ALLENBRADLEY_ENQ )
         )
         return;
      // we seem to have the beginning of the message, parse it
   }
   if (len > 3)
   {
      stationIDDest = (BYTE)buffer[AB_SOURCEBYTEOFF];          // Dest addr
      stationIDSource = (BYTE)buffer[AB_DESTINATIONBYTEOFF];   // Source addr
   }
   if (len >4)
      command = buffer[AB_COMMANDBYTEOFF];       // may be 0x0F other values are not processed
   if (len >5)
      transmissionStatus = buffer[AB_STATUSBYTEOFF];
   if (len >=7)
   {
      transactionID = (buffer[6]) + (buffer[7]<<8);
   }
   if (len >8)
      functionCode = buffer[8];
   if (len > 9)
      count = (BYTE)buffer[9];   // # bytes to be read (/2 to get integers)
   if (len > 10)
      fileNum = (BYTE)buffer[10];
   if (len >11)
      fileType = (BYTE)buffer[11];
   addressWidth = 1;
   elementWidth = 1;
   if (len >12)
   {
      address = (BYTE)buffer[12];
      if (address == 0xFF)
      {
         addressWidth=3;
         address = buffer[12+1] + (buffer[13+1]<<8);
         address = SwapBytes(address);
      }
   }
   if (len >=(13+addressWidth))   // 14
   {
      subElement = buffer[12+addressWidth];
      if (subElement == 0xFF)
      {
         elementWidth=3;
         subElement = buffer[12+addressWidth+1] + (buffer[13+addressWidth+1]<<8);
         subElement = SwapBytes(subElement);
      }

   }
   if (len >=(13+addressWidth+elementWidth))  // 15
      dataPtr = (BYTE*)&buffer[12+addressWidth+elementWidth];

   if (dataLayer) // app messages will not have a CRC byte anyway
   {
      //check the CRC at this point
      if (pGlobalDialog->m_useBCC)
      {
         if (len >= 17)
         {
            bccPtr = (WORD*)&buffer[totalLen-1];//count + 16];
            crcStartPtr = (BYTE*)&buffer[2];

            bcc = CalcBCC(crcStartPtr, totalLen-6);      // Only one buffer to calc crc of
            overalLen = count+16 + AB_BCC_LEN;
            crcCheckedOK = (bcc==*bccPtr);
         }
      }
      else
      {
         if (len >= 18)
         {
         CHAR ETXBuff[2];
            crcPtr = (WORD*)&buffer[totalLen-2];//count + 16];
            crcStartPtr = (BYTE*)&buffer[2];

            crc = 0x0;
            CalcCRC(crcStartPtr, totalLen-6, &crc);      // Only one buffer to calc crc of
            ETXBuff[0] = 0x03;
            CalcCRC((BYTE*)&ETXBuff[0], 1, &crc);      // include the ETX
            overalLen = count+16 + AB_CRC_LEN;
            crcCheckedOK = (crc==*crcPtr);
         }
      }
   }

   if (!crcCheckedOK)
      return;
   else
   {
      crc = 0xffff;
   }
} // CABMessage

// --------------------------- CABMessage --------------------------
// PURPOSE: copy constructor used to build responses, does not actually 
// copy the message.
CABMessage::CABMessage(const CABMessage & oldABMessage) 
    : CProtocolMessage(oldABMessage)
{
      memset(buffer, 0xCD, sizeof(buffer));
      //Copy in common stuff from both messages here!
      m_localStationID = oldABMessage.m_localStationID;
      stationIDSource    = oldABMessage.stationIDSource;
      stationIDDest    = oldABMessage.stationIDDest;
      functionCode = oldABMessage.functionCode;
      fileType = oldABMessage.fileType;
      address = oldABMessage.address;       // where to copy data from
      byteCount = oldABMessage.byteCount;   // length of data to copy
      
      overalLen = 0;   //New message so 0 for now!
      
      dataPtr = (BYTE*)buffer; //Nice a fresh pointer to the beginning!
}

// ------------------------- CalculateReadAheadLength -------------------------
// static function
WORD CABMessage::CalculateReadAheadLength(const BYTE*pBuffer, DWORD length)
{
   //if (length < 2)
   //   return(2);  // DLE ACK/NAK or DLE/STX in our case
   // look at the rest of the telegram
   return(1);
} // CalculateReadAheadLength

// -------------------------------- Status ----------------------------
// static function
BOOL CABMessage::Status(const BYTE*pBuffer, DWORD length)
{
   if (length >6)
      return(pBuffer[5]);  // STS byte

   return(FALSE);
} // CalculateReadAheadLength

// ------------------------------- GetValue -------------------------
//
WORD CABMessage::GetValue(WORD wIndex)
{
WORD *pData = (WORD*)dataPtr;
   pData+=wIndex;
   return(*pData);
}

// ------------------------------- StripDLEs ------------------------
LONG CProtocolMessage::StripDLEs(CHAR *bufferPtr, DWORD *numBytes)
{
char *pSourceData= bufferPtr;
char *pDestData = bufferPtr;
BOOL stripDLE = FALSE;
int count = *numBytes;
int bytesXferred=0;
int dleCount = 0;
   //if (*numBytes <= 20)
      return(0);
   while (count>0)
   {
      if (*pSourceData == 0x10)  // if current byte is a DLE
         stripDLE = TRUE;        // flag that byte was a DLE
      else
         stripDLE = FALSE;
      // copy current byte
      *pDestData++ = *pSourceData++;
      bytesXferred++;

      if ((stripDLE)&&(*pSourceData == 0x10))
      {
         *pSourceData++;   // skip the byte and clear the flag
         dleCount++;
         count--;
         stripDLE = FALSE;
      }
      count--;
   }
   *numBytes = bytesXferred;
   return(dleCount);
}


// ------------------------------ BuildMessagePreamble -------------------------
// PURPOSE: Builds the STN,FN and LEN bytes of the telegram.
// on completion dataPtr pointsto where the data must be packed in (if any)
CHAR * CABMessage::BuildMessagePreamble(BOOL error, WORD errorCode)
{
WORD  crc = 0;
WORD  dataLength=6;

   // swap the station IDs
   buffer[2] = stationIDSource;
   buffer[3] = stationIDDest;
   //
   buffer[AB_COMMANDBYTEOFF] |= 0x40;    // CMD byte
   buffer[5] = (BYTE)errorCode; // STS byte
   if (error)
   {
      buffer[8] = (BYTE)(errorCode>>8); //EXT-STS
      dataLength++;
   }
   // byte 6 & 7 contain the sender's TNS value
   byteCount = 0;
   totalLen = dataLength + 6;//13;  6+6=12 bytes

   return(buffer);
} // BuildMessagePreamble

  /*
// ------------------------------ BuildMessageEnd -------------------------------
// PURPOSE: glue a CRC onto the end of the message
// totalLen must be = the full telegram length (+CRC) when this is called.
CHAR * CABMessage::BuildMessageEnd()
{
WORD length;
BYTE *pCrcStart = (BYTE*)buffer;
WORD crc = 0xFFFF;
BYTE *crcPtr;

   // Add the CRC bytes
   length = totalLen - AB_CRC_LEN; //calc the CRC of all bytes but the 2 CRC bytes

   CalcCRC(pCrcStart, length, &crc);
   crcPtr = (BYTE*)&buffer[length];
   *(WORD *)crcPtr = crc;

   return (buffer);
} // BuildMessageEnd
*/

// ------------------------------ GetAddressArea --------------------
// Returns:    A supported MEM area index for any MOD address class
// Parameter:  A modbus command (e.g. 3 =read holding register)
//
WORD CABMessage::GetAddressArea(WORD classCode //  modbus command byte
                                )
{
   /*
   switch(classCode)
   {
      // read commands 
      case MOD_READ_COILS     : return(0); break;
      case MOD_READ_DIGITALS  : return(1); break;
      case MOD_READ_REGISTERS : return(2); break;   
      case MOD_READ_HOLDING   : return(3); break;
      case MOD_READ_EXTENDED  : return(4); break;
      // write commands      
      case MOD_WRITE_HOLDING        : return(3); break;
      case MOD_WRITE_SINGLEHOLDING  : return(3); break;
      case MOD_WRITE_SINGLE_COIL    : return(0); break;
      case MOD_WRITE_MULTIPLE_COILS : return(0); break;
      case MOD_WRITE_EXTENDED       : return(4); break;
   }
   */
   return(3); //Default here for now, Should never get here anyways!

} // GetAddressArea

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -