Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
Apollo3zehn committed Nov 14, 2022
2 parents e320608 + 8d82367 commit 2485395
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 16 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## v5.0.1 - 2022-11-14

### Bugs Fixed

- The Modbus server did not correctly detect request frames (thanks @jmsqlr, https://github.com/Apollo3zehn/FluentModbus/pull/75#issuecomment-1304653670)

## v5.0.0 - 2022-09-08

### Breaking Changes
Expand Down
6 changes: 5 additions & 1 deletion src/FluentModbus/Client/ModbusRtuClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ protected override Span<byte> TransceiveFrame(byte unitIdentifier, ModbusFunctio
frameLength += _serialPort!.Value.Value
.Read(_frameBuffer.Buffer, frameLength, _frameBuffer.Buffer.Length - frameLength);

if (ModbusUtils.DetectFrame(unitIdentifier, _frameBuffer.Buffer.AsMemory().Slice(0, frameLength)))
if (ModbusUtils.DetectResponseFrame(unitIdentifier, _frameBuffer.Buffer.AsMemory().Slice(0, frameLength)))
{
break;
}
Expand Down Expand Up @@ -230,6 +230,7 @@ protected override Span<byte> TransceiveFrame(byte unitIdentifier, ModbusFunctio

private bool _disposedValue;

/// <inheritdoc />
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
Expand All @@ -243,6 +244,9 @@ protected virtual void Dispose(bool disposing)
}
}

/// <summary>
/// Disposes the current instance.
/// </summary>
public void Dispose()
{
Dispose(disposing: true);
Expand Down
2 changes: 1 addition & 1 deletion src/FluentModbus/Client/ModbusRtuClientAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ protected override async Task<Memory<byte>> TransceiveFrameAsync(byte unitIdenti
{
frameLength += await _serialPort!.Value.Value.ReadAsync(_frameBuffer.Buffer, frameLength, _frameBuffer.Buffer.Length - frameLength, cancellationToken).ConfigureAwait(false);

if (ModbusUtils.DetectFrame(unitIdentifier, _frameBuffer.Buffer.AsMemory().Slice(0, frameLength)))
if (ModbusUtils.DetectResponseFrame(unitIdentifier, _frameBuffer.Buffer.AsMemory().Slice(0, frameLength)))
{
break;
}
Expand Down
4 changes: 3 additions & 1 deletion src/FluentModbus/Client/ModbusTcpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,9 @@ protected virtual void Dispose(bool disposing)
}
}

/// <inheritdoc />
/// <summary>
/// Diposes the current instance.
/// </summary>
public void Dispose()
{
Dispose(disposing: true);
Expand Down
4 changes: 0 additions & 4 deletions src/FluentModbus/FluentModbus.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@
</None>
</ItemGroup>

<ItemGroup>
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="5.0.0" />
</ItemGroup>

<ItemGroup>
<Compile Update="Client\ModbusClientAsync.cs">
<DesignTime>True</DesignTime>
Expand Down
25 changes: 19 additions & 6 deletions src/FluentModbus/ModbusRtuSerialPort.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace FluentModbus
{
/// <summary>
/// A wrapper for a <see cref="SerialPort" />.
/// </summary>
public class ModbusRtuSerialPort : IModbusRtuSerialPort
{
#region Fields
Expand All @@ -12,6 +15,10 @@ public class ModbusRtuSerialPort : IModbusRtuSerialPort

#region Constructors

/// <summary>
/// Initializes a new instances of the <see cref="ModbusRtuSerialPort" /> class.
/// </summary>
/// <param name="serialPort">The serial port to wrap.</param>
public ModbusRtuSerialPort(SerialPort serialPort)
{
_serialPort = serialPort;
Expand All @@ -21,8 +28,14 @@ public ModbusRtuSerialPort(SerialPort serialPort)

#region Properties

/// <summary>
/// Gets the port for communications.
/// </summary>
public string PortName => _serialPort.PortName;

/// <summary>
/// Gets a value indicating the open or closed status of the <see cref="ModbusRtuSerialPort" /> object.
/// </summary>
public bool IsOpen => _serialPort.IsOpen;

#endregion
Expand All @@ -49,8 +62,8 @@ public void Close()
/// Reads from the <see cref="SerialPort"/> input buffer.
/// </summary>
/// <param name="buffer">The byte array to write the input to.</param>
/// <param name="offset">The offset in <see cref="buffer"/> at which to write the bytes.</param>
/// <param name="count">The maximum number of bytes to read. Fewer bytes are read if <see cref="count"/> is greater than the number of bytes in the input buffer.</param>
/// <param name="offset">The offset in <paramref name="buffer"/> at which to write the bytes.</param>
/// <param name="count">The maximum number of bytes to read. Fewer bytes are read if <paramref name="count"/> is greater than the number of bytes in the input buffer.</param>
/// <returns>The number of bytes read.</returns>
public int Read(byte[] buffer, int offset, int count)
{
Expand All @@ -61,8 +74,8 @@ public int Read(byte[] buffer, int offset, int count)
/// Asynchronously reads from the <see cref="SerialPort"/> input buffer.
/// </summary>
/// <param name="buffer">The byte array to write the input to.</param>
/// <param name="offset">The offset in <see cref="buffer"/> at which to write the bytes.</param>
/// <param name="count">The maximum number of bytes to read. Fewer bytes are read if <see cref="count"/> is greater than the number of bytes in the input buffer.</param>
/// <param name="offset">The offset in <paramref name="buffer"/> at which to write the bytes.</param>
/// <param name="count">The maximum number of bytes to read. Fewer bytes are read if <paramref name="count"/> is greater than the number of bytes in the input buffer.</param>
/// <param name="token">A token to cancel the current operation.</param>
/// <returns>The number of bytes read.</returns>
public async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken token)
Expand Down Expand Up @@ -104,7 +117,7 @@ public async Task<int> ReadAsync(byte[] buffer, int offset, int count, Cancellat
/// Writes data to the serial port output buffer.
/// </summary>
/// <param name="buffer">The byte array that contains the data to write to the port.</param>
/// <param name="offset">The zero-based byte offset in the <see cref="buffer"/> parameter at which to begin copying bytes to the port.</param>
/// <param name="offset">The zero-based byte offset in the <paramref name="buffer"/> parameter at which to begin copying bytes to the port.</param>
/// <param name="count">The number of bytes to write.</param>
public void Write(byte[] buffer, int offset, int count)
{
Expand All @@ -115,7 +128,7 @@ public void Write(byte[] buffer, int offset, int count)
/// Asynchronously writes data to the serial port output buffer.
/// </summary>
/// <param name="buffer">The byte array that contains the data to write to the port.</param>
/// <param name="offset">The zero-based byte offset in the <see cref="buffer"/> parameter at which to begin copying bytes to the port.</param>
/// <param name="offset">The zero-based byte offset in the <paramref name="buffer"/> parameter at which to begin copying bytes to the port.</param>
/// <param name="count">The number of bytes to write.</param>
/// <param name="token">A token to cancel the current operation.</param>
public async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken token)
Expand Down
37 changes: 36 additions & 1 deletion src/FluentModbus/ModbusUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,42 @@ public static ushort CalculateCRC(Memory<byte> buffer)
return crc;
}

public static bool DetectFrame(byte unitIdentifier, Memory<byte> frame)
public static bool DetectRequestFrame(byte unitIdentifier, Memory<byte> frame)
{
#warning This method should be improved byte validating the total length against the expected length depending on the function code
/* Correct response frame (min. 4 bytes)
* 00 Unit Identifier
* 01 Function Code
* (0..x bytes - depends on function code)
* n-1 CRC Byte 1
* n CRC Byte 2
*/

var span = frame.Span;

if (span.Length < 4)
return false;

if (unitIdentifier != 255) // 255 means "skip unit identifier check"
{
var newUnitIdentifier = span[0];

if (newUnitIdentifier != unitIdentifier)
return false;
}

// CRC check
var crcBytes = span.Slice(span.Length - 2, 2);
var actualCRC = unchecked((ushort)((crcBytes[1] << 8) + crcBytes[0]));
var expectedCRC = ModbusUtils.CalculateCRC(frame.Slice(0, frame.Length - 2));

if (actualCRC != expectedCRC)
return false;

return true;
}

public static bool DetectResponseFrame(byte unitIdentifier, Memory<byte> frame)
{
/* Correct response frame (min. 6 bytes)
* 00 Unit Identifier
Expand Down
2 changes: 1 addition & 1 deletion src/FluentModbus/Server/ModbusRtuRequestHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ private async Task<bool> TryReceiveRequestAsync()
Length += await _serialPort.ReadAsync(FrameBuffer.Buffer, Length, FrameBuffer.Buffer.Length - Length, CancellationToken);

// full frame received
if (ModbusUtils.DetectFrame(255, FrameBuffer.Buffer.AsMemory(0, Length)))
if (ModbusUtils.DetectRequestFrame(255, FrameBuffer.Buffer.AsMemory(0, Length)))
{
FrameBuffer.Reader.BaseStream.Seek(0, SeekOrigin.Begin);

Expand Down
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"version": "5.0.0",
"version": "5.0.1",
"suffix": ""
}

0 comments on commit 2485395

Please sign in to comment.