flutter_blue icon indicating copy to clipboard operation
flutter_blue copied to clipboard

PlatformException(connect, Peripheral not found, null)

Open luisvilches opened this issue 5 years ago • 54 comments

Hi, i have the next error at method connect, only in ios, someone knows how to fix it?

PlatformException(connect, Peripheral not found, null)

luisvilches avatar Feb 17 '20 19:02 luisvilches

I have the same problem.

This is my source code:

import 'dart:async';

import 'package:flutter_blue/flutter_blue.dart';
import 'package:infinite_base_library/infinite_base_library.dart';
import 'package:infinite_hub/base/base_viewmodel.dart';
import 'package:infinite_hub/base/constants.dart';
import 'package:infinite_hub/base/enums.dart';

class DeviceDetailViewModel<T> extends BaseViewModel {
  bool _isStatic = false;
  StreamController<List<ScanResult>> sController;
  StreamSubscription<List<ScanResult>> scanSubscription;
  StreamController<List<int>> readDataStreamController;
  StreamSubscription<List<int>> readDataSubscription;
  StreamSubscription<BluetoothDeviceState> stateSubscriber;
  List<BluetoothDevice> connectedDevices;
  BluetoothDeviceState deviceState;
  BluetoothCharacteristic characteristics;
  Stream<List<int>> readDataStream;

  final String rpiPropertyService_UUID = kRpiPropertyService_UUID;
  final String rpiUUIDStrTransRx = kRpiUUIDStrTransRx;
  final String lairdUUIDStrTransRX = kLairdUUIDStrTransRX;
  final String lirdUUIDStrTransTX = kLairdUUIDStrTransTX;

  T _dev;
  T get device => _dev;

  BluetoothDevice deviceToConnect;

  set device(T d) {
    _dev = d;
    setState(state); //we don't change current state
  }

  bool get isStaticConn => _isStatic;

  set isStaticConn(bool value) {
    _isStatic = value;
    setState(state); //we don't change current state
  }

  sendWifiSettings() {}

  sendEthSettings() {}

  void connectWithBluetooth() async {
    setState(ViewState.Busy);

    if (deviceState == BluetoothDeviceState.connected) {
      print('disconnecting');

      await deviceToConnect.disconnect();
      print('disconnected');

      await checkState();
    } else if (null == deviceToConnect) {
      print('scan');
      scanForDevices();
    } else {
      try {
        await deviceToConnect.connect();

        await checkState();
      } catch (e) {
        setState(ViewState.Idle);

        print(e);
      }
    }
  }

  void scanForDevices() async {
    sController = StreamController();
    readDataStreamController = StreamController();

    //await checkConnectedDevices();

    sController.addStream(FlutterBlue.instance.scanResults);

    FlutterBlue.instance.startScan(timeout: Duration(seconds: 10));

    scanSubscription = sController.stream.listen((devices) async {
      final result = devices.where((currentDev) => currentDev.advertisementData.localName.contains((_dev as BaseDevice).psn)).toList();

      if (null == deviceToConnect && null != result && result.length > 0) {
        stopScanning();

        final dev = result.first;

        deviceToConnect = dev.device;
        print(dev.advertisementData.localName);

        try {
          await dev.device.connect();

          checkState();

          discoverServices();
        } catch (e) {
          setState(ViewState.Idle);

          print(e);
        }
      }
    });
  }

  Future checkConnectedDevices() async {
    print('check connected devices');
    connectedDevices = await FlutterBlue.instance.connectedDevices.whenComplete(() {
      if (null != connectedDevices) {
        print(connectedDevices.length);
      }
    });
  }

  Future checkState() async {
    stateSubscriber = deviceToConnect.state.listen((state) async {
      deviceState = state;
      print(state.toString());
      stopGettingState();
      setState(ViewState.Idle);
    });
  }

  void stopGettingState() {
    stateSubscriber.cancel();
  }

  void disconnectDevice() async {
    print('disconnecting ${deviceToConnect.name}');

    await deviceToConnect.disconnect();

    print('disconnected');
  }

