iOS 蓝牙初探

题外话:

两个月多月之前,华夏大地有多危险?

如果武汉没有封城、如果湖北没有封省、如果春节期间坚持走亲串户。

那么,现在欧洲处境就是我们处境。医疗资源耗尽、医疗体系崩溃、不断有人离去。真的不敢往下想。

如今,正式大家努力,让中国变成世界最安全的国家。从“危”转“机”。

而我本人也经历了一场“危”“机”,虽然跟新冠病毒没有直接关系。去年的项目因为各种原因,团队解散,在一次面临着失业。

好在朋友介绍,顺利尽力新公司,开始新的征程。

原生开发做了几年,其实涉及的内容并不多,无非就是界面的布局,与服务器做交互等待相关事情。

新岗位也是开发相关的,但是一开就是蓝牙通讯,这个之前未曾涉及。也很久没有更新博客,这篇文章算是做个记录:



做蓝牙开发,如果没有看过苹果的蓝牙相关的文档,个人建议先去看苹果的官方文档,虽然全市英文,啃完以后会清楚很多。以下是苹果官方文档的地址:

https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/PerformingCommonCentralRoleTasks/PerformingCommonCentralRoleTasks.html#//apple_ref/doc/uid/TP40013257-CH3-SW1

看完官方文档以后,可以看看别人的翻译和理解,这个也是很有帮助的:

http://www.saitjr.com/ios/core-bluetooth-overview.html

蓝牙开发其实也不难,个人理解大概可以分按照下面的思路进行:

打开蓝牙--搜索外设--连接--获取外设的服务--获取服务的特征--绑定通知--读写数据--断开连接

1 判断设备是否有蓝牙功能,即CBManagerState,如果设备都没蓝牙,其他都是纸上谈兵。只有设备支出蓝牙并且出于开启状态才能往下进行。

2 蓝牙连接的2端分为 中心和外设,中心Central:接收数据就是中心,外设Peripheral:发送数据就是外设。正常的开发中,手机是作为中心。蓝牙框架中,中心、外设都是对象,相关的方法是通过协议(代理)完成。

3 中心要搜索正在广播的蓝牙设备,那么要先有个中心对象,Central对象调用scanForPeripheralsWithServices:options 方法搜索,第一个参数传入要搜索的蓝牙设备UUID数组,如果没有传,则会搜索正在广播的所有蓝牙设备,第二参数一般为nil,表示在主线操作。

4 只有中心搜索到外设,会调用(搜索到一个调用一次)centralManager:centraldidDiscoverPeripheral:peripheraladvertisementData:advertisementDataRSSI: 

5 找到自己需要的外设,中心调用connectPeripheral: options:nil连接

连接成功调用centralManager: didConnectPeripheral:  这个时候可以搜索外设的服务:外设调用discoverServices方法,可以传入外设服务uuid,如果没有传则搜索所有服务。

连接失败:centralManager: didFailToConnectPeripheral: error:

断开连接:centralManager: didDisconnectPeripheral: error:

6 连接成功,获取外设的服务,如果上面提到的discoverServices的方法有传入参数,就可以直接找服务的特征,如果没有传,这里要遍历服务,找到需要的服务,发现服务的方法外设的代理方法:peripheral: didDiscoverServices:  发现了服务:紧接着是特征:外设discoverCharacteristics:nil forService:发现对象服务的特征,

7 发现特征以后,调用peripheral:didDiscoverCharacteristicsForService: error:这里要根据自己开发中的蓝牙协议,哪些是特征是可以订阅的,哪些是特征是可以写的,哪些特征是可以读的(很少用)

8 特征订阅是否成功都会调用peripheral: didUpdateNotificationStateForCharacteristic: error:

9 写入成功回调方法:peripheral:didWriteValueForDescriptor:error:

外设写入数据的方法:writeValue:forCharacteristic: type:

10 收到蓝牙数据回调方法:peripheral:didUpdateValueForCharacteristic: error:

如果看过官方文档,获取随便度娘找,做到这一步应该都没问题,

