iOS蓝牙开发:蓝牙连接和数据读写

作者: 干不动 | 来源:发表于2016-10-15 14:26 被阅读8405次

当下蓝牙开发可谓是越来越火,不论是智能穿戴的兴起还是蓝牙家具,车联网蓝牙等等,很多同学也会接触到蓝牙的项目,我从事蓝牙开发也有一段时间了,经手了两个项目。废话不多说了,先向大家简单的介绍有关蓝牙开发的知识。蓝牙低能耗(BLE),以下介绍的都是围绕iOS的<CoreBluetooth/CoreBluetooth.h>框架展开的。

蓝牙开发分为中心者模式和管理者模式:1.常用的(其实99.99%)就是使用中心者模式作为开发,就是我们手机作为主机,连接蓝牙外设;2.管理者模式,这个基本用到的比较少,我们手机自己作为外设,自己创建服务和特征,然后有其他的设备连接我们的手机。

在做蓝牙开发之前,最好先了解一些概念:
服务(services):蓝牙外设对外广播的必定会有一个服务,可能也有多个,服务下面包含着一些特征,服务可以理解成一个模块的窗口;
特征(characteristic):存在于服务下面的,一个服务下面也可以存在多个特征,特征可以理解成具体实现功能的窗口,一般特征都会有value,也就是特征值,特征是与外界交互的最小单位;
UUID:可以理解成蓝牙上的唯一标识符(硬件上肯定不是这个意思,但是这样理解便于我们开发),为了区分不同的服务和特征,或者给服务和特征取名字,我们就用UUID来代表服务和特征。

蓝牙连接可以大致分为以下几个步骤
1.建立一个Central Manager实例进行蓝牙管理
2.搜索外围设备
3.连接外围设备
4.获得外围设备的服务
5.获得服务的特征
6.从外围设备读数据
7.给外围设备发送数据
其他:提醒

首先我们先导入系统的BLE的框架
#import <CoreBluetooth/CoreBluetooth.h>

必须遵守2个协议
<CBCentralManagerDelegate, CBPeripheralDelegate>

/** 中心管理者 */
@property (nonatomic, strong) CBCentralManager *cMgr;

/** 连接到的外设 */
@property (nonatomic, strong) CBPeripheral *peripheral;

1.建立一个Central Manager实例进行蓝牙管理

-(CBCentralManager *)cmgr
{
    if (!_cmgr) {
        _cMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    }
    return _cMgr;
}

//只要中心管理者初始化 就会触发此代理方法 判断手机蓝牙状态
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    switch (central.state) {
        case 0:
            NSLog(@"CBCentralManagerStateUnknown");
            break;
        case 1:
            NSLog(@"CBCentralManagerStateResetting");
            break;
        case 2:
            NSLog(@"CBCentralManagerStateUnsupported");//不支持蓝牙
            break;
        case 3:
            NSLog(@"CBCentralManagerStateUnauthorized");
            break;
        case 4:
        {
            NSLog(@"CBCentralManagerStatePoweredOff");//蓝牙未开启
        }
            break;
        case 5:
        {
            NSLog(@"CBCentralManagerStatePoweredOn");//蓝牙已开启
              // 在中心管理者成功开启后再进行一些操作
            // 搜索外设
            [self.cMgr scanForPeripheralsWithServices:nil // 通过某些服务筛选外设
                                              options:nil]; // dict,条件
            // 搜索成功之后,会调用我们找到外设的代理方法
            // - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI; //找到外设
        }
            break;
        default:
            break;
    }
}

2.搜索外围设备 (我这里为了举例,采用了自己身边的一个手环)

