美文网首页
iOS Core Bluetooth

iOS Core Bluetooth

作者: 清风沐沐 | 来源:发表于2017-01-17 17:21 被阅读161次

    记录下蓝牙开发:

    先明确5个概念:

    CBCentral 中心设备(蓝牙主机)
    CBPeripheral 外设(蓝牙从机)
    CBService 服务
    CBCharacteristic 特征
    CBUUID UUID
    

    蓝牙连接的步骤就是建立中心设备,扫描外设,按硬件话说就是主机找从机。在外设中找到服务,在服务里找到它所有的特征。
    写了个BluetoothHelper,注释已经写的很清楚了。

    BluetoothHelper.h
    
    #import <Foundation/Foundation.h>
    #import <CoreBluetooth/CoreBluetooth.h>
    
    @interface BluetoothHelper : NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>
    
    + (BluetoothHelper *)sharedInstance;
    
    - (void)connect;
    
    - (void)disConnect;
    
    - (void)sendData:(NSString *)command;
    
    @end
    
    
    
    BluetoothHelper.m
    
    #import "BluetoothHelper.h"
    #import "ToolHelper.h"
    
    static NSString * const kName = @"BLE_Serial";
    
    static NSString * const kSUUID= @"0003CDD0-XXXX-XXXX-XXXX-00805f9bXXXX";
    static NSString * const KNotifyUUID = @"0003CDD1-XXXX-XXXX-XXXX-00805f9bXXXX";
    static NSString * const kWriteUUID= @"0003CDD2-XXXX-XXXX-XXXX-00805f9bXXXX";
    
    @interface BluetoothHelper ()
    
    @property (nonatomic, strong) CBCentralManager * manger;
    @property (nonatomic, strong) CBPeripheral * cbPeripheral;
    @property (nonatomic, assign) BOOL blueIsOn;
    
    @end
    
    @implementation BluetoothHelper
    
    #pragma mark - life cycle
    
    + (BluetoothHelper *)sharedInstance{
        static BluetoothHelper *instance = nil;
        static dispatch_once_t predicate;
        dispatch_once(&predicate, ^{
            instance = [[self alloc] init];
        });
        return instance;
    }
    
    - (instancetype)init{
        self = [super init];
        if (self) {
            self.manger = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
        }
        return self;
    }
    
    #pragma mark - CBCentralManagerDelegate Methods
    
    //检测蓝牙状态
    - (void)centralManagerDidUpdateState:(CBCentralManager *)central{
        switch (central.state) {
                
            case CBCentralManagerStatePoweredOn:{
                self.blueIsOn = YES;
            }
                break;
            case CBCentralManagerStateResetting:
            case CBCentralManagerStateUnauthorized:
            case CBCentralManagerStateUnknown:
            case CBCentralManagerStateUnsupported:
            case CBCentralManagerStatePoweredOff:{
                self.blueIsOn = NO;
            }
                break;
            default:
                NSLog(@"Central Manager did change state");
                break;
        }
    }
    
    //发现蓝牙设备
    - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
        //设置监听,以保证始终寻找外设
        [self startScanningTimeoutMonitor];
        
        if ([peripheral.name isEqualToString:kName]) {
            [self.manger stopScan];
            [self.manger connectPeripheral:peripheral options:nil];
            self.cbPeripheral = peripheral;
        }
        NSLog(@"发现蓝牙%@",peripheral);
    }
    
    //连接外设成功
    -(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
        self.cbPeripheral = peripheral;
        self.cbPeripheral.delegate = self;
        [self.cbPeripheral discoverServices:@[]];
        [self cancelScanningTimeoutMonitor];
        [self cancelSendTimeOut];
        NSLog(@"连接成功%@",self.cbPeripheral);
    }
    
    //连接外设失败
    - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
        if (error) {
            NSLog(@"连接失败ERROR:%@ peripheral:%@",error,peripheral);
        }
    }
    
    //断开外设连接
    -(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
        NSLog(@"断开连接%@",peripheral);
        self.cbPeripheral = nil;
        [ToolHelper showErrorMessage:@"连接失败,重新连接"];
        [self connect];
    }
    
    #pragma mark - CBPeripheralDelegate Methods
    
    //已搜索到services 根据周边找特征
    -(void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
        
        for (CBService *s in peripheral.services) {
            if ([s.UUID isEqual:[CBUUID UUIDWithString:kSUUID]]) {
                [peripheral discoverCharacteristics:nil forService:s];
                NSLog(@"找到周边peripheral:%@ Service:%@",peripheral,s);
                return;
            }
        }
    }
    
    //已搜索到Characteristics  设置订阅
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
        for (CBCharacteristic *c in service.characteristics) {
            if ([c.UUID isEqual:[CBUUID UUIDWithString:KNotifyUUID]]) {
                //设置监听然后会走didUpdateNotificationStateForCharacteristic
                [peripheral setNotifyValue:YES forCharacteristic:c];
                NSLog(@"设置订阅 peripheral%@ Characteristic%@",peripheral,c);
            }
        }
    }
    
    //注册订阅后的中间通知步骤 判断是否正确
    - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
        if (error == nil) {
            [peripheral readValueForCharacteristic:characteristic];
        }
        NSLog(@"设置读取返回数据 peripheral%@ characteristic%@",peripheral,characteristic);
        
        //给外设发送指定字符验证是否联通
        [self sendData:@"yue?"];
    }
    
    //蓝牙回传的数据都会从这个方法中得到
    - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
        if (error) {
            NSLog(@"返回数据ERROR:%@",error);
        }
        NSString * updateString = [[NSString alloc]initWithData:characteristic.value encoding:NSUTF8StringEncoding];
        
        NSLog(@"updateString - %@",updateString);
        
        if ([updateString isEqualToString:@"yue!"]){
            
            [ToolHelper showSuccessMessage:@"成功连接设备"];
            
        } else {
            
        }
    }
    
    #pragma mark - private methods
    
    //把要发送的数据用ASCII编码
    - (void)sendData:(NSString *)command
    {
        NSData * data = [command dataUsingEncoding:NSASCIIStringEncoding];
        [self writeData:data];
    }
    
    //将数据传送给蓝牙
    - (void)writeData:(NSData *)bluetoothData{
        for (CBService *service in self.cbPeripheral.services ) {
            if ([service.UUID isEqual:[CBUUID UUIDWithString:kSUUID]]) {
                for ( CBCharacteristic *characteristic in service.characteristics ) {
                    if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kWriteUUID]]) {
                        /* EVERYTHING IS FOUND, WRITE characteristic ! */
                        [self.cbPeripheral writeValue:bluetoothData forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
                    }
                }
            }
        }
    }
    
    
    #pragma mark - public methods
    
    //寻找外设
    - (void)connect{
        if (self.blueIsOn) {
            NSLog(@"scan....");
            if(self.cbPeripheral){
                [self.manger connectPeripheral:self.cbPeripheral options:nil];
            }else {
                [self.manger scanForPeripheralsWithServices:nil  options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
            }
        }
        [self startSendTimeOut];
    }
    
    //断开蓝牙连接
    - (void)disConnect{
        if (self.cbPeripheral) {
            [self.manger cancelPeripheralConnection:self.cbPeripheral];
            [self.manger stopScan];
        }
        [ToolHelper showErrorMessage:@"发送失败,请重新发送"];
    }
    
    
    #pragma mark - Connection Timeout
    
    - (void)startScanningTimeoutMonitor {
        [self cancelScanningTimeoutMonitor];
        [self performSelector:@selector(connect)
                   withObject:nil
                   afterDelay:2.0f];
    }
    
    - (void)cancelScanningTimeoutMonitor {
        [NSObject cancelPreviousPerformRequestsWithTarget:self
                                                 selector:@selector(connect)
                                                   object:nil];
    }
    
    - (void)startSendTimeOut {
        [self performSelector:@selector(disConnect)
                   withObject:nil
                   afterDelay:60.0f];
    }
    
    - (void)cancelSendTimeOut {
        [NSObject cancelPreviousPerformRequestsWithTarget:self
                                                 selector:@selector(disConnect)
                                                   object:nil];
    }
    
    @end
    

    相关文章

      网友评论

          本文标题:iOS Core Bluetooth

          本文链接:https://www.haomeiwen.com/subject/kpombttx.html