在CoreBluetooth框架中,有两个主要的角色:外设和中心,整个框架都是围绕这两个主要角色设计的.
中心角色变成实现过程
1.设置CBCentralManager
2.发现并连接外设
3.发现服务
4.发现特征
5.预定特征通知
6.读取数据
[objc]view plaincopy
print?
#import
#import
#define TRANSFER_SERVICE_UUID @"D63D44E5-E798-4EA5-A1C0-3F9EEEC2CDEB"
#define TRANSFER_CHARACTERISTIC_UUID @"1652CAD2-6B0D-4D34-96A0-75058E606A98"
@interfaceViewController : UIViewController
@property(strong,nonatomic) CBCentralManager *centralManager;//CBCentralManager 是用来管理BLE的中心设备
@property(strong,nonatomic) CBPeripheral *discoveredPeripheral;
@property(strong,nonatomic) NSMutableData *data;
@property(weak,nonatomic) IBOutletUIActivityIndicatorView*activityIndicatorView;
@property(weak,nonatomic) IBOutletUILabel*scanLabel;
@property(weak,nonatomic) IBOutletUITextView*textView;
@end
[objc]view plaincopy
print?
@implementationViewController
- (void)viewDidLoad
{
[superviewDidLoad];
// 设置CBCentralManager
_centralManager = [[CBCentralManageralloc]initWithDelegate:selfqueue:nil];
// 保存接收数据
_data = [[NSMutableDataalloc]init];
}
- (void)viewWillDisappear:(BOOL)animated
{
[self.centralManagerstopScan];
[self.activityIndicatorViewstopAnimating];
NSLog(@"扫描停止");
[superviewWillDisappear:animated];
}
- (void)didReceiveMemoryWarning
{
[superdidReceiveMemoryWarning];
}
#pragma mark - Central Methods
//设置成功回调方法
- (void)centralManagerDidUpdateState:(CBCentralManager*)central
{
if(central.state!= CBCentralManagerStatePoweredOn) {
return;
}
//开始扫描
[selfscan];
}
/** 通过制定的128位的UUID,扫描外设
*/
- (void)scan
{
//扫描
[self.centralManagerscanForPeripheralsWithServices:@[[CBUUIDUUIDWithString:TRANSFER_SERVICE_UUID]]
options:@{ CBCentralManagerScanOptionAllowDuplicatesKey :@YES}];
[self.activityIndicatorViewstartAnimating];
self.scanLabel.hidden=NO;
NSLog(@"Scanning started");
}
/** 停止扫描
*/
- (void)stop
{
[self.centralManagerstopScan];
[self.activityIndicatorViewstopAnimating];
self.scanLabel.hidden=YES;
self.textView.text=@"";
NSLog(@"Scanning stoped");
}
//扫描成功调用此方法
- (void)centralManager:(CBCentralManager*)centraldidDiscoverPeripheral:(CBPeripheral*)peripheraladvertisementData:(NSDictionary*)advertisementDataRSSI:(NSNumber*)RSSI
{
// 过滤信号强度范围
if(RSSI.integerValue> -15) {
return;
}
if(RSSI.integerValue< -35) {
return;
}
NSLog(@"发现外设 %@ at %@", peripheral.name, RSSI);
if(self.discoveredPeripheral!= peripheral) {
self.discoveredPeripheral= peripheral;
NSLog(@"连接外设 %@", peripheral);
[self.centralManagerconnectPeripheral:peripheraloptions:nil];
}
}
- (void)centralManager:(CBCentralManager*)centraldidFailToConnectPeripheral:(CBPeripheral*)peripheralerror:(NSError*)error
{
NSLog(@"连接失败 %@. (%@)", peripheral, [errorlocalizedDescription]);
[selfcleanup];
}
//连接外设成功
- (void)centralManager:(CBCentralManager*)centraldidConnectPeripheral:(CBPeripheral*)peripheral
{
NSLog(@"外设已连接");
// Stop scanning
[selfstop];
NSLog(@"扫描停止");
[self.datasetLength:0];//重置data属性
peripheral.delegate=self;//设置外设对象的委托为self
[peripheraldiscoverServices:@[[CBUUIDUUIDWithString:TRANSFER_SERVICE_UUID]]];
}
/** 服务被发现
*/
//发现服务成功
- (void)peripheral:(CBPeripheral*)peripheraldidDiscoverServices:(NSError*)error
{
if(error) {
NSLog(@"Error discovering services: %@", [errorlocalizedDescription]);
[selfcleanup];
return;
}
// 发现特征
for(CBService*service in peripheral.services) {
[peripheraldiscoverCharacteristics:@[[CBUUIDUUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]forService:service];
}
}
//发现特征成功
- (void)peripheral:(CBPeripheral*)peripheraldidDiscoverCharacteristicsForService:(CBService*)serviceerror:(NSError*)error
{
if(error) {
NSLog(@"发现特征错误: %@", [errorlocalizedDescription]);
[selfcleanup];
return;
}
for(CBCharacteristic*characteristic in service.characteristics) {
if([characteristic.UUIDisEqual:[CBUUIDUUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
// 预定特征
[peripheralsetNotifyValue:YESforCharacteristic:characteristic];
}
}
}
//特征状态发生变化
- (void)peripheral:(CBPeripheral*)peripheraldidUpdateValueForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error
{
if(error) {
NSLog(@"发现特征错误:: %@", [errorlocalizedDescription]);
return;
}
NSString*stringFromData = [[NSStringalloc]initWithData:characteristic.valueencoding:NSUTF8StringEncoding];
// 判断是否为数据结束
if([stringFromDataisEqualToString:@"EOM"]) {
// 显示数据
[self.textViewsetText:[[NSStringalloc]initWithData:self.dataencoding:NSUTF8StringEncoding]];
// 取消特征预定
[peripheralsetNotifyValue:NOforCharacteristic:characteristic];
// 断开外设
[self.centralManagercancelPeripheralConnection:peripheral];
}
// 接收数据追加到data属性中
[self.dataappendData:characteristic.value];
NSLog(@"Received: %@", stringFromData);
}
//特征值发生变化
- (void)peripheral:(CBPeripheral*)peripheraldidUpdateNotificationStateForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error
{
if(error) {
NSLog(@"特征通知状态变化错误: %@", error.localizedDescription);
}
// 如果没有特征传输过来则退出
if(![characteristic.UUIDisEqual:[CBUUIDUUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
return;
}
// 特征通知已经开始
if(characteristic.isNotifying) {
NSLog(@"特征通知已经开始 %@", characteristic);
}
// 特征通知已经停止
else{
NSLog(@"特征通知已经停止 %@", characteristic);
[self.centralManagercancelPeripheralConnection:peripheral];
}
}
//与外设连接断开时回调
- (void)centralManager:(CBCentralManager*)centraldidDisconnectPeripheral:(CBPeripheral*)peripheralerror:(NSError*)error
{
NSLog(@"外设已经断开");
self.discoveredPeripheral=nil;
//外设已经断开情况下,重新扫描
[selfscan];
}
/** 清除方法
*/
- (void)cleanup
{
// 如果没有连接则退出
if(!self.discoveredPeripheral.isConnected) {
return;
}
// 判断是否已经预定了特征
if(self.discoveredPeripheral.services!=nil) {
for(CBService*service inself.discoveredPeripheral.services) {
if(service.characteristics!=nil) {
for(CBCharacteristic*characteristic in service.characteristics) {
if([characteristic.UUIDisEqual:[CBUUIDUUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
if(characteristic.isNotifying) {
//停止接收特征通知
[self.discoveredPeripheralsetNotifyValue:NOforCharacteristic:characteristic];
//断开与外设连接
[self.centralManagercancelPeripheralConnection:self.discoveredPeripheral];
return;
}
}
}
}
}
}
//断开与外设连接
[self.centralManagercancelPeripheralConnection:self.discoveredPeripheral];
}
@end
外设角色编程实现过程
1.设置CBPeripheraManager
2.设置服务与特征
3.发布服务与特征
4.广播服务
5.发送数据
[objc]view plaincopy
print?
#import
#import
#define TRANSFER_SERVICE_UUID @"D63D44E5-E798-4EA5-A1C0-3F9EEEC2CDEB"
#define TRANSFER_CHARACTERISTIC_UUID @"1652CAD2-6B0D-4D34-96A0-75058E606A98"
#define NOTIFY_MTU 20
@interfaceViewController : UIViewController
@property(strong,nonatomic) CBPeripheralManager *peripheralManager;//用来管理BLE的外设设备
@property(strong,nonatomic) CBMutableCharacteristic *transferCharacteristic;//特征类
@property(strong,nonatomic) NSData *dataToSend;
@property(nonatomic,readwrite) NSInteger sendDataIndex;
@property(weak,nonatomic) IBOutletUITextView*textView;
- (IBAction)valueChanged:(id)sender;
@end
[objc]view plaincopy
print?
@implementationViewController
- (void)viewDidLoad
{
[superviewDidLoad];
//设置CBPeripheralManager
_peripheralManager = [[CBPeripheralManageralloc]initWithDelegate:selfqueue:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[self.peripheralManagerstopAdvertising];
[superviewWillDisappear:animated];
}
#pragma mark - Peripheral Methods
//外设设置成功回调此方法
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager*)peripheral
{
if(peripheral.state!= CBPeripheralManagerStatePoweredOn) {
return;
}
NSLog(@"BLE打开");
// 初始化特征
self.transferCharacteristic= [[CBMutableCharacteristicalloc]
initWithType:[CBUUIDUUIDWithString:TRANSFER_CHARACTERISTIC_UUID]
properties:CBCharacteristicPropertyNotify
value:nil
permissions:CBAttributePermissionsReadable];
// 初始化服务
CBMutableService*transferService = [[CBMutableServicealloc]
initWithType:[CBUUIDUUIDWithString:TRANSFER_SERVICE_UUID]
primary:YES];
// 添加特征到服务
transferService.characteristics= @[self.transferCharacteristic];
// 发布服务与特征
[self.peripheralManageraddService:transferService];
}
- (void)peripheralManager:(CBPeripheralManager*)peripheral
didAddService:(CBService*)service
error:(NSError*)error {
NSLog(@"添加服务");
if(error) {
NSLog(@"添加服务失败: %@", [errorlocalizedDescription]);
}
}
- (IBAction)valueChanged:(id)sender {
UISwitch* advertisingSwitch = (UISwitch*)sender;
if(advertisingSwitch.on) {
// 开始广播
[self.peripheralManagerstartAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[[CBUUIDUUIDWithString:TRANSFER_SERVICE_UUID]] }];
}
else{
[self.peripheralManagerstopAdvertising];
}
}
//远程中心预定数据回调该方法
- (void)peripheralManager:(CBPeripheralManager*)peripheralcentral:(CBCentral*)centraldidSubscribeToCharacteristic:(CBCharacteristic*)characteristic
{
NSLog(@"中心已经预定了特征");
self.dataToSend= [self.textView.textdataUsingEncoding:NSUTF8StringEncoding];
self.sendDataIndex=0;
[selfsendData];
}
- (void)peripheralManager:(CBPeripheralManager*)peripheralcentral:(CBCentral*)centraldidUnsubscribeFromCharacteristic:(CBCharacteristic*)characteristic {
NSLog(@"中心没有从特征预定");
}
- (void)sendData {
//发送数据结束标识
staticBOOLsendingEOM =NO;
if(sendingEOM) {
BOOLdidSend = [self.peripheralManagerupdateValue:[@"EOM"dataUsingEncoding:NSUTF8StringEncoding]forCharacteristic:self.transferCharacteristiconSubscribedCentrals:nil];
if(didSend) {
sendingEOM =NO;
NSLog(@"Sent: EOM");
}
return;
}
if(self.sendDataIndex>=self.dataToSend.length) {
return;
}
BOOLdidSend =YES;
while(didSend) {
NSInteger amountToSend =self.dataToSend.length-self.sendDataIndex;
if(amountToSend > NOTIFY_MTU) amountToSend = NOTIFY_MTU;
NSData*chunk = [NSDatadataWithBytes:self.dataToSend.bytes+self.sendDataIndexlength:amountToSend];
//发送数据
didSend = [self.peripheralManagerupdateValue:chunkforCharacteristic:self.transferCharacteristiconSubscribedCentrals:nil];
if(!didSend) {
return;
}
NSString*stringFromData = [[NSStringalloc]initWithData:chunkencoding:NSUTF8StringEncoding];
NSLog(@"Sent: %@", stringFromData);
self.sendDataIndex+= amountToSend;
if(self.sendDataIndex>=self.dataToSend.length) {
sendingEOM =YES;
BOOLeomSent = [self.peripheralManagerupdateValue:[@"EOM"dataUsingEncoding:NSUTF8StringEncoding]forCharacteristic:self.transferCharacteristiconSubscribedCentrals:nil];
if(eomSent) {
sendingEOM =NO;
NSLog(@"Sent: EOM");
}
return;
}
}
}
//发送数据失败后(发送数据的队列已经满了)重新发送
- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager*)peripheral {
[selfsendData];
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
}
@end