Monthly Archives: December 2015

BLE device Simulator

I just started working for a project where I need to implement simple application for custom BLE device. Basically what I would need to do, is to read characteristics values, show them in the UI and store the data in a file.

This sounds pretty easy, however, the BLE device is currently under development, and I would not be getting one for the next couple of weeks.

I’m really eager on getting started with it, and as the task for the app is really simply to find a device, connect to it and to monitor & store values from it, I got thinking that maybe I could make a simple simulator that would fake the device.

And as I do have Android device which is supporting full peripheral mode, I indeed can get it done rather easily. Basically what I need to do, is to check what kind of stuff my Polar H7 is advertising, and then simply doing the same with my own BLE advertiser.

The result project is called HeartBeatSimulator and as always, its open source project available under my GitHub repository.

Note that, if you use the examples used with my Using BLE GATT services with Windows 10, you would need to remember that Windows does use caching when pairing Bluetooth devices, thus first do remove any existing paring for the device and then do following:

  1. Do run the simulator in android device first (and let it run in background while doing pairing)
  2. Open Bluetooth settings in the android device
  3. Switch to Windows device, and open Bluetooth settings. Do enable Bluetooth if its disabled
  4. Start pairing from Windows device, and if there is multiple entries shown for the device, so pair all of them (The right BLE device would be the one that asks you to supply 6 digits ID on the android side, so remember to fill it right)
  5. After successfull paring, start the Windows application (the one that reads the values from the simulator)
  6. Search devices, and Select the simulator device to connect to it.
  7. With first time usage, the Windows device will ask permission to use the BLE simulator device, and you need to accept this.
  8. After this, the data from the simulator should be updated to the Windows app normally.

With the Foreground Example I made earlier, I did notice that for some reason the call to ReadClientCharacteristicConfigurationDescriptorAsync  inside the HeartbeatEngine does harng, thus before I get it fixed, you should simply comment out the line. Anyway, do make sure you call the WriteClientCharacteristicConfigurationDescriptorAsync, since if its not handled, the value changed event’s will not be delivered to your app.

Using BLE GATT services with Windows 10

Windows 10 brings nice update on the apps front by introducing Universal Windows app . With it you can create one app, and run it in all Windows 10 platforms, including phones & laptops.

To get started with development for it, you could first fetch the Windows-universal-samples  that allows you to get your old device update to Windows 10. I personally used my really old 920 for development & testing, simply because I do have access to few of special Developer device versions of them.

The Universal Windows app examples are for some reason not including any examples for using BLE GATT services, thus I decided to make one. Of course there is older 8.1 example, which indeed could be used as a base.

Additionally Windows 10 brings a new API that be used with BLE GATT services, and that is GattCharacteristicNotificationTriggerDetails, which can be used for monitoring single Characteristic while running in background.

Reading BLE characteristics values in Foreground

With Windows 10 devices, in order to connect to any BLE device, you need to pair them first. Thus you need to go to the Bluetooth settings, enable the Bluetooth. And then find the device you with to communicate with and get it paired. Which after you can find the device in your own code by searching for it with DeviceInformation.FindAllAsync():

 var devices = await DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(GattServiceUuids.HeartRate));
 
if (devices != null)
{
   foreach (DeviceInformation device in devices)
   {
       // add device into your UI here
   }
}

After we have paired with the device, it will be shown in the list even when it’s out of range, thus it’s advisable to actually to monitor whether we have connection, before attempting to read any values, though you can of course set value changed event handlers for characteristics, but those won’t be called if you don’t have connection anyways.

Do note that it appears that the device is handling the connection, thus from your application point of view, you simply find then device service, and then you check the status of the connection to that device, and then simply subscribe for connection events, which will inform you if we get any changes on connection. From coding point of view it looks like this:

service = await GattDeviceService.FromIdAsync(device.Id);
DeviceConnectionUpdated((service.Device.ConnectionStatus == BluetoothConnectionStatus.Connected), null);
service.Device.ConnectionStatusChanged += OnConnectionStatusChanged;

Then to get the characteristics from the service, you simply use the GetCharacteristics() function:

