microsoft / Windows-universal-samples

API samples for the Universal Windows Platform.
MIT License
9.53k stars 7.97k forks source link

How does the DeviceWatcher actually work with respect to discovering bluetooth LE devices #1089

Closed brianreinhold closed 4 years ago

brianreinhold commented 5 years ago

I started with the C++/winRT example BluetoothLE Scenario1_Discovery.cpp and closed issue #513 and #932. What makes using the API so difficult is probably that it is so generic and one must learn what the meaning and definitions of numerous Microsoft unique fields are like Properties which has esoteric names like System.Devices.Aep.DeviceAddress with a very limited description of what the consequences of these strings are when used in the DeviceWatcher. In addition there is this L"(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")" string (the above from the example) which is completely undocumented. The example is very terse in its explanation of the parameters and their effects (the hard part) which makes using these API very confusing (especially when coming from a much more straight forward type of API as provided in embedded systems or Android.

What I wanted to do was simulate the simple LE advertisement watcher which does exactly what I expect it to do; its just that I cannot connect to a discovered device using that method (even though the discovered adv IS connectable. So now the DeviceWatcher First I try the createWatcher(string) only. The mysterious ProtocolID above. Result? Immediate signal of the enumeration completed callback and no ability to discover an advertising BTLE device. Okay, next I add that list of properties. Same result. Immediate enumeration stop, and no discovery of any devices. Now add the association kind. No immediate enumeration stop. I do discover devices BUT there is a catch. If the device was discovered previously (and is not active) it is STILL reported even though the Properties contains the System.Devices.Aep.IsPresent is included. It will get removed. And then one can re-discover it. But it will not get removed, even though the device stops advertising. Then I can only discover that once; a restart of the device is not shown. A stop and restart does not re-discover the device.

The Advertisement watcher is SOOOO much cleaner I would love to throw the DeviceWatcher in the trash and use the advertisement watcher ... if I could only connect. Or maybe microsoft could clearly document how the DeviceWatcher is used for BTLE devices and what all the parameters do (and what are the default behaviors when various fields are NOT included...

FrankGorgenyi commented 5 years ago

Hey @gabrielfreire,

Thank-you for the well taken trace file.

The trace shows that your query is not returning devices, likely looking for devices, those only exist for paired devices. It think the code you have and what you want to do are unaligned.

If you're trying to perform a continuous long running query for unpaired devices you need to watch for advertisements specifically (this is most efficient and can be long running). You would use the BluetoothLEAdvertisement watcher and look for a pattern that matches your expectations and is connectable.

If you're looking to perform a short running query to look for a device to pair with look explicitly for unpaired devices using selector returned from BluetoothLEDevice.GetDeviceSelectorFromPairingState(Boolean pairingState) on DeviceWatcher.

Both require your device to be advertising as connectable (an example is pairing mode).

Please can you try using either of those methods and if it still fails return another trace file? :)

Thanks, Fg

gabrielfreire commented 5 years ago

Hi @FrankGorgenyi ,

Thank you very much for your help, using the BluetoothLEAdvertisementWatcher did it. Now my device gets properly listed and i can apply it's protocol as expected.

Thanks.