Xabre BLE Android respectively slow at scanning and connecting - c#

I have an application in which I use the Xabre library to connect to a BLE device.
On Android (I have tested on a Galaxy A40 and a Galaxy S7), I experience that the application utilize alot of time to respectively scan and connect.
I have changed the latency of my ScanMode to ScanMode.LowLatency - Which increased the scan-time a small bit. (though still unacceptable)
Additionally, when the device connects to a Device, it spends a lot of time and reconnects several times before connecting. (Yes, the device is within proximity, and other apps like LightBlue connects without any problems)
During connection I have set my ConnectParameters to ConnectParameters(true, true);.
I have not tested on iOS yet with this project, but have previously used Xabre for iOS where I didn't experience similar behavior.
The following code that I'm working with is:
public async void Connect(IDevice unit)
{
await adapter.StopScanningForDevicesAsync();
try
{
var parameters = new ConnectParameters(true, true);
await adapter.ConnectToDeviceAsync(unit, parameters);
//Add device
Bluetooth.Device = unit;
Console.Write(unit.Id);
//Add service and characteristics to Device object
Bluetooth.Service = await Bluetooth.Device.GetServiceAsync(Guid.Parse(Service_UUID));
Bluetooth.Characteristic = await Bluetooth.Service.GetCharacteristicAsync(Guid.Parse(Characteristic_UUID));
Characteristic_ValueUpdated();
}
catch (DeviceConnectionException e)
{
Console.WriteLine("Error: " + e);
Connect(unit);
}
}
public async void Disconnect()
{
try
{
await Characteristic.StopUpdatesAsync();
await adapter.DisconnectDeviceAsync(Device);
}
catch
{
}
}
public async void Scan()
{
adapter.ScanMode = ScanMode.LowLatency;
adapter.DeviceDiscovered += (s, a) =>
{
if (a.Device.Name == "Device_name")
{
Connect(a.Device);
}
};
await adapter.StartScanningForDevicesAsync();
}
On Galaxy S7 things generally run abit faster, but I still experience several reconnects.

Related

Xamarin Plugin.BLE why data read doesn't change?

