Windows Phone 8.1 for Developers–Introducing Bluetooth LE
This blog post is part of a series about how Windows Phone 8.1 affects developers. This blog introduces the new Bluetooth LE support and is written by Jimmy Engström at Apeoholic and was originally posted here.
Introduction
With Windows phone 8.1 Microsoft also released the ability to communicate with Bluetooth Low Energy devices.
This is really exciting for Windows phone developers, this way we can start developing apps that can talk to devices without draining the battery dry.
Sadly this is not available in the developer preview of Windows phone 8.1, but will be available when Windows Phone 8.1 is released for general availability.
Pairing
The first step is always to pair with the device you want to connect to. This is easy to do by going to Settings –> Bluetooth on your phone and tapping on the device you wish to pair with, just as you would do with a “ordinary” Bluetooth device.
Capabilities
To be able to communicate with Bluetooth Low energy (or Bluetooth Smart, as it’s also called) you need to add a capability to your app.
This can’t be done from a GUI, you need to edit the package.appmanifest manually and add the following lines of code just above </Package>.
<Capabilities>
<m2:DeviceCapability Name="bluetooth.genericAttributeProfile">
<m2:Device Id="any">
<m2:Function Type="serviceId:1803"/>
</m2:Device>
</m2:DeviceCapability>
</Capabilities>
Now you are are set to start coding =)
Iterate through devices
To keep this as simple as possible, I’ll just show you how to iterate through devices and pick up a predefined one.
BluetoothLEDevice currentDevice { get; set; }
string deviceName = "Philips AEA1000";
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
foreach (DeviceInformation di in await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelector()))
{
BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromIdAsync(di.Id);
if (bleDevice.Name == deviceName)
{
currentDevice = bleDevice;
break;
}
}
}
Find out what your device can do
GATT (Generic Attribute Profile) provides profile discovery and description services for Bluetooth Low Energy protocol, it basically makes it possible to ask your device what it can do. The documentation for this is very thorough and shows how to communicate.
Here is how to get a list of the GATTServices your device supports.
List<string> serviceList = new List<string>();
foreach (var service in currentDevice.GattServices)
{
switch (service.Uuid.ToString())
{
case "00001811-0000-1000-8000-00805f9b34fb":
serviceList.Add("AlertNotification");
break;
case "0000180f-0000-1000-8000-00805f9b34fb":
serviceList.Add("Battery");
break;
case "00001810-0000-1000-8000-00805f9b34fb":
serviceList.Add("BloodPressure");
break;
case "00001805-0000-1000-8000-00805f9b34fb":
serviceList.Add("CurrentTime");
break;
case "00001818-0000-1000-8000-00805f9b34fb":
serviceList.Add("CyclingPower");
break;
case "00001816-0000-1000-8000-00805f9b34fb":
serviceList.Add("CyclingSpeedAndCadence");
break;
case "0000180a-0000-1000-8000-00805f9b34fb":
serviceList.Add("DeviceInformation");
break;
case "00001800-0000-1000-8000-00805f9b34fb":
serviceList.Add("GenericAccess");
break;
case "00001801-0000-1000-8000-00805f9b34fb":
serviceList.Add("GenericAttribute");
break;
case "00001808-0000-1000-8000-00805f9b34fb":
serviceList.Add("Glucose");
break;
case "00001809-0000-1000-8000-00805f9b34fb":
serviceList.Add("HealthThermometer");
break;
case "0000180d-0000-1000-8000-00805f9b34fb":
serviceList.Add("HeartRate");
break;
case "00001812-0000-1000-8000-00805f9b34fb":
serviceList.Add("HumanInterfaceDevice");
break;
case "00001802-0000-1000-8000-00805f9b34fb":
serviceList.Add("ImmediateAlert");
break;
case "00001803-0000-1000-8000-00805f9b34fb":
serviceList.Add("LinkLoss");
break;
case "00001819-0000-1000-8000-00805f9b34fb":
serviceList.Add("LocationAndNavigation");
break;
case "00001807-0000-1000-8000-00805f9b34fb":
serviceList.Add("NextDstChange");
break;
case "0000180e-0000-1000-8000-00805f9b34fb":
serviceList.Add("PhoneAlertStatus");
break;
case "00001806-0000-1000-8000-00805f9b34fb":
serviceList.Add("ReferenceTimeUpdate");
break;
case "00001814-0000-1000-8000-00805f9b34fb":
serviceList.Add("RunningSpeedAndCadence");
break;
case "00001813-0000-1000-8000-00805f9b34fb":
serviceList.Add("ScanParameters");
break;
case "00001804-0000-1000-8000-00805f9b34fb":
serviceList.Add("TxPower");
break;
default:
break;
}
}
MessageDialog md = new MessageDialog(String.Join("\r\n", serviceList));
md.ShowAsync();
Time for some fun, Lets make it beep!
In my case I have a Key finder (key fob) and it implements (among other services) the Immediate Alert Service, which makes it possible to make it beep.
The GATT specification shows us how to communicate with the ImmediateAlertService
Download the PDF here.
The documentation shows us that if we want to set the alert level we need to do that with “Write without Response”.
The different values for Alert Level can be found here.
Value 0, meaning “No Alert”
Value 1, meaning “Mild Alert”
Value 2, meaning “High Alert”
This snippet will make the key finder (key fob) sound a high alert.
var immediateAlertService = currentDevice.GetGattService(GattServiceUuids.ImmediateAlert);
var characteristics = immediateAlertService.GetCharacteristics(GattCharacteristicUuids.AlertLevel).First();
byte[] data = new byte[1];
data[0] = (byte)2;
await characteristics.WriteValueAsync(data.AsBuffer(), GattWriteOption.WriteWithoutResponse);
In my next blog post I will go through more of the things you can do with a key finder (key fob).
Comments
Anonymous
May 04, 2014
As of WP8.1, if my App just need to support bluetooth keyboard instead of just onscreen keyboard, am I still required to add these code? Or will any App that accepts onscreen keyboard input can get free ride with bluetooth keyboards? As you see, the bluetooth features are not fully functional in developer preview, so I wish to get some authoritive answer.Anonymous
May 10, 2014
The comment has been removedAnonymous
June 04, 2014
The comment has been removedAnonymous
June 08, 2014
The comment has been removedAnonymous
July 29, 2014
First it was WP8, then it was the Amber Update, then the Black Update, now it's the Cyan Update! Come on MS, sort it out, some of us are just wishing we had bought an I-Phone and had BLE for a year and a half.Anonymous
September 17, 2014
Hey I am now developing a BLE app on wp8 After the step when I receive a BluetoothLEDevice object how can I connect to it. I have seen PeerFinder.ConnectAsync(selectedDevice); it requires a peerinformation object and it fails when I am try to use this, I got a error The connection is refused. I have seen example someone uses PnpObject.CreateFromIdAsync(PnpObjectType.DeviceContainer, device.Properties["System.Devices.ContainerId"].ToString(), new string[] { "System.Devices.Connected" }); I dont know if this is correct way to do it.Anonymous
October 01, 2014
nothing works for me. how did you manage do make it working guys ? I have 8.1, nokia black update. I have a lumia 925 and when running update it is says it is updtodate so not able to get Cyan update for now . any other way ? Does any of you can share a working sample ? I am estimate beacon in handsAnonymous
October 05, 2014
I want to use bluetooth app in my appln.am new to wp 8.1.can you pl tel me how to do in c# code.i want to list paired device in my app.pl share the code.Anonymous
January 16, 2015
anyone have a working sample here...strange thing I want to use this for. I wonder if it can find a lost Microsoft Band in the house?Anonymous
February 01, 2015
The comment has been removedAnonymous
July 19, 2015
Update: There is a keyboard with WP8.1U2 Bluetooth support: www.microsoft.com/.../universal-foldable-keyboardAnonymous
July 19, 2015
Hello, I have tried this code /---------------------------------------------------------------------------------------------------------------------/ DeviceInformationCollection collection = await DeviceInformation.FindAllAsync(); IEnumerable<DeviceInformation> bthleDevices = collection.Where(x => x.Id.Contains("BTHLE")); foreach (DeviceInformation di in bthleDevices) { System.Diagnostics.Debug.WriteLine("BTHLE:" + di.Id); BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromIdAsync(di.Id); } /---------------------------------------------------------------------------------------------------------------------/ Above code show my required BLE device but "BluetoothLEDevice.FromIdAsync(di.Id)" line give error "Element not Found" When I tried below code, it even do not show any BLE devices that is paired /---------------------------------------------------------------------------------------------------------------------/ foreach (DeviceInformation di in await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelector()){ System.Diagnostics.Debug.WriteLine("found any device"); if (di.Name.Equals("EMS_LINK_PTB")) { System.Diagnostics.Debug.WriteLine("Ble device " + di.Name + " id=" + di.Id); } } /------------------------------------------------------------------------------------------------------------------------/ In bluetooth setting BLE device named EMS_LINK_PTB shows connected but i am not able to get device instance at all in my application. Please suggest any solution, I have most recent updated Microsoft Lumia 8.10.15148.160 windows phone deviceAnonymous
July 23, 2015
I have a similar error, I can connect to device (parrot rolling spider) with BluetoothLEDevice (WP8.1) but I get an "Element Not Found" error when I try to connect using GattDeviceService (W8, not Phone!) How can I emulate the BluetoothLEDevice on W8 platform?Anonymous
October 22, 2015
Please, please, please fire whoever is in charge of your BLE APIs and hire someone who actually understands the use-cases for IoT devices. Sending users to Settings->Deices->Bluetooth to pair is absolutely NOT an option for many if not most situations. UWP 10 improves things only very slightly with the addition of the advertisement watcher. You still can't create a BluetoothLEDevice from the acquired MAC address unless it has already been paired. Many devices can communicate fine without pairing. For those that actually require pairing, you desperately need to expose a pairing API. You also need to provide a solution for 8.1 Universal Windows apps that will make it through the app store verification. If that requires a pre-approved native binary that we have to reference, fine, do that. For the record, your own bluetooth scanning/pairing settings page is painfully slow and unreliable. Even if it was a viable option for most use-cases, I wouldn't want to send users there. I don't even get the option to send them there outside of Windows Phone, though. It's very sad that right now, Apple is the only company that seems to be getting this right. Android is nearly there but the platform is so fractured due to OEMs refusing to update devices that it's nearly as bad as Windows. At least with Android, you can do it so long as people are lucky enough to have been given a recent version.