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

苹果在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):当然在正常连接的过程中总会出现点意外,如果两个设备突然断掉了连接,一般我们还是希望它们能够再次连接的,这里就得要看硬件和程序里对于连接断开的处理代码了

 

示例代码

1.创建BluetoothEquipment类,然后在BluetoothEquipment.h里

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

#define PERIPHERAL_NAME    @"KL940704079"

@interface BluetoothEquipment : NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>

@property(nonatomic,strong)CBCentralManager *centralManager;
@property(nonatomic,strong)CBPeripheral *myPeripheral;
///上锁和解锁的characteristic
@property(nonatomic,strong)CBCharacteristic *lockUnlockCharacteristic;
///电量的characteristic
@property(nonatomic,strong)CBCharacteristic *readPowerCharacteristic;

///初始化中心设备管理器
-(void)initCentralManager;
///传入上锁指令
-(void)setLockInstruction:(NSString*)lockInstruction;
///传入解锁指令
-(void)setUnlockInstruction:(NSString *)unlockInstruction;


@end

 

2.在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) {
        //扫描外设:如果你将第一个参数设置为nil,Central Manager就会开始寻找所有的服务。
        [_centralManager scanForPeripheralsWithServices:nil options:nil];
    }
}

//执行扫描的动作之后,如果扫描到外设了,就会自动回调下面的协议方法了
- (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

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值