Powering up with BLE in Windows 8.1
Today's Windows Wednesday post is kind of a hardware thing, but I sort of cheated in last Friday's Hardware post, Building your own Office Remote like project... so I'm going to make up for it today... I guess... Hey! It's a Windows post, and kind of cool to, who cares if it's a little hardware related... right? So let's get too it!
Today Dan Ardelean gives us a great introduction to Windows 8.1 and its Bluetooth Low Energy API's...
For who doesn't know Bluetooth Smart/Low Energy devices are devices optimized for low power consumption. Devices can act as an GATT Server, GATT client or both at the same time. In Server mode the device exposes one or more services. Each service has one or more characteristics with properties attached to it (read, write, notify, broadcast,...). The GATT Client connects to the Server and "consumes" its services.
Windows 8.1 has added support for communicating with Bluetooth devices from the store applications. This opened the development for a lot of accessories including the Bluetooth Low Energy devices. Windows 8.1 supports only GATT client mode. This is the first iteration of the Bluetooth api and, from some points of view, it is not complete and kinda rushed out to be available. Here are some missing features:
- The User eXperience when connecting to an Bluetooth device is bad. The common scenario for this kind of device is that you buy the device you see the application for the Windows Store is available, download it and run the app to play with the device. Here comes the "fun" part: form inside the store application you cannot connect to devices that were not previously paired from PC Settings - Devices - Bluetooth. So, for the first connection, when the user launches the application and you don't find any device to connect to, you will have to find a way to explain and convince the user to open Settings ->Change PC Settings->.... Bluetooth and then come back to your application. Also it is not possible to launch the Bluetooth screen directly like in Windows Phone case.
- For the BLE devices the whole idea of the application is to consume less but have a connection between the device (server) and the application (client). Too bad that is there is no to make teh application run in the background or receive notifications from the devices when the application is suspended. This missing feature "kills" a little bit the BLE principles and without it the protocol from the app side is not better than the classical SPP. The application should be able to connect, receive notifications in the background, be aware when the device disconnects and to be able to reconnect when available again.
- Without being able to connect to devices that were not previously paired beacon scenarios are not possible.
- Missing api's to discover the services and the characteristics of each service for any BLE device.
Beside that let's have a first look at how the new apis work.
If you want to start testing/demo the BLE api I think the SensorTAG is the best choice. The Texas Instruments chipset CC2540/1 is one of the most used chipset in BLE devices and the price of this kit is around 25$. It includes 6 sensors inside: IR temperature Sensor, Humidity Sensor, Pressure Sensor, Accelerometer, Gyroscope, Magnetometer so you can simulate various scenarios.
When interacting with the device you will have to find the devices that expose the services we want to connect to and then connect to the desired service. For this we will call Enumeration.DeviceInformation.FindAllAsync passing an AQS string to filter the devices. Let's say we want to connect to the devices that expose the Generic Access Service as it is an standard service. We can actually generate the AQS in 3 different ways for this service:
- Using the the standard implemented GattServiceUuids GetDeviceSelectorFromUuid(GattServiceUuids.GenericAccess)
- Generating an standard UUID from an shortID GetDeviceSelectorFromShortId(0x1800) -what it actually does is to add "-0000-1000-8000-00805f9b34fb" to the id
- When the service is not a standard one you will have to use GetDeviceSelectorFromUuid(new Guid(serviceGuid)) and pass the custom service guid in our case serviceGuid="00001800-0000-1000-8000-00805f9b34fb"
The code below shows how to read the device name using the Generic Access Service of the Sensor Tag. Here are the standard characteristics of the generic access service link.