I'm writing an app using Swift on Xcode that connects to a bluetooth BLE peripheral. I've established a connection to a the device, and want to read some data from a specific characteristic (specifically FFF1 in service UUID FFF0).
I'm able to request a read of characteristics using the following code if the characteristic that I want to find info for is characteristicx
:
peripheral.readValueForCharacteristic(charactericsx)
What I want to know is this: How do I check that this read value is what I'm looking for. I want to be able to do an if statement to check my value against the discovered value for that characteristic.
Eg: If discovered value is X then do something, else if discovered value is Y then do something else.
That's not a very good explanation of what I want to do, but I hope you get the gist.
Anyone know how to go about doing this?
Updated For Swift3
After you execute that method, the delegate
of your peripheral is going to asynchronously receive the peripheral(_:didUpdateValueFor:error:)
method. In that method you can query the value
of the passed characteristic
parameter. value
will be an NSData
which you can pull the bytes out of. E.g.
// MARK: - CBPeripheralDelegate
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if let e = error {
print("ERROR didUpdateValue \(e)")
return
}
guard let data = characteristic.value else { return }
...
}
The value
method actually returns an Optional
around the expected Data
, so a let guard is the way to go.
Usually a characteristic will have a simple value encoded in it's up-to-20-byte Data
payload. E.g. maybe it's a simple UInt16 counter. To
To convert between these Data
glumps and meaningful numbers, have a look at the answer to round trip Swift number types to/from Data (I've included my own implementation of that below).
So for example, if you know that the characteristic of interest is some counter that is a meant to be extracted as a UInt16
, I would fill out the above example with something like:
// MARK: - CBPeripheralDelegate
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if let e = error {
print("ERROR didUpdateValue \(e)")
return
}
guard let data = characteristic.value else { return }
print("counter is \(UInt16(data:data))")
}
// Data Extensions:
protocol DataConvertible {
init(data:Data)
var data:Data { get }
}
extension DataConvertible {
init(data:Data) {
guard data.count == MemoryLayout<Self>.size else {
fatalError("data size (\(data.count)) != type size (\(MemoryLayout<Self>.size))")
}
self = data.withUnsafeBytes { $0.pointee }
}
var data:Data {
var value = self
return Data(buffer: UnsafeBufferPointer(start: &value, count: 1))
}
}
extension UInt8:DataConvertible {}
extension UInt16:DataConvertible {}
extension UInt32:DataConvertible {}
extension Int32:DataConvertible {}
extension Int64:DataConvertible {}
extension Double:DataConvertible {}
extension Float:DataConvertible {}