using System; using System.Diagnostics; using System.IO; using System.Text; using NModbus.Logging; using NModbus.Utility; namespace NModbus.IO { /// /// Refined Abstraction - http://en.wikipedia.org/wiki/Bridge_Pattern /// internal class ModbusAsciiTransport : ModbusSerialTransport, IModbusAsciiTransport { internal ModbusAsciiTransport(IStreamResource streamResource, IModbusFactory modbusFactory, IModbusLogger logger) : base(streamResource, modbusFactory, logger) { Debug.Assert(streamResource != null, "Argument streamResource cannot be null."); } public override byte[] BuildMessageFrame(IModbusMessage message) { var msgFrame = message.MessageFrame; var msgFrameAscii = ModbusUtility.GetAsciiBytes(msgFrame); var lrcAscii = ModbusUtility.GetAsciiBytes(ModbusUtility.CalculateLrc(msgFrame)); var nlAscii = Encoding.UTF8.GetBytes(Modbus.NewLine.ToCharArray()); var frame = new MemoryStream(1 + msgFrameAscii.Length + lrcAscii.Length + nlAscii.Length); frame.WriteByte((byte)':'); frame.Write(msgFrameAscii, 0, msgFrameAscii.Length); frame.Write(lrcAscii, 0, lrcAscii.Length); frame.Write(nlAscii, 0, nlAscii.Length); return frame.ToArray(); } public override bool ChecksumsMatch(IModbusMessage message, byte[] messageFrame) { return ModbusUtility.CalculateLrc(message.MessageFrame) == messageFrame[messageFrame.Length - 1]; } public override byte[] ReadRequest() { return ReadRequestResponse(); } public override IModbusMessage ReadResponse() { return CreateResponse(ReadRequestResponse()); } internal byte[] ReadRequestResponse() { // read message frame, removing frame start ':' string frameHex = StreamResourceUtility.ReadLine(StreamResource).Substring(1); // convert hex to bytes byte[] frame = ModbusUtility.HexToBytes(frameHex); Logger.Trace($"RX: {string.Join(", ", frame)}"); if (frame.Length < 3) { throw new IOException("Premature end of stream, message truncated."); } return frame; } public override void IgnoreResponse() { ReadRequestResponse(); } } }