A look at the CBPeripheral class of iOS

Hi !

In this article we will look at the CBPeripheral class of iOS which handles all communication and managing of a single peripheral (device, slave etc).

Each time a peripheral is detected by the CBCentralManager, the didDiscoverPeripheral callback is called, it is accompanied by a CBPeripheral instance called peripheral.

OK, let start with the delegate functions from CBPeripheralDelegate protocol as these are mentioned thoroughly throughout the text :

didDiscoverCharacteristicsForService,is called after a discoverCharacteristicsForService is called, it is called one time for each service it is run on.

didDiscoverDescriptorsForCharacteristics, is called after a discoverDescriptorsForCharacteristics call is run.

didDiscoverIncludedServicesForService, is called after a discoverIncludedServicesForService call is run.

didDiscoverServices, is called after a discoverServices call is run. It is called to tell its delegate that the services array now is filled with the Services on the peripheral.

didUpdateNotificationStateForCharacteristic, is called after a setNotificationStateForCharacteristic is called. If the characteristic does not have support for notifications, an error is returned in the error property if the called failed.

didUpdateValueForCharacteristic, is called either if a readValueForCharacteristic is called, or if notifications are enabled and the peripheral has updated the value of the characteristic.

same as above, though using CBDescriptors instead of CBCharacteristic directly.

didWriteValueForCharacteristic, is called when a write operation is complete or failed.

same as above, using CBDescriptors.

peripheralDidUpdateRSSI, is called after a readRSSI call is run, when it is called, the new RSSI value is correct from the peripheral.

 

The properties of a CBPeripheral class worth mentioning are :

This is an UUID reference generated by the iOS device, this is the property which is nil, on some devices when they are discovered but not connected. After a connection to the device, this property is always a valid CFUUIDRef. This property is often stored to be used to uniquely identify the device. The UUID for a given peripheral is stored on the iOS device for all future, and is the same across versions of iOS (to my knowledge anyhow :) .

This number represents the RSSI of the link between the peripheral and the iOS device. This number is updated when readRSSI is called on the CBPeripheral.

The device name, it is assigned as follows : When device is first detected and the didDiscoverPeripheral callback is called, it is assigned to the name that is contained in the Advertisement data (if any). Often the didDiscoverPeripheral callback is called again, when the “Scan Response” data is received by the iOS device, the name is then updated to what is contained in this data.

The device name, it is assigned as follows : When device is first detected and the didDiscoverPeripheral callback is called, it is assigned to the name that is contained in the Advertisement data (if any). Often the didDiscoverPeripheral callback is called again, when the “Scan Response” data is received by the iOS device, the name is then updated to what is contained in this data.

When a device is first discovered, the services array is empty, when the device is connected, calling the discoverServices function on a peripheral discovers its services and assigns an array of the services in the services property of the CBPeripheral class. All services are discovered in one iteration, the didDiscoverServices, is only called once on each device. We will look more into the CBService later …

Now, lets look at the functions of CBPeripheral :

discoverCharacteristics forService, this function is used to get the CBCharacteristics for a given service, typically it is used during service discovery of a newly found device, I usually call it from the didDiscoverServices function. The function is only called for one given service. This means that for each of the services in the service array, this function must be called, and for each call of discoverCharacteristics, a didDiscoverCharacteristic callback is called.

discoverDescriptorsForCharacteristic, this function is a “simplified” interface to write and read from characteristics, I do not personally use it because I found it easier to use the CBCharacteristic directly in read and writes.

discoverIncludedServices forService, this function is used to discover subServices of a primary service.

discoverServices, one call to this function discovers all services on the device, or only the ones included in the array serviceUUIDs. When the services have been discovered over the air, the didDiscoverServices callback is called.

readRSSI, call this function when a peripheral is connected, to get a didUpdateRSSI callback with the current RSSI in dB of the RF link.

readValueForCharacteristic, this function is used to read the current value of a characteristic from a peripheral. It is called with the CBCharacteristic to read, didUpdateValueForCharacteristic will be called for each of the readValueForCharacteristic run.

readValueForDescriptor, is the same as above only using a CBDescriptor instead of the CBCharacteristic and that the didUpdateValueForDescriptor is called as callback.

