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

📄 modethcommsprocessor.cpp

📁 mod_RSsim
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// CMODEthCommsProcessor.cpp: implementation of the Ethernet CMODEthCommsProcessor class.
//
// Ethernet:
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


#define MAX_MOD_MESSAGELENGTH  2048

// --------------------------------- PackASCIIField ------------------------------
void PackASCIIField(CHAR **pBuffer, WORD value, WORD length)
{
CHAR tempStr[80];
CHAR formatStr[80];

   // build a format string
   sprintf(formatStr, "%%0%dX", length);
   // plonk it in
   sprintf(tempStr, formatStr, value);
   strncpy(*pBuffer, tempStr, length);
   // increment pointer
   *pBuffer+=length;
   **pBuffer = '\0'; // add a null
}


// ------------------------- GetBCC ---------------------------------
// PURPOSE: Calculates a messages BCC value and returns it
// NOTE:
//    The message must be "[NNNNNNNN"
//    The bcc may be "cccc" or come from a valid message from the PLC.
//
LONG GetBCC(CHAR * bccString, DWORD msgLen)
{
LONG    accumulator = 0;

   return (accumulator);
} // GetBCC



//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// constructor to create listen socket
CMODEthCommsProcessor::CMODEthCommsProcessor(int responseDelay,
                                             BOOL MOSCADchecks,
                                             BOOL modifyThenRespond,
                                             BOOL disableWrites,
                                             LONG PDUSize,
                                             WORD portNum) : CDDKSrvSocket(portNum)
{
CString description;

   InitializeCriticalSection(&stateCS);
   description.Format("Starting comms emulation : %s", "MODBUS TCP/IP [host]");
   SockDataMessage(description);

   m_responseDelay = 0;
   m_linger = FALSE;

   m_responseDelay = responseDelay;
   SetPDUSize(PDUSize);

   SetEmulationParameters(MOSCADchecks, modifyThenRespond, disableWrites);
   m_pWorkerThread->ResumeThread(); //start thread off here

}

// constructor to re-use the listen socket
CMODEthCommsProcessor::CMODEthCommsProcessor(int responseDelay,
                                             BOOL  MOSCADchecks,
                                             BOOL modifyThenRespond,
                                             BOOL disableWrites,
                                             LONG PDUSize,
                                             SOCKET * pServerSocket) : CDDKSrvSocket(0, 0, pServerSocket)
{
   InitializeCriticalSection(&stateCS);
   m_responseDelay = 0;
   m_linger = FALSE;

   m_responseDelay = responseDelay;
   SetPDUSize(PDUSize);

   SetEmulationParameters(MOSCADchecks, modifyThenRespond, disableWrites);
   m_pWorkerThread->ResumeThread(); //start thread off here

}

CMODEthCommsProcessor::~CMODEthCommsProcessor()
{

}

// ------------------------------- SockDataMessage ------------------------------
void CMODEthCommsProcessor::SockDataMessage(LPCTSTR msg)
{
   EnterCriticalSection(&stateCS);
   OutputDebugString("##");
   if (NULL!=pGlobalDialog)
      pGlobalDialog->AddCommsDebugString(msg);
   LeaveCriticalSection(&stateCS);
}


// ------------------------------ SockDataDebugger ------------------------------
void CMODEthCommsProcessor::SockDataDebugger(const CHAR * buffer, LONG length, BOOL transmit)
{
   CRS232Port::GenDataDebugger((BYTE*)buffer, length, transmit);
   /*
CString debuggerString;
char *data;
byte hiNib,loNib;

   data = new char[(length*2)+1];
   for (int i = 0; i < length; i++)
   {
       hiNib = ( *(buffer+i) >>4) & 0x0f;
       loNib = ( *(buffer+i)    ) & 0x0f;
       data[(i*2)]   = ( (hiNib < 0x0A) ? ('0' + hiNib) : ('A' + hiNib-10) );
       data[(i*2)+1] = ( (loNib < 0x0A) ? ('0' + loNib) : ('A' + loNib-10) );
   }

   data[(length*2)] = '\0';
   // call the base class
   //CDDKSocket::SockDataDebugger(buffer, length, transmit);
   if (transmit)
   {
      if (length)
         pGlobalDialog->OnCharactersSent();
      debuggerString.Format("TX:%s\n", data);
   }
   else
   {
      if (length)
         pGlobalDialog->OnCharactersReceived();
      debuggerString.Format("RX:%s\n", data);
   }
   OutputDebugString(debuggerString);

   // Send to debugger list-box
   if (length)
      pGlobalDialog->AddCommsDebugString(debuggerString);

   delete (data);*/
} // SockDataDebugger

// ------------------------------- SockStateChanged -----------------------
void CMODEthCommsProcessor::SockStateChanged(DWORD state)
{
   EnterCriticalSection(&stateCS);
   if (NULL != pGlobalDialog)
      pGlobalDialog->m_ServerSocketState = state;

   LeaveCriticalSection(&stateCS);
} // SockStateChanged

// ------------------------------- ActivateStationLED ---------------------------
void CMODEthCommsProcessor::ActivateStationLED(LONG stationID)
{
   if (stationID>0 && stationID<STATIONTICKBOXESMAX)
   {
      //start the counter for this station at the beginning
      if (NULL != pGlobalDialog)
         pGlobalDialog->m_microTicksCountDown[stationID] = pGlobalDialog->GetAnimationOnPeriod();
      // it will count down untill it extinguishes
   }
} // ActivateStation

