Added implementation of Modbus TCP Server
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("AMWD.Protocols.Modbus.Tests")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||
|
||||
@@ -59,6 +59,15 @@ namespace AMWD.Protocols.Modbus.Common.Protocols
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
<PackageTags>Modbus Protocol Network TCP LAN</PackageTags>
|
||||
</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>
|
||||
<None Include="README.md" Pack="true" PackagePath="/" />
|
||||
</ItemGroup>
|
||||
|
||||
25
AMWD.Protocols.Modbus.Tcp/Events/CoilWrittenEventArgs.cs
Normal file
25
AMWD.Protocols.Modbus.Tcp/Events/CoilWrittenEventArgs.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
35
AMWD.Protocols.Modbus.Tcp/Events/RegisterWrittenEventArgs.cs
Normal file
35
AMWD.Protocols.Modbus.Tcp/Events/RegisterWrittenEventArgs.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
26
AMWD.Protocols.Modbus.Tcp/Extensions/StreamExtensions.cs
Normal file
26
AMWD.Protocols.Modbus.Tcp/Extensions/StreamExtensions.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("AMWD.Protocols.Modbus.Tests")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||
1149
AMWD.Protocols.Modbus.Tcp/ModbusTcpServer.cs
Normal file
1149
AMWD.Protocols.Modbus.Tcp/ModbusTcpServer.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -161,8 +161,8 @@ namespace AMWD.Protocols.Modbus.Tests.Tcp.Utils
|
||||
public async Task ShouldThrowApplicationExceptionHostnameNotResolvable()
|
||||
{
|
||||
// Arrange
|
||||
_hostname = "123.321.123.321";
|
||||
var connection = GetConnection();
|
||||
connection.GetType().GetField("_hostname", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(connection, "");
|
||||
|
||||
// Act
|
||||
await connection.ConnectAsync();
|
||||
|
||||
Reference in New Issue
Block a user