蓝牙学习
名称与缩写
- MFI (make for iPad ,iTouch,iPhone)为苹果设备制定的蓝牙,开发使用ExternalAccessory框架
- BLE (blueTooth low energy) 蓝牙4.0之后耗电低,又名BLE,开发时使用CoreBluetooth框架
- peripheral and central 外设与中心 ,中心控制向外发起连接,被连接的设备即为外设(外部设备)
- service and characteristic 服务和特征 ,每个设备会提供若干服务,每个服务中又有不同的特征,特征权限一般分为读写以及通知等
- Description 每个特征都有许多用户描述,介绍设备的属性信息(生产商,版本号等)
基础知识
CoreBluetooth框架的核心是外设与控制中心,控制中心用于连接外部蓝牙设备,外设模式主要是与其它蓝牙设备通信
特征的定义枚举
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//
};
蓝牙版本以及对应的使用限制
- 蓝牙2.0 === 越狱设备
- 蓝牙4.0 === iOS 6以上(操作系统)
- MFI认证设备 ===无限制
蓝牙设备状态
1. 待机状态(standby):设备没有传输和发送数据,并且没有连接到任何设
2. 广播状态(Advertiser):周期性广播状态
3. 扫描状态(Scanner):主动寻找正在广播的设备
4. 发起链接状态(Initiator):主动向扫描设备发起连接。
5. 主设备(Master):作为主设备连接到其他设备。
6. 从设备(Slave):作为从设备连接到其他设备。
蓝牙设备工作状态
- 准备(standby)
- 广播(advertising)
- 监听扫描(Scanning
- 发起连接(Initiating)
- 已连接(Connected)
蓝牙中心模式流程及实现简码
1.建立中心角色,即初始化控制中心 CBCentralManager
CBCentralManager *centralManager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()];
2.开始扫描外部设备
一个比较重要的委托,判断设备蓝牙运行状态,只有在蓝牙打开的情况下才能开始扫描-(void)centralManagerDidUpdateState:(CBCentralManager *)central
{
CBCentralManagerStateUnknown ,//未知
CBCentralManagerStateResetting,//重置
CBCentralManagerStateUnsupported,//不支持
CBCentralManagerStateUnauthorized,//为验证
CBCentralManagerStatePoweredOff,//关闭
CBCentralManagerStatePoweredOn,//打开
}
开始扫描 [centralManager scanForPeripheralsWithServices:nil options:nil];
options具体类型及含义CBCentralManagerScanOptionAllowDuplicatesKey 表示是否重复扫描已经发现的设备
CBCentralManagerScanOptionSolicitedServiceUUIDsKey 扫描指定UUID设备
扫描到设备会进入回调方法
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
在这个回调函数中开始连接外设
停止扫描 [centralManager stopScan];
3.连接扫描到的外部设备
[centralManager connectPeripheral:peripheral options:nil];
连接成功回调方法 - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
在这个回调函数中开始扫描连接到的外设的服务
连接失败回调方法-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
4.扫描外设中的服务,获取外设服务
[peripheral discoverServices:nil];
扫描到服务的回调函数 -(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
在这个回调函数中开始扫描服务的所有特征
5.扫描外设中的特征,获取外设的特征,找出并备份需要使用的带有读写权限的特征
[peripheral discoverCharacteristics:nil forService:service];
扫描到服务中特征的回调函数 -(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
在这个回调函数中开始设置用于读写的特征,以备与外设交互时使用
[peripheral readValueForCharacteristic:characteristic];
记录用于写的特征writeCharacteristic=XXXXXX;
6.与外部设备进行数据通信交互
当有外设返回数据信息时调用本回调函数,方便用户读取信息-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
向设备写数据即发送命令 [peripheral writeValue:data forCharacteristic:writeCharacteristic type:CBCharacteristicWriteWithoutResponse];
7.订阅特征通知
设置通知 [peripheral setNotifyValue:YES forCharacteristic:characteristic];
数据通知会进入:didUpdateValueForCharacteristic方法
取消通知 [peripheral setNotifyValue:NO forCharacteristic:characteristic];
8.断开宇外部设备的连接
[centralManager cancelPeripheralConnection:peripheral];
蓝牙外设模式流程及实现简码
1.初始化外设管理对象 CBPeripheralManager
peripheralManager = [[CBPeripheralManager alloc]initWithDelegate:self queue:nil];
2.设置本地外设的服务、特性、描述、特征权限等并添加到peripheralManager中
只有在外设存在并打开的情况下才可以设置服务特征
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
定义设备特征的UUID CBUUID *strUUID = [CBUUID UUIDWithString:@“1234”];
定义设备特征
可以通知的Characteristic
properties:CBCharacteristicPropertyNotify
permissions CBAttributePermissionsReadable
可读写的characteristics
properties:CBCharacteristicPropertyWrite | CBCharacteristicPropertyRead
permissions CBAttributePermissionsReadable | CBAttributePermissionsWriteable
只读的Characteristic
properties:CBCharacteristicPropertyRead
permissions CBAttributePermissionsReadable
通知CBMutableCharacteristic *notiyCharacteristic = [[CBMutableCharacteristic alloc]initWithType:strUUID properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable];
读写 CBMutableCharacteristic *readwriteCharacteristic = [[CBMutableCharacteristic alloc]initWithType:strUUID properties:CBCharacteristicPropertyWrite | CBCharacteristicPropertyRead value:nil
permissions:CBAttributePermissionsReadable | CBAttributePermissionsWriteable];
只读 CBMutableCharacteristic *readCharacteristic = [[CBMutableCharacteristic alloc]initWithType:[CBUUID UUIDWithString:readCharacteristicUUID] properties:CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadable];
设置设备服务特征的描述
CBMutableDescriptor *readwriteCharacteristicDescription= [[CBMutableDescriptor alloc]initWithType: CBUUIDCharacteristicUserDescriptionStringUUID value:@"name"];
[readwriteCharacteristic setDescriptors:@[readwriteCharacteristicDescription]];
初始化设备服务并加入服务特征
CBMutableService *service = [[CBMutableService alloc]initWithType:[CBUUID UUIDWithString:@“4321”] primary:YES];
[service setCharacteristics:@[notiyCharacteristic,readwriteCharacteristic]];
给外设添加服务
[peripheralManager addService:service];
添加后就会调用回调函数 - (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error
在回调函数中开始广播自己的存在
3.开始发送广播,声明自己的存在
[peripheralManager startAdvertising:@{
CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:ServiceUUID]],
CBAdvertisementDataLocalNameKey : LocalNameKey
} ];
开始广播回调函数
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error
4.设置处理订阅、取消订阅、读写特征的委托方法
订阅
-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic
取消订阅
-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic
发送数据
[peripheralManager updateValue: Data forCharacteristic:(CBMutableCharacteristic *)characteristic onSubscribedCentrals:nil];
处理读请求
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request{
[peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
}
处理写请求
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests{
[peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
}
5.关闭外设