140 lines
4.8 KiB
C#
140 lines
4.8 KiB
C#
using NModbus;
|
|
using System;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace DeviceCommand.Base
|
|
{
|
|
public class ModbusTcp
|
|
{
|
|
public string IPAddress { get; private set; } = "127.0.0.1";
|
|
public int Port { get; private set; } = 502;
|
|
public int SendTimeout { get; private set; } = 3000;
|
|
public int ReceiveTimeout { get; private set; } = 3000;
|
|
public TcpClient TcpClient { get; private set; } = new TcpClient();
|
|
public IModbusMaster Modbus { get; private set; }
|
|
|
|
private readonly SemaphoreSlim _commLock = new(1, 1);
|
|
|
|
public void ConfigureDevice(string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000)
|
|
{
|
|
IPAddress = ipAddress;
|
|
Port = port;
|
|
SendTimeout = sendTimeout;
|
|
ReceiveTimeout = receiveTimeout;
|
|
}
|
|
|
|
public async Task<bool> ConnectAsync(CancellationToken ct = default)
|
|
{
|
|
await _commLock.WaitAsync(ct);
|
|
try
|
|
{
|
|
if (TcpClient.Connected)
|
|
{
|
|
var remoteEndPoint = (IPEndPoint)TcpClient.Client.RemoteEndPoint!;
|
|
if (remoteEndPoint.Address.MapToIPv4().ToString() == IPAddress && remoteEndPoint.Port == Port)
|
|
return true;
|
|
|
|
TcpClient.Close();
|
|
TcpClient.Dispose();
|
|
TcpClient = new TcpClient();
|
|
}
|
|
await TcpClient.ConnectAsync(IPAddress, Port, ct);
|
|
Modbus = new ModbusFactory().CreateMaster(TcpClient);
|
|
return true;
|
|
}
|
|
finally
|
|
{
|
|
_commLock.Release();
|
|
}
|
|
}
|
|
public void Close()
|
|
{
|
|
if (TcpClient.Connected) TcpClient.Close();
|
|
}
|
|
|
|
public async Task WriteSingleRegisterAsync(byte slaveAddress, ushort registerAddress, ushort value, CancellationToken ct = default)
|
|
{
|
|
await _commLock.WaitAsync(ct);
|
|
try
|
|
{
|
|
await Modbus.WriteSingleRegisterAsync(slaveAddress, registerAddress, value).WaitAsync(TimeSpan.FromMinutes(SendTimeout),ct);
|
|
}
|
|
finally
|
|
{
|
|
_commLock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task WriteMultipleRegistersAsync(byte slaveAddress, ushort startAddress, ushort[] values, CancellationToken ct = default)
|
|
{
|
|
await _commLock.WaitAsync(ct);
|
|
try
|
|
{
|
|
await Modbus.WriteMultipleRegistersAsync(slaveAddress, startAddress, values).WaitAsync(TimeSpan.FromMinutes(SendTimeout), ct);
|
|
}
|
|
finally
|
|
{
|
|
_commLock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task<ushort[]> ReadHoldingRegistersAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints, CancellationToken ct = default)
|
|
{
|
|
await _commLock.WaitAsync(ct);
|
|
try
|
|
{
|
|
var result =await Modbus.ReadHoldingRegistersAsync(slaveAddress, startAddress, numberOfPoints).WaitAsync(TimeSpan.FromMinutes(SendTimeout), ct);
|
|
return result;
|
|
}
|
|
finally
|
|
{
|
|
_commLock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task WriteSingleCoilAsync(byte slaveAddress, ushort coilAddress, bool value, CancellationToken ct = default)
|
|
{
|
|
await _commLock.WaitAsync(ct);
|
|
try
|
|
{
|
|
await Modbus.WriteSingleCoilAsync(slaveAddress, coilAddress, value).WaitAsync(TimeSpan.FromMinutes(SendTimeout), ct);
|
|
}
|
|
finally
|
|
{
|
|
_commLock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task<bool[]> ReadCoilsAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints, CancellationToken ct = default)
|
|
{
|
|
await _commLock.WaitAsync(ct);
|
|
try
|
|
{
|
|
var result = await Modbus.ReadCoilsAsync(slaveAddress, startAddress, numberOfPoints).WaitAsync(TimeSpan.FromMinutes(SendTimeout), ct);
|
|
return result;
|
|
}
|
|
finally
|
|
{
|
|
_commLock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task<ushort[]> ReadInputRegistersAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints, CancellationToken ct = default)
|
|
{
|
|
await _commLock.WaitAsync(ct);
|
|
try
|
|
{
|
|
var result = await Modbus.ReadInputRegistersAsync(slaveAddress, startAddress, numberOfPoints).WaitAsync(TimeSpan.FromMinutes(SendTimeout), ct);
|
|
return result;
|
|
}
|
|
finally
|
|
{
|
|
_commLock.Release();
|
|
}
|
|
}
|
|
}
|
|
}
|