using System.Net; using System.Net.Sockets; using System.Text; using DotNext; using WebProtocol; /// /// UDP客户端发送池 /// public class UDPClientPool { private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static IPAddress localhost = IPAddress.Parse("127.0.0.1"); /// /// 发送字符串 /// /// IP端点(IP地址与端口) /// 字符串数组 /// 是否成功 public static bool SendString(IPEndPoint endPoint, string[] stringArray) { var isSuccessful = true; Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); foreach (var str in stringArray) { byte[] sendbuf = Encoding.ASCII.GetBytes(str); var sendLen = socket.SendTo(sendbuf, endPoint); if (str.Length != sendLen) isSuccessful = false; } socket.Close(); if (isSuccessful) { return true; } else { return false; } } /// /// 异步发送字符串 /// /// IP端点(IP地址与端口) /// 字符串数组 /// 是否成功 public async static ValueTask SendStringAsync(IPEndPoint endPoint, string[] stringArray) { return await Task.Run(() => { return SendString(endPoint, stringArray); }); } /// /// 发送二进制字节 /// /// IP端点(IP地址与端口) /// 二进制字节 /// 是否成功 public static bool SendBytes(IPEndPoint endPoint, byte[] buf) { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); var sendLen = socket.SendTo(buf, endPoint); socket.Close(); logger.Debug($"UDP socket send bytes to device {endPoint.Address.ToString()}:{endPoint.Port.ToString()}:"); logger.Debug($" Original Data: {BitConverter.ToString(buf).Replace("-", " ")}"); if (sendLen == buf.Length) { return true; } else { return false; } } /// /// 异步发送二进制字节 /// /// IP端点(IP地址与端口) /// 二进制字节 /// 是否成功 public async static ValueTask SendBytesAsync(IPEndPoint endPoint, byte[] buf) { return await Task.Run(() => { return SendBytes(endPoint, buf); }); } /// /// 发送地址包 /// /// IP端点(IP地址与端口) /// 地址包 /// 是否成功 public static bool SendAddrPack(IPEndPoint endPoint, WebProtocol.SendAddrPackage pkg) { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); var sendBytes = pkg.ToBytes(); var sendLen = socket.SendTo(sendBytes, endPoint); socket.Close(); logger.Debug($"UDP socket send address package to device {endPoint.Address.ToString()}:{endPoint.Port.ToString()}:"); logger.Debug($" Original Data: {BitConverter.ToString(pkg.ToBytes()).Replace("-", " ")}"); logger.Debug($" Decoded Data: {pkg.ToString()}"); if (sendLen == sendBytes.Length) { return true; } else { return false; } } /// /// 异步发送地址包 /// /// IP端点(IP地址与端口) /// 地址包 /// 是否成功 public async static ValueTask SendAddrPackAsync(IPEndPoint endPoint, WebProtocol.SendAddrPackage pkg) { return await Task.Run(() => { return SendAddrPack(endPoint, pkg); }); } /// /// 发送数据包 /// /// IP端点(IP地址与端口) /// 数据包 /// 是否成功 public static bool SendDataPack(IPEndPoint endPoint, WebProtocol.SendDataPackage pkg) { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); var sendBytes = pkg.ToBytes(); var sendLen = socket.SendTo(sendBytes, endPoint); socket.Close(); logger.Debug($"UDP socket send data package to device {endPoint.Address.ToString()}:{endPoint.Port.ToString()}:"); logger.Debug($" Original Data: {BitConverter.ToString(pkg.ToBytes()).Replace("-", " ")}"); if (sendLen == sendBytes.Length) { return true; } else { return false; } } /// /// 异步发送数据包 /// /// IP端点(IP地址与端口) /// 数据包 /// 是否成功 public async static ValueTask SendDataPackAsync(IPEndPoint endPoint, WebProtocol.SendDataPackage pkg) { return await Task.Run(() => { return SendDataPack(endPoint, pkg); }); } /// /// 发送字符串到本地 /// /// 端口 /// 字符串数组 /// 是否成功 public static bool SendStringLocalHost(int port, string[] stringArray) { return SendString(new IPEndPoint(localhost, port), stringArray); } /// /// 循环发送字符串到本地 /// /// 发送总次数 /// 间隔时间 /// 端口 /// 字符串数组 /// 是否成功 public static bool CycleSendStringLocalHost(int times, int sleepMilliSeconds, int port, string[] stringArray) { var isSuccessful = true; while (times-- >= 0) { isSuccessful = SendStringLocalHost(port, stringArray); if (!isSuccessful) break; Thread.Sleep(sleepMilliSeconds); } return isSuccessful; } /// /// [TODO:description] /// /// [TODO:parameter] /// [TODO:parameter] /// [TODO:parameter] /// [TODO:return] public static async ValueTask> ReadAddr( IPEndPoint endPoint, int taskID, uint devAddr, int timeout = 1000) { var ret = false; var opts = new SendAddrPackOptions(); opts.BurstType = BurstType.FixedBurst; opts.BurstLength = 0; opts.CommandID = Convert.ToByte(taskID); opts.Address = devAddr; // Read Jtag State Register opts.IsWrite = false; ret = await UDPClientPool.SendAddrPackAsync(endPoint, new SendAddrPackage(opts)); if (!ret) return new(new Exception("Send Address Package Failed!")); // Wait for Read Ack if (!MsgBus.IsRunning) return new(new Exception("Message Bus not Working!")); var retPack = await MsgBus.UDPServer.WaitForDataAsync( endPoint.Address.ToString(), taskID, endPoint.Port, timeout); if (!retPack.IsSuccessful) return new(retPack.Error); else if (!retPack.Value.IsSuccessful) return new(new Exception("Send address package failed")); var retPackOpts = retPack.Value.Options; if (retPackOpts.Data is null) return new(new Exception($"Data is Null, package: {retPackOpts.ToString()}")); return retPack; } /// /// [TODO:description] /// /// [TODO:parameter] /// [TODO:parameter] /// [TODO:parameter] /// [TODO:parameter] /// [TODO:parameter] /// [TODO:return] public static async ValueTask> ReadAddr( IPEndPoint endPoint, int taskID, uint devAddr, UInt32 result, UInt32 resultMask, int timeout = 1000) { var address = endPoint.Address.ToString(); var ret = await ReadAddr(endPoint, taskID, devAddr, timeout); if (!ret.IsSuccessful) return new(ret.Error); if (!ret.Value.IsSuccessful) return new(new Exception($"Read device {address} address {devAddr} failed")); var retData = ret.Value.Options.Data; if (retData is null) return new(new Exception($"Device {address} receive none")); if (retData.Length != 4) return new(new Exception( $"Device {address} receive data is {retData.Length} bytes instead of 4 bytes")); // Check result try { var retCode = Convert.ToUInt32(Common.Number.BytesToUInt64(retData).Value); return Common.Number.BitsCheck(retCode, result, resultMask); } catch (Exception error) { return new(error); } } /// /// [TODO:description] /// /// [TODO:parameter] /// [TODO:parameter] /// [TODO:parameter] /// [TODO:parameter] /// [TODO:parameter] /// [TODO:return] public static async ValueTask> ReadAddrWithWait( IPEndPoint endPoint, int taskID, uint devAddr, UInt32 result, UInt32 resultMask, int timeout = 1000) { var address = endPoint.Address.ToString(); var startTime = DateTime.Now; while (true) { var elapsed = DateTime.Now - startTime; if (elapsed >= TimeSpan.FromMilliseconds(timeout)) break; var timeleft = TimeSpan.FromMilliseconds(timeout) - elapsed; try { var ret = await ReadAddr(endPoint, taskID, devAddr, Convert.ToInt32(timeleft.TotalMilliseconds)); if (!ret.IsSuccessful) return new(ret.Error); if (!ret.Value.IsSuccessful) return new(new Exception($"Read device {address} address {devAddr} failed")); var retData = ret.Value.Options.Data; if (retData is null) return new(new Exception($"Device {address} receive none")); if (retData.Length != 4) return new(new Exception( $"Device {address} receive data is {retData.Length} bytes instead of 4 bytes")); // Check result var retCode = Convert.ToUInt32(Common.Number.BytesToUInt64(retData).Value); if (Common.Number.BitsCheck(retCode, result, resultMask)) return true; } catch (Exception error) { return new(error); } } return false; } /// /// [TODO:description] /// /// [TODO:parameter] /// [TODO:parameter] /// [TODO:parameter] /// [TODO:parameter] /// [TODO:return] public static async ValueTask> WriteAddr( IPEndPoint endPoint, int taskID, UInt32 devAddr, UInt32 data, int timeout = 1000) { var ret = false; var opts = new SendAddrPackOptions(); opts.BurstType = BurstType.FixedBurst; opts.BurstLength = 0; opts.CommandID = Convert.ToByte(taskID); opts.Address = devAddr; // Write Jtag State Register opts.IsWrite = true; ret = await UDPClientPool.SendAddrPackAsync(endPoint, new SendAddrPackage(opts)); if (!ret) return new(new Exception("Send 1st address package failed!")); // Send Data Package ret = await UDPClientPool.SendDataPackAsync(endPoint, new SendDataPackage(Common.Number.NumberToBytes(data, 4).Value)); if (!ret) return new(new Exception("Send data package failed!")); // Check Msg Bus if (!MsgBus.IsRunning) return new(new Exception("Message bus not working!")); // Wait for Write Ack var udpWriteAck = await MsgBus.UDPServer.WaitForAckAsync( endPoint.Address.ToString(), taskID, endPoint.Port, timeout); if (!udpWriteAck.IsSuccessful) return new(udpWriteAck.Error); return udpWriteAck.Value.IsSuccessful; } /// /// [TODO:description] /// /// [TODO:parameter] /// [TODO:parameter] /// [TODO:parameter] /// [TODO:parameter] /// [TODO:return] public static async ValueTask> WriteAddr( IPEndPoint endPoint, int taskID, UInt32 devAddr, byte[] dataArray, int timeout = 1000) { var ret = false; var opts = new SendAddrPackOptions(); opts.BurstType = BurstType.FixedBurst; opts.CommandID = Convert.ToByte(taskID); opts.Address = devAddr; // Check Msg Bus if (!MsgBus.IsRunning) return new(new Exception("Message bus not working!")); opts.IsWrite = true; var hasRest = dataArray.Length % (256 * (32 / 8)) != 0; var writeTimes = hasRest ? dataArray.Length / (256 * (32 / 8)) + 1 : dataArray.Length / (256 * (32 / 8)); for (var i = 0; i < writeTimes; i++) { // Sperate Data Array var isLastData = i == writeTimes - 1; var sendDataArray = isLastData ? dataArray[(i * (256 * (32 / 8)))..] : dataArray[(i * (256 * (32 / 8)))..((i + 1) * (256 * (32 / 8)))]; // Write Jtag State Register opts.BurstLength = ((byte)(sendDataArray.Length / 4 - 1)); ret = await UDPClientPool.SendAddrPackAsync(endPoint, new SendAddrPackage(opts)); if (!ret) return new(new Exception("Send 1st address package failed!")); // Send Data Package ret = await UDPClientPool.SendDataPackAsync(endPoint, new SendDataPackage(sendDataArray)); if (!ret) return new(new Exception("Send data package failed!")); // Wait for Write Ack var udpWriteAck = await MsgBus.UDPServer.WaitForAckAsync(endPoint.Address.ToString(), taskID, endPoint.Port, timeout); if (!udpWriteAck.IsSuccessful) return new(udpWriteAck.Error); if (!udpWriteAck.Value.IsSuccessful) return false; } return true; } }