/// <summary> /// Инициализировать ADU запроса и рассчитать длину ответа /// </summary> public virtual void InitReqADU(byte devAddr, TransModes transMode) { if (ReqPDU != null) { int pduLen = ReqPDU.Length; switch (transMode) { case TransModes.RTU: ReqADU = new byte[pduLen + 3]; ReqADU[0] = devAddr; ReqPDU.CopyTo(ReqADU, 1); ushort crc = ModbusUtils.CalcCRC16(ReqADU, 0, pduLen + 1); ReqADU[pduLen + 1] = (byte)(crc % 256); ReqADU[pduLen + 2] = (byte)(crc / 256); RespAduLen = RespPduLen + 3; break; case TransModes.ASCII: byte[] aduBuf = new byte[pduLen + 2]; aduBuf[0] = devAddr; ReqPDU.CopyTo(aduBuf, 1); aduBuf[pduLen + 1] = ModbusUtils.CalcLRC(aduBuf, 0, pduLen + 1); StringBuilder sbADU = new StringBuilder(); foreach (byte b in aduBuf) { sbADU.Append(b.ToString("X2")); } ReqADU = Encoding.Default.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; ReqPDU.CopyTo(ReqADU, 7); RespAduLen = RespPduLen + 7; break; } } }
/// <summary> /// Выполнить запрос в режиме RTU /// </summary> public bool RtuRequest(DataUnit dataUnit) { if (!CheckConnection()) { return(false); } bool result = false; // отправка запроса ExecWriteToLog(dataUnit.ReqDescr); Connection.Write(dataUnit.ReqADU, 0, dataUnit.ReqADU.Length, CommUtils.ProtocolLogFormats.Hex, out string logText); ExecWriteToLog(logText); // приём ответа // считывание начала ответа для определения длины PDU int readCnt = Connection.Read(InBuf, 0, 5, Timeout, CommUtils.ProtocolLogFormats.Hex, out logText); ExecWriteToLog(logText); if (readCnt == 5) { int pduLen; int count; if (InBuf[0] != dataUnit.ReqADU[0]) // проверка адреса устройства в ответе { ExecWriteToLog(ModbusPhrases.IncorrectDevAddr); } else if (!(InBuf[1] == dataUnit.FuncCode || InBuf[1] == dataUnit.ExcFuncCode)) { ExecWriteToLog(ModbusPhrases.IncorrectPduFuncCode); } else { if (InBuf[1] == dataUnit.FuncCode) { // считывание окончания ответа pduLen = dataUnit.RespPduLen; count = dataUnit.RespAduLen - 5; readCnt = Connection.Read(InBuf, 5, count, Timeout, CommUtils.ProtocolLogFormats.Hex, out logText); ExecWriteToLog(logText); } else // устройство вернуло исключение { pduLen = 2; count = 0; readCnt = 0; } if (readCnt == count) { if (InBuf[pduLen + 1] + InBuf[pduLen + 2] * 256 == ModbusUtils.CalcCRC16(InBuf, 0, pduLen + 1)) { // расшифровка ответа string errMsg; if (dataUnit.DecodeRespPDU(InBuf, 1, pduLen, out errMsg)) { ExecWriteToLog(ModbusPhrases.OK); result = true; } else { ExecWriteToLog(errMsg + "!"); } } else { ExecWriteToLog(ModbusPhrases.CrcError); } } else { ExecWriteToLog(ModbusPhrases.CommErrorWithExclamation); } } } else { ExecWriteToLog(ModbusPhrases.CommErrorWithExclamation); } return(result); }
/// <summary> /// Run RTU query /// </summary> public bool RtuRequest(DataUnit dataUnit) { if (!CheckConnection()) { return(false); } var result = false; // sending request ExecWriteToLog(dataUnit.ReqDescr); Connection.Write(dataUnit.ReqADU, 0, dataUnit.ReqADU.Length, CommUtils.ProtocolLogFormats.Hex, out string logText); ExecWriteToLog(logText); // reception of the answer // reading the start of the response to determine the length of the PDU int readCnt = Connection.Read(InBuf, 0, 5, Timeout, CommUtils.ProtocolLogFormats.Hex, out logText); ExecWriteToLog(logText); if (readCnt == 5) { int pduLen; int count; if (InBuf[0] != dataUnit.ReqADU[0]) // checking device address in response { ExecWriteToLog(ModbusPhrases.IncorrectDevAddr); } else if (!(InBuf[1] == dataUnit.FuncCode || InBuf[1] == dataUnit.ExcFuncCode)) { ExecWriteToLog(ModbusPhrases.IncorrectPduFuncCode); } else { if (InBuf[1] == dataUnit.FuncCode) { // read end of response pduLen = dataUnit.RespPduLen; count = dataUnit.RespAduLen - 5; readCnt = Connection.Read(InBuf, 5, count, Timeout, CommUtils.ProtocolLogFormats.Hex, out logText); ExecWriteToLog(logText); } else // device returned exception { pduLen = 2; count = 0; readCnt = 0; } if (readCnt == count) { if (InBuf[pduLen + 1] + InBuf[pduLen + 2] * 256 == ModbusUtils.CalcCRC16(InBuf, 0, pduLen + 1)) { // answer decryption string errMsg; if (dataUnit.DecodeRespPDU(InBuf, 1, pduLen, out errMsg)) { ExecWriteToLog(ModbusPhrases.OK); result = true; } else { ExecWriteToLog(errMsg + "!"); } } else { ExecWriteToLog(ModbusPhrases.CrcError); } } else { ExecWriteToLog(ModbusPhrases.CommErrorWithExclamation); } } } else { ExecWriteToLog(ModbusPhrases.CommErrorWithExclamation); } return(result); }