美文网首页
iOS蓝牙开发

iOS蓝牙开发

作者: ___吉 | 来源:发表于2017-01-11 22:05 被阅读0次

    iOS蓝牙开发有三个框架

    1.GameKit.framework:iOS7之前的蓝牙通讯框架,从iOS7开始过期。
    2.MultipeerConnectivity.framework:iOS7开始引入的新的蓝牙通讯开发框架,用于取代GameKit。
    3.CoreBluetooth.framework:功能强大的蓝牙开发框架,要求设备必须支持蓝牙4.0。目前蓝牙开发多半基于此框架,此笔记也是写基于此框架。
    

    蓝牙开发有两种模式:
    1.手机作为中心设备,获取外设的数据
    2.手机作为外设,对外提供数据(这里不做讨论)

    本文记录的是利用tableView展示所有扫描到的外设,点击某行时连接对应的外设进行数据交互
    实现流程如下:

    1.导入蓝牙库,宏定义服务UUID、读数据UUID、写数据UUID
    #import <CoreBluetooth/CoreBluetooth.h>
    
    #define     kServiceUUID        @"1234"//服务UUID
    #define     kReadUUID           @"1236"//读数据UUID
    #define     kWriteUUID          @"1235"//写数据UUID
    
    @property (nonatomic, strong) CBPeripheral   *peripheral;               //外设
    @property (nonatomic, strong) CBCentralManager *myCentralManager;       //管理中心
    @property (nonatomic, strong) CBCharacteristic *readCharacteristic;     //读取数据特性
    @property (nonatomic, strong) CBCharacteristic *writeCharacteristic;    //写数据特性
    
    2.创建蓝牙管理中心
     _myCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];//如果设置为nil,默认在主线程中跑。设置了代理为self,记得遵守协议
    
    3.监测蓝牙状态,如果蓝牙开启则扫描外设
    - (void)centralManagerDidUpdateState:(CBCentralManager *)central{
        switch (central.state){
            case CBCentralManagerStateUnknown:
                break;
            case CBCentralManagerStateUnsupported:
                JCLog(@"模拟器不支持蓝牙调试");
                break;
            case CBCentralManagerStateUnauthorized:
                break;
            case CBCentralManagerStatePoweredOff:{
                JCLog(@"蓝牙处于关闭状态");
            }
                break;
            case CBCentralManagerStateResetting:
                break;
            case CBCentralManagerStatePoweredOn:{
                JCLog(@"蓝牙已开启");
                //开始扫描外设
                [_myCentralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey:[NSNumber numberWithBool:NO]}];
            }
                break;
        }
    }
    
    4.实现代理方法。当扫描到外部设备时会进入         发现外设        的代理方法
    - (void)centralManager:(CBCentralManager *)central //管理中心
     didDiscoverPeripheral:(CBPeripheral *)peripheral //发现的外设
         advertisementData:(NSDictionary *)advertisementData //外设中的广播数据
                      RSSI:(NSNumber *)RSSI //外设信号强度
    {
        
    //    JCLog(@"蓝牙广播数据------>>%@",advertisementData);
    //每次扫描出一个外设都会进入此代理方法,在此方法中可以将外设添加到外设数组中,在添加进数组之前,判断一下数组中是否已经添加过这个外设,如果添加过,则不再添加。
    if(![_allperipherals containsObject:peripheral]){
            [_allperipherals addObject:peripheral];
    //添加了新的外设进去,刷新tableview
           [_tableView reloadData];
        }
    
    5.连接外设
    //在选中某行cell的代理方法中,调用连接蓝牙外设的方法
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
    //需要连接的外设必须强引用,否则出了此方法作用域后会被释放掉,导致蓝牙断开连接,控制台输出错误信息
        _peripheral = _allperipherals[indexPath.row];
        JCLog(@"连接蓝牙:%@",_peripheral.name);
        [_myCentralManager connectPeripheral:_peripheral options:nil];//连接蓝牙
    }
    
    6.蓝牙连接成功,会调用代理方法
    - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
    {
    //    JCLog(@"成功连接%@",peripheral.name);
        _peripheral = peripheral;
        peripheral.delegate = self;
        //开始寻找外设服务
        [peripheral discoverServices:nil];
    /*
    关于外设服务是什么的理解:
    每个蓝牙4.0的设备都是通过服务和特征来展示自己的,一个设备必然包含一个或多个服务,每个服务下面又包含若干个特征。
    特征是与外界交互的最小单位。比如说,一台蓝牙4.0设备,用特征A来描述自己的出厂信息,用特征B来与收发数据等。
    此处应用时可以借助一个叫:LightBlue的App来理解蓝牙外设的服务及特征值。
    最近做的一个蓝牙项目中,硬件工程师选择的蓝牙模块有提供开发文档,文档中有提供 服务值 及 读取数据 和 写数据 的特征值。按照文档中提供的对应的值填写即可。借助LightBlue也可以看到服务值和读写数据特征值。具体值,参考步骤1中的三个宏定义。
    理解不是很到位,请见谅。
    */
    }
    
    连接外部蓝牙设备失败调用此方法,可在此再次连接外设
    - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
    {
    //如何实现自动断线重连,就是在断开的委托方法中,执行连接蓝牙的方法  可以在此处重新调用连接蓝牙方法
    //    JCLog(@"连接%@失败--error:%@",peripheral.name,error);
        [_myCentralManager connectPeripheral:_peripheral options:nil];//连接蓝牙
    }
    
    7.发现蓝牙外设服务,调用此方法
    -(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
        
        if(error){
            JCLog(@"外围设备寻找服务过程中发生错误,错误信息:%@",error.localizedDescription);
        }
        //遍历查找到的服务
        CBUUID *serviceUUID=[CBUUID UUIDWithString:kServiceUUID];
        for (CBService *service in peripheral.services) {
            if([service.UUID isEqual:serviceUUID]){
                //外围设备查找指定服务中的特征
                [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:kReadUUID],[CBUUID UUIDWithString:kWriteUUID]] forService:service];
            }
        }
    }
    
    8.寻找蓝牙服务中的特性
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
        if (error) {//报错直接返回退出
            JCLog(@"didDiscoverCharacteristicsForService error : %@", [error localizedDescription]);
            return;
        }
        
        for (CBCharacteristic *characteristic in service.characteristics)//遍历服务中的所有特性
        {
            if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kReadUUID]]){//找到收数据特性
                [peripheral setNotifyValue:YES forCharacteristic:characteristic];//订阅其特性(这个特性只有订阅方式)
                _readCharacteristic = characteristic;
            }
            if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kWriteUUID]]) {//找到发数据特性
                _writeCharacteristic = characteristic;
            }
        }
    }
    
    9.收到外设更新发送过来的数据
    -(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
        if (error) {
            JCLog(@"更新特征值时发生错误,错误信息:%@",error.localizedDescription);
            return;
        }
        NSString *value=[[NSString alloc]initWithData:characteristic.value encoding:NSUTF8StringEncoding];
        JCLog(@"读取到特征值:%@",value);//即收到的数据
    }
    
    10.发送数据到外设
    -(void)sendString:(NSString *)string{
       NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
       [_eripheral writeValue:data
            forCharacteristic:_writeCharacteristic
                         type:CBCharacteristicWriteWithoutResponse];
    }
    
    /*======至此,蓝牙收发数据的流程基本结束======*/
    
    /*
    注意点:
    1.发送到外设的数据最大为20字节
    2.接收的数据也为20字节
    3.MAC端蓝牙调试助手推荐使用CoolTerm,相当于windows中的串口调试助手
    4.iPhone手机端调试,推荐LightBlue
    */
    
    
    /*
    关于服务UUID,特征值UUID的解释
    1.此文介绍的蓝牙开发是固定的服务UUID、固定的特征值UUID。即已获知项目中使用的外设蓝牙模块的服务UUID、特征值UUID,这两个数据可以在硬件工程师那里拿到,蓝牙模块文档中一般会提及。如果没有,则使用上文中提到的调试工具LightBlue可以获取得到。
    2.最近开发项目中的服务UUID、特征值UUID都是使用LightBlue获知。
    */
    

    如有错误之处,望看到此文的大神批评指正,谢谢!

    相关文章

      网友评论

          本文标题:iOS蓝牙开发

          本文链接:https://www.haomeiwen.com/subject/mcarbttx.html