一.概念
1.引用的框架是CoreBluetooth,在iphone4s开始支持,专门用于与BLE设备通讯(因为它的API都是基于BLE的)。这个不需要MFI,并且现在很多蓝牙设备都支持4.0,所以也是在IOS比较推荐的一种开发方法。
2.CoreBluetooth框架的核心其实是两个东西,peripheral和central, 可以理解成外围和中心。如下图所示:
3.特征和服务
有个概念有必要先说明一下。什么是服务和特征呢(service and characteristic)?
每个蓝牙4.0的设备都是通过服务和特征来展示自己的,一个设备必然包含一个或多个服务,每个服务下面又包含若干个特征。特征是与外界交互的最小单位。比如说,一台蓝牙4.0设备,用特征A来描述自己的出厂信息,用特征B来与收发数据等。
服务和特征都是用UUID来唯一标识的,UUID的概念如果不清楚请自行google,国际蓝牙组织为一些很典型的设备(比如测量心跳和血压的设备)规定了标准的service UUID.
4.作为一个中心要实现完整的通讯,一般要经过这样几个步骤:
建立中心角色—扫描围(discover)—连接外围(connect)—扫描外围中的服务和特征(discover)—与外围做数据交互(explore and interact)—断开连接(disconnect)。
二.代码实现.
1.外围工程类代码实现如下:
/**创建一个外围类*/
#import "ViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>
/**服务端的UUID*/
#define kServiceUUID @"3AF70026-AB81-4EF2-B90B-9C482B4812F1"
/**特征端的UUID*/
#define kCharacteristicUUID @"2F5A22C7-7AB5-446A-9F94-4E9B924BE508"
@interface ViewController ()<CBPeripheralManagerDelegate>{
/**1.创建一个外围管理者*/
CBPeripheralManager* _manager;
/**2.创建服务端*/
CBMutableService* _service;
/**3.创建一个特征端*/
CBMutableCharacteristic* _characteristic;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
/**4.实例化一个特征类*/
_manager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
}
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"发现外设");
}
/**5.检测中央设备状态*/
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{
/**5.1.如果不是打开的,打印蓝牙关闭,直接返回,调用开始中心服务,CBCentralManagerStatePoweredOn,表示蓝牙打开*/
if (peripheral.state != CBCentralManagerStatePoweredOn){
NSLog(@"蓝牙关闭");
return;
}
//开始中心服务
[self startService];
}
/**6.开始中心服务*/
- (void)startService{
/**6.1通过uuid创建一个特征,kCharacteristicUUID特征类的UUID,UUID是唯一标识,通过唯一标识可以找到设备*/
CBUUID* characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID];
/**6.2第一个参数uuid,第二个参数决定这个特征怎么去用,第三个是是否加密*/
_characteristic = [[CBMutableCharacteristic alloc] initWithType:characteristicUUID properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable];
/**6.3创建一个服务uuid*/
CBUUID* serviceUUID = [CBUUID UUIDWithString:kServiceUUID];
/**6.4通过uuid创建服务*/
_service = [[CBMutableService alloc] initWithType:serviceUUID primary:YES];
/**6.5给服务设置特征*/
[_service setCharacteristics:@[_characteristic]];
/**6.6使用这个服务,添加到管理者中*/
[_manager addService:_service];
}
/**7.添加服务后的回调*/
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error{
/**7.1如果没有错误,就可以开始广播服务了*/
if (error == nil) {
[_manager startAdvertising:@{
CBAdvertisementDataLocalNameKey:@"PKServer",
CBAdvertisementDataServiceUUIDsKey:@[[CBUUID UUIDWithString:kServiceUUID]]
}];
//[_manager updateValue:[@"pk" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:_characteristic onSubscribedCentrals:]
}
}
/**8.有人连接成功后调用*/
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic{
NSLog(@"连接成功");
[_manager updateValue:[@"pk" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:_characteristic onSubscribedCentrals:@[central]];
}
/**9.断开调用*/
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic{
NSLog(@"断开");
}
@end
2.中心工程类代码实现如下:
#import "ViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>
/**服务UUID*/
#define kServiceUUID @"3AF70026-AB81-4EF2-B90B-9C482B4812F1"
/**特征UUID*/
#define kCharacteristicUUID @"2F5A22C7-7AB5-446A-9F94-4E9B924BE508"
@interface ViewController ()<CBCentralManagerDelegate, CBPeripheralDelegate>{
CBCentralManager* _manager;
NSMutableData* _data;
CBPeripheral* _peripheral;
}
@end
@implementation ViewController
- (void)viewDidLoad {
/**创建一个中央*/
_manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
if (central.state != CBCentralManagerStatePoweredOn) {
NSLog(@"蓝牙未打开");
return;
}
/**开始寻找所有的服务*/
[_manager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:kServiceUUID]] options:@{
CBCentralManagerScanOptionAllowDuplicatesKey:@YES
}];
}
/**寻找到服务*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
/**停止寻找*/
[_manager stopScan];
if (_peripheral != peripheral) {
_peripheral = peripheral;
/**开始连接周边*/
[_manager connectPeripheral:_peripheral options:nil];
}
}
/**连接周边成功*/
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
[_data setLength:0];
_peripheral.delegate = self;
/**连接周边服务*/
[_peripheral discoverServices:@[[CBUUID UUIDWithString:kServiceUUID]]];
}
/**连接周边失败*/
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"连接失败");
}
/**连接周边服务*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
if (error) {
NSLog(@"错误的服务");
return;
}
/**遍历服务*/
for (CBService* service in peripheral.services) {
if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]) {
/**连接特征*/
[_peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:kCharacteristicUUID]] forService:service];
}
}
}
/**发现特征*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
if (error) {
NSLog(@"连接特征失败");
return;
}
/**遍历特征*/
if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]) {
for (CBCharacteristic* characteristic in service.characteristics) {
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicUUID]]) {
/**开始监听特征*/
[_peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
}
}
/**监听到特征值更新*/
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
if (error) {
NSLog(@"特征值出错");
return;
}
if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicUUID]]) {
return;
}
/**如果有新值,读取新的值*/
if (characteristic.isNotifying) {
[peripheral readValueForCharacteristic:characteristic];
}
}
/**收到新值*/
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
NSString* str = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
NSLog(@"%@", str);
}