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

如何在iOS应用中获取iBeacon的原始字节数据数组?

iOS获取iBeacon原始字节数据及电池电量方案

一、不修改iBeacon的排查与解决

  • 检查CoreBluetooth扫描配置
    先确保CoreBluetooth扫描权限和配置正确:

    let centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main)
    // 扫描所有外设并允许重复上报,避免漏扫
    centralManager.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
    

    同时确认Info.plist中添加了iOS 13+要求的蓝牙权限描述:NSBluetoothAlwaysUsageDescription。

  • 正确解析Manufacturer Data
    iBeacon的广播数据属于苹果厂商(ID: 0x004C)的Manufacturer Data,你可能之前没正确匹配解析。在扫描回调里提取完整原始字节:

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        guard let manufacturerData = advertisementData[CBAdvertisementDataManufacturerDataKey] as? Data else { return }
        // 验证厂商ID(小端序对应字节[0x4C, 0x00])
        guard manufacturerData.count >= 2, manufacturerData.subdata(in: 0..<2) == Data([0x4C, 0x00]) else { return }
        
        // manufacturerData就是完整的iBeacon原始字节数组
        let rawBytes = manufacturerData
        // 标准iBeacon数据占25字节,自定义电池电量应在这之后
        if rawBytes.count > 25 {
            let batteryLevel = rawBytes[25] // 按你的实际字节偏移调整
            print("电池电量:\(batteryLevel)%")
        }
    }
    

    如果还是拿不到Manufacturer Data,大概率是iBeacon的广播包长度超过BLE最大限制(31字节),或者设备广播配置有误。

  • CoreLocation的限制说明
    CoreLocation的CLBeacon对象只封装了标准iBeacon字段(UUID、Major、Minor、RSSI等),不会暴露原始广播数据,所以这条路走不通,只能依赖CoreBluetooth。

二、修改iBeacon的可靠方案

如果上面的方法无效,修改iBeacon的广播配置是最稳妥的选择,有两种常用方式:

  • 扩展iBeacon的Manufacturer Data
    标准iBeacon的Manufacturer Data固定为25字节:

    0-1字节:厂商ID(0x4C00)
    2字节:iBeacon类型(0x02)
    3字节:数据长度(0x15)
    4-19字节:UUID
    20-21字节:Major
    22-23字节:Minor
    24字节:校准RSSI
    你可以在第25字节之后添加1字节的电池电量数据(注意总长度不能超过31字节),这样CoreBluetooth扫描到的Manufacturer Data就会包含这部分,按上面的解析代码即可获取。

  • 同时广播iBeacon和自定义BLE服务
    让iBeacon同时作为BLE外设,广播一个自定义服务,并把电池电量存放在该服务的特征中。iOS端先通过CoreLocation定位到目标iBeacon,再用CoreBluetooth连接外设读取特征值:

    // CoreLocation扫描到目标iBeacon后触发连接
    func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {
        for beacon in beacons where beacon.proximityUUID == UUID(uuidString: "你的目标UUID") {
            centralManager.scanForPeripherals(withServices: [CBUUID(string: "自定义服务UUID")], options: nil)
        }
    }
    
    // 连接外设后读取电池电量特征
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        peripheral.delegate = self
        peripheral.discoverServices([CBUUID(string: "自定义服务UUID")])
    }
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        guard let service = peripheral.services?.first else { return }
        peripheral.discoverCharacteristics([CBUUID(string: "电池电量特征UUID")], for: service)
    }
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        guard let characteristic = service.characteristics?.first else { return }
        peripheral.readValue(for: characteristic)
    }
    
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        guard let data = characteristic.value, data.count > 0 else { return }
        let batteryLevel = data[0]
        print("电池电量:\(batteryLevel)%")
    }
    

内容的提问来源于stack exchange,提问作者Sunbey13

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 17:03:18