iOS蓝牙开发(bluetooth)

蓝牙库( 4.0 BLE )

苹果自身有一个操作蓝牙的库 CoreBluetooth.framework,这是 大部分人进行蓝牙开发的首选框架。
除此之外,目前github上还有一个比较流行的对原生框架进行封装的三方库 BabyBluetooth

蓝牙设备版本要求

蓝牙设备必须是4.0及以上.
BLE : bluetouch low enery,蓝牙4.0设备因为低功耗,所以也被称为BLE。苹果在 iphone4s 及之后的手机都支持蓝牙4.0。
低于蓝牙4.0协议的设备需要进行MFI认证
MFI : make for ipad, iphone, itouch 专门为苹果设备制作的设备
MFI : 开发框架为 ExternalAccessory 框架
BLE 4.0 : 开发框架为 CoreBluetooth 框架

蓝牙知识 ( 主讲中心模式,外设暂未开发留作以后补充 )

蓝牙处理是16进制,并且每次传输最多是20个字节
CoreBluetooth 框架主要核心部分就是两个,peripheral 和 central。
发起连接的是中心设备,被连接的是外围设备。
中心模式:以app作为中心,连接其他外设的场景
外设模式:使用手机作为外设连接其他中心设备的操作场景

服务,特征,特征的属性(service and characteristic)

一个外设可以包含一个或多个服务(CBService),一个服务又包含一个或多个特征(CBCharacteristic),特征就是具体功能的键值对,提供数据的地方。每个特征的属性分为:通知,读,写这几种方式

外设,服务,特征之间的关系如下:


关系图

蓝牙中心模式流程 ( 以BabyBluetooth为例 )

1.初始化中心设备管理者:CBCentralManager
/**
将蓝牙模块进行封装单例
初始化蓝牙设置蓝牙中心设备
*/
+ (instancetype)shareBaby {
    
    static BabyBlueToothManager *babyBluetooth;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!babyBluetooth) {
            babyBluetooth = [[self class] alloc];
            // 提示蓝牙功能开启
            NSDictionary *options = @{CBCentralManagerOptionShowPowerAlertKey: @YES};
            babyBluetooth.centeralManager = [[CBCentralManager alloc] initWithDelegate:babyBluetooth queue:nil options:options];
            
            // 初始化 baby 蓝牙库
            babyBluetooth.baby = [BabyBluetooth shareBabyBluetooth];
            // 设置蓝牙代理
            [babyBluetooth babyDelegate];
           //babyBluetooth.baby.scanForPeripherals().begin();
        }
    });
    return babyBluetooth;
}
2.扫描外围设备
[BabyBlueToothManager shareBaby].baby.scanForPeripherals().begin();
3.扫描结果通过CBCentralManagerDelegate代理进行回调,这里BabyBluetooth进行block块封装
/**
搜索设备获取中心设备,
外设
外设advertisementData数据(广告数据),通常情况下mac地址会存储在这里
RSSI为信号强度
*/
[_baby setBlockOnDiscoverToPeripherals:^(CBCentralManager *central, CBPeripheral *peripheral, NSDictionary *advertisementData, NSNumber *RSSI) {
        NSLog(@"搜索到了设备:%@",peripheral.name);
        @strongify_self
    
    }];
/**
获取外设后,对外设进行过滤,筛选符合规则的蓝牙设备
*/
[_baby setFilterOnDiscoverPeripherals:^BOOL(NSString *peripheralName, NSDictionary *advertisementData, NSNumber *RSSI) {
        //判断设备,通过相应规则搜索出的设备会显示在  BlockOnDiscoverToPeripherals 这个方法中
        if (peripheralName.length >1) {
            if ([advertisementData[@"kCBAdvDataLocalName"] hasPrefix:@"Pxxxxx"] || [advertisementData[@"kCBAdvDataLocalName"] hasPrefix:@"Sxxxx"]) {
                return YES;
            }
        }
        return NO;
    }];
4.连接设备并断开搜索
/**
 连接蓝牙
 */

- (void)connetBlueToothWithCBPeripheral:(CBPeripheral *)peripheral {
    
// 连接外设.发现服务.发现特征.读取特征数据.发现特征数据(键值对).读取特征描述.开始连接
self.baby.having(peripheral).connectToPeripherals().discoverServices().discoverCharacteristics().readValueForCharacteristic().discoverDescriptorsForCharacteristic().readValueForDescriptors().begin();  
// 取消搜索蓝牙
    [self.baby cancelScan];

}
5.设备连接状态回调
// 设备连接成功
    [_baby setBlockOnConnected:^(CBCentralManager *central, CBPeripheral *peripheral) {
        NSLog(@"设备:%@--连接成功",peripheral.name);
        @strongify_self
    }];

