using System; using System.Diagnostics; using System.Globalization; using System.IO; using log4net; using Modbus.Message; using Modbus.Utility; namespace Modbus.IO { /// /// Transport for Serial protocols. /// Refined Abstraction - http://en.wikipedia.org/wiki/Bridge_Pattern /// public abstract class ModbusSerialTransport : ModbusTransport { private static readonly ILog _logger = LogManager.GetLogger(typeof(ModbusSerialTransport)); private bool _checkFrame = true; internal ModbusSerialTransport(IStreamResource streamResource) : base(streamResource) { Debug.Assert(streamResource != null, "Argument streamResource cannot be null."); } /// /// Gets or sets a value indicating whether LRC/CRC frame checking is performed on messages. /// public bool CheckFrame { get { return _checkFrame; } set { _checkFrame = value; } } internal void DiscardInBuffer() { StreamResource.DiscardInBuffer(); } internal override void Write(IModbusMessage message) { DiscardInBuffer(); byte[] frame = BuildMessageFrame(message); _logger.InfoFormat("TX: {0}", StringUtility.Join(", ", frame)); StreamResource.Write(frame, 0, frame.Length); } internal override IModbusMessage CreateResponse(byte[] frame) { IModbusMessage response = base.CreateResponse(frame); // compare checksum if (CheckFrame && !ChecksumsMatch(response, frame)) { string errorMessage = String.Format(CultureInfo.InvariantCulture, "Checksums failed to match {0} != {1}", StringUtility.Join(", ", response.MessageFrame), StringUtility.Join(", ", frame)); _logger.Error(errorMessage); throw new IOException(errorMessage); } return response; } internal abstract bool ChecksumsMatch(IModbusMessage message, byte[] messageFrame); internal override void OnValidateResponse(IModbusMessage request, IModbusMessage response) { // no-op } } }