美文网首页
iOS蓝牙4.0(BLE)开发(二)

iOS蓝牙4.0(BLE)开发(二)

作者: 悟2023 | 来源:发表于2017-07-04 16:57 被阅读99次

CoreBluetooth框架使用及工作原理介绍

1、准备工作:

新建一个BLE工程之后首先要做的事情就是导入CoreBluetooth库,我们在TARGETS——>Build Phases——>Link Binary With Libraries中搜索添加,如下图所示:



接下来就是在需要使用的时候引入头文件#import <CoreBluetooth/CoreBluetooth.h>,并且声明代理:
#import "ZQBluetooth.h"
#import "instructDefine.h"
#import <CoreBluetooth/CoreBluetooth.h>
@interface ZQBluetooth ()
<CBCentralManagerDelegate,
CBPeripheralDelegate>

@property (nonatomic,  weak)id<ZQBluetoothDelegate> delegate;

@property (nonatomic,strong) CBCentralManager*                  centralManager;
@property (nonatomic,strong) CBPeripheral*                      linkPeripheral;         //链接的外设

@property (nonatomic,strong) CBCharacteristic*                  characteristicTx;       //特征Tx
@property (nonatomic,strong) CBCharacteristic*                  characteristicRx;       //特征Rx

@property (nonatomic,strong) CBUUID*                            uuidService;
@property (nonatomic,strong) CBUUID*                            uuidCharTx;
@property (nonatomic,strong) CBUUID*                            uuidCharRx;

@end

可以看到我定义了一些宏,这就是具体你需要连接的外围设备中的服务与特征的UUID了,你的硬件工程师会给你相应的说明文档。
characteristicTx、characteristicRx是其中一个服务的两个特征值,我们就是通过这些特征值和设备做交互的,Tx是读取设备发送给我的数据的,Rx是向设备写入数据发送数据的。
uuidService、uuidCharTx、uuidCharRx分别是服务UUID、Tx特性UUID和Rx特性UUID。

2、创建中心设备管理员对象扫描外设
//初始化 CentralManager
- (void)initBluetoothCentralManager {
    self.uuidService = [CBUUID UUIDWithString:SERVICE_UUID];
    self.uuidCharTx = [CBUUID UUIDWithString:CHAR_TX_UUID];
    self.uuidCharRx = [CBUUID UUIDWithString:CHAR_RX_UUID];
    
    self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
//MARK: ---- CBCentralManagerDelegate(中心)
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    switch (central.state) {
        case CBManagerStateUnknown:         //未知的
            break;
        case CBManagerStateResetting:       //重置
            break;
        case CBManagerStateUnsupported:     //不支持
            break;
        case CBManagerStateUnauthorized:    //未授权
            break;
        case CBManagerStatePoweredOff:      //断开
            break;
        case CBManagerStatePoweredOn:       //链接
        {
            NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],CBCentralManagerScanOptionAllowDuplicatesKey, nil];
            [self scanPeripheralWithServices:nil options:options];
        }
            break;
        default:
            break;
    }
}
[self.centralManager stopScan];    //停止扫描

一般情况下我们会将扫描到的设备添加到一个数组里边,然后建一个TableView来显示我们搜索到的设备对象。

CoreBluetooth有一个搜索到设备之后回调的代理方法,在这个方法中我们可以得到搜索到外设信息,每搜索到一个设备就会调用一次该方法:

