整体概念

1

1

1

1

蓝牙连接发送数据流程

1

基础概念

BLE: 全称Bluetooth low energy ,蓝牙4.0设备,(因为低功耗)

Central: 中心设备,发起蓝牙连接的设备(一般指手机)

peripheral: 外设,被蓝牙连接的设备(一般是带蓝牙模块的硬件设备,如手环、音响等)

Service: 服务,外设广播和运行的时候会有服务,可以理解成一个功能模块,外设可以有多个服务。中心设备可以读取服务。

Characteristic: 特征,每个服务都包含很多特征值,特征值会有一个value,一般读写的数据就是这个value,特征分read、write、notify等权限

Description: 描述,每个特征可以对应一个或者多个,用于描述特征的信息或者属性。

MFI: made for iOS (苹果MFI认证),是苹果公司对其授权配件厂商生产的外置配件的一种标识使用许可

UUID: unique identify,UUID是一个16bit或128bit的值,用于区分不同的服务和特征,可以理解为服务或者特征的身份证。它通常不会由我们定义,一般是通过查询后获取。一般在编写外设时,定义设备(NSUUID),服务(CBUUID)或特征(CBUUID)的唯一标识符时用到。编写中心设备时,需根据搜索设备(NSUUID)或服务(CBUUID)时也会用到。UUID每个字符用的是16进制表示。

NSUUID: 采用RFC4122 version 4协议形成的128位唯一标识字符串,这里用于唯一标识蓝牙设备。这意味着每个蓝牙模块都是唯一的。

CBUUID: 也是一个128位唯一标识符,用于标识蓝牙的服务、特征或特征的描述符descriptor。这里使用的是蓝牙技术联盟Bluetooth SIG制定的规范。

广播: 就是外设不停散播蓝牙信号,让中心设备可以扫描到。

基础操作 - 检测蓝牙的状态

在对蓝牙进行广播、连接等一系列操作之前,都要先检查蓝牙的状态,在已确保蓝牙开启的前提下去操作,避免因为蓝牙未开启而导致操作失败。


#import "ViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>

@interface ViewController ()<CBCentralManagerDelegate>
/// 蓝牙相关 中心管理者(手机设备)
@property (nonatomic, strong) CBCentralManager *mCentral;
/// 是否已打开蓝牙
@property (nonatomic, assign) BOOL isOpenBluetooth;


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 检测程序进入前台并处于活动状态时蓝牙的状态
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkBLEStatus) name:UIApplicationDidBecomeActiveNotification object:nil];
    // 初始化BLE中心设备
    [self mCentral];
    
}

/// 1开始,初始化一个中心设备
- (CBCentralManager *)mCentral {
    if (!_mCentral) {
        _mCentral = [[CBCentralManager alloc] initWithDelegate:self
                                                         queue:dispatch_get_main_queue()
                                                       options:nil];
    }
    return _mCentral;
}

/// 2如果成功初始化中心管理者,就会回调 CBCentralManagerDelegate 触发此代理方法
/// @param central 中心设备
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    if (central.state == CBManagerStatePoweredOn) {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.isOpenBluetooth = YES;
            [[NSUserDefaults standardUserDefaults]setBool:true forKey:@"isOpenBluetooth"];
            [[NSUserDefaults standardUserDefaults]synchronize];
            [self checkBLEStatus];
        });
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.isOpenBluetooth = NO;
            [[NSUserDefaults standardUserDefaults]setBool:false forKey:@"isOpenBluetooth"];
            [[NSUserDefaults standardUserDefaults]synchronize];
            [self checkBLEStatus];
        });
    }
}

/// 检测蓝牙开启状态
- (void)checkBLEStatus {
    if (self.isOpenBluetooth) {
        NSLog(@"已开启蓝牙");
    } else {
        NSLog(@"没有打开蓝牙");
    }
}

基础操作 - NSUUID一般用法

// 生成一个随机128位唯一标识符
NSUUID *uu = [NSUUID UUID];

// 读取UUID
NSString *str = uu.UUIDString;

// 两个UUID比较不能使用== 
if ([UUID1 isEqueal: UUID2]) {
// other code;
}

常见问题 - [CoreBluetooth] XPC connection invalid

CBCentralManager 的创建是异步的,如果初始化完成之后没有被当前创建它的类所持有,就会在下一次 RunLoop 迭代的时候释放。当然 CBCentralManager 实例如果不是在 ViewController 中创建的,那么持有 CBCentralManager 的这个类在初始化之后也必须被 ViewController 持有,否则控制台会有此输出

常见问题 - 关于Mac地址的获取

自iOS7之后,苹果不支持获取Mac地址,只能用UUID来标识设备。值得注意的是同一个设备在不同手机上显示的UUID不相同。但有的设备可以通过 “180A”这个服务来发现特征,再读取 “2A23”这个特征值,可以获得Mac地址。若该蓝牙设备不支持此获取方式,你可以跟硬件工程师协商添加一个获取地址命令或者增加一个含地址的特征值来获得Mac地址。(前提都是需要先建立连接)。若要求在扫描的时候获得Mac地址,需让硬件工程师把数据写入广播包里。