ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

微信小程序BLE开发踩坑记02|系统蓝牙可见却搜不到?

微信小程序BLE开发踩坑记02|系统蓝牙可见却搜不到?

背景

上一篇刚把"安卓搜不到设备"那事摆平,我还挺得意,以为扫描这块算是摸清了。结果一接血压计,又懵了:同一台手机、同一套扫描代码,血氧仪一搜就出来,血压计扫半天页面干干净净。

更邪门的是,这台血压计在手机自带的"蓝牙设置"里明明看得到,点配对也没问题。

先说结论

不是所有 BLE 设备都会在广播里带名字。我那台血压计的广播包里压根没有设备名字段,而我的扫描层写了一句"名字为空就丢弃"——于是它被我自己筛掉了。

一句话记住:扫描层的活儿是"上报设备","认不认得出目标"是识别层的事。

现象

  • 血氧仪:扫描页 1~2 秒就列出来了。
  • 血压计:页面毫无反应,等再久也不出来。
  • 手机系统蓝牙里:这台血压计可见、可配对。

两条信息又打架了。不过这回我没慌——上次刚学会"对照实验",直接套用。

排查

  1. 先看日志。把设备发现回调里的原始数据整条打出来(name、localName、advertisData全打)。可一开始什么都印不出来。

  2. 我反应过来:是我那句"丢弃"执行在打印之前,设备根本没机会出现在日志里。于是我把丢弃那行先注释掉、只留打印,才第一次看到这台设备的广播原貌——name: ""、localName: "",但advertisData里带着一串非空数据。

  3. 再用 BLE 调试 App(比如 nRF Connect 这类)连上它看原始广播,确认:它广播的只有 Flags、服务 UUID、制造商数据三块,没有设备名字段。回头翻协议文档"广播包格式"那节,也对上了——它就是设计成这样。

根因

BLE 扫描时,周围会扫到一堆没名字的杂散设备(邻居的耳机、手环、电视)。所以很多示例代码里都有一句"没名字的丢掉",我的扫描层也照抄了:

// 【踩坑写法】扫描层里,名字为空就丢弃if(!device.name&&!device.localName)return;// 血压计天生无名 → 直接被筛掉

"所有 BLE 设备都有广播名"这个前提本身就不成立。血氧仪的广播里带名字,所以一直正常;血压计天生无名,于是全灭。

代码一个字没改,变量是设备。

解决:扫描层只上报,识别交给上层

扫描层不再做任何"认设备"的判断,来者一律上报;是不是目标设备,交给设备识别模块综合判断(型号码 + 名字关键词 + 服务 UUID 一起看):

// 【修复】扫描层不做识别,无名设备也一律上报wx.onBluetoothDeviceFound(function(res){res.devices.forEach(function(device){// 不再按 name 是否为空丢弃,直接交给上层识别reportToDeviceManager(device);});});

顺带在扫描层开了一条广播 hex 诊断日志,无名设备从此有据可查:

// 把广播原始数据打成 hex(形如 "AA 4C 41 ..."),无名设备也能排查if(device.advertisData){console.log('[扫描] 无名设备广播:',hexDump(device.advertisData),device.deviceId);}

(hexDump就是把ArrayBuffer逐字节转成大写十六进制字符串,调 BLE 这活儿离不了它。)

改完把手机拿来再跑一遍,血压计和血氧仪都稳稳地出来了。

预防 / 复盘要点

  1. 对接新硬件前,先抓一遍它的原始广播包,拿工具看一眼,别用"别的设备都这样"去假设它。
  2. 扫描层负责"上报",识别层负责"过滤"。过滤逻辑要放在掌握完整判据(名字 / 型号码 / 服务 UUID)的那一层,扫描层越"单纯"越好。
  3. 出现"别的设备都正常,唯独这台不正常",先怀疑这台设备的广播格式特殊,而不是扫描代码有 bug。

常见问题

Q1:蓝牙设备在系统设置里能看到,小程序就是搜不到,一般是什么原因?

最常见两类:一是本文这种,设备广播里没有名字字段,被"无名即丢弃"的过滤逻辑筛掉了;二是安卓定位权限没给全,扫描根本起不来。区分方法很简单——把扫描回调的原始日志打开,看有没有这台设备的记录。有记录 = 被自己筛了;没记录 = 扫描压根没起来。

Q2:怎么知道我的设备广播里到底有没有名字?

用 BLE 调试 App 看一眼原始广播最快;没有的话,就在小程序里把advertisData打成 hex 打出来看。别猜,看一眼就有答案。

Q3:无名设备该怎么确认它是我要连的那台?

看广播里的其他东西——制造商数据、服务 UUID、广播内容的特征,都能当判据。我后面会专门写一篇"名字没有、型号也不对时,怎么认出设备"。

最后

扫描层和识别层这层"分工",我后来整理成了那套开源 BLE SDK 的一部分——设备发现一律上报,认不认得出来交给识别模块,接入方不用自己写过滤逻辑:

Gitee:https://gitee.com/wanrendi75/jingjin-ble-sdk

这个连载我才写到第二篇,踩的坑一个比一个刁钻,后面接着记。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进