Merge branch 'main' of http://47.109.191.115:3000/ZengQingming/JoyD
This commit is contained in:
12
README.md
12
README.md
@@ -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
|
||||
@@ -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
@@ -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实现原子操作检查,防止重入
|
||||
|
||||
18
Windows/CS/Framework4.0/Toprie/Toprie/README.md
Normal file
18
Windows/CS/Framework4.0/Toprie/Toprie/README.md
Normal 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
|
||||
@@ -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通信管理器已初始化");
|
||||
|
||||
@@ -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]
|
||||
};
|
||||
|
||||
// 这里应该解析完整的响应数据
|
||||
// 简化实现,返回默认值
|
||||
|
||||
54
Windows/CS/Framework4.0/Toprie/Toprie/todolist.md
Normal file
54
Windows/CS/Framework4.0/Toprie/Toprie/todolist.md
Normal 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`
|
||||
- 实现线程安全的数据访问方法
|
||||
- 添加温度数据缓存机制,保留最近几帧数据
|
||||
- 提供获取特定区域温度数据的辅助方法
|
||||
Reference in New Issue
Block a user