Added implementation of Modbus TCP Server

This commit is contained in:
2024-03-25 20:41:49 +01:00
parent fbc9f9e429
commit d6bc5f1a4a
9 changed files with 1252 additions and 5 deletions

View File

@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("AMWD.Protocols.Modbus.Tests")] [assembly: InternalsVisibleTo("AMWD.Protocols.Modbus.Tests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

View File

@@ -59,6 +59,15 @@ namespace AMWD.Protocols.Modbus.Common.Protocols
/// </summary> /// </summary>
public const ushort MAX_REGISTER_WRITE_COUNT = 0x007B; // 123 public const ushort MAX_REGISTER_WRITE_COUNT = 0x007B; // 123
/// <summary>
/// The maximum allowed ADU length in bytes.
/// </summary>
/// <remarks>
/// A Modbus frame consists of a PDU (protcol data unit) and additional protocol addressing / error checks.
/// The whole data frame is called ADU (application data unit).
/// </remarks>
public const int MAX_ADU_LENGTH = 260; // bytes
#endregion Constants #endregion Constants
/// <inheritdoc/> /// <inheritdoc/>

View File

@@ -13,6 +13,12 @@
<PackageTags>Modbus Protocol Network TCP LAN</PackageTags> <PackageTags>Modbus Protocol Network TCP LAN</PackageTags>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Compile Include="../AMWD.Protocols.Modbus.Common/InternalsVisibleTo.cs" Link="InternalsVisibleTo.cs" />
<Compile Include="../AMWD.Protocols.Modbus.Common/Extensions/ArrayExtensions.cs" Link="Extensions/ArrayExtensions.cs" />
<Compile Include="../AMWD.Protocols.Modbus.Common/Extensions/ReaderWriterLockSlimExtensions.cs" Link="Extensions/ReaderWriterLockSlimExtensions.cs" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="README.md" Pack="true" PackagePath="/" /> <None Include="README.md" Pack="true" PackagePath="/" />
</ItemGroup> </ItemGroup>

View File

@@ -0,0 +1,25 @@
using System;
namespace AMWD.Protocols.Modbus.Tcp.Events
{
/// <summary>
/// Represents the coil written event arguments.
/// </summary>
public class CoilWrittenEventArgs : EventArgs
{
/// <summary>
/// Gets or sets the unit id.
/// </summary>
public byte UnitId { get; internal set; }
/// <summary>
/// Gets or sets the coil address.
/// </summary>
public ushort Address { get; internal set; }
/// <summary>
/// Gets or sets the coil value.
/// </summary>
public bool Value { get; internal set; }
}
}

View File

@@ -0,0 +1,35 @@
using System;
namespace AMWD.Protocols.Modbus.Tcp.Events
{
/// <summary>
/// Represents the register written event arguments.
/// </summary>
public class RegisterWrittenEventArgs : EventArgs
{
/// <summary>
/// Gets or sets the unit id.
/// </summary>
public byte UnitId { get; internal set; }
/// <summary>
/// Gets or sets the address of the register.
/// </summary>
public ushort Address { get; internal set; }
/// <summary>
/// Gets or sets the value of the register.
/// </summary>
public ushort Value { get; internal set; }
/// <summary>
/// Gets or sets the high byte of the register.
/// </summary>
public byte HighByte { get; internal set; }
/// <summary>
/// Gets or sets the low byte of the register.
/// </summary>
public byte LowByte { get; internal set; }
}
}

View File

@@ -0,0 +1,26 @@
using System.Threading;
using System.Threading.Tasks;
namespace System.IO
{
internal static class StreamExtensions
{
public static async Task<byte[]> ReadExpectedBytesAsync(this Stream stream, int expectedBytes, CancellationToken cancellationToken = default)
{
byte[] buffer = new byte[expectedBytes];
int offset = 0;
do
{
int count = await stream.ReadAsync(buffer, offset, expectedBytes - offset, cancellationToken).ConfigureAwait(false);
if (count < 1)
throw new EndOfStreamException();
offset += count;
}
while (offset < expectedBytes && !cancellationToken.IsCancellationRequested);
cancellationToken.ThrowIfCancellationRequested();
return buffer;
}
}
}

View File

@@ -1,4 +0,0 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("AMWD.Protocols.Modbus.Tests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

File diff suppressed because it is too large Load Diff

View File

@@ -161,8 +161,8 @@ namespace AMWD.Protocols.Modbus.Tests.Tcp.Utils
public async Task ShouldThrowApplicationExceptionHostnameNotResolvable() public async Task ShouldThrowApplicationExceptionHostnameNotResolvable()
{ {
// Arrange // Arrange
_hostname = "123.321.123.321";
var connection = GetConnection(); var connection = GetConnection();
connection.GetType().GetField("_hostname", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(connection, "");
// Act // Act
await connection.ConnectAsync(); await connection.ConnectAsync();