characteristic = _service.GetCharacteristics(GattCharacteristicUuids.HeartRateMeasurement)[0];
characteristic.ValueChanged += Oncharacteristic_ValueChanged;

 

And to make sure you’ll get notifications for the characteristics value change, you do need to make sure Characteristic notifications are enabled by making sure that characteristics configuration is set to Notify:

var currentDescriptorValue = await _characteristic.ReadClientCharacteristicConfigurationDescriptorAsync();

if ((currentDescriptorValue.Status != GattCommunicationStatus.Success) ||(currentDescriptorValue.ClientCharacteristicConfigurationDescriptor != GattClientCharacteristicConfigurationDescriptorValue.Notify))
{
await _characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
}

After this, you are basically done. Then you just need to implement handling the events and updating your UI with the values. Full example for the foreground reading for heartbeat characteristics can be found under my github repo at: BLETestStuffWindows/HeartbeatFg

Background Characteristics monitoring

I also have full example for the background monitoring available under my github repo at: BLETestStuffWindows/HeartbeatBg, The Uis for both examples are exactly the same, but the usage of the BLE Api’s are quite different.

The main changes made for the foreground example were:

  1. The MainPage in addition to finding the device, also monitors connection to it. This is to make sure that we only attempt to display values for devices we actually have connection to.
  2. The HeartbeatPage gets the heartbeat value via progress event handler from background task, thus its simply listening the progress events, and showing the value in the UI controls
  3. We needed to remove any characteristics value monitoring etc. from the BLE engine, since the value reading is now handled in background. Only connection monitoring parts are still used in MainPage.

Additionally we needed to add new functionality

  1. There is now 3 modules in the app. In addition to the main application, there is background service part, and Common module which is hosting parts that needs to be accessed from both foreground & background parts.
  2. MainPage is also doing Background task registration. UnRegistratering is handled in App class (when going back from HeartbeatPage)
  3. When we launch the app while having active background task, the start page is changed to be the HeartbeatPage, since we don’t need to select any device for showing the values anymore. This has effected the navigation design in app class.

The Background registration  is handled in BackgroundManager class. This class also implements the functions for setting & removing progress events handlers needed by HeartbeatPage.

In MainPage we use the lighter version of the BLE engine to find the characteristic we want to monitor in background, then we use BackgroundTaskBuilder class to register it with the instance of GattCharacteristicNotificationTrigger:

BackgroundTaskBuilder backgroundTaskBuilder = new BackgroundTaskBuilder();

backgroundTaskBuilder.Name = HeartbeatMonitorBackgroundTaskName;

backgroundTaskBuilder.TaskEntryPoint = HeartbeatMonitorBackgroundTaskEntryPoint;

backgroundTaskBuilder.SetTrigger(new GattCharacteristicNotificationTrigger(characteristic));

BackgroundTaskRegistration backgroundTaskRegistration = backgroundTaskBuilder.Register();

The framework then should handle keeping the connection to the device, until we remove the background task. And any change in the characteristics value should cause our background task to be executed.

In the background task, we then simply get the value of the characteristic from the taskinstance, and set it to the Progress variable, and if we have the progress event handler set, our UI will be informed on the newly gotten value.

GattCharacteristicNotificationTriggerDetails details = (GattCharacteristicNotificationTriggerDetails)taskInstance.TriggerDetails;
byte[] ReceivedData = new byte[details.Value.Length];
DataReader.FromBuffer(details.Value).ReadBytes(ReceivedData);

HeartbeatMeasurement tmpMeasurement = HeartbeatMeasurement.GetHeartbeatMeasurementFromData(ReceivedData);

taskInstance.Progress = tmpMeasurement.HeartbeatValue;

In the example implementation for the background task, I also have additional ways on informing the user of the values:

  1. ToastNotificationManager is used to make notifications to inform user of the cancellation of the task (so they could click the notification and re-start the task from the UI app)
  2. TileUpdateManager is used to update the main tile of the application with the heartbeat value, so the user can see what the last value we got was without opening the UI app.
  3. System.Launcher.LaunchUriAsync() is used to start the UI application directly when we have the heartbeat value outside the defined range.