refactor(蓝牙&多语言): 优化多项功能并修复问题

1. 更新多语言文件中星期的英文缩写为完整标准写法
2. 移除OTA传输中的额外延迟,优化传输速度
3. 蓝牙连接时请求高吞吐量MTU和连接优先级
4. 修复蚊虫数据请求前初始化容器的时序问题
5. 重构BLE帧解析逻辑,批量处理帧避免协程积压
This commit is contained in:
“虞渠成” 2026-07-14 08:56:20 +08:00
parent 8f20291be6
commit b83bf75330
5 changed files with 59 additions and 49 deletions

View File

@ -652,22 +652,22 @@
{ {
"key": "100131", "key": "100131",
"zh": "一", "zh": "一",
"en": "M" "en": "Mon"
}, },
{ {
"key": "100132", "key": "100132",
"zh": "二", "zh": "二",
"en": "T" "en": "Tue"
}, },
{ {
"key": "100133", "key": "100133",
"zh": "三", "zh": "三",
"en": "W" "en": "Wed"
}, },
{ {
"key": "100134", "key": "100134",
"zh": "四", "zh": "四",
"en": "Th" "en": "Thu"
}, },
{ {
"key": "100135", "key": "100135",

View File

@ -2337,57 +2337,60 @@ namespace Kill.Bluetooth
/// </summary> /// </summary>
private void TryParseFrameInternal() private void TryParseFrameInternal()
{ {
byte[] buffer = _receiveBuffer.ToArray(); // 收集所有完整帧,避免频繁 StartCoroutine 和 return 导致积压
var frames = new List<BLEFrame>();
int totalRemoved = 0;
// 查找帧头 while (totalRemoved < _receiveBuffer.Count)
for (int i = 0; i < buffer.Length - 1; i++)
{ {
if (buffer[i] == BLEConstants.FRAME_HEADER_1 && int searchStart = totalRemoved;
buffer[i + 1] == BLEConstants.FRAME_HEADER_2) byte[] buffer = _receiveBuffer.ToArray();
bool found = false;
for (int i = searchStart; i < buffer.Length - 1; i++)
{ {
// 检查是否有足够的数据长度字段 if (buffer[i] == BLEConstants.FRAME_HEADER_1 &&
if (i + 4 >= buffer.Length) buffer[i + 1] == BLEConstants.FRAME_HEADER_2)
{ {
continue; if (i + 4 >= buffer.Length) continue;
}
byte dataLength = buffer[i + 4]; byte dataLength = buffer[i + 4];
int totalFrameLength = 7 + dataLength; // 帧头(2) + 命令(1) + 读写(1) + 长度(1) + 数据(dataLength) + CRC(2) int totalFrameLength = 7 + dataLength;
// 检查是否有完整的帧 if (i + totalFrameLength > buffer.Length) continue;
if (i + totalFrameLength > buffer.Length)
{
continue;
}
// 提取帧数据 byte[] frameBytes = new byte[totalFrameLength];
byte[] frameBytes = new byte[totalFrameLength]; Buffer.BlockCopy(buffer, i, frameBytes, 0, totalFrameLength);
Buffer.BlockCopy(buffer, i, frameBytes, 0, totalFrameLength);
// 解析帧 if (BLEFrame.TryParse(frameBytes, out BLEFrame frame))
if (BLEFrame.TryParse(frameBytes, out BLEFrame frame)) {
{ frames.Add(frame);
// 从缓冲区移除已解析的数据 totalRemoved += (i - searchStart) + totalFrameLength;
int removeLength = i + totalFrameLength; searchStart = totalRemoved;
_receiveBuffer.RemoveRange(0, removeLength); found = true;
break;
// 在锁外处理帧,避免死锁和重入问题 }
// 使用异步方式在下一帧处理 else
StartCoroutine(HandleFrameAsync(frame)); {
return; LogWarning("帧解析失败 (CRC校验可能失败)");
} }
else
{
LogWarning("帧解析失败 (CRC校验可能失败)");
} }
} }
if (!found) break;
} }
// 清理过期的缓冲区数据 (保留最后100字节) // 移除已解析的数据
if (totalRemoved > 0)
_receiveBuffer.RemoveRange(0, totalRemoved);
// 清理过期缓冲区
if (_receiveBuffer.Count > 200) if (_receiveBuffer.Count > 200)
{
_receiveBuffer.RemoveRange(0, _receiveBuffer.Count - 100); _receiveBuffer.RemoveRange(0, _receiveBuffer.Count - 100);
}
// 在锁外批量处理帧
foreach (var frame in frames)
StartCoroutine(HandleFrameAsync(frame));
} }
/// <summary> /// <summary>

View File

@ -4,6 +4,7 @@ using System.Collections.Generic;
using Kill.Core; using Kill.Core;
using Kill.UI; using Kill.UI;
using Kill.UI.Components; using Kill.UI.Components;
using static BluetoothLEHardwareInterface;
namespace Kill.Bluetooth namespace Kill.Bluetooth
{ {
@ -828,6 +829,14 @@ namespace Kill.Bluetooth
OnConnected?.Invoke(address); OnConnected?.Invoke(address);
// 请求高吞吐量MTU 512 + 高优先级连接间隔
BluetoothLEHardwareInterface.RequestMtu(address, 512, (addr, mtu) =>
{
Log($"MTU 协商完成: {mtu} 字节");
});
BluetoothLEHardwareInterface.BluetoothConnectionPriority(ConnectionPriority.High);
Log("已请求高优先级 BLE 连接");
// 延迟通知连接成功并可通信 // 延迟通知连接成功并可通信
Invoke(nameof(NotifyConnectedSuccess), 0.5f); Invoke(nameof(NotifyConnectedSuccess), 0.5f);
} }

View File

@ -284,12 +284,6 @@ namespace Kill.Bluetooth
// 报告进度(无重试) // 报告进度(无重试)
OnTransferProgress?.Invoke(i + 1, _totalPackets, 0, 0); OnTransferProgress?.Invoke(i + 1, _totalPackets, 0, 0);
// 每包之间添加小延迟,避免设备处理不过来
if (i < _totalPackets - 1)
{
yield return new WaitForSeconds(0.01f);
}
} }
SetState(OTAState.Ending); SetState(OTAState.Ending);

