React Native蓝牙
采用:innoveit/react-native-ble-manager: React Native BLE 通信模块 (opens new window)组件,该组件只适用于BLE蓝牙通信,不适用于经典蓝牙通信
参考:React Native BLE蓝牙通信_react-native-ble-manager (opens new window)
# 流程
- 初始化
- 搜索
- 连接
- 获取Service和Characteristic
- 通知监听
- 写数据
- 解析蓝牙指令
# 初始化
start() {
BleManager.start({ showAlert: false })
.then(() => {
// 初始化成功后检查蓝牙状态
this.checkState();
console.log("初始化成功");
})
.catch(error => {
console.log("初始化失败", error);
});
}
checkState() {
BleManager.checkState();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
相应的监听器
// 蓝牙状态改变监听
bleManagerEmitter.addListener("BleManagerDidUpdateState", (args) => {
// The new state: args.state
});
2
3
4
# 搜索
// 扫描可用设备,5秒后结束
scan(): Promise<void> {
return new Promise((resolve, reject) => {
BleManager.scan([], 5, true)
.then(() => {
console.log("扫描成功");
resolve();
})
.catch(error => {
console.log("扫描失败", error);
reject(error);
});
});
}
// 停止扫描
BleManager.stopScan().then(() => {
// Success code
console.log("Scan stopped");
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
相应的监听器
// 搜索到一个新设备监听
bleManagerEmitter.addListener("BleManagerDiscoverPeripheral", (args) => {
// The id: args.id
// The name: args.name
});
// 搜索结束监听
bleManagerEmitter.addListener("BleManagerStopScan", (args) => {
// Scanning is stopped
});
2
3
4
5
6
7
8
9
10
# 连接
android使用Mac地址与蓝牙连接,ios使用UUID与蓝牙连接。
// 连接蓝牙
connect(id: string): Promise<PeripheralInfo> {
return new Promise((resolve, reject) => {
BleManager.connect(id)
.then(() => {
console.log("蓝牙连接成功");
// 获取已连接蓝牙设备的服务和特征
return BleManager.retrieveServices(id);
})
.then(peripheralInfo => {
console.log("蓝牙连接成功 设备信息:", JSON.stringify(peripheralInfo));
this.peripheralId = peripheralInfo.id;
this.getUUID(peripheralInfo);
this.setMtu();
this.stopNotification();
this.startNotification();
resolve(peripheralInfo);
})
.catch(error => {
console.log("蓝牙连接失败", error);
reject(error);
});
});
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
相应的监听器
// 蓝牙设备已连接监听
bleManagerEmitter.addListener('BleManagerConnectPeripheral', (args) => {
console.log('BleManagerConnectPeripheral:', args);
//
});
// 返回来的数据
args {"peripheral": "xxxxxxxxxxxxxxx", "status": 0}
2
3
4
5
6
7
# 设置MTU
setMtu() {
setTimeout(() => {
BleManager.requestMTU(this.peripheralId, 247)
.then((mtu) => {
// Success code
console.log("MTU size changed to " + mtu + " bytes");
})
.catch((error) => {
// Failure code
console.log(error);
});
}, 1000);
}
2
3
4
5
6
7
8
9
10
11
12
13
# 获取Service和Characteristic
BLE分为三部分Service(服务)、Characteristic(特征)、Descriptor(描述符)
包含多个Service,一个Service可以包含多个Characteristic,一个Characteristic包含一个Value和多个Descriptor,一个Descriptor包含一个Value。
Characteristic是手机与BLE终端交换数据的关键,Characteristic有跟权限相关的字段
需要调用retrieveServices
方法获取Notify
、Read
、Write
的serviceUUID
和characteristicUUID
作为参数来跟蓝牙进一步通信
// 获取蓝牙Service和Characteristics
BleManager.retrieveServices(peripheralId)
.then((peripheralInfo) => {
console.log('Peripheral info:', peripheralInfo);
});
2
3
4
5
6
蓝牙连接后会显示该设备的具体信息,android平台下连接成功后返回的数据如下:
{
"characteristics": [
{
"properties": {"Read": "Read"},
"characteristic": "xxxx",
"service": "xxxx"
},
{
"properties": {"Read": "Read"},
"characteristic": "xxxx",
"service": "xxxx"
},
{
"properties": {"Read": "Read"},
"characteristic":"xxxx",
"service":"xxxx"
},
{
"descriptors":[{"value":null,"uuid":"xxxx"}],
"properties":{"Indicate":"Indicate"},
"characteristic":"xxxx","service":"xxxx"
},
{
"descriptors":[{"value":null,"uuid":"xxxx"}],
"properties":{"Notify":"Notify"},
"characteristic":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"service":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
},
{
"properties":{"Write":"Write","WriteWithoutResponse":"WriteWithoutResponse"},
"characteristic":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"service":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
},
{
"descriptors":[{"value":null,"uuid":"2902"}],
"properties":{"Notify":"Notify","Write":"Write"},
"characteristic":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"service": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
],
"services": [
{"uuid": "xxxx"},
{"uuid": "xxxx"},
{"uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}
],
"advertising": {
"serviceUUIDs": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"],
"txPowerLevel":-2147483648,
"isConnectable":true,
"serviceData":{},
"localName":"t2",
"manufacturerData":{
"bytes":[x,x,x,x,x,x,x·····x,x,x],
"data": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"CDVType": "ArrayBuffer"
}
},
"name": "t2",
"rssi": -51,
"id": "xxxxxxxxxxxxx"
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
ios平台下连接成功后返回的数据如下:
{
"characteristics": [
{
"service": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"characteristic": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"properties": {
"Notify": "Notify"
},
"isNotifying": false,
"descriptors": [
{
"uuid": "xxxx"
}
]
},
{
"service": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"characteristic": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"isNotifying": false,
"properties": {
"Write": "Write",
"WriteWithoutResponse": "WriteWithoutResponse"
}
},
{
"service": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"characteristic": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"properties": {
"Write": "Write",
"Notify": "Notify"
},
"isNotifying": false,
"descriptors": [
{
"uuid": "2902"
}
]
}
],
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"advertising": {
"serviceUUIDs": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"],
"manufacturerData": {
"CDVType": "ArrayBuffer",
"data": "9wQCAw==",
"bytes": [247,4,2,3]
},
"kCBAdvDataRxSecondaryPHY": 0,
"kCBAdvDataRxPrimaryPHY": 129,
"isConnectable": 1,
"localName": "t2",
"kCBAdvDataTimestamp": 715684811.602319
},
"name": "t2",
"rssi": -57,
"services": [{"uuid": "a6ed0201-d344-460a-8075-b9e8ec90d71b"}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
笔记
找到需要的信息
202 通知
203 写入
# 通知监听
蓝牙连接成功,当我们向设备写入数据成功并且指令也正确的话,我们就会得到设备通过蓝牙发送给APP的响应数据,实现这一响应的前提是需要开启通知监听,这样就能在回调中监听到数据返回了。
// 打开通知
BleManager.startNotification(peripheralId, nofityServiceUUID, nofityCharacteristicUUID)
.then(() => {
console.log('Notification started');
})
.catch((error) => {
console.log('Notification error:',error);
});
// 关闭通知
BleManager.stopNotification(peripheralId, nofityServiceUUID, nofityCharacteristicUUID)
.then(() => {
console.log('stopNotification success!');
})
.catch((error) => {
console.log('stopNotification error:',error);
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
相应的监听器
bleManagerEmitter.addListener("BleManagerDidUpdateValueForCharacteristic",({ value, peripheral, characteristic, service }) => {
// 接收的新数据
// 解析蓝牙命令
}
);
2
3
4
5
# 写数据
写数据有两个方法,分别为 write:Write with response to the specified characteristic writeWithoutResponse:Write without response to the specified characteristic
// 此处是传入十六进制字符串,后续要改成直接传字节数组,
write(data: any): Promise<void> {
// 将一个十六进制字符串转换为一个 Uint8Array 类型的二进制数据(字节数组)
const buffer = toBuffer(data);
return new Promise((resolve, reject) => {
BleManager.write(
this.peripheralId,
this.writeServiceUUID,
this.writeCharacteristicUUID,
buffer
)
.then(() => {
console.log("Write success", buffer.map((num) => num.toString(16)));
resolve();
})
.catch(error => {
console.log("Write failed", buffer);
reject(error);
});
});
}
BleManager.writeWithoutResponse(peripheralId,serviceUUID,characteristicUUID,data)
.then(() => {
// Success code
console.log("Writed: " + data);
})
.catch((error) => {
// Failure code
console.log(error);
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31