今天项目中的蓝牙功能已经开发完毕,总结一下。
CoreBluetooth.framework:功能强大的蓝牙框架,只要该设备支持蓝牙4.0,就可以进行蓝牙传输,只要该设备支持蓝牙4.0。
CoreBluetooth中分为两大设备:中央设备和外围设备。
1.如果一个设备设置为外围设备,那他负责发布并广播服务,通知周围的中央设备它的可用服务和特征,相当于通信中的服务端
2.如果设备设置为中央设备,那他负责和外围设备建立连接,连接成功可以使用外围设备的服务和特征,相当于通信中的客户端。
即:
外围设备 —–类似于——-》服务器端
中央设备 —–类似于——-》客户端

这两大设备进行交互靠的是服务和特征。服务和特征都有唯一标识CBUUID来确定。
1.服务CBService:
中央设备只有通过服务才能与外围设备进行数据传输,类似于客户端通过网址URL才能与服务器连接一样
2.特征CBCharacteristic:
每个服务可以有多个特征,中央设备必须订阅外围设备服务的特征值,才能获取外围设备的数据,类似于GET请求可以请求获取服务器数据,POST请求可以向服务器传输数据一样。

一般我们需要的是中央设备,外围设备可以是手环,耳机……
设备作为中央设备 实现过程如下:

1.创建中央设备管理器对象,遵循代理CBCentralManagerDelegate

self.manager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()];
    self.BleViewPerArr = [[NSMutableArray alloc]initWithCapacity:1];


2.代理方法 判断设备的蓝牙是否开启

- (void)centralManagerDidUpdateState:(CBCentralManager *)central{

        switch (central.state) {
            case CBCentralManagerStatePoweredOff:
                NSLog(@"您的手机蓝牙未开启");
                break;
            case CBCentralManagerStateResetting:
                NSLog(@"检测到您的手机蓝牙重置");
                break;
            case CBCentralManagerStateUnsupported:
                NSLog(@"检测到您的手机不支持蓝牙4.0");
                break;
            case CBCentralManagerStateUnauthorized:
                NSLog(@"检测到您的手机蓝牙没有授权");
                break;
            case CBCentralManagerStateUnknown:
                NSLog(@"未知状态");
                break;
            case CBCentralManagerStatePoweredOn:
                NSLog(@"检测到您的手机蓝牙正常开启,可以扫描外围设备");
                break;
            default:
                break;
        }
}


只有在蓝牙正常开启状态下才可以进行扫描
3.开始扫描外围设备

/*
    判断状态开始扫瞄周围设备 第一个参数为空则会扫瞄所有的可连接设备  你可以
    指定一个CBUUID对象 从而只扫瞄注册用指定服务的设备
    */
    [self.manager scanForPeripheralsWithServices:nil options:nil];
    //清空所有外设数组 没扫描一次最好清空数据源 以备战展示用
    [self.BleViewPerArr removeAllObjects];


4.扫描完成会调用CBCentralManagerDelegate代理方法

/*
 发现外围设备调用
  central           中央设备管理器
  peripheral        外围设备
  advertisementData 设备信息
  RSSI              信号质量(信号强度)可以用判断周边设备离中央设备的远近
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI方法{
    if (peripheral == nil||peripheral.identifier == nil/*||peripheral.name == nil*/)
    {
        return;
    }
    //存放在数据源中
    NSString *pername=[NSString stringWithFormat:@"%@",peripheral.name];
    //判断是否存在@"你的设备名"
    NSRange range=[pername rangeOfString:@"你的设备名"];
    //如果从搜索到的设备中找到指定设备名,和BleViewPerArr数组没有它的地址
    //加入BleViewPerArr数组
    if(range.location!=NSNotFound&&[_BleViewPerArr containsObject:peripheral]==NO){
        [_BleViewPerArr addObject:peripheral];
    }
    //刷新自己的列表
    [_tableView reloadData];
}


以上就扫描到了外围设备,当然还需要将外围设备,展示在列表上

