This commit is contained in:
JoyD
2025-10-30 21:45:27 +08:00
8 changed files with 1038 additions and 522 deletions

View File

@@ -1,3 +1,15 @@
# JoyD
久鼎代码库
### 修改流程:
1. 暂停或恢复时设置暂停状态调用更新Info
2. 断开或连接时设置连接状态调用更新Info
3. Ping通状态变化时修改Ping状态调用更新Info
4. 图像更新时, 保存LastImage, 调用更新到UI
### 更新Info:
1. 如果暂停显示暂停信息否则如果Ping不通或断开显示重连信息否则清空InfoImage
2. 最后调用更新UI
### 更新UI:
1. 先将LastImage绘制到全局缓冲
2. 再将InfoImage绘制到缓冲
3. 最后一次性绘制到图像框的bitmap

View File

@@ -35,6 +35,8 @@ namespace JoyD.Windows.CS.Toprie
this.ironGrayToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.redHotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.rainbow2ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.pauseDetectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
((System.ComponentModel.ISupportInitialize)(this.imageBox)).BeginInit();
this.contextMenuStrip1.SuspendLayout();
this.SuspendLayout();
@@ -54,9 +56,11 @@ namespace JoyD.Windows.CS.Toprie
//
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.imageModeToolStripMenuItem,
this.colorModeToolStripMenuItem});
this.colorModeToolStripMenuItem,
this.toolStripSeparator1,
this.pauseDetectionToolStripMenuItem});
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(161, 74);
this.contextMenuStrip1.Size = new System.Drawing.Size(161, 100);
//
// imageModeToolStripMenuItem
//
@@ -72,14 +76,14 @@ namespace JoyD.Windows.CS.Toprie
this.thermalModeToolStripMenuItem.Name = "thermalModeToolStripMenuItem";
this.thermalModeToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.thermalModeToolStripMenuItem.Text = "红外模式";
this.thermalModeToolStripMenuItem.Click += new System.EventHandler(this.thermalModeToolStripMenuItem_Click);
this.thermalModeToolStripMenuItem.Click += new System.EventHandler(this.ThermalModeToolStripMenuItem_Click);
//
// visibleModeToolStripMenuItem
//
this.visibleModeToolStripMenuItem.Name = "visibleModeToolStripMenuItem";
this.visibleModeToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.visibleModeToolStripMenuItem.Text = "自然模式";
this.visibleModeToolStripMenuItem.Click += new System.EventHandler(this.visibleModeToolStripMenuItem_Click);
this.visibleModeToolStripMenuItem.Click += new System.EventHandler(this.VisibleModeToolStripMenuItem_Click);
//
// colorModeToolStripMenuItem
//
@@ -92,6 +96,18 @@ namespace JoyD.Windows.CS.Toprie
this.ironGrayToolStripMenuItem,
this.redHotToolStripMenuItem,
this.rainbow2ToolStripMenuItem});
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(157, 6);
//
// pauseDetectionToolStripMenuItem
//
this.pauseDetectionToolStripMenuItem.Name = "pauseDetectionToolStripMenuItem";
this.pauseDetectionToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
this.pauseDetectionToolStripMenuItem.Text = "暂停检测";
this.pauseDetectionToolStripMenuItem.Click += new System.EventHandler(this.PauseDetectionToolStripMenuItem_Click);
this.colorModeToolStripMenuItem.Name = "colorModeToolStripMenuItem";
this.colorModeToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
this.colorModeToolStripMenuItem.Text = "色彩模式";
@@ -101,56 +117,56 @@ namespace JoyD.Windows.CS.Toprie
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);
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);
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);
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);
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);
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);
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);
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);
this.blackHotToolStripMenuItem.Click += new System.EventHandler(this.BlackHotToolStripMenuItem_Click);
//
// 已移除蓝红菜单项不在SDK的8种标准色板中
//
@@ -158,6 +174,7 @@ namespace JoyD.Windows.CS.Toprie
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
// 添加imageBox
this.Controls.Add(this.imageBox);
this.Name = "Camera";
this.Size = new System.Drawing.Size(512, 384);
@@ -172,6 +189,8 @@ namespace JoyD.Windows.CS.Toprie
private System.Windows.Forms.PictureBox imageBox;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem pauseDetectionToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.ToolStripMenuItem colorModeToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem whiteHotToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem blackHotToolStripMenuItem;