  void stopScanning() async {
    print('stopping scan');

    await FlutterBlue.instance.stopScan();

    if (null != scanSubscription) await scanSubscription.cancel();

    if (null != sController) await sController.close();
  }

  void discoverServices() async {
    List<BluetoothService> services = await deviceToConnect.discoverServices();

    //checking each services provided by device
    services.forEach((service) {
      if (service.uuid.toString().toUpperCase() == rpiPropertyService_UUID) {
        service.characteristics.forEach((characteristic) {
          if (characteristic.uuid.toString() == rpiUUIDStrTransRx || characteristic.uuid.toString() == lairdUUIDStrTransRX) {
            characteristics = characteristic;
          } else if (characteristic.uuid.toString() == lirdUUIDStrTransTX) {
            readDataStream = characteristic.value;
            characteristic.setNotifyValue(!characteristic.isNotifying);
          }
        });
      }
    });

    if (null != readDataStream) await readValuesFromDevice();
  }

  Future readValuesFromDevice() async {
    await readDataStreamController.addStream(readDataStream);

    readDataSubscription = readDataStreamController.stream.listen((currentValue) async {
      interpretReceivedData(currentValue);
    });
  }

  void interpretReceivedData(List<int> data) async {
    print('characteristics: $data');
  }
}

Works fine, but not always. For example:

  • first time works fine
  • second time doesn't work
  • thirth time works fine
  • fourth time doesn't work
  • ...

sami-samcla avatar Feb 19 '20 11:02 sami-samcla

You should probably provide the full code example (eg. where do you hold field deviceToConnect and when you clear it).

Note1 : sController.stream.listen will remain when scanning timeout happens. Note2: commented stopScanning() should be called as soon as you detect the scanned device (before any await).

boskokg avatar Feb 19 '20 18:02 boskokg

You should probably provide the full code example (eg. where do you hold field deviceToConnect and when you clear it).

Note1 : sController.stream.listen will remain when scanning timeout happens. Note2: commented stopScanning() should be called as soon as you detect the scanned device (before any await).

@boskokg please find above the full code. Now I call stopScanning() method just before I detect the scanned device. Thanks for your comments.

sami-samcla avatar Feb 20 '20 07:02 sami-samcla

@boskokg did you find out any potencial problem in the full code? Thanks in advance!!

sami-samcla avatar Mar 02 '20 12:03 sami-samcla

@sami-samcla Sorry for the delay.

Are you still experiencing this issue?

pauldemarco avatar Apr 01 '20 03:04 pauldemarco

Hello Paul.

Yes I'm still experiencing this issue.

Do you have any suggestion to solve it.

Many thanks for your attention.

El mié., 1 abr. 2020 5:14, Paul DeMarco [email protected] escribió:

@sami-samcla https://github.com/sami-samcla Sorry for the delay.

Are you still experiencing this issue?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/pauldemarco/flutter_blue/issues/497#issuecomment-607002575, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOGWXNNFJS4URF5FDBCG7TTRKKWPPANCNFSM4KWXKFSQ .

sami-samcla avatar Apr 01 '20 08:04 sami-samcla

Also experiencing this issue randomly.

KeenStratium avatar May 22 '20 11:05 KeenStratium

