Brian (previously)found himself contracting for an IoT company, shipping thermostats and other home automation tools, along with mobile apps to control them.
Brian was hired because the previous contractor had hung around long enough for the product to launch, cashed the check, and vanished, never to be heard from again.
And let’s just say that Brian’s predecessor had a unique communication style.
private class NoOpHandler extends AsyncCharisticHandler {
public NoOpHandler(Consumer<BluetoothGattCharacteristic> consumer) {
super(null, consumer);
}
@Override
public void Execute() {
// Don't do any actual BLE Communication here, and just go straight to the callback, This
// handler is just to allow people to get a callback ...
Brian (previously)found himself contracting for an IoT company, shipping thermostats and other home automation tools, along with mobile apps to control them.
Brian was hired because the previous contractor had hung around long enough for the product to launch, cashed the check, and vanished, never to be heard from again.
And let’s just say that Brian’s predecessor had a unique communication style.
private class NoOpHandler extends AsyncCharisticHandler {
public NoOpHandler(Consumer<BluetoothGattCharacteristic> consumer) {
super(null, consumer);
}
@Override
public void Execute() {
// Don't do any actual BLE Communication here, and just go straight to the callback, This
// handler is just to allow people to get a callback after after a bunch of Async IO Operations
// have happened, without throwing all the completion logic into the "last" async callback of your batch
// since the "last" one changes.
InvokeCallback();
// After this callback has been handled, recheck the queue to run any subsequent Async IO Operations
OnBLEAsyncOperationCompleted();
// I'm aware this is recursive. If you get a stack overflow here, you're using it wrong.
// You're not supposed to queue thousands of NoOp handlers one after the other, Stop doing it!
// If you need to have code executed sequentially just, er... write a fu*king function there is
// nothing special about this callback, or the thread it is called on, and you don't need to use
// it for anything except getting a callback after doing a batch of async IO, and then, it runs
// in the context of the last IO Completion callback, which shouldn't take ages. If you use
// AsyncRunWhenCompleted() to create more of these within the callback of AsyncRunWhenCompleted
// it just keeps the IO completion thread busy, which also breaks shit.
// Basically, you shouldn't be using AsyncRunWhenCompleted() at all if you're not me.
}
}
Who said bad programmers don’t write comments? This bad programmer wrote a ton of comments. What’s funny about this is that, despite the wealth of comments, I’m not 100% certain I actually know what I’m supposed to do, aside from not use AsyncRunWhenCompleted.
The block where we initialize the Bluetooth system offers more insight into this programmer’s style.
@SuppressLint("MissingPermission")
private void initializeBluetooth() {
_bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
_bluetoothAdapter = _bluetoothManager != null ? _bluetoothManager.getAdapter() : null;
if (_bluetoothAdapter != null && _bluetoothAdapter.isEnabled()) {
/* #TODO: I don't know if cancelDiscovery does anything... either good, or bad. It seems to make BLE discovery faster after
* the service is restarted by android, but I don't know if it screws anything else up in the process. Someone should check into that */
_bluetoothAdapter.cancelDiscovery();
_bluetoothScanner = _bluetoothAdapter.getBluetoothLeScanner();
_scanFilters = Collections.singletonList(new ScanFilter.Builder().setServiceUuid(new ParcelUuid(BLE_LIVELINK_UUID)).build());
CreateScanCallback();
} else {
// #TODO: Handle Bluetooth not available or not enabled
stopSelf();
}
}
This is a clear example of “hacked together till it works”. What does cancelDiscovery do? No idea, but we call it anyway because it seems to be faster. Should we look it up? Because yes, it sounds like calling it is correct, based on the docs. Which took me 15 seconds to find. “Someone should check into that,” and apparently I am that someone.
Similarly, the second TODO seems like an important missing feature. At least a notification which says, “Hey, you need bluetooth on to talk to bluetooth devices,” would go a long way.
All this is in service of an IoT control app, which seems to double as a network scanner. It grabs the name of every Bluetooth and WiFi device it finds, and sends them and a location back to a web service. That web service logs them in a database, which nobody at the company ever looks at. No one wants to delete the database, because it’s “valuable”, though no one can ever specify exactly how they’d get value from it. At best, they claim, “Well, every other app does it.” Mind you, I think we all know how they’d get value: sell all this juicy data to someone else. It’s just no one at the company is willing to say that out loud.
[Advertisement] Keep all your packages and Docker containers in one place, scan for vulnerabilities, and control who can access different feeds. ProGet installs in minutes and has a powerful free version with a lot of great features that you can upgrade when ready.Learn more.