setNotifyValue forCharacteristic, this function enables notifications for CBCharacteristics that support notification (checked by oring the properties parameter of the CBCharacteristic value with CBCharacteristicPropertyNotify), for each time a notification is received from the peripheral a didUpdateValueForCharacteristic is called.

writeValue forCharacteristic writeType, this function is the primary function for writing to a characteristic on a device. the writeType property is either set to write with no response or write with response. When write with response is used, all writes to the peripheral are cached while the iOS device is waiting to receive the ok response and the callback. When write no response is used, the data will not be cached. This is important when using things which need low latency, like an RC car or helicopter etc. when using write with response, the iOS device may sometime lag behind, which does not make great response … For each write the didWriteCharacteristic callback is called.

writeValue forDescriptor, same as above, only using descriptors and didWriteDescriptor.

 

Using the CBPeripheral class in your program :

Initializing :

The CBPeripheral class is not initialised by the programmer of a CoreBluetooth application, it is initialised by CoreBluetooth and delivered to us by the didDiscoverPeripheral function of CBCentralManager.

Normal flow of handling a CBPeripheral :

didDiscoverPeripheral:

  • Generate a list and add the peripherals to it (NSMutableArray), or we do a check against a stored UUID to find our previously connected and stored peripheral :

or

  • Connect to peripheral (calling connectPeripheral), or enable a button or menu to let user connect to a device.

 

didConnectPeripheral:

  • Start service discovery (peripheral discoverServices)

didDiscoverServices:

  • Start characteristic discovery (peripheral discoverCharacteristics forService) for each service, or only the one we need

didDiscoverCharacteristics:

  • Peripheral is fully configured in the iOS “world” and we can continue with read and writes

Reading and writing :

Reading and writing to a peripheral is the main thing we are doing all of this for, the main principle is as follows :

We need to know :

  • Peripheral to read from / write to / setting notifications for
  • UUID of the service that contains the characteristic (this is not entirely necessary as one could search all services and all characteristics …)
  • UUID of the characteristic we are going to write to / read from /setting notifications for
  • Value to write in case of write or notification setting.

What to do :

  • Peripheral we know.
  • UUID of the service we find by going through the different services in the peripheral.services array :

What happens :

  • Callback from CBPeripheralDelegate :

4 Responses to A look at the CBPeripheral class of iOS

  1. amin says:

    Hi, Thanks for your great blog. There is no documentation for CBPeripheral yet in Core Bluetooth.

    I want to put some little data in advertising packet (like a room Id). Which function is meant to do this? I want to skip connection between central and peripheral. Central will get the id and from advertising packet without the need to connect.

  2. Omkar Zunjurke says:

    Hi,
    thanks this is great post
    I refer your code to discover all bluetooth device in iphone programmatically but did not work I just want list all bluetooth device programmatically using core bluetooth.
    how can i do this
    I used
    self.cm=[[CBCentralManager alloc] initWithDelegate:self queue:nil];
    [self.cm scanForPeripheralsWithServices:nil options:nil];

    and implement this delegates
    -(void)centralManagerDidUpdateState:(CBCentralManager *)central{
    NSLog(@”Update the state”);

    // self.cBReady = false;
    switch (central.state) {
    case CBCentralManagerStatePoweredOff:
    NSLog(@”CoreBluetooth BLE hardware is powered off”);
    break;
    case CBCentralManagerStatePoweredOn:
    NSLog(@”CoreBluetooth BLE hardware is powered on and ready”);
    //self.cBReady = true;
    break;
    case CBCentralManagerStateResetting:
    NSLog(@”CoreBluetooth BLE hardware is resetting”);
    break;
    case CBCentralManagerStateUnauthorized:
    NSLog(@”CoreBluetooth BLE state is unauthorized”);
    break;
    case CBCentralManagerStateUnknown:
    NSLog(@”CoreBluetooth BLE state is unknown”);
    break;
    case CBCentralManagerStateUnsupported:
    NSLog(@”CoreBluetooth BLE hardware is unsupported on this platform”);
    break;
    default:
    break;
    }

    }
    -(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
    NSLog(@”didDiscoverPeripheral %@”,peripheral.name);

    }
    but it still not list any device in code…
    waiting for your reply
    thanks in advance

  3. 12345 says:

    erfgfergfergver

  4. 12345 says:

    fgdsbvdfsfgvdfdfb

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">