본문 바로가기

[Flutter] 플러터 블루투스 연결 구현 #5 Notify, Write 구현

I'm 영서 2023. 3. 10.
반응형

1. 블루투스를 연결하기 위해 필요한것.

   - 블루투스 용어정리

   - 블루투스 라이브러리 

2. 블루투스 연결

    - 아두이노 코드분석

    - 모바일(플러터)에서 확인

3. 데이터 송수신

 

 

글이 꽤나 길어질것같으므로 필요한 내용만 코드로 남긴다.

나는 블루투스 기기와 실시간 연동을 하려했기 때문에 반드시 Notify 혹은 Indicate 기능이 필요했다. 

  • Notify - 클라이언트가 서버로 데이터를 요청하지 않아도 서버에서 새로운 데이터가 생겼을때 자동으로 클라이언트에 알리는 방식으로 대용량데이터 전송이 필요한 경우 선택
  • Indicate - Notify와 비슷하나 클라이언트가 데이터를 받았다는 신호를 서버에게 보내는 것이 추가됨. 데이터의 안정성과 신뢰성이 중요한경우 선택

나는 두개다 테스트를 진행했고, 시간상의 이유로 Notify를 선택했다.(Indicate로 조금씩 수정중..)

아두이노에 해당 코드를 작성하였다.

 

 

아두이노 코드작성

 

1. NotifyCharacteristic 생성

pNotifyCharacteristic = pService->createCharacteristic(
      CHARACTERISTIC_UUID_TX,
      BLECharacteristic::PROPERTY_INDICATE|
      BLECharacteristic::PROPERTY_NOTIFY|
      BLECharacteristic::PROPERTY_WRITE|
      BLECharacteristic::PROPERTY_READ
      );
  pNotifyCharacteristic->addDescriptor(new BLE2902());
  pNotifyCharacteristic->setCallbacks(new MyCallbacks_Notify());

2. 콜백함수 정의

class MyCallbacks_Notify: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
        std::string rxValue = pCharacteristic->getValue();
        //...
    }   
}

3. loop에 추가

pNotifyCharacteristic->setValue( 원하는 값 );
pNotifyCharacteristic->notify();

 

 

플러터 코드작성

 

1. service Uuid와 Characteristic Uuid에 해당하는 캐릭터리스틱 찾기

  void _findServiceAndCharacteristics() async {
    List<BluetoothService> services = await _device!.discoverServices();

    for (BluetoothService service in services) {
      if (service.uuid == aeratorServiceUuid) {
        for (BluetoothCharacteristic characteristic
            in service.characteristics) {
          if (characteristic.uuid == aeratorWriteCharacteristicUuid) {
            _writeCharacteristic = characteristic;
          } else if (characteristic.uuid == aeratorNotifyCharacteristicUuid) {
            print('----------find Notify Characteristic----------');
            _notifyCharacteristic = characteristic;
            await _notifyCharacteristic?.setNotifyValue(true);

            _subscription = _notifyCharacteristic!.value.listen((event) {
              print('Received: ${String.fromCharCodes(event)}');
              var result = '';
              event.toList().forEach((element) {
                result += String.fromCharCode(element);
              });
              if (result.isNotEmpty) {
                var list = result.split('/');
                if (val1 != int.parse(list[0]) ||
                    val2 != double.parse(list[1])) {
                  setState(() {
                    val1 = int.parse(list[0]);
                    val2 = double.parse(list[1]);
                  });                
                  //setState에서 데이터를 받아올 때마다 위젯을 새로 그려주기 위함
                
              }
            });
          }
        }
      }
    }
    if (_writeCharacteristic == null || _notifyCharacteristic == null) {
      throw 'Failed to find desired characteristics';
    }
  }

 

2. 찾아온 캐릭터리스틱별 메서드 작성

-1) Write

void writeData(
      List<int> data, BluetoothCharacteristic _characteristic) {
    if (_characteristic == null) {
      throw 'Write characteristic not found';
    }
    print(data.toString());
    _characteristic!.write(
      data,
      withoutResponse: true,
    );
  }

 

-2) Notify

위 코드에서 setNotifycation(true)를 통해 notify기능을 열어줬으므로

stop만 작성

void _stopNotifications() {
    if (_notifyCharacteristic == null) {
      throw '_stopNotifications Notify characteristic not found';
    }
    _notifyCharacteristic!.setNotifyValue(false);
  }

 

이렇게 사용하면 블루투스 통신이 가능하다.

 

생성자 및 소멸자는 이렇게 작성하였다.  

  @override
  void initState() {
    super.initState();
    isConnected = false;
    startScan();
    Future.delayed(const Duration(milliseconds: 1000), () {
      _findServiceAndCharacteristics();
    });
  }

  @override
  void dispose() {
    _subscription?.cancel();
    _device?.disconnect();
    flutterBlue.stopScan();
    super.dispose();
  }
반응형

댓글