An overview of Core Bluetooth Framework

Apple introduced Core Bluetooth Framework with IOS 5 SDK. With Core Bluetooth framework, developers are allowed to write an application that communicates with hardware gadgets and ios device using Bluetooth Low Energy Standard.
In this article we will see about Bluetooth low energy and the overview of  Core bluetooth Framework.

What is Bluetooth Low Energy?


Bluetooth Low Energy(BLE) sometimes referred as Bluetooth Smart is the technology used for transferring data. It consumes low amount of energy and allows the  device battery to last longer. Ideally BLE is  used to transmit small packets of data, such as fitness related data to fitness tracker.
There are two major players involved in all Bluetooth low energy communication: Central and Peripheral.

Central and peripherals in Core Bluetooth


Central:
It defines logic behind the Core bluetooth communication. It is able to scan, connect and disconnect peripherals and it also consumes information available at each peripheral. The central devices are usually mobile devices or tablets.
Peripheral:
The device that has information to share eg. Heart rate or temperature etc. The information can be pushed or advertise over the air.The peripheral devices are things like Heart rate monitor, BLE enables proximity tags, etc.
The following image defines the relationship between central and peripherals
In the above scenario IOS devices (Central) communicate with the Heart rate Monitoring system (Peripheral) to get heart rate information and shows it on a device.

How Central communicates with Peripherals?

In Bluetooth low energy, Advertising is the primary  way that peripheral make their presence known via BLE.
Peripherals broadcast some of the data they have in the form of advertising packets. An advertising packet is a relatively small bundle of data that may contain useful information that peripheral offers, such as the peripheral’s name and other primary functionality. For example, a Heart rate monitor may advertise that it provides Heartbeat per minutes.
On the other hand, Central can scan and listen any peripheral device that is advertising information and  connect to a particular device for more information that it’s interested in.
BLE peripheral is connected to Only one central at One time. As a peripheral connects to a central device, it will stop advertising itself and other devices will no longer be able to see it or connect to it until the existing connection is broken.
The Bluetooth low energy devices transfer the data in the form of the Services and Characteristics.

Services and characteristics in Bluetooth low energy

Services is the collection of data or characteristics. The device can contain multiple services. Each service distinguishes from other services using Unique Numeric Id called as UUID which can be either 16 bit or 128 bit.
Characteristics are  like properties of peripheral device which provides more details about the services. the service can have more than one characteristic. Similar to the service characteristics also distinguishes itself using predefined 16 bit or 128 bit UUID.

CBPeripherals, CBCentralManager, CBServices,

CBCharacteristics in Core Bluetooth Framework.

In the core Bluetooth framework peripherals are represented by CBPeripheral object and services related to the peripheral device is represented by CBService object.
CBCharacteristics objects used to represent characteristics of peripheral services. Central is represented by CBCentralManager object that is used to manage discovered and connected peripherals.
The following figure shows the basic hierarchical  structure of peripherals services and characteristics.
Now we have enough knowledge about core Bluetooth, before we proceed, I will give you the basic workflow of core Bluetooth : –
1.First Create Object of CBCentralManager
2.If the Central device state is PoweredOn, Scan for the peripheral device
3.When you found  peripheral you want to connect to, stop scanning and then connect to the peripheral you found
4.After the connection successful discover the peripheral services, you can discover specific service or ask to return all services that peripheral offers
5.After you found the service that you are interested in, discover it’s characteristics. The peripheral service may have one or more characteristics
6.When you found the characteristic that you are interested in,  you can read from or Write to the values to those characteristics
Let’s create one project with single view controller and add the corebluetooth framework.
Import the corebluetooth framework in viewcontroller and confirm the delegate CBCentralManagerDelegate and CBPeripheralDelegate.
First, you must allocate and initialize a central manager instance before you can perform any Bluetooth low energy transactions.
Create object of CBCentralManager and confirming delegates in viewDidLoad

var centralManager:CBCentralManager!

override func viewDidLoad() {

                     super.viewDidLoad()

          // Do any additional setup after loading the view, typically from a nib.

                centralManager = CBCentralManager()                              

                centralManager = CBCentralManager(delegate: self, queue:       dispatch_get_main_queue(), options:nil)

}

When you create a central manager, the central manager calls the centralManagerDidUpdateState: method of its delegate object. you must implement this delegate method to ensure that bluetooth low energy is supported and available to use on central device.
There are following states of CBCentralManager : –
✓ CBCentralManagerStateUnknown
✓ CBCentralManagerStateResetting
✓ CBCentralManagerStateUnsupported
✓ CBCentralManagerStateUnauthorized
✓ CBCentralManagerStatePoweredOff
✓ CBCentralManagerStatePoweredOn
Implement the method to get device state. As mentioned earlier in central discovers and connect to peripherals that are advertising. You can discover any peripheral device that is advertising by calling scanForPeripheralsWithServices:options: method of CBCentralManager class. Like this :

print(Scanning Started)
centralManager.scanForPeripheralsWithServices(nil,options:[CBCentralManagerScanOptionAllowDuplicatesKey : false])

NOTE:
Here we pass nil for first parameter, the central manager returns all discovered peripherals regardless of their supported services. instead of nil you can pass array of CBUUID objects, each of which represents UUID of a service that a peripheral advertising.
After scanning completed, the central manager calls the centralManager: didDiscoverPeripheral:advertisementData:RSSI: method each time a peripheral is discovered. Each peripheral that is discovered is returned as CBPeripheral object.

func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {

        print(Discovered \(peripheral.name)  at  \(RSSI)”)

}

When you find a peripheral, stop scanning for other devices in order to save power.

