Framework

CoreBluetooth.Framework

Privacy

Privacy - Bluetooth Always Usage Description

Check Bluetooth State

Init CBCentralManager object and will get the bluetooth state from the CBCentralManagerDelegate. Must handle the bluetooth power off state.

1
2
3
4
5
6
7
8
9
10
public func centralManagerDidUpdateState(_ central: CBCentralManager){
var state : String
switch(central.state){
case .poweredOn:
case .poweredOff:
case .resetting:
case .unauthorized:
case .unsupported:
}

Check & ask for Bluetooth Permission

1
2
3
4
if CBPeripheralManager.authorization == .denied{
// ask user to grant the bluetooth permission in app setting.
return false
}

Scan for Bluetooth

  • Init CBCentralManager object.

    1
    centralManager = CBCentralManager(delegate: self, nil)
  • Start scan

    1
    2
    centralManager = CBCentralManager(delegate: self, queue: centralQueue)
    centralManager.scanForPeripherals(withServices: serviceUUIDs, options: nil)
  • Handle the function below in the CBCentralManagerDelegate

    1
    2
    3
    4
    5
    6
    public func centralManager(_ central: CBCentralManager, 
    didDiscover peripheral: CBPeripheral,
    advertisementData: [String : Any],
    rssi RSSI: NSNumber){

    }
  • Stop scan

    1
    centralManager.stopScan()

Connect & Disconnect with device

  • Connect with a peripheral

    1
    centralManager.connect(peripheral, options: nil)
  • Disconnect with a peripheral

    1
    centralManager.cancelPeripheralConnection(peripheral)
  • Handle the functions below in the CBCentralManagerDelegate

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public func centralManager(_ central: CBCentralManager, 
    didConnect peripheral: CBPeripheral){

    }

    public func centralManager(_ central: CBCentralManager,
    didFailToConnect peripheral: CBPeripheral, error: Error?){

    }

    public func centralManager(_ central: CBCentralManager,
    didDisconnectPeripheral peripheral: CBPeripheral, error: Error?){

    }
  • Handle the functions below in the CBPeripheralDelegate

    1
    2
    3
    4
    5
    6
    7
    func peripheralDidUpdateRSSI(_ peripheral: CBPeripheral, error: Error?){
    bluetoothPeripheral.readRSSI()
    }

    func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?){
    //print("rssi = \(RSSI)")
    }

Get Connected device services & characteristics

  • Discover services
    1
    peripheral.discoverServices([ServiceUUID])
  • Discover characteristics and handle the functions below in the CBPeripheralDelegate
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?){
    guard error == nil else {
    //Handle the error
    return
    }

    for aService: CBService in peripheral.services! {
    if aService.uuid.isEqual(YourServiceUUID) {
    peripheral.discoverCharacteristics(nil, for: aService)
    return
    }
    }
    }

    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?){

    guard error == nil else {
    //Handle the error
    return
    }

    if service.uuid.isEqual(YourServiceUUID) {
    for aCharacteristic : CBCharacteristic in service.characteristics! {
    if aCharacteristic.uuid.isEqual(YourTXCharacteristicUUID) {
    logw("TX Characteristic found")
    theTXCharacteristic = aCharacteristic
    }

    if aCharacteristic.uuid.isEqual(YourRXCharacteristicUUID) {
    logw("RX Characteristic found")
    theRXCharacteristic = aCharacteristic
    }
    }
    }
    }

Read & Write operations

  • Read data

    1
    2
    3
    4
    /*
    If successful, the peripheral then calls the peripheral(_:didUpdateValueFor:error:) method of its delegate object whenever the characteristic value changes.
    */
    Peripheral.setNotifyValue(true, for: theRXCharacteristic)
  • Write data

    1
    peripheral.writeValue(data, for: txChar, type: .withResponse)
  • Handle the functions below in the CBPeripheralDelegate

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?){

    guard error == nil else {
    logw("Updating characteristic has failed \(error?.localizedDescription ?? "")")
    return
    }

    // try to print a friendly string of received bytes if they can be parsed as UTF8
    guard let dataReceived = characteristic.value else {
    logw("Notification received from: \(characteristic.uuid.uuidString), with empty value")
    return
    }

    //let str : String = NSString(data: dataReceived, encoding: String.Encoding.utf8.rawValue)! as String
    logw("\(Date().timeIntervalSince1970*1000) didReceiveData \(dataReceived.count) from characteristic \(characteristic.uuid.uuidString)")
    ...
    }

    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?){
    guard error == nil else {
    logw("Writing value to characteristic failed \(error?.localizedDescription ?? "")")

    return
    }

    //delegate?.writeDone?(ret: true)
    logw("Data has written to characteristic: \(characteristic.uuid.uuidString)")
    }

References

https://developer.apple.com/documentation/corebluetooth/cbcentralmanager

https://developer.apple.com/documentation/corebluetooth/cbperipheral

https://developer.apple.com/documentation/corebluetooth/cbcentralmanagerdelegate

https://developer.apple.com/documentation/corebluetooth/cbperipheraldelegate

https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/CoreBluetoothBackgroundProcessingForIOSApps/PerformingTasksWhileYourAppIsInTheBackground.html