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;
}
}
}
}