Category Archives: Bluetooth

The Bluetooth device address (BD_ADDR)

As you’d expect, a Bluetooth device has a MAC address assigned to it, however the BD_ADDR (Bluetooth Device Address), at least in my experiments, doesn’t necessarily map to the MAC address you see in, for example, the Window Device Manager properties page for the Bluetooth device. I will update this document if I find my findings have changed.

The information listed below is taken from a few sources, some of which I’ve referenced at the end of the post, my knowledge on the subject is taken from those and my own experiments.

The BD_ADDR is a unique identifier using 48-bit address space. For example

11:22:33:44:55:66

The address denotes several pieces of information, as follows

  • NAP

    The Non-significant Address Part is denoted by the first 16 bits, using our example this would be the 11:22 value. The NAP is used in Frequency Hopping Synchronization frames/packets.

  • UAP

    The Upper Address Part is denoted by the next 8 bits, using our example this would be the 33 value. The UAP is used for seeding various Bluetooth specification algorithms.

  • OUI

    The Organizationally Unique Identifier (the first 24 bits) is actually the combination of the NAP and UAP, hence in our example the NAP + UAP gives us the OU which is 11:22:33

    With the knowledge on the make up of the BD_ADDR, we can see that by taking the OUI value, we should be able to fairly easily lookup the manufacturer of a device. For example using the OUI List.

  • LAP

    The Lower Address Part is made up of the final 24-bits, hence in our example this would be the 44:55:66 and is allocated by the device vendor. The LAP identifies a Bluetooth device and is transmitted with each frame/packet as part of the packet header.

References

Bluetooth: Defining NAP + UAP + LAPBluetooth MAC Address Changer for Windows
OUI List
BD_ADDR – how do you get one?
Discovering the Bluetooth UAP
Does each Bluetooth device has its own unique MAC Address? How can we access it in an app?

Bluetooth Proximity

This post is going to cover aspects of determining proximity with Bluetooth devices and hence covers a couple of key pieces of data.

RSSI

RSSI stands for Received Signal Strength Indication as is a measurement of radio signal strength, measure in dBm (decibel-milliwatts). The higher the RSSI value, the stronger the signal.

Signal strength can be affected by many things. Along with the obvious environment affects, such as walls and interference the different chipsets used can give wide variations and hence cannot be guaranteed to indicate whether one Bluetooth device is actually closer than another.

To use RSSI effectively to try to approximate proximity, at least in terms of whether we’re getting closer to the device or moving further away, we should track multiple samples of RSSI over time. If the signal is getting weaker then we might suggest the device is getting further away (ofcourse taking into account any environment and others forms of interference).

RSSI can be calculated (although it will likely be available from your preferred Bluetooth LE library) using the following formula (although this includes distance as a parameter which is, after all what we’re after with proximity so unlikely to have).

RSSI = -10n log(d) + A

where 

d is distance
A is txPower
and
n is a signal propagation constant 
(for example it might be set to 2 in free space, but 
vary in a walled area).

In situations where we have RSSI only (i.e. no TX Power) we can approximate proximity using the signal strength by checking the RSSI against the following range of values

RSSI of -50dBm to 0dBm – very close
RSSI of -90dBm to -50dBm – medium distance
RSSI of less than -90dBm – far away

However, as stated, signals may be affected by different forms of interference and also by the chipsets and power used for the radio, so can only be taken as “guesses” to proximity.

TX Power

If you see the an option on your preferred Bluetooth LE library called txPower which stands for transmitted power (also known as measured power).

Note: This doesn’t seem to be available/used by all Bluetooth devices. In which case it’ll be defaulted to zero.

TX power is used within the previous formula (along with the RSSI value) to help determine distance or proximity estimates. It allows us to take into consideration the actual power of the Bluetooth device as it’s a calibrated (read-only constant) which indicates the expected RSSI at a distance of 1 metre from the Bluetooth device. So with RSSI and TX Power we can rearrange the previous equation to calculate distance, here’s a C# implementation of that

