在CoreBluetooth框架中,有两个主要的角色:外设和中心,整个框架都是围绕这两个主要角色设计的.
中心角色变成实现过程
1.设置CBCentralManager
2.发现并连接外设
3.发现服务
4.发现特征
5.预定特征通知
6.读取数据
#import <UIKit/UIKit.h> #import <CoreBluetooth/CoreBluetooth.h> #define TRANSFER_SERVICE_UUID @"D63D44E5-E798-4EA5-A1C0-3F9EEEC2CDEB" #define TRANSFER_CHARACTERISTIC_UUID @"1652CAD2-6B0D-4D34-96A0-75058E606A98" @interface ViewController : UIViewController <CBCentralManagerDelegate, CBPeripheralDelegate> @property (strong, nonatomic) CBCentralManager *centralManager;//CBCentralManager 是用来管理BLE的中心设备 @property (strong, nonatomic) CBPeripheral *discoveredPeripheral; @property (strong, nonatomic) NSMutableData *data; @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicatorView; @property (weak, nonatomic) IBOutlet UILabel *scanLabel; @property (weak, nonatomic) IBOutlet UITextView *textView; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 设置CBCentralManager _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; // 保存接收数据 _data = [[NSMutableData alloc] init]; } - (void)viewWillDisappear:(BOOL)animated { [self.centralManager stopScan]; [self.activityIndicatorView stopAnimating]; NSLog(@"扫描停止"); [super viewWillDisappear:animated]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } #pragma mark - Central Methods //设置成功回调方法 - (void)centralManagerDidUpdateState:(CBCentralManager *)central { if (central.state != CBCentralManagerStatePoweredOn) { return; } //开始扫描 [self scan]; } /** 通过制定的128位的UUID,扫描外设 */ - (void)scan { //扫描 [self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }]; [self.activityIndicatorView startAnimating]; self.scanLabel.hidden = NO; NSLog(@"Scanning started"); } /** 停止扫描 */ - (void)stop { [self.centralManager stopScan]; [self.activityIndicatorView stopAnimating]; self.scanLabel.hidden = YES; self.textView.text = @""; NSLog(@"Scanning stoped"); } //扫描成功调用此方法 - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(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.centralManager connectPeripheral:peripheral options:nil]; } } - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@"连接失败 %@. (%@)", peripheral, [error localizedDescription]); [self cleanup]; } //连接外设成功 - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { NSLog(@"外设已连接"); // Stop scanning [self stop]; NSLog(@"扫描停止"); [self.data setLength:0];//重置data属性 peripheral.delegate = self;//设置外设对象的委托为self [peripheral discoverServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]]; } /** 服务被发现 */ //发现服务成功 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { if (error) { NSLog(@"Error discovering services: %@", [error localizedDescription]); [self cleanup]; return; } // 发现特征 for (CBService *service in peripheral.services) { [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]] forService:service]; } } //发现特征成功 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { if (error) { NSLog(@"发现特征错误: %@", [error localizedDescription]); [self cleanup]; return; } for (CBCharacteristic *characteristic in service.characteristics) { if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) { // 预定特征 [peripheral setNotifyValue:YES forCharacteristic:characteristic]; } } } //特征状态发生变化 - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { if (error) { NSLog(@"发现特征错误:: %@", [error localizedDescription]); return; } NSString *stringFromData = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding]; // 判断是否为数据结束 if ([stringFromData isEqualToString:@"EOM"]) { // 显示数据 [self.textView setText:[[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]]; // 取消特征预定 [peripheral setNotifyValue:NO forCharacteristic:characteristic]; // 断开外设 [self.centralManager cancelPeripheralConnection:peripheral]; } // 接收数据追加到data属性中 [self.data appendData:characteristic.value]; NSLog(@"Received: %@", stringFromData); } //特征值发生变化 - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { if (error) { NSLog(@"特征通知状态变化错误: %@", error.localizedDescription); } // 如果没有特征传输过来则退出 if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) { return; } // 特征通知已经开始 if (characteristic.isNotifying) { NSLog(@"特征通知已经开始 %@", characteristic); } // 特征通知已经停止 else { NSLog(@"特征通知已经停止 %@", characteristic); [self.centralManager cancelPeripheralConnection:peripheral]; } } //与外设连接断开时回调 - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@"外设已经断开"); self.discoveredPeripheral = nil; //外设已经断开情况下,重新扫描 [self scan]; } /** 清除方法 */ - (void)cleanup { // 如果没有连接则退出 if (!self.discoveredPeripheral.isConnected) { return; } // 判断是否已经预定了特征 if (self.discoveredPeripheral.services != nil) { for (CBService *service in self.discoveredPeripheral.services) { if (service.characteristics != nil) { for (CBCharacteristic *characteristic in service.characteristics) { if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) { if (characteristic.isNotifying) { //停止接收特征通知 [self.discoveredPeripheral setNotifyValue:NO forCharacteristic:characteristic]; //断开与外设连接 [self.centralManager cancelPeripheralConnection:self.discoveredPeripheral]; return; } } } } } } //断开与外设连接 [self.centralManager cancelPeripheralConnection:self.discoveredPeripheral]; } @end
外设角色编程实现过程
1.设置CBPeripheraManager
2.设置服务与特征
3.发布服务与特征
4.广播服务
5.发送数据
#import <UIKit/UIKit.h> #import <CoreBluetooth/CoreBluetooth.h> #define TRANSFER_SERVICE_UUID @"D63D44E5-E798-4EA5-A1C0-3F9EEEC2CDEB" #define TRANSFER_CHARACTERISTIC_UUID @"1652CAD2-6B0D-4D34-96A0-75058E606A98" #define NOTIFY_MTU 20 @interface ViewController : UIViewController <CBPeripheralManagerDelegate, UITextViewDelegate> @property (strong, nonatomic) CBPeripheralManager *peripheralManager;//用来管理BLE的外设设备 @property (strong, nonatomic) CBMutableCharacteristic *transferCharacteristic;//特征类 @property (strong, nonatomic) NSData *dataToSend; @property (nonatomic, readwrite) NSInteger sendDataIndex; @property (weak, nonatomic) IBOutlet UITextView *textView; - (IBAction)valueChanged:(id)sender; @end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //设置CBPeripheralManager _peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil]; } - (void)viewWillDisappear:(BOOL)animated { [self.peripheralManager stopAdvertising]; [super viewWillDisappear:animated]; } #pragma mark - Peripheral Methods //外设设置成功回调此方法 - (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral { if (peripheral.state != CBPeripheralManagerStatePoweredOn) { return; } NSLog(@"BLE打开"); // 初始化特征 self.transferCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID] properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable]; // 初始化服务 CBMutableService *transferService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID] primary:YES]; // 添加特征到服务 transferService.characteristics = @[self.transferCharacteristic]; // 发布服务与特征 [self.peripheralManager addService:transferService]; } - (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error { NSLog( @"添加服务" ); if (error) { NSLog(@"添加服务失败: %@", [error localizedDescription]); } } - (IBAction)valueChanged:(id)sender { UISwitch* advertisingSwitch = (UISwitch*)sender; if (advertisingSwitch.on) { // 开始广播 [self.peripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] }]; } else { [self.peripheralManager stopAdvertising]; } } //远程中心预定数据回调该方法 - (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic { NSLog(@"中心已经预定了特征"); self.dataToSend = [self.textView.text dataUsingEncoding:NSUTF8StringEncoding]; self.sendDataIndex = 0; [self sendData]; } - (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic { NSLog(@"中心没有从特征预定"); } - (void)sendData { //发送数据结束标识 static BOOL sendingEOM = NO; if (sendingEOM) { BOOL didSend = [self.peripheralManager updateValue:[@"EOM" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil]; if (didSend) { sendingEOM = NO; NSLog(@"Sent: EOM"); } return; } if (self.sendDataIndex >= self.dataToSend.length) { return; } BOOL didSend = YES; while (didSend) { NSInteger amountToSend = self.dataToSend.length - self.sendDataIndex; if (amountToSend > NOTIFY_MTU) amountToSend = NOTIFY_MTU; NSData *chunk = [NSData dataWithBytes:self.dataToSend.bytes+self.sendDataIndex length:amountToSend]; //发送数据 didSend = [self.peripheralManager updateValue:chunk forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil]; if (!didSend) { return; } NSString *stringFromData = [[NSString alloc] initWithData:chunk encoding:NSUTF8StringEncoding]; NSLog(@"Sent: %@", stringFromData); self.sendDataIndex += amountToSend; if (self.sendDataIndex >= self.dataToSend.length) { sendingEOM = YES; BOOL eomSent = [self.peripheralManager updateValue:[@"EOM" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil]; if (eomSent) { sendingEOM = NO; NSLog(@"Sent: EOM"); } return; } } } //发送数据失败后(发送数据的队列已经满了)重新发送 - (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral { [self sendData]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end
更多干货,请支持原作:http://item.jd.com/11436547.html