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
}
}
}