在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
这章稍显复杂,我有一天不明白,如果有外设,那么如果外设不是iPhone设备我们要怎么做呢,怎么把ios代码弄进去呢?
更多干货,请支持原作:http://item.jd.com/11436547.html