UWP Bluetooth Communication: bluetoothDevice object is always set to null - bluetooth

I try to let PC and HoloLens communicate over Bluetooth RFCOMM so I'm writing a UWP App. I can get the device info and so the id with a device watcher. My problem is this line:
var bluetoothDevice = await BluetoothDevice.FromIdAsync(deviceInfo.Id);
My problem is that bluetoothDevice is always set to null althought that shouldn't be. Microsoft says in their RfcommChat Excample to this line:
// If we were unable to get a valid Bluetooth device object,
// it's most likely because the user has specified that all unpaired devices
// should not be interacted with.
But my PC and and my HoloLens are already paired. And I'm getting the same error no matter if I execute the App with my PC and using HoloLens to connect with or the HoloLens and using my PC to connect with.
Can anybody help?
Regards
Dustin

i found my mistake. I forgot to add bluetooth in the capabilities of package.appxmanifest:
<DeviceCapability Name="bluetooth" />
<DeviceCapability Name="bluetooth.rfcomm">
<Device Id="any">
<Function Type="serviceId:34B1CF4D-1069-4AD6-89B6-E161D79BE4D8" />
</Device>
</DeviceCapability>

Try to use FromBluetoothAddressAsync with MAC of just found/paired device instead cause Device.Id can be wrong or not set actually.

Related

Web Bluetooth Bypass Pairing Screen

The BLE Peripheral Simulator app, combined with the Web Bluetooth Samples, is a tremendous resource for developers.
Once a device is paired, is there any way through Web Bluetooth to bypass the pairing screen and go straight to the app?
Yes, this is possible. Code Source. Not my code though.
// Selected device object cache
let deviceCache = null;
// Launch Bluetooth device chooser and connect to the selected
function connect() {
return (deviceCache ? Promise.resolve(deviceCache) :
requestBluetoothDevice())
.then(device => connectDeviceAndCacheCharacteristic(device))
.then(characteristic => startNotifications(characteristic))
.catch(error => log(error));
function requestBluetoothDevice() {
log('Requesting bluetooth device...');
return navigator.bluetooth.requestDevice({
filters: [{services: [myService]}],
})
.then(device => {
log('"' + device.name + '" bluetooth device selected');
deviceCache = device;
// Listen for disconnet event
deviceCache.addEventListener('gattserverdisconnected',
handleDisconnection);
return deviceCache;
});
}
Also, there is a way of reconnecting after site refresh, but it is not implemented yet
I recently implemented a new permissions backend as well as two APIs that will enable previously permitted Bluetooth devices to be used.
The new permissions backend is implemented behind the chrome://flags/#enable-web-bluetooth-new-permissions-backend. The new backend will persist device permissions granted through requestDevice() until the permission is reset in Site Settings or the Page Info dialog box.
The getDevices() and watchAdvertisements() are implemented behind the chrome://flags/#enable-experimental-web-platform-features flag for Chrome 85.0.4165.0 or greater. The recommended use of these APIs is to use getDevices() to retrieve an array of permitted BluetoothDevices and then calling watchAdvertisements() on these devices to start a scan. When advertisement packets are detected from the devices, the advertisementreceived Event will be fired on the device that it corresponds to. At this point, the Bluetooth device is in range and can be connected to.
Please give this new feature a try, and file any bugs at https://crbug.com using the Blink>Bluetooth component.

UWP Bluetooth RFComm ConnectAsync problems

I am developing an application which makes Bluetooth (RFComm, SPP) connections with a device. My Android App works like a charm but with UWP I have big problems getting the connection done using:
socket.ConnectAsync(service.ConnectionHostName, service.ConnectionServiceName);
When the device is connected everything works.
Sometimes the ConnectAsync takes a long time (1 minute) or finally it doesnt work.
It seems like when I start the App the first connection works and connects within a vew seconds but all following connections seem to be very unstable.
I tried different USB Dongles, but with same results. I am now on Win 10 Pro 64 1709.
I also tried the UWP RFComm Chat sample app. Same problems there.
Does somebody have similar problems? Any ideas?
Thanks,
Joachim
A few updates:
I testet a few other Dongles and SPP Devices. My results:
One SPP Device works, two have this problem. A not working example: BluePort XP and ASUS USB-BT400
Using Virtual COM Ports over Win32 API or .net SerialPort works on all devices!
Conclusion: Hardware works. The problem is on UWP using socket.ConnectAsync!
Is this a Win10 UWP Bug??!!
Second update:
I found out that if I use Devices from:
DeviceInformationCollection collection = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));
and connect using rfcomm:
var services = await _device.GetRfcommServicesForIdAsync(RfcommServiceId.SerialPort, BluetoothCacheMode.Uncached);
var op = _socket.ConnectAsync(_service.ConnectionHostName, _service.ConnectionServiceName);
then I have this problems with connection times - manly after the first connect/disconnect phase
BUT: When I use the virtual com ports created from SPP Dongles
DeviceInformationCollection collection = await DeviceInformation.FindAllAsync("System.Devices.InterfaceClassGuid:=\"{86E0D1E0-8089-11D0-9CE4-08003E301F73}\" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True");
and create a SerialDevice using:
var serialDevice = await SerialDevice.FromIdAsync(info.Id);
which automatically connects the bluetooth target while this serialDevice is created, then everything works perfect.

