using System.Diagnostics;
using System.IO;
using NModbus.Logging;
namespace NModbus.IO
{
///
/// Transport for Serial protocols.
/// Refined Abstraction - http://en.wikipedia.org/wiki/Bridge_Pattern
///
public abstract class ModbusSerialTransport : ModbusTransport, IModbusSerialTransport
{
private bool _checkFrame = true;
internal ModbusSerialTransport(IStreamResource streamResource, IModbusFactory modbusFactory, IModbusLogger logger)
: base(streamResource, modbusFactory, logger)
{
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 => _checkFrame;
set => _checkFrame = value;
}
public void DiscardInBuffer()
{
StreamResource.DiscardInBuffer();
}
public override void Write(IModbusMessage message)
{
DiscardInBuffer();
byte[] frame = BuildMessageFrame(message);
Logger.LogFrameTx(frame);
StreamResource.Write(frame, 0, frame.Length);
}
public override IModbusMessage CreateResponse(byte[] frame)
{
IModbusMessage response = base.CreateResponse(frame);
// compare checksum
if (CheckFrame && !ChecksumsMatch(response, frame))
{
string msg = $"Checksums failed to match {string.Join(", ", response.MessageFrame)} != {string.Join(", ", frame)}";
Logger.Warning(msg);
throw new IOException(msg);
}
return response;
}
public abstract void IgnoreResponse();
public abstract bool ChecksumsMatch(IModbusMessage message, byte[] messageFrame);
internal override void OnValidateResponse(IModbusMessage request, IModbusMessage response)
{
// no-op
}
}
}