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.

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

Comments (14)

  1. cheong00 says:

    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.

  2. Richard Beyea says:

    when I follow through you code above in my own app VS2013 ultimate. capabilities set up.

    foreach (DeviceInformation di in await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelector()))

    never returns anything.

    if I step in to the foreach. there is not info displayed for DeviceInformation.

    I have a BTLE device paired.

    Thanks,

    Richard Beyea

  3. Jimmy Engström says:

    Hi Richard

    You need to have the Lumia Cyan update for Bluetooth LE to work, and it hasn't been released for general avalibility yet.

    /Jimmy

  4. Federico says:

    Hi Jimmy, I have Lumia 630 with Cyan update but I can't see my BTLE device in Bluetooth screen. Obviously the procedure returns anything. Any hints? BR, Federico

  5. Richard Carpenter says:

    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.

  6. Jovie says:

    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.

  7. serge says:

    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 hands

  8. Ramachandran says:

    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.

  9. Jeff Pigott says:

    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?

  10. Ahmad says:

    Does anyone care in the blogs department to check how the post actually looks like after it has been posted? code cutting off on the right hand side, total wastage of screen real estate, tiny nit size fonts, etc.?

  11. cheong00 says:

    Update: There is a keyboard with WP8.1U2 Bluetooth support:

    http://www.microsoft.com/…/universal-foldable-keyboard

  12. EmsLink says:

    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 device

  13. Alberto Nuti says:

    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?

  14. jclary says:

    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.