using Common.Attributes; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using static Common.Attributes.ATSCommandAttribute; namespace DeviceCommand.Base { [ATSCommand] [DeviceCategory("全部驱动")] // 添加分类属性 public class Udp { public string RemoteIpAddress { get; set; } = "127.0.0.1"; public int RemotePort { get; set; } = 8080; public int LocalPort { get; set; } = 0; // 0 表示系统自动分配 public int SendTimeout { get; set; } = 3000; public int ReceiveTimeout { get; set; } = 3000; public UdpClient UdpClient { get; set; } = new UdpClient(); /// /// 创建UDP设备对象 /// /// IP地址 /// 端口号 /// 发送超时时间 /// 接收超时时间 public Udp CreateDevice(string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000) { RemoteIpAddress = ipAddress; RemotePort = port; SendTimeout = sendTimeout; ReceiveTimeout = receiveTimeout; if (LocalPort > 0) { UdpClient = new UdpClient(LocalPort); } else { UdpClient = new UdpClient(); } UdpClient.Client.SendTimeout = SendTimeout; UdpClient.Client.ReceiveTimeout = ReceiveTimeout; return this; } /// /// 修改UDP连接参数 /// /// UDP设备对象 /// IP地址 /// 端口号 /// 发送超时时间 /// 接收超时时间 public static void ChangeDeviceConfig(Udp udp, string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000) { udp.RemoteIpAddress = ipAddress; udp.RemotePort = port; if (sendTimeout > 0) { udp.SendTimeout = sendTimeout; } if (receiveTimeout > 0) { udp.ReceiveTimeout = receiveTimeout; } if (udp.UdpClient != null) { udp.UdpClient.Client.SendTimeout = udp.SendTimeout; udp.UdpClient.Client.ReceiveTimeout = udp.ReceiveTimeout; } } // ———————————————————————— // 功能 78 // ———————————————————————— /// /// UDP连接(功能78) /// UDP是无连接的,此处主要进行初始化和设置默认远程端点 /// /// UDP设备对象 /// 取消令牌 /// 连接结果 public static async Task ConnectAsync(Udp udp, CancellationToken ct = default) { if (udp.UdpClient == null) { if (udp.LocalPort > 0) { udp.UdpClient = new UdpClient(udp.LocalPort); } else { udp.UdpClient = new UdpClient(); } } udp.UdpClient.Client.SendTimeout = udp.SendTimeout; udp.UdpClient.Client.ReceiveTimeout = udp.ReceiveTimeout; var remoteEndpoint = new IPEndPoint(IPAddress.Parse(udp.RemoteIpAddress), udp.RemotePort); //await udp.UdpClient.ConnectAsync(remoteEndpoint, ct); return true; } /// /// 紧急停止(功能78) /// /// UDP设备对象 public static void EmergencyStop(Udp udp) { Close(udp); // 复用 Close 逻辑 } // ———————————————————————— // 功能 79 // ———————————————————————— /// /// 设备初始化(功能79) /// /// UDP设备对象 public static void InitializeDevice(Udp udp) { if (udp.UdpClient == null) { if (udp.LocalPort > 0) { udp.UdpClient = new UdpClient(udp.LocalPort); } else { udp.UdpClient = new UdpClient(); } } udp.UdpClient.Client.SendTimeout = udp.SendTimeout; udp.UdpClient.Client.ReceiveTimeout = udp.ReceiveTimeout; } /// /// 断开(功能79) /// /// UDP设备对象 public static void Disconnect(Udp udp) { Close(udp); // 复用 Close 逻辑 } /// /// 连接(功能79) /// /// UDP设备对象 /// 取消令牌 /// 连接结果 public static async Task Connect(Udp udp, CancellationToken ct = default) { // 与 ConnectAsync 功能相同,可以复用 return await ConnectAsync(udp, ct); } // ———————————————————————— // 功能 80 // ———————————————————————— /// /// 发送字符串(功能80) /// /// UDP设备对象 /// 要发送的字符串 /// 取消令牌 public static async Task SendString(Udp udp, string str, CancellationToken ct = default) { await SendAsync(udp, str, ct); // 复用 SendAsync 逻辑 } /// /// 发送字节(功能80) /// /// UDP设备对象 /// 要发送的字节数组 /// 取消令牌 public static async Task SendByte(Udp udp, byte[] bytes, CancellationToken ct = default) { await SendAsync(udp, bytes, ct); // 复用 SendAsync 逻辑 } /// /// 接收字节(功能80) /// /// UDP设备对象 /// 取消令牌 /// 接收到的字节数组 public static async Task ReceiveByte(Udp udp, CancellationToken ct = default) { // UDP 接收通常不需要预先分配固定大小的 buffer,直接返回整个数据报 if (udp.UdpClient == null) throw new InvalidOperationException("UDP Client 未初始化。"); var timeoutMs = udp.ReceiveTimeout; if (timeoutMs <= 0) { var res = await udp.UdpClient.ReceiveAsync(); return res.Buffer; } var readTask = udp.UdpClient.ReceiveAsync(); var timeoutTask = Task.Delay(timeoutMs, ct); var completedTask = await Task.WhenAny(readTask, timeoutTask); if (completedTask == timeoutTask) { throw new TimeoutException($"UDP通讯异常:读取操作在 {timeoutMs} ms内未完成"); } var result = await readTask; return result.Buffer; } /// /// 接收字符串(功能80) /// /// UDP设备对象 /// 取消令牌 /// 接收到的字符串 public static async Task ReceiveString(Udp udp, CancellationToken ct = default) { var bytes = await ReceiveByte(udp, ct); return Encoding.UTF8.GetString(bytes); } // ———————————————————————— // 内部辅助方法 (与 Tcp 风格一致) // ———————————————————————— /// /// 关闭UDP连接 /// /// UDP设备对象 private static void Close(Udp udp) { udp.UdpClient?.Close(); // udp.UdpClient?.Dispose(); // 通常 Close 就足够了 } /// /// 发送字节数组到UDP设备 (内部核心方法) /// /// UDP设备对象 /// 要发送的字节数组 /// 取消令牌 public static async Task SendAsync(Udp udp, byte[] bytes, CancellationToken ct = default) { if (udp.UdpClient == null) throw new InvalidOperationException("UDP Client 未初始化。"); var timeoutMs = udp.SendTimeout; if (timeoutMs <= 0) { await udp.UdpClient.SendAsync(bytes, bytes.Length); return; } var sendTask = udp.UdpClient.SendAsync(bytes, bytes.Length); var timeoutTask = Task.Delay(timeoutMs, ct); var completedTask = await Task.WhenAny(sendTask, timeoutTask); if (completedTask == timeoutTask) { throw new TimeoutException($"UDP通讯异常:写入操作在 {timeoutMs} ms内未完成"); } await sendTask; } /// /// 发送字符串到UDP设备 (内部核心方法) /// /// UDP设备对象 /// 要发送的字符串 /// 取消令牌 private static async Task SendAsync(Udp udp, string str, CancellationToken ct = default) { await SendAsync(udp, Encoding.UTF8.GetBytes(str), ct); } // ———————————————————————— // 实例方法 (可选,便于链式调用) // ———————————————————————— /// /// 连接UDP设备(实例方法) /// /// 取消令牌 /// 连接结果 public async Task ConnectAsync(CancellationToken ct = default) { return await ConnectAsync(this, ct); } } }