Talking Bluetooth (Low Energy) with Xamarin

With the rising popularity of IoT (Internet of Things), it becomes more common that you need to communicate with hardware. In most cases you can accomplish this with network connectivity, but you might want to consider Bluetooth Low Energy (BLE) as well. As the name suggests, BLE uses a lot less energy in comparison to classic Bluetooth. Less energy consumption means that it’s possible to use smaller (and portable) batteries what might be very useful for IoT devices. When deciding if BLE suites your needs, you should take a few things in consideration:

  • Bandwidth: Bluetooth is less suitable for transmitting large sets of data, especially BLE.
  • Costs: in comparison to network adapters, bluetooth is more affordable.
  • Range: the range of your device really depends on the bluetooth device and version that is used by the hardware and the smartphone/tablet. The environment might also impact the range. At a maximum you can reach 100 meters, but the average will be around 15 meters.
  • Power consumption: you can use BLE to save energy, but this will limit the throughput. If you are transferring small packages this might be interesting. The classic way of bluetooth communication is also less consuming than network connectivity.

Instead of writing the bluetooth code for every platform, you can choose to use a plugin that provides an abstraction layer so it’s possible to access BLE from shared code. At the time of writing, I find Bluetooth LE Plugin for Xamarin the best pick for the job. The plug-in is easy to implement and is continuously getting updates. If you want to use classic bluetooth you might want to look into some other plugins. in this post I will focus on Bluetooth LE Plugin for Xamarin.

When working with BLE, there are 3 (most important) different bluetooth abstraction layers:

  • Services: A service contains one or more characteristics. For example, you could have a service called “Heart Rate service” that includes characteristics such as “heart rate measurement.” Each service has it’s unique pre-defined 16-bit or 128-bit UUID.
  • Characteristics: A characteristic is some kind of endpoint for a specific part of the service. Just like a service, the characteristic also has a UUID. Characteristics support a range of different interactions: read, write, notify, indicate, signedWrite, writableAuxilliaries, broadcast.
  • DescriptorsDescriptors are defined attributes that describe a characteristic value. For example, a descriptor might specify a human-readable description, an acceptable range for a characteristic’s value, or a unit of measure that is specific to a characteristic’s value.

Now, let’s dive into some code samples! To give you a taste of what the plugin has in store for you, some snippets:

Scan for BLE devices (advertisements)
The Adapter class makes it possible to detect devices in the surrounding area. You can simply get an instance of the adapter and start scanning with the following code:

 var adapter = CrossBluetoothLE.Current.Adapter;
adapter.DeviceDiscovered += (s,a) =+ deviceList.Add(a.Device);
await adapter.StartScanningForDevicesAsync(); 

Connect to device
When you’ve found the device you want to connect to, you are able to initiate a connection with the device. After connecting successfully to a device you are able to get the available characteristics and start sending requests or start retrieving notifications from the device. When the bluetooth device doesn’t receive any requests for a specific period (may differ per device), it will disconnect to save battery power. After getting a device instance (with the previous sample), it’s fairly easy to setup a connection:

    await _adapter.ConnectToDeviceAsync(device);
catch(DeviceConnectionException e)
// ... could not connect to device

Note: a device scan is only necessary when connecting to the device for the first time. It’s also possible to initiate a connection based on the UUID of the device.

Get services, characteristics, descriptors
As described above, a service is the first abstraction layer. When an instance of a service is resolved, the characteristics of this specific service can be requested. The same goes for a characteristic and his descriptors. On a characteristic you can request the descriptors.

The different abstraction layers can be requested in a similar way, GetAll or GetById:

// Get All services and getting a specific service
var services = await connectedDevice.GetServicesAsync();
var service = await connectedDevice.GetServiceAsync(Guid.Parse("ffe0ecd2-3d16-4f8d-90de-e89e7fc396a5"));

// Get All characteristics and getting a specific characteristic
var characteristics = await service.GetCharacteristicsAsync();
var characteristic = await service.GetCharacteristicAsync(Guid.Parse("37f97614-f7f7-4ae5-9db8-0023fb4215ca"));

// Get All descriptors and getting a specific descriptor
var descriptors = await characteristic.GetDescriptorsAsync();
var descriptor = await characteristic.GetDescriptorAsync(Guid.Parse("6f361a84-eeac-404c-ae48-e65b9cba6af8"));

Send write command
After retrieving an instance of the characteristic you’re able to interact with it. Writing bytes for example:

await characteristic.WriteAsync(bytes);

Send read command
You can also request information from a characteristic:

var bytes = await characteristic.ReadAsync();

Pretty easy, right? To get you started, you can find an example project on the Bluetooth LE Plugin GitHub page. Although this seems pretty simple,  I’ve experienced some difficulties in making it rock solid. Some tips to improve your code:

  • Run bluetooth code on main thread.
  • Don’t scan for devices and send commands simultaneously, also don’t send multiple commands simultaneously. A characteristic can only execute one request at a time.
  • Adjust ScanMode to suit your use case.
  • Don’t store instances of characteristics or services.

Related links:

2 thoughts on “Talking Bluetooth (Low Energy) with Xamarin

  1. Hello, I’m trying to use this plugin too but I find myself a bit confused on some of the things to do to make a simple app. The snippets of code seem to short and the example project is too complicated, do you know something in the middle?

    I need to make an IoT app for iOS and Android and I was able to get the bluetooth status of the device correctly.

    I could also let the OS handle the device discovery and connection but how do I send data to a device? I think characteristics are not the right thing to do it


    1. Hi Giovanni,

      Providing a sample for this library is a bit more complicated because it depends on what device you are trying to communicate with. In general there are two different ways of communicating with Bluetooth Low Energy:

      – Advertising
      Most BLE devices broadcast messages, these messages are referred to as advertising. You can receive these messages by registering an EventHandler on IAdapter.DeviceAdvertised. When you call IAdapter.StartScanningForDevicesAsync() the app will start receiving updates.

      – Connected
      Because advertising is insecure, and can be monitored by anyone, you can also setup a connection. When connected you can use the BLE services and characteristics. As far as I know there is no other way to communicate through BLE, besides characteristics. This is also described in the GATT specification: .
      You can initiate a connection by calling IAdapter.ConnectToDeviceAsync or IAdapter.ConnectToKnownDeviceAsync. Characteristics allow you to write or read data to/from the device.

      Note: because bluetooth is energy efficient, the device might disconnect when the connection isn’t actively used. It’s also important to send commands one by one, you can’t send multiple commands at the same time. The calls to the bluetooth library also have to be done on the main thread.

      I hope this is of any help to you.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s