using System; using System.Net; using System.Net.Sockets; using log4net; using Modbus.IO; using Modbus.Message; using Modbus.Utility; namespace Modbus.Device { /// /// Modbus UDP slave device. /// public class ModbusUdpSlave : ModbusSlave { private static readonly ILog _logger = LogManager.GetLogger(typeof(ModbusUdpSlave)); private readonly UdpClient _udpClient; private ModbusUdpSlave(byte unitId, UdpClient udpClient) : base(unitId, new ModbusIpTransport(new UdpClientAdapter(udpClient))) { _udpClient = udpClient; } /// /// Modbus UDP slave factory method. /// Creates NModbus UDP slave with default /// public static ModbusUdpSlave CreateUdp(UdpClient client) { return new ModbusUdpSlave(Modbus.DefaultIpSlaveUnitId, client); } /// /// Modbus UDP slave factory method. /// public static ModbusUdpSlave CreateUdp(byte unitId, UdpClient client) { return new ModbusUdpSlave(unitId, client); } /// /// Start slave listening for requests. /// public override void Listen() { _logger.Debug("Start Modbus Udp Server."); try { while (true) { IPEndPoint masterEndPoint = null; byte[] frame; frame = _udpClient.Receive(ref masterEndPoint); _logger.DebugFormat("Read Frame completed {0} bytes", frame.Length); _logger.InfoFormat("RX: {0}", StringUtility.Join(", ", frame)); IModbusMessage request = ModbusMessageFactory.CreateModbusRequest(CollectionUtility.Slice(frame, 6, frame.Length - 6)); request.TransactionId = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 0)); // perform action and build response IModbusMessage response = ApplyRequest(request); response.TransactionId = request.TransactionId; // write response byte[] responseFrame = Transport.BuildMessageFrame(response); _logger.InfoFormat("TX: {0}", StringUtility.Join(", ", responseFrame)); _udpClient.Send(responseFrame, responseFrame.Length, masterEndPoint); } } catch (SocketException se) { // this hapens when slave stops if (se.ErrorCode != Modbus.WSACancelBlockingCall) throw; } } } }