如何使用react原生BLE管理器在移动应用中整合BLE技术。了解如何使用中心和外围设备进行基本操作。
所需的库和设备信息
我们使用 react native ble manager 库,将react-native移动应用与BLE技术整合在一起。我使用Mansa智能灯泡创建了一个演示应用程序并进行了操作。我使用 react原生颜色选择器 库来显示一个颜色选择器。
你如何实现它?
1.到你的项目中,运行以下命令来安装库
yarn add react-native-ble-manager react-native-color-picker
2.对于iOS,使用下面的命令安装pods。
cd ios && pod install OR cd ios &&
3.在Android平台上,你需要 按照给定的格式更新 AndroidManifest.xml 文件。了解更多关于(Android-Configuration)
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="YOUR_PACKAGE_NAME">
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28"/>
<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" tools:targetApi="Q"/>
<!-- Only when targeting Android 12 or higher -->
<!-- Please make sure you read the following documentation to have a
better understanding of the new permissions.
https://developer.android.com/guide/topics/connectivity/bluetooth/permissions#assert-never-for-location
-->
<!-- If your app doesn't use Bluetooth scan results to derive physical location information,
you can strongly assert that your app
doesn't derive physical location. -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"
android:usesPermissionFlags="neverForLocation"
tools:targetApi="s" />
<!-- Needed only if your app looks for Bluetooth devices. -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<!-- Needed only if your app makes the device discoverable to Bluetooth devices. -->
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
4.对于iOS,你需要在info.plist文件中添加NSBluetoothAlwaysUsageDescription字符串键。
5.首先,在执行任何种类的操作或行动之前,我们必须初始化BLE模块。
useEffect(() => {
BleManager.start({ showAlert: false, forceLegacy: true });
}, []);
6.在初始化BLE模块后,你需要检查蓝牙许可。如果该许可不可用,你需要申请并获得它。
const checkForBluetoothPermission = () => {
if (Platform.OS === 'android' && Platform.Version >= 23) {
let finalPermission = Platform.Version >= 29
? PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
: PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION;
PermissionsAndroid.check(finalPermission).then((result) => {
if (result) {
enableBluetoothInDevice()
} else {
PermissionsAndroid.request(finalPermission).then((result) => {
if (result) {
enableBluetoothInDevice()
} else {
console.log("User refuse");
}
});
}
});
}
else {
console.log("IOS");
enableBluetoothInDevice()
}
}
7.如果有许可,在开始扫描附近的BLE外围设备之前,您应该启用蓝牙。
const enableBluetoothInDevice = () => {
BleManager.enableBluetooth()
.then(() => {
setBluetoothtoggle(true)
startScan()
})
.catch((error) => {
console.log("Error--->", error);
});
}
const startScan = () => {
if (!isScanning) {
BleManager.scan([], 10, true).then((results) => {
console.log('Scanning...');
setIsScanning(true);
}).catch(err => {
console.error(err);
});
}
}
8.扫描后,您可以得到附近可用的BLE外围设备的列表。你可以根据需要使用FlatList来显示列表中的元素。为了这个演示的目的,我创建了以下屏幕。
9.现在我们可以连接到列表中的任何外围设备,并执行不同种类的操作。所以首先我们需要检查外围设备是否与我们的应用程序(中央设备)连接。如果一个设备没有连接,那么我们需要连接,然后我们就可以继续了。
const connectBLEDevice = (item, index) => {
toggleConnecting(true, index)
BleManager.isPeripheralConnected(item.id, []).then((res) => {
if (res == false) {
BleManager.connect(item.id)
.then((res7) => {
redirectUserToNext(item, index)
}).catch((error) => {
console.log("Error---BLE connect--->", error);
toggleConnecting(false, index)
ToastAndroid.show("Something went wrong while connecting..", ToastAndroid.SHORT)
})
}
else {
redirectUserToNext(item, index)
}
}).catch((error) => {
toggleConnecting(false, index)
ToastAndroid.show("Something went wrong while connecting..", ToastAndroid.SHORT)
})
}
10.你也可以给你的生命周期方法添加一个监听器,以检测外围设备,停止扫描,并在更新发生时为你的BLE设备获得一个分数。事件的名称是分配给所使用的库的。
useEffect(() => {
BleManager.start({ showAlert: false, forceLegacy: true });
const ble1 = bleManagerEmitter.addListener('BleManagerDiscoverPeripheral', handleDiscoverPeripheral);
const ble2 = bleManagerEmitter.addListener('BleManagerStopScan', handleStopScan);
const ble3 = bleManagerEmitter.addListener('BleManagerDisconnectPeripheral', handleDisconnectedPeripheral);
const ble4 = bleManagerEmitter.addListener('BleManagerDidUpdateValueForCharacteristic', handleUpdateValueForCharacteristic);
checkForBluetoothPermission()
return (() => {
ble1.remove()
ble2.remove()
ble3.remove()
ble4.remove()
})
}, []);
11.你现在可以使用BLE设备实现读和写了。描述了读和写的操作。首先,你需要获得 执行读写操作所需的 所有服务和 特性 。如果所需的服务和 特性 不可用,您将无法在BLE设备上执行操作。
12.现在您应该看到您的BLE设备上的可用服务列表。在这里,你需要为外围设备传递一个唯一的ID。Blemanager库有一个叫做retriveServices的方法。
const getAllServiceForBLEDevice = () => {
let item = route.params && route.params.peripheral ? route.params.peripheral : null
var tempdata = [];
BleManager.retrieveServices(item.id).then((res1) => {
console.log("Res1===>", res1);
}).catch((err) => {console.log("err-->", err);})
}
13.在获取服务后,你可以执行所需的逻辑。而在这里,我们检查所需的服务和 特性是否 在指定的列表中可用。这里我们定义了使用Smart Bulb执行写操作所需的服务UUID和属性UUID。为了做到这一点,它检测它是否可用。你需要获得执行操作的硬件所需的所有信息和参数。
const serviceUUIDForWriteBlubColor = "ffb0"
const characteristicUUIDForWriteBlubColor = "ffb2"
const getAllServiceForBLEDevice = () => {
let item = route.params && route.params.peripheral ? route.params.peripheral : null
var tempdata = [];
BleManager.retrieveServices(item.id).then((res1) => {
console.log("Res1===>", res1);
let data = res1.characteristics;
var seen = {};
tempdata = data.filter(function (entry) {
var previous;
if (seen.hasOwnProperty(entry.service)) {
previous = seen[entry.service];
previous.characteristicList.push({
characteristic: entry.characteristic,
properties: entry.properties,
});
return false;
}
if (!Array.isArray(entry.characteristicList)) {
entry.characteristicList = [{
characteristic: entry.characteristic,
properties: entry.properties,
}];
}
seen[entry.service] = entry;
delete entry.characteristic;
delete entry.properties;
delete entry.descriptors;
return true;
});
console.log("tempdata-0----->", tempdata);
setServiceAndCharList(tempdata)
let isListContainBlubChangeColorService = tempdata.filter((obj) => obj.service == serviceUUIDForWriteBlubColor);
console.log("isListContainBlubChangeColorService---->", isListContainBlubChangeColorService);
if (isListContainBlubChangeColorService.length > 0) {
let isListContainBlubChangeColorChar = isListContainBlubChangeColorService[0].characteristicList.filter((obj) => obj.characteristic == characteristicUUIDForWriteBlubColor);
console.log("isListContainBlubChangeColorChar---->", isListContainBlubChangeColorChar);
if (isListContainBlubChangeColorChar.length) {
setAvaibility(true)
}
else {
setAvaibility(false)
}
}
else {
setAvaibility(false)
}
}).catch((err) => {
console.log("err-->", err);
})
}
14.现在我们需要用写操作来改变灯泡的颜色。 在这里,我创建了以下屏幕。 在这里面,我使用了一个颜色选择器来选择颜色来改变灯泡的颜色。我还添加了一些主要颜色的色调来改变灯泡的颜色。
15.现在,当我们挑选颜色时,首先我们需要检查我们需要的服务和特性是否可用,然后我们可以继续,否则就不行。当我们从选色器或预定义的颜色阴影中挑选颜色时,它将是HEX格式的。 因此,需要将其转换为RGB格式。
export function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
const fullBrightNessHexValue = 49; // 1
const zeroBrightNessHexValue = 48; // 0
const onColorPicked = (color) => {
if (isServiceAndCharAvailable) {
let item = route.params && route.params.peripheral ? route.params.peripheral : null
let hexToRgbValue = hexToRgb(color)
let { r, g, b } = hexToRgbValue
let tempObj = {
id: item.id,
name: item.name,
service: serviceUUIDForWriteBlubColor,
characteristic: characteristicUUIDForWriteBlubColor,
writeValueData: [fullBrightNessHexValue, r, g, b]
}
setLastColor(color)
readAndWriteData(tempObj)
}
else {
ToastAndroid.show("Bulb change color service is not available.", ToastAndroid.SHORT)
}
}
16.我创建了一个obj来传递执行写操作。你需要传递一个长度为4的字节数组(writeValueData)。这第一个元素需要你传递十六进制代码的亮度值,其他三个参数是R、G、B的。
17.然后再次检查BLE外围设备是否与应用程序连接。如果连接了,就可以继续,如果没有连接,就不能继续。
const readAndWriteData = (peripheral, isRead, isToggleBlub) => {
BleManager.isPeripheralConnected(peripheral.id, []).then((res) => {
if (res == false) {
BleManager.connect(peripheral.id)
.then((res7) => {
if (isRead) readCharData(peripheral)
else writeCharData(peripheral, isToggleBlub)
})
.catch((error) => { console.log("error---456464454->", error); });
}
else {
if (isRead) readCharData(peripheral)
else writeCharData(peripheral, isToggleBlub)
}
}).catch((error) => { console.log("Error--->", error) })
}
18.接下来,让我们使用BleManager库的写入方法进行最后的写入。要写,你必须传递一个唯一的外设ID、服务UDID、属性UDID和字节数组。(我已经有了这个项目)。
const writeCharData = (peripheral, isToggleBlub) => {
try {
BleManager.write(peripheral.id,
peripheral.service,
peripheral.characteristic,
peripheral.writeValueData
).then((response) => {
if (isToggleBlub == "1") {
ToastAndroid.show("Blub is now Turned On", ToastAndroid.SHORT)
}
else if (isToggleBlub == "2") {
ToastAndroid.show("Blub is now Turned Off", ToastAndroid.SHORT)
}
else {
}
}).catch(error => {
console.log("Error--->", error);
ToastAndroid.show(JSON.stringify(error), ToastAndroid.SHORT)
})
} catch (error) {
console.log("Error---123123123-<", error);
}
}
19.如果一切正常,写完后灯泡会变色。然后进行读操作。要做到这一点,使用BleManager的读取方法来获得灯泡的名称。为了得到智能灯泡的名称,你需要传递外围设备的唯一ID、serviceUDID和特性UDID。为了从读取方法中获得字节数组中的响应,我们首先需要将其转换为人类可读的格式。然后就可以查看转换后得到的名称。
const serviceUUIDForWriteBlubColor = "ffb0"
const characteristicUUIDForWriteBlubColor = "ffb2"
const characteristicUUIDForChangeBlubName = "ffb7"
BleManager.read(item.id, serviceUUIDForWriteBlubColor, characteristicUUIDForChangeBlubName).then((characteristic) => {
const bytesString = String.fromCharCode(...characteristic)
setBlubName(bytesString)
}).catch((error) => {
console.log("Error--write name->", error);
})
20.现在,让我们用一张图来看看整个场景,这是各种技术学科的正常流程。这也是所有开发者的共同流程。
- 有两种类型的设备,中心设备和外围设备。
- 当你打开外围设备时,广告就会开始。
- 当应用程序在中央设备上打开时,它首先检查权限,询问是否可用。然后,在获得许可后,开始扫描几秒钟。
- 中央设备现在将搜索广告包,并找到附近可用的BLE外围设备列表。
- 现在,为了在外围设备上执行BLE操作,你需要检查所选外围设备是否连接到应用程序。如果没有连接,你需要先进行连接。
- 一旦建立了连接,就需要获得所有的资源,在此基础上,需要获得扫盲过程所需的服务。
- 如果有服务,你需要查看与该服务相关的所有特性,在此基础上,找到读写所需的特性。
- 如果没有性能或功能,你应该相应地处理这个错误。
- 一旦你找到了该特性,你就可以进行读、写和通知操作。
总结
这篇文章对那些想学习使用react原生BLE管理器将BLE技术集成到移动应用中的开发者来说可能很有用。首先,你需要BLE硬件或BLE模拟器应用来执行操作。然而,最重要的还是,我们需要BLE的硬件相关信息,因为我们需要一些初步信息来执行BLE操作。B. 服务和特征UDID,这是一种用于书写的数据格式。因此,通过BLE技术,你可以使用React native来创建有趣的应用程序。最后的流程图提供了对BLE特性的基本理解。