File diff suppressed because it is too large Load Diff

View File

@@ -153,6 +153,9 @@ namespace JoyD.Windows.CS.Toprie
// 设计模式标志,用于在设计模式下跳过实际的设备连接和初始化
public static bool IsDesignMode { get; set; } = true;
// 暂停检测标志,用于控制是否进行连接检测和重连操作
public bool IsDetectionPaused { get; set; } = false;
// 项目路径,用于数据文件的存取
private string _projectPath = "";
@@ -165,7 +168,7 @@ namespace JoyD.Windows.CS.Toprie
private List<DeviceInfo> _deviceList = new List<DeviceInfo>();
// 目标设备ID用于指定ID连接
private int _targetDeviceId = -1;
private readonly int _targetDeviceId = -1;
// 当前设备ID
private int _currentDeviceId = -1;
// 默认设备IP
@@ -177,7 +180,7 @@ namespace JoyD.Windows.CS.Toprie
// 是否已初始化
private bool _isInitialized = false;
// 是否已释放
private bool _isDisposed = false;
private readonly bool _isDisposed = false;
// 图像模式
private ImageMode _currentImageMode = ImageMode.Infrared;
// 当前色彩模式
@@ -185,14 +188,12 @@ namespace JoyD.Windows.CS.Toprie
// 当前视频模式
private VideoMode _currentVideoMode = VideoMode.Infrared; // 默认红外模式
// 自动重连是否启用
private bool _autoReconnectEnabled = true;
// 自动重连定时器
private System.Threading.Timer _reconnectTimer;
// 重连间隔(毫秒)
private int _reconnectInterval = 2000;
private int _connectionCheckInterval = 5000;
// 重连尝试次数
private int _reconnectAttempts = 0;
// 最大重连尝试次数
public static int MaxReconnectAttempts = 5;
// 连接检查定时器
@@ -211,22 +212,17 @@ namespace JoyD.Windows.CS.Toprie
private const int DataReceivedTimeout = 15000; // 15秒内未收到数据则认为连接可能断开
// TCP客户端
// 该变量已在文件上方定义,删除重复实现
// 网络流
private NetworkStream _imageNetworkStream;
// 图像接收任务
private Task _imageReceivingTask;
// 取消令牌源
private CancellationTokenSource _imageReceivingCts;
// 停止请求事件
private ManualResetEvent _stopRequested = new ManualResetEvent(false);
// 缓冲区
private byte[] _imageBuffer = new byte[4096];
private readonly byte[] _imageBuffer = new byte[4096];
// 图像数据累积缓冲区
private byte[] _imageDataAccumulator = new byte[0];
private readonly byte[] _imageDataAccumulator = new byte[0];
// 多部分请求边界
private string _multipartBoundary = string.Empty;
private readonly string _multipartBoundary = string.Empty;
// 锁对象
private object _lockObject = new object();
private readonly object _lockObject = new object();
// 是否启用自动重连
private bool _isAutoReconnectEnabled = true;
// 最大重连次数
@@ -234,7 +230,7 @@ namespace JoyD.Windows.CS.Toprie
// 是否已连接
private bool _isConnected = false;
// 连接超时设置
private int _connectTimeout = 5000;
private readonly int _connectTimeout = 5000;
// 当前重连尝试次数
private int _currentReconnectAttempt = 0;
// 连接取消令牌源
@@ -384,7 +380,7 @@ namespace JoyD.Windows.CS.Toprie
// 保存状态变更相关信息供后续处理
ConnectionStatus finalNewStatus = newStatus;
bool shouldReconnect = (newStatus == ConnectionStatus.Disconnected && _autoReconnectEnabled && oldStatus != ConnectionStatus.Connecting);
bool shouldReconnect = (newStatus == ConnectionStatus.Disconnected && _isAutoReconnectEnabled && oldStatus != ConnectionStatus.Connecting);
bool shouldReset = (newStatus == ConnectionStatus.Connected);
// 添加状态转换验证,避免不合理的状态切换
@@ -872,7 +868,7 @@ namespace JoyD.Windows.CS.Toprie
/// <summary>
/// 启动连接状态检查
/// </summary>
private void StartConnectionCheck()
public void StartConnectionCheck()
{
lock (_lockObject) // 添加线程同步锁
{
@@ -885,6 +881,13 @@ namespace JoyD.Windows.CS.Toprie
return;
}
// 在暂停检测模式下,跳过连接检查
if (IsDetectionPaused)
{
Log("暂停检测模式下跳过连接检查");
return;
}
// 首先停止现有的连接检查,确保资源释放
StopConnectionCheck();
@@ -931,7 +934,7 @@ namespace JoyD.Windows.CS.Toprie
Log("重新初始化失败,确认连接已断开");
UpdateConnectionStatus(ConnectionStatus.Disconnected, "设备未初始化,连接已断开");
// 启动自动重连
if (_autoReconnectEnabled)
if (_isAutoReconnectEnabled)
{
StartAutoReconnect();
}
@@ -980,8 +983,8 @@ namespace JoyD.Windows.CS.Toprie
{
UpdateConnectionStatus(ConnectionStatus.Disconnected, "连接检查异常", ex);
_isInitialized = false;
// 启动自动重连
if (_autoReconnectEnabled)
// 启动自动重连,只有在未暂停检测时才执行
if (_isAutoReconnectEnabled && !IsDetectionPaused)
{
StartAutoReconnect();
}
@@ -1033,9 +1036,11 @@ namespace JoyD.Windows.CS.Toprie
// 先检查对象状态,避免不必要的操作
lock (_lockObject)
{
if (_isDisposed || _connectionStatus != ConnectionStatus.Connected)
if (_isDisposed || _connectionStatus != ConnectionStatus.Connected || IsDetectionPaused)
{
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 对象已释放或连接状态非Connected跳过检查");
string reason = _isDisposed ? "对象已释放" :
(_connectionStatus != ConnectionStatus.Connected ? "连接状态非Connected" : "检测已暂停");
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - {reason},跳过检查");
return;
}
}
@@ -1092,8 +1097,8 @@ namespace JoyD.Windows.CS.Toprie
UpdateConnectionStatus(ConnectionStatus.Disconnected, "连接已断开:设备离线");
// 断开连接后自动启动重连,但在锁外执行
if (_autoReconnectEnabled)
// 断开连接后自动启动重连,但在锁外执行,只有在未暂停检测时才执行
if (_isAutoReconnectEnabled && !IsDetectionPaused)
{
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 连接断开,将启动自动重连");
// 在锁外启动自动重连,避免潜在的死锁
@@ -1121,6 +1126,13 @@ namespace JoyD.Windows.CS.Toprie
return true;
}
// 在暂停检测模式下,跳过连接有效性检查,直接返回连接有效
if (IsDetectionPaused)
{
Log("暂停检测模式下跳过连接有效性检查,模拟连接有效");
return true;
}
// 注意此方法被CheckConnectionWrapper调用已经在线程安全的上下文中
// 不需要额外加锁但需要确保SDK实例的访问是线程安全的
@@ -1598,7 +1610,6 @@ namespace JoyD.Windows.CS.Toprie
}
Log("开始使用HTTP方式接收图像数据");
bool existed = false;
try
{
// 确保之前的连接已关闭
@@ -2448,29 +2459,52 @@ namespace JoyD.Windows.CS.Toprie
{
try
{
// 确保设备已连接且SDK实例有效
if (_connectionStatus == ConnectionStatus.Connected && _a8Sdk != null)
// 使用SDK操作锁保护对_a8Sdk的访问
lock (_sdkOperationLock)
{
// 获取当前设备的色彩模式值
int currentValue = _a8Sdk.GetColorPlate();
Log($"从设备读取的色彩模式值: {currentValue}");
// 尝试将读取到的值转换为PaletteType枚举并更新内部状态
if (Enum.IsDefined(typeof(PaletteType), currentValue))
// 确保设备已连接且SDK实例有效
if (_connectionStatus == ConnectionStatus.Connected && _a8Sdk != null)
{
PaletteType actualPalette = (PaletteType)currentValue;
_currentPaletteType = actualPalette;
Log($"已更新内部状态为设备实际值: {actualPalette}");
try
{
// 获取当前设备的色彩模式值
int currentValue = _a8Sdk.GetColorPlate();
Log($"从设备读取的色彩模式值: {currentValue}");
// 尝试将读取到的值转换为PaletteType枚举并更新内部状态
if (Enum.IsDefined(typeof(PaletteType), currentValue))
{
PaletteType actualPalette = (PaletteType)currentValue;
_currentPaletteType = actualPalette;
Log($"已更新内部状态为设备实际值: {actualPalette}");
}
else
{
Log($"警告:设备返回的色彩模式值 {currentValue} 不在枚举定义范围内,使用默认值");
}
}
catch (Exception ex)
{
Log($"从设备读取色彩模式时出错: {ex.Message}");
// 尝试重新创建SDK实例
Log("尝试重新创建SDK实例...");
try
{
_a8Sdk = new A8SDK(_deviceIp);
Log("SDK实例已重新创建");
}
catch (Exception recreateEx)
{
Log($"重新创建SDK实例失败: {recreateEx.Message}");
}
throw;
}
}
else
{
Log($"警告:设备返回的色彩模式值 {currentValue} 不在枚举定义范围内,使用默认值");
Log($"同步色彩模式失败设备未连接或SDK未初始化");
}
}
else
{
Log($"同步色彩模式失败设备未连接或SDK未初始化");
}
}
catch (Exception ex)
{
@@ -2504,11 +2538,27 @@ namespace JoyD.Windows.CS.Toprie
// 重试间隔(毫秒)
const int retryDelayMs = 100;
// 确保SDK实例存在如果不存在则尝试创建
if (_a8Sdk == null)
{
Log("SDK实例为空尝试创建新实例...");
try
{
_a8Sdk = new A8SDK(_deviceIp);
Log("SDK实例创建成功");
}
catch (Exception ex)
{
Log($"创建SDK实例失败: {ex.Message}");
return false;
}
}
// 先获取原始值,只读取一次,避免嵌套调用
int originalValue = -1;
try
{
if (_a8Sdk != null && _connectionStatus == ConnectionStatus.Connected)
if (_connectionStatus == ConnectionStatus.Connected)
{
originalValue = _a8Sdk.Color_plate;
Log($"成功读取当前色彩模式值: {originalValue}");
@@ -2517,6 +2567,17 @@ namespace JoyD.Windows.CS.Toprie
catch (Exception ex)
{
Log($"获取当前色彩模式值时出错: {ex.Message}");
// 尝试重新创建SDK实例
Log("尝试重新创建SDK实例...");
try
{
_a8Sdk = new A8SDK(_deviceIp);
Log("SDK实例已重新创建");
}
catch (Exception recreateEx)
{
Log($"重新创建SDK实例失败: {recreateEx.Message}");
}
// 即使获取失败,仍尝试设置新值
}
@@ -2534,8 +2595,24 @@ namespace JoyD.Windows.CS.Toprie
{
try
{
// 检查对象状态和连接状态
if (_a8Sdk == null || _connectionStatus != ConnectionStatus.Connected)
// 再次确保SDK实例存在
if (_a8Sdk == null)
{
Log("SDK实例为空尝试重新创建...");
try
{
_a8Sdk = new A8SDK(_deviceIp);
Log("SDK实例重新创建成功");
}
catch (Exception ex)
{
Log($"重新创建SDK实例失败: {ex.Message}");
continue; // 继续下一次尝试
}
}
// 检查连接状态
if (_connectionStatus != ConnectionStatus.Connected)
{
Log($"色彩模式设置失败: {(attempt > 0 ? "" : "")}SDK实例为空或设备未连接");
Thread.Sleep(retryDelayMs);
@@ -3195,7 +3272,6 @@ namespace JoyD.Windows.CS.Toprie
if (result)
{
_isConnected = true;
_reconnectAttempts = 0;
// 启动心跳检测和连接检查
StartHeartbeat();
@@ -3383,7 +3459,7 @@ namespace JoyD.Windows.CS.Toprie
// 连接进行中标志(用于防止重连期间再次触发连接)
private volatile bool _isConnecting = false;
private void StartAutoReconnect()
public void StartAutoReconnect()
{
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartAutoReconnect() - 开始执行");
@@ -3394,6 +3470,13 @@ namespace JoyD.Windows.CS.Toprie
return;
}
// 在暂停检测模式下,跳过重连启动
if (IsDetectionPaused)
{
Log("暂停检测模式下跳过重连启动");
return;
}
// 检查对象是否已释放
if (_isDisposed)
{
@@ -3599,6 +3682,13 @@ namespace JoyD.Windows.CS.Toprie
return;
}
// 在暂停检测模式下,跳过重连操作
if (IsDetectionPaused)
{
Log("暂停检测模式下跳过实际的重连操作");
return;
}
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 开始执行");
// 使用Interlocked.Exchange实现原子操作检查防止重入

View File

@@ -0,0 +1,18 @@
# JoyD
### InfoImage, ImageBuffer, 图像框的bitmap, LastImage
1. 初始化时都创建成512x384的透明bitmap
2. 中途不进行Dispose和设置为null只在上面进行绘制
3. 仅当控件被Dispose时才进行Dispose和设置为null
### 修改流程:
1. 暂停或恢复时设置暂停状态调用更新Info
2. 断开或连接时设置连接状态调用更新Info
3. Ping通状态变化时修改Ping状态调用更新Info
4. 图像更新时, 保存LastImage, 调用更新到UI
### 更新Info:
1. 如果暂停显示暂停信息否则如果Ping不通或断开显示重连信息否则清空InfoImage
2. 最后调用更新UI
### 更新UI:
1. 先将LastImage绘制到全局缓冲
2. 再将InfoImage绘制到缓冲
3. 最后一次性绘制到图像框的bitmap

View File

@@ -69,8 +69,7 @@ namespace JoyD.Windows.CS.Toprie
// 启动工作线程
_isRunning = true;
_workerThread = new Thread(ProcessRequests);
_workerThread.IsBackground = true;
_workerThread = new Thread(ProcessRequests) { IsBackground = true };
_workerThread.Start();
Console.WriteLine("UDP通信管理器已初始化");

View File

@@ -128,16 +128,14 @@ namespace JoyD.Windows.CS.Toprie
}
// 私有字段
private string deviceIp;
private Socket socket;
private bool isConnected;
private readonly string deviceIp;
private Socket socket = null;
private static bool isSdkInitialized = false;
private static Dictionary<string, V8> deviceInstances = new Dictionary<string, V8>();
private static readonly Dictionary<string, V8> deviceInstances = new Dictionary<string, V8>();
public V8(string ip)
{
deviceIp = ip;
isConnected = false;
}
~V8()
@@ -158,10 +156,9 @@ namespace JoyD.Windows.CS.Toprie
if (socket != null)
{
socket.Close();
socket = null;
}
isConnected = false;
Console.WriteLine("UDP通信状态已重置");
socket = null;
}
Console.WriteLine("UDP通信状态已重置");
}
catch (Exception ex)
{
@@ -1132,9 +1129,10 @@ namespace JoyD.Windows.CS.Toprie
if (SendCommand(command, out string response))
{
// 创建默认的ImagePos对象
SharedStructures.ImagePos data = new SharedStructures.ImagePos();
data.area = new SharedStructures.AreaPos[6];
data.spot = new SharedStructures.SpotPos[6];
SharedStructures.ImagePos data = new SharedStructures.ImagePos() {
area = new SharedStructures.AreaPos[6],
spot = new SharedStructures.SpotPos[6]
};
// 这里应该解析完整的响应数据
// 简化实现,返回默认值

View File

@@ -0,0 +1,54 @@
# 托普瑞热像仪应用开发任务列表
## 1. SDK集成准备
- [x] 1.1 复制托普瑞SDK文件到项目目录
- [x] 1.2 在Visual Studio项目中添加SDK引用
- [x] 1.3 阅读SDK文档了解API接口
## 2. 设备连接功能
- [x] 2.1 实现设备连接模块
- [x] 2.2 完善连接状态管理
## 3. 温度数据处理
### 3.1 设备连接建立与管理
- [ ] 3.1.1 实现设备连接建立流程
- 使用SDK的`sdk_initialize()`初始化套接字库
- 利用`sdk_search_device()`搜索设备IP地址
- 验证设备IP地址是否为默认地址(192.168.100.2)或自定义地址
- 建立与热像仪的TCP连接使用8081端口获取原始温度数据
- [ ] 3.1.2 连接状态维护机制
- 利用现有的`_heartbeatTimer`实现SDK心跳检测(`sdk_heartbeat`)
- 扩展`UpdateConnectionStatus()`方法,支持温度数据连接状态管理
- 实现基于`_connectionCheckTimer`的定时连接状态检测
- 利用现有的自动重连机制,当温度数据连接断开时自动重连
- [ ] 3.1.3 连接条件判断
- 调用`IsNetworkAvailable()`验证网络连接状态
- 检查设备型号兼容性支持IRAY-A8系列设备
- 验证设备版本信息确保SDK兼容性
- 在获取温度数据前检查设备是否处于正常工作状态
### 3.2 原始温度数据获取
- [ ] 3.2.1 温度数据获取方法实现
-`DeviceManager.cs`中添加`GetRawTemperatureData()`方法
- 创建TCP客户端连接到设备的8081端口
- 实现数据接收线程,使用类似现有的`_imageReceiveThread`模式
- 实现24字节头部结构体解析提取mark("+TEMP")、payload_length和timestamp
- [ ] 3.2.2 温度数据解析与处理
- 根据设备分辨率计算温度数据总长度(宽*高*2字节)
- 实现温度数据解码算法:摄氏温度 = (H*256 + L)/10其中L是低8位H是高8位
- 调用`sdk_get_comp_temp()`获取设备温补值并进行叠加修正
- 创建温度数据模型类,存储解析后的温度矩阵
- [ ] 3.2.3 数据获取条件控制与异常处理
- 添加连接状态验证,确保`_connectionStatus``Connected`
- 实现数据接收超时处理,基于`_lastDataReceivedTime``DataReceivedTimeout`
- 添加数据校验机制,确保接收到的温度数据格式正确
- 实现断线自动重连,利用现有的`_reconnectTimer`机制
- 添加异常捕获和日志记录,使用现有的`Log()`方法
- [ ] 3.2.4 温度数据接口设计
- 添加温度数据接收事件`TemperatureDataReceived`
- 实现线程安全的数据访问方法
- 添加温度数据缓存机制,保留最近几帧数据
- 提供获取特定区域温度数据的辅助方法