diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/Camera.Designer.cs b/Windows/CS/Framework4.0/Toprie/Toprie/Camera.Designer.cs
index a27acbe..7cba02f 100644
--- a/Windows/CS/Framework4.0/Toprie/Toprie/Camera.Designer.cs
+++ b/Windows/CS/Framework4.0/Toprie/Toprie/Camera.Designer.cs
@@ -15,12 +15,25 @@
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
this.imageBox = new System.Windows.Forms.PictureBox();
+ this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.colorModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.whiteHotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.blackHotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.ironRedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.lavaToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.rainbowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.ironGrayToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.redHotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.rainbow2ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
((System.ComponentModel.ISupportInitialize)(this.imageBox)).BeginInit();
+ this.contextMenuStrip1.SuspendLayout();
this.SuspendLayout();
//
// imageBox
//
+ this.imageBox.ContextMenuStrip = this.contextMenuStrip1;
this.imageBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.imageBox.Location = new System.Drawing.Point(0, 0);
this.imageBox.Name = "imageBox";
@@ -29,6 +42,86 @@
this.imageBox.TabIndex = 0;
this.imageBox.TabStop = false;
//
+ // contextMenuStrip1
+ //
+ this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.colorModeToolStripMenuItem});
+ this.contextMenuStrip1.Name = "contextMenuStrip1";
+ this.contextMenuStrip1.Size = new System.Drawing.Size(161, 48);
+ //
+ // colorModeToolStripMenuItem
+ //
+ this.colorModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.whiteHotToolStripMenuItem,
+ this.blackHotToolStripMenuItem,
+ this.ironRedToolStripMenuItem,
+ this.lavaToolStripMenuItem,
+ this.rainbowToolStripMenuItem,
+ this.ironGrayToolStripMenuItem,
+ this.redHotToolStripMenuItem,
+ this.rainbow2ToolStripMenuItem});
+ this.colorModeToolStripMenuItem.Name = "colorModeToolStripMenuItem";
+ this.colorModeToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
+ this.colorModeToolStripMenuItem.Text = "色彩模式";
+ //
+ // rainbowToolStripMenuItem
+ //
+ this.rainbowToolStripMenuItem.Name = "rainbowToolStripMenuItem";
+ this.rainbowToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.rainbowToolStripMenuItem.Text = "彩虹";
+ this.rainbowToolStripMenuItem.Click += new System.EventHandler(this.rainbowToolStripMenuItem_Click);
+ //
+ // ironRedToolStripMenuItem
+ //
+ this.ironRedToolStripMenuItem.Name = "ironRedToolStripMenuItem";
+ this.ironRedToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.ironRedToolStripMenuItem.Text = "铁红";
+ this.ironRedToolStripMenuItem.Click += new System.EventHandler(this.ironRedToolStripMenuItem_Click);
+ //
+ // lavaToolStripMenuItem
+ //
+ this.lavaToolStripMenuItem.Name = "lavaToolStripMenuItem";
+ this.lavaToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.lavaToolStripMenuItem.Text = "熔岩";
+ this.lavaToolStripMenuItem.Click += new System.EventHandler(this.lavaToolStripMenuItem_Click);
+ //
+ // ironGrayToolStripMenuItem
+ //
+ this.ironGrayToolStripMenuItem.Name = "ironGrayToolStripMenuItem";
+ this.ironGrayToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.ironGrayToolStripMenuItem.Text = "铁灰";
+ this.ironGrayToolStripMenuItem.Click += new System.EventHandler(this.ironGrayToolStripMenuItem_Click);
+ //
+ // redHotToolStripMenuItem
+ //
+ this.redHotToolStripMenuItem.Name = "redHotToolStripMenuItem";
+ this.redHotToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.redHotToolStripMenuItem.Text = "红热";
+ this.redHotToolStripMenuItem.Click += new System.EventHandler(this.redHotToolStripMenuItem_Click);
+ //
+ // rainbow2ToolStripMenuItem
+ //
+ this.rainbow2ToolStripMenuItem.Name = "rainbow2ToolStripMenuItem";
+ this.rainbow2ToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.rainbow2ToolStripMenuItem.Text = "彩虹2";
+ this.rainbow2ToolStripMenuItem.Click += new System.EventHandler(this.rainbow2ToolStripMenuItem_Click);
+ //
+ // whiteHotToolStripMenuItem
+ //
+ this.whiteHotToolStripMenuItem.Name = "whiteHotToolStripMenuItem";
+ this.whiteHotToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.whiteHotToolStripMenuItem.Text = "白热";
+ this.whiteHotToolStripMenuItem.Click += new System.EventHandler(this.whiteHotToolStripMenuItem_Click);
+ //
+ // blackHotToolStripMenuItem
+ //
+ this.blackHotToolStripMenuItem.Name = "blackHotToolStripMenuItem";
+ this.blackHotToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.blackHotToolStripMenuItem.Text = "黑热";
+ this.blackHotToolStripMenuItem.Click += new System.EventHandler(this.blackHotToolStripMenuItem_Click);
+ //
+ // 已移除蓝红菜单项(不在SDK的8种标准色板中)
+ //
// Camera
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
@@ -38,6 +131,7 @@
this.Size = new System.Drawing.Size(512, 384);
this.Load += new System.EventHandler(this.Camera_Load);
((System.ComponentModel.ISupportInitialize)(this.imageBox)).EndInit();
+ this.contextMenuStrip1.ResumeLayout(false);
this.ResumeLayout(false);
}
@@ -45,5 +139,15 @@
#endregion
private System.Windows.Forms.PictureBox imageBox;
+ private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem colorModeToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem whiteHotToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem blackHotToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem ironRedToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem lavaToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem rainbowToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem ironGrayToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem redHotToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem rainbow2ToolStripMenuItem;
}
}
diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs b/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs
index b052b60..3eea4bc 100644
--- a/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs
+++ b/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs
@@ -853,6 +853,162 @@ namespace JoyD.Windows.CS.Toprie
}
}
+ #region 色彩模式切换方法
+
+ ///
+ /// 白热色彩模式
+ ///
+ private void whiteHotToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ if (_deviceManager != null)
+ {
+ Console.WriteLine("切换到白热色彩模式");
+ _deviceManager.SetPaletteType(PaletteType.WhiteHot);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"切换到白热色彩模式失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 黑热色彩模式
+ ///
+ private void blackHotToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ if (_deviceManager != null)
+ {
+ Console.WriteLine("切换到黑热色彩模式");
+ _deviceManager.SetPaletteType(PaletteType.BlackHot);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"切换到黑热色彩模式失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 铁红色彩模式
+ ///
+ private void ironRedToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ if (_deviceManager != null)
+ {
+ Console.WriteLine("切换到铁红色彩模式");
+ _deviceManager.SetPaletteType(PaletteType.IronRed);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"切换到铁红色彩模式失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 熔岩色彩模式
+ ///
+ private void lavaToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ if (_deviceManager != null)
+ {
+ Console.WriteLine("切换到熔岩色彩模式");
+ _deviceManager.SetPaletteType(PaletteType.Lava);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"切换到熔岩色彩模式失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 彩虹色彩模式
+ ///
+ private void rainbowToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ if (_deviceManager != null)
+ {
+ Console.WriteLine("切换到彩虹色彩模式");
+ _deviceManager.SetPaletteType(PaletteType.Rainbow);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"切换到彩虹色彩模式失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 铁灰色彩模式
+ ///
+ private void ironGrayToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ if (_deviceManager != null)
+ {
+ Console.WriteLine("切换到铁灰色彩模式");
+ _deviceManager.SetPaletteType(PaletteType.IronGray);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"切换到铁灰色彩模式失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 红热色彩模式
+ ///
+ private void redHotToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ if (_deviceManager != null)
+ {
+ Console.WriteLine("切换到红热色彩模式");
+ _deviceManager.SetPaletteType(PaletteType.RedHot);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"切换到红热色彩模式失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 彩虹2色彩模式
+ ///
+ private void rainbow2ToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ if (_deviceManager != null)
+ {
+ Console.WriteLine("切换到彩虹2色彩模式");
+ _deviceManager.SetPaletteType(PaletteType.Rainbow2);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"切换到彩虹2色彩模式失败: {ex.Message}");
+ }
+ }
+
+ #endregion
+
///
/// 清理资源
///
diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs
index 0d8b01e..3d356ba 100644
--- a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs
+++ b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs
@@ -37,6 +37,22 @@ namespace JoyD.Windows.CS.Toprie
Fusion
}
+ ///
+ /// 色彩模式枚举
+ /// 对应SDK文档中的8种色板模式:白热、黑热、铁红、熔岩、彩虹、铁灰、红热、彩虹2
+ ///
+ public enum PaletteType
+ {
+ WhiteHot, // 白热,对应SDK参数0
+ BlackHot, // 黑热,对应SDK参数1
+ IronRed, // 铁红,对应SDK参数2
+ Lava, // 熔岩,对应SDK参数3
+ Rainbow, // 彩虹,对应SDK参数4
+ IronGray, // 铁灰,对应SDK参数5
+ RedHot, // 红热,对应SDK参数6
+ Rainbow2 // 彩虹2,对应SDK参数7
+ }
+
///
/// 连接状态改变事件参数
///
@@ -1711,6 +1727,32 @@ namespace JoyD.Windows.CS.Toprie
CurrentImageMode = mode;
}
+ ///
+ /// 设置色彩模式
+ ///
+ /// 色彩模式
+ public void SetPaletteType(PaletteType paletteType)
+ {
+ try
+ {
+ if (_a8Sdk != null)
+ {
+ // 将PaletteType枚举转换为int类型并发送命令
+ // 按照SDK文档中的参数映射:白热(0)、黑热(1)、铁红(2)、熔岩(3)、彩虹(4)、铁灰(5)、红热(6)、彩虹2(7)
+ int paletteValue = (int)paletteType;
+
+ // 尝试设置色彩模式
+ _a8Sdk.Color_plate = paletteValue;
+ Console.WriteLine($"色彩模式设置成功: {paletteType} (值: {paletteValue})");
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"设置色彩模式失败: {ex.Message}");
+ // 发生异常时可以考虑恢复到之前的设置或记录错误
+ }
+ }
+
///
/// 发送模式切换命令
///
diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/Toprie.csproj b/Windows/CS/Framework4.0/Toprie/Toprie/Toprie.csproj
index fdd4ec2..817a1a5 100644
--- a/Windows/CS/Framework4.0/Toprie/Toprie/Toprie.csproj
+++ b/Windows/CS/Framework4.0/Toprie/Toprie/Toprie.csproj
@@ -73,6 +73,7 @@
+
diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/UdpCommunicationManager.cs b/Windows/CS/Framework4.0/Toprie/Toprie/UdpCommunicationManager.cs
new file mode 100644
index 0000000..615d5f5
--- /dev/null
+++ b/Windows/CS/Framework4.0/Toprie/Toprie/UdpCommunicationManager.cs
@@ -0,0 +1,341 @@
+using System;
+using System.Collections.Generic;
+using System.Net.Sockets;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace JoyD.Windows.CS.Toprie
+{
+ ///
+ /// UDP通信管理器,负责管理所有UDP通信,实现请求-响应匹配和状态管理
+ /// 防止异步数据相互影响
+ ///
+ public class UdpCommunicationManager : IDisposable
+ {
+ // 单例实例
+ private static readonly UdpCommunicationManager _instance = new UdpCommunicationManager();
+
+ // 命令队列
+ private readonly Queue _requestQueue = new Queue();
+
+ // 请求映射表,用于匹配请求和响应
+ private readonly Dictionary _activeRequests = new Dictionary();
+
+ // 锁对象,保护共享资源
+ private readonly object _queueLock = new object();
+ private readonly object _requestLock = new object();
+
+ // UDP客户端实例
+ private UdpClient _udpClient;
+
+ // 工作线程
+ private Thread _workerThread;
+ private bool _isRunning;
+
+ // 信号量,用于通知工作线程有新请求
+ private AutoResetEvent _requestAvailable = new AutoResetEvent(false);
+
+ // 默认端口
+ private const int DEFAULT_UDP_PORT = 18890;
+
+ // 请求超时时间(毫秒)
+ private const int DEFAULT_TIMEOUT = 500;
+
+ ///
+ /// 获取UdpCommunicationManager的单例实例
+ ///
+ public static UdpCommunicationManager Instance => _instance;
+
+ ///
+ /// 私有构造函数,初始化UDP通信管理器
+ ///
+ private UdpCommunicationManager()
+ {
+ Initialize();
+ }
+
+ ///
+ /// 初始化UDP通信管理器
+ ///
+ private void Initialize()
+ {
+ try
+ {
+ // 创建UDP客户端
+ _udpClient = new UdpClient();
+ _udpClient.Client.ReceiveTimeout = DEFAULT_TIMEOUT;
+
+ // 启动工作线程
+ _isRunning = true;
+ _workerThread = new Thread(ProcessRequests);
+ _workerThread.IsBackground = true;
+ _workerThread.Start();
+
+ Console.WriteLine("UDP通信管理器已初始化");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"UDP通信管理器初始化失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 处理请求队列的工作线程函数
+ ///
+ private void ProcessRequests()
+ {
+ while (_isRunning)
+ {
+ // 等待请求可用信号
+ _requestAvailable.WaitOne();
+
+ if (!_isRunning) break;
+
+ UdpRequest request = null;
+
+ // 从队列中获取请求
+ lock (_queueLock)
+ {
+ if (_requestQueue.Count > 0)
+ {
+ request = _requestQueue.Dequeue();
+ }
+ }
+
+ if (request != null)
+ {
+ // 处理请求
+ ProcessRequest(request);
+ }
+ }
+ }
+
+ ///
+ /// 处理单个UDP请求
+ ///
+ /// UDP请求对象
+ private void ProcessRequest(UdpRequest request)
+ {
+ try
+ {
+ Console.WriteLine($"处理UDP请求: {request.RequestId}, 目标: {request.TargetIp}:{request.Port}");
+
+ // 将请求添加到活动请求列表
+ lock (_requestLock)
+ {
+ _activeRequests[request.RequestId] = request;
+ }
+
+ // 发送UDP数据报
+ _udpClient.Send(request.Data, request.Data.Length, request.TargetIp, request.Port);
+ Console.WriteLine($"UDP命令已发送: {Encoding.ASCII.GetString(request.Data)}");
+
+ // 启动异步接收响应
+ IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
+ IAsyncResult ar = _udpClient.BeginReceive(result =>
+ {
+ try
+ {
+ byte[] responseData = _udpClient.EndReceive(result, ref remoteEndPoint);
+ HandleResponse(request.RequestId, responseData);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"接收UDP响应异常: {ex.Message}");
+ HandleTimeout(request.RequestId);
+ }
+ }, null);
+
+ // 设置超时处理(兼容.NET Framework 4.0)
+ ThreadPool.QueueUserWorkItem(state =>
+ {
+ string requestId = (string)state;
+ Thread.Sleep(request.Timeout);
+ HandleTimeout(requestId);
+ }, request.RequestId);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"处理UDP请求异常: {ex.Message}");
+ request.OnResponse?.Invoke(null, true); // 通知请求失败
+
+ // 从活动请求列表中移除
+ lock (_requestLock)
+ {
+ _activeRequests.Remove(request.RequestId);
+ }
+ }
+ }
+
+ ///
+ /// 处理接收到的UDP响应
+ ///
+ /// 请求ID
+ /// 响应数据
+ private void HandleResponse(string requestId, byte[] responseData)
+ {
+ UdpRequest request = null;
+
+ // 查找对应的请求
+ lock (_requestLock)
+ {
+ if (_activeRequests.TryGetValue(requestId, out request))
+ {
+ _activeRequests.Remove(requestId);
+ }
+ }
+
+ if (request != null)
+ {
+ Console.WriteLine($"收到UDP响应: {requestId}, 长度: {responseData?.Length ?? 0}");
+ request.OnResponse?.Invoke(responseData, false); // 通知请求成功
+ }
+ }
+
+ ///
+ /// 处理请求超时
+ ///
+ /// 请求ID
+ private void HandleTimeout(string requestId)
+ {
+ UdpRequest request = null;
+
+ // 查找对应的请求
+ lock (_requestLock)
+ {
+ if (_activeRequests.TryGetValue(requestId, out request))
+ {
+ _activeRequests.Remove(requestId);
+ }
+ }
+
+ if (request != null)
+ {
+ Console.WriteLine($"UDP请求超时: {requestId}");
+ request.OnResponse?.Invoke(null, true); // 通知请求超时
+ }
+ }
+
+ ///
+ /// 发送UDP请求
+ ///
+ /// 目标IP地址
+ /// 要发送的数据
+ /// 目标端口,默认为18890
+ /// 超时时间(毫秒),默认为500
+ /// 包含响应数据的Task
+ public Task SendRequestAsync(string targetIp, byte[] data, int port = DEFAULT_UDP_PORT, int timeout = DEFAULT_TIMEOUT)
+ {
+ var tcs = new TaskCompletionSource();
+ string requestId = Guid.NewGuid().ToString();
+
+ var request = new UdpRequest
+ {
+ RequestId = requestId,
+ TargetIp = targetIp,
+ Port = port,
+ Data = data,
+ Timeout = timeout,
+ OnResponse = (response, isTimeout) =>
+ {
+ if (isTimeout)
+ {
+ tcs.TrySetResult(null);
+ }
+ else
+ {
+ tcs.TrySetResult(response);
+ }
+ }
+ };
+
+ // 将请求添加到队列
+ lock (_queueLock)
+ {
+ _requestQueue.Enqueue(request);
+ }
+
+ // 通知工作线程有新请求
+ _requestAvailable.Set();
+
+ return tcs.Task;
+ }
+
+ ///
+ /// 同步发送UDP请求
+ ///
+ /// 目标IP地址
+ /// 要发送的数据
+ /// 目标端口,默认为18890
+ /// 超时时间(毫秒),默认为500
+ /// 响应数据,如果超时则返回null
+ public byte[] SendRequest(string targetIp, byte[] data, int port = DEFAULT_UDP_PORT, int timeout = DEFAULT_TIMEOUT)
+ {
+ try
+ {
+ var task = SendRequestAsync(targetIp, data, port, timeout);
+ task.Wait(timeout);
+ return task.Result;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"同步发送UDP请求异常: {ex.Message}");
+ return null;
+ }
+ }
+
+ ///
+ /// 清理资源
+ ///
+ public void Dispose()
+ {
+ _isRunning = false;
+ _requestAvailable.Set(); // 唤醒工作线程以便它可以退出
+
+ if (_workerThread != null && _workerThread.IsAlive)
+ {
+ _workerThread.Join(1000); // 等待工作线程退出
+ }
+
+ if (_udpClient != null)
+ {
+ _udpClient.Close();
+ _udpClient = null;
+ }
+
+ if (_requestAvailable != null)
+ {
+ _requestAvailable.Dispose();
+ _requestAvailable = null;
+ }
+
+ // 清空请求队列和活动请求
+ lock (_queueLock)
+ {
+ _requestQueue.Clear();
+ }
+
+ lock (_requestLock)
+ {
+ _activeRequests.Clear();
+ }
+
+ Console.WriteLine("UDP通信管理器已释放");
+ }
+
+ ///
+ /// UDP请求类,封装单个UDP请求的信息
+ ///
+ private class UdpRequest
+ {
+ public string RequestId { get; set; }
+ public string TargetIp { get; set; }
+ public int Port { get; set; }
+ public byte[] Data { get; set; }
+ public int Timeout { get; set; }
+ public Action OnResponse { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/V8.cs b/Windows/CS/Framework4.0/Toprie/Toprie/V8.cs
index e45592e..6fc3661 100644
--- a/Windows/CS/Framework4.0/Toprie/Toprie/V8.cs
+++ b/Windows/CS/Framework4.0/Toprie/Toprie/V8.cs
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
-using System.Net.Sockets;
using System.Text;
+using System.Net.Sockets;
+using System.Net;
using System.Threading;
using System.IO;
using System.Runtime.InteropServices;
-using System.Net;
+// 导入UDP通信管理器
+using JoyD.Windows.CS.Toprie;
namespace JoyD.Windows.CS.Toprie
{
@@ -187,25 +189,20 @@ namespace JoyD.Windows.CS.Toprie
try
{
- // 修改为UDP协议,与SDK保持一致
- // SDK中使用的是UDP协议(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))
- // 端口使用18890,与SDK中的CMD_SERVER_UDP_PORT保持一致
- using (UdpClient udpClient = new UdpClient())
+ // 使用UDP通信管理器发送请求
+ response = UdpCommunicationManager.Instance.SendRequest(deviceIp, command, 18890, 200);
+
+ if (response != null)
{
- // 设置接收超时,与SDK中的超时保持一致
- udpClient.Client.ReceiveTimeout = 200; // SDK中普通命令超时为200ms
-
- // 发送UDP数据报,端口使用18890与SDK保持一致
- udpClient.Send(command, command.Length, deviceIp, 18890);
Console.WriteLine($"UDP命令已发送到 {deviceIp}:18890");
-
- // 尝试接收响应
- IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
- response = udpClient.Receive(ref remoteEndPoint);
-
Console.WriteLine($"收到UDP命令响应,长度: {response.Length}");
return true;
}
+ else
+ {
+ Console.WriteLine($"UDP命令发送后未收到响应或超时");
+ return false;
+ }
}
catch (Exception ex)
{
@@ -221,28 +218,23 @@ namespace JoyD.Windows.CS.Toprie
try
{
- // 修改为UDP协议,与SDK保持一致
- // SDK中使用的是UDP协议(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))
- // 端口使用18890,与SDK中的CMD_SERVER_UDP_PORT保持一致
- using (UdpClient udpClient = new UdpClient())
+ // 使用UDP通信管理器发送请求
+ byte[] responseBytes = UdpCommunicationManager.Instance.SendRequest(deviceIp,
+ Encoding.ASCII.GetBytes(cmd), 18890, 200);
+
+ if (responseBytes != null)
{
- // 设置接收超时,与SDK中的超时保持一致
- udpClient.Client.ReceiveTimeout = 200; // SDK中普通命令超时为200ms
-
- // 发送UDP数据报,端口使用18890与SDK保持一致
- byte[] commandBytes = Encoding.ASCII.GetBytes(cmd);
- udpClient.Send(commandBytes, commandBytes.Length, deviceIp, 18890);
+ response = Encoding.ASCII.GetString(responseBytes);
Console.WriteLine($"UDP命令已发送: {cmd}");
Console.WriteLine($"目标IP: {deviceIp}:18890");
-
- // 尝试接收响应
- IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
- byte[] responseBytes = udpClient.Receive(ref remoteEndPoint);
- response = Encoding.ASCII.GetString(responseBytes);
-
Console.WriteLine($"收到UDP命令响应: {response}");
return true;
}
+ else
+ {
+ Console.WriteLine($"UDP命令发送后未收到响应或超时: {cmd}");
+ return false;
+ }
}
catch (Exception ex)
@@ -1666,10 +1658,7 @@ namespace JoyD.Windows.CS.Toprie
// 使用UDP协议发送心跳命令,与SDK保持一致
public int Heartbeat()
{
- // 关键修改:与SDK保持一致,使用UDP协议发送心跳命令
- // SDK中使用的是UDP协议(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))
- // 之前的实现使用了TCP协议,这是心跳失败的根本原因
- // 端口修改为18890,与SDK中的CMD_SERVER_UDP_PORT保持一致
+ // 使用UDP通信管理器进行心跳检测,防止异步数据相互影响
try
{
// 根据SDK实际实现,心跳命令格式是 +CMD:24$
@@ -1683,71 +1672,47 @@ namespace JoyD.Windows.CS.Toprie
Console.WriteLine($"心跳命令: {command}");
Console.WriteLine($"目标IP: {deviceIp}:18890");
- using (UdpClient udpClient = new UdpClient())
+ try
{
- try
+ // 使用UDP通信管理器发送心跳请求,设置500ms超时
+ byte[] responseBytes = UdpCommunicationManager.Instance.SendRequest(deviceIp,
+ commandBytes, 18890, 500);
+
+ Console.WriteLine("UDP心跳命令已发送,等待响应...");
+
+ if (responseBytes != null)
{
- // 注意:SDK中tv_out.tv_sec=50实际表示50秒,这是SDK的实现方式
- // 这里我们设置一个更合理的值500毫秒,既保证能接收到响应,又不会等待太久
- udpClient.Client.ReceiveTimeout = 500;
+ string response = Encoding.ASCII.GetString(responseBytes);
- // 发送UDP数据报,端口使用18890与SDK保持一致
- udpClient.Send(commandBytes, commandBytes.Length, deviceIp, 18890);
- Console.WriteLine("UDP心跳命令已发送,等待响应...");
-
- // 尝试接收响应
- IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
-
- // 使用BeginReceive和EndReceive进行非阻塞接收,更好地处理超时
- IAsyncResult ar = udpClient.BeginReceive(null, null);
- if (ar.AsyncWaitHandle.WaitOne(500)) // 额外的超时检查,双重保险
+ Console.WriteLine($"收到UDP心跳响应: {response}");
+ // 不使用LINQ的Select方法,避免缺少System.Linq命名空间的问题
+ string[] asciiValues = new string[response.Length];
+ for (int i = 0; i < response.Length; i++)
{
- try
- {
- byte[] responseBytes = udpClient.EndReceive(ar, ref remoteEndPoint);
- string response = Encoding.ASCII.GetString(responseBytes);
-
- Console.WriteLine($"收到UDP心跳响应: {response}");
- // 不使用LINQ的Select方法,避免缺少System.Linq命名空间的问题
- string[] asciiValues = new string[response.Length];
- for (int i = 0; i < response.Length; i++)
- {
- asciiValues[i] = ((int)response[i]).ToString();
- }
- Console.WriteLine($"响应长度: {response.Length} 字节,响应ASCII码: {string.Join(",", asciiValues)}");
-
- // SDK要求响应中必须包含 ":ok" 字符串才算成功
- if (!string.IsNullOrEmpty(response) && response.Contains(":ok"))
- {
- Console.WriteLine("心跳成功: 响应包含':ok'");
- return 1; // 返回1表示成功,与DeviceManager中的heartbeatResult > 0判断一致
- }
- else
- {
- Console.WriteLine($"心跳响应不包含':ok',验证失败。收到的响应: '{response}'");
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"处理UDP响应时发生异常: {ex.Message}");
- }
+ asciiValues[i] = ((int)response[i]).ToString();
+ }
+ Console.WriteLine($"响应长度: {response.Length} 字节,响应ASCII码: {string.Join(",", asciiValues)}");
+
+ // SDK要求响应中必须包含 ":ok" 字符串才算成功
+ if (!string.IsNullOrEmpty(response) && response.Contains(":ok"))
+ {
+ Console.WriteLine("心跳成功: 响应包含':ok'");
+ return 1; // 返回1表示成功,与DeviceManager中的heartbeatResult > 0判断一致
}
else
{
- Console.WriteLine("UDP接收超时,取消接收操作");
- udpClient.Close(); // 关闭以取消接收操作
+ Console.WriteLine($"心跳响应不包含':ok',验证失败。收到的响应: '{response}'");
}
}
- catch (SocketException ex) when (ex.SocketErrorCode == SocketError.TimedOut)
+ else
{
- // 超时异常,继续重试
- Console.WriteLine("UDP心跳接收超时");
- }
- catch (Exception ex)
- {
- Console.WriteLine($"UDP心跳异常: {ex.Message}");
+ Console.WriteLine("UDP心跳未收到响应或超时");
}
}
+ catch (Exception ex)
+ {
+ Console.WriteLine($"UDP心跳异常: {ex.Message}");
+ }
// 如果不是最后一次尝试,短暂延迟后重试
if (retry < 2)