noble / noble

A Node.js BLE (Bluetooth Low Energy) central module
MIT License
3.4k stars 867 forks source link

multiple processes #835

Open btsimonh opened 5 years ago

btsimonh commented 5 years ago

Hi, when running multiple processes, noble seems to see activity from the other process, and neither process works well. I'm using the noble-device wrapper... Hardware: Rpi3 Raspberian with bluez 5.48 (the upgrade to 5.48 from 5.43 resolved a number of other multi-device issues).

Examples: a single process can detect and talk to 2 devices (eq3 valves). I'm using a 'connect, read, disconnect, wait 40s, repeat' scheme. If I start a second of the same process, the first process died with: (this is the first time i've seen it die!)

connecting 00:1a:22:09:2c:9a
/home/pi/.node-red/node_modules/noble/lib/hci-socket/gatt.js:618
  var characteristic = this._characteristics[serviceUuid][characteristicUuid];
                                                      ^

TypeError: Cannot read property 'd0e8434dcd290996af416c90f4e0eb2a' of undefined
    at Gatt.notify (/home/pi/.node-red/node_modules/noble/lib/hci-socket/gatt.js:618:58)
    at NobleBindings.notify (/home/pi/.node-red/node_modules/noble/lib/hci-socket/bindings.js:398:10)
    at Noble.notify (/home/pi/.node-red/node_modules/noble/lib/noble.js:353:19)
    at Characteristic.notify (/home/pi/.node-red/node_modules/noble/lib/characteristic.js:106:15)
    at EQ3BLE.NobleDevice.notifyCharacteristic (/home/pi/.node-red/node_modules/noble-device/lib/noble-device.js:134:18)
    at NobleDevice.connectAndSetup.call (/home/pi/.node-red/node_modules/node-red-contrib-eq3-bluetooth/lib/eq3device.js:69:12)
    at EQ3BLE.<anonymous> (/home/pi/.node-red/node_modules/noble-device/lib/noble-device.js:83:7)
    at EQ3BLE.<anonymous> (/home/pi/.node-red/node_modules/noble-device/lib/noble-device.js:71:5)
    at Peripheral.<anonymous> (/home/pi/.node-red/node_modules/noble/lib/peripheral.js:101:13)
    at Service.<anonymous> (/home/pi/.node-red/node_modules/noble/lib/service.js:53:7)

and the second process worked correctly.

If I re-run the first process, it sees the device(s), but reports:

connecting 00:1a:22:09:2c:db
connectThenSetup err :Error: Command Disallowed (0xc)

and the second process can no longer connect to devices (connect does not succeed within 10s, and I cancel it with disconnect). If I then stop the first process again, the second process resumes normal operations.

I also see:

noble: unknown peripheral 001a22092cdb connected!

and other 'cross application' messages (I assume it hears everything happening on the bluetooth);

Q: is it meant to be able to work from multiple processes? Should I/will it help to stop noble completely in my 40s between polls, and randomise the polling, and just deal with times it does not work?

I notice there is also an interaction between noble and hcitool (e.g. when I connect to a device in noble, hciscan drops out. Is this normal? - or is my bluez stack still no good?

oyooyo commented 5 years ago

I experience similar issues. While running a Node.js application using noble (on Kubuntu 18.04), other programs trying to use Bluetooth LE show strange problems.

For example, while running the following minimalistic script (which does hardly anything - no scanning, no communicating with Bluetooth devices):

var noble = require('noble');

noble.on('stateChange', function(state) {
  if (state === 'poweredOn') {
    console.log('powered on');
  }
});

a webpage using Web Bluetooth in Chrome no longer works properly; it will throw an "Error: GATT operation failed for unknown reasons" error. As soon as I cancel the above script, the webpage in Chrome using Web Bluetooth works properly.

ggsubs commented 5 years ago

Confirmed on Bluez version 5.23-2+rpi2 and bleno 0.5.0 and bluetooth-hci-socket 0.5.1.

If a concurrent process uses HCI the following "uh, oh" message appears in debug:

  att 78:9c:85:04:8d:6e: write: 100100ffff0028 +1ms
  hci write acl data pkt - writing: 0240000b0007000400100100ffff0028 +1ms
  hci onSocketData: 024020070003000400030001 +7ms
  hci   event type = 2 +0ms
  hci       cid = 4 +1ms
  hci       handle = 64 +0ms
  hci       data = 030001 +1ms
  hci onSocketData: 0240201b001a000400110601000500001806000600011807000f000a18100020 +13ms
  hci   event type = 2 +1ms
  hci       cid = 4 +0ms
  hci onSocketData: 02401003000024fe +1ms
  hci   event type = 2 +0ms
  att 78:9c:85:04:8d:6e: uh oh, no current command +3ms
  hci onSocketData: 04050400400013 +30s
  hci   event type = 4 +1ms
  hci   sub event type = 5 +1ms
  hci       handle = 64 +0ms
  hci       reason = 19 +1ms
henfri commented 5 years ago

Hello,

I am also experiencing this issue. Is there a workaround?

Greetings, Hendrik

sasha-stojanovic commented 4 years ago

@btsimonh @henfri did you guys sort this out? I'm having the exact same issue on a raspberry pi zero with two separate processes that are trying to find different BLE profiles.

henfri commented 4 years ago

Unfortunately not

btsimonh commented 4 years ago

@sasha-stojanovic - I have put it to one side hoping the stack will be updated at some point in the future. Not tested recently. Certainly bluez was in flux when I was trying. If you download and build the very latest (hopefully it's moved on from 5.48), please do let us know your results...

arthare commented 4 years ago

I have a raspi 4 running bluez 5.50, and still get this issue. I was hoping to be able to run a bunch of simple processes to talk to a bunch of different BLE devices, but as soon as I go from spawning 1 at a time to spawning 2 at a time, they start throwing all kinds of weird errors I haven't seen before.

arthare commented 4 years ago

I spent a bunch of time working on getting this working, and have gotten surprisingly close.

What I did: -Started from ws-slave, which runs a websocket-based server for other processes to talk to. -Made it recognize each incoming websocket as a unique "context" with its own unique set of connections and requests. -Reorganized a bunch of the listeners to take into account this "context" concept.

How does it do? -Actually works very well, except for scanning for new devices concurrently with doing other bluetooth operations. Anytime a scan-for-new-devices is going on, it completely hoses all other BLE operations. If you could make your multiple processes coordinate their scanning sequence so they all scan, find their devices, and only then proceed to do their bluetooth stuff, then this would work.

Other tip: -Doing my BLE work in ws-slave separate from my main process really helped my pace of development because it made it easy to debug noble-only problems. It also meant that my master process can destroy and restart the ws-slave process at will in case it messes up.

You can take a look at https://github.com/arthare/noble