蓝牙(CoreBluetooth) - Obj-C

  • iOS中提供了4个框架用于实现蓝牙连接:

1.GameKit.framework(用法简单,只能用于iOS设备间,iOS 7过期)
2.MultipeerConnectivity.framework(只能iOS设备间,iOS 7用来替代GameKit,WiFi蓝牙都支持,WiFi优先级高)
3.ExternalAccessory.framework(可用于第三方蓝牙设备交互,但需要蓝牙设备经过苹果MFi认证)
4.CoreBluetooth(可用于第三方蓝牙设备交互,必须要支持蓝牙4.0)

当前主要使用CoreBluetooth(CoreBluetooth下无法使用模拟器进行演示)

蓝牙使用时需要两个两个设备,一个作为中心,一个作为外设,作为手机端,既可以作为外设,也可以作为中心,这里主要演示手机作为中心设备的场景

  • CoreBluetooth实现的具体步骤主要有:
    1.创建中央管理者
    2.扫描外设
    3.连接外设
    4.查找服务
    5.查找特征
    6.读写数据

接收数据的示例代码:

#import "ViewController.h"
#import 

@interface ViewController () 
// 扫描蓝牙设备按钮
@property (weak, nonatomic) IBOutlet UIButton *scanBtn;
// 中央管理者(自己的设备)
@property (nonatomic,strong) CBCentralManager *centralManager;
// 外设(相对自己,手机端需要去连接的设备)
@property (nonatomic,strong) CBPeripheral *peripheral;
@end

@implementation ViewController


- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 1. 创建一个中央管理者 (传递nil,将使用主队列)
    self.centralManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
    
    self.scanBtn.enabled = NO;
}


// 扫描蓝牙
- (IBAction)scanBluetoothDevice{
    
    // 2. 扫描外设  (传递nil 扫描所有外设)
    [self.centralManager scanForPeripheralsWithServices:nil options:nil];
    
}

#pragma mark - CBCentralManagerDelegate

// 中央管理者已经更新状态后调用
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    
    /*
         CBCentralManagerStateUnknown = 0,  未知
         CBCentralManagerStateResetting,    正在重启
         CBCentralManagerStateUnsupported,  不支持
         CBCentralManagerStateUnauthorized, 未授权
         CBCentralManagerStatePoweredOff,   关闭蓝牙
         CBCentralManagerStatePoweredOn,    开启蓝牙  只有该状态才是正常情况
     */
    if (central.state == CBCentralManagerStatePoweredOn) { // 蓝牙开启
        
        // 当蓝牙开启时,扫描蓝牙
        self.scanBtn.enabled = YES;
        
    }
    
}
/**
 *  已经发现某个外设后调用
 *
 *  @param central           中央管理者
 *  @param peripheral        外设
 *  @param advertisementData 广播数据
 *  @param RSSI              信号强度 分贝
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
    
    // 3. 连接外设(使用场景:显示搜索到的蓝牙设备列表,UI展示供用户选择,判断名称后进行连接)
    
    /*
         NSString *const CBAdvertisementDataLocalNameKey;
         NSString *const CBAdvertisementDataManufacturerDataKey;
         NSString *const CBAdvertisementDataServiceDataKey;
         NSString *const CBAdvertisementDataServiceUUIDsKey;
         NSString *const CBAdvertisementDataOverflowServiceUUIDsKey;
         NSString *const CBAdvertisementDataTxPowerLevelKey;
         NSString *const CBAdvertisementDataIsConnectable;
         NSString *const CBAdvertisementDataSolicitedServiceUUIDsKey;
     */
    if ([advertisementData[CBAdvertisementDataLocalNameKey] isEqualToString:@"外设名称"]) {
        // 在查找到需要的设备后停止扫描外设
        [self.centralManager stopScan];
        // 连接外设
        [self.centralManager connectPeripheral:peripheral options:nil];
        // 记录外设
        self.peripheral = peripheral;
        
    }
    
}

/**
 *  已经连接到外设后调用
 *
 *  @param central    中央管理者
 *  @param peripheral 外设
 */
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    
    // 4. 查找服务  (传递nil,查找所有的服务)
    [peripheral discoverServices:nil];
    
    // 获取数据(查找的),设置外设的代理
    peripheral.delegate = self;
    
}

