How to access two different services from the same ble device - c#

For example, I have two heart rate monitors paired with my tablet PC.
I'm using such code to get list of HRM devices:
var devices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync
(
GattDeviceService.GetDeviceSelectorFromUuid(GattServiceUuids.HeartRate)
);
Then I show a listbox in GUI with device names got from devices[i].Name.
For example, I select device with index 0. Then I can get access to it HR serivice and HRM characteristic:
var service = await GattDeviceService.FromIdAsync(devices[0].Id);
var characteristic = await service.GetCharacteristics(attCharacteristicUuids.HeartRateMeasurement);
Along with heart rate I need a battery status. How can I get access to battery service of the same (already selected) device?

Some information before we start:
You do have to pair your Bluetooth devices with your computer, before you could scan them!
Listing your paired devices:
ListBox1.Items.Clear();
var devices = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));
foreach (var device in devices)
{
ListBox1.Items.Add(device);
}
If you want to know the battery life of the Bluetooth device:
How to get the battery level after connect to the BLE device?
To access multiple services at once, you need to "reconnect" to the device:
Device A can connect only one at a time to service S on Device B. Device A can connect to service S on Device B, C, D and E, etc at the same time.
#alanjmcf
Source: Establishing multiple bluetooth SPPs at the same time
But do not get confused with the method GetAllIncludedServices();, because it does really return "included services". As one answer stated at an other question:
You probably don't want to get the "included services". Included services is a special concept in BLE which I doubt you are using that is used to link one service from another.
#Emil

Related

Windows UWP Bluetooh multiple devices showing for single device

I am currently working on a C#-UWP app that needs to be able to discovery bluetooth devices (Not BLE) on the network and ones that have been previously connected to/paired.
Im sure anyone who is new to this task will have quickly found the documentation and example are of little help. I have learned more from Stackoverflow questions about peoples experimentations than from the docs and examples, but anyways.
My main question/problem is this: After setting up the device watcher to find bluetooth devices I found that I consistently get multiple additions of the same device but having a different bluetooth address (this is a device that was previously paired but not live on the network). After much investigate and brainstorming, we discovered that each device id is actually a pairing of the devices MAC address and the BT receivers MAC address.
The reason I was getting 3 device additions per 1 physical device is because I have connected to that same device with 3 different BT receiver dongles in the past. So my question is, is there anyway to make the device watcher return the device that corresponds to the currently active BT receiver dongle?
Otherwise I will need to find the currently active BT receivers MAC address and filter out the devices that do not have this, because otherwise the user will see 3 identical devices to select and only 1 of them will pass while the other 2 will fail.
While on this subject I would also like to mention that the device properties dont seem to be working. Before creating the watcher, I have a list of properties like this for example:
requestedProperties.Add("System.Devices.Aep.DeviceAddress");
requestedProperties.Add("System.Devices.Aep.IsConnected");
requestedProperties.Add("System.Devices.Aep.Bluetooth.Le.IsConnectable");
requestedProperties.Add("System.Devices.Aep.IsPresent");
requestedProperties.Add("System.Devices.Aep.ContainerId");
requestedProperties.Add("System.Devices.Aep.ModelId");
requestedProperties.Add("System.Devices.Aep.Manufacturer");
requestedProperties.Add("System.Devices.Aep.ProtocolId");
requestedProperties.Add("System.Devices.Aep.SignalStrength");
But when I debug the device that is added, it doesnt have any properties:
debug info showing no properties for added device
I would be useful to have this information.
Thank you for any input or suggestions.
Update
I found a quick solution that overcomes this problem (although i did find a lot more problems with the device watcher but that is probably a topic for another question).
For now I simply get the current BT adaptors MAC address and then check each incoming device if it has this MAC address in its pair. If it does not that means the device is paired with an old/unused BT adaptor.
/* NOTE:
Windows allows only 1 BT adapter to be active on 1 machine at a time
Therefore this function will either return the active dongle or a null if
there is no BT adapter on the machine or its disabled.
*/
BluetoothAdapter BTAdaptor = await BluetoothAdapter.GetDefaultAsync();
if (BTAdaptor == null)
{
// Log error
// return
}
//
// Code block to check if the BT adaptor can support the BT tech stack you are interested in.
//
// Format into hex with 12 characters (12 being the number of characters for MAC address)
string tempMac = BTAdaptor.BluetoothAddress.ToString("X12").ToLower();
// Pattern for MAC address.
string pattern = "(.{2})(.{2})(.{2})(.{2})(.{2})(.{2})";
string replace = "$1:$2:$3:$4:$5:$6";
m_strBTAdapterMAC = Regex.Replace(tempMac, pattern, replace);
Then when the device is added/updated/removed by the watcher event, check it:
// If device is not paired with the currently used BT adapter.
if (deviceInfo.Id.Contains(m_strBTAdapterMAC) == false)
{
// Device paired with old dongle, dont want to show the user.
return;
}
If anyone ever figures out how to make the device watcher just not give old devices, please let me know, its probably a better solution.