实际开发中,最主要的是写入数据的方法(writeValue:forCharacteristic: type:),以及收到数据的方法:peripheral:didUpdateValueForCharacteristic: error:

至于用什么格式写入什么数据,要根据自己的协议完成,转成NSData在写入

收到数据的处理,也要自己的协议,完成解析,才能拿到数据。

代买如下:

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

    // 更新中心蓝牙状态回调 central.state == CBManagerStatePoweredOn 才是可用的

}

// 扫描到外设,

- (void)centralManager:(CBCentralManager*)centraldidDiscoverPeripheral:(nonnullCBPeripheral*)peripheraladvertisementData:(nonnullNSDictionary *)advertisementDataRSSI:(nonnullNSNumber*)RSSI {

    NSLog(@"%@", peripheral.name);

   //        这里要找到自己的需要的外设才能连接

        self.peripheral= peripheral;

        [centralconnectPeripheral:peripheraloptions:nil];

}

// 链接成功,调用下面的方法

- (void)centralManager:(CBCentralManager*)centraldidConnectPeripheral:(CBPeripheral*)peripheral {

//    NSLog(@"外设连接成功,先停止扫描");

    // 链接成功,出于对性能的考虑,应该停止扫描

    [self.centralManager stopScan];

    // 设置外设代理

    peripheral.delegate=self;

        // 根据uuid来寻找服务  这个参数不能为空,否则会崩

    [peripheraldiscoverServices:nil];

}

- (void)centralManager:(CBCentralManager*)centraldidFailToConnectPeripheral:(CBPeripheral*)peripheralerror:(NSError*)error {

    NSLog(@"连接失败");

}

- (void)centralManager:(CBCentralManager*)centraldidDisconnectPeripheral:(CBPeripheral*)peripheralerror:(NSError*)error {

    NSog(@"连接断开");

}

#pragma mark CBPeripheralDelegate  外设代理方法

// 发现服务  回调

- (void)peripheral:(CBPeripheral*)peripheraldidDiscoverServices:(NSError*)error {

    if(error) {

        PLog(@"发生错误");

    }else{

        // 在这里遍历服务,找到需要的服务

        [peripheral.servicesenumerateObjectsUsingBlock:^(CBService*obj,NSUIntegeridx,BOOL*stop) {

            CBService*service = obj;

            if([obj.UUID.UUIDStringisEqual:SERVICES_UUID]) {

                [self.peripheral discoverCharacteristics:nil forService:service];

            }

        }];

    }

}

// 发现特征  回调

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(nonnull CBService *)service error:(nullable NSError *)error {

    // 遍历特征

    [service.characteristicsenumerateObjectsUsingBlock:^(CBCharacteristic*_Nonnullobj,NSUIntegeridx,BOOL*_Nonnullstop) {

        if([obj.UUID.UUIDStringisEqual:ChAR_NOTIFY_UUID]) {// 支持订阅

            self.bleNotifyChar= obj;

            // 开启通讯通道

            [peripheral setNotifyValue:YES forCharacteristic:obj];

        }

        if([obj.UUID.UUIDStringisEqual:CHAR_WRITE_UUID]) {// 支持写入

            self.bleWriteChar = obj;

        }

    }];

}

// 订阅状态发送改变,调用下面这个方法

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error {

    if(error) {

        NSLog(@"订阅失败----%@", error);

        return;

    }

    NSString*rst = characteristic.isNotifying?@"订阅成功 -------->    读取数据":@"取消订阅";

    NSLog(@"%@", rst);

}

// 接收到数据回调

- (void)peripheral:(CBPeripheral*)peripheraldidUpdateValueForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error {

    if(error) {

        PLog(@"发生错误了");

        return;

    }

    NSData*data = characteristic.value;

    // 只有当返回的数据不为空,并且回调有实现才执行回调

    NSString*str = [Tools convertDataToHexStr:data];

}

- (void)peripheral:(CBPeripheral*)peripheraldidWriteValueForDescriptor:(CBDescriptor*)descriptorerror:(NSError*)error {

    NSLog(@"写入成功");

}



©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容