iOS蓝牙开发
相比于网络请求,蓝牙是一种低功耗(low-energy)的通信手段。目前iOS的开发都是针对CoreBluetooth 4.0版本。
iOS的蓝牙开发,是基于Core Bluetooth framework。
Do not subclass any of the classes of the Core Bluetooth framework. Overriding these classes is unsupported and results in undefined behavior.
大致的意思不要尝试继承Core Bluetooth framework中任何相关的类,因为重载将会导致未知的结果。
Core Bluetooth framework中几个主要的类的相关概念如下:
1、中心设备:CBCentral 外围设备管理类: CBPeripheralManager 外围设备的服务 CBMutableService 外围设备的特征 CBMutableCharacteristic 作为外围设备服务特征的唯一标志:CBUUID
2、外围设备:CBPeripheral 中心设备管理类: CBCentralManager 外围设备的服务 :CBService 外围设备的特征: CBCharacteristic 读写中心设备数据的请求:CBATTRequest
上面两种区别,是以不同的角色开发,1是以外围角色当作开发,远端设备是中心角色;2是以中心角色作为开发,远端为外围角色。如下图:
开发模式注意:iOS10以后,所有的蓝牙开发都需要向用户申请蓝牙权限,所以需要在项目的info.plist设置NSBluetoothPeripheralUsageDescription.
一、以中心设备CBCentral作为本地,外围设备CBPeripheral作为远端的开发模式方案:
1、首先我们需要初始化一个CBCentralManager的实例对象,是用来扫描发现外围设备的服务跟特征:
NSDictionary *options = @{CBCentralManagerOptionShowPowerAlertKey: @YES};
CBCentralManager* tM = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:options];
self.myCentralManager = tM;
2、其次开始扫描外围设备:
[self.myCentralManager scanForPeripheralsWithServices:nil options:nil];
如果没有指定扫描哪些外围设备,services可以传nil,option也可以为nil。
3、扫面的结果会通过CBCentralManagerDelegate回调:
///@required 蓝牙状态变化监听
- (void)centralManagerDidUpdateState:(CBCentralManager*)central;
///@optional发现外围设备,双方可以约定外围设备唯一参数,一般是外围设备的MAC地址
- (void)centralManager:(CBCentralManager*)central didDiscoverPeripheral:(CBPeripheral*)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber*)RSSI;
4、发现设备后,开始连接设备:
[self.myCentralManager connectPeripheral:self.peripheral options:nil];
5、连接结果也是通过CBCentralManagerDelegate回调:
///连接成功
- (void)centralManager:(CBCentralManager*)central didConnectPeripheral:(CBPeripheral*)peripheral;
///连接失败
- (void)centralManager:(CBCentralManager*)central didFailToConnectPeripheral:(CBPeripheral*)peripheral error:(nullableNSError*)error;
///断开连接结果
- (void)centralManager:(CBCentralManager*)central didDisconnectPeripheral:(CBPeripheral*)peripheral error:(nullableNSError*)error;
6、连接成功后,扫描外围设备的服务CBService:
///UUID双方约定好的
[self.myPeripheral discoverServices:@[[CBUUID UUIDWithString:KServiceUUID]]];
7、扫描服务结果会通过CBPeripheralDelegate回调:
///如果失败,error不为空,否则为nil,比较双方约定的UUID
- (void)peripheral:(CBPeripheral*)peripheral didDiscoverServices:(nullableNSError*)error;
8、发现CBService后,查询服务的特征CBCharacteristic:
[self.myPeripheral discoverCharacteristics:nil forService:service];
9、查询特征结果会通过CBPeripheralDelegate回调:
///如果失败,error不为空,否则为nil,比较双方约定的特征UUID
-(void)peripheral:(CBPeripheral*)peripheral didDiscoverCharacteristicsForService:(CBService*)service error:(NSError*)error;
10、发现服务特征后,注册特征通知,这样中心设备就可以读取外围发过来的数据了:
[self.myPeripheral setNotifyValue:YES forCharacteristic:characteristic];
11、注册通知的结果通过CBPeripheralDelegate回调:
///如果失败,error不为空,否则为nil
-(void)peripheral:(CBPeripheral*)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic*)characteristic error:(NSError*)error;
12、特征的数据也是通过CBPeripheralDelegate回调:
///如果失败,error不为空,否则为nil。数据在characteristic的value中
- (void)peripheral:(CBPeripheral*)peripheral didUpdateValueForCharacteristic:(CBCharacteristic*)characteristic error:(NSError*)error;
13、如果给对应的特征发送数据,则调用:
///type有两个值,一个是不用返回发送的结果,一个需要返回发送数据的结果,默认是返回CBCharacteristicWriteWithResponse =0,CBCharacteristicWriteWithoutResponse,
[self.myPeripheral writeValue:sendData forCharacteristic:_mWriteCharacteristic type:CBCharacteristicWriteWithResponse];
14、如果需要返回结果,发送数据结果也是通过CBPeripheralDelegate回调:
///失败error不为nil
- (void)peripheral:(CBPeripheral*)peripheral didWriteValueForCharacteristic:(CBCharacteristic*)characteristic error:(nullableNSError*)error;
第二种方案(以外围设备当作本地,中心当作远端)未完待续,有时间继续更新。。。