I'm stuck with this task about reading some data from my BLE Device.
I have a HM-19 DSD Tech Bluetooth LE module on my target machine, and I want communicate with it with my smartphone.
I'm using Xamarin with Plugin.BLE to try to achieve this.
There is my BluetoothPage.xaml.cs code
public partial class BluetoothPage : ContentPage
{
IAdapter adapter;
ObservableCollection<IDevice> devicesList;
ListView pageList;
public BluetoothPage()
{
adapter = CrossBluetoothLE.Current.Adapter;
deviceList = new ObservableCollection<IDevice>();
pageList = new ListView();
pageList.ItemSource = deviceList;
pageList.ItemSelected += ActionConnect;
pageStackLayout.Children.Add(pageList); // Layout component declared on BluetoothPage.xaml
}
private void ButtonScan(object sender, EventArgs e)
{
try
{
devicesList.Clear();
adapter.DeviceDiscovered += (s, a) =>
{
devicesList.Add(a.Device);
};
if(!adapter.isScanning)
{
await adapter.StartScanningForDevicesAsync();
}
}
catch(Exception ex)
{
Console.WriteLine("ERROR: " + ex.Message);
}
}
private async void ActionConnect(object sender, SelectedItemChangedEventArgs se)
{
if(se != null)
{
try
{
if(adapter.IsScanning)
{
await adapter.StopScanningForDevicesAsync();
}
await adapter.ConnectToDeviceAsync((IDevice)pageList.SelectedItem);
IDevice device = adapter.ConnectedDevices[0];
// now get the service and characteristics of connected device
var services = await device.GetServicesAsync();
IService service = services[0];
var characteristics = await service.GetCharacteristicsAsync();
ICharacteristic characteristic = characteristics[0];
// now we can write and hopefully read values
byte[] data = { Coderequest.InitRequest, Coderequest.Info }; // My message to sendo to the machine to trigger his functions and his response
byte[] response = { 0 };
await characteristic.WriteAsync(data); // Send the data
response = await characteristic.ReadAsync() // Theorically we reading the response from the machine by BLE
}
catch(Exception ex)
{
Console.WriteLine("ERROR: " + ex.Message);
}
}
}
}
When I launch my app:
I trigger the scan button and it works very fine
then I tap on the BLE device that I want, it connect perfectly
with a debugger on the target machine I can see that the data was really sent by app via BLE
But I didn't get the response expected, I'm reading always the same bytes (that are maybe default values) that aren't the bytes I expected.
The strange thing is that if I use the DSD Tech Demo App for the HM-19 module and execute same instructions (connect, send and read) it works! I send the data that trigger a response by machine and the demo app show the expect right bytes I sent from the machine.
So...how I can read that data? On the developer site the docs barely guide you on scan and connect, but on the write/read lacks of info. It is very disappointing and this plugin is the best on the Nuget repos.
Can anyone help me, where I'm doing bad?
This is a link for the plugin, maybe I missed something https://github.com/xabre/xamarin-bluetooth-le
After various try I got the solution:
To read effectively the data from the BLE module, is necessary to use the ValueUpdateHandler.
Then I changed my code in this way:
public partial class BluetoothPage : ContentPage
{
IAdapter adapter;
ObservableCollection<IDevice> devicesList;
ListView pageList;
List<byte> buffer = new List<byte>();
public BluetoothPage()
{
adapter = CrossBluetoothLE.Current.Adapter;
deviceList = new ObservableCollection<IDevice>();
pageList = new ListView();
pageList.ItemSource = deviceList;
pageList.ItemSelected += ActionConnect;
pageStackLayout.Children.Add(pageList); // Layout component declared on BluetoothPage.xaml
}
private void UpdatingValue(object sender, CharacteristicUpdateEventArgs args)
{
buffer.AddRange(args.Characteristic.Value);
}
private void ButtonScan(object sender, EventArgs e)
{
try
{
devicesList.Clear();
adapter.DeviceDiscovered += (s, a) =>
{
devicesList.Add(a.Device);
};
if(!adapter.isScanning)
{
await adapter.StartScanningForDevicesAsync();
}
}
catch(Exception ex)
{
Console.WriteLine("ERROR: " + ex.Message);
}
}
private async void ActionConnect(object sender, SelectedItemChangedEventArgs se)
{
if(se != null)
{
try
{
if(adapter.IsScanning)
{
await adapter.StopScanningForDevicesAsync();
}
await adapter.ConnectToDeviceAsync((IDevice)pageList.SelectedItem);
IDevice device = adapter.ConnectedDevices[0];
// now get the service and characteristics of connected device
IService service = device.GetServiceAsync(Guid.Parse("0000ffe0-1000-8000-00805f9b34fb"));
ICharacteristic characteristic = service.GetCharacteristicAsync(Guid.Parse("0000ffe1-1000-8000-00805f9b34fb"));
// we attach the UpdateVale event to the characteristic
// and we start the service
characteristic.ValueUpdated += UpdatingValue;
await characteristic.StartUpdatesAsync();
// now we can write and hopefully read values
byte[] data = { Coderequest.InitRequest, Coderequest.Info }; // My message to sendo to the machine to trigger his functions and his response
await characteristic.WriteAsync(data); // Send the data
}
catch(Exception ex)
{
Console.WriteLine("ERROR: " + ex.Message);
}
}
}
}
So first I create a byte buffer to store the data: List<byte> buffer = new List<byte>().
I create a method for the event to catch the value readed and fill the buffer
private void UpdatingValue(object sender, CharacteristicUpdateEventArgs args)
{
buffer.AddRange(args.Characteristic.Value);
}
Finally I attach the method to the characteristic's EventHandler and start the service
characteristic.ValueUpdated += UpdatingValue;
await characteristic.StartUpdatesAsync();
Now every time the module send data to my app, the UpdateEvent triggers and fill the buffer, then print the buffer or show in some views to see the result.
BLE communication can be a pain particularly with Xamarin.
In any case asynchronous calls from your application may return before data has actually been sent to your end device.
This is due to several factors:
Operating system BLE driver behaviour - Any call that you make in your application code is handled by the operating system drivers. These may return before any data is actually handled by the BLE hardware.
BLE transport layer delays - BLE transmission of data is not instant. The data connection between two devices actually occurs within discrete time slots, between which the BLE transceiver is turned off to save power.
End device response time.
Most implementations of two way communication between devices using BLE use a minimum of two characteristics, one for data being sent and the other for data being received by a device e.g. device 1 receives data on the characteristic that device 2 sends on and vice versa. ​This avoids the possibility of any collision of data being sent by both parties.
You could try placing a delay in your code prior to polling for characteristic data and see if that helps, but its not an optimal solution.
I see that you are using your characteristic "anonymously", rather than using its uuid to select it. If the Bluetooth service supports more than one characteristic then you will need to use the uuid to ensure that you are using the correct one. The list of characteristics, much like the list of services and devices may not be returned in the same order whenever you request them.
You have the option of polling characteristics by reading them on a timed basis or setting up handlers for characteristic notification/indication events if the characteristic supports it and your BLE device uses that mechanism to show that data is ready.
The program is not working well, so I looked it up and found something similar,
What is missing is not finding the Bluetooth device.
I'm sorry, but if you can share, please send the entire program by e-mail.
thank you
kdg000#empas.com
AndroidManifest.xml
MainPage.xaml
<Button Text="Search" Clicked="searchDevice"/>
<ListView x:Name="DevicesList"
CachingStrategy="RecycleElement"
ItemSelected="DevicesList_OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding name}"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
MainPage.xaml.cs
namespace employeeID
{
public partial class MainPage : ContentPage
{
IAdapter adapter;
IBluetoothLE ble;
ObservableCollection devicelist;
IDevice device;
public MainPage()
{
InitializeComponent();
ble = CrossBluetoothLE.Current;
adapter = CrossBluetoothLE.Current.Adapter;
devicelist = new ObservableCollection<IDevice>();
DevicesList.ItemsSource = devicelist;
}
private async void searchDevice(object sender, EventArgs e)
{
if (ble.State == BluetoothState.Off)
{
await DisplayAlert("Message", "Bluetooth is not available.", "OK");
}
else
{
try
{
devicelist.Clear();
adapter.ScanTimeout = 10000;
adapter.ScanMode = ScanMode.Balanced;
adapter.DeviceDiscovered += (s, a) =>
{
//devicelist.Add(new ScanResultViewModel() { Device = a.Device, IsConnect = "Status: " + a.Device.State.ToString(), Uuid = "UUID:" + a.Device.Id.ToString() });
devicelist.Add(a.Device);
};
//We have to test if the device is scanning
if (!ble.Adapter.IsScanning)
{
await adapter.StartScanningForDevicesAsync();
}
}
catch (Exception ex)
{
await DisplayAlert("Notice", ex.Message.ToString(), "Error !");
}
}
}
private async void DevicesList_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
device = DevicesList.SelectedItem as IDevice;
var result = await DisplayAlert("Message", "Do you want to connect to this device?", "Connect", "Cancel");
if (!result)
return;
//Stop Scanner
await adapter.StopScanningForDevicesAsync();
try
{
await adapter.ConnectToDeviceAsync(device);
await DisplayAlert("Message", "Connect Status:" + device.State, "OK");
}
catch (DeviceConnectionException ex)
{
await DisplayAlert("Error", ex.Message, "OK");
}
}
}
}