Windows 10 - how to detect when a Bluetooth device is in range

I have previously paired with a Bluetooth device that supports RFCOMM.
When my app is opened I continuously try to connect to the device by opening the RFCOMM. This way my app automatically connects when the device comes in range.
deviceInfoCollection = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));
LogData(String.Format("Number of mldp devices is {0}", deviceInfoCollection.Count));
foreach (DeviceInformation deviceInfo in deviceInfoCollection)
{
LogData(String.Format("ID:{0}, NAME:{1}", deviceInfo.Id, deviceInfo.Name));
}
Then run this on a timer:
try
{
// The first time this method is invoked by a store app, it should be called
// from a UI thread in order to display the consent prompt
// https://msdn.microsoft.com/en-us/windows.devices.bluetooth.rfcomm.rfcommdeviceservice.fromidasync
RfcommDeviceService rfcommService = await RfcommDeviceService.FromIdAsync(deviceInfo.Id);
LogData(String.Format("ID:{0}, NAME:{1}", deviceInfo.Id, deviceInfo.Name));
}
catch (Exception)
{
LogData(String.Format("Can not request rfcomm service from device ID:{0}, NAME:{1}", deviceInfo.Id, deviceInfo.Name));
}
Is there any way to query when the device is in range , rather than trying to connect? I would prefer to only attempt connection when the device is in range.
For RFCOMM (BT2.0, BT2.1) you can run a device enumeration periodically, see also Get bluetooth devices in range
However your actual implementation with a connection attempt may work a little better.
For Bluetooth 4.0, you can listen to the advertisements of the BT module, see also https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/BluetoothAdvertisement
If you're talking to an embedded device (e.g. some robot, or homebrew appliances using RFCOMM) I am afraid there is no better solution than what you're doing.
If you're taking to a phone (which supports both BT4.0 and BT2.1) you can use the BT4 advertisements to signal the proximity of the device, then connect via RFCOMM.

Stream Audio to Bluetooth Device in C#

I am trying to stream Audio to a bluetooth device in-code in C#. I've picked up the 32feet.net library to help with this. I am able to get a bluetooth speaker paired just fine, and then I use the code below to connect to the device.
globalClient.BeginConnect(device.DeviceAddress, BluetoothService.SerialPort, new AsyncCallback(BluetoothConnectedAsyncHandler), device);
Async Callback method:
private void BluetoothConnectedAsyncHandler(IAsyncResult result)
{
BluetoothDeviceInfo connectedDevice = (BluetoothDeviceInfo)result.AsyncState;
globalClient.EndConnect(result);
if (result.IsCompleted)
{
NetworkStream btStream = globalClient.GetStream();
}
}
This all works well, but when I try to set the service from BluetoothService.SerialPort to BluetoothService.AudioSource, then I receive a SocketException on the "globalClient.EndConnect(result);" line saying "A socket operation failed because the destination host was down". See screenshot:
I've also tried to throw data at the speaker through the NetworkStream when it is setup with BluetoothService.SerialPort, but it doesn't play anything - no noise or static.
My running hypothesis is that this can't be done easily with 32feet.net, and I would have to code up the a2dp spec in code. I think the 32feet.net library is used so that I can tell the Operating System to use the speaker as an output device, rather than control audio output in-code as a supported feature.
Please help! Has anyone done this?
Would it even work if I sent an a2dp compliant stream to the device over the BluetoothService.SerialPort connection?
A2DP spec: https://www.bluetooth.org/docman/handlers/DownloadDoc.ashx?doc_id=8236
Thanks for any help!
Update:
This isn't possible within the 32feet.net library, you can only set the device up to talk the the Microsoft audio service using the setService method call in 32feet.net
www.nudoq.org/#!/Packages/32feet.NET/InTheHand.Net.Personal/MicrosoftSdpService/M/SetService
This MS service manages the A2DP output to the device. There is no way to directly output audio from code into the Bluetooth Device using this library in C#.

How to get information about CONNECTED bluetooth device for android?

If I have a Android phone which is already connected with a bluetooth headset (paired and connected) to it.
How I can get information about that specific headset.
Using getBondedDevices() method I get list of all paired devices..I need information about CONNECTED device only.
I can not wait for broadcast receiver to check status, because I need this information at the start of my application. So please suggest is there any way to get this information without waiting for broadcast.
You can do this through the IBluetoothA2dp interface in API 11 and up. Some more info on there is here: Android connect to a paired bluetooth headset
Here is a great resource to see the difference in what is available to this interface between API 10 and 11 where it changed quite a bit.
http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/bluetooth/BluetoothA2dp.java/?v=diff&id2=2.2_r1.1
Hope that helps.
You can use the getConnectedDevices for the HEADSET Profile to get the device to which it is connected.
Check this out to see if headset is connected (ICS only):
public boolean isVoiceConnected()
{
boolean retval = true;
try {
retval = BluetoothAdapter.getDefaultAdapter().getProfileConnectionState(android.bluetooth.BluetoothProfile.HEADSET) != android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
} catch (Exception exc) {
// nothing to do
}
return retval;
}

Resources