Zero based iOS Bluetooth development

Preface

In this paper, the author recorded the process of the first contact with Bluetooth and the use of App to communicate with peripheral Bluetooth devices. Only discuss App as a central device, not including App as a peripheral device.

IOS using Core Bluetooth framework to achieve Bluetooth communication. Core Bluetooth is based on Bluetooth 4 low-power mode.

Bluetooth connection is similar to the Client/Server framework model. Central equipment as the client, the peripheral device as a server, scan and establish a connection for data exchange.

In the beginning of the coding, the first familiar with the Bluetooth communication in iOS involves several categories, moving bricks without effort.

Get ready

Bluetooth class diagram:

Zero based iOS Bluetooth development
bluetooth.001.png
  • CBCentralManager class represents the central device, scanning found around the Bluetooth device, the surrounding Bluetooth devices with CBPeripheral class.
  • A Bluetooth device may be used for a variety of purposes, each of which corresponds to a service that uses a CBService representation, such as a heart rate sensor heart rate monitoring service.
  • A service can be broken down into a variety of features, the use of CBCharacteristic, such as heart rate monitoring services, including heart rate measurement, location of geographic location, such as Characteristic.
  • A feature can be described in many ways, with CBDescriptor representation.

The above mentioned CBService, CBCharacteristic, and CBDescriptor classes are inherited from CBAttribute, which have a common property of CBUUID, used as the only identifier.

Peripheral as the Server side, Central as Client, Peripheral broadcast its Services and Characteristics, Central can choose to subscribe to a specific Service, you can subscribe to all the Server (not recommended). After getting to a Service, you also need to continue to discover the Characteristics under this service. Peripheral and Central through the Characteristic to establish a two-way data channel.

Must pay attention to the use of real test.

Code

After iOS 10 need to set up the NSBluetoothPeripheralUsageDescription field in the Info.plist file, add a description of the access to Bluetooth privileges, otherwise forced access to Bluetooth will cause Crash.

To start a central device:

CBCentralManager *centralManager = [[CBCentralManager initWithDelegate:self queue:nil options:nil]; _centralManager = centralManager alloc];

There is a note that the CBCentralManager is asynchronous, and if it is not held by the class that is currently being created, it will be released at the next RunLoop iteration. Of course, if not the instance of CBCentralManager is created in ViewController, then hold CBCentralManager of this class after initialization must also be held by ViewController, otherwise there will be the following error output console:

[CoreBluetooth] XPC connection invalid

If successful, it will call back CBCentralManagerDelegate:

/ / in cetral state to the CBManagerStatePoweredOn start scanning - (void) centralManagerDidUpdateState: (CBCentralManager * central) {if (central.state = = CBManagerStatePoweredOn) {[_centralManager scanForPeripheralsWithServices:nil options:nil]}};

When the equipment is in the state of the PowerOn center to scan the peripheral equipment, using the specified UUID found the specific Service, can also be passed to nil, said that all the surrounding Bluetooth devices, but it is recommended that only they need service equipment. The following methods will be found after the callback:

- (void) centralManager: (CBCentralManager * central) didDiscoverPeripheral: (CBPeripheral *) peripheral advertisementData: (NSDictionary< NSString id> * *, advertisementData) RSSI: (NSNumber * RSSI) {if (peripheral.name!) return Ingore name is nil peripheral.; / / if ([_peripheralsList! ContainsObject:peripheral]) {[_peripheralsList addObject:peripheral]; _peripherals = _peripheralsList.copy;}}

After the success of the device, select a peripheral to establish a connection, after the establishment of the connection to stop the discovery:

[_centralManager connectPeripheral:peripheral options:nil];

After the connection is successful, you will continue to call the CBCentralManagerDelegate method:

- (void) centralManager: (CBCentralManager * central) didConnectPeripheral: (CBPeripheral * peripheral) {peripheral.delegate = self; / / Client to do discover services method... CBUUID *seriveUUID [CBUUID UUIDWithString:@ = "d2009d00-6000-1000-8000-XXXX"]; / / `nil` represents the discovery of all services. [peripheral discoverServices:@[seriveUUID]];}

After connecting to the peripheral device, discover the specific service that needs to be used.
next is the response to the CBPeripheralDelegate proxy method.

Response method for successful detection of a service of peripheral devices:

/ / discovery service - (void) peripheral: (CBPeripheral *) peripheral didDiscoverServices: (nullable NSError * error *services) {NSArray = peripheral.services; if (services) {CBService *service = services[0]; CBUUID = *writeUUID [CBUUID UUIDWithString: TRANSFER_SERVICE_UUID]; CBUUID *notifyUUID = [CBUUID UUIDWithString: TRANSFER_SERVICE_UUID]; [peripheral discoverCharacteristics:@[writeUUID, notifyUUID] forService:service];}} / / discovery service

After discovery service (CBService), also need to find the characteristics of the service (Characteristic). There are usually two features: writing and notification features.

After the discovery of the characteristics must open the notification feature, no write data, will not receive the reply data.

Discovery feature - (void) / (CBPeripheral * peripheral:) peripheral didDiscoverCharacteristicsForService: (CBService * service) error: (nullable * NSError) {if (error! Error) {NSArray *characteristicArray = service.characteristics; if (characteristicArray.count > 1) {CBCharacteristic *writeCharacteristic = characteristicArray[0] CBCharacteristic; *notifyCharacteristic = characteristicArray[1]; / / `YES` enable notification can make the notice, only, `NO` disable notifications and indications [peripheral setNotifyValue:YES forCharacteristic:notifyCharacteristic];}} else {NSLog ("Discover Charactertics @ Error:% @", error);}}

Use writeCharactersitc to write data:

[peripheral writeValue:writeData.copy forCharacteristic:writeCharactersitc type:CBCharacteristicWriteWithResponse];

After the data is written, the following two proxy methods will be returned on the premise of the need to reply:

/ / write successful - (void) peripheral: (CBPeripheral * peripheral) didWriteValueForCharacteristic: (CBCharacteristic * characteristic) error: (nullable * NSError) {if (error! Error) {NSLog (@ "Write Success");} else {NSLog ("WriteVale Error = @% @", error);}} / / write successful the response - (void) peripheral: (CBPeripheral * peripheral) didUpdateValueForCharacteristic: (CBCharacteristic * characteristic) error: (NSError * error) {if (error) {NSLog ("update value error: @% @", error);} else {NSData *responseData = characteristic.value;}}

So far, a complete Bluetooth communication is completed.

Bluetooth data packet load is relatively small, in the process of answering, often need to dismantle, combination. The first byte of the packet represents the serial number of the package.

Demo address

Reference resources

Core Bluetooth Overview iOS development fun Bluetooth CoreBluetooth