chipweinberger / flutter_blue_plus

Flutter plugin for connecting and communicationg with Bluetooth Low Energy devices, on Android, iOS, macOS
Other
791 stars 478 forks source link

[Help]: The scan result service is returned as null. #885

Closed mika324 closed 6 months ago

mika324 commented 6 months ago

Requirements

Have you checked this problem on the example app?

No

FlutterBluePlus Version

1.31.16

Flutter Version

3.19.5

What OS?

iOS

OS Version

15.5

Bluetooth Module

OPPO Enco Free2, AirBuds U

What is your problem?

discoverServices() does not work because the scan result service is null. After scanning, the service may or may not be acquired normally. How can I obtain service stably? Because service is null, the following error is output. Unhandled Exception: FlutterBluePlusException | discoverServices | fbp-code: 6 | device is not connected

The implemented code is as follows.

final PERIPHERAL_DEVICE_INFO = {
    "id": Platform.isIOS
       ? "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
       : "XX:XX:XX:XX:XX:XX",
}
class _ScanScreenState extends State<ScanScreen> with WidgetsBindingObserver {
  List<BluetoothDevice> _systemDevices = [];
  List<ScanResult> _scanResults = [];
  bool _isScanning = false;
  late StreamSubscription<List<ScanResult>> _scanResultsSubscription;
  Timer? _scanTimer;

