React Native를 통해 bluetooth를 사용하고자 하는 경우, 가장 대표적으로 알려져 있는 2가지 라이브러리를 비교해보고 알아보고자 한다.
1.react-native-ble-plx
(이하 'plx')
react-native-ble-manager
(이하 'manager')
- classic Bluetooth 기술 이후 약 10여년 전에 저전력으로 동일한 기능을 수행할 수 있는 Bluetooth Low Energy(BLE) 기술이 등장
- BLE Communication 기술은 2가지 역할로 나뉨
1.Peripheral
Central
GATT 란?
GATT is an acronym for the Generic Attribute Profile, and it defines the way that two Bluetooth Low Energy devices transfer data back and forth using concepts called Services and Characteristics.
Profile
doesn’t actually exist on the BLE peripheral itself, it’s simple a pre-defined collection of Services that has been compiled by either the Bluetooth SIG or by the peripheral designers.
Services
are used to break data up into logic entities, and contain specific chunks of data called characteristics. A service can have one or more characteristics, and each service distinguishes itself from other services by means of a unique numeric ID called a UUID, which can be either 16-bit (for officially adopted BLE Services) or 128-bit (for custom services).
The lowest level concept in GATT transactions is the Characteristic
, which encapsulates a single data point (though it may contain an array of related data, such as X/Y/Z values from a 3-axis accelerometer, etc.).
npm install --save react-native-ble-plx
npm install --save react-native-base64
static #bleManager = new BleManager();
...
this.#bleManager.startDeviceScan(null, null, (error, device) => {
if (device.id === targetDeviceID) {
this.#bleManager.stopDeviceScan();
console.log('scan stopped');
device
.connect()
.then(connectedDevice => {
return connectedDevice.discoverAllServicesAndCharacteristics();
})
.then(preparedDevice => {
this.#preparedDeviceList[preparedDevice.id] = preparedDevice;
resolve();
})
}
monitorCharacteristicForService
함수)monitorCharacteristicForService
함수의 콜백함수 인자 내 characteristic.value를 변환한 값을 직접 정의 updateCallback(원하는 동작 포함) 함수 내의 인자로 계속적으로 전달하여, 실시간 업데이트 값을 표시 할 수 있음const subscription = await this.#preparedDeviceList[
deviceID
].monitorCharacteristicForService(
this.#serviceUUID,
this.#readCharacteristicUUID,
(error, characteristic) => {
const valueInBase64 = characteristic.value;
const valueInString = base64.decode(valueInBase64).trim();
updateCallback(valueInString);
},
);
npm install --save react-native-ble-manager
npm install --save convert-string
npm install --save buffer
(Android)
// file: android/app/src/main/AndroidManifest.xml
...
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
...
(iOS)
In iOS >= 13 you need to add the NSBluetoothAlwaysUsageDescription string key.
bleManagerEmitter.addListener('BleManagerDiscoverPeripheral',
handleDiscoverPeripheral);
bleManagerEmitter.addListener('BleManagerStopScan', handleStopScan);
bleManagerEmitter.addListener('BleManagerDisconnectPeripheral', handleDisconnectedPeripheral);
bleManagerEmitter.addListener('BleManagerDidUpdateValueForCharacteristic', handleUpdateValueForCharacteristic);
BleManager.scan()
으로 디바이스 스캐닝 프로세스 trigger
handleDiscoverPeripheral
함수 실행testPeripheral()
함수 실행useEffect(() => {
BleManager.start({showAlert: true});
bleManagerEmitter.addListener(
'BleManagerDiscoverPeripheral',
handleDiscoverPeripheral,
);
bleManagerEmitter.addListener('BleManagerStopScan', handleStopScan);
bleManagerEmitter.addListener(
'BleManagerDisconnectPeripheral',
handleDisconnectedPeripheral,
);
bleManagerEmitter.addListener(
'BleManagerDidUpdateValueForCharacteristic',
({value, peripheral, characteristic, service}) => {
const data = bytesToString(value).substring(3);
setLocation(data);
console.log(`Recieved ${data} for characteristic ${characteristic}`);
},
);
}, [])
- 두 가지 라이브러리 모두 공통적으로,
devicescan
-> deviceconnect
-> commnunication(write
,read
)의 3가지 단계로 나뉨- value의 실시간 업데이트 값을 가져오기 위해서, plx는 built-in 함수인
monitorCharacteristicForService
함수를 사용하였고, manager는 이벤트 리스너의 콜백함수를 이용하고 있는 차이가 있음- connect가 된 상태여야만 각 chracteristic에 serviceUUID 등이 부여되어 통신이 가능하고, connect 상태가 아니면 통신 불가 (직접 구현 과정에서 오류 많이 겪음)
- 통신 중 주고 받는 데이터는 일정 형식의 변환이 필요함 (plx에서 base64.decode()나 manager에서 buffer.from())
- 실질적인 동일 구성이지만, connect 전에는
device
, connected 되어 communication 가능한 상태는characteristic
이라 하는 것으 추측됨