iOS 蓝牙BLE4.0的开发使用

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

BLE:(Bluetooth low energy)蓝牙4.0设备因为低耗电

一、主要角色:

Central: 中心设备,发起蓝牙连接的设备(一般指手机)
Peripheral: 外设,被蓝牙连接的设备(一般是运动手环/蓝牙模块)
Service:服务,每个设备会提供服务,一个设备有很多服务
Characteristic:特征,每个服务中包含很多个特征,这些特征的权限一般分为:读(read)/写(write)/通知(notice)几种,可以通过特征进行读写数据(重要角色)
Descriptor:描述者,每个特征可以对应一个或者多个描述者,用于描述特征的信息或者属性

<一般开发中用到特征读写数据就结束了,一般不会用到描述者>
<特征就是具体的键值对,每个特征中都有一个对应的特征值,特征的属性分为读(read)/写(write)/通知(notice)等>
<每个描述者都有一个对应的描述值>

二、简述蓝牙通讯的过程:

  1. 建立中心角色
  2. 扫描外设(Discover Peripheral)
  3. 连接外设(Connect Peripheral)
  4. 扫描外设中的服务和特征 (Discover Service and Characteristic)
    4.1 获取外设中的server
    4.2 获取外设的特征 和 特征值
    4.3 获取特征中的描述者 和描述者的值
  5. 利用特征与外设做数据交互
  6. 订阅特征中的通知
  7. 断开连接

三、项目中的相关代码

一、在项目中导入框架并在类中遵循两个协议

二、初始化中心管理者对象(主线程):

- (CBCentralManager *)CentralManager
{
    if (!_CentralManager) {
        _CentralManager = [[CBCentralManager alloc] initWithDelegate:self  queue:dispatch_get_main_queue() options:nil];                                         
    }
    return _CentralManager;
}

三、触发初始化中心管理者代理:初始化成功后开始通过服务扫描外设

//创建完成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就会开始寻找所有的服务。
    }
} 

四、扫描到外设,触发代理方法,根据外设name属性连接相应外设

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

//如果我们成功读取某个特征值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"]]){
            // 根据特征属性来判断特征值
            if(c.properties & CBCharacteristicPropertyWrite && c.properties & CBCharacteristicPropertyRead){
               _lockUnlockCharacteristic = c;
            }
            NSLog(@“找到可读写特征lockUnlockCharacteristic : %@", c);
    }
        
        //读取蓝牙4.0设备电量的特征值、订阅这个特征值以监听电量变化
        if ([[c UUID] isEqual:[CBUUID UUIDWithString:@"0000fff4-0000-1000-8000-00805f9b34fb"]]){
            self.readPowerCharacteristic = c;

      // 获取特征对应的描述 会回调didUpdateValueForDescriptor
      // [peripheral discoverDescriptorsForCharacteristic:cha];
      // 获取特征的值 会回调didUpdateValueForCharacteristic
      // [peripheral readValueForCharacteristic:cha]; 

            NSLog(@"找到可读特征readPowerCharacteristic : %@", c);
            [self.myPeripheral setNotifyValue:YES forCharacteristic:_readPowerCharacteristic];
            }
    }
}

八、发送数据

#pragma 发送数据
-(void)sendDataToBLE:(NSString*)data{ 
     NSData* myData = [data dataUsingEncoding:NSUTF8StringEncoding];
     if(nil != self.lockUnlockCharacteristic){ 
         [self.myPeripheral  writeValue:myData forCharacteristic:self.lockUnlockCharacteristic type:CBCharacteristicWriteWithResponse]; 
     } 
}

九、监听发送回调、通知回调

//向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);

    // 在此处读取描述即可
    for (CBDescriptor *descriptor in characteristic.descriptors) {
        self.mDescriptor = descriptor;
        NSLog(@"发现外设的特征descriptor==%@",descriptor);
    }   }

}

十、根据业务去求,封装对应的数据格式转换的方法

//将传入的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];
}
iOS 蓝牙BLE4.0的开发使用_第1张图片
Snip20180315_2.png

参考博客:
http://blog.csdn.net/Alexander_Wei/article/details/69664308
http://blog.csdn.net/qq_30379689/article/details/61413950

你可能感兴趣的:(iOS 蓝牙BLE4.0的开发使用)