  @override
  void initState() {
    super.initState();
    _scanResultsSubscription =
        FlutterBluePlus.scanResults.listen((List<ScanResult> results) async {

     bool found = results.isNotEmpty &&
         results.any((result) =>
             result.device.remoteId.toString() ==
             PERIPHERAL_DEVICE_INFO['id'].toString());
     if (found) {
      var device = results[0].device;
      _scanTimer?.cancel();
        print(
            'timer cancel■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ${devicesList.length}');
      if (devicesList.length == 0) {
          setState(() {
            devicesList.add(device);
            hasConnectedBefore = true;
          });
        connectDevice();
      }
     }
     // Not detected when connecting
     FlutterBluePlus.events.onConnectionStateChanged.listen((state) {
       print('onConnectionStateChanged events: ${state.connectionState}');
     });

     scanDevice();
  }

  void getCharacteristic() async {
    List<BluetoothService> services = await devicesList[0].discoverServices();
    print(' services!: $services');
    services.forEach((service) {
      service.characteristics.forEach((characteristic) async {
        print('characteristic: $characteristic');
        var isNotify = characteristic.properties.notify;
        print('isNotify: $isNotify');
        if (isNotify) {
          print('isNotify if: $isNotify');
          var subscription =
              characteristic.onValueReceived.listen((List<int> value) async {
            print("Received data: $value");
          });
          await characteristic.setNotifyValue(true);
          // リスナーのサブスクリプションをリストに追加
          _valueReceivedSubscriptions.add(subscription);
        }
      });
    });
  }

  void connectDevice() async {
    if (FlutterBluePlus.connectedDevices.length > 0) return;
    _scanResultsSubscription.cancel();
    print('start reconnect');
    try {
      // 自動接続
      isIOS
          ? await devicesList[0].autoConnect()
          : await devicesList[0].connectAndUpdateStream();
      getCharacteristic();
  }

  void scanDevice() async {
      print(
        'scan start■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■');
      FlutterBluePlus.stopScan();
      isIOS
          ? FlutterBluePlus.startScan(
              withRemoteIds: [PERIPHERAL_DEVICE_INFO['id'] as String],
              timeout: const Duration(milliseconds: 1000),
            )
          : FlutterBluePlus.startScan(
              withRemoteIds: [PERIPHERAL_DEVICE_INFO['id'] as String],
              timeout: const Duration(milliseconds: 1000),
            );
    }
}

I would like someone who knows how to solve this problem to tell me. Thank you for reviewing the question.

I'm Japanese, so I apologize if there are any mistakes in the English translation.🙏

Logs

2024-05-16 13:01:35.255792+0900 Runner[11661:4874038] Metal API Validation Enabled
centralManagerDidUpdateState!!!!! CBManagerState
2024-05-16 13:01:35.389803+0900 Runner[11661:4874363] flutter: The Dart VM service is listening on http://127.0.0.1:54577/ZGtPdtno4Tg=/
2024-05-16 13:01:35.620275+0900 Runner[11661:4874038] [FBP-iOS] handleMethodCall: flutterHotRestart
2024-05-16 13:01:35.620350+0900 Runner[11661:4874038] [FBP-iOS] initializing CBCentralManager
2024-05-16 13:01:35.620373+0900 Runner[11661:4874038] [FBP-iOS] show power alert: yes
2024-05-16 13:01:35.620610+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<setLogLevel>\^[[0m args: \^[[1;35<…>
2024-05-16 13:01:35.620704+0900 Runner[11661:4874038] [FBP-iOS] initializing checkForMtuChangesTimer
2024-05-16 13:01:35.620762+0900 Runner[11661:4874038] [FBP-iOS] disconnectAllDevices(flutterHotRestart)
2024-05-16 13:01:35.620784+0900 Runner[11661:4874038] [FBP-iOS] connectedPeripherals: 0
2024-05-16 13:01:35.621157+0900 Runner[11661:4874038] [FBP-iOS] handleMethodCall: setLogLevel
2024-05-16 13:01:35.624656+0900 Runner[11661:4874038] [FBP-iOS] centralManagerDidUpdateState CBManagerStatePoweredOn
2024-05-16 13:01:35.930652+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<setLogLevel>\^[[0m result: \^[[1;33mtr<…>
2024-05-16 13:01:35.932701+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<getAdapterState>\^[[0m args: \^[[1;35mnu<…>
2024-05-16 13:01:35.932803+0900 Runner[11661:4874038] [FBP-iOS] handleMethodCall: getAdapterState
2024-05-16 13:01:35.934339+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m[[ OnAdapterStateChanged ]]\^[[0m result: \^[[1;33m{adapter_state: <…>
2024-05-16 13:01:35.938206+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<getAdapterState>\^[[0m result: \^[[1;33m{adapter_state: <…>
2024-05-16 13:01:36.042860+0900 Runner[11661:4874346] flutter: results: []
2024-05-16 13:01:36.042923+0900 Runner[11661:4874346] flutter: found: false
2024-05-16 13:01:36.042985+0900 Runner[11661:4874346] flutter: _systemDevices: []
2024-05-16 13:01:36.045603+0900 Runner[11661:4874346] flutter: state: BluetoothAdapterState.on
2024-05-16 13:01:45.981099+0900 Runner[11661:4874346] flutter: scan start■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
2024-05-16 13:01:45.987698+0900 Runner[11661:4874346] flutter: [FBP] stopScan: already stopped
2024-05-16 13:01:45.994725+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<startScan>\^[[0m args: \^[[1;35m{with_services: [], with_remote_ids: [D89BE109-8326-B20F-0CDF-BFDC698019AA], with_names: [], with_keywords: [], with_msd: [], with_service_data: [], continuous_updates: false, continuous_divisor: 1, android_scan_mode: 2, android_uses_fine_location: fals<…>
2024-05-16 13:01:45.996126+0900 Runner[11661:4874038] [FBP-iOS] handleMethodCall: startScan
2024-05-16 13:01:45.996847+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<startScan>\^[[0m result: \^[[1;33mtr<…>
2024-05-16 13:01:45.998455+0900 Runner[11661:4874346] flutter: results: []
2024-05-16 13:01:45.998582+0900 Runner[11661:4874346] flutter: found: false
2024-05-16 13:01:45.998669+0900 Runner[11661:4874346] flutter: _systemDevices: []
2024-05-16 13:01:46.419787+0900 Runner[11661:4874038] [FBP-iOS] centralManager didDiscoverPeripheral
2024-05-16 13:01:47.011924+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<stopScan>\^[[0m args: \^[[1;35mnu<…>
2024-05-16 13:01:47.012439+0900 Runner[11661:4874038] [FBP-iOS] handleMethodCall: stopScan
2024-05-16 13:01:47.014029+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<stopScan>\^[[0m result: \^[[1;33mtr<…>
2024-05-16 13:01:55.977438+0900 Runner[11661:4874346] flutter: scan start■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
2024-05-16 13:01:55.978146+0900 Runner[11661:4874346] flutter: [FBP] stopScan: already stopped
2024-05-16 13:01:55.979294+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<startScan>\^[[0m args: \^[[1;35m{with_services: [], with_remote_ids: [D89BE109-8326-B20F-0CDF-BFDC698019AA], with_names: [], with_keywords: [], with_msd: [], with_service_data: [], continuous_updates: false, continuous_divisor: 1, android_scan_mode: 2, android_uses_fine_location: fals<…>
2024-05-16 13:01:55.980181+0900 Runner[11661:4874038] [FBP-iOS] handleMethodCall: startScan
2024-05-16 13:01:55.981188+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<startScan>\^[[0m result: \^[[1;33mtr<…>
2024-05-16 13:01:55.981857+0900 Runner[11661:4874346] flutter: results: []
2024-05-16 13:01:55.982039+0900 Runner[11661:4874346] flutter: found: false
2024-05-16 13:01:55.982228+0900 Runner[11661:4874346] flutter: _systemDevices: []
2024-05-16 13:01:56.054981+0900 Runner[11661:4874038] [FBP-iOS] centralManager didDiscoverPeripheral
2024-05-16 13:01:56.056388+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m[[ OnScanResponse ]]\^[[0m result: \^[[1;33m{advertisements: [{remote_id: D89BE109-8326-B20F-0CDF-BFDC698019AA, platform_name: OPPO Enco Free2, manufacturer_data: {1946: 1020063f000198045d077ab3fd2c09b5b5b501}, connectable: 1, rssi: -28, adv_name: OPPO Enco Free2}<…>
2024-05-16 13:01:56.079983+0900 Runner[11661:4874346] flutter: results: [ScanResult{device: BluetoothDevice{remoteId: D89BE109-8326-B20F-0CDF-BFDC698019AA, platformName: OPPO Enco Free2, services: null}, advertisementData: AdvertisementData{advName: OPPO Enco Free2, txPowerLevel: null, appearance: null, connectable: true, manufacturerData: {1946: [16, 32, 6, 63, 0, 1, 152, 4, 93, 7, 122, 179, 253, 44, 9, 181, 181, 181, 1]}, serviceData: {}, serviceUuids: []}, rssi: -28, timeStamp: 2024-05-16 13:01:56.073480}]
2024-05-16 13:01:56.080186+0900 Runner[11661:4874346] flutter: found: true
2024-05-16 13:01:56.080540+0900 Runner[11661:4874346] flutter: _systemDevices: [BluetoothDevice{remoteId: D89BE109-8326-B20F-0CDF-BFDC698019AA, platformName: OPPO Enco Free2, services: null}]
2024-05-16 13:01:56.080758+0900 Runner[11661:4874346] flutter: timer cancel■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 0
2024-05-16 13:01:56.081646+0900 Runner[11661:4874346] flutter: devicesList: [BluetoothDevice{remoteId: D89BE109-8326-B20F-0CDF-BFDC698019AA, platformName: OPPO Enco Free2, services: null}]
2024-05-16 13:01:56.084753+0900 Runner[11661:4874346] flutter: start reconnect
2024-05-16 13:01:56.086295+0900 Runner[11661:4874346] flutter: auto connect start!
2024-05-16 13:01:56.088023+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<connect>\^[[0m args: \^[[1;35m{remote_id: D89BE109-8326-B20F-0CDF-BFDC698019AA, auto_connect: <…>
2024-05-16 13:01:56.088291+0900 Runner[11661:4874038] [FBP-iOS] handleMethodCall: connect
2024-05-16 13:01:56.088900+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<connect>\^[[0m result: \^[[1;33mtr<…>
2024-05-16 13:01:56.089022+0900 Runner[11661:4874346] flutter: auto connect success!
2024-05-16 13:01:56.089304+0900 Runner[11661:4874038] [FBP-iOS] didConnectPeripheral
2024-05-16 13:01:56.094665+0900 Runner[11661:4874346] [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: FlutterBluePlusException | discoverServices | fbp-code: 6 | device is not connected
#0      BluetoothDevice.discoverServices (package:flutter_blue_plus/src/bluetooth_device.dart:228:7)
#1      _ScanScreenState.getCharacteristic (package:flutter_application_2/screens/scan_screen.dart:318:60)
#2      _ScanScreenState.connectDevice (package:flutter_application_2/screens/scan_screen.dart:369:7)
<asynchronous suspension>
2024-05-16 13:01:56.094937+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m<stopScan>\^[[0m args: \^[[1;35mnu<…>
2024-05-16 13:01:56.095105+0900 Runner[11661:4874038] [FBP-iOS] handleMethodCall: stopScan
2024-05-16 13:01:56.095343+0900 Runner[11661:4874346] flutter: [FBP] \^[[1;30m[[ OnConnectionStateChanged ]]\^[[0m result: \^[[1;33m{remote_id: D89BE109-8326-B20F-0CDF-BFDC698019AA, connection_state: 1, disconnect_reason_code: null, disconnect_reason_string: nul<…>
2024-05-16 13:01:56.097491+0900 Runner[11661:4874346] flutter: onConnectionStateChanged: BluetoothDevice{remoteId: D89BE109-8326-B20F-0CDF-BFDC698019AA, platformName: OPPO Enco Free2, services: null} BluetoothConnectionState.connected
...
chipweinberger commented 6 months ago

wait until connection before discoverServices

await device.connectionState.where((val) => val == BluetoothConnectionState.connected).first;

however, I advise you do not use autoConnect until you understand it better.

//  - when using autoConnect, connect() always returns immediately, so we must
//    explicity listen to `device.connectionState` to know when connection occurs