using System;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using NModbus.IO;
using NModbus.Logging;
using NModbus.Unme.Common;
namespace NModbus.Device
{
using Extensions;
///
/// Modbus UDP slave device.
///
public class ModbusUdpSlaveNetwork : ModbusSlaveNetwork
{
private readonly UdpClient _udpClient;
public ModbusUdpSlaveNetwork(UdpClient udpClient, IModbusFactory modbusFactory, IModbusLogger logger)
: base(new ModbusIpTransport(new UdpClientAdapter(udpClient), modbusFactory, logger), modbusFactory, logger)
{
_udpClient = udpClient;
}
///
/// Start slave listening for requests.
///
public override async Task ListenAsync(CancellationToken cancellationToken = new CancellationToken())
{
using (cancellationToken.Register(() =>
{
_udpClient.Dispose();
}))
{
Logger.Information("Start Modbus Udp Server.");
try
{
while (!cancellationToken.IsCancellationRequested)
{
UdpReceiveResult receiveResult = await _udpClient.ReceiveAsync().ConfigureAwait(false);
IPEndPoint masterEndPoint = receiveResult.RemoteEndPoint;
byte[] frame = receiveResult.Buffer;
Debug.WriteLine($"Read Frame completed {frame.Length} bytes");
Logger.LogFrameRx(frame);
IModbusMessage request = ModbusFactory.CreateModbusRequest(frame.Slice(6, frame.Length - 6).ToArray());
request.TransactionId = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 0));
// perform action and build response
IModbusMessage response = ApplyRequest(request);
if (response != null)
{
response.TransactionId = request.TransactionId;
// write response
byte[] responseFrame = Transport.BuildMessageFrame(response);
Logger.LogFrameTx(frame);
await _udpClient.SendAsync(responseFrame, responseFrame.Length, masterEndPoint)
.ConfigureAwait(false);
}
}
}
catch( ObjectDisposedException) when (cancellationToken.IsCancellationRequested)
{
// Swallow this error.
}
catch (SocketException se)
{
// this hapens when slave stops
if (se.SocketErrorCode != SocketError.Interrupted)
{
throw;
}
}
}
}
}
}