Get bluetooth devices connection notification

I'm making a winform application that monitors things happening on the computer like processes, wifi, screenshots,... and I'm working on Bluetooth connection.
I need to get the notification when a Bluetooth device connects or disconnects to the computer (or laptop), for example mobile phones. In addition, I need something to identify the device like ID or just the name of it if possible.
One thing to notice, I'm using C# and it's a winform app, it would be nice if the solution uses Windows native library (like winapi, pInvoke). Third party library is fine but it would be my last choice.
Update: I've followed Rita Han's answer and got some results.
Below is my code inside the override WndProc method. It works totally fine with USB but not with Bluetooth devices.
While the app is running, I turn on Bluetooth on both my laptop and mobile phone but they have not paired yet → the function gets called and it says Bluetooth came, then I connect the two devices → now they are connected but no notification except the one above.
After that, while they are connected, I try to remove the mobile phone device, they are disconnected and I connect them back again and one more time I get no notification about a new Bluetooth connection has been scanned or connected.
So in short, I get notified when Bluetooth radio scans for a new device but not when connecting in the first time. After that, disconnecting and reconnecting do not give me any notifications also.
Am I missing some events?
case USB.DBT_DEVICEARRIVAL:
devType = Marshal.ReadInt32(m.LParam, 4);
if (devType == USB.DBT_DEVTYP_VOLUME)
{
USB.DEV_BROADCAST_VOLUME vol;
vol = (USB.DEV_BROADCAST_VOLUME)
Marshal.PtrToStructure(m.LParam, typeof(USB.DEV_BROADCAST_VOLUME));
// Get the drive letter
c = USB.DriveMaskToLetter(vol.dbcv_unitmask);
listBox1.Items.Add("New USB has come with name " + c);
}
else if (devType == BluetoothDeviceNotification.DbtDevtypDeviceinterface)
{
BluetoothDeviceNotification.DevBroadcastDeviceinterface vol;
vol = (BluetoothDeviceNotification.DevBroadcastDeviceinterface)Marshal.PtrToStructure(m.LParam, typeof(BluetoothDeviceNotification.DevBroadcastDeviceinterface));
listBox1.Items.Add("Bluetooth came GUID " + vol.ClassGuid + "\t Name: " + vol.Name);
break;
}
break;
For using Windows native API you can use RegisterDeviceNotification function.
Refer to "Registering for Device Notification" sample for getting started.
Bluetooth interface GUID:
GUID BluetoothGUID = {0x0850302A, 0xB344, 0x4fda, 0x9BE9, 0x90, 0x57, 0x6B, 0x8D, 0x46, 0xF0 };
Bluetooth and WM_DEVICECHANGE Messages.

Windows RT (r-pi IoT 10) HID device