UWP C# UART RS485 DetachBuffer

I have previously posted regarding the issue but haven't really found the problem.
Recently, I found this post regarding detachbuffer and wonder if this could be the reason i encounter the problem.
I have my UART for RS485 using a FTDI USB to 485 cable connected to Raspberry Pi on Windows IoT Core.
I set a dispatchertimer at every 1second to transmit polling to respective field devices.
I am able to tx and rx the 485 data with no problem.
However, after the polling loop to about 20 times it just crash and exited the debug mode.
I used try & catch to trap the exception but could not get it. However, i manage to read the error message at the debug output pane - The program [0xBB0] PwD.exe' has exited with code -1073741811 (0xc000000d).
I wonder if i repeatedly transmit polling, dataWriteObject.DetachBuffer(); would cause the problem?
Thanks.
snippets of my code are as follow;
private void PollTimer_Tick(object sender, object e)
{
if (pollCounter <= maxDevice)
{
var a = pollCounter | 0x80;
pollCounter++;
TxAdr = Convert.ToByte(a);
TxCmd = TxPoll;
TxPollCard();
}
else pollCounter = 0;
}
private async void TxPollCard()
{
if (serialPort != null)
{
List<byte> data = new List<byte>();
data.Add(TxHeader);
data.Add(TxAdr);
data.Add(TxCmd);
TxChkSum = 0;
foreach (byte a in data)
{
TxChkSum += a;
}
TxChkSum = (byte)(TxChkSum - 0x80);
data.Add(TxChkSum);
try
{
// Create the DataWriter object and attach to OutputStream
dataWriteObject = new DataWriter(serialPort.OutputStream);
dataWriteObject.WriteBytes(data.ToArray());
Task<UInt32> storeAsyncTask;
// Launch an async task to complete the write operation
storeAsyncTask = dataWriteObject.StoreAsync().AsTask();
UInt32 bytesWritten = await storeAsyncTask;
dataWriteObject.DetachBuffer();
}
catch (Exception ex)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
MainStatusDisplay.Text = ex.Message;
});
}
}
else
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
MainStatusDisplay.Text = "No UART port found";
});
}
}
Update:
Additional test i did which i disconnect the devices & keep transmitting without expecting response, it didn't crash.
On the other hand, i stop transmit and only listen to the 485 bus, it didn't crash either.

