diff --git a/AMWD.Protocols.Modbus.Common/Contracts/ModbusClientBase.cs b/AMWD.Protocols.Modbus.Common/Contracts/ModbusClientBase.cs
index d00c99b..5a59f3d 100644
--- a/AMWD.Protocols.Modbus.Common/Contracts/ModbusClientBase.cs
+++ b/AMWD.Protocols.Modbus.Common/Contracts/ModbusClientBase.cs
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
-using System.Threading.Tasks;
-using System.Threading;
using System.Linq;
using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
namespace AMWD.Protocols.Modbus.Common.Contracts
{
diff --git a/AMWD.Protocols.Modbus.Common/Exceptions/ModbusException.cs b/AMWD.Protocols.Modbus.Common/Exceptions/ModbusException.cs
index 377e9f2..87cfdad 100644
--- a/AMWD.Protocols.Modbus.Common/Exceptions/ModbusException.cs
+++ b/AMWD.Protocols.Modbus.Common/Exceptions/ModbusException.cs
@@ -1,6 +1,8 @@
using System;
using System.Diagnostics.CodeAnalysis;
+#if !NET8_0_OR_GREATER
using System.Runtime.Serialization;
+#endif
namespace AMWD.Protocols.Modbus.Common
{
diff --git a/AMWD.Protocols.Modbus.Common/Models/ModbusObject.cs b/AMWD.Protocols.Modbus.Common/Models/ModbusObject.cs
index c7b91b0..a6e3b6b 100644
--- a/AMWD.Protocols.Modbus.Common/Models/ModbusObject.cs
+++ b/AMWD.Protocols.Modbus.Common/Models/ModbusObject.cs
@@ -1,4 +1,6 @@
-using System;
+#if NET6_0_OR_GREATER
+using System;
+#endif
namespace AMWD.Protocols.Modbus.Common
{
diff --git a/AMWD.Protocols.Modbus.Common/Protocols/RtuOverTcpProtocol.cs b/AMWD.Protocols.Modbus.Common/Protocols/RtuOverTcpProtocol.cs
index 72089b4..3815822 100644
--- a/AMWD.Protocols.Modbus.Common/Protocols/RtuOverTcpProtocol.cs
+++ b/AMWD.Protocols.Modbus.Common/Protocols/RtuOverTcpProtocol.cs
@@ -10,7 +10,9 @@ namespace AMWD.Protocols.Modbus.Common.Protocols
///
///
/// The Modbus RTU over Modbus TCP is rarely used.
- /// It is a non-standard variant of Modbus TCP that includes wrapps a Modbus RTU message within a Modbus TCP message.
+ /// It is a non-standard variant:
+ /// You can define it as RTU message with an additional TCP header
+ /// or as TCP message with an additional CRC16 checksum at the end (header not included!).
///
/// Definition found on Fernhill Software.
///
diff --git a/AMWD.Protocols.Modbus.Proxy/ModbusTcpProxy.cs b/AMWD.Protocols.Modbus.Proxy/ModbusTcpProxy.cs
index 40987e0..ce1ef23 100644
--- a/AMWD.Protocols.Modbus.Proxy/ModbusTcpProxy.cs
+++ b/AMWD.Protocols.Modbus.Proxy/ModbusTcpProxy.cs
@@ -370,7 +370,7 @@ namespace AMWD.Protocols.Modbus.Proxy
responseBytes.Add((byte)ModbusErrorCode.SlaveDeviceFailure);
}
- return [.. responseBytes];
+ return ReturnResponse(responseBytes);
}
private async Task HandleReadDiscreteInputsAsync(byte[] requestBytes, CancellationToken cancellationToken)
@@ -409,7 +409,7 @@ namespace AMWD.Protocols.Modbus.Proxy
responseBytes.Add((byte)ModbusErrorCode.SlaveDeviceFailure);
}
- return [.. responseBytes];
+ return ReturnResponse(responseBytes);
}
private async Task HandleReadHoldingRegistersAsync(byte[] requestBytes, CancellationToken cancellationToken)
@@ -443,7 +443,7 @@ namespace AMWD.Protocols.Modbus.Proxy
responseBytes.Add((byte)ModbusErrorCode.SlaveDeviceFailure);
}
- return [.. responseBytes];
+ return ReturnResponse(responseBytes);
}
private async Task HandleReadInputRegistersAsync(byte[] requestBytes, CancellationToken cancellationToken)
@@ -477,7 +477,7 @@ namespace AMWD.Protocols.Modbus.Proxy
responseBytes.Add((byte)ModbusErrorCode.SlaveDeviceFailure);
}
- return [.. responseBytes];
+ return ReturnResponse(responseBytes);
}
private async Task HandleWriteSingleCoilAsync(byte[] requestBytes, CancellationToken cancellationToken)
@@ -494,7 +494,8 @@ namespace AMWD.Protocols.Modbus.Proxy
{
responseBytes[7] |= 0x80;
responseBytes.Add((byte)ModbusErrorCode.IllegalDataValue);
- return [.. responseBytes];
+
+ return ReturnResponse(responseBytes);
}
try
@@ -524,7 +525,7 @@ namespace AMWD.Protocols.Modbus.Proxy
responseBytes.Add((byte)ModbusErrorCode.SlaveDeviceFailure);
}
- return [.. responseBytes];
+ return ReturnResponse(responseBytes);
}
private async Task HandleWriteSingleRegisterAsync(byte[] requestBytes, CancellationToken cancellationToken)
@@ -564,7 +565,7 @@ namespace AMWD.Protocols.Modbus.Proxy
responseBytes.Add((byte)ModbusErrorCode.SlaveDeviceFailure);
}
- return [.. responseBytes];
+ return ReturnResponse(responseBytes);
}
private async Task HandleWriteMultipleCoilsAsync(byte[] requestBytes, CancellationToken cancellationToken)
@@ -583,7 +584,8 @@ namespace AMWD.Protocols.Modbus.Proxy
{
responseBytes[7] |= 0x80;
responseBytes.Add((byte)ModbusErrorCode.IllegalDataValue);
- return [.. responseBytes];
+
+ return ReturnResponse(responseBytes);
}
try
@@ -623,7 +625,7 @@ namespace AMWD.Protocols.Modbus.Proxy
responseBytes.Add((byte)ModbusErrorCode.SlaveDeviceFailure);
}
- return [.. responseBytes];
+ return ReturnResponse(responseBytes);
}
private async Task HandleWriteMultipleRegistersAsync(byte[] requestBytes, CancellationToken cancellationToken)
@@ -642,7 +644,8 @@ namespace AMWD.Protocols.Modbus.Proxy
{
responseBytes[7] |= 0x80;
responseBytes.Add((byte)ModbusErrorCode.IllegalDataValue);
- return [.. responseBytes];
+
+ return ReturnResponse(responseBytes);
}
try
@@ -679,7 +682,7 @@ namespace AMWD.Protocols.Modbus.Proxy
responseBytes.Add((byte)ModbusErrorCode.SlaveDeviceFailure);
}
- return [.. responseBytes];
+ return ReturnResponse(responseBytes);
}
private async Task HandleEncapsulatedInterfaceAsync(byte[] requestBytes, CancellationToken cancellationToken)
@@ -691,7 +694,8 @@ namespace AMWD.Protocols.Modbus.Proxy
{
responseBytes[7] |= 0x80;
responseBytes.Add((byte)ModbusErrorCode.IllegalFunction);
- return [.. responseBytes];
+
+ return ReturnResponse(responseBytes);
}
var firstObject = (ModbusDeviceIdentificationObject)requestBytes[10];
@@ -699,7 +703,8 @@ namespace AMWD.Protocols.Modbus.Proxy
{
responseBytes[7] |= 0x80;
responseBytes.Add((byte)ModbusErrorCode.IllegalDataAddress);
- return [.. responseBytes];
+
+ return ReturnResponse(responseBytes);
}
var category = (ModbusDeviceIdentificationCategory)requestBytes[9];
@@ -707,7 +712,8 @@ namespace AMWD.Protocols.Modbus.Proxy
{
responseBytes[7] |= 0x80;
responseBytes.Add((byte)ModbusErrorCode.IllegalDataValue);
- return [.. responseBytes];
+
+ return ReturnResponse(responseBytes);
}
try
@@ -764,7 +770,8 @@ namespace AMWD.Protocols.Modbus.Proxy
bodyBytes[5] = numberOfObjects;
responseBytes.AddRange(bodyBytes);
- return [.. responseBytes];
+
+ return ReturnResponse(responseBytes);
}
bodyBytes.AddRange(objBytes);
@@ -773,13 +780,15 @@ namespace AMWD.Protocols.Modbus.Proxy
bodyBytes[5] = numberOfObjects;
responseBytes.AddRange(bodyBytes);
- return [.. responseBytes];
+
+ return ReturnResponse(responseBytes);
}
catch
{
responseBytes[7] |= 0x80;
responseBytes.Add((byte)ModbusErrorCode.SlaveDeviceFailure);
- return [.. responseBytes];
+
+ return ReturnResponse(responseBytes);
}
}
@@ -863,6 +872,16 @@ namespace AMWD.Protocols.Modbus.Proxy
return [.. result];
}
+ private static byte[] ReturnResponse(List response)
+ {
+ ushort followingBytes = (ushort)(response.Count - 6);
+ byte[] bytes = followingBytes.ToBigEndianBytes();
+ response[4] = bytes[0];
+ response[5] = bytes[1];
+
+ return [.. response];
+ }
+
#endregion Request Handling
}
}
diff --git a/AMWD.Protocols.Modbus.Serial/ModbusSerialConnection.cs b/AMWD.Protocols.Modbus.Serial/ModbusSerialConnection.cs
index 8d54951..94cc1fa 100644
--- a/AMWD.Protocols.Modbus.Serial/ModbusSerialConnection.cs
+++ b/AMWD.Protocols.Modbus.Serial/ModbusSerialConnection.cs
@@ -107,9 +107,7 @@ namespace AMWD.Protocols.Modbus.Serial
set => _serialPort.PortName = value;
}
- ///
- /// Gets or sets the serial baud rate.
- ///
+ ///
public virtual BaudRate BaudRate
{
get => (BaudRate)_serialPort.BaudRate;
@@ -118,7 +116,11 @@ namespace AMWD.Protocols.Modbus.Serial
///
///
- /// Should be 7 for ASCII mode and 8 for RTU mode.
+ /// From the Specs:
+ ///
+ /// On it can be 7 or 8.
+ ///
+ /// On it has to be 8.
///
public virtual int DataBits
{
@@ -159,9 +161,9 @@ namespace AMWD.Protocols.Modbus.Serial
///
/// From the Specs:
///
- /// Should be for or and
+ /// Should be for or .
///
- /// should be for .
+ /// Should be for .
///
public virtual StopBits StopBits
{
@@ -188,7 +190,6 @@ namespace AMWD.Protocols.Modbus.Serial
try
{
- _processingTask.Wait();
_processingTask.Dispose();
}
catch
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 006455c..ede9233 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The `ModbusTcpProxy.ReadWriteTimeout` has a default value of 100 seconds (same default as a `HttpClient` has).
+### Fixed
+
+- Wrong _following bytes_ calculation in `ModbusTcpProxy`.
+
## [v0.3.2] (2024-09-04)