Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Windows] Unhandled Exception: PlatformException(IllegalArgument, Unknown devicesId: .... , null, null) #136

Open
rebeccasc opened this issue Dec 3, 2022 · 6 comments

Comments

@rebeccasc
Copy link

QuickBlue irregularly throws an exception when calling

await QuickBlue.setNotifiable(
            device.address,
            myUartServiceUUID,
            myUartCharacteristicsUUID,
            BleInputProperty.notification);

This exception does not always occur thats why I assume it's a timing error.

Here's the full code:

// scan for device
String deviceId;
QuickBlue.scanResultStream.listen((result) {
     deviceId = result.deviceId;
     // return if device found
});
QuickBlue.startScan();
// wait some time for scanning
await Future.delayed(const Duration(seconds: 1));
QuickBlue.stopScan();

// set value handler
QuickBlue.setValueHandler((String deviceId, String characteristicId, Uint8List value) {
          // do something with the recevied values
 });

// connect and set notifiable
QuickBlue.connect(deviceId);
// give quick_blue some time to handle async function
await Future.delayed(const Duration(seconds: 2));
await QuickBlue.setNotifiable(
            deviceId,
            myUartServiceUUID,
            myUartCharacteristicsUUID,
            BleInputProperty.notification);
// give quick_blue some time to handle async function
await Future.delayed(const Duration(seconds: 2));

What I did trying to fix it:

  • added delays (see ahead)
  • checked for the correct deviceId. The deviceId comes from the scan result and stable works for QuickBlue.connect(deviceId);

Is this related to: #93, or #90?

Does anyone have an idea how I can fix/avoid the exception?

Thanks!

@alevlako
Copy link

alevlako commented Dec 4, 2022

You can use prerelease plugin version 0.5.0-dev.2
In this version, the author completed the receiving serviceId and characteristicIds from device for Windows.

QuickBlue.setConnectionHandler(_handleConnectionChange);
QuickBlue.setServiceHandler(_handleServiceDiscovery);

void _handleConnectionChange(String deviceId, BlueConnectionState state) {
    if (state == BlueConnectionState.connected) {
      QuickBlue.discoverServices(deviceId);
    }
  }

//The main point: This handler is called multiple times during the connection process
void _handleServiceDiscovery(String deviceId, String serviceId, List<String>? characteristicIds) {
    if (deviceId.isNotEmpty && serviceId.isNotEmpty && characteristicIds != null && characteristicIds.length > 1) {
      //Update: Here you are already dealing with different services and you can choose which you need, no need any Future and delays :-)
     }
    }
  }

@rebeccasc
Copy link
Author

@alevlako Thanks for the fast response!

You can use prerelease plugin version 0.5.0-dev.2

Have tried this. Unfortunately this does not fix the error...

@AErmek
Copy link

AErmek commented Jun 15, 2023

@rebeccasc
Hi, did you find any solution or workaround?

@rebeccasc
Copy link
Author

@rebeccasc Hi, did you find any solution or workaround?

I fixed it with some workaround. Maybe it's not the smartest way to solve it but it works for me.

First I wrap the code block with an flutter runZonedGuarded so the error can be caught. It turned out that the thrown error cannot be caught by a simple try-catch statement. Because the error will be thrown irregularly I simply try to run the code 5 times. Practice shows that it usually works with the second call. The code looks like this:

var connectionRetry = 5;
while (connectionRetry > 0 && !(await connectPlatformWindows())) {
   // connection failed, try again
   connectionRetry--;
}

Future<bool> connectPlatformWindows() async {
    var success = true;
    await runZonedGuarded(() async {
        // run the code ahead ...
        QuickBlue.setValueHandler((String deviceId, String characteristicId, Uint8List value) {
             // do something with the recevied values
         });
        
        QuickBlue.connect(deviceId);

        // give quick_blue some time to handle async function
        await Future.delayed(const Duration(seconds: 2));

        await QuickBlue.setNotifiable(
                deviceId,
                myUartServiceUUID,
                myUartCharacteristicsUUID,
                BleInputProperty.notification);

        // give quick_blue some time to handle async function
        await Future.delayed(const Duration(milliseconds: 250));
    }, (e, stack) {
      success = false;
    });
    return success;
}

Hope it helps.

@AErmek
Copy link

AErmek commented Jun 19, 2023

@rebeccasc Hi, did you find any solution or workaround?

I fixed it with some workaround. Maybe it's not the smartest way to solve it but it works for me.

First I wrap the code block with an flutter runZonedGuarded so the error can be caught. It turned out that the thrown error cannot be caught by a simple try-catch statement. Because the error will be thrown irregularly I simply try to run the code 5 times. Practice shows that it usually works with the second call. The code looks like this:

var connectionRetry = 5;
while (connectionRetry > 0 && !(await connectPlatformWindows())) {
   // connection failed, try again
   connectionRetry--;
}

Future<bool> connectPlatformWindows() async {
    var success = true;
    await runZonedGuarded(() async {
        // run the code ahead ...
        QuickBlue.setValueHandler((String deviceId, String characteristicId, Uint8List value) {
             // do something with the recevied values
         });
        
        QuickBlue.connect(deviceId);

        // give quick_blue some time to handle async function
        await Future.delayed(const Duration(seconds: 2));

        await QuickBlue.setNotifiable(
                deviceId,
                myUartServiceUUID,
                myUartCharacteristicsUUID,
                BleInputProperty.notification);

        // give quick_blue some time to handle async function
        await Future.delayed(const Duration(milliseconds: 250));
    }, (e, stack) {
      success = false;
    });
    return success;
}

Hope it helps.

Thanks for reply,
It looks really interesting workaround. I'have tried it , but infortunately, in my case i'm getting native windows fatal crash on first call of connect method (even runZonedGuarded not catching exception). I really don't know why this package has so chaotic behavior for windows platform implementation. I've also tried to make connection via win32 package with winsock2, but there are also has its own issues. Now I'm just stuck.

@alevlako
Copy link

... in my case i'm getting native windows fatal crash on first call of connect method (even runZonedGuarded not catching exception). I really don't know why this package has so chaotic behavior for windows platform implementation. I've also tried to make connection via win32 package with winsock2, but there are also has its own issues. Now I'm just stuck.

The plugin behaves like this when there is no bluetooth receiver (dongle) connected to the PC. This is a known issue and it has the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants