node-ble icon indicating copy to clipboard operation
node-ble copied to clipboard

Cannot get notifications from HCI service

Open DrCWO opened this issue 8 months ago • 2 comments

Hi out there, I got an issue I cannot solve by myself so some help would be appreciated. Here my configuration.

I am on a Raspberry with Raspbian. I have a Microsoft Surface Dial (which is a HCI device). The Surface Dial is paired with the Raspberry. I did this with bluetoothctl.

I like to get notifications directly from D-Bus so I disabled the HCI service in /lib/systemd/system/bluetooth.service by setting ExecStart=/usr/libexec/bluetooth/bluetoothd --noplugin=sap,input,hog to be able to access the HCI service via D-Bus.

In my first implementation I used RAW HCI to get the data but after a disconnect of the device it takes more than three seconds after touching the Surface Dial until the HCI-Service was available again. This is much to long as rotating the dial a sudden reaction must occur. This is why I tried to use D-Bus. So in this implementation here I get the connect event immediately but I was not able to get the data any more 👎

I used the code below to get notification from the HCI Report Characteristic of the Surface Dial but it failed:

var deviceUuid = '70:BC:10:87:C1:B8';
var genericServiceUuid = '1812';
var genericCharacteristicUuid = '2a4d';


async function startBleServer() {

	console.log('************************************** Start BLE-Server: ' + deviceUuid);

	var { createBluetooth } = require('node-ble');
	var { bluetooth, destroy } = createBluetooth();
	var adapter = await bluetooth.defaultAdapter();
	console.log('adapter: ');

	// discover surfache Dial
	if (! await adapter.isDiscovering()) {
		console.log('Start discovery: ');
		await adapter.startDiscovery()
	}

	console.log('Wait for device: ' + deviceUuid);
	var device = await adapter.waitDevice(deviceUuid);

	device.on('disconnect', function () {
		console.log('######## Ble >>>>> EVENT: ' + 'Device disconnected');
	})

	device.on('connect', function () {
		console.log('######## Ble >>>>> EVENT: ' + 'Device connected');
	})

	console.log('stop discovery');
	await adapter.stopDiscovery()

	console.log('discovered, wait till connected');
	await device.connect()


	console.log('connected, wait for GATT server');
	var gattServer = await device.gatt();
	console.log('gatt server ready!');

	// Get service UUIDs and search for service 1812
	var myServices = await gattServer.services();
	var hciServiceUuid = null;
	for (var i = 0; i < myServices.length; i++) {
		if (myServices[i].indexOf(genericServiceUuid + '-') >= 0) hciServiceUuid = myServices[i];
	}
	console.log('HCI service UUID: ' + hciServiceUuid);

	// If I found the UUID of the HCI-Service get the HCI service
	if (hciServiceUuid) {

		//********************* get hciService
		var hciService = await gattServer.getPrimaryService(hciServiceUuid);
		console.log('Serice ' + hciServiceUuid + ' discovered');

		// get the characteristic UUIDs
		var myCharacteristics = await hciService.characteristics();
		console.log('Got HCI characteristic UUIDs');

		// find Reprt Characteristi UUIDs suchen
		var reportCharacteristicUuid = null;
		for (var i = 0; i < myCharacteristics.length; i++) {
			if (myCharacteristics[i].indexOf(genericCharacteristicUuid + '-') >= 0) reportCharacteristicUuid = myCharacteristics[i];
		}
		console.log('HCI Characteristic UUID' + reportCharacteristicUuid);

		// get Report Characteristic 
		var reportCharacteristic = await hciService.getCharacteristic(reportCharacteristicUuid);
		console.log('Report Characteristics ' + reportCharacteristicUuid + ' found');

		// Setup callback for Notifications
		reportCharacteristic.on('valuechanged', buffer => {
			console.log('Data received');
			console.log(buffer)
		})
		console.log('callback set');

		await reportCharacteristic.startNotifications();
		console.log('Notification started');

	}
}

startBleServer();

Running this code anything worked fine at the beginning. The service and the characteristic were found. But trying to setup the notification I get an error message. See output below:

root@DrCWO:/home/pi# node xx_ble.js
************************************** Start BLE-Server: 70:BC:10:87:C1:B8
adapter:
Start discovery:
Wait for device: 70:BC:10:87:C1:B8
stop discovery
discovered, wait till connected
######## Ble >>>>> EVENT: Device connected
connected, wait for GATT server
gatt server ready!
HCI service UUID: 00001812-0000-1000-8000-00805f9b34fb
Serice 00001812-0000-1000-8000-00805f9b34fb discovered
Got HCI characteristic UUIDs
HCI Characteristic UUID00002a4d-0000-1000-8000-00805f9b34fb
Report Characteristics 00002a4d-0000-1000-8000-00805f9b34fb found
callback set
/home/pi/rooExtend/node_modules/dbus-next/lib/bus.js:343
            return reject(new DBusError(reply.errorName, reply.body[0], reply));
                          ^

DBusError: Operation is not supported
    at _methodReturnHandlers.<computed> (/home/pi/rooExtend/node_modules/dbus-next/lib/bus.js:343:27)
    at handleMessage (/home/pi/rooExtend/node_modules/dbus-next/lib/bus.js:101:11)
    at EventEmitter.<anonymous> (/home/pi/rooExtend/node_modules/dbus-next/lib/bus.js:151:9)
    at EventEmitter.emit (node:events:513:28)
    at /home/pi/rooExtend/node_modules/dbus-next/lib/connection.js:132:14
    at USocket.<anonymous> (/home/pi/rooExtend/node_modules/dbus-next/lib/message.js:65:9)
    at USocket.emit (node:events:513:28)
    at emitReadable_ (node:internal/streams/readable:590:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:81:21) {
  type: 'org.bluez.Error.NotSupported',
  text: 'Operation is not supported',
  reply: Message {
    type: 3,
    _sent: false,
    _serial: 3374,
    path: undefined,
    interface: undefined,
    member: undefined,
    errorName: 'org.bluez.Error.NotSupported',
    replySerial: 100,
    destination: ':1.3859',
    sender: ':1.3820',
    signature: 's',
    body: [ 'Operation is not supported' ],
    flags: 1
  }
}

Node.js v18.7.0

Any idea why I cannot start the notification?

Best DrCWO

DrCWO avatar Nov 01 '23 16:11 DrCWO