react-native-ble-plx icon indicating copy to clipboard operation
react-native-ble-plx copied to clipboard

Wait for successful pairing

Open Xenofono opened this issue 4 years ago • 5 comments

  • I am running the latest version
  • I checked the documentation and found no answer

Hi Guys, I posted this on github as well f y i, hope someone can give me some insight!

I'm new to bluetooth and to react native as well and I've encountered a problem that I've spent days on but I haven't gotten anywhere.

I'm developing an app using the react-native-ble-plx library, but I encountered the same issue using react-native-ble-manager. I've been given a requirement that we need to have security level 3 with numeric comparison and in one of the first screens in the app the user should scan a QR code on the printer which gives the bluetooth library scanner the name it should look for so the user shouldn't have to see any other devices.

This works fine but the problem is when the pairing starts, the app should wait until pairing has been completed before going to the next screen but I haven't seen any way to do this. So what happens is that as soon as the device is connected and services are retrieved, the next then-function gets triggered even if the user aborted the pairing because technically I guess the connection is still active because its waiting for the pairing to complete. I've marked out what I mean in a code example.

So summarize, is there a way to wait for a successful pairing before allowing the user to the next stage? They'll be potentially changing to many different devices all on the same day so I can't really count on them just having to successfully pair just once and it'll be fine. Thanks!

bleManager.startDeviceScan(
        null,
        {scanMode: ScanMode.LowLatency},
        (err, device) => {
          if (err) {
            setLoading(false);
            return;
          }

          if (device && device.name === printer.printerName) {
            bleManager.stopDeviceScan();
            device
              .connect({timeout: 10000})
              .then((d) => {
                return d.discoverAllServicesAndCharacteristics();
              })
              .then((d) => {
                //THIS SHOULD ONLY HAPPEN IF PAIRING WAS COMPLETED
                dispatch({
                  type: 'SET_PRINTER',
                  payload: {
                    printerId: d.id,
                    printerName: printer.printerName,
                    isBluetooth: printer.isBluetooth,
                    printerNetworkId: printer.id,
                  },
                });

                setLoading(false);

                navigation.canGoBack()
                  ? navigation.goBack()
                  : navigation.navigate(patientRoute);
              })
              .catch((error) => {
                console.log(error);
                setLoading(false);
              });

Xenofono avatar Feb 28 '21 17:02 Xenofono

I'm having the same issue that it doesn't wait for the peripheral to actually pair before running other logic:

const device = await this.device.connect();
this.device = await device.discoverAllServicesAndCharacteristics();

// other logic

It'll just try to execute all the logic before the device is even paired.

brandonin avatar Apr 06 '21 19:04 brandonin

Also seeing the same issue.

Here is the function that should scan, stop scan when target device is found, connect, and then discover services and characteristic after the device.connect() promise resolves successfully. But, error is encountered when trying to perform connected operations.

 const connectDevice = ({ address, name }) => {
          setDevicesLoading(true);
          let numScanned = 0;
          manager.startDeviceScan(
              null,
              { allowDuplicates: false },
              (error, scannedDevice) => {
                  if (error) {
                      setDevicesLoading(false);
                      console.error(error);
                      return;
                  }
                  if (scannedDevice != null) {
                      numScanned = numScanned + 1;
                      if (numScanned >= 1500) {
                          manager.stopDeviceScan();
                          setDevicesLoading(false);
                          return;
                      }
                      console.log(numScanned);
                      if (
                          scannedDevice.id == address ||
                          scannedDevice.name == name
                      ) {
                          console.log("target device found");
                          manager.stopDeviceScan();
                          scannedDevice
                              .connect()
                              .then(device => {
                                  console.log("Device connect promise returned.");
                                  device
                                      .discoverAllServicesAndCharacteristics()
                                      .then(device => console.log(device))
                                      .catch(err => console.error(err));
                              })
                              .catch(err => console.error(err));
                          setDevicesLoading(false);
                      }
                  }
              }
          );
      };

Here are the logs:

[Tue Apr 13 2021 07:23:15.812]  LOG      1
[Tue Apr 13 2021 07:23:15.813]  LOG      target device found
[Tue Apr 13 2021 07:23:16.225]  LOG      Device connect promise returned.
[Tue Apr 13 2021 07:23:16.239]  ERROR    [BleError: Device 64:33:DB:BE:3A:80 is not connected]

adamlbailey avatar Apr 13 '21 14:04 adamlbailey

The issue I had was for android and I fixed it by moving to react-native-ble-manager for android. I ended up bonding the peripheral before connecting and it solved my issues.

brandonin avatar Apr 13 '21 17:04 brandonin

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jun 16 '21 23:06 stale[bot]

I had the same problem of needing to wait until manager.startDeviceScan() was done with scanning and connection.

The solution is to wrap the manager.startDeviceScan() function in a promise and resolve that promise within device.connect().

Here's an adaption of the official intro code:

export async function scanAndConnect() {
    let promise = new Promise((resolve, reject) => {
    manager.startDeviceScan(null, null, (error, device) => {
        if (error) {
        // Handle error (scanning will be stopped automatically)
        reject(error);
        }

        if (device.name === 'TI BLE Sensor Tag' || device.name === 'SensorTag') {
        // Stop scanning as it's not necessary if you are scanning for one device.
        manager.stopDeviceScan();

        // Proceed with connection.
        device
            .connect()
            .then((device) => {
            return device.discoverAllServicesAndCharacteristics();
            })
            .then((device) => {
            // Do work on device with services and characteristics
            console.log(
                `[INFO] BLE device connected! name: ${device.name}, id: ${device.id}`
            );
            resolve(true);
            })
            .catch((error) => {
            // Handle errors
            reject(error);
            });
        }
    });
    });

    let result = await promise;
    return result;
}

This returns true once the connection is finished. Of course you can return other things with resolve() too.

You can then call this function in some other part of your application:

scanAndConnect().then((res) => {
    // logic that should be executed after successful connection
    res
        ? console.log("[INFO] connection successful")
        : console.log("[INFO] connection failed");
});

Some more info on using Promises.

Fivefold avatar Sep 24 '21 20:09 Fivefold

I'm excited to inform you that we've released a new version of react-native-ble-plx. Many of the concerns and bugs have been addressed in this update.

If you encounter any issues or have further suggestions, please don't hesitate to open a new issue.

abursztynowska avatar Oct 06 '23 08:10 abursztynowska