蓝牙设备逆向:Web Bluetooth调用writeValue发送Wireshark捕获值
解决蓝牙GATT写入错误并正确发送指定十六进制值
嘿,我来帮你搞定这个蓝牙GATT写入的问题!你遇到的DOMException: GATT operation failed for unknown reason很大概率是因为发送的数据格式不对——你之前尝试的几种写法都没有正确把0120030000000000这个十六进制序列转换成蓝牙设备期望的字节流。
问题出在哪?
你之前的写法都误解了TypedArray的用法:
- 直接传
0x0120030000000000:这是一个64位数字,而writeValue需要的是ArrayBuffer或TypedArray类型,不是单个数字。 Uint16Array([0x0120030000000000]):Uint16Array的每个元素是16位(2字节),你把整个64位数字塞进去会导致溢出,生成完全错误的字节序列。Uint8Array([0x0120030000000000]):Uint8Array每个元素只能存8位(1字节),这个大数字会被截断成单个字节,完全不符合设备需要的8字节序列。- TextEncoder编码:这是用来将字符串转换成字节的工具,和十六进制字节流完全不相关,当然无效。
正确的做法:拆分十六进制为单个字节
Wireshark里捕获的0120030000000000是8个连续的十六进制字节,每两位代表一个字节,所以你需要把它拆分成8个单独的字节值,用Uint8Array包装后发送。
完整代码示例
// 将目标十六进制值拆分为单个字节的十六进制常量 const targetBytes = new Uint8Array([ 0x01, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 ]); try { // 尝试写入数据,部分设备需要指定写入类型(比如需要响应) await characteristic.writeValue(targetBytes); // 如果上面的writeValue报错,可以试试带响应的写入: // await characteristic.writeValueWithResponse(targetBytes); console.log("数据写入成功!"); } catch (error) { console.error("写入失败详情:", error); }
额外排查点(针对GATT未知错误)
如果按上面的写法还是报错,你可以检查这几点:
- 确认目标特征的properties包含
write或writeWithoutResponse(可以通过characteristic.properties查看) - 确保设备处于稳定连接状态,没有中途断开
- 部分设备要求写入时指定类型,比如用
writeValueWithResponse替代writeValue,或者在选项里指定:await characteristic.writeValue(targetBytes, { type: 'response' })
内容的提问来源于stack exchange,提问作者Gurmukh Panesar
相关产品推荐
相关产品推荐