// 发现外设后调用的方法
- (void)centralManager:(CBCentralManager *)central // 中心管理者
 didDiscoverPeripheral:(CBPeripheral *)peripheral // 外设
     advertisementData:(NSDictionary *)advertisementData // 外设携带的数据
                  RSSI:(NSNumber *)RSSI // 外设发出的蓝牙信号强度
{
    //NSLog(@"%s, line = %d, cetral = %@,peripheral = %@, advertisementData = %@, RSSI = %@", __FUNCTION__, __LINE__, central, peripheral, advertisementData, RSSI);
    
    /*
     peripheral = <CBPeripheral: 0x166668f0 identifier = C69010E7-EB75-E078-FFB4-421B4B951341, Name = "OBand-75", state = disconnected>, advertisementData = {
     kCBAdvDataChannel = 38;
     kCBAdvDataIsConnectable = 1;
     kCBAdvDataLocalName = OBand;
     kCBAdvDataManufacturerData = <4c69616e 0e060678 a5043853 75>;
     kCBAdvDataServiceUUIDs =     (
     FEE7
     );
     kCBAdvDataTxPowerLevel = 0;
     }, RSSI = -55
     根据打印结果,我们可以得到运动手环它的名字叫 OBand-75
     
     */
    
    // 需要对连接到的外设进行过滤
    // 1.信号强度(40以上才连接, 80以上连接)
    // 2.通过设备名(设备字符串前缀是 OBand)
    // 在此时我们的过滤规则是:有OBand前缀并且信号强度大于35
    // 通过打印,我们知道RSSI一般是带-的
    
    if ([peripheral.name hasPrefix:@"OBand"]) {
        // 在此处对我们的 advertisementData(外设携带的广播数据) 进行一些处理
        
        // 通常通过过滤,我们会得到一些外设,然后将外设储存到我们的可变数组中,
        // 这里由于附近只有1个运动手环, 所以我们先按1个外设进行处理
        
        // 标记我们的外设,让他的生命周期 = vc
        self.peripheral = peripheral;
        // 发现完之后就是进行连接
        [self.cMgr connectPeripheral:self.peripheral options:nil];
        NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
    }
}

3.连接外围设备

// 中心管理者连接外设成功
- (void)centralManager:(CBCentralManager *)central // 中心管理者
  didConnectPeripheral:(CBPeripheral *)peripheral // 外设
{
    NSLog(@"%s, line = %d, %@=连接成功", __FUNCTION__, __LINE__, peripheral.name);
    // 连接成功之后,可以进行服务和特征的发现
    
    //  设置外设的代理
    self.peripheral.delegate = self;
    
    // 外设发现服务,传nil代表不过滤
    // 这里会触发外设的代理方法 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
    [self.peripheral discoverServices:nil];
}
// 外设连接失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@"%s, line = %d, %@=连接失败", __FUNCTION__, __LINE__, peripheral.name);
}

// 丢失连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@"%s, line = %d, %@=断开连接", __FUNCTION__, __LINE__, peripheral.name);
}

4.获得外围设备的服务 & 5.获得服务的特征

// 发现外设服务里的特征的时候调用的代理方法(这个是比较重要的方法,你在这里可以通过事先知道UUID找到你需要的特征,订阅特征,或者这里写入数据给特征也可以)
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
    
    for (CBCharacteristic *cha in service.characteristics) {
        //NSLog(@"%s, line = %d, char = %@", __FUNCTION__, __LINE__, cha);
       
    }
}

6.从外围设备读数据

// 更新特征的value的时候会调用 (凡是从蓝牙传过来的数据都要经过这个回调,简单的说这个方法就是你拿数据的唯一方法) 你可以判断是否
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
    if (characteristic == @"你要的特征的UUID或者是你已经找到的特征") {
    //characteristic.value就是你要的数据
    }
}

7.给外围设备发送数据(也就是写入数据到蓝牙)
这个方法你可以放在button的响应里面,也可以在找到特征的时候就写入,具体看你业务需求怎么用啦

