
1. 环境准备搭建微信小程序蓝牙开发基础第一次接触微信小程序的蓝牙开发时我踩过不少坑。记得当时为了调试一个简单的温度计设备光是环境配置就折腾了大半天。现在回头看其实只要掌握几个关键点半小时就能搞定基础环境。首先需要确认的是开发工具版本。我推荐使用最新稳定版的微信开发者工具目前2023年最新版本已经对蓝牙调试做了很多优化。安装完成后记得在详情-本地设置中勾选不校验合法域名这个选项在开发阶段可以避免很多不必要的麻烦。项目配置文件中需要声明蓝牙权限这是很多新手容易忽略的一步。在app.json里添加以下配置{ permission: { scope.bluetooth: { desc: 需要蓝牙权限连接设备 } } }实际开发中我发现不同手机厂商对蓝牙的支持程度差异很大。比如某些国产手机需要手动开启GPS才能正常使用蓝牙功能而iOS设备则相对统一。建议在代码中加入完善的错误处理wx.openBluetoothAdapter({ success(res) { console.log(蓝牙适配器初始化成功) }, fail(err) { console.error(初始化失败, err) if (err.errCode 10001) { wx.showToast({ title: 请检查手机蓝牙是否开启 }) } } })硬件准备方面我建议先用一些常见设备做测试比如小米手环、智能体重秤等。这些设备协议成熟调试起来比较容易。等掌握了基本流程后再对接自己的目标硬件会顺利很多。2. 设备发现高效扫描与筛选策略搜索蓝牙设备看似简单但要做好其实很有讲究。刚开始我直接调用wx.startBluetoothDevicesDiscovery就开始处理结果结果发现设备列表里混入了大量无关设备用户体验很糟糕。后来我总结出一个实用的过滤方案通过设备名称前缀和serviceUUID双重过滤。比如我们开发的智能锁设备都以SL_开头代码可以这样写wx.onBluetoothDeviceFound((res) { const device res.devices[0] if (device.name device.name.startsWith(SL_)) { this.deviceList.push(device) } })搜索超时设置也很重要。我一般会设置10秒的搜索时限同时给用户显示倒计时提示this.searchTimer setTimeout(() { wx.stopBluetoothDevicesDiscovery() wx.showToast({ title: 搜索完成, icon: none }) }, 10000)对于需要持续监测设备的场景我建议采用间歇式搜索策略搜索3秒暂停2秒如此循环。这样既能节省电量又能保持设备列表更新。实测下来这种方案比持续搜索要稳定得多。设备列表展示也有讲究。除了显示设备名称最好把信号强度(RSSI)也展示出来方便用户选择距离最近的设备。可以用进度条直观呈现view classdevice-item wx:for{{deviceList}} text{{item.name}}/text progress percent{{item.RSSI 100}} stroke-width6/ /view3. 稳定连接提升蓝牙连接成功率连接失败是蓝牙开发中最常见的问题。经过多次实践我总结出一个稳定的连接流程先停止搜索再建立连接最后设置合适的超时时间。连接代码看似简单但细节决定成败wx.createBLEConnection({ deviceId: deviceId, timeout: 5000, // 5秒超时 success: (res) { this.getServices(deviceId) }, fail: (err) { if (err.errCode 10012) { wx.showToast({ title: 连接超时请靠近设备 }) } } })连接成功后建议立即获取设备的所有服务UUID。这里有个小技巧服务UUID通常以0000XXXX-0000-1000-8000-00805F9B34FB的形式出现其中XXXX是关键部分。我们可以这样提取const shortUUID service.uuid.substring(4, 8) if (shortUUID FFE0) { // 这是我们需要的服务 }对于需要保持长连接的场景一定要实现自动重连机制。我的做法是在连接断开时先等待2秒再尝试重连最多重试3次wx.onBLEConnectionStateChange((res) { if (!res.connected) { this.reconnect(deviceId, 3) } }) reconnect(deviceId, retryCount) { if (retryCount 0) return setTimeout(() { wx.createBLEConnection({ deviceId }) }, 2000) }4. 数据通信高效可靠的数据传输方案数据通信是蓝牙开发的核心也是最容易出问题的环节。经过多个项目的积累我总结出一套稳定的数据传输方案。首先是特征值操作。一定要先确认特征值的属性不同的属性支持不同的操作const chars res.characteristics this.writeChar chars.find(c c.properties.write !c.properties.notify ) this.notifyChar chars.find(c c.properties.notify )发送数据时ArrayBuffer的处理是关键。我封装了一个通用的转换方法function stringToBuffer(str) { const buffer new ArrayBuffer(str.length) const view new Uint8Array(buffer) for (let i 0; i str.length; i) { view[i] str.charCodeAt(i) } return buffer }对于超过20字节的数据必须实现分包发送。我的做法是定义一个简单的协议第一包发送数据总长度后续包带序号function sendLargeData(data) { const chunkSize 18 // 留2字节给包头 const total Math.ceil(data.length / chunkSize) // 发送数据头 const header new Uint8Array(2) header[0] total header[1] data.length this.write(header) // 发送数据体 for (let i 0; i total; i) { const chunk data.slice(i*chunkSize, (i1)*chunkSize) this.write(chunk) } }接收数据时经常会遇到分包情况。我们需要实现一个简单的数据组装器this.buffer { data: [], total: 0, add(packet) { if (packet.length 2 this.data.length 0) { this.total packet[0] return false } this.data.push(packet) return this.data.length this.total }, clear() { this.data [] this.total 0 } }5. 实战优化提升用户体验的关键细节开发蓝牙小程序时用户体验往往决定了产品的成败。这里分享几个经过实战检验的优化技巧。首先是连接状态管理。我建议使用一个集中式的状态管理器来维护蓝牙连接状态// 状态定义 const states { DISCONNECTED: 0, CONNECTING: 1, CONNECTED: 2, ERROR: 3 } // 状态转换逻辑 function handleStateChange(newState) { switch(newState) { case states.CONNECTING: showLoading(连接中...) disableConnectButton() break case states.CONNECTED: showSuccess(连接成功) enableDisconnectButton() break } }其次是错误处理的优化。不同平台返回的错误码可能不同需要统一处理function handleError(err) { let msg 操作失败 if (err.errCode 10000) msg 未初始化蓝牙适配器 else if (err.errCode 10001) msg 当前蓝牙适配器不可用 // ...其他错误码处理 wx.showToast({ title: msg, icon: none }) }对于需要用户等待的操作建议使用带取消按钮的加载提示this.loadingTimer setTimeout(() { wx.showLoading({ title: 正在搜索设备, mask: true }) }, 500) // 用户取消搜索 onCancelSearch() { clearTimeout(this.loadingTimer) wx.hideLoading() wx.stopBluetoothDevicesDiscovery() }最后是设备兼容性处理。不同厂商设备可能有不同的特性需要做好适配// iOS需要先停止搜索才能连接 if (wx.getSystemInfoSync().platform ios) { await wx.stopBluetoothDevicesDiscovery() } await wx.createBLEConnection({ deviceId })6. 调试技巧快速定位问题的实用方法蓝牙调试往往比普通开发更复杂掌握正确的调试方法可以事半功倍。这里分享几个我常用的调试技巧。首先是日志记录。建议建立一个完整的日志系统记录所有蓝牙操作function bluetoothLog(action, params, result) { const log { time: new Date().toISOString(), action, params, result } this.logs.push(log) // 开发环境直接打印 if (process.env.NODE_ENV development) { console.log([BLE], log) } }利用微信开发者工具的真机调试功能非常重要。在电脑上调试蓝牙往往会有各种限制真机调试可以看到更真实的运行情况。我习惯在代码中加入调试快捷键// 摇一摇触发调试菜单 wx.onAccelerometerChange(() { if (this.shakeCount 5) { this.showDebugMenu() } })特征值读写测试可以使用微信小程序BLE调试工具。这是一个官方提供的小程序可以查看设备的所有服务和特征值非常实用。对于复杂的通信问题我建议使用数据包嗅探工具。虽然微信环境限制较多但我们可以通过日志还原通信过程function logDataTransfer(direction, data) { console.log( [${direction}] ${data.byteLength} bytes, this.ab2hex(data) ) }最后保持耐心很重要。蓝牙问题往往需要反复测试才能找到规律。我习惯把遇到的所有问题和解决方案记录在一个Markdown文档中方便后续查阅。