View File

@ -1498,6 +1498,10 @@ namespace Kill.UI.Pages
Debug.Log($"检测到 {count.Count} 条蚊虫数据,正在请求..."); Debug.Log($"检测到 {count.Count} 条蚊虫数据,正在请求...");
// 在请求前先初始化接收容器,避免通知先于主线程回调到达导致数据丢失
mosquitoDatas = new List<MosquitoData>();
aimMosquitoDataCount = (int)count.Count;
// 步骤2: 请求所有蚊虫数据 // 步骤2: 请求所有蚊虫数据
BLECommunicationManager.Instance.RequestMosquitoData(count.Count, (success) => BLECommunicationManager.Instance.RequestMosquitoData(count.Count, (success) =>
{ {
@ -1509,12 +1513,12 @@ namespace Kill.UI.Pages
tip=tip.Replace("{0}",count.ToString()); tip=tip.Replace("{0}",count.ToString());
ToastUI.ShowText(tip); ToastUI.ShowText(tip);
Debug.Log($"已请求 {count.Count} 条蚊虫数据,等待接收..."); Debug.Log($"已请求 {count.Count} 条蚊虫数据,等待接收...");
mosquitoDatas=new List<MosquitoData>();
aimMosquitoDataCount=(int)count.Count;
} }
else else
{ {
Debug.Log("蚊虫数据请求失败"); Debug.Log("蚊虫数据请求失败");
mosquitoDatas = null;
aimMosquitoDataCount = 0;
LoadingUI.Hide(); LoadingUI.Hide();
} }
}); });