iOS蓝牙开发记录

        在公司待的一年多时间里,做了几个蓝牙、Wi-Fi通讯的项目,碍于时间关系一直没有做整理工作,现在稍微闲下来,就顺便整理一下。iOS蓝牙3.0需要获得苹果MFI认证,因此项目初期和嵌入式工程师沟通iOS蓝牙只做4.0BLE,和嵌入式工程师做好沟通后,就开始进入BLE的iOS开发阶段。蓝牙、Wi-Fi项目中,实现连接、通讯很简单,项目大部分的时间是和嵌入式工程师联调通讯部分,最让人头痛的是iOS开发工程师没做过蓝牙项目同时嵌入式工程师也没做过蓝牙项目(笔者亲身体验)出了问题的时候不清楚到底是嵌入式工程师AT指令不对呢,还是iOS开发工程师自己的代码有问题,也花费大量时间发现、处理iphone与蓝牙模块中的异常情况,做出逻辑改进,优化用户体验。我们的项目中,iphone与蓝牙模块基于Modbus协议通讯,这以后笔者会慢慢写。本文是通过iphone手机控制外设,不涉及iphone手机之间的蓝牙连接交互,也不涉及其他设备控制iphone手机。

第一步:建立连接

1.基于系统库进行开发,因此导入头文件#import 

遵循代理

2.创建CBCentralManager实例

3.当创建完CBCentralManager实例后,会收到CBCentralManagerDelegate回调,执行以下代理方法(可自行把苹果弃用的方法枚举改为新的枚举,笔者较懒没改,但能用);

CBCentralManagerStatePoweredOff的时候可添加方法通知到你当前的控制器,让它提示用户到系统->设置->蓝牙里打开蓝牙连接;CBCentralManagerStatePoweredOn的时候可添加方法通知你当前的控制器,告诉它蓝牙可用,让用户继续后面的操作。

4.当蓝牙走到CBCentralManagerStatePoweredOn的时候,此时添加方法去告诉控制器蓝牙是可用的,此时用户可进行scan扫描周边蓝牙设备的操作,scanForPeripheralsWithServices中,传入nil表示对搜索周边所有的蓝牙设备,当然你也可以通过UUID寻找特定的蓝牙设备;

5.当CBCentralManager开始做scan这个搜索动作后,会触发CBCentralManagerDelegate的回调;此处有三坑,第一坑:蓝牙模块很久都搜不出来。针对这个坑,需要找到嵌入式工程师,让嵌入式工程师去调整蓝牙模块广播的频率,笔者的项目中,当嵌入式工程师调整完此频率后,就很容易把蓝牙模块搜索出来了;第二坑:比如我有一个蓝牙模块,两台名字不同的机器,第一台机器叫A,第二台机器叫B,当蓝牙模块插进A的时候,此时我们搜出的名字应该叫A,当蓝牙模块插进B的时候,此时我们搜出的名字应该叫B,如果此时间用peripheral.name,我们把原本插在A的蓝牙拔出,然后插进B,会发现peripheral.name还没变过来依然叫A,但嵌入式工程师广播的name,NSString* name = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];确实已经变成B了,笔者原来一直用peripheral.name,然后一直跟嵌入式工程师纠缠说他没改过来,但其实他确实已经改过来了;第三坑:iOS与安卓不同,安卓能轻松拿到蓝牙设备的mac地址,但iOS拿不到,这里嵌入式工程师和产品又会跟你说你最讨厌的一句话“安卓可以”,然后问题又推到iOS开发者身上了,笔者是不能够通过iphone直接拿到mac地址,要获取mac地址只能叫嵌入式工程师把mac地址写在广播里的advertisementData中,key是kCBAdvDataManufacturerData,要写到这个key的value里,关于kCBAdvDataManufacturerData,请自行百度搜索;RSSI为距离值;

至此,已经完成搜索

6.搜索出你的蓝牙模块后,开始下一个动作,用iphone去连接蓝牙模块;

7.当调用上面connectPeripheral:options的方法连接成功后,会触发CBCentralManagerDelegate的回调,在回调中,需要调起服务services和特征Characteristics,这时,去找到你的嵌入式工程师,问他把读\写放在services、Characteristics这两个数组的哪个地方,找出特征,通过该特征实现iphone和蓝牙设备之间的交互;

8.当上面peripheral调用discoverServices时,会触发CBPeripheralDelegate代理的回调。下面回调里面的内容忽略,根据具体情况而定,哪个服务里的哪个特征是读写的问嵌入式,使劲质问他就对了;

9.上面调用discoverCharacteristics:forService,触发CBPeripheralDelegate回调。readValueForCharacteristic 和 setNotifyValue:forCharacteristic:请记得打开,不打开这两个进行操作的话,数据发出去了,得不到回调,然后一脸懵逼地跟嵌入式说没有数据返回,他只会跟你说已经给你返回了,人家确实是返回了;

第二步:实现通讯

10.   iphone手机发送指令

value是你组好的包NSData,Characteristic是那个打开了readValueForCharacteristic和setNotifyValue:forCharacteristic的特征

 [self.peripheral writeValue:sendData forCharacteristic:self.charater type:CBCharacteristicWriteWithResponse];

11.调用了readValueForCharacteristic和setNotifyValue:forCharacteristic:后,按照嵌入式制定的modbus协议发送数据,触发CBPeripheralDelegate回调,忘记了是什么原因触发下图第一个回调了请自行尝试,后面按照正确的modbus协议发出数据,蓝牙模块透传给机器,机器完成操作返回给模块,模块->iphone,调起didUpdateValueForCharacteristic回调,NSData*data = characteristic.value;data就是要取回的包,回调中拼包等一系列数据处理、block回传值之类的乱七八遭的东西请自行发挥;

至此,iphone手机连接蓝牙外设的项目已完成最主要的连接、交互两部分,剩下的功能实现,就要看各种逻辑处理的自行发挥了;

12.断开蓝牙

整个交互过程就是这么简单,然后就是一大堆的组包、解包、拼包等逻辑题;以上,为本人在实战中自行探讨出来,如有说得不对的地方、可以更简单的地方,请帮忙指出;

你可能感兴趣的:(iOS蓝牙开发记录)