Mac端Web Bluetooth指令重复发送问题排查求助
排查与解决Mac端Chrome下Web Bluetooth指令重复发送问题
核心问题定位
你的代码存在无终止条件的递归重试逻辑,当Mac端Chrome的蓝牙连接状态判断出现偏差时,会触发无限递归调用writeValue,导致指令重复发送。同时Mac Chrome的Web Bluetooth实现与Windows端存在细节差异,需要针对性调整。
排查思路与修复技巧
1. 修复递归重试的无限循环问题
当前代码在设备未连接时递归调用自身,但没有终止限制,一旦Mac端device.gatt.connected判断延迟或误判,就会无限重复执行。给重试添加最大次数限制:
export async function writeValue(deviceId, serviceId, characteristicId, value, retryCount = 0) { const maxRetries = 3; // 设置最大重试次数 var device = getDevice(deviceId); console.log("START WRITE VALUE.JS", value); if (device.gatt.connected) { try { const service = await device.gatt.getPrimaryService("e2088282-4fde-42f9-bb22-6ec3c7ed8f91"); const characteristic = "6d92661d-f429-4d67-929b-28e7a9780912"; const ch = await service.getCharacteristic(characteristic); await ch.writeValue(new Uint8Array(value)); console.log("Write operation successful"); } catch (error) { console.error("Error during write operation:", error); } } else { if (retryCount >= maxRetries) { console.error("Max retries reached, device not connected"); return; } await sleep(1000); await writeValue(deviceId, serviceId, characteristicId, value, retryCount + 1); } }
2. 适配Mac Chrome的Web Bluetooth写入特性
Mac端Chrome对writeValue的处理存在差异,可能因设备蓝牙特性属性(如是否支持带响应写入)导致写入未被正确确认,显式指定写入类型:
// 替换原writeValue调用,根据设备特性选择写入类型 await ch.writeValue(new Uint8Array(value), { type: "withResponse" });
注:若设备支持无响应写入,使用
"withoutResponse"可减少延迟;若需确保写入成功,优先用"withResponse"。
3. 提升连接状态判断的可靠性
Mac端蓝牙连接状态判断可能存在延迟,不要依赖device.gatt.connected的即时值,主动尝试重连后再重试:
else { if (retryCount >= maxRetries) { console.error("Max retries reached, failed to connect device"); return; } try { await device.gatt.connect(); // 主动尝试重新连接设备 } catch (connectError) { console.error("Failed to reconnect device:", connectError); } await sleep(1000); await writeValue(deviceId, serviceId, characteristicId, value, retryCount + 1); }
4. 避免Blazor按钮重复触发
Mac端Blazor可能存在按钮点击事件重复触发的问题,添加状态锁防止重复调用:
<button @onclick="SendCutCommand">发送切割指令</button> @code { private bool _isSending; private async Task SendCutCommand() { if (_isSending) return; _isSending = true; try { await JSRuntime.InvokeVoidAsync("writeValue", deviceId, serviceId, characteristicId, cutCommandValue); } finally { _isSending = false; } } }
5. 增加日志追踪细节
在Mac端Chrome DevTools中添加更详细的日志,定位问题根源:
console.log(`Write attempt ${retryCount + 1}, device connected: ${device.gatt.connected}`);
内容的提问来源于stack exchange,提问作者user17511401
相关产品推荐
相关产品推荐

