您的位置:首页 > 移动开发 > IOS开发

iOS开发—蓝牙4.0(BLE)与外设连接及收发数据的流程

2017-04-08 06:13 585 查看
苹果在iOS 6系统之后开始支持BLE 4.0,iPhone4s,iPod 5,iPad 3等之后的机型开始内嵌BLE4.0硬件,因此在开发前请先确认你的开发环境符合上述要求,并且苹果在BLE4.0之后,对外部的连接设备已经不再需要MFI认证了,当然你的外设肯定得要有蓝牙4.0模块。

开发BLE4.0的App,你需要在你的项目里面导入框架:



在需要使用到蓝牙的文件里面导入头文件,并且在你的蓝牙类里面实现两个协议,CBCentralManagerDelegate ,CBPeripheralDelegate

#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>

@interface BluetoothEquipment : NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>


现在我们需要有两个实例对象CBCentralManager和CBPeripheral,第一个是蓝牙中心管理器,主要用来搜索外设,连接外设以及处理外设断开的情况;第二个主要用于在蓝牙中心管理器成功连接外设之后的一系列动作,如:读取外设的服务号CBService,特征值号CBCharacteristic以及对这些特征值号进行读写操作等,下面我们来看一下中心管理器和外设连接的一个大概流程:
1):蓝牙中心管理器开始扫描广播包(扫描的时长可以自己写一个定时器控制,并且可以设定扫描的具体条件)
2):外设开始广播(当然外设的广播时长也是可以设定的)
3):中心管理器发现有广播包,就请求连接外设
4):连接成功之后就可以读取外设的相关信息了,比如服务号CBService,特征值号CBCharacteristic,还有外设的一些硬件信息,电池电量,信号强度RSSI什么的
5):当然在正常连接的过程中总会出现点意外,如果两个设备突然断掉了连接,一般我们还是希望它们能够再次连接的,这里就得要看硬件和程序里对于连接断开的处理代码了

编程代码:
创建BluetoothEquipment类,然后在BluetoothEquipment.h里

#define PERIPHERAL_NAME      @"KL940704079"
#import <Foundation/Foundation.h>#import <CoreBluetooth/CoreBluetooth.h>
@interface BluetoothEquipment : NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>
@property(nonatomic,strong)CBCentralManager* centralManager;@property(nonatomic,strong)CBPeripheral* myPeripheral;
@property(nonatomic,strong)CBCharacteristic* lockUnlockCharacteristic;//上锁和解锁的characteristic@property(nonatomic,strong)CBCharacteristic* readPowerCharacteristic;//电量的characteristic
-(void)initCentralManager;//初始化中心设备管理器-(void)setLockInstruction:(NSString*)lockInstruction;//传入上锁指令-(void)setUnlockInstruction:(NSString *)unlockInstruction;//传入解锁指令
@end

在BluetoothEquipment.m里

#import "BluetoothEquipment.h"
@implementation BluetoothEquipment
//传入上锁指令- (void)setLockInstruction:(NSString *)lockInstruction{    if (_lockUnlockCharacteristic) {        NSData* lockValue = [self dataWithString:lockInstruction];        NSLog(@"上锁的指令lockValue= %@",lockValue);
        [_myPeripheral writeValue:lockValue forCharacteristic:_lockUnlockCharacteristic type:CBCharacteristicWriteWithResponse];        }}