/**
 已经搜索到外设

 @param central 中心设备
 @param peripheral 搜索到的外设
 @param advertisementData 广告和扫描响应数据
 @param RSSI 获取到与设备的距离
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI {
    
    NSValue *value_isConnectable = [advertisementData objectForKey:@"kCBAdvDataIsConnectable"];
    const char *connectable = [[value_isConnectable description] cStringUsingEncoding:NSUTF8StringEncoding];
    NSString *isConnectable = [NSString stringWithFormat:@"%s",connectable];
    
    NSValue *value_localName = [advertisementData objectForKey:@"kCBAdvDataLocalName"];
    const char *name = [[value_localName description] cStringUsingEncoding:NSUTF8StringEncoding];
    NSString *localName = [NSString stringWithFormat:@"%s",name];
    
    if ([isConnectable boolValue] == YES && [self isNull:localName] == NO && [self isNull:peripheral.name] == NO) {
        NSLog(@"搜索到外设==%@==广播数据==%@距离==%.2f",peripheral,advertisementData,[self bluetoothDistanceByRSSI:RSSI]);
        
        NSData *data = advertisementData[@"kCBAdvDataManufacturerData"];
        NSLog(@"=========%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        
        
        if (_peripherals.count > 0) {
            BOOL contains = [_peripherals containsObject:peripheral];
            if (!contains) {
                [self.peripherals addObject:peripheral];
                if (self.delegate && [self.delegate respondsToSelector:@selector(scanPeripheral:)]) {
                    [self.delegate scanPeripheral:peripheral];
                }
            }
        }
        else {
            [self.peripherals addObject:peripheral];
            if (self.delegate && [self.delegate respondsToSelector:@selector(scanPeripheral:)]) {
                [self.delegate scanPeripheral:peripheral];
            }
        }
    }
}
3、连接外设 or 断开外设

当我们做完第二步,获取到了外设信息之后,当然是要开始连接设备了,如果我们使用了TableView,我们可以在cell的点击方法里里调用下边的方法:

//链接外设
- (void)connectPeripheral:(CBPeripheral *)peripheral {
    [_centralManager connectPeripheral:peripheral options:nil];// 连接外设 传入你搜索到的目标外设对象
    peripheral.delegate = self;     //设置外设的代理
}
//断开外设
- (void)disConnectPeripheral:(CBPeripheral *)peripheral {
    [_centralManager cancelPeripheralConnection:peripheral];//断开连接
}

连接设备的回调方法:

/**
 已经链接成功

 @param central 中心设备
 @param peripheral 连接的外设
 */
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    _linkPeripheral = peripheral;
    if (self.delegate && [self.delegate respondsToSelector:@selector(scanSuccess:)]) {
        [self.delegate scanSuccess:peripheral];
    }
    [self discoverService];
}
/**
 链接外设失败

 @param central 中心设备
 @param peripheral 链接的外设
 @param error 失败原因
 */
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error {
    if (self.delegate && [self.delegate respondsToSelector:@selector(scanFailure:)]) {
        [self.delegate scanFailure:error];
    }
}
4、发现服务与特征

成功的连接到外设之后,当然是要看看它的内部有什么服务和特征了,这样我们才能顺利的与之进行数据的交互。
发现服务: 我们连接成功的时候已经调用了这个方法来发现服务。

//发现服务
- (void)discoverService {
    [_linkPeripheral discoverServices:@[[CBUUID UUIDWithString:OTA_SERVICE_UUID]]];
}

我们可以看到这个这个方法的参数是传入一个数组,因为一个外设中可能有很多个服务,但是对于我们有使用价值的可能就呢么一个或者两个,我们可以传入相应的UUID来过滤,比如我现在只传入了一个UUID那么我发现的服务就只有这一个了,如果为nil则发现所有服务。 如果成功的发现了其中的服务系统自动回调:

