ESP32 实战教程:制作一个 BLE 信标并实现手机近距离识别

BLE 信标的工作方式很“安静”:它不主动连接手机,也不传输一大段业务数据,只是周期性地广播“我是谁”和“我大概在哪”。手机扫描到后,可以根据 UUID、Major、Minor 识别区域,再用 RSSI 粗略估算距离。商场导览、仓库资产、展会签到和家庭房间识别,都可以从这个小项目开始。

ESP32 BLE 信标与手机扫描架构

一、广播和连接不是一回事

BLE 设备可以作为广播者,只发送 advertising packet;也可以作为 GATT 外设,等待手机连接读写特征。信标主要使用前一种模式,所以功耗低、容量小、手机无需配对。看到信标并不意味着已经建立安全连接,广播内容默认是任何附近扫描器都能看到的。

一个典型 iBeacon 数据里包含 Apple 厂商标识、16 字节 UUID、2 字节 Major、2 字节 Minor 和校准发射功率。UUID 通常代表一个项目或场地,Major 代表楼层/区域,Minor 代表某个具体设备。不要把真实姓名、手机号或门锁口令塞进广播包,31 字节很短,隐私风险却不会因此变小。

二、先决定信标的身份层级

BLE 信标部署前的校验流程

建议在项目表格中提前分配身份:

项目 UUID:代表“仓库 A”
Major 1:代表一楼
Minor 101:代表货架 101
Minor 102:代表货架 102

这样手机端只要判断 UUID 和 Major,就能先知道“这是哪个仓库的一楼”,再用 Minor 定位具体点位。身份一旦部署就不要随便改,否则后台会把同一只设备当成新设备,历史轨迹和维护记录都会断掉。

三、Arduino BLE 广播示例

Arduino-ESP32 自带 BLE 库可以创建服务器和广播器。不同版本的 BLE API 在 BLEAdvertisementData、厂商数据设置方式上可能有细节差异,建议以当前板卡包自带 BLE 广播示例为准。下面示例展示基本结构:

#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEAdvertising.h>

BLEAdvertising* advertising;

void startBeacon() {
  BLEDevice::init("esp32-beacon");
  advertising = BLEDevice::getAdvertising();

  BLEAdvertisementData data;
  // 实际项目中按目标协议构造厂商数据或 service data
  data.setName("warehouse-beacon");
  data.setManufacturerData("beacon-v1");
  advertising->setAdvertisementData(data);
  advertising->setMinInterval(160); // 约 100 ms 的量级,单位随 API 版本
  advertising->setMaxInterval(320);
  advertising->start();
}

void setup() {
  Serial.begin(115200);
  startBeacon();
}

void loop() {
  delay(1000);
}

上面 setManufacturerData() 的字符串只是为了说明接口位置,不等于完整的 iBeacon 帧。要与系统级 iBeacon 扫描器兼容,应按照目标协议写入正确的二进制字段,并核对厂商 ID、长度和字节序。协议字段一旦写错,手机可能仍然“看到一个 BLE 设备”,但不会把它识别成目标信标。

四、RSSI 为什么只能估算距离

RSSI 是接收信号强度,受距离、墙体、人体、天线方向、手机型号和 2.4 GHz 干扰共同影响。理想公式可以写成:

distance ≈ 10 ^ ((measuredPower - rssi) / (10 * n))

但环境系数 n 不是常量。办公室里同一间房可以测出 1 米、2 米、5 米三组样本,再拟合一个大概的分段阈值;不要把 RSSI 当成激光测距仪。它适合判断“近、中、远”或进入/离开区域,不适合精确到厘米。

校准时,手机要用实际部署的型号,信标要固定姿态。把信标塞进金属配电箱后再测,会发现昨天的公式突然像失忆了一样,这是天线环境改变的结果,不是数学课本的问题。

五、功耗和广播间隔

广播间隔越短,手机越容易快速发现,功耗也越高;间隔越长,电池续航更好,但进入区域后的发现延迟会增加。仓库资产可以用 500 ms 到 1 s 的量级,门口触发器希望快速识别时可以更短。最终参数应根据“允许的发现延迟”和“电池容量”一起决定。

发射功率也不是越大越好。功率太高会导致多个房间的信标覆盖互相重叠,RSSI 阈值更难分辨;功率太低则容易漏检。先用中等功率铺一圈现场数据,再调整,比一上来开到最大更可控。

六、用手机扫描验证

开发阶段可以用通用 BLE Scanner 查看设备名称、服务 UUID、厂商数据和 RSSI。测试清单至少包括:

  • 冷启动后是否自动开始广播;
  • 手机进入范围后,平均需要多久发现;
  • 离开范围后,后台多久认为设备消失;
  • 多个信标同时存在时,UUID/Major/Minor 是否能区分;
  • 设备断电、重启后身份是否保持不变。

不要只用一部手机在桌面上测试。手机扫描系统会缓存结果,某些 App 还会过滤后台广播。至少换一部手机、换一个方向、换一处墙体,观察结果是否依然符合预期。

七、安全和隐私边界

广播包没有加密,任何人都能复制它。若信标只是“房间标签”,复制不会造成严重后果;若它用于门禁、支付或人员考勤,就不能只依赖 UUID 和 RSSI。更安全的方案是让手机扫描到信标后,再通过 HTTPS 向服务器完成真正的身份认证,信标只负责提供非敏感线索。

ESP32 的 MAC 地址、UUID 和部署位置也应当视为资产信息。公共场所的信标不要在名称里写出员工姓名或内部系统地址。做测试时可以用随机 UUID,发布时再换成项目分配的正式编号。

八、让广播内容动态变化

有些项目需要广播电池电量、温度或设备状态。可以定时停止广播、更新 service data、再重新开始,但要控制更新频率,避免手机端缓存和功耗抖动。更稳妥的方式是固定身份广播,业务数据通过连接后的 GATT 特征读取;两者职责清楚,后台也更容易处理。

如果设备进入深睡,广播会停止,唤醒后需要重新初始化 BLE 控制器并开始广播。电池项目可以根据运动传感器或定时器决定何时广播,不要让“低功耗信标”在没有需求时一直全功率工作。

九、总结

BLE 信标的难点不在于让手机看到一个名字,而在于把身份规划、广播协议、现场 RSSI、功耗和安全边界一起设计好。ESP32 适合做原型,因为 UUID 和广播内容都能快速修改;正式部署前则要固定编号规则、测量覆盖、记录电池曲线,并在手机端处理缓存和权限。

这个项目往后可以扩展成仓库盘点、展会导航、房间自动化、宠物活动区域提醒,甚至把 BLE 广播和前面写过的温湿度传感器结合起来,做“能被路过设备发现的环境节点”。

部署多只信标时,还要考虑同频干扰和维护效率。不要把所有设备设置成相同的广播相位,否则它们可能周期性地同时发包,扫描结果会出现短暂拥挤。可以给不同区域分配稍有差异的广播间隔,并在安装表中记录电池更换日期、固件版本、最后一次现场 RSSI。

手机端也不能只写收到信号就触发。应当加入进入和离开区域的迟滞,例如连续三次读到近距离才算进入,连续十次都变远才算离开。这样可以减少人体遮挡、手机放进口袋和电梯金属壁造成的状态来回跳变。

参考资料

打赏

如果这篇学习记录对你有帮助,欢迎扫码支持后续整理。

打赏码

打赏支持:王庆岩

posted on 2026-09-30 10:18  潇洒石头  阅读(22)  评论(0)    收藏  举报

导航