
macos 的 web bluetooth api 对单次写入数据长度限制为 152 字节,超出则触发底层重试机制,导致指令被重复发送;而 windows 无此严格限制,因此同一套代码在两平台行为不一致。解决关键在于分块写入并确保每块 ≤152 字节,同时添加写入完成确认与防重入保护。
macos 的 web bluetooth api 对单次写入数据长度限制为 152 字节,超出则触发底层重试机制,导致指令被重复发送;而 windows 无此严格限制,因此同一套代码在两平台行为不一致。解决关键在于分块写入并确保每块 ≤152 字节,同时添加写入完成确认与防重入保护。
在基于 Blazor + JavaScript 的 Web Bluetooth 应用中,您遇到的“macOS 下切割指令无限重复执行、且 console.log("Write operation successful") 不触发”问题,并非设备故障或 Chrome 实现缺陷,而是 macOS 特定的 BLE 协议栈行为:其 Core Bluetooth 框架对 writeValue() 调用施加了严格的 MTU(Maximum Transmission Unit)约束——单次 writeValue() 最多仅允许 152 字节有效载荷(含 ATT 层头,实际可用约 149–151 字节)。当传入超长 Uint8Array 时,Safari 和 Chrome on macOS 并不会抛出错误,而是静默截断或触发不可见的底层重发逻辑,最终表现为指令循环下发、await 永不 resolve、回调不执行。
✅ 正确做法:分块写入(Chunked Write)
请将原 writeValue 函数重构为支持自动分块的版本,示例如下:
export async function writeValue(deviceId, serviceId, characteristicId, value) {
const device = getDevice(deviceId);
console.log("START WRITE VALUE.JS", value);
if (!device?.gatt?.connected) {
console.warn("Device not connected, retrying...");
await sleep(1000);
return writeValue(deviceId, serviceId, characteristicId, value);
}
try {
const service = await device.gatt.getPrimaryService(serviceId);
const characteristic = await service.getCharacteristic(characteristicId);
// ? 关键:按 152 字节分块
const MAX_CHUNK_SIZE = 152;
const data = new Uint8Array(value);
let offset = 0;
while (offset <h3>⚠️ 补充注意事项</h3>
禁用递归重试逻辑:原代码中 else { await sleep(1000); await writeValue(...); } 在连接失败时会无限递归调用,极易引发堆栈溢出或重复触发。应改用有限次数重试(如 3 次)+ 明确错误上报。
防重复提交:在 Blazor 端按钮点击后立即禁用按钮,或使用 AbortController 配合 characteristic.writeValueWithResponse()(若设备支持)确保可取消性。
验证设备 MTU:可通过 device.gatt.mtu 获取当前协商 MTU(但注意该值在 macOS 上常返回默认 23,不可靠),因此始终以 152 为安全上限更稳妥。
-
服务/特征 ID 建议硬编码优化:您代码中 serviceId 和 characteristicId 参数未被使用,却写死 UUID。建议统一提取为常量,提升可维护性:
const CUTTING_SERVICE_UUID = "e2088282-4fde-42f9-bb22-6ec3c7ed8f91"; const CUTTING_CHAR_UUID = "6d92661d-f429-4d67-929b-28e7a9780912";
✅ 总结
macOS 的 Web Bluetooth 行为差异并非“bug”,而是其 BLE 栈对规范的更严格实现。解决问题的核心不是绕过系统,而是适配它:主动分块、明确边界、杜绝超限、增强可观测性。经此改造后,您的切割指令将在 Windows 与 macOS 上均稳定、精确、一次性执行,彻底告别“无限切割”的诡异现象。