[self.peripherale writeValue:_batteryData forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
//第一个参数是已连接的蓝牙设备 ;第二个参数是要写入到哪个特征; 第三个参数是通过此响应记录是否成功写入
// 需要注意的是特征的属性是否支持写数据
- (void)yf_peripheral:(CBPeripheral *)peripheral didWriteData:(NSData *)data forCharacteristic:(nonnull CBCharacteristic *)characteristic
{
    /*
     typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {
     CBCharacteristicPropertyBroadcast                                              = 0x01,
     CBCharacteristicPropertyRead                                                   = 0x02,
     CBCharacteristicPropertyWriteWithoutResponse                                   = 0x04,
     CBCharacteristicPropertyWrite                                                  = 0x08,
     CBCharacteristicPropertyNotify                                                 = 0x10,
     CBCharacteristicPropertyIndicate                                               = 0x20,
     CBCharacteristicPropertyAuthenticatedSignedWrites                              = 0x40,
     CBCharacteristicPropertyExtendedProperties                                     = 0x80,
     CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0)        = 0x100,
     CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0)  = 0x200
     };
     
     打印出特征的权限(characteristic.properties),可以看到有很多种,这是一个NS_OPTIONS的枚举,可以是多个值
     常见的又read,write,noitfy,indicate.知道这几个基本够用了,前俩是读写权限,后俩都是通知,俩不同的通知方式
     */
//    NSLog(@"%s, line = %d, char.pro = %d", __FUNCTION__, __LINE__, characteristic.properties);
    // 此时由于枚举属性是NS_OPTIONS,所以一个枚举可能对应多个类型,所以判断不能用 = ,而应该用包含&
}

其他:提醒
有那么多的特征,我们怎么知道哪些特征是用来读数据的,哪些是用来写入的,哪些是需要订阅之后再读的呢?
如果你们硬件工程师事先告诉你了,或者有完成的开发文档,那么就可以直接知道了,否则你就需要自己去查看特征的属性,推介可以使用下第三方的app——LightBlue,让你更能清楚的看到你蓝牙里面的服务,特征,特征的属性。

其他后续有关文章,我会慢慢整理发出来,我也可以回答相关的问题,有错误的地方可以帮忙指出来呦!

相关文章

网友评论

  • 今年27:感谢楼主分享,跪求Demo视频1012353929@qq.com
  • 吊吊的plus:大神,可以给发一份视频和demo嘛?13035155560@163.com
  • yoUrzEromAx:好文章
  • CoderW:您好, 请问获得的value是NSData类型的, 怎么变成自己要用的NSString类型的呢
  • 真爱要有你才完美:大神 fudongkaikaifa@163.com 能不能发下视频 谢谢了 万分感谢
  • fa1d4a4beda4:感谢楼主分享,同求Demo视频305075253@qq.com
  • 代码粉刷匠:楼主你好,最近在开发蓝牙项目,求DEMO,我的邮箱22900662@qq.com,谢谢
  • 73999895d54c:906571118@qq.com 博主,麻烦也发我一份视频吧,最近正在学习蓝牙,非常感谢了
  • _明川:您好,可以发给我一份demo 和视频么? 本人小白,多谢! 邮箱:18768880074@163.com
  • 编程的蚂蚁:楼主你好,麻烦给发一下Demo和视频,289278874@qq.com,楼主好人。:stuck_out_tongue_winking_eye::stuck_out_tongue_winking_eye::stuck_out_tongue_winking_eye::kissing_heart::kissing_heart::kissing_heart:
  • f6b7c3f02295:316699748@qq.com 楼主可以给小白发一份教学视频和资料嘛...
    谢谢大神~
  • 8636ffac27f8:大佬,刚开始接触蓝牙,求视频和demo 邮箱:505658864@qq.com :smile: 好人一生平安
  • tjfeng88:跪求一份视频+demo 先谢谢了 tianjinfeng10086@gmail.com
  • 8c392b25ce9c:最近在研究蓝牙,大佬能不能发我个demo或者视频么 834112686@163.com 万分感谢!
  • 净水清梦的无愧于心:1195041218@qq.com,谢谢
  • RiberWang:我搜索到的蓝牙设备的name怎么好多为空
  • ceec63a80194:求视频,991866448@qq.com。。。。谢谢
  • 老屋旁的女孩:膜拜....发下视频和Demo呗, 邮箱475203826@qq.com
    谢谢
  • Metatronxl:381827702@qq.com 大佬能发一下邮箱么:smile: ,本人学生党在做软硬件结合的学校项目,在此不胜感激
  • Charming_Zhang:求 视屏和demo 谢谢 1104094894@qq.com
  • Hiker5:同求视频和demo 867690241@qq.com 谢谢:pray:
  • 刘跃:你好,可以把视频发给我一份吗?386093010@qq.com
  • 宋鸿康iOS:就不能 上传到github?
  • fe52052a1163:楼主是好人,谢谢 825992515@qq.com
  • b1c132baa092:你好,可以把视频发给我一份吗?
    1757630244@qq.com
  • 土豆_8f5e:能给发下具体的代码和学习资料吗,非常感谢,2872893762@qq.com
  • 豌豆大师:768805503@qq.com 好人一生平安~~
    豌豆大师:本人也姓姚。。哈哈
  • yaya7305:亲,可以发一份适配和demo让我学习一下吗?1820104054@qq.com 谢谢
  • 152d032ed8b6:求demo一份。 544520724@qq.com
  • 152d032ed8b6:544520724@qq.com
  • 59da898276b9:楼主,我问一下,我的项目现在能连接外设,能进行数据交互,但是现在要做来电提示,短信提醒,这个我百度着需要用ANCS,这个前提是需要和外设配对上,问题是我这个连上之后根本就不提示什么什么要与你配对 这个系统的弹框,怎么办,愁了好几天了。。。求解答。。。
  • 90ce7e0994ea:你好,可以把视频发给我一份吗?
    576746872@qq.com@姚兜兜
  • 9692a9ef1242:您好,可以发一份视频 和demo么。。。 271320736@qq.com
  • d63d3136f13a:求视频 谢谢楼主 629489948@qq.com :smile:
  • Xanthuim:博主把Demo放到github上啊,非iOS出身参考参考。
  • 069e26decf4a:求视频,最近在学习中。谢谢楼主。yxd@ccynet.cn
  • Lael:求视频。306745930@qq.com。多谢楼主分享,手动赞。
  • 待我富可敌国娶你可好:求视频教程,1215401534@qq.com 现在搞蓝牙搞的焦头烂额
  • 策马鞭程:您好,请问硬件CBCharacteristicPropertyIndicate方式如何获取数据?
  • 我爱蚕宝宝:楼主,你好,可以发一下视频学习一下,最近在研究蓝牙,我的邮箱85682159@qq.com,谢谢您嘞。
  • e6300248b3cd:楼主你好!最近在研究这块。 能发一份Demo或则视频吗? 谢谢了 QQ:3376512101
  • 科24:你好,可以发我一份视频吗? 最近在研究蓝牙开发这块。谢谢了 2602845404@qq.com
  • 6e2c5a8150c5:@姚兜兜 能发一份视频到我邮箱吗?谢谢 1322587172@qq.com
  • 宋鸿康iOS:感谢楼主那么用心去编写,很详细,最近研究硬件用蓝牙发送数据到APP,求视频和Demo,邮箱:139994824@qq.com
  • Angelia_:最近在研究蓝牙方面的情况,能发一份demo和视频吗?1418059580@qq.com
  • 爱掏蜂窝的熊:感谢楼主用心分享,同求Demo视频 chengyong_luo@163.com
  • 79c8ebe2e6e9:求视频 + demo
    522689376@qq.com
    谢谢
  • 169e8e9b9437:楼主你好 可以发视频和demo学习一下吗,我的邮箱562645384@qq.com,谢谢!
  • 35e836cf936f:大神,能求分蓝牙的视频么?1274332579@qq.com 万分感谢
  • 0cd6c78ba2d4:感谢楼主用心分享,同求Demo视频809176334@qq.com
  • 子木俊霞:你好,可以发视频和demo学习一下吗,邮箱364893724@qq.com,谢谢!
  • fghjn:楼主你好,可以发视频和demo学习一下吗 2496653044@qq.com
  • 刘了个二:求demo,353796440@qq.com,谢谢了
  • 张戈戈爱书:求视频 840205966@qq.com
  • 咖啡bu加糖:1042657187@qq.com 求一份视频
  • 清心清语:感谢楼主写的很详细,给我这个小白很大的帮助,最近研究硬件用蓝牙发送数据到APP,求视频和Demo,邮箱:544715003@qq.com
  • f3b01ce18885:你好,可以把视频发给我一份吗?多谢楼主分享
    81229429@qq.com
  • 0a021e484759:你好,最近也在研究蓝牙这一块,可以发我一份视频和demo吗?我的邮箱是747616215@qq.com,谢谢🙏
  • 一个认真工作的iOS留下背影:你好,可以把视频发给我一份吗?
    emailForHan@163.com
    一个认真工作的iOS留下背影:才开发蓝牙,好多东西还不懂,可以发下demo吗?邮箱还是上面那个。谢谢了!
  • 10046a579844:大神可以发个Demo和视频吗 1393803081@qq.com 谢谢啦~
  • 贱精先玍丶:看完了, 感觉要写成功还是不容易, 求份视频和demo行吗?作者大哥, ldcz6614@sina.cn
  • Tim_1d0d:楼主好人,可以发视频和demo学习一下吗,我的邮箱1598212126@qq.com,谢谢!
  • 5aae19619952:楼主 求一份视频与Demo,目前在做蓝牙这快开发。谢谢楼主
  • f389126a1b08:1012777468@qq.com 谢谢分享
  • 聚朋友iOS:楼主好人,可以发视频和demo学习一下吗,我的邮箱819592183@qq.com,谢谢!
  • Mr_ZNN:最近项目要做手环,可以分享一些资料和视频吗?谢谢啦!邮箱 3296204071@qq.com
  • Python数据分析实战:求视频和demo,我的邮箱2604470550@qq.com,谢谢
  • 131b09cc6f52:您好,可以把视频发给我一份吗?1451888395@qq.com 麻烦楼主了
  • Mr丶Summer:4673643146@qq.com 楼主可以给我发一个吗 还有我想问一个问题,就是蓝牙在APP打开时开始搜索,是要一直保持搜索的好还是设定个时间,到一定时间后关闭,然后其他地方需要连接外设的时候在重新开启蓝牙去搜寻?
  • 贝一壳:楼主你好,可以发视频和demo学习一下吗,我的邮箱757148001@qq.com,谢谢!
  • 无痕树人:楼主你好,可以发视频和demo学习一下吗,我的邮箱931550959@qq.com,谢谢!
  • 6eb95aa286dc:麻烦给发一下视频和demo 864226839@qq.com 谢谢楼主
  • 86335714d1f3:跪求大神视频!a8333196@qq.com
  • 5fe3ee03c48b:大神,给我也来份蓝牙的demo把,635873117@qq.com
  • 760a86597520:最近接触蓝牙开发 ,楼主求demo和视频 samyang1107@icloud.com 谢谢!
  • 4865a560d8a6:你好,可否发一份视频,835124343@qq.com 万分感谢
  • 049915214704:最近接触蓝牙开发 ,楼主求demo和视频 492342828@qq.com 谢谢!
  • 5b01f47e6752:写的很不错,我也在做这块,可以给份视频和demo吗?1484172225@qq.com 谢谢
  • Lee馍馍:在研究蓝牙技术,楼主能共享一下视频和demo吗?感谢!lzy2911@163.com
  • 边河:你好,最近在做蓝牙项目,求视频和Demo,邮箱:3280964762@qq.com
  • d631da6b2639:感谢楼主分享,同求Demo视频707307952@qq.com
    干不动:邮件已发
  • 056586ad6462:您好 可以发一份视频到邮箱吗 最近在研究蓝牙模块 谢谢! 邮箱:459661469@qq.com
    干不动:邮件已发
  • 5a2f141238f3:求视频和demo 大神183700913@qq.com谢谢了
    干不动:邮件已发
  • CoderMikeHe:不错 ...学习了 ,能给我一份视频吗 ? 491273090@qq.com 谢谢
    CoderMikeHe:@姚兜兜 谢谢。
    干不动:邮件已发
  • GavinKang:大神求指教:776362265@qq.com
    干不动:邮件已发
  • wutengwei:求一份demo 15239184251@126.com 多谢
    干不动:@why_not1 已发
  • SunStart:求视频 250226337@qq.com
    干不动:@SunStart 已发
  • 大王叫我来巡山丨:您好 可以给我发下视频么? 898317594@qq.com
    大王叫我来巡山丨:@姚兜兜 收到 多谢
    干不动:@Siers 已发
  • james_w7:您好!能共享一下视频和demo吗?感谢!987292012@qq.com
    干不动:@JamesW001 已发邮箱
  • kenkeng:楼主给个demo,最近在做这个。oujinfuchn@163.com
    kenkeng:@姚兜兜 thanks:smile:
    干不动:@kenkeng 已发邮箱
  • 商丘彭于晏:965545784@qq.com 求一份视频,谢谢楼主!
    干不动:@受惊的小象 已发
  • 爆炸头的波波安:349421117@qq.com大兄弟,来一个
    干不动:@theway 已发
  • MakeThatChange:904885694@qq.com 希望能观摩楼主Demo~ :smile:
    彦子凡:楼主空中升级的demo可以发给我吗?13295553856@163.com
    MakeThatChange:@姚兜兜 3q vv much
    干不动:@MakeThatChange 请查收哈
  • 懒人啊:感谢楼主那么用心去编写,很详细,最近研究硬件用蓝牙发送数据到APP,求视频和Demo,邮箱:747726013@qq.com
    55ee69e2531d:感谢楼主用心分享,同求Demo视频231105890@qq.com
    懒人啊:@姚兜兜 已查收!感谢! :smile:
    干不动:@国柱 已发,请查收
  • 木鱼_cc:亲,求个demo. nail_candy@163.com
    木鱼_cc:@姚兜兜 谢谢
    干不动:@木鱼_江健锋 已发送
  • Yochi:亲,同求视频和demo 邮箱:605949540@qq.com :smile: 万分感谢
    干不动:@践行oO渐远 已发邮箱
  • 一舟孤月:你好,最近在做蓝牙项目,求视频和Demo,邮箱:1205628533@qq.com
    干不动:@一舟孤月 已发
  • cd59f729e81e:同求视频和demo tonight523@gmail.com 谢谢
    cd59f729e81e:@姚兜兜 不好意思,我gmail登不上去了……麻蛋重新发一下,tonight523@163.com
    干不动:@刀枪不入的脆皮肠 已发

本文标题:iOS蓝牙开发:蓝牙连接和数据读写

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