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

📄 mod232commsprocessor.cpp

📁 mod_RSsim
💻 CPP
📖 第 1 页 / 共 3 页
字号:
void CMOD232CommsProcessor::RSDataDebugger(const BYTE * buffer, LONG length, int transmit)
{
   CRS232Port::GenDataDebugger(buffer,length,transmit);
/*
CString debuggerString;
BYTE *data;
byte hiNib,loNib;

   //convert BIN-ary to ASCII for display
   data = new BYTE[(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';

   if (transmit)
   {
      if (length)
         pGlobalDialog->OnCharactersSent();
      debuggerString.Format("TX:%s\n", data);
   }
   else
   {
      if (length)
         pGlobalDialog->OnCharactersReceived();
      debuggerString.Format("RX:%s\n", data);
   }

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

#ifdef _COMMS_DEBUGGING
   OutputDebugString(debuggerString);
#endif

   delete (data);*/
} // RSDataDebugger

// ------------------------------- RSStateChanged -----------------------
void CMOD232CommsProcessor::RSStateChanged(DWORD state)
{
   EnterCriticalSection(&stateCS);
   if (NULL==pGlobalDialog)
      return;
   pGlobalDialog->m_ServerRSState = state;
   LeaveCriticalSection(&stateCS);
} // RSStateChanged

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

// ------------------------------- RSModemStatus ---------------------------
void CMOD232CommsProcessor::RSModemStatus(DWORD status)
{
   EnterCriticalSection(&stateCS);
   if (NULL!=pGlobalDialog)
      pGlobalDialog->OnModemStatusUpdate(status);
   LeaveCriticalSection(&stateCS);
}


// ------------------------------ OnProcessData --------------------------------
BOOL CMOD232CommsProcessor::OnProcessData(const CHAR *pBuffer, DWORD numBytes, BOOL *discardData)
{
   // build noise telegram
   if (numBytes)
   { //append recieved bytes to the noise telegram
      if (m_noiseLength + numBytes >= sizeof(m_noiseBuffer))
      {
         RSDataMessage("OVERFLOW:Restarting interpretation.");

         m_noiseLength = 0;
         //SetEngineState(ENG_STATE_IDLE);
         return(TRUE);
      }
      memcpy(&m_noiseBuffer[m_noiseLength], pBuffer, numBytes);
      m_noiseLength += numBytes;
      *discardData = TRUE;
   }

   if (m_noiseLength < MODBUS_NORMAL_LEN)
      return(FALSE);
   CMODMessage::SetEthernetFrames(FALSE);
   CMODMessage msg((char*)m_noiseBuffer, m_noiseLength);
   if (msg.CRCOK())
   {
   BOOL ret;
      // build a response etc
      ret = ProcessData((char*)m_noiseBuffer, msg.overalLen + 2);   //+2 for the CRC
      m_noiseLength = 0;
      return(ret);
   }
   else
   {
      // try strip away leading byte "noise"?
// comment out the following 2 lines, from spaccabbomm [beta@mmedia.it]
/*
      m_noiseLength--;
      memmove(m_noiseBuffer, &m_noiseBuffer[1], m_noiseLength);
*/
      return(TRUE);
   }
   *discardData = FALSE;
   return(FALSE);
}

// --------------------------------- TestMessage ------------------------
//
BOOL CMOD232CommsProcessor::TestMessage(CMODMessage &modMsg, 
                                        WORD &startRegister, 
                                        WORD &endRegister, 
                                        WORD &MBUSerrorCode,
                                        WORD &requestMemArea,
                                        WORD &numBytesInReq
                                        )
{
BOOL MBUSError = FALSE;

   if (!modMsg.CRCOK())
   {
      // bail
   }

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

   // validate the request is a valid command code
   startRegister = modMsg.address;
   //endRegister = startRegister + modMsg.byteCount;
   endRegister = startRegister + modMsg.byteCount/2;  // CDB rev 7.0

   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.
      if ((modMsg.functionCode == MOD_READ_COILS)||      // 01
          (modMsg.functionCode == MOD_READ_DIGITALS)||   // 02
          (modMsg.functionCode == MOD_WRITE_MULTIPLE_COILS))  // 0F
         numBytesInReq = modMsg.byteCount/8; // # bits
      else
         numBytesInReq = modMsg.byteCount*2; // # registers
      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

   if ((m_MOSCADchecks)&& // Is a (Analog/holding/extended register)
       ((requestMemArea == 2)||(requestMemArea == 3)||(requestMemArea == 4))
      )
   {
   WORD startTable,endTable;     // table #
   WORD startCol,endCol;         // col #
   
      endTable = MOSCADTABLENUMBER(endRegister); // MOSCAD specify register # on the wire for the formula
      endCol = MOSCADCOLNUMBER(endRegister);
      startTable = MOSCADTABLENUMBER(startRegister);
      startCol = MOSCADCOLNUMBER(startRegister);
      // test that this request does not bridge 2 columns.
      // , else we cannot job/request them together.
      if ((endTable != startTable) ||
          (endCol != startCol))
      {
         MBUSError = TRUE;
         MBUSerrorCode = MOD_EXCEPTION_ILLEGALADDR;   // 02
      }
   }
   
   // if we want to disable all writes
   if ((m_disableWrites) &&
       ((modMsg.functionCode == MOD_WRITE_SINGLE_COIL) ||
        (modMsg.functionCode == MOD_WRITE_SINGLEHOLDING) ||
        (modMsg.functionCode == MOD_WRITE_MULTIPLE_COILS) ||
        (modMsg.functionCode == MOD_WRITE_HOLDING) ||
        (modMsg.functionCode == MOD_WRITE_EXTENDED) 
       )
      )
   {
   CString deb;
      MBUSError = TRUE;
      MBUSerrorCode = MOD_EXCEPTION_ILLEGALFUNC;   // 02
      deb.Format("Writting to registers or I/O is disabled!\n");
      OutputDebugString(deb);
      RSDataMessage(deb);
   }
   
   // do a address+length range check too
   if (!MBUSError)
      if (PLCMemory[requestMemArea].GetSize() < endRegister)
      {
         MBUSError = TRUE;
         MBUSerrorCode = (PLCMemory[requestMemArea].GetSize() < startRegister ?
                             MOD_EXCEPTION_ILLEGALADDR:MOD_EXCEPTION_ILLEGALVALUE);   // 02
      }

   if (MBUSError)
   {
   CString msg;
      msg.Format("Modbus message in error x%02X\n", MBUSerrorCode);
      OutputDebugString(msg);
      RSDataMessage(msg);
   }
   return(MBUSError);
}


