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.

image


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