// ------------------------------- StationIsEnabled ---------------------------
// Return TRUE if station is enabled
BOOL CMODEthCommsProcessor::StationIsEnabled(LONG stationID)
{
   if (!pGlobalDialog)
      return(FALSE);
   if (stationID>0 && stationID<STATIONTICKBOXESMAX)
   {
      return (pGlobalDialog->StationEnabled(stationID));
   }
   return TRUE;
} // StationIsEnabled



// --------------------------------- ProcessData -----------------------------
BOOL CMODEthCommsProcessor::ProcessData(SOCKET openSocket, CHAR *pBuffer, DWORD numBytes)
{
CHAR  telegramBuffer[MAX_MOD_MESSAGELENGTH];
CHAR  responseBuffer[MAX_MOD_MESSAGELENGTH];
CHAR  debugStr[MAX_MOD_MESSAGELENGTH];
WORD  responseLen;
BYTE  *pDataPortion;
int   i=0;
//WORD  guardword1=1;
WORD  requestMemArea;   // telegram read/write are being referenced=0..MAX_MOD_MEMTYPES
//WORD  guardword2=2;
WORD  startRegister, endRegister, MBUSerrorCode=0;
BOOL  MBUSError = TRUE;
WORD  numBytesInReq;
WORD  numRegs;
CString deb;

   m_debuggerStep = 100;
   // inc counter
   pGlobalDialog->PacketsReceivedInc();

   responseBuffer[0] = '\0';

   // copy the Rx'd telegram neatly
   memcpy(telegramBuffer, pBuffer, numBytes);
   telegramBuffer[numBytes] = '\0';
   

   // simulate the I/O and network delays
   Sleep(m_responseDelay);
   if (pGlobalDialog->m_Unloading)
      return(TRUE);           // stop processing during shutdown of the socket array to allow easy closing.

   // parse the telegram

   // 1. break up the telegram
   CMODMessage::SetEthernetFrames();
   CMODMessage  modMsg(telegramBuffer, numBytes);

   //check the station #
   ActivateStationLED(modMsg.stationID);
   if (!StationIsEnabled(modMsg.stationID))
   {
   CString msg;
      // station off-line
      msg.Format("Station ID %d off-line, no response sent\n", telegramBuffer[6]);
      SockDataMessage(msg);
      return(TRUE);
   }
   // 2. parse 

   //Get memory area which to update or retrieve from
   requestMemArea = modMsg.GetAddressArea(modMsg.functionCode);//.type);
   if (requestMemArea >= MAX_MOD_MEMTYPES)
   {
      // TO DO!
      // handle the error
      Beep(2000,200);
      requestMemArea = 3;  // for now just default to "Holding" for now!
   }

   //
   // Validate that the request is a valid command code
   //
   startRegister = modMsg.address;
   //endRegister = startRegister + modMsg.byteCount/2;
   if (MOD_WRITE_SINGLE_COIL == modMsg.functionCode)
      endRegister = startRegister;
   else
      endRegister = startRegister + modMsg.byteCount;

   if ((modMsg.functionCode == MOD_READ_COILS)||      // 01
       (modMsg.functionCode == MOD_READ_DIGITALS)||   // 02
       (modMsg.functionCode == MOD_READ_REGISTERS)||  // 04
       (modMsg.functionCode == MOD_READ_HOLDING)||    // 03
       (modMsg.functionCode == MOD_READ_EXTENDED)||   // 14
       (modMsg.functionCode == MOD_WRITE_SINGLE_COIL)||     // 05
       (modMsg.functionCode == MOD_WRITE_MULTIPLE_COILS)||  // 0F
       (modMsg.functionCode == MOD_WRITE_HOLDING)||         // 10
       (modMsg.functionCode == MOD_WRITE_SINGLEHOLDING)||         // 06 (testing)
       (modMsg.functionCode == MOD_WRITE_EXTENDED)          // 15
      )
   {
      // Check the request length against our PDU size.
      switch (modMsg.functionCode)
      {
      case MOD_READ_COILS:      // 01
      case MOD_READ_DIGITALS:   // 02
         numBytesInReq = modMsg.byteCount/8; // # bits
         break;
      case MOD_WRITE_MULTIPLE_COILS:  // 0F
         numBytesInReq = (WORD)ceil(modMsg.byteCount/8); // # bits
         break;
      case MOD_WRITE_SINGLE_COIL:
         numBytesInReq = 1;
         break;
      default:
         numBytesInReq = modMsg.byteCount*2; // # registers
         break;
      }
      if (numBytesInReq > m_PDUSize)
      {
         MBUSError = TRUE;
         MBUSerrorCode = MOD_EXCEPTION_ILLEGALVALUE;   // too long data field
      }
      else
         MBUSError = FALSE;
   }
   else
   {
      MBUSError = TRUE;
      MBUSerrorCode = MOD_EXCEPTION_ILLEGALFUNC;   // 01
   }

   if (modMsg.m_packError)
   {
      // request message has a corrupted field somewhere
      MBUSError = TRUE;
      MBUSerrorCode = MOD_EXCEPTION_ILLEGALVALUE;   // too long data field
   }
   
   // 3. build response
   CMODMessage  responseModMsg(modMsg); //Call copy constructor

   //
   // Do some more message validation tests etc.
   //
   if (!MBUSError)
   {
      if ((m_MOSCADchecks)&& // Is a (Analog/holding/extended register)
          ((requestMemArea == 2)||(requestMemArea == 3)||(requestMemArea == 4))
         )
      {
      WORD startTable,endTable;     // table #

⌨️ 快捷键说明

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