public static double GetProximity(int rssi, int txPower)
{
   const int signalPropagationConstant = 2; 
   return Math.Pow(10d, ((double) txPower - rssi) / (10 * signalPropagationConstant));
}

Obviously when calculating proximity with a 0 txPower the distance will no longer be valid and hence you’ll have to simply have to use sample RSSI to get a basic idea of signal strength).

References
Bluetooth LE Advertisements – Gauging Distance
How to Calculate Distance from the RSSI value of the BLE Beacon
Estimating beacon proximity/distance based on RSSI – Bluetooth LE
Proximity And RSSI

Enumerating available devices in UWP

In my previous post (Displaying the device picker in a UWP application) I showed how to reuse the UWP device picker flyout within an application.

However, it’s possible that the developer would prefer to offer devices in some alternate UI or, of course, simply locate a known device for an application to use. In the previous post I looked at filtering for Bluetooth devices and those are what I’m after for a little application I’m writing in which I do not require the DevicePicker UI.

Filtering

Before I get into code to enumerate the devices, I’ll first expand on the lines of code from my previous post, that look like this

BluetoothDevice.GetDeviceSelectorFromPairingState(false)

Each of the lines like this one actually returns a string which is an Advanced Query Syntax (AQS) language query. So for example this line will produce the following string (formatted to make it more readable)

