如何解决ReactNative ble 管理器未从 IOS 上的外围设备读取数据
我正在为 IOS 和 Android 平台构建一个 ReactNative 应用程序。我的应用程序需要通过 BLE 通信从另一台设备读取数据。我正在使用这个包来实现 BLE 通信,https://github.com/innoveit/react-native-ble-manager。我在 IOS 上接收特征数据时遇到问题,即使它在 Android 平台上按预期工作。
Privacy - Bluetooth Always Usage Description: App needs to use Bluetooth to receive data from WaterRower machine
我有一个组件可以扫描并列出 BLE 设备,如下所示。它被称为,BleDeviceList.js
import React,{
useState,useEffect,} from 'react';
import {
SafeAreaView,StyleSheet,ScrollView,View,Text,StatusBar,NativeModules,NativeEventEmitter,Button,Platform,PermissionsAndroid,FlatList,TouchableHighlight,} from 'react-native';
import {
Colors,} from 'react-native/Libraries/NewAppScreen';
import BleManager from 'react-native-ble-manager';
const BleManagerModule = NativeModules.BleManager;
const bleManagerEmitter = new NativeEventEmitter(BleManagerModule);
const BleDeviceList = (props) => {
const [isScanning,setIsScanning] = useState(false);
const peripherals = new Map();
const [list,setList] = useState([]);
const [ connectedDevices,setConnectedDevices ] = useState([ ]);
const [ permissionsAllowed,setPermissionsAllowed ] = useState(false)
const startScan = () => {
if (!isScanning) {
BleManager.scan([],3,true).then((results) => {
console.log('Scanning...');
setIsScanning(true);
}).catch(err => {
console.error(err);
});
}
}
const handleStopScan = () => {
console.log('Scan is stopped');
setIsScanning(false);
}
const handledisconnectedPeripheral = (data) => {
let peripheral = peripherals.get(data.peripheral);
if (peripheral) {
peripheral.connected = false;
peripherals.set(peripheral.id,peripheral);
setList(Array.from(peripherals.values()));
}
console.log('disconnected from ' + data.peripheral);
}
const handleUpdateValueForCharacteristic = (data) => {
console.log('Received data from ' + data.peripheral + ' characteristic ' + data.characteristic,data.value);
}
const retrieveConnected = () => {
BleManager.getConnectedperipherals([]).then((results) => {
if (results.length == 0) {
console.log('No connected peripherals')
}
console.log(results);
for (var i = 0; i < results.length; i++) {
var peripheral = results[i];
peripheral.connected = true;
peripherals.set(peripheral.id,peripheral);
setList(Array.from(peripherals.values()));
}
});
}
const handlediscoverPeripheral = (peripheral) => {
console.log('Got ble peripheral',peripheral);
if (!peripheral.name) {
peripheral.name = 'NO NAME';
}
peripherals.set(peripheral.id,peripheral);
setList(Array.from(peripherals.values()));
}
const isConnected = (peripheral) => {
return connectedDevices.filter(cd => cd.id == peripheral.id).length > 0;
}
const toggleConnectPeripheral = (peripheral) => {
if (peripheral){
if (isConnected(peripheral)){
BleManager.disconnect(peripheral.id);
setConnectedDevices(connectedDevices.filter(cd => cd.id != peripheral.id))
}else{
BleManager.connect(peripheral.id).then(() => {
let tempConnnectedDevices = [ ...connectedDevices ]
tempConnnectedDevices.push(peripheral);
setConnectedDevices(tempConnnectedDevices);
props.navigation.push('BleRowingSession',{ peripheral: peripheral });
let p = peripherals.get(peripheral.id);
if (p) {
p.connected = true;
peripherals.set(peripheral.id,p);
setList(Array.from(peripherals.values()));
props.navigation.push('BleDeviceServiceList',{ peripheral: peripheral });
}
console.log('Connected to ' + peripheral.id);
}).catch((error) => {
console.log('Connection error',error);
});
}
}
}
useEffect(() => {
BleManager.start({showAlert: false});
bleManagerEmitter.addListener('BleManagerdiscoverPeripheral',handlediscoverPeripheral);
bleManagerEmitter.addListener('BleManagerStopScan',handleStopScan );
bleManagerEmitter.addListener('BleManagerdisconnectPeripheral',handledisconnectedPeripheral );
bleManagerEmitter.addListener('BleManagerDidUpdateValueForCharacteristic',handleUpdateValueForCharacteristic );
if (Platform.OS === 'android' && Platform.Version >= 23) {
PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION).then((result) => {
if (result) {
console.log("Permission is OK");
setPermissionsAllowed(true);
} else {
PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION).then((result) => {
if (result) {
console.log("User accept");
setPermissionsAllowed(true);
} else {
console.log("User refuse");
setPermissionsAllowed(false);
}
});
}
});
} else {
setPermissionsAllowed(true)
}
return (() => {
console.log('unmount');
bleManagerEmitter.removeListener('BleManagerdiscoverPeripheral',handlediscoverPeripheral);
bleManagerEmitter.removeListener('BleManagerStopScan',handleStopScan );
bleManagerEmitter.removeListener('BleManagerdisconnectPeripheral',handledisconnectedPeripheral );
bleManagerEmitter.removeListener('BleManagerDidUpdateValueForCharacteristic',handleUpdateValueForCharacteristic );
})
},[]);
const renderConnectButton = (item) => {
if (isConnected(item)) {
return null
}
return (
<Button
title="Connect"
onPress={() => {
toggleConnectPeripheral(item)
}}
/>
)
}
const renderdisconnectButton = (item) => {
if (! isConnected(item)) {
return null
}
return (
<Button
title="disconnect"
onPress={() => {
toggleConnectPeripheral(item)
}}
/>
)
}
const renderItem = (item) => {
const color = item.connected ? 'green' : '#fff';
return (
<TouchableHighlight>
<View style={[styles.row,{backgroundColor: color}]}>
<Text style={{fontSize: 12,textAlign: 'center',color: '#333333',padding: 10}}>{item.name}</Text>
<Text style={{fontSize: 10,padding: 2}}>RSSI: {item.RSSi}</Text>
<Text style={{fontSize: 8,padding: 2,paddingBottom: 20}}>{item.id}</Text>
{renderConnectButton(item)}
{renderdisconnectButton(item)}
</View>
</TouchableHighlight>
);
}
const renderContent = () => {
if (! permissionsAllowed) {
return <Text>Bluetooth and locations permissions are required.</Text>
}
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={styles.scrollView}>
{global.HermesInternal == null ? null : (
<View style={styles.engine}>
<Text style={styles.footer}>Engine: Hermes</Text>
</View>
)}
<View style={styles.body}>
<View style={{margin: 10}}>
<Button
title={'Scan Bluetooth (' + (isScanning ? 'on' : 'off') + ')'}
onPress={() => startScan() }
/>
</View>
<View style={{margin: 10}}>
<Button title="Retrieve connected peripherals" onPress={() => retrieveConnected() } />
</View>
{(list.length == 0) &&
<View style={{flex:1,margin: 20}}>
<Text style={{textAlign: 'center'}}>No peripherals</Text>
</View>
}
</View>
</ScrollView>
<FlatList
data={list}
renderItem={({ item }) => renderItem(item) }
keyExtractor={item => item.id}
/>
</SafeAreaView>
</>
)
}
return (
renderContent()
);
};
const styles = StyleSheet.create({
scrollView: {
backgroundColor: Colors.lighter,},engine: {
position: 'absolute',right: 0,body: {
backgroundColor: Colors.white,sectionContainer: {
marginTop: 32,paddingHorizontal: 24,sectionTitle: {
fontSize: 24,fontWeight: '600',color: Colors.black,sectionDescription: {
marginTop: 8,fontSize: 18,fontWeight: '400',color: Colors.dark,highlight: {
fontWeight: '700',footer: {
color: Colors.dark,fontSize: 12,padding: 4,paddingRight: 12,textAlign: 'right',});
export default BleDeviceList;
正如您在代码中看到的,当点击 Connect 按钮时,它会将用户重定向到另一个组件,该组件从另一个设备读取数据。下面是从另一个设备读取数据的 BleRowingSession.js。
import React,{ useEffect,useState } from 'react';
import { Text,ScrollView } from 'react-native';
import BleManager from 'react-native-ble-manager';
const BleManagerModule = NativeModules.BleManager;
const bleManagerEmitter = new NativeEventEmitter(BleManagerModule);
const serviceId = "00001826-0000-1000-8000-00805F9B34FB";
const characteristicId = "00002AD1-0000-1000-8000-00805F9B34FB";
let readDataCache = "";
const BleRowingSession = (props) => {
let peripheral = props.route.params.peripheral;
const [ readData,setReadData ] = useState("");
const setUpBleNotification = () => {
BleManager.retrieveServices(peripheral.id).then((peripheralData) => {
console.log('Retrieved peripheral services',peripheralData);
setTimeout(() => {
BleManager.startNotification(peripheral.id,serviceId,characteristicId).then(() => {
console.log('Started notification on ' + peripheral.id);
bleManagerEmitter.addListener('BleManagerDidUpdateValueForCharacteristic',(data) => {
readDataCache = readDataCache + "\n" + data.value.toString()
setReadData(readDataCache);
});
setTimeout(() => {
},500);
}).catch((error) => {
console.log('Notification error',error);
});
},500)
});
}
useEffect(() => {
setUpBleNotification()
},[ ])
return (
<View style={styles.container}>
<ScrollView>
<Text>Ble Rowing Session</Text>
<Text>{readData}</Text>
</ScrollView>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,justifyContent: "center",alignItems: "center"
}
})
export default BleRowingSession;
目前,服务 ID 和特征 ID 是硬编码的。当然,我必须在显示 BLE 设备列表的第一页上选择正确的设备。
当我运行代码时,它在 Android 设备上按预期工作,它正在接收特征值。当我在实际的 IOS 设备上运行代码时,它没有接收任何数据。但它可以扫描设备并连接到它们。我的代码有什么问题,我该如何解决?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。