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.
Related
How can I detect 4G dongle(s) connected to my computer using NodeJS?
I tried the following code:
var os = require('os');
var allNetworkInterfaces = os.networkInterfaces();
console.log(allNetworkInterfaces);
It works, but I got all network interfaces... I would like to get a list with my 4G dongles only. Knowing that I could have either 1 dongle, or several dongles connected to the same computer, as well as other USB hardwares connected.
After installing the usb package by running npm install usb I was able to get a list of usb devices using the following code:
const usb = require('usb');
const devices = usb.getDeviceList();
console.log( devices );
You will have to go through that list and decide which is your "4G dongle".
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);
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.
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#.
I wanted to use Usage default app to determine how much data my own app send when in roaming mode.
I was very surprised to see that my device sent about 500 Mo. Then I realised that other apps on my phone should have used the network also.
So my question is: how can I enable roaming for just my app and prevent network access for everything else (updates, agenda, mail, ...)?
I run Firefox-OS 2.0 on a ZTE-Open device.
No, this is not possible.
The Data Usage App performs a test like this using the with the Network Stats API:
var end = new Date();
var start = new Date();
// Returns a mozNetworkStats object
var test = navigator.mozNetworkStats.getSamples('mobile', start, end);
console.log(test);
But this test will return a sample of all device connections, not only yours. The simplest solution is to measure the traffic in your Network Monitor.
However, if you want to reduce the amount of mobile traffic for your application, you can restrict all connections to specific connection types (like wifi). Just listen to the typechange event of the NetworkInformation.connection API.
In your WebIDE console (Firefox OS 2.0):
navigator.connection
NetworkInformation { type: "wifi", ontypechange: null }
or
navigator.connection
NetworkInformation { type: "cellular", ontypechange: null }
Please notice, that Firefox OS <=1.5 will never show you a cellular type of connection (it will return none if not wifi).