// --------------------------------- ProcessData -----------------------------
// Interpret MODBUS request pBuffer, and respond to it.
//
BOOL CMOD232CommsProcessor::ProcessData(const CHAR *pBuffer, DWORD numBytes)
{
BYTE  telegramBuffer[MAX_RX_MESSAGELENGTH+MODBUS_FRAME_LENGTH_MAX];
CHAR  debugStr[160];
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;
WORD  seperationOffset; // offset added to each address, due to stations having seperate reg.s
BOOL  MBUSError = TRUE;
WORD  numBytesInReq;
WORD  numRegs;
CString deb;

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

   // simulate the I/O and network delays of a real PLC
   Sleep(m_responseDelay);

   //
   // Parse the telegram
   //

   // 1. break up the telegram
   memcpy(telegramBuffer, pBuffer, numBytes);
   CMODMessage::SetEthernetFrames(FALSE);
   CMODMessage  modMsg((CHAR*)telegramBuffer, numBytes);
   
   ActivateStationLED(modMsg.stationID);
   if (!StationIsEnabled(modMsg.stationID))
      return(TRUE);

   // 2. parse it, by testing it first
   CMODMessage  responseModMsg(modMsg); //Call copy constructor


   MBUSError = TestMessage(modMsg, 
                           startRegister,  
                           endRegister,    
                           MBUSerrorCode,  
                           requestMemArea, 
                           numBytesInReq   
                          );
   if (pGlobalDialog->m_seperateRegisters)
   {
      seperationOffset = (WORD)(pGlobalDialog->m_numSeperate * modMsg.stationID);
      if ((PLCMemory[requestMemArea].GetSize() < seperationOffset+endRegister) ||
          (endRegister > pGlobalDialog->m_numSeperate))
      {
         MBUSError = TRUE;
         MBUSerrorCode = (PLCMemory[requestMemArea].GetSize() < seperationOffset + startRegister ?
                             MOD_EXCEPTION_ILLEGALADDR:MOD_EXCEPTION_ILLEGALVALUE);   // 02
      }
   }
   else
      seperationOffset = 0;

                        // 1st 3 bytes + any others up to data get 
                        // added in at this time 
   responseModMsg.BuildMessagePreamble(MBUSError,
                                       MBUSerrorCode); 

   // A read must now pack into dataPtr onwards! and calc len etc!
   //   writes must update our mem areas accordingly.
   if (!MBUSError)
   {
      // 4. fill in the data portion of telegram
      switch (modMsg.functionCode)
      {
      case MOD_READ_COILS     : // 01 READ
      case MOD_READ_DIGITALS  : // 02 READ
         pDataPortion = responseModMsg.dataPtr; //Get offset to fill in data
         if (MAX_MOD_MEMWORDS >= modMsg.address + modMsg.byteCount)
         {
         WORD memValueTemp;
         WORD bitOffset;

            deb.Format("Read In/output from %d for %d bits.\n", modMsg.address, modMsg.byteCount);
            OutputDebugString(deb);
            RSDataMessage(deb);

            // pack SIM memory: one WORD of sim memory for every BIT in the data.
            // Ie the sim uses one word for each I/O bit in modbus.
            numBytesInReq = modMsg.byteCount/8;
            if (modMsg.byteCount%8)  // if we overflow the byte
               numBytesInReq++;
            for (i=0; i <numBytesInReq;i++)
            {
               // grab the memory now
               memValueTemp = 0;
               for (bitOffset=0;bitOffset<8;bitOffset++)
               {
                  if ((i*8)+bitOffset < modMsg.byteCount)
                     if (PLCMemory[requestMemArea][(seperationOffset + modMsg.address)+(i*8)+bitOffset])
                        memValueTemp += (0x01<<bitOffset);
                     // else bit is off
               }
               *(BYTE*)pDataPortion =  (BYTE)memValueTemp;
               pDataPortion +=1;
            }

         }
         else
         {
            // pack the exception code into the message
            ASSERT(0); // this is supposed to be caught in TestMessage()
            responseModMsg.buffer[1] |= 0x80;
            responseModMsg.buffer[2] = 0x02;    // exception code here (could also use 0x03)
         }
         break;

      case MOD_READ_REGISTERS : 
      case MOD_READ_HOLDING   :
      case MOD_READ_EXTENDED  :

⌨️ 快捷键说明

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