Can Raspberry Pi running Win10 IoT uses both Wifi and Bluetooth communication at the same time?

I'm still a beginner to programming. I have met some problem of my problem, where the pi couldnt use the wifi and bluetooth at the same time. This is because initially the code without the bluetooth element, it works fine. But when i added the bluetooth code into the program, it just went weird. It couldnt retrieve any data from the Firebase through Wifi. Is it really that they couldnt work together at the same time or it is wrong with the code. Is it because of the socketstream something like this? Really thanks for the help.
Link to the code as it is too long.
I have tested with your code. The app will get an exception as "Access is denied. ", it will cause the app crash. So you need to add try catch in the function DeviceWatcher_Added to ensure the app won't dump when the Bluetooth could not connect.
private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
{
try
{
var device = await BluetoothDevice.FromIdAsync(args.Id);
var services = await device.GetRfcommServicesAsync();
if (services.Services.Count > 0)
{
var service = services.Services[0];
stream = new StreamSocket();
await stream.ConnectAsync(service.ConnectionHostName, service.ConnectionServiceName);
rx = new DataReader(stream.InputStream);
tx = new DataWriter(stream.OutputStream);
await this.Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
() => { Device_9.IsEnabled = true; });
deviceWatcher.Stop();
}
}
catch(Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
BTW, you may refer to the sample mentioned in my first comment, it shows how to connect the RfcommService to communicate with Bluetooth. Please note that, in the sample the server creates the RfcommServiceProvider by guid, and the client connects the server with RfcommService from this guid as uuid.
var rfcommServices = await bluetoothDevice.GetRfcommServicesForIdAsync(
RfcommServiceId.FromUuid(Constants.RfcommChatServiceUuid), BluetoothCacheMode.Uncached);

BluetoothLEAdvertisementWatcher fails to communicate with Samsung phone BLE beacon

I am developing a Windows 10 UWP app on Visual Studios 2017 Community.
I am attempting to read some information from android and IOS devices. I use a BluetoothLEAdvertisementWatcher watcher which looks for valid BLE advertisement packets that are in range. I than connect to the Gatt service with a specific service Uuid. Finally I read the characteristics attached to the service.
This works fine for all devices that I have tested so far except for two S7 Samsung phones.
The process does actually work, but it is very slow and eventually will stop working and even block the bluetooth stack. After a while I will have to manually turn the bluetooth off and on again.
I consistently get these errors after every BLE communication with a Samsung S7 phone:
onecoreuap\drivers\wdm\bluetooth\user\winrt\common\devquerydevpropprovider.cpp(297)\Windows.Devices.Bluetooth.dll!1462192B: (caller: 14621514) ReturnHr(15) tid(36d4) 80070490 Element not found.
onecoreuap\drivers\wdm\bluetooth\user\winrt\common\devquerydevpropprovider.cpp(131)\Windows.Devices.Bluetooth.dll!14621555: (caller: 14578E83) ReturnHr(16) tid(36d4) 80070490 Element not found.
onecoreuap\drivers\wdm\bluetooth\user\winrt\device\bluetoothledevice.cpp(1418)\Windows.Devices.Bluetooth.dll!14578E9A: (caller: 14576350) LogHr(8) tid(36d4) 80070490 Element not found.
And here is the code that I use to connect to the Gatt service:
private async void OnAdvertisementReceived(
BluetoothLEAdvertisementWatcher sender,
BluetoothLEAdvertisementReceivedEventArgs args)
{
BluetoothLEDevice bleModule = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
var gattServicesResult = await bleModule.GetGattServicesForUuidAsync(new Guid("YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY"));
if (gattServicesResult.Status == GattCommunicationStatus.Success)
{
foreach (var gattService in gattServicesResult.Services.ToList())
{
if (gattServicesResult.Status == GattCommunicationStatus.Success)
{
GattCharacteristicsResult characteristicsImageID = await gattService.GetCharacteristicsForUuidAsync(new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"));
if (characteristicsImageID.Status == GattCommunicationStatus.Success)
{
string imageID = null;
foreach (GattCharacteristic gattImageID in characteristicsImageID.Characteristics.ToList())
{
GattReadResult valueImageID = await gattImageID.ReadValueAsync();
IBuffer bufferImageID = valueImageID.Value;
DataReader dataReaderImageID = DataReader.FromBuffer(bufferImageID);
imageID = dataReaderImageID.ReadString(bufferImageID.Length);
}
}
}
}
}
}
The line that causes the errors (which aren't actually fatal) is:
bleModule = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
My question is, has anyone else found this to be a problem and whether or not there is a solution to it? (it may need Microsoft to fix a problem in their BLE implementation).

Why is BluetoothLEDevice.GattServices Empty

I am trying to communicate with a peripheral device without pairing it to Windows and I am using BluetoothLEAdvertisementWatcher to scan for devices in range. This is my WatcherOnReceived method:
async private void WatcherOnReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
{
BluetoothLEDevice device = null;
BluetoothDevice basicDevice = null;
GattDeviceService services = null;
if (args.Advertisement.LocalName != "Nexus 6")
return;
_watcher.Stop();
device = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
device.GattServicesChanged += Device_GattServicesChanged;
//basicDevice = await BluetoothDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
//services = await GattDeviceService.FromIdAsync(device.DeviceId);
lock (m_syncObj)
{
Debug.WriteLine("");
Debug.WriteLine("----------- DEVICE --------------");
Debug.WriteLine(args.ToString());
Debug.WriteLine(args.Advertisement.DataSections.Count);
foreach (var item in args.Advertisement.DataSections)
{
var data = new byte[item.Data.Length];
using (var reader = DataReader.FromBuffer(item.Data))
{
reader.ReadBytes(data);
}
Debug.WriteLine("Manufacturer data: " + BitConverter.ToString(data));
//Debug.WriteLine("Data : " + item.Data.ToString());
//Debug.WriteLine("Data capacity: " + item.Data.Capacity);
Debug.WriteLine("Data Type: " + item.DataType);
}
foreach (var md in args.Advertisement.ManufacturerData)
{
var data = new byte[md.Data.Length];
using (var reader = DataReader.FromBuffer(md.Data))
{
reader.ReadBytes(data);
}
Debug.WriteLine("Manufacturer data: " + BitConverter.ToString(data));
}
foreach (Guid id in args.Advertisement.ServiceUuids)
{
Debug.WriteLine("UUIDs: " + id.ToString() + " Count: " + args.Advertisement.ServiceUuids.Count);
//services = device.GetGattService(id);
}
Debug.WriteLine("Receive event...");
Debug.WriteLine("BluetoothAddress: " + args.BluetoothAddress.ToString("X"));
Debug.WriteLine("Advertisement.LocalName: " + args.Advertisement.LocalName);
Debug.WriteLine("AdvertisementType: " + args.AdvertisementType);
Debug.WriteLine("RawSignalStrengthInDBm: " + args.RawSignalStrengthInDBm);
if (device != null)
{
Debug.WriteLine("Bluetooth Device: " + device.Name);
Debug.WriteLine("Bluetooth Device conn status: " + device.ConnectionStatus);
Debug.WriteLine("Bluetooth DeviceId: " + device.DeviceId);
Debug.WriteLine("Bluetooth GettServices Count: " + device.GattServices.Count);
}
}
}
When a device is received I successfully create the BluetoothLEDevice from the args.BlutoothAddress but the device.GattServices are always empty and thus I can not use them to communicate with the device. Is the problem in the device or in the Windows API and what else can I try?
UPDATE 04/17 - CREATORS UPDATE
Microsoft have just updated their Bluetooth APIs. We now have unpaired BLE device communication!
They have very little documentation up at the moment but here is the much simplified new structure:
BleWatcher = new BluetoothLEAdvertisementWatcher
{
ScanningMode = BluetoothLEScanningMode.Active
};
BleWatcher.Start();
BleWatcher.Received += async (w, btAdv) => {
var device = await BluetoothLEDevice.FromBluetoothAddressAsync(btAdv.BluetoothAddress);
Debug.WriteLine($"BLEWATCHER Found: {device.name}");
// SERVICES!!
var gatt = await device.GetGattServicesAsync();
Debug.WriteLine($"{device.Name} Services: {gatt.Services.Count}, {gatt.Status}, {gatt.ProtocolError}");
// CHARACTERISTICS!!
var characs = await gatt.Services.Single(s => s.Uuid == SAMPLESERVICEUUID).GetCharacteristicsAsync();
var charac = characs.Single(c => c.Uuid == SAMPLECHARACUUID);
await charac.WriteValueAsync(SOMEDATA);
};
Much better now. As I said there is next to no documentation at the moment, I have a weird issue where my ValueChanged callback stops being called after 30 seconds or so, though that seems to be a separate scoping issue.
UPDATE 2 - SOME WEIRDNESS
After some more playing around with the new creators update there are a few more things to consider when building BLE apps.
You no longer need to run the Bluetooth stuff on the UI thread. There doesn't seem to be any permissions windows for BLE without pairing so no longer necessary to run on UI thread.
You may find that your application stops receiving updates from the device after a period of time. This is a scoping issue where objects are being disposed of that shouldn't. In the code above if you were listening to ValueChanged on the charac you may hit this issue. This is because the GattCharacteristic is disposed of before it should be, set the characteristic as a global rather than relying on it being copied in.
Disconnecting seems to be a bit broken. Quitting an app does not terminate connections. As such make sure you use the App.xml.cs OnSuspended callback to terminate your connections. Otherwise you get in a bit of a weird state where Windows seems to maintain (and keep reading!!) the BLE connection.
Well it has its quirks but it works!
This is still an issue with Windows Universal apps, the initial issue is that a device must be paired (not bonded) for GattServices to be discovered. However they also need to be discovered using Windows Devices rather than the BLE API. Microsoft are aware and are working on a new BLE API which does not require pairing but frankly their BLE support is pretty useless until this is ready.
Try pairing the device manually in Control Panel then list the services again. For some reason in Windows Universal Apps you can only list the Gatt Services for paired devices despite one of the advantages of BLE being that you do not need to pair with the device before using its services.
You can pair the device programmatically however depending on the platform the application is being run on this requires UI prompts. Therefore interrogating BLE services in the background is in-feasible. This needs to be fixed as it really stunts BLE support in UWP.
Its weird but works!
OLD ANSWER
Here is some sample code with a working BLE device connection:
private void StartWatcher()
{
ConnectedDevices = new List<string>();
Watcher = new BluetoothLEAdvertisementWatcher { ScanningMode = BluetoothLEScanningMode.Active };
Watcher.Received += DeviceFound;
DeviceWatcher = DeviceInformation.CreateWatcher();
DeviceWatcher.Added += DeviceAdded;
DeviceWatcher.Updated += DeviceUpdated;
StartScanning();
}
private void StartScanning()
{
Watcher.Start();
DeviceWatcher.Start();
}
private async void DeviceFound(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs btAdv)
{
if (!ConnectedDevices.Contains(btAdv.Advertisement.LocalName) && _devices.Contains(btAdv.Advertisement.LocalName))
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Low, async () =>
{
var device = await BluetoothLEDevice.FromBluetoothAddressAsync(btAdv.BluetoothAddress);
if (device.GattServices.Any())
{
ConnectedDevices.Add(device.Name);
device.ConnectionStatusChanged += (sender, args) =>
{
ConnectedDevices.Remove(sender.Name);
};
SetupWaxStream(device);
} else if (device.DeviceInformation.Pairing.CanPair && !device.DeviceInformation.Pairing.IsPaired)
{
await device.DeviceInformation.Pairing.PairAsync(DevicePairingProtectionLevel.None);
}
});
}
}
private async void DeviceAdded(DeviceWatcher watcher, DeviceInformation device)
{
if (_devices.Contains(device.Name))
{
try
{
var service = await GattDeviceService.FromIdAsync(device.Id);
var characteristics = service.GetAllCharacteristics();
}
catch
{
Debug.WriteLine("Failed to open service.");
}
}
}
private async void DeviceUpdated(DeviceWatcher watcher, DeviceInformationUpdate update)
{
var device = await DeviceInformation.CreateFromIdAsync(update.Id);
if (_devices.Contains(device.Name))
{
try
{
var service = await GattDeviceService.FromIdAsync(device.Id);
var characteristics = service.GetAllCharacteristics();
}
catch
{
Debug.WriteLine("Failed to open service.");
}
}
}

Categories

Resources