一.概念

1.引用的框架是CoreBluetooth,在iphone4s开始支持,专门用于与BLE设备通讯(因为它的API都是基于BLE的)。这个不需要MFI,并且现在很多蓝牙设备都支持4.0,所以也是在IOS比较推荐的一种开发方法。

2.CoreBluetooth框架的核心其实是两个东西,peripheral和central, 可以理解成外围和中心。如下图所示:

苹果IOS 蓝牙SPP ipone蓝牙_代码实现


苹果IOS 蓝牙SPP ipone蓝牙_#define_02


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);
}