Initial commit
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
using Modbus.Device;
|
||||
using RobotNet10.Script.IO;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace RobotNet10.ScriptEngine.IO;
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of ModbusTCP connection using NModbus4 library.
|
||||
/// </summary>
|
||||
public class ModbusTcpConnection(string ipAddress, int port = 502, byte slaveId = 1, int connectTimeoutMs = 5000) : IModbusTcpConnection
|
||||
{
|
||||
private TcpClient? _tcpClient;
|
||||
private ModbusMaster? _modbusMaster;
|
||||
private bool _disposed;
|
||||
|
||||
public string IpAddress { get; } = ipAddress;
|
||||
public int Port { get; } = port;
|
||||
public byte SlaveId { get; } = slaveId;
|
||||
public int ConnectTimeoutMs { get; } = connectTimeoutMs;
|
||||
public bool IsConnected { get; private set; } = false;
|
||||
|
||||
public async Task ConnectAsync()
|
||||
{
|
||||
if (IsConnected)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
_tcpClient = new TcpClient();
|
||||
|
||||
// Sử dụng ConnectTimeout
|
||||
using (var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(ConnectTimeoutMs)))
|
||||
{
|
||||
await _tcpClient.ConnectAsync(IpAddress, Port).WaitAsync(cts.Token);
|
||||
}
|
||||
|
||||
_modbusMaster = ModbusIpMaster.CreateIp(_tcpClient);
|
||||
IsConnected = true;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
Disconnect();
|
||||
throw new TimeoutException($"Connection to {IpAddress}:{Port} timed out after {ConnectTimeoutMs}ms");
|
||||
}
|
||||
catch
|
||||
{
|
||||
Disconnect();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public Task DisconnectAsync()
|
||||
{
|
||||
Disconnect();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void Disconnect()
|
||||
{
|
||||
IsConnected = false;
|
||||
_modbusMaster?.Dispose();
|
||||
_modbusMaster = null;
|
||||
_tcpClient?.Close();
|
||||
_tcpClient?.Dispose();
|
||||
_tcpClient = null;
|
||||
}
|
||||
|
||||
public async Task<ushort[]> ReadHoldingRegistersAsync(ushort startAddress, ushort numberOfPoints)
|
||||
{
|
||||
EnsureConnected();
|
||||
return await Task.Run(() => _modbusMaster!.ReadHoldingRegisters(SlaveId, startAddress, numberOfPoints));
|
||||
}
|
||||
|
||||
public async Task<ushort[]> ReadInputRegistersAsync(ushort startAddress, ushort numberOfPoints)
|
||||
{
|
||||
EnsureConnected();
|
||||
return await Task.Run(() => _modbusMaster!.ReadInputRegisters(SlaveId, startAddress, numberOfPoints));
|
||||
}
|
||||
|
||||
public async Task<bool[]> ReadCoilsAsync(ushort startAddress, ushort numberOfPoints)
|
||||
{
|
||||
EnsureConnected();
|
||||
return await Task.Run(() => _modbusMaster!.ReadCoils(SlaveId, startAddress, numberOfPoints));
|
||||
}
|
||||
|
||||
public async Task<bool[]> ReadDiscreteInputsAsync(ushort startAddress, ushort numberOfPoints)
|
||||
{
|
||||
EnsureConnected();
|
||||
return await Task.Run(() => _modbusMaster!.ReadInputs(SlaveId, startAddress, numberOfPoints));
|
||||
}
|
||||
|
||||
public async Task WriteSingleCoilAsync(ushort coilAddress, bool value)
|
||||
{
|
||||
EnsureConnected();
|
||||
await Task.Run(() => _modbusMaster!.WriteSingleCoil(SlaveId, coilAddress, value));
|
||||
}
|
||||
|
||||
public async Task WriteMultipleCoilsAsync(ushort startAddress, bool[] values)
|
||||
{
|
||||
EnsureConnected();
|
||||
await Task.Run(() => _modbusMaster!.WriteMultipleCoils(SlaveId, startAddress, values));
|
||||
}
|
||||
|
||||
public async Task WriteSingleRegisterAsync(ushort registerAddress, ushort value)
|
||||
{
|
||||
EnsureConnected();
|
||||
await Task.Run(() => _modbusMaster!.WriteSingleRegister(SlaveId, registerAddress, value));
|
||||
}
|
||||
|
||||
public async Task WriteMultipleRegistersAsync(ushort startAddress, ushort[] values)
|
||||
{
|
||||
EnsureConnected();
|
||||
await Task.Run(() => _modbusMaster!.WriteMultipleRegisters(SlaveId, startAddress, values));
|
||||
}
|
||||
|
||||
private void EnsureConnected()
|
||||
{
|
||||
if (!IsConnected || _modbusMaster == null)
|
||||
{
|
||||
throw new InvalidOperationException("ModbusTCP connection is not connected. Call ConnectAsync() first.");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
Disconnect();
|
||||
_disposed = true;
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user