I'm experiencing a similar issue. So far, my conclusions are as follows:

  • iOS keeps a list of devices connected to the phone (which is obtained by flutter_blue using the .connectedDevices attribute - mapping to iOS' "retrieveConnectedPeripheralsWithServices")

  • If a device is not in that list, it is discovered by scanning, and calling .connect() on such a "freshly discovered" device always works for me

  • If a device is in that list, it will not be discovered by scanning. I can still call connect on the BluetoothDevice instance I get from .connectedDevices, but now the issues begin...

  • If the last discovery of the device has been more or less recent, connecting usually works

  • If the last discovery of the device has been longer ago (let's say 1-2 hours), connecting does not work, and I get the "PlatformException(connect, Peripheral not found, null)"

  • What's really bad is that from that point on, I can neither connect nor re-discover the device by scanning, as it appears to be still in the connectedDevices list but not working anymore

  • If I turn Bluetooth off and on again at this point, it appears that the connectedDevices list gets cleared and I can re-discover the device again by scanning and also connect to it again successfully

  • If I wait longer than the "critical window", I may not run into the issue at all, because the device has been removed from the connectedDevices list by iOS? I think that explains the "randomness" of the effect.

  • It appears to me that different iPhones (or different iOS versions) not sure about that are affected to different extents. My own iPhone Xs running iOS 13.4.1 appears to be not affected, and devices disappear from the connectedDevices list within a few minutes after I call disconnect() in my app. One of my colleagues has an iPhone 7 Plus (also running iOS 13.4.1, so the difference in behavior seems to be related to the hardware?), which runs into the problem quite often. It appears that on his phone, devices are staying much longer in the connectedDevices list.

Hope that helps to figure out more about the issue. If anyone knows a workaround that would be highly appreciated.

dusalex avatar May 27 '20 17:05 dusalex

Yesterday, one of our test users reported the same issue also with an iPhone 11, so it does not appear to be limited to older hardware like the iPhone 7 Plus I mentioned in my previous post.

dusalex avatar May 29 '20 05:05 dusalex

Having the same issue here today on various iDevices and a moto e5

darrendavidhumphrey avatar Jun 05 '20 19:06 darrendavidhumphrey

We are also having this issue with iOS from devices 5c, iphone 11, Xs, 6+. Seldomly happens on android but is still existent.

mbaz2 avatar Jun 16 '20 04:06 mbaz2

@pauldemarco: Any chance on looking into this topic? It is pretty detrimental to our user experience. I would also be happy to help looking into the issue (coding-wise) if you have some pointers what it could be related to.

dusalex avatar Jun 16 '20 10:06 dusalex

@Alex-Evo I've noticed on iOS when a device gets into this state trying to press our 'Connect' button this error will will persist and doesn't seem to resolve itself. If I transition away from the connection screen and back though it will work as intended.

mbaz2 avatar Jun 23 '20 17:06 mbaz2

Yes, me know if we can help debug this issue. It is also pretty detrimental to our device setup experience. We just released 1.0 of our app to the IOS store with the issue.

On Tue, Jun 23, 2020 at 1:06 PM Matt Bazin [email protected] wrote:

@Alex-Evo https://github.com/Alex-Evo I've noticed on iOS when a device gets into this state trying to press our 'Connect' button this error will will persist and doesn't seem to resolve itself. If I transition away from the connection screen and back though it will work as intended.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/pauldemarco/flutter_blue/issues/497#issuecomment-648294035, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIG47W3MFIENBFKOOUNQTYLRYDOKPANCNFSM4KWXKFSQ .

darrendavidhumphrey avatar Jun 23 '20 20:06 darrendavidhumphrey

@mbaz2: Can you share what happens code-wise in your application when you a) transition to your connection screen b) press your connect button c) transition away from your connection screen

Maybe there are some pointers in there that would help us either find a work-around or identify the core of the issue.

dusalex avatar Jun 24 '20 11:06 dusalex

I will try to create a minimal app that demonstrates the issue.

On Wed, Jun 24, 2020 at 7:35 AM Alex-Evo [email protected] wrote:

@mbaz2 https://github.com/mbaz2: Can you share what happens code-wise in your application when you a) transition to your connection screen b) press your connect button c) transition away from your connection screen

Maybe there are some pointers in there that would help us either find a work-around or identify the core of the issue.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/pauldemarco/flutter_blue/issues/497#issuecomment-648766794, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIG47W3AQUEGQW5KXT5VY73RYHQJ5ANCNFSM4KWXKFSQ .

darrendavidhumphrey avatar Jun 24 '20 15:06 darrendavidhumphrey

I have a potential workaround - see code below.

