基于ESP32 BLE客户端获取iBeacon的电量、RSSI及距离
获取iBeacon的电量水平(基于ESP32 BLE客户端)
核心前提
iBeacon的标准广播帧本身不包含电量数据,要获取电量必须依赖目标iBeacon设备额外提供GATT电池服务(Bluetooth SIG标准服务,UUID 0x180F)。首先确认你的目标iBeacon是否支持该服务——如果设备本身没有实现这个服务,就无法通过BLE获取电量。
实现步骤
你已经能扫描获取RSSI,接下来只需在扫描到目标iBeacon后,发起BLE连接并读取GATT电池特征:
- 扫描匹配到目标iBeacon(通过UUID、Major/Minor值)
- 与该iBeacon建立BLE连接
- 发现并访问GATT电池服务中的电量特征(UUID
0x2A19) - 读取特征值,得到0-100的电量百分比
ESP32代码示例(Arduino框架)
#include <BLEDevice.h> #include <BLEUtils.h> #include <BLEClient.h> #include <BLEScan.h> // 替换为你的目标iBeacon参数 #define TARGET_IBEACON_UUID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #define TARGET_MAJOR 1234 #define TARGET_MINOR 5678 #define APPLE_MANUF_ID "\x4C\x00" // 苹果iBeacon厂商ID BLEClient* pClient = nullptr; class BeaconScanCallbacks : public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advDevice) { // 过滤苹果iBeacon设备 if (advDevice.haveManufacturerData()) { std::string manufData = advDevice.getManufacturerData(); if (manufData.substr(0, 2) == APPLE_MANUF_ID && manufData.length() >= 25) { // 解析iBeacon UUID、Major、Minor std::string beaconUUID = manufData.substr(4, 16); uint16_t major = ((uint16_t)manufData[20] << 8) | manufData[21]; uint16_t minor = ((uint16_t)manufData[22] << 8) | manufData[23]; // 匹配目标iBeacon if (beaconUUID == TARGET_IBEACON_UUID && major == TARGET_MAJOR && minor == TARGET_MINOR) { Serial.print("目标iBeacon RSSI: "); Serial.println(advDevice.getRSSI()); // 停止扫描并发起连接 BLEDevice::getScan()->stop(); pClient = BLEDevice::createClient(); if (pClient->connect(&advDevice)) { Serial.println("连接iBeacon成功"); // 获取电池服务 BLERemoteService* batteryService = pClient->getService(BLEUUID((uint16_t)0x180F)); if (batteryService != nullptr) { // 获取电量特征 BLERemoteCharacteristic* batteryChar = batteryService->getCharacteristic(BLEUUID((uint16_t)0x2A19)); if (batteryChar != nullptr && batteryChar->canRead()) { uint8_t batteryPercent = batteryChar->readValue()[0]; Serial.print("电池电量: "); Serial.print(batteryPercent); Serial.println("%"); } else { Serial.println("无法读取电池特征"); } } else { Serial.println("iBeacon未提供标准电池服务"); } pClient->disconnect(); } else { Serial.println("连接iBeacon失败"); } // 重新启动扫描 BLEDevice::getScan()->start(5); } } } } }; void setup() { Serial.begin(115200); BLEDevice::init("ESP32_Beacon_Client"); BLEScan* pScan = BLEDevice::getScan(); pScan->setAdvertisedDeviceCallbacks(new BeaconScanCallbacks()); pScan->setActiveScan(true); // 主动扫描获取完整广播数据 pScan->start(0); // 持续扫描 } void loop() { delay(1000); }
补充说明
- 距离计算:用iBeacon的发射功率(TxPower,通常为-59dBm@1米)和RSSI估算,公式为:
distance = pow(10, (TxPower - RSSI) / (10 * n)),其中n是环境衰减因子(室内取2.5-3,室外取2)。 - 功耗优化:频繁连接iBeacon会增加ESP32功耗,建议设置扫描间隔,避免持续连接。
- 非标准服务:如果你的iBeacon用自定义UUID提供电量数据,需替换代码中对应的服务/特征UUID。
内容的提问来源于stack exchange,提问作者Ganesh Reddy
相关产品推荐
相关产品推荐

