Unity bluetooth communication - implementation - bluetooth

So I have read and tried about everything in order to start a simple bluetooth listener in Unity but with no luck. And couldn't find anyone who managed this.
The main issue is this socket exception:
"SocketException: An address incompatible with the requested protocol was used."
Has anyone successfully implemented bluetooth communication in Unity?
P.S.
I also tried the 32feet library but it gives the same exception when trying to create a new bluetooth listener :
Guid mUUID = new Guid("00001101-0000-1000-8000-00805F9B34FB");
BluetoothListener blueListener = new BluetoothListener(mUUID);

Related

Writing a notification descriptor value in iOS using bluetooth

I'm using Plugin.BLE to iterate a bluetooth device's services / characteristics / descriptors. When I find the descriptor I'm looking for, I try enabling notifications by writing 02-00 into the descriptor. This works for Android devices but on iOS, I get a an error:
Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: Client Characteristic Configuration descriptors must be configured using setNotifyValue:forCharacteristic
The offending C# code looks like:
await descriptor.WriteAsync(new byte[2] { 02, 00 });
Is there a different way on iOS devices to enable notifications?
It is apparent that this is one of those platform specific issues that will have to be refactored out into an interface / platform-implementation pattern. So for the iOS version of the application, in order to do the above, I had to write against CoreBluetooth. Once you have your device / service / characteristic / client configuration descriptor, you call the following:
peripheral.SetNotifyValue(true, characteristic);
After setting that value, a callback is issued to the peripheral delegate:
public override void UpdatedCharacterteristicValue(CBPeripheral peripheral, CBCharacteristic characteristic, NSError error) { }
From there I was able to continue what I was doing before.

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#.

Resources