I suspect there is some caching or other state that isn't being cleaned up properly. When I force recreate the FlutterBlue.instance the problem goes away (in my particular implementation at least). I saw this error when trying to reconnect to BT after the app resumes from background state, which I was doing so I could clear the BT connection while not in active use.

My flow was:

  1. Init & scan etc
  2. Connect device
  3. Discover services & Characteristics etc
  4. Do stuff
  5. Disconnect all BT devices (triggered by app entering background 'paused' state)
  6. Resume app
  7. Init and scan etc => note: after finding the correct device (and before connecting or calling discover) it still had the list of Services & Characteristics that were found previously... this is a red flag (these should be empty).
  8. Connect device ==> PlatformException(connect, Peripheral not found, null)

My workaround is to add this BlowItUp method to the FluttereBlue class and call it before getting FlutterBlue.instance whenever I connect to BT. This ensures each time I try to reconnect I get a freshly instantiated FlutterBlue.

  static FlutterBlue _instance = new FlutterBlue._();
  static FlutterBlue get instance => _instance;

  static BlowItUp() {
    _instance = new FlutterBlue._();
  }

This isn't ideal given FlutterBlue is designed as a singleton, and there may be side effects, but for now it's working for me.

Huacanacha avatar Jul 15 '20 01:07 Huacanacha

Very interesting finding @Huacanacha - sounds like something does not get properly (re-)initialized. Maybe this helps us get to the bottom of the issue...

I will also try your workaround to see if this helps in our case as well.

dusalex avatar Jul 16 '20 07:07 dusalex

Hi,

I have forked the lib, added this workaround, and testing it on android device-works, but on iphone 4s the error ramains. Maybe I am doing something wrong, has anyone else managed to remove this error.

JUREXT avatar Aug 06 '20 15:08 JUREXT

@JUREXT I have used this workaround for iPhone 8 and iPhone 11 devices so as far as I know it works for iOS. Not sure if it may be an issue with older hardware or iOS versions - have you tested on a more recent iOS device?

Huacanacha avatar Aug 06 '20 21:08 Huacanacha

@Huacanacha I have only iphone 4s for testing currently. Will try it on newer version, but have to get a phone first.

JUREXT avatar Aug 07 '20 08:08 JUREXT

@Huacanacha I was thinking, do you maybe have a forked version of this lib, where you say it works, could you give me the link, so I can test in my test app, to see have it behaves.

JUREXT avatar Aug 07 '20 10:08 JUREXT

@JUREXT no I didn't fork. I just fixed locally given I see this as a temporary workaround. The commit in your fork looks the same as what I have in my local flutter_blue code. I do also make sure to stopScan() and disconnect all devices before recreating the instance... something like this:

var flutterBlue = FlutterBlue.instance;
await flutterBlue.stopScan();
for (var device in await flutterBlue.connectedDevices) {
  await device.disconnect();
}

Huacanacha avatar Aug 07 '20 20:08 Huacanacha

@Huacanacha Thank you.

JUREXT avatar Aug 08 '20 14:08 JUREXT

Hi, PlatformException(connect, Peripheral not found, null) i also have the error at method connect, only in ios, anyone knows how to fix it?

yiguozhen0510 avatar Sep 11 '20 09:09 yiguozhen0510

Hi, PlatformException(connect, Peripheral not found, null) i also have the error at method connect, only in ios, anyone knows how to fix it?

Did you try my workaround?

Huacanacha avatar Sep 11 '20 23:09 Huacanacha

Is any update here? Is there an wokaround without forking?

aBuder avatar Nov 04 '20 14:11 aBuder

I'm also occasionally experiencing this issue with a macos app. I'd love to get an update on this!

BananaNeil avatar Feb 01 '21 03:02 BananaNeil

https://github.com/joankabello/flutter_blue

I made some fixes on this forked repo. It fixed the issue with the PlatformException.

joankabello avatar Feb 01 '21 10:02 joankabello

@joankabello would be nice if you made a PR with the fix into this repo. And maybe explain what the issue was?

jlubeck avatar Mar 04 '21 20:03 jlubeck