#pragma mark - CBPeripheralDelegate
/**
 *  已经查找到服务后调用
 *
 *  @param peripheral 外设
 *  @param error      错误信息
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    
    NSArray *serivicesArr = peripheral.services;
    // 遍历服务,查找指定的所务
    for (CBService *service in serivicesArr) {
        
        if ([service.UUID.UUIDString isEqualToString:@"服务的UUID"] ) {
            
            // 5. 查找特征
            [peripheral discoverCharacteristics:nil forService:service];
            
        }
    }
}
// 已经查找到特征后调用
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    
    // 判断特征的UUID是否是需求的特征
    for (CBCharacteristic *characteristic in service.characteristics) {
        
        if ([characteristic.UUID.UUIDString isEqualToString:@"特征的UUID"]) {
            
            // 6. 收发数据(读写数据)
            
            // 读
            [peripheral readValueForCharacteristic:characteristic];
            
        }
    }
}
// 当已经获取的更新的特征的数据后调用
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
    NSData *data = characteristic.value;
    NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
    
    
}
@end

如果需要发送数据,在didUpdateValueForCharacteristic中调用writeValue forCharacteristic方法

- (void)writeValue:(NSData *)data forCharacteristic:(CBCharacteristic *)characteristic type:(CBCharacteristicWriteType)type;

如果需要回应,发送数据时的类型需要为:CBCharacteristicWriteWithResponse

// 已经发送成功后调用
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
    NSLog(@"发送成功");
    
}

完整的发送数据实例代码:

#import "ViewController.h"
#import 

@interface ViewController () 
// 扫描蓝牙设备按钮
@property (weak, nonatomic) IBOutlet UIButton *scanBtn;
// 中央管理者(自己的设备)
@property (nonatomic,strong) CBCentralManager *centralManager;
// 外设
@property (nonatomic,strong) CBPeripheral *peripheral;
@end

@implementation ViewController


- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 1. 创建一个中央管理者 (传递nil,将使用主队列)
    self.centralManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
    
    self.scanBtn.enabled = NO;
    
    
}


// 扫描蓝牙
- (IBAction)scanBluetoothDevice{
    
    // 2. 扫描外设  (传递nil 扫描所有外设)
    [self.centralManager scanForPeripheralsWithServices:nil options:nil];
    
}

#pragma mark - CBCentralManagerDelegate

// 中央管理者已经更新状态后调用
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    
    /*
         CBCentralManagerStateUnknown = 0,  未知
         CBCentralManagerStateResetting,    正在重启
         CBCentralManagerStateUnsupported,  不支持
         CBCentralManagerStateUnauthorized, 未授权
         CBCentralManagerStatePoweredOff,   关闭蓝牙
         CBCentralManagerStatePoweredOn,    开启蓝牙  只有该状态才是正常情况
     */
    if (central.state == CBCentralManagerStatePoweredOn) { // 蓝牙开启
        
        // 当蓝牙开启时,扫描蓝牙
        self.scanBtn.enabled = YES;
        
    }
    
}
/**
 *  已经发现某个外设后调用
 *
 *  @param central           中央管理者
 *  @param peripheral        外设
 *  @param advertisementData 广播数据
 *  @param RSSI              信号强度 分贝
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
    
    // 3. 连接外设(使用场景:显示搜索到的蓝牙设备列表,UI展示供用户选择,判断名称后进行连接)
    
    /*
         NSString *const CBAdvertisementDataLocalNameKey;
         NSString *const CBAdvertisementDataManufacturerDataKey;
         NSString *const CBAdvertisementDataServiceDataKey;
         NSString *const CBAdvertisementDataServiceUUIDsKey;
         NSString *const CBAdvertisementDataOverflowServiceUUIDsKey;
         NSString *const CBAdvertisementDataTxPowerLevelKey;
         NSString *const CBAdvertisementDataIsConnectable;
         NSString *const CBAdvertisementDataSolicitedServiceUUIDsKey;
     */
    if ([advertisementData[CBAdvertisementDataLocalNameKey] isEqualToString:@"外设名称"]) {
        
        // 连接外设
        [self.centralManager connectPeripheral:peripheral options:nil];
        // 记录外设
        self.peripheral = peripheral;
        
    }
    
}

/**
 *  已经连接到外设后调用
 *
 *  @param central    中央管理者
 *  @param peripheral 外设
 */
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    
    // 4. 查找服务  (传递nil,查找所有的服务)
    [peripheral discoverServices:nil];
    
    // 获取数据(查找的),设置外设的代理
    peripheral.delegate = self;
    
}

#pragma mark - CBPeripheralDelegate
/**
 *  已经查找到服务后调用
 *
 *  @param peripheral 外设
 *  @param error      错误信息
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    
    NSArray *serivicesArr = peripheral.services;
    // 遍历服务,查找指定的所务
    for (CBService *service in serivicesArr) {
        
        if ([service.UUID.UUIDString isEqualToString:@"服务的UUID"] ) {
            
            // 5. 查找特征
            [peripheral discoverCharacteristics:nil forService:service];
            
        }
    }
}
// 已经查找到特征后调用
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    
    // 判断特征的UUID是否是需求的特征
    for (CBCharacteristic *characteristic in service.characteristics) {
        
        if ([characteristic.UUID.UUIDString isEqualToString:@"特征的UUID"]) {
            
            // 6. 收发数据(读写数据)
            
            // 读
            [peripheral readValueForCharacteristic:characteristic];
            
        }
    }
}
// 当已经获取的更新的特征的数据后调用
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
    // 发送数据
    NSString *write = @"发送数据";
    /*
     CBCharacteristicWriteWithResponse = 0, 回应
     CBCharacteristicWriteWithoutResponse,  只发送,不知道是否成功
     */
    [peripheral writeValue:[write dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
    
    
}
// 已经发送成功后调用
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
    NSLog(@"发送成功");
}
@end

你可能感兴趣的:(蓝牙(CoreBluetooth) - Obj-C)