//传入解锁指令-(void)setUnlockInstruction:(NSString *)unlockInstruction{    if (_lockUnlockCharacteristic) {        NSData* unlockValue = [self dataWithString:unlockInstruction];        NSLog(@"解锁的指令unlockValue= %@",unlockValue);                [_myPeripheral writeValue:unlockValue forCharacteristic:_lockUnlockCharacteristic type:CBCharacteristicWriteWithResponse];    }}
//初始化中心设备管理器- (void)initCentralManager{    _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];}
//创建完成CBCentralManager对象之后会回调的代理方法- (void)centralManagerDidUpdateState:(CBCentralManager *)central;{    if (central.state == CBCentralManagerStatePoweredOff) {        NSLog(@"系统蓝牙关闭了,请先打开蓝牙");    }if (central.state == CBCentralManagerStateUnauthorized) {        NSLog(@"系统蓝未被授权");    }if (central.state == CBCentralManagerStateUnknown) {        NSLog(@"系统蓝牙当前状态不明确");    }if (central.state == CBCentralManagerStateUnsupported) {        NSLog(@"系统蓝牙设备不支持");    }if (central.state == CBCentralManagerStatePoweredOn) {        //扫描外设         [_centralManager scanForPeripheralsWithServices:nil options:nil];//如果你将第一个参数设置为nil,Central Manager就会开始寻找所有的服务。    }}
//执行扫描的动作之后,如果扫描到外设了,就会自动回调下面的协议方法了- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI;{ //根据名字有选择性地连接蓝牙设备
    if([peripheral.name  isEqualToString:PERIPHERAL_NAME]){        _myPeripheral = peripheral;        _myPeripheral.delegate = self;        //连接外设        [_centralManager connectPeripheral:_myPeripheral options:nil];    }}
//如果连接成功,就会回调下面的协议方法了- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;{    //停止中心管理设备的扫描动作,要不然在你和已经连接好的外设进行数据沟通时,如果又有一个外设进行广播且符合你的连接条件,那么你的iOS设备也会去连接这个设备(因为iOS BLE4.0是支持一对多连接的),导致数据的混乱。    [_centralManager stopScan];            //一次性读出外设的所有服务    [_myPeripheral discoverServices:nil];}
//掉线- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{    NSLog(@"掉线");}
//连接外设失败- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;{    NSLog(@"连接外设失败");}
//一旦我们读取到外设的相关服务UUID就会回调下面的方法- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error;{    //到这里,说明你上面调用的  [_peripheral discoverServices:nil]; 方法起效果了,我们接着来找找特征值UUID    NSLog(@"发现服务");    for (CBService *s in [peripheral services]) {               [peripheral discoverCharacteristics:nil forService:s];    }    }
//如果我们成功读取某个特征值UUID,就会回调下面的方法- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error;{
    for(int i=0; i < service.characteristics.count; i++) {                CBCharacteristic *c = [service.characteristics objectAtIndex:i];         NSLog(@"特征 UUID: %@ (%@)", c.UUID.data, c.UUID);                if ([[c UUID] isEqual:[CBUUID UUIDWithString:@"0000fff6-0000-1000-8000-00805f9b34fb"]]){                        _lockUnlockCharacteristic = c;            NSLog(@"找到可写特征lockUnlockCharacteristic : %@", c);    }                //读取蓝牙4.0设备电量的特征值        if ([[c UUID] isEqual:[CBUUID UUIDWithString:@"0000fff4-0000-1000-8000-00805f9b34fb"]]){                        self.readPowerCharacteristic = c;            NSLog(@"找到可读特征readPowerCharacteristic : %@", c);
            [self.myPeripheral setNotifyValue:YES forCharacteristic:_readPowerCharacteristic];            }    }    }
//向peripheral中写入数据后的回调函数- (void)peripheral:(CBPeripheral*)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{    NSLog(@"write value success(写入成功) : %@", characteristic);}
//获取外设发来的数据,不论是read和notify,获取数据都从这个方法中读取- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{    [peripheral readRSSI];    NSNumber* rssi = [peripheral RSSI];
    //读取BLE4.0设备的电量    if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"0000fff4-0000-1000-8000-00805f9b34fb"]]){        NSData* data = characteristic.value;        NSString* value = [self hexadecimalString:data];        NSLog(@"characteristic(读取到的) : %@, data : %@, value : %@", characteristic, data, value);        }    }
//将传入的NSData类型转换成NSString并返回- (NSString*)hexadecimalString:(NSData *)data{    NSString* result;    const unsigned char* dataBuffer = (const unsigned char*)[data bytes];    if(!dataBuffer){        return nil;    }    NSUInteger dataLength = [data length];    NSMutableString* hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];    for(int i = 0; i < dataLength; i++){        [hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]];    }    result = [NSString stringWithString:hexString];    return result;}
//将传入的NSString类型转换成ASCII码并返回- (NSData*)dataWithString:(NSString *)string{    unsigned char *bytes = (unsigned char *)[string UTF8String];    NSInteger len = string.length;    return [NSData dataWithBytes:bytes length:len];}
@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: