connect method

Future<void> connect({
  1. Duration timeout = const Duration(seconds: 35),
  2. int? mtu = 512,
  3. bool autoConnect = false,
})

Establishes a connection to the Bluetooth Device. timeout if timeout occurs, cancel the connection request and throw exception mtu Android only. Request a larger mtu right after connection, if set. autoConnect reconnect whenever the device is found - if true, this function always returns immediately. - you must listen to connectionState to know when connection occurs. - auto connect is turned off by calling disconnect - auto connect results in a slower connection process compared to a direct connection because it relies on the internal scheduling of background scans.

Implementation

Future<void> connect({
  Duration timeout = const Duration(seconds: 35),
  int? mtu = 512,
  bool autoConnect = false,
}) async {
  // If you hit this assert, you must set `mtu:null`, i.e `device.connect(mtu:null, autoConnect:true)`
  // and you'll have to call `requestMtu` yourself. `autoConnect` is not compatibile with `mtu`.
  assert((mtu == null) || !autoConnect, "mtu and auto connect are incompatible");

  // make sure no one else is calling disconnect
  _Mutex dmtx = _MutexFactory.getMutexForKey("disconnect");
  bool dtook = await dmtx.take();

  // Only allow a single ble operation to be underway at a time
  _Mutex mtx = _MutexFactory.getMutexForKey("global");
  await mtx.take();

  try {
    // remember auto connect value
    if (autoConnect) {
      FlutterBluePlus._autoConnect.add(remoteId);
    }

    var request = BmConnectRequest(
      remoteId: remoteId,
      autoConnect: autoConnect,
    );

    var responseStream = FlutterBluePlus._methodStream.stream
        .where((m) => m.method == "OnConnectionStateChanged")
        .map((m) => m.arguments)
        .map((args) => BmConnectionStateResponse.fromMap(args))
        .where((p) => p.remoteId == remoteId);

    // Start listening now, before invokeMethod, to ensure we don't miss the response
    Future<BmConnectionStateResponse> futureState = responseStream.first;

    // invoke
    bool changed = await FlutterBluePlus._invokeMethod('connect', request.toMap());

    // we return the disconnect mutex now so that this
    // connection attempt can be canceled by calling disconnect
    dtook = dmtx.give();

    // only wait for connection if we weren't already connected
    if (changed && !autoConnect) {
      BmConnectionStateResponse response = await futureState
          .fbpEnsureAdapterIsOn("connect")
          .fbpTimeout(timeout.inSeconds, "connect")
          .catchError((e) async {
        if (e is FlutterBluePlusException && e.code == FbpErrorCode.timeout.index) {
          await FlutterBluePlus._invokeMethod('disconnect', remoteId.str); // cancel connection attempt
        }
        throw e;
      });

      // failure?
      if (response.connectionState == BmConnectionStateEnum.disconnected) {
        if (response.disconnectReasonCode == bmUserCanceledErrorCode) {
          throw FlutterBluePlusException(
              ErrorPlatform.fbp, "connect", FbpErrorCode.connectionCanceled.index, "connection canceled");
        } else {
          throw FlutterBluePlusException(
              _nativeError, "connect", response.disconnectReasonCode, response.disconnectReasonString);
        }
      }
    }
  } finally {
    if (dtook) {
      dmtx.give();
    }
    mtx.give();
  }

  // request larger mtu
  if (Platform.isAndroid && isConnected && mtu != null) {
    await requestMtu(mtu);
  }
}