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

Peripheral disconnects the device in connection #111

Open
vsnikkil opened this issue Dec 2, 2014 · 24 comments
Open

Peripheral disconnects the device in connection #111

vsnikkil opened this issue Dec 2, 2014 · 24 comments

Comments

@vsnikkil
Copy link

vsnikkil commented Dec 2, 2014

Hello,

I am connecting to a peripheral but it disconnects the noble in the connection (GATT server sends the disconnection I think). Noble doesn't notice this and gets stuck:

noble.on('discover', function(p) {
  p.discoverSerivces(null, function(err, service) {
    // gets stuck here
  });
});

How to prevent noble from getting stuck?

Thanks, Vesa

@tompropst
Copy link

@vsnikkil, are you explicitly connecting to the peripheral before attempting discoverServices?

noble.on('discover', function(p) {
  p.connect(function(err) {
    p.discoverSerivces(null, function(err, service) {
      // gets stuck here
    });
  });
});

@sandeepmistry
Copy link
Collaborator

@tompropst thanks!

@vsnikkil there is also a disconnect event:

p.connect(function(err) {
  // ...

  p.once('disconnect', function() {
    // do something
  });
});

@vsnikkil
Copy link
Author

vsnikkil commented Dec 8, 2014

@sandeepmistry thank you, that works. What should I put inside the disconnect event function to stop execution of discoverServices() function?

@tompropst
Copy link

@vsnikkil,
discoverServices does not run indefinitely. Once it interrogates the BLE device for its services, it terminates. You can use the callback to know when it is done.

@vsnikkil
Copy link
Author

vsnikkil commented Dec 9, 2014

@tompropst in my case the discoverService doesn't call the callback function but is stuck somewhere inside the function

@tompropst
Copy link

@vsnikkil, are you checking the error status on the connect call? I'd be happy to try and help if you want to share your code.

@vsnikkil
Copy link
Author

@tompropst, thanks!

yes, I check the errors in p.connect:

p.connect(err) {
  if(err) console.log(err); // No errors ever occurred here
  p.discoverServices(null, function(err, services) {
    // Does not execute
    // Gets stuck inside the discoverServices before callback is called
  });
}

The used BLE peripheral was faulty (physical problems) and it disconnected noble quite often. p.once('disconnect', ...) resolved my problem but I'm not sure if the program will consume memory because I guess node is still executing discoverServices function

@tompropst
Copy link

@vsnikkil,
Is that your actual code? If so, it looks like you're missing the propper connect callback function definition. If the code runs, you may be seeing the discoverServices start before connect succeeds.

Try:

p.connect(function(err) {
  if(err) console.log(err);
  else p.discoverServices(null, function(err, services) {
    console.log("Discover complete");
  });
});

@vsnikkil
Copy link
Author

@tompropst, thanks!
Sorry, my code example was flawed. Yes, I have exactly that code you wrote and I never get inside the callback in discoverServices. I mean the discoverServices function does not call the callback function and I never get notification "Discover complete". Here I attached a picture of what happens in BLE traffic that I logged with WireShark.

You see, the device is disconnected during the discovery procedure and noble gets stuck inside the discoverService function and it doesn't call the callback function. This is the problem. This can be bypassed with disconnect event as @sandeepmistry suggested.

untitled

@tompropst
Copy link

@vsnikkil, I'm not an expert in the BLE protocol but I suspect that the MTU request just before the disconnection is part of the connection flow and not part of the service discovery. Do you know? MTU stands for "Maximum Transmission Units" which needs to be established between the two devices.

Have you confirmed that the discoverServices call is being made? Or perhaps is the connection not established and hence the discoverServices isn't being called?

If you're sure that it is being called, I'm afraid I don't know how to diagnose the underlying l2cap-ble module.

@vsnikkil
Copy link
Author

@tompropst thanks again,

exchanging Rx MTUs isn't very important here. Devices just exchange MTU sizes (my device has 23) and minimum will be used of these (23). The log just shows that there is a disconnection without any apparent reason and it got noble stuck.

Yes, I have made very sure discoverServices is being called.

@sandeepmistry
Copy link
Collaborator

@vsnikkil MTU exchange is very important, it looks like you device doesn't like it at all and disconnects. What are you trying to connect to?

noble emits the connect event before MTU exchange is complete.

Also, there is not much error handling in noble currently, so the discoverServices callback will never get called in this case. There will be a lingering listener leak.

Btw, did you get Wireshark working with BLE on Linux?

@vsnikkil
Copy link
Author

@sandeepmistry, thanks!

Yes I got WireShark work on linux. Just grabbed the newest version of it from git repository (BLE is quite new addition). I remember it had some dependencies that wasn't 100% straight forward to install.

The sensor had some internal radio problems in it, which caused it to disconnect noble. Sometimes it worked perfectly. That log is just an example. Exchanging MTUs works sometimes too, the device will response with packet size of 23. Sometimes service discovery works but reading the characteristic won't and it gets stuck there.

Thanks!

@sandeepmistry
Copy link
Collaborator

@vsnikkil interesting, is it more reliable closer to your PC (or whatever your are using noble on)?

Is there anything else I can help out on for this issue?

@vsnikkil
Copy link
Author

@sandeepmistry, thanks again

