读书笔记---蓝牙(CoreBluetooth)

在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






你可能感兴趣的:(读书笔记,蓝牙,CoreBluetooth)