增加菜单
This commit is contained in:
104
Windows/CS/Framework4.0/Toprie/Toprie/Camera.Designer.cs
generated
104
Windows/CS/Framework4.0/Toprie/Toprie/Camera.Designer.cs
generated
@@ -15,12 +15,25 @@
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -853,6 +853,162 @@ namespace JoyD.Windows.CS.Toprie
|
||||
}
|
||||
}
|
||||
|
||||
#region 色彩模式切换方法
|
||||
|
||||
/// <summary>
|
||||
/// 白热色彩模式
|
||||
/// </summary>
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 黑热色彩模式
|
||||
/// </summary>
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 铁红色彩模式
|
||||
/// </summary>
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 熔岩色彩模式
|
||||
/// </summary>
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 彩虹色彩模式
|
||||
/// </summary>
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 铁灰色彩模式
|
||||
/// </summary>
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 红热色彩模式
|
||||
/// </summary>
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 彩虹2色彩模式
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// 清理资源
|
||||
/// </summary>
|
||||
|
||||
@@ -37,6 +37,22 @@ namespace JoyD.Windows.CS.Toprie
|
||||
Fusion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 色彩模式枚举
|
||||
/// 对应SDK文档中的8种色板模式:白热、黑热、铁红、熔岩、彩虹、铁灰、红热、彩虹2
|
||||
/// </summary>
|
||||
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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接状态改变事件参数
|
||||
/// </summary>
|
||||
@@ -1711,6 +1727,32 @@ namespace JoyD.Windows.CS.Toprie
|
||||
CurrentImageMode = mode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置色彩模式
|
||||
/// </summary>
|
||||
/// <param name="paletteType">色彩模式</param>
|
||||
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}");
|
||||
// 发生异常时可以考虑恢复到之前的设置或记录错误
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送模式切换命令
|
||||
/// </summary>
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
<Compile Include="DeviceManager.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SharedStructures.cs" />
|
||||
<Compile Include="UdpCommunicationManager.cs" />
|
||||
<Compile Include="V8.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
341
Windows/CS/Framework4.0/Toprie/Toprie/UdpCommunicationManager.cs
Normal file
341
Windows/CS/Framework4.0/Toprie/Toprie/UdpCommunicationManager.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// UDP通信管理器,负责管理所有UDP通信,实现请求-响应匹配和状态管理
|
||||
/// 防止异步数据相互影响
|
||||
/// </summary>
|
||||
public class UdpCommunicationManager : IDisposable
|
||||
{
|
||||
// 单例实例
|
||||
private static readonly UdpCommunicationManager _instance = new UdpCommunicationManager();
|
||||
|
||||
// 命令队列
|
||||
private readonly Queue<UdpRequest> _requestQueue = new Queue<UdpRequest>();
|
||||
|
||||
// 请求映射表,用于匹配请求和响应
|
||||
private readonly Dictionary<string, UdpRequest> _activeRequests = new Dictionary<string, UdpRequest>();
|
||||
|
||||
// 锁对象,保护共享资源
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// 获取UdpCommunicationManager的单例实例
|
||||
/// </summary>
|
||||
public static UdpCommunicationManager Instance => _instance;
|
||||
|
||||
/// <summary>
|
||||
/// 私有构造函数,初始化UDP通信管理器
|
||||
/// </summary>
|
||||
private UdpCommunicationManager()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化UDP通信管理器
|
||||
/// </summary>
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理请求队列的工作线程函数
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理单个UDP请求
|
||||
/// </summary>
|
||||
/// <param name="request">UDP请求对象</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理接收到的UDP响应
|
||||
/// </summary>
|
||||
/// <param name="requestId">请求ID</param>
|
||||
/// <param name="responseData">响应数据</param>
|
||||
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); // 通知请求成功
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理请求超时
|
||||
/// </summary>
|
||||
/// <param name="requestId">请求ID</param>
|
||||
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); // 通知请求超时
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送UDP请求
|
||||
/// </summary>
|
||||
/// <param name="targetIp">目标IP地址</param>
|
||||
/// <param name="data">要发送的数据</param>
|
||||
/// <param name="port">目标端口,默认为18890</param>
|
||||
/// <param name="timeout">超时时间(毫秒),默认为500</param>
|
||||
/// <returns>包含响应数据的Task</returns>
|
||||
public Task<byte[]> SendRequestAsync(string targetIp, byte[] data, int port = DEFAULT_UDP_PORT, int timeout = DEFAULT_TIMEOUT)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<byte[]>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步发送UDP请求
|
||||
/// </summary>
|
||||
/// <param name="targetIp">目标IP地址</param>
|
||||
/// <param name="data">要发送的数据</param>
|
||||
/// <param name="port">目标端口,默认为18890</param>
|
||||
/// <param name="timeout">超时时间(毫秒),默认为500</param>
|
||||
/// <returns>响应数据,如果超时则返回null</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理资源
|
||||
/// </summary>
|
||||
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通信管理器已释放");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UDP请求类,封装单个UDP请求的信息
|
||||
/// </summary>
|
||||
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<byte[], bool> OnResponse { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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())
|
||||
{
|
||||
// 设置接收超时,与SDK中的超时保持一致
|
||||
udpClient.Client.ReceiveTimeout = 200; // SDK中普通命令超时为200ms
|
||||
// 使用UDP通信管理器发送请求
|
||||
byte[] responseBytes = UdpCommunicationManager.Instance.SendRequest(deviceIp,
|
||||
Encoding.ASCII.GetBytes(cmd), 18890, 200);
|
||||
|
||||
// 发送UDP数据报,端口使用18890与SDK保持一致
|
||||
byte[] commandBytes = Encoding.ASCII.GetBytes(cmd);
|
||||
udpClient.Send(commandBytes, commandBytes.Length, deviceIp, 18890);
|
||||
if (responseBytes != null)
|
||||
{
|
||||
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,28 +1672,16 @@ namespace JoyD.Windows.CS.Toprie
|
||||
Console.WriteLine($"心跳命令: {command}");
|
||||
Console.WriteLine($"目标IP: {deviceIp}:18890");
|
||||
|
||||
using (UdpClient udpClient = new UdpClient())
|
||||
{
|
||||
try
|
||||
{
|
||||
// 注意:SDK中tv_out.tv_sec=50实际表示50秒,这是SDK的实现方式
|
||||
// 这里我们设置一个更合理的值500毫秒,既保证能接收到响应,又不会等待太久
|
||||
udpClient.Client.ReceiveTimeout = 500;
|
||||
// 使用UDP通信管理器发送心跳请求,设置500ms超时
|
||||
byte[] responseBytes = UdpCommunicationManager.Instance.SendRequest(deviceIp,
|
||||
commandBytes, 18890, 500);
|
||||
|
||||
// 发送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)) // 额外的超时检查,双重保险
|
||||
if (responseBytes != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] responseBytes = udpClient.EndReceive(ar, ref remoteEndPoint);
|
||||
string response = Encoding.ASCII.GetString(responseBytes);
|
||||
|
||||
Console.WriteLine($"收到UDP心跳响应: {response}");
|
||||
@@ -1727,27 +1704,15 @@ namespace JoyD.Windows.CS.Toprie
|
||||
Console.WriteLine($"心跳响应不包含':ok',验证失败。收到的响应: '{response}'");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"处理UDP响应时发生异常: {ex.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("UDP接收超时,取消接收操作");
|
||||
udpClient.Close(); // 关闭以取消接收操作
|
||||
Console.WriteLine("UDP心跳未收到响应或超时");
|
||||
}
|
||||
}
|
||||
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.TimedOut)
|
||||
{
|
||||
// 超时异常,继续重试
|
||||
Console.WriteLine("UDP心跳接收超时");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"UDP心跳异常: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 如果不是最后一次尝试,短暂延迟后重试
|
||||
if (retry < 2)
|
||||
|
||||
Reference in New Issue
Block a user