diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs b/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs
index e530f26..dbdf5a6 100644
--- a/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs
+++ b/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs
@@ -2173,54 +2173,27 @@ namespace JoyD.Windows.CS.Toprie
// 如果用户选择了文件路径
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
- // 现在直接从设备管理器获取温度数据,不再使用缓存的温度数据
- // 调用设备管理器的方法获取最新的温度数据
+ // 获取已有的温度数据(从DeviceManager缓存中获取)
TemperatureData temperatureData = _deviceManager.LastTemperature;
- if (temperatureData == null)
- {
- MessageBox.Show("获取温度数据失败,请确保设备已连接且正在接收数据。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
- return;
- }
-
- // 保存温度数据到CSV文件
- using (StreamWriter writer = new StreamWriter(saveFileDialog.FileName))
- {
- // 写入文件头部信息(以#开头的注释行不会被CSV解析器当作数据)
- writer.WriteLine("# 温度数据文件 - CSV格式(逗号分隔值)");
- writer.WriteLine($"# 生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
- writer.WriteLine($"# 分辨率: {temperatureData.Width} x {temperatureData.Height}");
- writer.WriteLine($"# 最高温度: {temperatureData.MaxTemperature:F2} °C");
- writer.WriteLine($"# 最低温度: {temperatureData.MinTemperature:F2} °C");
- writer.WriteLine($"# 平均温度: {temperatureData.AverageTemperature:F2} °C");
- writer.WriteLine();
-
- // 写入温度数据矩阵(CSV格式)
- for (int i = 0; i < temperatureData.Height; i++)
- {
- StringBuilder lineBuilder = new StringBuilder();
- for (int j = 0; j < temperatureData.Width; j++)
- {
- // 获取温度值
- string tempValue = $"{temperatureData.TemperatureMatrix[i, j]:F2}";
-
- // CSV标准格式:如果值包含逗号、引号或换行符,需要用引号包围并转义内部引号
- if (tempValue.Contains(',') || tempValue.Contains('"') || tempValue.Contains('\n'))
- {
- tempValue = $"\"{tempValue.Replace("\"", "\"\"")}\"";
- }
-
- lineBuilder.Append(tempValue);
- if (j < temperatureData.Width - 1)
- {
- lineBuilder.Append(",");
- }
- }
- writer.WriteLine(lineBuilder.ToString());
- }
+ if (temperatureData == null)
+ {
+ MessageBox.Show("获取温度数据失败,请确保设备已连接且正在接收数据。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
}
- // 显示保存成功消息
- MessageBox.Show($"温度数据已成功保存到:\n{saveFileDialog.FileName}", "保存成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ // 使用DeviceManager的新重载方法,直接传入已获取的温度数据
+ bool saveResult = _deviceManager.SaveTemperatureDataToCsv(saveFileDialog.FileName, temperatureData);
+
+ if (saveResult)
+ {
+ // 显示保存成功消息
+ MessageBox.Show($"温度数据已成功保存到:\n{saveFileDialog.FileName}", "保存成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+ else
+ {
+ // 显示保存失败消息
+ MessageBox.Show("保存温度数据失败,请检查文件路径是否有效且有写入权限。", "保存失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
}
}
catch (Exception ex)
diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs
index 9f0b328..72713bc 100644
--- a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs
+++ b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs
@@ -257,8 +257,6 @@ namespace JoyD.Windows.CS.Toprie
private bool _isAutoReconnectEnabled = true;
// 最大重连次数
private int _maxReconnectAttempts = 5;
- // 是否已连接
- private bool _isConnected = false;
// 连接超时设置
private readonly int _connectTimeout = 5000;
// 当前重连尝试次数
@@ -1599,6 +1597,8 @@ namespace JoyD.Windows.CS.Toprie
private const int HEADER_SIZE = 24; // 24字节头部结构体
private const int WIDTH = 256;
private const int HEIGHT = 192;
+ private const int FixedWidth = 512;
+ private const int FixedHeight = 384;
/// 累积的温度数据包列表
// 重入保护标志
@@ -4181,7 +4181,6 @@ namespace JoyD.Windows.CS.Toprie
Log("设计模式下跳过实际设备连接");
// 不设置真实的连接状态,避免触发图像接收
_currentDeviceId = deviceId;
- _isConnected = false;
_connectionStatus = ConnectionStatus.Disconnected;
UpdateConnectionStatus(ConnectionStatus.Disconnected, "设计模式:跳过设备连接");
return;
@@ -4374,9 +4373,7 @@ namespace JoyD.Windows.CS.Toprie
}
if (result)
- {
- _isConnected = true;
-
+ {
// 启动心跳检测和连接检查
StartHeartbeat();
StartConnectionCheck();
@@ -5440,17 +5437,16 @@ namespace JoyD.Windows.CS.Toprie
///
/// CSV文件路径
/// 是否保存成功
- public bool SaveTemperatureDataToCsv(string filePath)
+ ///
+ /// 保存温度数据到CSV文件(接受已有的温度数据)
+ ///
+ /// CSV文件路径
+ /// 温度数据对象
+ /// 是否保存成功
+ public bool SaveTemperatureDataToCsv(string filePath, TemperatureData temperatureData)
{
try
{
- // 检查设备是否连接
- if (!_isConnected || _a8Sdk == null)
- {
- Console.WriteLine("设备未连接,无法保存温度数据");
- return false;
- }
-
// 检查文件路径是否有效
if (string.IsNullOrEmpty(filePath))
{
@@ -5475,91 +5471,13 @@ namespace JoyD.Windows.CS.Toprie
}
}
- // 尝试从设备获取温度数据
- List temperatureData = new List();
-
- try
- {
- // 使用A8SDK的Get_all_temp方法获取所有温度数据
- Console.WriteLine("正在获取设备温度数据...");
-
- SharedStructures.ImageTemp imageTemp = _a8Sdk.Get_all_temp();
-
- // 检查是否获取到温度数据
- bool hasTemperatureData = false;
-
- // 处理全局温度数据
- if (imageTemp.globa.max_temp > -273.0f) // 检查是否有有效温度值(高于绝对零度)
- {
- Console.WriteLine($"全局温度数据: 最高={imageTemp.globa.max_temp}°C, 最低={imageTemp.globa.min_temp}°C");
-
- // 添加全局温度点
- temperatureData.Add(new TemperatureDataPoint(0, 0, imageTemp.globa.max_temp));
- temperatureData.Add(new TemperatureDataPoint(0, 1, imageTemp.globa.min_temp));
-
- // 添加最高温度点的坐标
- temperatureData.Add(new TemperatureDataPoint(
- imageTemp.globa.max_temp_x,
- imageTemp.globa.max_temp_y,
- imageTemp.globa.max_temp));
-
- // 添加最低温度点的坐标
- temperatureData.Add(new TemperatureDataPoint(
- imageTemp.globa.min_temp_x,
- imageTemp.globa.min_temp_y,
- imageTemp.globa.min_temp));
-
- hasTemperatureData = true;
- }
-
- // 处理区域温度数据
- for (int i = 0; i < imageTemp.area.Length; i++)
- {
- if (imageTemp.area[i].enable == 1 && imageTemp.area[i].ave_temp > -273.0f)
- {
- Console.WriteLine($"区域 {i+1} 温度: {imageTemp.area[i].ave_temp}°C");
- temperatureData.Add(new TemperatureDataPoint(i + 1, 0, imageTemp.area[i].ave_temp));
- hasTemperatureData = true;
- }
- }
-
- // 处理点温度数据
- for (int i = 0; i < imageTemp.spot.Length; i++)
- {
- if (imageTemp.spot[i].enable == 1 && imageTemp.spot[i].temp > -273.0f)
- {
- Console.WriteLine($"点 {i+1} 温度: {imageTemp.spot[i].temp}°C");
- temperatureData.Add(new TemperatureDataPoint(i + 1, 1, imageTemp.spot[i].temp));
- hasTemperatureData = true;
- }
- }
-
- if (!hasTemperatureData)
- {
- Console.WriteLine("未获取到有效温度数据,使用模拟数据");
- // 如果无法获取真实数据,使用模拟数据
- GenerateMockTemperatureData(temperatureData);
- }
- else
- {
- Console.WriteLine($"成功获取到 {temperatureData.Count} 个温度数据点");
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"获取温度数据失败: {ex.Message}");
- // 如果获取真实数据失败,使用模拟数据
- Console.WriteLine("使用模拟温度数据作为备选");
- GenerateMockTemperatureData(temperatureData);
- }
-
// 写入CSV文件
try
{
// 确保有温度数据
- if (temperatureData.Count == 0)
+ if (temperatureData == null || temperatureData.TemperatureMatrix == null || temperatureData.Width == 0 || temperatureData.Height == 0)
{
- Console.WriteLine("没有温度数据可保存");
+ Console.WriteLine("没有有效的温度数据可保存");
return false;
}
@@ -5568,31 +5486,30 @@ namespace JoyD.Windows.CS.Toprie
// 写入CSV头部和元信息
writer.WriteLine("# 温度数据导出");
writer.WriteLine($"# 导出时间: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
- writer.WriteLine($"# 设备IP: {_deviceIp}");
- writer.WriteLine($"# 数据点数: {temperatureData.Count}");
+ writer.WriteLine($"# 采样分辨率: {temperatureData.Width}x{temperatureData.Height}");
+ writer.WriteLine($"# 修正分辨率: {FixedWidth}x{FixedHeight}");
+ writer.WriteLine($"# 最高温度: {temperatureData.MaxTemperature:F2}°C");
+ writer.WriteLine($"# 最低温度: {temperatureData.MinTemperature:F2}°C");
+ writer.WriteLine($"# 平均温度: {temperatureData.AverageTemperature:F2}°C");
writer.WriteLine("#");
// 写入数据列头
- writer.WriteLine("数据类型,X坐标,Y坐标,温度值(°C)");
+ writer.WriteLine("X坐标,Y坐标,温度值(°C)");
- // 写入温度数据
- foreach (var dataPoint in temperatureData)
+ // 写入温度矩阵数据
+ for (int y = 0; y < FixedHeight; y++)
{
- // 根据X坐标判断数据类型
- string dataType = "未知";
- if (dataPoint.X == 0 && dataPoint.Y == 0) dataType = "全局最高";
- else if (dataPoint.X == 0 && dataPoint.Y == 1) dataType = "全局最低";
- else if (dataPoint.X == 0 && dataPoint.Y == 2) dataType = "全局平均";
- else if (dataPoint.Y == 0 && dataPoint.X > 0 && dataPoint.X <= 6) dataType = $"区域{dataPoint.X}";
- else if (dataPoint.Y == 1 && dataPoint.X > 0 && dataPoint.X <= 6) dataType = $"点{dataPoint.X}";
- else dataType = "温度点";
-
- writer.WriteLine($"{dataType},{dataPoint.X},{dataPoint.Y},{dataPoint.Temperature:F2}");
+ for (int x = 0; x < FixedWidth; x++)
+ {
+ // 获取温度值
+ float temperature = temperatureData.RealTemperatureMatrix[y, x];
+ writer.WriteLine($"{x},{y},{temperature:F2}");
+ }
}
}
Console.WriteLine($"温度数据已成功保存到: {filePath}");
- Console.WriteLine($"共保存 {temperatureData.Count} 个温度数据点");
+ Console.WriteLine($"采样分辨率: {temperatureData.Width}x{temperatureData.Height}");
return true;
}
catch (IOException ioEx)
@@ -5641,190 +5558,6 @@ namespace JoyD.Windows.CS.Toprie
}
}
}
-
- ///
- /// 获取当前温度数据
- ///
- /// 当前温度数据对象,如果获取失败则返回null
- public TemperatureData GetCurrentTemperatureData()
- {
- try
- {
- // 检查设备是否连接
- if (!_isConnected || _a8Sdk == null)
- {
- Log("设备未连接,无法获取温度数据");
- return null;
- }
-
- // 尝试从设备获取温度数据
- try
- {
- // 使用A8SDK的Get_all_temp方法获取所有温度数据
- Log("正在获取设备温度数据...");
-
- SharedStructures.ImageTemp imageTemp = _a8Sdk.Get_all_temp();
-
- // 检查是否获取到温度数据(使用默认值比较而不是null比较)
- if (imageTemp.Equals(default(SharedStructures.ImageTemp)))
- {
- Log("未获取到温度数据,返回null");
- return null;
- }
-
- // 获取温度补偿值
- float compensationValue = _a8Sdk.Comp_temp;
- Log($"获取到的温度补偿值: {compensationValue}");
-
- // 创建温度数据对象
- // 这里使用模拟的温度矩阵,实际项目中应该使用真实的温度数据
- // 根据设备实际分辨率创建温度矩阵
- const int width = 640; // 假设设备分辨率为640x480
- const int height = 480;
-
- // 生成模拟的温度数据矩阵
- float[,] temperatureMatrix = new float[height, width];
-
- // 填充温度矩阵,使用获取到的最大和最小温度作为参考
- float maxTemp = imageTemp.globa.max_temp > -273.0f ? imageTemp.globa.max_temp : 30.0f;
- float minTemp = imageTemp.globa.min_temp > -273.0f ? imageTemp.globa.min_temp : 20.0f;
-
- // 生成温度矩阵,在最大和最小温度之间变化
- Random rand = new Random();
- for (int i = 0; i < height; i++)
- {
- for (int j = 0; j < width; j++)
- {
- // 生成在最小和最大温度之间的随机值
- temperatureMatrix[i, j] = minTemp + (float)rand.NextDouble() * (maxTemp - minTemp);
- // 添加一些变化模式,使温度分布更自然
- temperatureMatrix[i, j] += (float)Math.Sin(i * 0.02) * 2.0f + (float)Math.Cos(j * 0.02) * 2.0f;
- }
- }
-
- // 确保最大和最小温度点存在
- if (imageTemp.globa.max_temp_x >= 0 && imageTemp.globa.max_temp_y >= 0)
- {
- int x = Math.Min(imageTemp.globa.max_temp_x, width - 1);
- int y = Math.Min(imageTemp.globa.max_temp_y, height - 1);
- temperatureMatrix[y, x] = maxTemp;
- }
-
- if (imageTemp.globa.min_temp_x >= 0 && imageTemp.globa.min_temp_y >= 0)
- {
- int x = Math.Min(imageTemp.globa.min_temp_x, width - 1);
- int y = Math.Min(imageTemp.globa.min_temp_y, height - 1);
- temperatureMatrix[y, x] = minTemp;
- }
-
- // 创建TemperatureData对象
- // 使用Toprie.TemperatureData类的构造函数
- // 首先创建符合构造函数要求的rawData格式
- List rawDataList = new List();
- for (int i = 0; i < height; i++)
- {
- for (int j = 0; j < width; j++)
- {
- // 将温度值转换回原始格式(不包含补偿值)
- float tempValue = temperatureMatrix[i, j] - compensationValue;
- int tempInt = (int)(tempValue * 10.0f);
- rawDataList.Add((byte)((tempInt >> 8) & 0xFF)); // 高字节
- rawDataList.Add((byte)(tempInt & 0xFF)); // 低字节
- }
- }
-
- // 使用全局TemperatureData类的构造函数
- TemperatureData temperatureData = new TemperatureData(
- rawDataList.ToArray(),
- width,
- height,
- compensationValue
- );
-
- Log($"成功创建温度数据对象,分辨率: {width}x{height}, 最大温度: {temperatureData.MaxTemperature:F2}°C, 最小温度: {temperatureData.MinTemperature:F2}°C");
- return temperatureData;
- }
- catch (Exception ex)
- {
- Log($"获取温度数据失败: {ex.Message}");
- // 如果获取真实数据失败,尝试生成模拟数据
- return GenerateMockTemperatureData();
- }
- }
- catch (Exception ex)
- {
- Log($"GetCurrentTemperatureData方法异常: {ex.Message}");
- return null;
- }
- }
-
- ///
- /// 生成完整的模拟温度数据对象
- ///
- /// 模拟的温度数据对象
- private TemperatureData GenerateMockTemperatureData()
- {
- try
- {
- Log("生成模拟温度数据...");
-
- // 假设分辨率为640x480
- const int width = 640;
- const int height = 480;
-
- // 创建温度矩阵
- float[,] temperatureMatrix = new float[height, width];
- Random rand = new Random();
-
- // 生成有一定模式的模拟温度数据
- for (int i = 0; i < height; i++)
- {
- for (int j = 0; j < width; j++)
- {
- // 基础温度25度,加上一些变化模式
- float baseTemp = 25.0f;
- // 添加波浪形变化
- float waveVariation = (float)(Math.Sin(i * 0.05) * Math.Cos(j * 0.05)) * 10.0f;
- // 添加随机噪声
- float noise = (float)(rand.NextDouble() - 0.5) * 2.0f;
- // 组合生成最终温度
- temperatureMatrix[i, j] = baseTemp + waveVariation + noise;
- }
- }
-
- // 创建并返回模拟温度数据对象
- // 首先创建符合构造函数要求的rawData格式
- List rawDataList = new List();
- for (int i = 0; i < height; i++)
- {
- for (int j = 0; j < width; j++)
- {
- // 将温度值转换回原始格式
- float tempValue = temperatureMatrix[i, j];
- int tempInt = (int)(tempValue * 10.0f);
- rawDataList.Add((byte)((tempInt >> 8) & 0xFF)); // 高字节
- rawDataList.Add((byte)(tempInt & 0xFF)); // 低字节
- }
- }
-
- // 使用全局TemperatureData类的构造函数
- TemperatureData temperatureData = new TemperatureData(
- rawDataList.ToArray(),
- width,
- height,
- 0 // 模拟数据不需要补偿值
- );
-
- Log($"模拟温度数据生成完成,最大温度: {temperatureData.MaxTemperature:F2}°C, 最小温度: {temperatureData.MinTemperature:F2}°C");
- return temperatureData;
- }
- catch (Exception ex)
- {
- Log($"生成模拟温度数据失败: {ex.Message}");
- return null;
- }
- }
-
#region IDisposable 实现
private bool _disposed = false;
diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/TemperatureData.cs b/Windows/CS/Framework4.0/Toprie/Toprie/TemperatureData.cs
index 713588c..94a717b 100644
--- a/Windows/CS/Framework4.0/Toprie/Toprie/TemperatureData.cs
+++ b/Windows/CS/Framework4.0/Toprie/Toprie/TemperatureData.cs
@@ -80,69 +80,69 @@ namespace JoyD.Windows.CS.Toprie
}
///
- /// 解析原始温度数据
- ///
- /// 原始温度数据
- /// 温度补偿值
- private void ParseRawData(byte[] rawData, float compensationValue)
- {
- // 检查数据是否有效
- if (rawData == null || rawData.Length == 0)
+ /// 解析原始温度数据
+ ///
+ /// 原始温度数据
+ /// 温度补偿值
+ private void ParseRawData(byte[] rawData, float compensationValue)
{
- throw new ArgumentNullException(nameof(rawData), "原始温度数据为空");
- }
-
- // 根据SDK文档要求,使用24字节头部
- const int HEADER_SIZE = 24;
-
- // 确保数据长度足够(至少包含头部)
- if (rawData.Length < HEADER_SIZE)
- {
- throw new ArgumentException("数据长度不足,无法解析");
- }
-
- // 计算温度数据长度和像素总数
- int dataLength = rawData.Length - HEADER_SIZE;
- int pixelCount = dataLength / 2; // 每个像素2字节
-
- // 计算最大可处理的像素数
- int maxPixels = Math.Min(pixelCount, Width * Height);
-
- // 跳过24字节头部,按照行优先顺序解析温度数据
- for (int i = 0; i < maxPixels; i++)
- {
- // 计算行列索引
- int row = i / Width;
- int col = i % Width;
-
- if (row < Height && col < Width)
+ // 检查数据是否有效
+ if (rawData == null || rawData.Length == 0)
{
- // 计算数据偏移量(跳过24字节头部)
- int offset = HEADER_SIZE + i * 2;
-
- if (offset + 1 < rawData.Length)
+ throw new ArgumentNullException(nameof(rawData), "原始温度数据为空");
+ }
+
+ // 根据SDK文档要求,使用24字节头部
+ const int HEADER_SIZE = 24;
+
+ // 确保数据长度足够(至少包含头部)
+ if (rawData.Length < HEADER_SIZE)
+ {
+ throw new ArgumentException("数据长度不足,无法解析");
+ }
+
+ // 计算温度数据长度和像素总数
+ int dataLength = rawData.Length - HEADER_SIZE;
+ int pixelCount = dataLength / 2; // 每个像素2字节
+
+ // 计算最大可处理的像素数
+ int maxPixels = Math.Min(pixelCount, Width * Height);
+
+ // 跳过24字节头部,按照行优先顺序解析温度数据
+ for (int i = 0; i < maxPixels; i++)
+ {
+ // 计算行列索引
+ int row = i / Width;
+ int col = i % Width;
+
+ if (row < Height && col < Width)
{
- // 根据SDK文档要求,温度值计算方法:(H×256+L)/10,单位为摄氏度
- // H为高8位,L为低8位
- int highByte = rawData[offset + 1]; // 高8位
- int lowByte = rawData[offset]; // 低8位
- int tempValue = (highByte << 8) | lowByte;
+ // 计算数据偏移量(跳过24字节头部)
+ int offset = HEADER_SIZE + i * 2;
+
+ if (offset + 1 < rawData.Length)
+ {
+ // 根据SDK文档要求,温度值计算方法:(H×256+L)/10,单位为摄氏度
+ // H为高8位,L为低8位
+ int highByte = rawData[offset + 1]; // 高8位
+ int lowByte = rawData[offset]; // 低8位
+ int tempValue = (highByte << 8) | lowByte;
- // 计算实际温度值:(H×256+L)/10
- float rawTemperature = tempValue / 10.0f;
+ // 计算实际温度值:(H×256+L)/10
+ float rawTemperature = tempValue / 10.0f;
- // 应用温度补偿值
- float compensatedTemperature = rawTemperature + compensationValue;
+ // 应用温度补偿值
+ float compensatedTemperature = rawTemperature + compensationValue;
- // 原始温度存入TemperatureMatrix(未温补)
- TemperatureMatrix[row, col] = rawTemperature;
+ // 原始温度存入TemperatureMatrix(未温补)
+ TemperatureMatrix[row, col] = rawTemperature;
- // 温补后的温度存入RealTemperatureMatrix(映射到512×384矩阵)
- MapToRealTemperatureMatrix(row, col, compensatedTemperature);
+ // 温补后的温度存入RealTemperatureMatrix(映射到512×384矩阵)
+ MapToRealTemperatureMatrix(row, col, compensatedTemperature);
+ }
}
}
}
- }
///
/// 将原始温度数据映射到512×384的实际温度矩阵