/**
 发现服务

 @param peripheral 外设
 @param error 发现服务报错
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error {
    if (error) {
        NSLog(@"发现服务 error:%@",[error localizedDescription]);
    }
    //连接成功就遍历这些服务 来发现每个服务中的特征
    else {
        for (CBService *service in peripheral.services) {
            NSLog(@"发现服务 UUID: %@", service.UUID);
            if ([service.UUID isEqual:[CBUUID UUIDWithString:SERVICE_UUID]]) {
                //调用此方法来发现该服务中的特征值
                [peripheral discoverCharacteristics:nil forService:service];
                
            }
        }
    }
}

发现特征:发现服务之后就该扫描到该服务中的特征了,发现特征值之后系统自动回调下边的方法 ,每发现一个服务都会调用一次该方法:

/**
 发现特征回调

 @param peripheral 外设
 @param service 服务
 @param error 错误
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error {
    if (!error) {
        //如果成功,我们可以自己写一个方法,查看特征信息等操作。
        [self didFindAllCharacteristic:service.characteristics forService:service];
    }
    else  {
        NSLog(@"%@",error);
    }
}

自己写一个方法来查看所有的特征值:

- (void)didFindAllCharacteristic:(NSArray<CBCharacteristic *> *)characteristics forService:(CBService *)service {
    self.characteristicTx = NULL;
    self.characteristicRx = NULL;
    
    for (CBCharacteristic *cha in characteristics) {
        switch (cha.properties) {
            case CBCharacteristicPropertyBroadcast:                 //广播
                break;
            case CBCharacteristicPropertyRead:                      //读
                NSLog(@"%@------------读",cha);
                break;
            case CBCharacteristicPropertyWriteWithoutResponse:      //写-没有响应
                break;
            case CBCharacteristicPropertyWrite:                     //写
                NSLog(@"%@------------写",cha);
                break;
            case CBCharacteristicPropertyNotify:                    //通知
                NSLog(@"%@------------订阅",cha);
                break;
            case CBCharacteristicPropertyIndicate:                  //声明
                break;
            case CBCharacteristicPropertyAuthenticatedSignedWrites: //通过验证的
                break;
            case CBCharacteristicPropertyExtendedProperties:        //拓展
                break;
            case CBCharacteristicPropertyNotifyEncryptionRequired:  //需要加密的通知
                break;
            case CBCharacteristicPropertyIndicateEncryptionRequired://需要加密的申明
                break;
                
            default:
                NSLog(@"%@------------other",cha);
                break;
        }
        
        if ([[cha UUID] isEqual:_uuidCharTx]) {
            _characteristicTx = cha;
            //判断相应的UUID来给我们声明的属性赋值
            //这个特征只有写入的属性,所有不能为其注册通知
        }
        if ([[cha UUID] isEqual:_uuidCharRx]) {
            _characteristicRx = cha;
            //订阅通知
            [self.linkPeripheral setNotifyValue:YES forCharacteristic:cha];
            //这里要订阅通知,因为这个特征拥有 读 和 订阅 属性,这里注册之后设备通过这个特性值传送给APP的数据就可以收到了。
        }
    }
}

我们还可以通过这一个方法监听到通知的状态:

//监听到通知的状态
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error {
    if (!error) {
        NSLog(@"注册成功!");
    }
    else {
        NSLog(@"注册失败!:%@",error);
    }
}

获取到服务与特征之后,就可以开始和设备进行数据的交互了。而整个蓝牙开发过程最复杂的地方,也是最重要的地方就是,数据的交互了。下篇文章再讲

相关文章

  • CoreBluetooth

    iOS-BLE蓝牙开发持续更新 - 简书 蓝牙打印小票 一个第三方 IOS BLE4.0蓝牙和外设连接和收发数据的...

  • iOS 蓝牙BLE4.0开发

    蓝牙开发,现在普遍的都是BLE4.0低功耗蓝牙,CoreBluetooth是iOS 开发I比较推荐的一种开发方法...

  • iOS蓝牙4.0基础开发

    1.蓝牙开发基础 蓝牙4.0是低电量模式所以也叫4.0BLE。本文将使用iOS系统提供的CoreBluetooth...

  • macOS-BLE蓝牙4.0开发

    macOS-BLE蓝牙4.0开发 !!!中心模式 !!! macOS的BLE程序代码和iOS差不多,只需要修改一些...

  • iOS CoreBluetooth 蓝牙4.0学习接入笔记

    最近公司的项目中提到了蓝牙开发,而且现在市面上的蓝牙分为普通蓝牙和低功耗蓝牙(BLE)也就是蓝牙4.0 iOS 提...

  • Android 蓝牙BLE开发流程

    关键术语和概念 蓝牙有传统蓝牙(3.0以下)和低功耗蓝牙(BLE,又称蓝牙4.0)之分,而蓝牙4.0开发需要and...

  • 蓝牙

    iOS蓝牙4.0 BLE开发总结 非自写,转过来做个笔记,原文来自这里[http://mideablog.gith...

  • iOS蓝牙4.0(BLE)开发(二)

    CoreBluetooth框架使用及工作原理介绍 1、准备工作: 新建一个BLE工程之后首先要做的事情就是导入Co...

  • IOS蓝牙4.0(BLE)开发(二)

    其实IOS的BLE开发并不是特别复杂,难度也不是很大。它的实质就是CoreBluetooth.framework...

  • iOS开发蓝牙4.0初识

    iOS开发蓝牙4.0初识转载 2015-09-20 15:26:44标签:ios开发蓝牙ios开发蓝牙4.0ios...

网友评论

      本文标题:iOS蓝牙4.0(BLE)开发(二)

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