ModbusUdpSlaveNetwork.cs 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using System;
  2. using System.Diagnostics;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using NModbus.IO;
  9. using NModbus.Logging;
  10. using NModbus.Unme.Common;
  11. namespace NModbus.Device
  12. {
  13. using Extensions;
  14. /// <summary>
  15. /// Modbus UDP slave device.
  16. /// </summary>
  17. public class ModbusUdpSlaveNetwork : ModbusSlaveNetwork
  18. {
  19. private readonly UdpClient _udpClient;
  20. public ModbusUdpSlaveNetwork(UdpClient udpClient, IModbusFactory modbusFactory, IModbusLogger logger)
  21. : base(new ModbusIpTransport(new UdpClientAdapter(udpClient), modbusFactory, logger), modbusFactory, logger)
  22. {
  23. _udpClient = udpClient;
  24. }
  25. /// <summary>
  26. /// Start slave listening for requests.
  27. /// </summary>
  28. public override async Task ListenAsync(CancellationToken cancellationToken = new CancellationToken())
  29. {
  30. using (cancellationToken.Register(() =>
  31. {
  32. _udpClient.Dispose();
  33. }))
  34. {
  35. Logger.Information("Start Modbus Udp Server.");
  36. try
  37. {
  38. while (!cancellationToken.IsCancellationRequested)
  39. {
  40. UdpReceiveResult receiveResult = await _udpClient.ReceiveAsync().ConfigureAwait(false);
  41. IPEndPoint masterEndPoint = receiveResult.RemoteEndPoint;
  42. byte[] frame = receiveResult.Buffer;
  43. Debug.WriteLine($"Read Frame completed {frame.Length} bytes");
  44. Logger.LogFrameRx(frame);
  45. IModbusMessage request = ModbusFactory.CreateModbusRequest(frame.Slice(6, frame.Length - 6).ToArray());
  46. request.TransactionId = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 0));
  47. // perform action and build response
  48. IModbusMessage response = ApplyRequest(request);
  49. if (response != null)
  50. {
  51. response.TransactionId = request.TransactionId;
  52. // write response
  53. byte[] responseFrame = Transport.BuildMessageFrame(response);
  54. Logger.LogFrameTx(frame);
  55. await _udpClient.SendAsync(responseFrame, responseFrame.Length, masterEndPoint)
  56. .ConfigureAwait(false);
  57. }
  58. }
  59. }
  60. catch( ObjectDisposedException) when (cancellationToken.IsCancellationRequested)
  61. {
  62. // Swallow this error.
  63. }
  64. catch (SocketException se)
  65. {
  66. // this hapens when slave stops
  67. if (se.SocketErrorCode != SocketError.Interrupted)
  68. {
  69. throw;
  70. }
  71. }
  72. }
  73. }
  74. }
  75. }