/*蓝牙对象在下面环节会查找出来,被放进BleViewPerArr数组里面,是CBPeripheral对象,取出name
    */
    CBPeripheral *per=(CBPeripheral *)_BleViewPerArr[indexPath.row];
    cell.textLabel.text =per.name;


5.接下来就是连接设备了,遵循外围设备对象代理CBPeripheralDelegate 我是在tableView的didSelect方法里连接的,如果确定只有一个设备,可以下载上面的方法里 直接连接

CBPeripheral *peripheral=(CBPeripheral *)_BleViewPerArr[indexPath.row];
    //设定周边设备,指定代理者
    peripheral.delegate = self;
    //连接设备
    [_manager connectPeripheral:peripheral
                        options:nil];


6.中央设备管理器成功连接到外围设备后调用

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    //设置设备代理
    [peripheral setDelegate:self];
    //大概获取服务和特征,或许只获取你的设备蓝牙服务的uuid数组,一个或者多个;
    //用 UUIDWithString 添加数组
    [peripheral discoverServices:nil];
    //停止扫描
    [_manager stopScan];
}
<font color=#0099ff size=2>

7.连接失败

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
    NSLog(@"error ==%@",error);
}


8.外围设备寻找到服务后调用CBPeripheralDelegate代理方法

- (void)peripheral:(CBPeripheral *)peripheral 
        didDiscoverServices:(NSError *)error
{    
    if (error) {
        NSLog(@"Error discovering services: %@", [error     localizedDescription]);
        return;
    }
    //已发现可用服务
    //遍历查找到的服务
    CBUUID *serviceUUID = [CBUUID UUIDWithString:@"你的设备服务的uuid"];
    CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID];
    for (CBService *service in peripheral.services) {
        if([service.UUID isEqual:@"你的设备服务的uuid"]){
            //外围设备查找指定服务中的特征,characteristics为nil,表示寻找所有特征
            [peripheral discoverCharacteristics:nil forService:service];
        }
    }
}


9.围设备寻找到特征后调用CBPeripheralDelegate代理方法

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    if (error)
    {
        NSLog(@"Discovered characteristics for %@ with error: %@", service.UUID, [error localizedDescription]);
        return;
    }
    NSLog(@"服务:%@",service.UUID);
    // 特征
    for (CBCharacteristic *characteristic in service.characteristics)
    {
        NSLog(@"%@",characteristic.UUID);
        //发现特征
        //注意:uuid 分为可读,可写,要区别对待!!!
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"你的特征uuid"]])
       {
            NSLog(@"监听:%@",characteristic);//监听特征
            //保存characteristic特征值对象
            //以后发信息也是用这个uuid
            _characteristic1 = characteristic;
            [_discoveredPeripheral setNotifyValue:YES forCharacteristic:characteristic];
        }

        /*当然,你也可以监听多个characteristic特征值对象
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"你的特征uuid"]])
        {
            //同样用一个变量保存,demo里面没有声明变量,要去声明
                       _characteristic2 = characteristic;
                       [peripheral setNotifyValue:YES forCharacteristic:_characteristic2];
                        NSLog(@"监听:%@",characteristic);//监听特征
       }
       */

    }
}


10.外围设备读取到特征值后调用

- (void)peripheral:(CBPeripheral *)peripheral 
        didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
      if (error)
      {
        NSLog(@"Error updating value for characteristic %@ error: %@", characteristic.UUID, [error localizedDescription]);
        return;
     }
     //收到的数据
    if (characteristic.value) { 
        NSString *value = [[NSString alloc] initWithData:characteristic.value 
                                                encoding:NSUTF8StringEncoding];
        NSLog(@"读取到特征值:%@",value); 
    }else{
        NSLog(@"未发现特征值."); 
    }
}


至此 整个中央设备连接外围设备连接成功完成!
总结:
蓝牙连接可以大致分为以下几个步骤
1.建立一个Central Manager蓝牙管理对象
2.搜索外围设备
3.连接外围设备
4.获得外围设备的服务
5.获得服务的特征