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

requestDevice filter does not find Heart Rate belt #289

Open
Abasz opened this issue Jan 22, 2025 · 14 comments
Open

requestDevice filter does not find Heart Rate belt #289

Abasz opened this issue Jan 22, 2025 · 14 comments

Comments

@Abasz
Copy link

Abasz commented Jan 22, 2025

I am trying to connect to a Polar HR belt using the example code (heartrate.js).

But actually request device does not seem to find any device by the serviceUUID. I checked this in nRF connect and the service UUID seems to be advertised properly, not to mention that any other device is able to find it (even webbluetooth in chrome)

Image

EDIT:

I am on linux

@thegecko
Copy link
Owner

thegecko commented Feb 1, 2025

Thanks for raising this. Can you confirm if your code works as expected using webbluetooth in chrome?

@Abasz
Copy link
Author

Abasz commented Feb 1, 2025

Native web bluetooth (navigator.bluetooth) works in chrome yes. This device is found as a HRM.

@thegecko
Copy link
Owner

thegecko commented Feb 15, 2025

This is a challenge to investigate without a heart rate monitor available!

Does the device appear when listing nearby devices and their adverts?

node examples/selector.js

@Abasz
Copy link
Author

Abasz commented Feb 16, 2025

Yes, infact it does:

Image

I suspect that when the request device with filter is searching it does not see the advertisement data and filters the strap out:

Image

Here you can see that the device is found but discarded when calling the validDevice function with the serviceUUID. As you can see buildBluetoothDevice does not see the service UUID in advertisement data. I am not sure why this happens, I dont know muhc about Dbus and Bluez.

@thegecko
Copy link
Owner

thegecko commented Feb 16, 2025

I think we lost the ability to detect advertisements when the library was switched from noble(deprecated) to SimpleBLE.

Version v2.2.0 of this library was the last release to use noble, would you mind trying with that version to confirm my suspicion?

@Abasz
Copy link
Author

Abasz commented Feb 17, 2025

I only see 2.1.0 version as a tag and as a release.

Besides NoBLE will not work with our application, we are also trying to move away from bleno and noble :)

But for the sake of completeness I will do the test shortly.

@Abasz
Copy link
Author

Abasz commented Feb 17, 2025

I am not able to do the test with noble as the noble.state returns "unknown" in the adapter's startScan method after calling init.

Bluetooth service is running:

● bluetooth.service - Bluetooth service
     Loaded: loaded (/lib/systemd/system/bluetooth.service; disabled; preset: enabled)
     Active: active (running) since Mon 2025-02-17 15:07:07 CET; 2min 39s ago
       Docs: man:bluetoothd(8)
   Main PID: 31783 (bluetoothd)
     Status: "Running"
      Tasks: 1 (limit: 3929)
        CPU: 81ms
     CGroup: /system.slice/bluetooth.service
             └─31783 /usr/libexec/bluetooth/bluetoothd

If I stop this service, the noble.state returns "powerOff".

@thegecko
Copy link
Owner

Hmm, I retested the noble version on my mac and it was still working.

If we can't get that to work, next step would be to see if SimpleBLE now supports advertisements and look to update that dependency...

@thegecko
Copy link
Owner

OK, a bit more digging into this and I can't see why the advertised service isn't shown when you run the selector example.

In case its a problem with SimpleBLE, I've updated this project to use the latest SimpleBLE release in this branch:

https://github.com/thegecko/webbluetooth/tree/simpleble-upgrade

Are you able to try it out?

Another option would be to try the old noble release on a mac or windows?

@Abasz
Copy link
Author

Abasz commented Feb 19, 2025

Ok, good news is that with this update things are working! Both the selector and the heartrate exmple. (I did a back and forth test between update branch and main and the latter never works, while the former always does).

I am pretty sure that some times in the past year Rpi kernel changed that rendered bleno and noble very unstable in its cooperation mode (i.e. when Rpi acts like central and peripheral at the same time). This worked fine in previous Rpi kernel versions.

So it is well possible that SimpleBLE needed update as well on the Dbus too. But also looking at release notes of SimpleBLE v0.7.0 there is a change:

(Linux) Use correct UUIDs for advertized services. (Thanks Symbitic!)

And your library used 6.x I think on the main branch

@Abasz
Copy link
Author

Abasz commented Feb 19, 2025

I spoke too fast. Now I am able to connect, but not able to start notifications:

Image

I will need to do more indepth lonnging to see where things go south. One thing for sure is that after abort is called the connection is not terminated so device is not visible until I restart the linux bluetooth service.