The device function was totally random. The device has been fixed and now it works very well. I am still curious if the discoverService function call eats memory when I use the disconnect event to prevent noble getting stuck. How could I stop the discoverServices function?

@sandeepmistry
Copy link
Collaborator

@vsnikkil one way to fix this, is with the following code change in peripheral.js:

Peripheral.prototype.discoverServices = function(uuids, callback) {
  var servicesDiscoverCallback = function(services) {
    this.removeListener('disconnect', disconnectCallback);
    callback(null, services);
  };

  var disconnectCallback = function() {
    this.removeListener('servicesDiscover', servicesDiscoverCallback);
    callback(new Error('peripheral disconnected'));
  }.bind(this);

  if (callback) {
    this.once('servicesDiscover', servicesDiscoverCallback);
    this.once('disconnect', disconnectCallback);
  }

  this._noble.discoverServices(this.uuid, uuids);
};

This would have to be done for methods in peripheral.js, service.js, characteristic.js, and descriptor.js - as the peripheral could disconnect during any method calls. A bit messy ... I'll try to think of a better way.

@theavijitsarkar
Copy link

@sandeepmistry Did you find a better way..This is really an issue..I have a faulty device, which behaves randomly...

@sandeepmistry
Copy link
Collaborator

I haven't looked at this for a while. It might be better if the hci-socket GATT layer handles this. Need to check what the behaviour on OS X is ...

@paulgavrikov
Copy link

I have that problem too. Sometimes it helps to unplug the Dongle and replug it again. Sometimes two exactly the same Dongle work differently: one works, one doesn't.

I found out that the disconnect happen after connection but before mtu exchange. Unfortunately neither hcidump nor your hci-bluetooth-socket debug log helps me to investigate further.

I saw somebody mentioning that authorization might be a problem. Could that be?

Here's the interesting part:

2016-02-17 10:38:57.454666 > HCI Event: LE Meta Event (0x3e) plen 12
    LE Read Remote Used Features Complete
      status 0x00 handle 64
      Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00

2016-02-17 10:38:59.445869 < HCI Command: Disconnect (0x01|0x0006) plen 3
    handle 64 reason 0x13
    Reason: Remote User Terminated Connection

Here's how a working dump looks:

2016-02-17 10:40:29.812468 > HCI Event: LE Meta Event (0x3e) plen 12
    LE Read Remote Used Features Complete
      status 0x00 handle 64
      Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00


2016-02-17 10:40:29.852652 < ACL data: handle 64 flags 0x00 dlen 7
    ATT: MTU req (0x02)
      client rx mtu 256
2016-02-17 10:40:29.872102 > ACL data: handle 64 flags 0x02 dlen 7
    ATT: MTU resp (0x03)
      server rx mtu 23
2016-02-17 10:40:29.882298 < ACL data: handle 64 flags 0x00 dlen 11
    ATT: Read By Group req (0x10)
      start 0x0001, end 0xffff
      type-uuid 0x2800

Here is a hciconfig dump of two hci dongles - 1 works 1 doesn't.. as you can see they are similar.

hci2:   Type: BR/EDR  Bus: USB
    BD Address: 5C:F3:70:75:D3:E0  ACL MTU: 1021:8  SCO MTU: 64:1
    UP RUNNING 
    RX bytes:6816 acl:68 sco:0 events:321 errors:0
    TX bytes:1879 acl:68 sco:0 commands:101 errors:0
    Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
    Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 
    Link policy: RSWITCH SNIFF 
    Link mode: SLAVE ACCEPT 
    Name: 'BCM20702A'
    Class: 0x000000
    Service Classes: Unspecified
    Device Class: Miscellaneous, 
    HCI Version: 4.0 (0x6)  Revision: 0x1000
    LMP Version: 4.0 (0x6)  Subversion: 0x220e
    Manufacturer: Broadcom Corporation (15)

hci1:   Type: BR/EDR  Bus: USB
    BD Address: 5C:F3:70:6E:57:93  ACL MTU: 1021:8  SCO MTU: 64:1
    UP RUNNING 
    RX bytes:2451 acl:0 sco:0 events:199 errors:0
    TX bytes:1316 acl:6 sco:0 commands:142 errors:0
    Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
    Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 
    Link policy: RSWITCH SNIFF 
    Link mode: SLAVE ACCEPT 
    Name: 'BCM20702A'
    Class: 0x000000
    Service Classes: Unspecified
    Device Class: Miscellaneous, 
    HCI Version: 4.0 (0x6)  Revision: 0x1000
    LMP Version: 4.0 (0x6)  Subversion: 0x220e
    Manufacturer: Broadcom Corporation (15)

@paulgavrikov
Copy link

Is there maybe a workaround such as a hardreset of bluez or something similar? I tried resetting the hci device, but that didn't work.

@brettdaman
Copy link

I want to use noble in a prototype embedded device, and sometimes I got this issue. Restarting the ble or the device is something I want to avoid. Did someone manage to fix it. I saw the code snipped above but that is only for the peripheral.

@rzr
Copy link

rzr commented May 14, 2020

@rzr
Copy link

rzr commented Sep 6, 2020

Relate-to: #923 (comment)

@rzr
Copy link

rzr commented Jan 26, 2021

It looks the maintenance of this project is in pause, but feel free to contribute to @abandonware fork until upstream is active again

Feel free to comment:
abandonware#2

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

7 participants