修复TemperatureData.cs中温度数据解析逻辑,使其符合SDK实际实现:1) 将头部长度从24字节修正为9字节;2) 修改数据布局解析方式,低字节在前半部分,高字节在后半部分;3) 确保正确的温度计算公式

This commit is contained in:
zqm
2025-10-31 13:30:25 +08:00
parent 2f9011d1b2
commit 5947b15e92

View File

@@ -86,37 +86,30 @@ namespace JoyD.Windows.CS.Toprie
/// <param name="compensationValue">温度补偿值</param> /// <param name="compensationValue">温度补偿值</param>
private void ParseRawData(byte[] rawData, float compensationValue) private void ParseRawData(byte[] rawData, float compensationValue)
{ {
// 按照SDK文档,温度数据格式为:24字节头部 + 温度数据 // 根据SDK实际实现,温度数据格式为:
// 温度数据为每个点2字节摄氏温度=(H*256+L)/10 // 9字节头部 (+TEMP + 4字节长度) + 低字节数据 + 高字节数据
// 温度数据是连续发送的,不需要分开处理奇偶数行 // 温度计算公式:(低字节 + 高字节*256 - 2730)/10
// 首先检查数据长度是否足够包含头部信息 // 首先检查数据长度是否足够包含头部信息
if (rawData.Length < 24) if (rawData.Length < 9)
{ {
System.Diagnostics.Debug.WriteLine("警告: 原始数据长度小于24字节,无法包含有效的头部信息"); System.Diagnostics.Debug.WriteLine("警告: 原始数据长度小于9字节,无法包含有效的头部信息");
throw new ArgumentException("原始数据长度不足以包含头部信息"); throw new ArgumentException("原始数据长度不足以包含头部信息");
} }
// 验证头部信息 // 验证头部标识字符是否为"+TEMP"
if (!ValidateHeader(rawData)) string headerMark = Encoding.ASCII.GetString(rawData, 0, 5).TrimEnd('\0');
if (headerMark != "+TEMP")
{ {
System.Diagnostics.Debug.WriteLine("警告: 温度数据头部信息验证失败,停止解析"); System.Diagnostics.Debug.WriteLine($"警告: 头部标识不匹配,期望'+TEMP',实际为'{headerMark}'");
throw new ArgumentException("温度数据头部信息无效"); // 即使头部不匹配,我们也尝试继续处理,因为有些情况下数据可能没有标准头部
} }
// 从头部解析温度数据长度 // 计算像素总数 - 根据SDK实现数据长度应该是头部(9字节) + 像素数*2
int payloadLength = GetPayloadLengthFromHeader(rawData); int totalDataSize = rawData.Length - 9; // 减去9字节头部
int actualDataLength = rawData.Length - 24; // 实际温度数据长度(总长度减去头部长度 int pixelCount = totalDataSize / 2; // 每个像素点使用2字节低字节和高字节分开存储
// 验证数据长度一致性 // 根据像素数确定宽高 - 使用标准分辨率
if (payloadLength > 0 && payloadLength != actualDataLength)
{
System.Diagnostics.Debug.WriteLine($"警告: 头部指定的数据长度({payloadLength})与实际数据长度({actualDataLength})不匹配");
// 但我们仍然使用实际数据长度继续处理
}
// 根据数据长度自适应确定宽高
int pixelCount = actualDataLength / 2; // 每个像素点2字节
int[] widthHeight = GetWidthHeightByPixelCount(pixelCount); int[] widthHeight = GetWidthHeightByPixelCount(pixelCount);
int adaptiveWidth = widthHeight[0]; int adaptiveWidth = widthHeight[0];
int adaptiveHeight = widthHeight[1]; int adaptiveHeight = widthHeight[1];
@@ -124,30 +117,30 @@ namespace JoyD.Windows.CS.Toprie
// 输出自适应宽高信息 // 输出自适应宽高信息
System.Diagnostics.Debug.WriteLine($"根据数据长度自适应宽高: {adaptiveWidth}x{adaptiveHeight} (像素数: {pixelCount})"); System.Diagnostics.Debug.WriteLine($"根据数据长度自适应宽高: {adaptiveWidth}x{adaptiveHeight} (像素数: {pixelCount})");
// 如果自适应宽高与传入的宽高不同,更新宽高并重新初始化矩阵 // 更新宽高并初始化矩阵
if (adaptiveWidth != Width || adaptiveHeight != Height)
{
Width = adaptiveWidth; Width = adaptiveWidth;
Height = adaptiveHeight; Height = adaptiveHeight;
TemperatureMatrix = new float[Height, Width]; TemperatureMatrix = new float[Height, Width];
System.Diagnostics.Debug.WriteLine($"注意: 使用自适应宽高替换了原始宽高设置");
}
// 跳过24字节的头部信息
int dataIndex = 24;
// 计算最大可处理的像素数 // 计算最大可处理的像素数
int maxPixels = Math.Min(pixelCount, Width * Height); int maxPixels = Math.Min(pixelCount, Width * Height);
// 遍历所有像素点,按顺序处理温度数据 // 按照SDK实现的数据布局处理低字节在前半部分高字节在后半部分
for (int row = 0; row < Height && dataIndex + 1 < rawData.Length; row++) int lowByteOffset = 9; // 低字节数据起始位置跳过9字节头部
int highByteOffset = 9 + pixelCount; // 高字节数据起始位置(在低字节数据之后)
// 遍历所有像素点按照SDK的方式计算温度
for (int i = 0; i < maxPixels; i++)
{ {
for (int col = 0; col < Width && dataIndex + 1 < rawData.Length; col++) // 计算行列索引
int row = i / Width;
int col = i % Width;
if (row < Height && col < Width)
{ {
// 按照SDK实际实现计算温度值:摄氏温度=(L + H*256 - 2730)/10 // 按照SDK实现计算温度值(低字节 + 高字节*256 - 2730)/10
// 注意SDK实现是低字节在前高字节在后且包含2730的开尔文到摄氏度转换 int lowByte = rawData[lowByteOffset + i];
int lowByte = rawData[dataIndex]; int highByte = rawData[highByteOffset + i];
int highByte = rawData[dataIndex + 1];
float rawTemperature = (lowByte + highByte * 256 - 2730) / 10.0f; float rawTemperature = (lowByte + highByte * 256 - 2730) / 10.0f;
float compensatedTemperature = rawTemperature + compensationValue; float compensatedTemperature = rawTemperature + compensationValue;
@@ -156,8 +149,6 @@ namespace JoyD.Windows.CS.Toprie
// 温补后的温度存入RealTemperatureMatrix映射到512×384矩阵 // 温补后的温度存入RealTemperatureMatrix映射到512×384矩阵
MapToRealTemperatureMatrix(row, col, compensatedTemperature); MapToRealTemperatureMatrix(row, col, compensatedTemperature);
dataIndex += 2;
} }
} }
} }
@@ -347,10 +338,10 @@ namespace JoyD.Windows.CS.Toprie
/// <returns>如果头部信息有效返回true否则返回false</returns> /// <returns>如果头部信息有效返回true否则返回false</returns>
private bool ValidateHeader(byte[] rawData) private bool ValidateHeader(byte[] rawData)
{ {
// 根据SDK文档,头部信息的前几个字节包含标识字符和数据长度 // 根据SDK实际实现,头部信息的前几个字节包含标识字符和数据长度
// 检查原始数据不为空且长度足够 // 检查原始数据不为空且长度足够
if (rawData == null || rawData.Length < 24) if (rawData == null || rawData.Length < 9)
return false; return false;
// 1. 验证头部标识字符是否为"+TEMP" // 1. 验证头部标识字符是否为"+TEMP"
@@ -362,7 +353,7 @@ namespace JoyD.Windows.CS.Toprie
} }
// 2. 检查数据长度是否合理(至少包含头部+最小温度数据) // 2. 检查数据长度是否合理(至少包含头部+最小温度数据)
if (rawData.Length < 24 + 2) // 24字节头部 + 至少1个温度点(2字节) if (rawData.Length < 9 + 2) // 9字节头部 + 至少1个温度点(2字节)
return false; return false;
return true; return true;
@@ -375,8 +366,8 @@ namespace JoyD.Windows.CS.Toprie
/// <returns>温度数据长度(字节数)</returns> /// <returns>温度数据长度(字节数)</returns>
private int GetPayloadLengthFromHeader(byte[] rawData) private int GetPayloadLengthFromHeader(byte[] rawData)
{ {
// 根据SDK文档payload_length在头部的第5-8字节 // 根据SDK实际实现payload_length在头部的第5-8字节
// 注意:SDK文档指出采用低字节在前的存储方式 // 注意:采用低字节在前的存储方式
if (rawData.Length >= 9) if (rawData.Length >= 9)
{ {
return BitConverter.ToInt32(rawData, 5); return BitConverter.ToInt32(rawData, 5);