Flutter(플러터)/Bluetooth

Flutter 블루투스 - flutter_ble_lib

병홍 2021. 12. 27. 13:34

https://pub.dev/packages/flutter_ble_lib

 

flutter_ble_lib | Flutter Package

FlutterBle Library is a flutter library that supports BLE operations. It uses MultiPlatformBleAdapter as a native backend..

pub.dev


제가 개발하는 IoT 앱의 주요 기능 중에 하나가 블루투스 입니다.

블루투스 관련 개발은 안드로이드, iOS도 프레임워크 동작이 다르고, 실제 결과도 조금씩 달라서 굉장히 까다롭습니다. 
각 OS별로 안정되게 구현된 블루투스 관련 로직을 플러터로 구현하면서 생각보다 꽤 많이 고생했습니다.
제가 설치해보고 테스트해본 라이브러리는 다음과 같습니다. 

1. flutter_reactive_ble 5.0.2
2. flutter_ble_lib 2.3.2
3. flutter_blue 0.8.0

모두 장단점이 확실히 있습니다. 개발하시는 분의 스타일에 따라 가면 될 것 같습니다. 
블루투스 모듈은 크게 검색, 연결, 데이터 쓰기, 데이터 읽기, 연결 종료 로 이루어 집니다. 
위의 내용은 순차적으로 이루어지며, 순차적으로 잘 이루어 졌을 때는 모든 라이브러리가 큰 문제가 없었습니다. 

하지만 제가 개발하는 앱은 검색, 재검색, 상시 연결 종료 등의 복잡한 기능을 가져서 
결과적으로 유명한(LIKES, POPULARITY가 높은) 블루투스 라이브러리들로 만족할 수 없었습니다. 

위 라이브러리들은 안드로이드에서는 모두 정상적으로 동작되나, iOS에서는 문제가 있었습니다.
flutter_ble_lib 경우는 
"스캔 후 재스캔 시에  이전에 연결했던 기기가 목록에서 사라져 버립니다."
이런 저런 방법을 찾아보고 했는데 해답을 찾지 못하고, 이 방식은 포기했습니다.

아래는 flutter_ble_lib를 사용 방법입니다. (데이터 읽기 방법이 추가되어 있습니다)

설치 방법

dependencies:
  flutter_ble_lib: ^2.3.2

 

초기화/사용 종료 

BleManager bleManager = BleManager();
await bleManager.createClient(); //ready to go!
// your peripheral logic
bleManager.destroyClient();

 

블루투스 설정 및 상태 정보 받기 

enum BluetoothState {
  UNKNOWN,
  UNSUPPORTED,
  UNAUTHORIZED,
  POWERED_ON,
  POWERED_OFF,
  RESETTING,
}


bleManager.enableRadio(); //ANDROID-ONLY turns on BT. NOTE: doesn't check permissions
bleManager.disableRadio() //ANDROID-ONLY turns off BT. NOTE: doesn't check permissions
BluetoothState currentState = await bleManager.bluetoothState();
bleManager.observeBluetoothState().listen((btState) {
  print(btState);
  //do your BT logic, open different screen, etc.
});

스캔(검색)

bleManager.startPeripheralScan(
  uuids: [
    "F000AA00-0451-4000-B000-000000000000",
  ],
).listen((scanResult) {
  //Scan one peripheral and stop scanning
  print("Scanned Peripheral ${scanResult.peripheral.name}, RSSI ${scanResult.rssi}");
  bleManager.stopPeripheralScan();
});

기기 연결 

Peripheral peripheral = scanResult.peripheral;
peripheral.observeConnectionState(emitCurrentValue: true, completeOnDisconnect: true)
  .listen((connectionState) {
    print("Peripheral ${scanResult.peripheral.identifier} connection state is $connectionState");
  });
await peripheral.connect();
bool connected = await peripheral.isConnected();
await peripheral.disconnectOrCancelConnection();

데이터 쓰기

peripheral.writeCharacteristic(
  "F000AA00-0451-4000-B000-000000000000",
  "F000AA02-0451-4000-B000-000000000000",
  Uint8List.fromList([0]),
  false); //returns Characteristic to chain operations more easily

service.writeCharacteristic(
  "F000AA02-0451-4000-B000-000000000000",
  Uint8List.fromList([0]),
  false); //returns Characteristic to chain operations more easily

characteristic.write(Uint8List.fromList([0]), false); //returns void

데이터 읽기

bluetoothManager.subscribeToCharacteristic(_readCharacteristic).listen((data) {
             responseData = data;
             handleListenData();
           }, onError: (dynamic error) {
             logger.d("DEVICE READ FAIL = $error");
           });