修复DeviceManager.cs中TCP温度数据接收相关的编译错误
This commit is contained in:
@@ -999,6 +999,7 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
lock (_lockObject)
|
lock (_lockObject)
|
||||||
{
|
{
|
||||||
_isTemperatureReceivingPaused = true;
|
_isTemperatureReceivingPaused = true;
|
||||||
@@ -1030,6 +1031,10 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// 记录调用堆栈,帮助定位问题
|
||||||
|
string callStack = Environment.StackTrace;
|
||||||
|
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ResumeTemperatureDataReceiving() - 调用堆栈:\n{callStack}");
|
||||||
|
|
||||||
lock (_lockObject)
|
lock (_lockObject)
|
||||||
{
|
{
|
||||||
_isTemperatureReceivingPaused = false;
|
_isTemperatureReceivingPaused = false;
|
||||||
@@ -1165,106 +1170,74 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
byte[] buffer = new byte[65536]; // 缓冲区大小
|
byte[] buffer = new byte[65536]; // 缓冲区大小
|
||||||
|
|
||||||
// 定义常量
|
// 定义常量
|
||||||
const int RECEIVE_TIMEOUT = 30000; // 增加到30秒,减少因超时导致的断开
|
const int RECEIVE_TIMEOUT = 30000; // 30秒超时
|
||||||
const int MEDIUM_SLEEP_MS = 50;
|
const int SLEEP_MS = 1000; // 标准等待时间
|
||||||
const int LONG_SLEEP_MS = 2000; // 增加重连等待时间
|
const int CONNECTION_CHECK_INTERVAL_MS = 5000; // 连接检查间隔5秒
|
||||||
const int ERROR_SLEEP_MS = 1000; // 增加异常恢复等待时间
|
const int LONG_SLEEP_MS = 5000; // 长等待时间
|
||||||
|
const int ERROR_SLEEP_MS = 3000; // 错误后等待时间
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 主循环,持续执行直到收到停止信号
|
// 主循环,持续执行直到收到停止信号
|
||||||
while (true)
|
while (!ShouldStop())
|
||||||
{
|
{
|
||||||
// 检查停止信号和对象是否已释放
|
|
||||||
bool shouldStop = false;
|
|
||||||
lock (_lockObject)
|
|
||||||
{
|
|
||||||
shouldStop = (_stopTemperatureEvent != null && _stopTemperatureEvent.WaitOne(0)) || _isDisposed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldStop)
|
|
||||||
{
|
|
||||||
Log("接收到停止信号或对象已释放,准备退出温度数据接收循环");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前状态和配置
|
// 获取当前状态和配置
|
||||||
bool isPaused = false;
|
bool isPaused = false;
|
||||||
string deviceIp = null;
|
string deviceIp = null;
|
||||||
int temperaturePort = 0;
|
int temperaturePort = TEMPERATURE_TCP_PORT;
|
||||||
|
|
||||||
lock (_lockObject)
|
lock (_lockObject)
|
||||||
{
|
{
|
||||||
isPaused = _isTemperatureReceivingPaused;
|
isPaused = _isTemperatureReceivingPaused;
|
||||||
deviceIp = _deviceIp;
|
deviceIp = _deviceIp;
|
||||||
temperaturePort = TEMPERATURE_TCP_PORT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 连接管理:当连接不存在、已断开或检测到连接不可用时创建新连接
|
// 如果连接不存在或已断开,创建新连接
|
||||||
if (localTcpClient == null || !IsTcpClientConnected(localTcpClient) || localStream == null)
|
if (localTcpClient == null || !IsTcpClientConnected(localTcpClient))
|
||||||
{
|
{
|
||||||
|
// 如果处于暂停状态,则Sleep 1秒后继续执行
|
||||||
|
if (isPaused)
|
||||||
|
{
|
||||||
|
Thread.Sleep(SLEEP_MS);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 否则创建一个新的连接实例
|
||||||
|
Log("创建新的温度数据TCP连接...");
|
||||||
|
|
||||||
// 清理之前可能存在的连接资源
|
// 清理之前可能存在的连接资源
|
||||||
try
|
CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient);
|
||||||
{
|
|
||||||
if (localStream != null)
|
|
||||||
{
|
|
||||||
localStream.Close();
|
|
||||||
localStream = null;
|
|
||||||
}
|
|
||||||
if (localTcpClient != null)
|
|
||||||
{
|
|
||||||
localTcpClient.Close();
|
|
||||||
localTcpClient = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log($"关闭旧连接异常: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 只有在未暂停状态下才创建连接
|
// 创建TCP客户端并连接
|
||||||
if (!isPaused)
|
localTcpClient = new TcpClient
|
||||||
{
|
{
|
||||||
Log("创建新的温度数据TCP连接...");
|
ReceiveTimeout = RECEIVE_TIMEOUT,
|
||||||
|
SendTimeout = RECEIVE_TIMEOUT,
|
||||||
// 创建TCP客户端并连接
|
ReceiveBufferSize = 65536 // 64KB
|
||||||
localTcpClient = new TcpClient
|
};
|
||||||
{
|
|
||||||
ReceiveTimeout = RECEIVE_TIMEOUT,
|
Log($"正在连接到温度数据端口 {temperaturePort}...");
|
||||||
SendTimeout = RECEIVE_TIMEOUT
|
localTcpClient.Connect(deviceIp, temperaturePort);
|
||||||
};
|
Log("温度数据TCP连接成功");
|
||||||
// 设置接收缓冲区大小
|
|
||||||
localTcpClient.ReceiveBufferSize = 65536; // 64KB
|
// 获取网络流
|
||||||
|
localStream = localTcpClient.GetStream();
|
||||||
Log($"正在连接到温度数据端口 {temperaturePort}...");
|
localStream.ReadTimeout = RECEIVE_TIMEOUT;
|
||||||
localTcpClient.Connect(deviceIp, temperaturePort);
|
|
||||||
Log("温度数据TCP连接成功");
|
// 更新状态标志
|
||||||
|
lock (_lockObject)
|
||||||
// 获取网络流
|
|
||||||
localStream = localTcpClient.GetStream();
|
|
||||||
localStream.ReadTimeout = RECEIVE_TIMEOUT;
|
|
||||||
|
|
||||||
// 更新状态标志
|
|
||||||
lock (_lockObject)
|
|
||||||
{
|
|
||||||
_isReceivingTemperatureData = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发送开始温度数据传输的命令
|
|
||||||
byte[] startCommand = Encoding.ASCII.GetBytes("start_temp_transfer\r\n");
|
|
||||||
localStream.Write(startCommand, 0, startCommand.Length);
|
|
||||||
localStream.Flush();
|
|
||||||
Log("已发送开始温度数据传输命令");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// 暂停状态下短暂等待后重试
|
_isReceivingTemperatureData = true;
|
||||||
Log("处于暂停状态,等待后重试连接");
|
|
||||||
Thread.Sleep(LONG_SLEEP_MS);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 发送开始温度数据传输的命令
|
||||||
|
byte[] startCommand = Encoding.ASCII.GetBytes("start_temp_transfer\r\n");
|
||||||
|
localStream.Write(startCommand, 0, startCommand.Length);
|
||||||
|
localStream.Flush();
|
||||||
|
Log("已发送开始温度数据传输命令");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1296,41 +1269,77 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
// 记录上次心跳时间和上次接收数据时间
|
// 记录上次心跳时间和上次接收数据时间
|
||||||
DateTime lastHeartbeatTime = DateTime.Now;
|
DateTime lastHeartbeatTime = DateTime.Now;
|
||||||
DateTime lastReceiveTime = DateTime.Now;
|
DateTime lastReceiveTime = DateTime.Now;
|
||||||
|
DateTime lastConnectionCheckTime = DateTime.Now;
|
||||||
|
DateTime lastPausedLogTime = DateTime.MinValue;
|
||||||
|
const int PAUSED_LOG_INTERVAL_MS = 30000; // 暂停状态日志间隔30秒
|
||||||
|
|
||||||
|
// 记录上次暂停状态,用于检测状态变化
|
||||||
|
bool lastPaused = false;
|
||||||
|
|
||||||
|
// 初始化lastPaused为当前状态
|
||||||
|
lock (_lockObject)
|
||||||
|
{
|
||||||
|
lastPaused = _isTemperatureReceivingPaused;
|
||||||
|
isPaused = lastPaused;
|
||||||
|
}
|
||||||
|
|
||||||
// 持续读取温度数据流
|
// 持续读取温度数据流
|
||||||
while (localTcpClient != null && localTcpClient.Connected)
|
while (localTcpClient != null && localTcpClient.Connected)
|
||||||
{
|
{
|
||||||
// 检查是否暂停
|
// 每次循环开始时检查是否收到停止信号
|
||||||
lock (_lockObject)
|
if (ShouldStop())
|
||||||
{
|
{
|
||||||
isPaused = _isTemperatureReceivingPaused;
|
Log("TCP连接循环中检测到停止信号,准备退出循环");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检测暂停状态是否发生变化
|
||||||
|
bool currentPaused = IsTemperatureReceivingPaused();
|
||||||
|
if (currentPaused != lastPaused)
|
||||||
|
{
|
||||||
|
if (currentPaused)
|
||||||
|
{
|
||||||
|
Log("温度接收暂停状态变化: 从运行中变为暂停");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log("温度接收暂停状态变化: 从暂停变为运行中");
|
||||||
|
}
|
||||||
|
// 更新lastPaused为当前状态
|
||||||
|
lastPaused = currentPaused;
|
||||||
|
}
|
||||||
|
// 更新isPaused为当前状态供后续使用
|
||||||
|
isPaused = currentPaused;
|
||||||
|
|
||||||
if (isPaused)
|
if (isPaused)
|
||||||
{
|
{
|
||||||
Log("温度接收已暂停,等待恢复");
|
// 减少暂停状态下的日志记录频率,避免日志过于冗长
|
||||||
Thread.Sleep(MEDIUM_SLEEP_MS);
|
DateTime currentTime = DateTime.Now;
|
||||||
// 在暂停状态下,仍然需要定期检查连接是否有效
|
if ((currentTime - lastPausedLogTime).TotalMilliseconds > PAUSED_LOG_INTERVAL_MS)
|
||||||
if (localTcpClient != null && !IsTcpClientConnected(localTcpClient))
|
|
||||||
{
|
{
|
||||||
Log("暂停状态下检测到连接已断开,将在恢复时重建连接");
|
Log("温度接收已暂停,等待恢复");
|
||||||
try
|
lastPausedLogTime = currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在暂停状态的Sleep前检查是否收到停止信号
|
||||||
|
if (ShouldStop())
|
||||||
|
{
|
||||||
|
Log("暂停状态下检测到停止信号,准备退出循环");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据规范,暂停时Sleep 1秒
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
|
||||||
|
// 在暂停状态下,降低连接检查频率
|
||||||
|
if ((currentTime - lastConnectionCheckTime).TotalMilliseconds > CONNECTION_CHECK_INTERVAL_MS)
|
||||||
|
{
|
||||||
|
if (localTcpClient != null && !IsTcpClientConnected(localTcpClient))
|
||||||
{
|
{
|
||||||
if (localStream != null)
|
Log("暂停状态下检测到连接已断开,将在恢复时重建连接");
|
||||||
{
|
CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient);
|
||||||
localStream.Close();
|
|
||||||
localStream = null;
|
|
||||||
}
|
|
||||||
if (localTcpClient != null)
|
|
||||||
{
|
|
||||||
localTcpClient.Close();
|
|
||||||
localTcpClient = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log($"关闭无效连接时发生异常: {ex.Message}");
|
|
||||||
}
|
}
|
||||||
|
lastConnectionCheckTime = currentTime;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1340,23 +1349,7 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
if (localTcpClient != null && !IsTcpClientConnected(localTcpClient))
|
if (localTcpClient != null && !IsTcpClientConnected(localTcpClient))
|
||||||
{
|
{
|
||||||
Log("恢复接收时检测到连接无效,需要重建连接");
|
Log("恢复接收时检测到连接无效,需要重建连接");
|
||||||
try
|
CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient);
|
||||||
{
|
|
||||||
if (localStream != null)
|
|
||||||
{
|
|
||||||
localStream.Close();
|
|
||||||
localStream = null;
|
|
||||||
}
|
|
||||||
if (localTcpClient != null)
|
|
||||||
{
|
|
||||||
localTcpClient.Close();
|
|
||||||
localTcpClient = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log($"关闭无效连接时发生异常: {ex.Message}");
|
|
||||||
}
|
|
||||||
// 跳出内层循环,回到外层循环重新建立连接
|
// 跳出内层循环,回到外层循环重新建立连接
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1368,7 +1361,15 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
byte[] startCommand = Encoding.ASCII.GetBytes("start_temp_transfer\r\n");
|
byte[] startCommand = Encoding.ASCII.GetBytes("start_temp_transfer\r\n");
|
||||||
localStream.Write(startCommand, 0, startCommand.Length);
|
localStream.Write(startCommand, 0, startCommand.Length);
|
||||||
localStream.Flush();
|
localStream.Flush();
|
||||||
Log("从暂停状态恢复,重新发送开始温度数据传输命令");
|
|
||||||
|
// 只有在从暂停状态恢复时(状态从true变为false的瞬间)才记录日志
|
||||||
|
lock (_lockObject)
|
||||||
|
{
|
||||||
|
if (lastPaused && !_isTemperatureReceivingPaused)
|
||||||
|
{
|
||||||
|
Log("从暂停状态恢复,重新发送开始温度数据传输命令");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1398,27 +1399,16 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
|
|
||||||
// 使用非阻塞方式检查是否有数据可读
|
// 使用非阻塞方式检查是否有数据可读
|
||||||
// 先检查连接是否仍然有效
|
// 先检查连接是否仍然有效
|
||||||
if (localTcpClient != null && !IsTcpClientConnected(localTcpClient))
|
DateTime now = DateTime.Now;
|
||||||
|
if ((now - lastConnectionCheckTime).TotalMilliseconds > CONNECTION_CHECK_INTERVAL_MS)
|
||||||
{
|
{
|
||||||
Log("检测到连接已断开,准备重建连接");
|
if (localTcpClient != null && !IsTcpClientConnected(localTcpClient))
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (localStream != null)
|
Log("检测到连接已断开,准备重建连接");
|
||||||
{
|
CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient);
|
||||||
localStream.Close();
|
continue;
|
||||||
localStream = null;
|
|
||||||
}
|
|
||||||
if (localTcpClient != null)
|
|
||||||
{
|
|
||||||
localTcpClient.Close();
|
|
||||||
localTcpClient = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
lastConnectionCheckTime = now;
|
||||||
{
|
|
||||||
Log($"关闭断开的连接时发生异常: {ex.Message}");
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localStream.DataAvailable)
|
if (localStream.DataAvailable)
|
||||||
@@ -1434,6 +1424,8 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
if (isPaused)
|
if (isPaused)
|
||||||
{
|
{
|
||||||
Log("处于暂停状态,数据已接收但丢弃");
|
Log("处于暂停状态,数据已接收但丢弃");
|
||||||
|
// 根据规范,暂停时Sleep 1秒
|
||||||
|
Thread.Sleep(1000);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1441,7 +1433,15 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
Array.Copy(buffer, receivedBytes, bytesRead);
|
Array.Copy(buffer, receivedBytes, bytesRead);
|
||||||
// 同步接收并处理数据
|
// 同步接收并处理数据
|
||||||
temperatureDataAccumulator.Add(receivedBytes);
|
temperatureDataAccumulator.Add(receivedBytes);
|
||||||
|
// 记录处理开始时间
|
||||||
|
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
|
||||||
|
stopwatch.Start();
|
||||||
|
|
||||||
ProcessReceivedTemperatureData(temperatureDataAccumulator);
|
ProcessReceivedTemperatureData(temperatureDataAccumulator);
|
||||||
|
|
||||||
|
// 停止计时并记录处理时间
|
||||||
|
stopwatch.Stop();
|
||||||
|
Log($"处理温度数据耗时: {stopwatch.ElapsedMilliseconds}ms");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (bytesRead == 0)
|
else if (bytesRead == 0)
|
||||||
@@ -1456,23 +1456,7 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 清理连接资源
|
// 清理连接资源
|
||||||
try
|
CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient);
|
||||||
{
|
|
||||||
if (localStream != null)
|
|
||||||
{
|
|
||||||
localStream.Close();
|
|
||||||
localStream = null;
|
|
||||||
}
|
|
||||||
if (localTcpClient != null)
|
|
||||||
{
|
|
||||||
localTcpClient.Close();
|
|
||||||
localTcpClient = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
|
|
||||||
localStream = null;
|
|
||||||
localTcpClient = null;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1481,7 +1465,7 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log($"接收数据异常: {ex.Message}");
|
Log($"接收数据异常: {ex.Message}, 堆栈: {ex.StackTrace}");
|
||||||
|
|
||||||
// 更新状态标志
|
// 更新状态标志
|
||||||
lock (_lockObject)
|
lock (_lockObject)
|
||||||
@@ -1490,93 +1474,220 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 清理连接资源
|
// 清理连接资源
|
||||||
try
|
CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient);
|
||||||
{
|
|
||||||
localStream.Close();
|
|
||||||
localTcpClient.Close();
|
|
||||||
}
|
|
||||||
catch {}
|
|
||||||
|
|
||||||
localStream = null;
|
|
||||||
localTcpClient = null;
|
|
||||||
|
|
||||||
// 异常后等待一段时间再重试
|
// 异常后等待一段时间再重试
|
||||||
Thread.Sleep(ERROR_SLEEP_MS);
|
Thread.Sleep(ERROR_SLEEP_MS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// 没有有效连接,短暂休眠
|
|
||||||
Thread.Sleep(MEDIUM_SLEEP_MS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReceiveTemperatureDataWithTcp() - 严重异常: {ex.Message}");
|
|
||||||
}
|
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReceiveTemperatureDataWithTcp() - 执行完成");
|
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReceiveTemperatureDataWithTcp() - 执行完成");
|
||||||
|
|
||||||
// 确保状态正确更新
|
// 确保状态正确更新
|
||||||
lock (_lockObject)
|
lock (_lockObject)
|
||||||
{
|
{
|
||||||
_isReceivingTemperatureData = false;
|
_isReceivingTemperatureData = false;
|
||||||
}
|
|
||||||
|
|
||||||
// 清理资源
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (localStream != null)
|
|
||||||
{
|
|
||||||
localStream.Close();
|
|
||||||
localStream = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (localTcpClient != null)
|
|
||||||
{
|
|
||||||
localTcpClient.Close();
|
|
||||||
localTcpClient = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {}
|
|
||||||
|
|
||||||
Log("温度数据接收线程已结束,重置相关状态");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 清理资源
|
||||||
|
CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient);
|
||||||
|
|
||||||
|
Log("温度数据接收线程已结束,重置相关状态");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查是否应该停止接收温度数据
|
||||||
|
/// </summary>
|
||||||
|
private bool ShouldStop()
|
||||||
|
{
|
||||||
|
lock (_lockObject)
|
||||||
|
{
|
||||||
|
return (_stopTemperatureEvent != null && _stopTemperatureEvent.WaitOne(0)) || _isDisposed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清理连接资源
|
||||||
|
/// </summary>
|
||||||
|
private void CleanupConnectionResources(ref NetworkStream stream, ref TcpClient client)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (stream != null)
|
||||||
|
{
|
||||||
|
stream.Close();
|
||||||
|
stream = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log($"关闭网络流异常: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (client != null)
|
||||||
|
{
|
||||||
|
client.Close();
|
||||||
|
client = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log($"关闭TCP客户端异常: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查温度接收是否处于暂停状态
|
||||||
|
/// </summary>
|
||||||
|
private bool IsTemperatureReceivingPaused()
|
||||||
|
{
|
||||||
|
lock (_lockObject)
|
||||||
|
{
|
||||||
|
return _isTemperatureReceivingPaused;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置温度接收状态标志
|
||||||
|
/// </summary>
|
||||||
|
private void SetReceivingState(bool isReceiving)
|
||||||
|
{
|
||||||
|
lock (_lockObject)
|
||||||
|
{
|
||||||
|
_isReceivingTemperatureData = isReceiving;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 处理接收到的温度数据
|
/// 处理接收到的温度数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dataAccumulator">累积的温度数据</param>
|
/// <param name="dataAccumulator">累积的温度数据包列表</param>
|
||||||
private void ProcessReceivedTemperatureData(List<byte[]> dataAccumulator)
|
private void ProcessReceivedTemperatureData(List<byte[]> dataAccumulator)
|
||||||
{
|
{
|
||||||
//根据TemperatureData类的要求,每个温度帧包含9字节头部 + 温度数据
|
// 头部标识
|
||||||
// 根据注释,设备实际提供的数据分辨率应为256x192,最终映射到512x384显示
|
const string HEADER_MARKER = "+TEMP";
|
||||||
const int HEADER_SIZE = 9; // 9字节头部("+TEMP"+数据长度)
|
|
||||||
const int WIDTH = 256;
|
const int WIDTH = 256;
|
||||||
const int HEIGHT = 192;
|
const int HEIGHT = 192;
|
||||||
const int TEMPERATURE_DATA_FRAME_SIZE = HEADER_SIZE + WIDTH * HEIGHT * 2; // 9字节头部 + 每个温度值2字节
|
const int HEADER_SIZE = 9; // 9字节头部("+TEMP"+数据长度)
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Log($"开始处理温度数据,当前累积数据量: {dataAccumulator.Count} 字节,所需帧大小: {TEMPERATURE_DATA_FRAME_SIZE} 字节");
|
Log($"开始处理温度数据,当前累积数据包数量: {dataAccumulator.Count}");
|
||||||
|
// 开始循环处理列表
|
||||||
// 检查是否有足够的数据构成完整的温度数据帧
|
while (dataAccumulator.Count > 0)
|
||||||
while (dataAccumulator.Count >= TEMPERATURE_DATA_FRAME_SIZE)
|
|
||||||
{
|
{
|
||||||
Log($"找到完整的温度数据帧,开始处理");
|
// 从列表中读取第一个数组
|
||||||
|
byte[] currentArray = dataAccumulator[0];
|
||||||
|
Log($"检查第一个数组,长度: {currentArray.Length} 字节");
|
||||||
|
|
||||||
// 提取一帧温度数据
|
// 查看是否有头信息
|
||||||
byte[] temperatureFrame = dataAccumulator.GetRange(0, TEMPERATURE_DATA_FRAME_SIZE).ToArray();
|
int headerIndex = FindHeader(currentArray, HEADER_MARKER);
|
||||||
dataAccumulator.RemoveRange(0, TEMPERATURE_DATA_FRAME_SIZE);
|
|
||||||
|
if (headerIndex == -1)
|
||||||
|
{
|
||||||
|
// 如果没有头信息,将数组从列表中移除
|
||||||
|
Log("未在数组中找到头部信息,移除该数组");
|
||||||
|
dataAccumulator.RemoveAt(0);
|
||||||
|
// 跳转到循环开始,检查列表是否为空
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Log($"提取温度数据帧完成,剩余累积数据量: {dataAccumulator.Count} 字节");
|
// 如果头部不在数组的开始位置,需要移除头部之前的无效数据
|
||||||
|
if (headerIndex > 0)
|
||||||
|
{
|
||||||
|
Log($"头部不在数组开始位置,移除前 {headerIndex} 个无效字节");
|
||||||
|
byte[] newArray = new byte[currentArray.Length - headerIndex];
|
||||||
|
Array.Copy(currentArray, headerIndex, newArray, 0, newArray.Length);
|
||||||
|
dataAccumulator[0] = newArray;
|
||||||
|
currentArray = newArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看头信息中数据长度信息
|
||||||
|
// 确保数组至少包含完整的头部
|
||||||
|
if (currentArray.Length < HEADER_SIZE)
|
||||||
|
{
|
||||||
|
Log("数组长度不足头部大小,退出循环");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从头部解析数据长度
|
||||||
|
int dataLength = CalculateDataLength(currentArray);
|
||||||
|
int totalFrameSize = HEADER_SIZE + dataLength;
|
||||||
|
|
||||||
|
// 检查数组中是否有足够的数据长度
|
||||||
|
while (currentArray.Length < totalFrameSize)
|
||||||
|
{
|
||||||
|
// 如果没有足够的数据长度,看列表中是否有下一个数组
|
||||||
|
if (dataAccumulator.Count <= 1)
|
||||||
|
{
|
||||||
|
// 如果没有,则退出循环
|
||||||
|
Log("数据长度不足,且没有更多数组可以合并,退出循环");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 否则将下一个数组合并到当前数组中尾部
|
||||||
|
Log("数据长度不足,合并下一个数组到当前数组尾部");
|
||||||
|
byte[] nextArray = dataAccumulator[1];
|
||||||
|
byte[] mergedArray = new byte[currentArray.Length + nextArray.Length];
|
||||||
|
Array.Copy(currentArray, 0, mergedArray, 0, currentArray.Length);
|
||||||
|
Array.Copy(nextArray, 0, mergedArray, currentArray.Length, nextArray.Length);
|
||||||
|
|
||||||
|
// 更新当前数组和列表
|
||||||
|
dataAccumulator[0] = mergedArray;
|
||||||
|
dataAccumulator.RemoveAt(1);
|
||||||
|
currentArray = mergedArray;
|
||||||
|
Log($"合并后数组长度: {currentArray.Length} 字节");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查数据是否足够(可能因为没有更多数组可以合并而不足)
|
||||||
|
if (currentArray.Length < totalFrameSize)
|
||||||
|
{
|
||||||
|
Log("数据长度仍不足,退出循环等待更多数据");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查数据长度范围内是否又出现了头信息
|
||||||
|
int nextHeaderIndex = FindHeader(currentArray, HEADER_MARKER, HEADER_SIZE, totalFrameSize);
|
||||||
|
if (nextHeaderIndex != -1)
|
||||||
|
{
|
||||||
|
// 如果有,则将数组中第二个头信息之前的数据移除
|
||||||
|
Log($"在数据长度范围内发现另一个头信息,索引位置: {nextHeaderIndex},移除前面的数据");
|
||||||
|
byte[] newArray = new byte[currentArray.Length - nextHeaderIndex];
|
||||||
|
Array.Copy(currentArray, nextHeaderIndex, newArray, 0, newArray.Length);
|
||||||
|
dataAccumulator[0] = newArray;
|
||||||
|
// 跳转到检查头信息的步骤
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有重复头信息,则将数据长度范围内的数据从数组取出进行处理
|
||||||
|
Log($"数据有效,提取完整帧数据,长度: {totalFrameSize} 字节");
|
||||||
|
byte[] temperatureFrame = new byte[totalFrameSize];
|
||||||
|
Array.Copy(currentArray, 0, temperatureFrame, 0, totalFrameSize);
|
||||||
|
|
||||||
|
// 保留剩余部分到数组中
|
||||||
|
if (currentArray.Length > totalFrameSize)
|
||||||
|
{
|
||||||
|
Log($"保留剩余数据,长度: {currentArray.Length - totalFrameSize} 字节");
|
||||||
|
byte[] remainingBytes = new byte[currentArray.Length - totalFrameSize];
|
||||||
|
Array.Copy(currentArray, totalFrameSize, remainingBytes, 0, remainingBytes.Length);
|
||||||
|
dataAccumulator[0] = remainingBytes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 如果没有剩余数据,移除当前数组
|
||||||
|
dataAccumulator.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理提取出的温度数据帧
|
||||||
|
Log($"成功提取完整温度数据帧,长度: {temperatureFrame.Length} 字节");
|
||||||
|
|
||||||
// 获取温度补偿值
|
// 获取温度补偿值
|
||||||
float compensationValue = GetTemperatureCompensationValue();
|
float compensationValue = GetTemperatureCompensationValue();
|
||||||
@@ -1591,7 +1702,7 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
Log($"温度数据接收事件触发完成");
|
Log($"温度数据接收事件触发完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
Log($"温度数据处理完成");
|
Log($"温度数据处理完成,剩余数据包数量: {dataAccumulator.Count}");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1602,6 +1713,97 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 在字节数组中查找头部标识
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">要搜索的字节数组</param>
|
||||||
|
/// <param name="headerMarker">头部标识字符串</param>
|
||||||
|
/// <returns>头部标识的起始索引,未找到返回-1</returns>
|
||||||
|
private int FindHeader(byte[] data, string headerMarker)
|
||||||
|
{
|
||||||
|
byte[] headerBytes = Encoding.ASCII.GetBytes(headerMarker);
|
||||||
|
|
||||||
|
for (int i = 0; i <= data.Length - headerBytes.Length; i++)
|
||||||
|
{
|
||||||
|
bool match = true;
|
||||||
|
for (int j = 0; j < headerBytes.Length; j++)
|
||||||
|
{
|
||||||
|
if (data[i + j] != headerBytes[j])
|
||||||
|
{
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 在字节数组的指定范围内查找头部标识
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">要搜索的字节数组</param>
|
||||||
|
/// <param name="headerMarker">头部标识字符串</param>
|
||||||
|
/// <param name="startIndex">搜索的起始索引</param>
|
||||||
|
/// <param name="endIndex">搜索的结束索引(不包含)</param>
|
||||||
|
/// <returns>头部标识的起始索引,未找到返回-1</returns>
|
||||||
|
private int FindHeader(byte[] data, string headerMarker, int startIndex, int endIndex)
|
||||||
|
{
|
||||||
|
byte[] headerBytes = Encoding.ASCII.GetBytes(headerMarker);
|
||||||
|
|
||||||
|
// 确保参数有效
|
||||||
|
if (startIndex < 0)
|
||||||
|
startIndex = 0;
|
||||||
|
if (endIndex > data.Length)
|
||||||
|
endIndex = data.Length;
|
||||||
|
if (startIndex >= endIndex)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// 调整结束索引,确保有足够空间容纳完整的头部标识
|
||||||
|
int adjustedEndIndex = endIndex - headerBytes.Length + 1;
|
||||||
|
if (startIndex >= adjustedEndIndex)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (int i = startIndex; i < adjustedEndIndex; i++)
|
||||||
|
{
|
||||||
|
bool match = true;
|
||||||
|
for (int j = 0; j < headerBytes.Length; j++)
|
||||||
|
{
|
||||||
|
if (data[i + j] != headerBytes[j])
|
||||||
|
{
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据头部计算数据长度
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="headerData">包含头部的字节数组</param>
|
||||||
|
/// <returns>数据长度</returns>
|
||||||
|
private int CalculateDataLength(byte[] headerData)
|
||||||
|
{
|
||||||
|
// 这里需要根据实际的头部格式来解析数据长度
|
||||||
|
// 假设头部的第5-8字节包含数据长度信息(4字节整数)
|
||||||
|
// 实际实现需要根据设备的协议规范进行调整
|
||||||
|
if (headerData.Length >= 9) // 确保至少有9字节头部
|
||||||
|
{
|
||||||
|
// 假设数据长度是固定的:256x192分辨率,每个温度值2字节
|
||||||
|
return 256 * 192 * 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 触发温度数据接收事件
|
/// 触发温度数据接收事件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -5759,5 +5961,30 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
// 移除内部的TemperatureData类定义,使用全局的TemperatureData类
|
// 移除内部的TemperatureData类定义,使用全局的TemperatureData类
|
||||||
|
|
||||||
#endregion 温度相关辅助类
|
#endregion 温度相关辅助类
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清理TCP连接资源的辅助方法
|
||||||
|
/// </summary>
|
||||||
|
private void CleanupConnectionResources(NetworkStream stream, TcpClient tcpClient, out NetworkStream cleanedStream, out TcpClient cleanedTcpClient)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (stream != null)
|
||||||
|
{
|
||||||
|
stream.Close();
|
||||||
|
}
|
||||||
|
if (tcpClient != null)
|
||||||
|
{
|
||||||
|
tcpClient.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log($"清理连接资源时发生异常: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanedStream = null;
|
||||||
|
cleanedTcpClient = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user