SureshJoshi.com ▼

Update Bluegiga Firmware in Swift


2016-06-14

Not but two weeks ago, I got around to redoing my Android Bluegiga Firmware Update App with my Blueteeth library (which can actually be used for the BLE112 and BLE121LR as well). This week, I decided to update my iOS BLE113 Update App in Swift!

Why Bother?

Well, originally, I wrote an implementation in Objective C, because that’s what was required by a client (who also gave me permission to open-source the result). I tried to keep it close to the style and organization guidelines dictated by the rest of their app as well.

It works well, doesn’t handle all possible errors, but I’ve never had to do more than try twice to get it to update my Bluegiga firmware (and a lot of the problems are on the Bluegiga chip level, or the iOS BLE stack level).

However, the more I look at it, the more I dislike it, because I think Objective C is a horrific programming language. Just really not appealing to read or write. So, I finally decided to write a basic (read: rough, unoptimized, no particular API) Swift implementation to do the same thing.

Cleaner and Slicker

In almost every iOS app I write nowadays, one of the first libraries I pull down is LGBluetooth (which was a basis for the Blueteeth library). I like the API, and it works without many issues. Those issues are revolving around what you need to do to connect to a device, as well as advertising-specific things.

So, I have a very simple fork here which can be pulled directly from a Podfile through Git. Note: I haven’t yet plugged this one into my Bluegiga iOS update app as I haven’t needed it so far.

Anyways, versus the Objective C version, the Swift version of this app is less functional in terms of UI flourishes, however, the code is a lot simpler.

In fact, here is the majority of the update code!

private func uploadNextPacket(completion: Void -> Void) {
        if self.currentPacket == self.totalNumberOfPackets {
            // Send reset command
            var resetCommand: UInt8 = 3
            let resetData = NSData(bytes: &resetCommand, length: 1)
            LGUtils.writeData(resetData, charactUUID: BluegigaCharacteristics.controlNoAck, serviceUUID: BluegigaServices.ota, peripheral: self.peripheral, completion: nil)
            completion()
        } else {
            // Send next packet
            print(self.currentPacket)
            let nextPacket = self.fileData.subdataWithRange(NSRange(location: self.currentPacket * BluegigaPeripheral.packetSize, length: BluegigaPeripheral.packetSize))
            self.currentPacket += 1

            LGUtils.writeData(nextPacket, charactUUID: BluegigaCharacteristics.data, serviceUUID: BluegigaServices.ota, peripheral: self.peripheral) {
                error in
                self.uploadNextPacket(completion)
            }
        }
    }

To anyone using this code, I would probably split off two private methods (one to call the ResetToDfu, the other to hide LGUtils) - but this is completely functional.

Base Bluetooth Peripheral

Just as a reminder to myself, at some point, I need to pull this class into my Github fork, as I end up using it in every LGBluetooth project anyways. It’s a simple encapsulation of the LGBluetooth library, and has the hooks in place to read the basic device info present in most BLE devices.

For example, something like this:

/**
 * Read in the firmware version
 * @param callback Will be called when the call returns with success or error
 */
private func readFirmwareRevision(callback: (() -> ())?) {
    let cb: LGCharacteristicReadCallback = {
        data, error in
        self.firmwareRevision = String(data: data, encoding: NSUTF8StringEncoding)
        callback?()
    }

    LGUtils.readDataFromCharactUUID(StandardCharacteristics.firmwareVersion, serviceUUID: StandardServices.deviceInformation, peripheral: peripheral, completion: cb)
}

Feature Photo credit: matsuyuki / Foter / CC BY-SA