You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于ESP32 BLE客户端获取iBeacon的电量、RSSI及距离

获取iBeacon的电量水平(基于ESP32 BLE客户端)

核心前提

iBeacon的标准广播帧本身不包含电量数据,要获取电量必须依赖目标iBeacon设备额外提供GATT电池服务(Bluetooth SIG标准服务,UUID 0x180F)。首先确认你的目标iBeacon是否支持该服务——如果设备本身没有实现这个服务,就无法通过BLE获取电量。

实现步骤

你已经能扫描获取RSSI,接下来只需在扫描到目标iBeacon后,发起BLE连接并读取GATT电池特征:

  1. 扫描匹配到目标iBeacon(通过UUID、Major/Minor值)
  2. 与该iBeacon建立BLE连接
  3. 发现并访问GATT电池服务中的电量特征(UUID 0x2A19)
  4. 读取特征值,得到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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 04:09:27