增加菜单

This commit is contained in:
zqm
2025-10-28 10:29:11 +08:00
parent f09bf047d3
commit 6da609c10f
6 changed files with 698 additions and 89 deletions

View File

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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

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

View File

@@ -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)