I am trying to use a HID (DualShock 4) connected to my R-PI 3 running Windows 10 IoT in a C# universal app. I was using the Device Enumeration sample as a guideline and managed to display the IDs of all connected devices. I could see that the connected DualShock was correctly enumerated because it logged the \\?\HID#VID_054C&PID_05C4....
So naturally the next thing I wanted to do was opening the device for communication. Since it is an HID I was using the HidDevice class with var device = await HidDevice.FromIdAsync(args.Id, FileAccessMode.ReadWrite);. Sadly the returned device is always null, nothing on the screen is prompted or so.
Next I assumed there at least has to be some kind of USB interface accessible so I went for var device = await UsbDevice.FromIdAsync(args.Id);
But now I am getting A device attached to the system is not functioning. (Exception from HRESULT: 0x8007001F) or sometimes also The process cannot access the file because it is being used by another process.
How can I talk to my device? :(

Can't instantiate a new GattDeviceService

I'm new to Bluetooth LE, and I'm trying to write to a Bluetooth HID device.
I'm using Visual Studios 2015 and am building a WPF application.
currently my code looks like this:
var hidDevices = await DeviceInformation
.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(
GattServiceUuids.HumanInterfaceDevice));
GattDeviceService bleDevice = await GattDeviceService.FromIdAsync(hidDevices[0].Id);
I have some code after, but my code stops right after I try to create a new GattDeviceService.
I know hidDevices[0] is occupied, but the ID generated shows up like this:
\\?/BTHLEDEVICE#{00001812-xxxx-xxxx-xxxx-xxxxxxxxxxxx}_Dev_VID&.........
I'm curious if that is normal.
GATT API does not allow you access HID Services.
I found information about your problems:
Bluetooth GATT—Windows.Device.Bluetooth.Gatt
The API lets Windows Store app developers implement GATT client
profiles for collecting data from low energy (LE) sensors.
A Bluetooth 4.0 radio is required to use the GATT API.
The GATT API prevents access to the following in-box and invalid
services:
(Bluetooth SIG name) 0x1812 HID Over GATT Service
For more informations: https://msdn.microsoft.com/en-us/library/windows/apps/bg182882.aspx

LiveConnectClient.BackgroundUploadAsync, is not working when phone not connected to usb

I'm trying to use LiveConnectClient.BackgroundUploadAsync in wp8, to upload copy of some data.
Her is my code:
var progress = new Progress<LiveOperationProgress>();
progress.ProgressChanged += progress_ProgressChanged;
try
{
LiveOperationResult res =
await liveClient.BackgroundUploadAsync(folderID,
new Uri(#"\shared\transfers\" + backupFile.Name, UriKind.Relative),
OverwriteOption.Overwrite, new System.Threading.CancellationTokenSource().Token, progress);
dynamic result = res.Result;
fileID = result.id;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
progress.ProgressChanged -= progress_ProgressChanged;
}
It's working fine on emulator, but when I tried it on the phone its working only when the phone connected to pc by usb , the phone connected to wifi.
You are facing 'problems' with BackgroundTransfer Policies.
The operating system enforces a number of restrictions on background transfers related to file size, connection speeds, and device resources.
Which means that when you download/upload larger files you need to change TransferPreferences - for example if you want to upload a file larger than 100 Mb you will be able to do that, but only via WiFi and while Phone is connected to external power source.
In your App you should check for WiFi connection and power supply before starting downlod/upload and then inform the User that he should (for example) turn WiFi on to perform operation on such a big file.
You can choose from:
// small files but via 3G and on Battery
liveClient.BackgroundTransferPreferences = BackgroundTransferPreferences.AllowCellularAndBattery;
// larger files via WiFi, on Battery
liveClient.BackgroundTransferPreferences = BackgroundTransferPreferences.AllowBattery;
// huge files but only WiFi and External power
liveClient.BackgroundTransferPreferences = BackgroundTransferPreferences.None;
The default setting is none - so if you hadn't changed it, your App will wait for external power and WiFi - that is probably why it is working while connected via USB (external power).

Categories

Resources