用 ESP32 搭建 BLE proximity 研究环境,手把手教你复现
最近在捣鼓物联网相关的安全研究,手头刚好有几块吃灰的 ESP32 开发板,就想琢磨一下蓝牙低功耗(BLE)的相关功能。特别是所谓的 BLE Proximity(邻近度)监测,这个功能在智能家居、防丢器或者资产追踪里非常常见,但很多人不知道其实用几十块钱的开发板就能自己做一套研究环境。
今天就把前阵子整理环境时踩的坑和一些经验分享出来,顺便丢出一个我已经配置好、可以直接复现的代码仓库,希望能帮到同样对这块感兴趣的朋友。
什么是 BLE Proximity?
简单来说,BLE Proximity 就是利用蓝牙信号的强度(RSSI)来判断设备的大致距离。大部分支持蓝牙的设备都会周期性地广播信号,而 ESP32 可以扫描这些广播包,并根据信号的强弱来估算目标设备是“在身边”还是“远离了”。
ESP32 开发板,支持 Wi-Fi 和蓝牙双模,是实现 BLE Proximity 项目的理想硬件。
虽然这种方式测不到精确的厘米级距离,用来做个大概的“进门提醒”或者“防丢检测”是绰绰有余的,而且成本极低。
选 ESP32 的理由
为什么不用电脑自带的蓝牙或者更贵的专业工具?首先,ESP32 本身就集成了 2.4GHz Wi-Fi 和蓝牙双模,硬件支持非常完善。其次,它价格便宜,生态系统丰富,Arduino IDE、ESP-IDF 都能很好地开发。最重要的是,它功耗低,哪怕是电池供电也能跑很久,非常适合做便携式的探测设备。
实现思路与核心代码
整个工程的实现逻辑其实不复杂,主要分为两部分:
- 扫描者:也就是 ESP32,它负责持续扫描周围的 BLE 广播包。
- 目标:任何可以广播 BLE 信号的设备,比如手机、手环或 Beacon。
使用 Arduino IDE 的串口绘图器查看 RSSI 的实时波形变化。
我们在代码里主要做的就是设置 ESP32 进入 GAP 扫描模式,然后在回调函数里捕获广播事件,提取出 RSSI 值。为了模拟报警,我们可以设定一个阈值,比如 RSSI 大于 -60dBm(也就是信号很强)时判定为“接近”,小于 -90dBm 则判定为“远离”。
这里我把核心的配置逻辑整理了一下,大家可以直接参考下面的伪代码思路:
- 初始化蓝牙控制器。
- 开启扫描模式,设置扫描参数(窗口间隔等,这决定了灵敏度和功耗)。
- 注册一个回调函数,每当发现一个设备时,检查其 MAC 地址或 UUID 是否匹配目标。
- 如果匹配,就读取当前的 RSSI,并通过串口打印出来,或者点亮开发板上的 LED 灯作为视觉反馈。
常见问题与解决方案
在折腾的过程中,我遇到了几个比较典型的问题,这里顺便列一下解决方案:
1. 扫描不到设备?
- 检查目标设备是否开启了广播,有些手机为了省电,在屏幕熄灭后会停止广播或变更广播间隔。
- 在代码中增加扫描的持续时间,或者调整扫描窗口参数,使其能捕获到间隔较长的广播包。
2. RSSI 数值跳动太大?
- 这是无线信号的物理特性决定的,受环境影响很大(甚至有人经过都会干扰)。建议在软件层做一个简单的“滑动平均”滤波,取最近 5 次结果的平均值,这样判断的稳定性会大大提升。
3. 功耗过高?
- 如果你是用电池供电,全速扫描是非常耗电的。可以尝试“间歇性扫描”,比如扫描 1 秒,休眠 3 秒,或者利用 ESP32 的 Deep Sleep 模式,仅在定时唤醒时进行检测。
关于那个可复现仓库
为了避免大家重复造轮子,我把调试通过的工程文件整理到了一个开源仓库里。里面包含了:
- 基于 Arduino IDE 的完整工程代码。
- 详细的 README,包含接线说明和库的依赖版本。
- 一个简单的串口绘图输出示例,方便你在电脑上直接看到 RSSI 的波形变化。
你可以直接 Clone 下来,烧录进你的 ESP32,只要修改代码里的目标 MAC 地址就能跑通。
总结与展望
这个项目本质上是一个 BLE Sniffer(嗅探器)的简化版,门槛不高,但非常有趣。熟练掌握 Proximity 监测后,你还可以进一步研究 BLE Mesh 组网、或者尝试解析某些特定设备的广播数据(比如解密 Temperature Sensor 的温度数据)。
如果你对智能家居的自动化改造感兴趣,把这个探测逻辑接入 Home Assistant 之类的系统里,就能实现低成本的人体存在传感器了。感兴趣的朋友试过之后,欢迎在评论区交流你的玩法!
评论已关闭