SureshJoshi.com ▼

Bluetooth... Bluetooths... Blueteeth?


2015-11-17

Where did the name “Bluetooth” come from anyways? It seems like a weird name…

With a lot of the Wearables and IoT work I do, inevitably, writing an app with Bluetooth BLE support comes up. The problem here, is that I personally think Android and iOS native BLE support is inherently garbage, and wayyy too convoluted.

Bluetooth Platforms

On Android, the BLE stack didn’t really work in 4.3 and has been getting progressively better since, but runs into all kinds of bugs depending on the platform (this StackOverflow post documents some of those problems very well). There are a lot of reasons, and some history, for why this is the case - but to me that doesn’t matter. As an app developer, all I know is that it’s only semi-stable depending on the manufacturer, OS, time of day, wind conditions, etc…

CoreBluetooth is much more stable in terms of BLE (except on a specific version of iOS which was horribly broken - I think it was iOS 8.1ish territory). However, it’s a little bit low-level and not very well abstracted away (I would say similar about Android BLE to some extent too). Also, iOS in general adds some limitations on how much BLE stack access there is (hard to modify connection intervals and such).

How’s Your API?

Anyways, all of these things got me looking around for libraries that I can put on top of those low-level libraries to make my life easier. For me, I’m all about the API. I’ve noticed that when you start looking at and developing APIs, you’ll find that there are some patterns you like, some you don’t; and that some people make APIs as simple as possible to start using, whereas some people like swiss-army knives - at the ‘expense’ of more code to get started on.

A good example of this is LGBluetooth vs BluetoothKit for iOS. LGBluetooth wants to make things simple, streamlined, and idiot-proof – but BluetoothKit wants a lot of functionality at the expense of somewhat ‘more challenging’ to setup and understand.

Me, personally, I love simplicity with the option to make extensible (extensibility - which, 90% of the time, I don’t use). For example, one of my proudest APIs is this one to control a camera:

auto cameraManager = std::make_unique< RPJ::CameraManager >();
auto camera = cameraManager->FromIndex( 0 );
if ( camera == nullptr )
{
    return -1;
}

camera->StartCapturing();
auto frame = camera->CaptureImage();
if ( frame != nullptr )
{
    // Do something
}
camera->StopCapturing();

Basically 10 lines of code, which controls a cross-platform, custom UVC camera. I have the hooks so that you can independently handle memory management, images, drivers, add custom algorithms, etc… However, to get up and running for 90% of the time, it’s 10ish lines.

That’s just my philosophy. As a developer, even if you make really good stuff, but hard to use, people probably won’t use it.

In my opinion, no one does the API game better than Square.

Back to BLE

So, extending that to the Android BLE API – it’s a nightmare. I have to set up a bunch of code, broadcast receivers, callbacks, etc… Ugh. Horrible.

What’s 90% of all BLE communication? Scanning for devices, getting advertisements, writing to a peripheral, reading from a peripheral… That’s it, so why does anyone really need more than those 4-5 API calls + 1-2 for initialization and maybe tear-down?

It’s a rhetorical question, but that’s what I think about how APIs work. If you want, add in hooks to do deeper levels of control over your library, but encourage people to use your ‘helper’ functions which encapsulate all the underlying cruft.

Lambda, Lambda, Lambda

People… Use lambda functions… “new Callback() {…}” is a lot of weak sauce.

The value of lambdas in BLE communication surrounds the fact that I usually need a callback directly after a successful read/write - so why should I dig through other parts of my code to see what the callback was doing, when it could be right in front of me in the form of “() ->”.

RetroLambda makes this happen.

Callback Hell

This one is prolific in Javascript code, but present in iOS and Android too.

BLE is inherently sequential, meaning that you can generally only do one call at a time (otherwise, you might squash a previous call if it wasn’t finished). If you want to chain calls, you need to nest them in callbacks. Problem is, when you want to read a BLE device’s standard information, that’s 5-6 nested calls, which ends up looking like this in LGBluetooth in Swift:

func readDeviceInformation(callback: () -> Void) {
    self.readManufacturerModel({
        self.readSerialNumber({
            self.readFirmwareRevision({
                self.readHardwareRevision({
                    self.readSoftwareRevision({
                        self.readManufacturerName(callback)
                    })
                })
            })
        })
    })
}

Absolutely horrific… Just … ugh…

In NodeJS - the Async library turns callback hell into sequential calls, so what’s the equivalent for Android?

Custom code mostly.

I wrote an Android USB driver to talk to a piece of hardware - but the hardware had a similar limitation of not being able to queue up calls (so I had to wait for a callback with the data). The solution? Simple - I moved the queue to the Android side and ended up with something like this (equivalent to the above code):

mTxMessageQueue.add(sendRequest(DeviceInformation.InfoType.Name));
mTxMessageQueue.add(sendRequest(DeviceInformation.InfoType.Firmware));
mTxMessageQueue.add(sendRequest(DeviceInformation.InfoType.Hardware));
mTxMessageQueue.add(sendRequest(DeviceInformation.InfoType.SerialNumber));
mTxMessageQueue.add(sendRequest(DeviceInformation.InfoType.PCB));

I just created a queue and after each message is sent, I pull the next one off the queue and send it in – simple. Even better, I have RXAndroid wrap up the result in an observable to get sent off to subscribers… Very easy, very slick.

Blueteeth

What this is all leading up to is that I’m finally getting a chance to put some more time into my Android BLE library called Blueteeth (located here: https://github.com/RobotPajamas/Blueteeth).

Currently, I’ve got a very rough basis for it used in my BLE113 OTA code (https://github.com/RobotPajamas/ble113-ota-android), but that was put on hold due to some very, very strange Android GATT issues (located here on StackOverflow, which was never answered). Until now, I haven’t had the time to work on it, but over the next month or two - I will be putting a lot of work into it to get it up and running.

This is an open call for recommendations or feature requests! If anyone has anything they would like to see, please let me know and I’ll see if I can accommodate… Or, better yet… Pull Request!!! Ahem, once the code is actually up there :)

Oh, and before anyone asks, yes, I have looked over the Android BLE libraries on GitHub and Android Arsenal and there are some really great ones out there - just not the features/APIs I would like. Also, not close enough to what I need to really justify a pull request (as they would basically be API revamps at this point).

Update: April 26, 2016

I’ve just released Blueteeth to JCenter!

Full instructions are on Github, but to pull it down in Gradle, use:

compile 'com.robotpajamas.blueteeth:blueteeth:0.1.1'

Feature Photo credit: Planetschwa / Foter / CC BY-NC-ND