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

使用react-native-ble-plx连接E7 Beacon至安卓平板时扫描异常咨询

问题解决:react-native-ble-plx扫描E7 Beacon UUID无效及RSSI距离计算优化

核心问题分析

  1. UUID扫描无效:react-native-ble-plx的startDeviceScan第一个参数传入的是BLE服务UUID,而E7 Beacon作为iBeacon设备,广播的是Proximity UUID(属于iBeacon广播帧的一部分),并非BLE服务UUID,因此直接传入该UUID无法匹配到设备。
  2. txPower错误:代码中txPower写死为0,而实际Beacon的txPower为40(需确认对应dBm值,通常E7的等级40对应+4dBm),这会导致距离计算完全失真。
  3. 不必要的连接:Beacon是广播设备,无需连接即可获取RSSI,连接操作反而可能干扰广播接收,且持续监听RSSI不需要建立BLE连接。

解决方案

1. 正确匹配E7 Beacon

扫描所有设备(传null),在回调中解析广播数据,过滤出iBeacon设备并匹配Proximity UUID:

  • iBeacon广播帧的特征是制造商数据(manufacturer data)的前两个字节为0x4C00(苹果公司的蓝牙厂商ID),后续数据包含Proximity UUID。

2. 修正txPower与距离计算

  • 使用Beacon实际的txPower dBm值(比如E7等级40对应+4dBm,可通过Beacon配置APP确认)。
  • 使用更准确的Free Space Path Loss公式计算距离。

3. 移除不必要的连接逻辑

直接通过扫描获取RSSI,无需建立BLE连接,减少资源消耗。

修改后的代码

import React, { useEffect, useRef, useState } from 'react';
import { PermissionsAndroid, Platform, Text, View } from 'react-native';
import { BleManager, Device, BleError } from 'react-native-ble-plx';

const BeaconDistanceTracker = () => {
    const [beaconDistance, setBeaconDistance] = useState<number | null>(null);
    const [detected, setDetected] = useState<boolean>(false);
    const manager = useRef(new BleManager()).current;

    // 目标E7 Beacon的Proximity UUID
    const TARGET_UUID = 'e2c56db5-dffb-48d2-b060-d0f5a71096e0';
    // E7 Beacon txPower等级40对应的实际dBm(需根据设备确认,示例为+4dBm)
    const BEACON_TX_POWER = 4;

    useEffect(() => {
        const requestPermissions = async () => {
            const fineLocationGranted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION);
            const coarseLocationGranted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION);

            if (Platform.OS === 'android' && Platform.Version >= 31) {
                await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN);
                await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT);
            }

            return fineLocationGranted === PermissionsAndroid.RESULTS.GRANTED &&
                   coarseLocationGranted === PermissionsAndroid.RESULTS.GRANTED;
        };

        // 解析iBeacon广播数据,提取Proximity UUID
        const parseIBeaconUUID = (manufacturerData: Uint8Array): string | null => {
            // iBeacon制造商数据格式:0x4C00 (苹果ID) + 0x02 (类型) + 0x15 (长度) + UUID(16字节) + ...
            if (manufacturerData.length < 25 || manufacturerData[0] !== 0x00 || manufacturerData[1] !== 0x4C) {
                return null;
            }
            if (manufacturerData[2] !== 0x02 || manufacturerData[3] !== 0x15) {
                return null;
            }
            // 提取UUID字节(第4到19字节)
            const uuidBytes = manufacturerData.slice(4, 20);
            // 转换为标准UUID格式
            const uuidParts = [
                uuidBytes.slice(0,4).reduce((acc, byte) => acc + byte.toString(16).padStart(2, '0'), ''),
                uuidBytes.slice(4,6).reduce((acc, byte) => acc + byte.toString(16).padStart(2, '0'), ''),
                uuidBytes.slice(6,8).reduce((acc, byte) => acc + byte.toString(16).padStart(2, '0'), ''),
                uuidBytes.slice(8,10).reduce((acc, byte) => acc + byte.toString(16).padStart(2, '0'), ''),
                uuidBytes.slice(10,16).reduce((acc, byte) => acc + byte.toString(16).padStart(2, '0'), '')
            ];
            return uuidParts.join('-').toLowerCase();
        };

        // RSSI转距离(Free Space Path Loss公式)
        const calculateDistance = (rssi: number, txPower: number): number => {
            if (rssi === 0) return -1;
            const ratio = rssi * 1.0 / txPower;
            if (ratio < 1.0) {
                return Math.pow(ratio, 10);
            } else {
                return (0.89976) * Math.pow(ratio, 7.7095) + 0.111;
            }
        };

        const handleDeviceScan = (error: BleError | null, device: Device | null) => {
            if (error) {
                console.error('扫描错误:', error);
                return;
            }
            if (!device) return;

            // 获取制造商数据,解析iBeacon
            const manufacturerData = device.manufacturerData;
            if (!manufacturerData) return;

            const beaconUUID = parseIBeaconUUID(manufacturerData);
            if (beaconUUID === TARGET_UUID.toLowerCase()) {
                setDetected(true);
                const rssi = device.rssi;
                if (rssi !== null) {
                    const distance = calculateDistance(rssi, BEACON_TX_POWER);
                    setBeaconDistance(distance);
                    console.log('RSSI:', rssi, '距离:', distance.toFixed(2), '米');
                }
            }
        };

        const startScanning = async () => {
            const hasPermissions = await requestPermissions();
            if (!hasPermissions) {
                console.error('权限不足,无法扫描蓝牙设备');
                return;
            }
            // 扫描所有设备,后续过滤iBeacon
            manager.startDeviceScan(null, null, handleDeviceScan);
        };

        startScanning();

        return () => {
            manager.stopDeviceScan();
        };
    }, [manager]);

    useEffect(() => {
        console.log('当前距离:', beaconDistance);
    }, [beaconDistance]);

    useEffect(() => {
        const subscription = manager.onStateChange((state) => {
            console.log('BLE管理器状态:', state);
        });
        return () => subscription.remove();
    }, []);

    return (
        <View style={{ padding: 20, backgroundColor: '#111' }}>
            <Text style={{ color: 'white', fontSize: 18, marginBottom: 10 }}>
                设备状态: {detected ? '已检测到E7 Beacon' : '未检测到Beacon'}
            </Text>
            <Text style={{ color: 'white', fontSize: 18 }}>
                与Beacon的距离: {beaconDistance !== null ? `${beaconDistance.toFixed(2)} 米` : '测量中...'}
            </Text>
        </View>
    );
};

export default BeaconDistanceTracker;

额外说明

  • txPower确认:如果不确定E7 Beacon等级40对应的dBm值,可通过Beacon配置APP查看,或者从iBeacon广播数据的第21字节读取(iBeacon格式中txPower为该字节的dBm值)。
  • 扫描优化:如果需要减少扫描范围,可在startDeviceScan的options中设置scanMode为ScanMode.LowLatency或ScanMode.Balanced,根据需求调整。

内容的提问来源于stack exchange,提问作者지민이

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 01:05:56