/// <summary> /// Initializes the request ADU and calculates the response length. /// </summary> public virtual void InitReqADU(byte devAddr, TransMode transMode) { if (ReqPDU == null) { return; } int pduLen = ReqPDU.Length; switch (transMode) { case TransMode.RTU: ReqADU = new byte[pduLen + 3]; ReqADU[0] = devAddr; Buffer.BlockCopy(ReqPDU, 0, ReqADU, 1, ReqPDU.Length); ushort crc = ModbusUtils.CRC16(ReqADU, 0, pduLen + 1); ReqADU[pduLen + 1] = (byte)(crc % 256); ReqADU[pduLen + 2] = (byte)(crc / 256); RespAduLen = RespPduLen + 3; break; case TransMode.ASCII: byte[] aduBuf = new byte[pduLen + 2]; aduBuf[0] = devAddr; Buffer.BlockCopy(ReqPDU, 0, aduBuf, 1, ReqPDU.Length); aduBuf[pduLen + 1] = ModbusUtils.LRC(aduBuf, 0, pduLen + 1); StringBuilder sbADU = new StringBuilder(); foreach (byte b in aduBuf) { sbADU.Append(b.ToString("X2")); } ReqADU = Encoding.ASCII.GetBytes(sbADU.ToString()); ReqStr = ModbusUtils.Colon + sbADU; RespAduLen = RespPduLen + 2; break; default: // TransModes.TCP ReqADU = new byte[pduLen + 7]; ReqADU[0] = 0; ReqADU[1] = 0; ReqADU[2] = 0; ReqADU[3] = 0; ReqADU[4] = (byte)((pduLen + 1) / 256); ReqADU[5] = (byte)((pduLen + 1) % 256); ReqADU[6] = devAddr; Buffer.BlockCopy(ReqPDU, 0, ReqADU, 7, ReqPDU.Length); RespAduLen = RespPduLen + 7; break; } }
/// <summary> /// Performs a request in the PDU mode. /// </summary> protected bool RtuRequest(DataUnit dataUnit) { bool result = false; // send request log.WriteLine(dataUnit.ReqDescr); Connection.Write(dataUnit.ReqADU, 0, dataUnit.ReqADU.Length, ProtocolFormat.Hex, out string logText); log.WriteLine(logText); // receive response // partial read to calculate PDU length const int FirstCount = 2; int readCnt = Connection.Read(InBuf, 0, FirstCount, Timeout, ProtocolFormat.Hex, out logText); log.WriteLine(logText); if (readCnt != FirstCount) { log.WriteLine(ModbusPhrases.CommErrorWithExclamation); } else if (InBuf[0] != dataUnit.ReqADU[0]) // validate device address { log.WriteLine(ModbusPhrases.IncorrectDevAddr); } else if (!(InBuf[1] == dataUnit.FuncCode || InBuf[1] == dataUnit.ExcFuncCode)) // validate function code { log.WriteLine(ModbusPhrases.IncorrectPduFuncCode); } else { int pduLen; int count; if (InBuf[1] == dataUnit.FuncCode) { pduLen = dataUnit.RespPduLen; count = dataUnit.RespAduLen - FirstCount; } else // exception received { pduLen = 2; count = 3; } // read rest of response readCnt = Connection.Read(InBuf, FirstCount, count, Timeout, ProtocolFormat.Hex, out logText); log.WriteLine(logText); if (readCnt != count) { log.WriteLine(ModbusPhrases.CommErrorWithExclamation); } else if (InBuf[pduLen + 1] + InBuf[pduLen + 2] * 256 != ModbusUtils.CRC16(InBuf, 0, pduLen + 1)) { log.WriteLine(ModbusPhrases.CrcError); } else if (dataUnit.DecodeRespPDU(InBuf, 1, pduLen, out string errMsg)) { log.WriteLine(ModbusPhrases.OK); result = true; } else { log.WriteLine(errMsg + "!"); } } return(result); }