System.Devices.DevObjectType:=5 AND 
System.Devices.Aep.ProtocolId:=\"{E0CBF06C-CD8B-4647-BB8A-263B43F0F974}\" AND 
(System.Devices.Aep.IsPaired:=System.StructuredQueryType.Boolean#False OR
System.Devices.Aep.Bluetooth.IssueInquiry:=System.StructuredQueryType.Boolean#True)

For completeness, here’s the results of each of the other GetDeviceSelectorFromPairingState calls

BluetoothLEDevice.GetDeviceSelectorFromPairingState(false)

System.Devices.DevObjectType:=5 AND 
System.Devices.Aep.ProtocolId:=\"{BB7BB05E-5972-42B5-94FC-76EAA7084D49}\" AND 
(System.Devices.Aep.IsPaired:=System.StructuredQueryType.Boolean#False OR 
System.Devices.Aep.Bluetooth.IssueInquiry:=System.StructuredQueryType.Boolean#True)

BluetoothLEDevice.GetDeviceSelectorFromPairingState(true)

System.Devices.DevObjectType:=5 AND 
System.Devices.Aep.ProtocolId:=\"{BB7BB05E-5972-42B5-94FC-76EAA7084D49}\" AND 
(System.Devices.Aep.IsPaired:=System.StructuredQueryType.Boolean#True OR 
System.Devices.Aep.Bluetooth.IssueInquiry:=System.StructuredQueryType.Boolean#False)

BluetoothDevice.GetDeviceSelectorFromPairingState(true)

System.Devices.DevObjectType:=5 AND 
System.Devices.Aep.ProtocolId:=\"{E0CBF06C-CD8B-4647-BB8A-263B43F0F974}\" AND 
(System.Devices.Aep.IsPaired:=System.StructuredQueryType.Boolean#True OR 
System.Devices.Aep.Bluetooth.IssueInquiry:=System.StructuredQueryType.Boolean#False)

Hence we could now create our own AQS query to search for devices.

See Using Advanced Query Syntax Programmatically for more information on AQS.

Enumerating over devices (simple approach)

A simple approach to enumerating over all the available devices is to use the DeviceInformation.FindAllAsync() method, which is async/await compatible, hence we simply use it like this

var devices = await DeviceInformation.FindAllAsync();

// output all devices
foreach (var device in devices)
{
   Debug.WriteLine(device.Name);
}

Obviously this is a little over the top if we’re looking for a specific device or set of devices. In such cases we can create an AQS query and pass this into one of the FindAllAsync overloads. Hence to recreate my previous post’s query looking for all Bluetooth devices we might prefer to use

var devices = await DeviceInformation.FindAllAsync(
    BluetoothDevice.GetDeviceSelectorFromPairingState(
        false));

Whilst this solution to the problem of locating devices may fulfil many of the developer’s requirements, an area it fails on is that once the developer has a list of devices they do not have a way to tell when devices are turned off/disabled/or otherwise no longer available. In such situations it’s better to watch for device changes.

Watching for device changes

The DeviceInformation.CreateWatcher method allows the developer to query for devices and via events, watch for items to be added, updated or removed. This would suit an RX type of implementation.

Here’s some code that demonstrates possible usage of the CreateWatcher

try
{
   deviceWatcher = DeviceInformation.CreateWatcher(
      BluetoothDevice.GetDeviceSelectorFromPairingState(false), 
      null,
      DeviceInformationKind.Device);

      deviceWatcher.Added += (watcher, args) =>
      {
         Debug.WriteLine($"Added {args.Name}");
      };
      deviceWatcher.Updated += (watcher, args) =>
      {
         Debug.WriteLine($"Updated {args.Id}");
      };
      deviceWatcher.Removed += (watcher, args) =>
      {
         Debug.WriteLine($"Removed {args.Id}");
      };
      deviceWatcher.EnumerationCompleted += (watcher, args) => 
      { 
         Debug.WriteLine("No more devices found"); 
      };
      deviceWatcher.Start();
}
catch (ArgumentException ex)
{
   Debug.WriteLine(ex.Message);
}

Again we’re using the AQS created via the GetDeviceSelectoryFromPairingState method and in this simplistic example, we simply subscribe to the Added/Updated/Removed and EnumerationCompleted events to output what devices have been added etc. We also need to be aware of possible ArgumentExceptions, such as incorrectly formatted GUID’s etc. See DeviceInformation Class for a more complete example of this usage.

Displaying the device picker in a UWP application

Developers can use the UWP device picker flyout control within their application to allow the user to select a device from a list of available devices. The list can be filtered to display only particular types of devices.

For example, here’s how to display the DevicePicker flyout without filtering, i.e. showing all available devices

var devicePicker = new DevicePicker();
devicePicker.Show(new Rect(x, y, width, height));

In this case we simply create a DevicePicker and call the Show method which is passed a rectangle where you want the picker to flyout from.

There’s an overload Show method which allows a placement as well.

If you run this code in your application you’ll find that devices are enumerated over and displayed as they are found, so obviously this may take a little bit of time to enumerate all devices.

In most cases we probably want to filter the DevicePicker for a certain type of device. For example if we want to locate all Bluetooth devices we would use the following

var devicePicker = new DevicePicker();

devicePicker.Filter
   .SupportedDeviceSelectors.Add(
      BluetoothLEDevice.GetDeviceSelectorFromPairingState(false));
devicePicker.Filter
   .SupportedDeviceSelectors.Add(
      BluetoothLEDevice.GetDeviceSelectorFromPairingState(true));
devicePicker.Filter
   .SupportedDeviceSelectors.Add(
      BluetoothDevice.GetDeviceSelectorFromPairingState(false));
devicePicker.Filter
   .SupportedDeviceSelectors.Add(
      BluetoothDevice.GetDeviceSelectorFromPairingState(true));

devicePicker.Show(new Rect(x, y, width, height));

In this case we’ve filtered the DevicePicker so it will only display BluetoothLE devices and Bluetooth devices both in a paired (the true parameter) or unpaired (the false parameter).

Obviously we’re going to want to get at the device information or the selected device, when using the Show method, we will need to subscribe to the DevicePicker’s DeviceSelected event, for example

devicePicker.DeviceSelected += (picker, args) =>
{
   // outputs the selected device name
   Debug.WriteLine(args.SelectedDevice.Name);
};

We can also respond to a couple of other events such as the DevicePickerDismissed and DisconnectButtonClicked.

As an alternate to the event approach, we could switch from using the Show method to use the async/await implementation which combines the Show and the DeviceSelected into he PickSingleDeviceAsync method, i.e.

var device = await 
   devicePicker.PickSingleDeviceAsync(
      new Rect(x, y, width, height));
// outputs the selected device name
Debug.WriteLine(device.Name);