centralManager.stopScan()

print(Scanning Stopped)

After you have discovered a peripheral device that are  advertising services you are interested in, you can request a connection to peripheral by calling the connectPeripheral:options: method. simply call this method and specify the discovered peripheral that you want to connect to. Like this: –

central.connectPeripheral(peripheral, options: nil)

Assuming that your connection request is successful, the central manager calls the centralManager:didConnectPeripheral: method like : –

func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {

         print(Connected)

}

and before you begin interacting with peripheral, you should set the  peripherals delegate to ensure that it receives the appropriate callback
peripheral.delegate = self
after you have established a connection to peripheral, you can begin to explore its data. First discover its available services . You can discover all services of peripheral by calling discoverSerices: method of CBPeripheral class like: –
peripheral.discoverServices(nil)
NOTE:
In the above method you can pass array of CBUUID of the services you are interested in, to save battery life and unnecessary use of time.
When the specified services are discovered the peripheral calls the peripheral:didDiscoverServices: method. It creates an array of CBService objects, one for each service that is discovered on peripheral. Implement this delegate method to access the array of discovering services like: –

func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {

          for service in peripheral.services! {

                 print(Discovered service: \(service)”)

                    ….

           }

          …..

}

after you find the service that you are interested in. The next step is to explore the service’s characteristics to discover all characteristics of service simply call discoverCharacteristics:forservice: method of CBPeripheral class.

print(Discovering characteristic for service: \(interestedservice)”)

peripheral.discoverCharacteristics(nil,forService: service)

NOTE:
Here we discover all characteristics of peripheral’s service. Because a peripheral’s service may contain many more characteristic than you are interested in, instead of discovering all of them specify the UUIDs of the characteristic that you are interested in to save battery life and unnecessary use of time.
The peripheral calls peripheral:didDiscovercharacterisitcsForSerivce:error: method of its delegate object when characteristic of the specified service is discovered. Core bluetooth creates an array of CBCharacteristic objects, one for each characteristic that is discovered like this: –

func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) {

         if (error != nil) {

            print(“error: \(error?.localizedDescription)”)

               return

           }

       for characteristic in service.characteristics! {

           print(“Discovered characteristic: \(characteristic)”)

           ……

     }

    …..

}

Retrieving the value of a Characteristic

A characteristic contains a single value that represents more information about a peripheral’s service. you can retrieve the value of a characteristic by reading it directly or by subscribing to it.
After you have found a characteristic of service that you are interested in, you can read the characteristic value by calling readValueForCharacteristic: method by specifying appropriate characteristic.

print(Reading value for characteristic: \(interestedcharacteristic)”)

peripheral.readValueForCharacteristic(interestedcharacteristic)

when you read a value of characteristic, the peripheral calls peripheral:didUpdateValueForCharacteristic:error: method to retrieve the value. If the value is successfully retrieved, you can access it through the characteristic value property like this: –

func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {

     if (error != nil) {

                print(Error:\(error?.localizedDescription)”)

                return

      }

    var data: NSData = characteristic.value

    // parse the retrieved data

    ……..

}

Note:
All the characteristics values are not readable. You can determine whether a characteristic value is readable by accessing the CBCharacteristicPropertyRead constant. If you try to read a value that is not readable, the peripheral:didUpdateValueForCharacteristic:error method return suitable error.
When you subscribe to a characteristic value, you receive a notification from the peripheral when the value changes.
You can subscribe to the value of a characteristic that you are interested in by calling the setNotifyValue:forcharacteristic: method of CBPeripheral class, set value of first parameter as true, like this: –

peripheral.setNotifyValue(true, forCharacteristic: interestedcharacteristic)

When you attempts to subscribe to characteristic value, the peripheral calls peripheral:didUpdateNotificationStateForCharacteristic:error: method if the subscription request fails, you can implement this method to get actual cause of the error, like this: –

func peripheral(peripheral: CBPeripheral, didUpdateNotificationStateForCharacteristic characteristic: CBCharacteristic, error: NSError?) {

           if ((error) != nil) {

                print(Error changing notification state \(error?.localizedDescription)”)

            }

           else  {

                      print(Notification began on: \(characteristic)”)

                  }

}

After you have successfully subscribed to characteristic value, the peripheral notifies your app when the value has changed. each time the value changes the peripheral calls the peripheral:didUpdateValueForcharacteristic:error: method, to retrieve the updated value implement this method.

Writing the Value of a characteristic

If characteristic value is writable, you can write its value with some data by calling the writeValue:forcharacteristic:type: method of CBPeripheral class like this:

print(Writing value for characteristic: \(interestedcharacteristic)”)

peripheral.writeValue(data, forCharacteristic: interestedcharacteristic, type: .WithResponse)

when you attempts to write the value of a characteristic, specify the type of writing  you want to perform. In the above example, write type is specified as CBCharacteristicWriteWithResponse, which indicates the peripheral lets your app know whether the write is successful.
If you specified CBCharacteristicWriteType as CBCharacteristicWriteWithResponse the peripheral responds to your write request by calling peripheral:didWriteValueForCharacteristic:error: method.

func peripheral(peripheral: CBPeripheral, didWriteValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {

     if ((error) != nil) {

         print(Error Writing characteristic value \(error?.localizedDescription)”)

     }

}

Conclusion:

You can also refer a BLE-IOS-Data-Exchange project for more details.
After reading this tutorial, you should understand the core Bluetooth framework specifications and how you can use this to connect with low energy peripheral devices to retrieve certain attributes related to the device.

subscribe to our newsletter

   
   
Related Posts

Leave a Comment

Code ReviewImage-Compression-Android