//设置设备连接失败的委托
    [_baby setBlockOnFailToConnect:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        NSLog(@"设备:%@--连接失败",peripheral.name);
        [GGProgress showProgressWithTitle:@"设备连接失败"];
    }];

//设置设备断开连接的委托
    [_baby setBlockOnDisconnect:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        NSLog(@"设备:%@--断开连接",peripheral.name);
        @strongify_self
        // 这里可以处理重新连接
    }];
6.连接成功后发现设备服务(service)
// 发现设备服务
 [_baby setBlockOnDiscoverServices:^(CBPeripheral *peripheral, NSError *error) {
        for (CBService *s in peripheral.services) {
            //每个service
        }
    }];
//设置发现设service的Characteristics的委托
    [_baby setBlockOnDiscoverCharacteristics:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
        NSLog(@"===service name:%@",service.UUID);
        [service.characteristics enumerateObjectsUsingBlock:^(CBCharacteristic * _Nonnull characteristic, NSUInteger idx, BOOL * _Nonnull stop) {
            // 通过枚举获取服务特征
            NSLog(@"aaaaaaaa    %@ \n %lu ", characteristic.UUID , (unsigned long)characteristic.properties);
        }];
    }];
 //设置发现characteristics的descriptors的委托
    [_baby setBlockOnDiscoverDescriptorsForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"===characteristic name:%@",characteristic.service.UUID);
        for (CBDescriptor *d in characteristic.descriptors) {
            NSLog(@"CBDescriptor name is :%@",d.UUID);
        }
    }];
7.读取设备服务-特征的数据
  [_baby setBlockOnReadValueForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
        // 
        @strongify_self
        CBUUID *uuid = characteristics.UUID;
        if ([uuid.UUIDString isEqualToString:@"xxxx"]) {
            // 如果是想要的服务特征 则赋值到 相对应的 外设及 特征中,进行数据交互
            self.characteristic = characteristics;
            self.peripheral = peripheral;
        }
    }];
8.读取特征的数据描述(键值对),注册特征通知,中心设备读取外设外围所发送过来的数据
   //设置读取Descriptor的委托
       [_baby setBlockOnReadValueForDescriptors:^(CBPeripheral *peripheral, CBDescriptor *descriptor, NSError *error) {
        @strongify_self
        CBUUID *uuid = descriptor.characteristic.UUID;
        CBCharacteristic *charach = descriptor.characteristic;
        NSData *data = charach.value;
        //  判断是否是当前设备
        if ([[BlueToothInfo shareBlueToothInfo].localName isEqualToString:@"xxxx"]) {
            // 获取 所要获取的特征
            if ([uuid.UUIDString isEqualToString:@"xxxx"]) {
                self.characteristic = descriptor.characteristic;
                self.peripheral = peripheral;
            }else {
                // 进行注册特征通知,获取外围数据
                [self.baby notify:peripheral characteristic:descriptor.characteristic block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
                    @strongify_self
                     // 收到的指令数据
                    NSData *wineData = characteristics.value;
                    // 16进制数据转换,判断指令
                    NSString *str16 = [self convertDataToHexStr:wineData];
                }];
            }
        }
        NSLog(@"Descriptor name:%@ value is:%@\n %@",descriptor.characteristic.UUID, descriptor.value, data);
    }];
9.处理数据(数据接收结束)。以下为向外围设备发送数据
/** 通过单例 获取当前外设, 通过特征值进行写入操作
data 通过 NSASCIIStringEncoding ASCII进行转换,蓝牙接收数据为16进制
 writeType 分为两种
1.CBCharacteristicWriteWihResponse(写成功一次,只可读)即有反馈
2.CBCharacteristicWriteWithoutResponse(一次也不能写成功,可以读,也可以通知)即无反馈
*/
[[BabyBlueToothManager shareBaby].peripheral writeValue:data forCharacteristic:[BabyBlueToothManager shareBaby].characteristic type:writeType];
// 写入的数据 均在 步骤 8中的 notify 回调中 回调数据
10.写入成功与否的回调
//写Characteristic成功后的block
 [_baby setBlockOnDidWriteValueForCharacteristic:^(CBCharacteristic *characteristic, NSError *error) {
        // error判断 写入特征是否成功,自行处理
    }];
//写descriptor成功后的block
[_baby setBlockOnDidWriteValueForDescriptor:^(CBDescriptor *descriptor, NSError *error) {
         // error判断 写入特征描述数据是否成功,自行处理
    }];
11.断开连接
//断开连接
- (void)cancelPeripheralConnection:(CBPeripheral *)peripheral {
    [babyCentralManager cancelPeripheralConnection:peripheral];
}
//断开所有连接
- (void)cancelAllPeripheralsConnection {
    [babyCentralManager cancelAllPeripheralsConnection];
}

如有疑问可以探讨,如有错误可以指正,欢迎补充,感谢支持

你可能感兴趣的:(iOS蓝牙开发(bluetooth))