@thegecko
Copy link
Owner

When upgrading, I got each version to work as I went.

Image

Version 8 introduced a different callback signature for notifications, so if the fix you need is in v7, you could try commit #106e859

@Abasz
Copy link
Author

Abasz commented Feb 21, 2025

I have the same abort error for every version. I will run a more detailed logging to check where exactly things fail over the weekend.

@Abasz
Copy link
Author

Abasz commented Feb 22, 2025

Ok, I have sent my self on a wild-goose chase with this one as actually the "Abort" was due to the node process exiting naturally while the back service (C++) was doing staff...

Not sure why the node process exited while being subscribed to events on the characteristics (having an eventlistener should have kept the process alive in my view) but it did (Node version 20.28.3).

So once I added a setTimeout after the try catch block it kept the process alive (and changed the event properties, data started to flow in...

So I confirm that the newer SimpleBLE works as expected with the updated SimpleBLE (0.9.x)

Just for reference:

const { server } = require("typescript");

const bluetooth = require("../").bluetooth;

const process = require("process");

let bleServer;
let device;

process.on("SIGINT",async ()=>{
	await device?.forget();
	bleServer?.disconnect();
	process.exit(0);
});

process.on("SIGTERM",async ()=>{
	await device?.forget();
	bleServer?.disconnect();
	process.exit(0);
});

(async () => {
	try {
		console.log("Requesting Bluetooth Devices...");

		const device = await bluetooth.requestDevice({
			filters: [{ services: [ "heart_rate" ] }]
		});
		console.log(`Found device: ${device.name}`);

		bleServer = await device.gatt.connect();
		console.log(`Gatt server connected: ${bleServer.connected}`);
		
		const service = await bleServer.getPrimaryService("heart_rate");
		console.log(`Primary service: ${service.uuid}`);

		const characteristic = await service.getCharacteristic("heart_rate_measurement");
		console.log(`Characteristic: ${characteristic.uuid}`);

		await characteristic.startNotifications();
		console.log("Notifications started");

		characteristic.addEventListener("characteristicvaluechanged", event => {
			if (!event.target._value.byteLength) {
				return;
			}
			
			const data = event.target._value;
			let index = 0;
			const flags = data.getUint8(index++);
			let heartRate;
		
			if (flags & 0x01) {
				heartRate = data.getUint16(index, true);
				index += 2;
			} else {
				heartRate = data.getUint8(index++);
			}
			
			console.log(heartRate);
		});
	} catch(error) {
		console.log("Catch: ",error);
		await device?.forget();
		bleServer?.disconnect();
		process.exit(1);
	};

	setTimeout(async ()=>{
		await device?.forget();
		bleServer?.disconnect();
		console.log("clsing application")
	}, 1000000);
})();

The only issue remains is that it is not able to connect to my forerunner 255 HR broadcast (not even with selector.js). It is able to detect the device (correctly determining that its a HR device) but connection fails:

1: Forerunner
        Advertising: 00001800-0000-1000-8000-00805f9b34fb,00001801-0000-1000-8000-00805f9b34fb,0000180d-0000-1000-8000-00805f9b34fb,00001814-0000-1000-8000-00805f9b34fb,00003802-0000-1000-8000-00805f9b34fb,6a4e2800-667b-11e3-949a-0800200c9a66,6a4e8022-667b-11e3-949a-0800200c9a66,cc353442-be58-4ea2-876e-11d8d6976366
2: Unknown or Unsupported Device (3E:3E:9A:73:DF:4E)
connecting...

Error: Connect failed
    at SimplebleAdapter.<anonymous> (/opt/webbluetooth/dist/adapters/simpleble-adapter.js:310:27)
    at step (/opt/webbluetooth/dist/adapters/simpleble-adapter.js:72:23)
    at Object.next (/opt/webbluetooth/dist/adapters/simpleble-adapter.js:53:53)
    at /opt/webbluetooth/dist/adapters/simpleble-adapter.js:47:71
    at new Promise (<anonymous>)
    at __awaiter (/opt/webbluetooth/dist/adapters/simpleble-adapter.js:43:12)
    at SimplebleAdapter.connect (/opt/webbluetooth/dist/adapters/simpleble-adapter.js:298:16)
    at BluetoothRemoteGATTServerImpl.<anonymous> (/opt/webbluetooth/dist/server.js:110:65)
    at step (/opt/webbluetooth/dist/server.js:57:23)
    at Object.next (/opt/webbluetooth/dist/server.js:38:53)

Actually we had the same issue with noble/bleno (HR strap of polar worked, watch not)

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

2 participants