iOS蓝牙4.0基础开发
1.蓝牙开发基础
蓝牙4.0是低电量模式所以也叫4.0BLE。本文将使用iOS系统提供的CoreBluetooth框架。
CoreBluetooth框架的核心其实是两个东西,peripheral和central, 可以理解成外设和主设备(中心)。
左边是主设备模式,即开发的app在手机上,手机连接其它硬件(外设);
右边的是外设模式,手机作为外设,其它硬件设备作为主设备。本文只讲主设备模式,这种应用场景是最多的。
外设peripheral(主设备模式下,与手机连接的硬件是peripheral,例如AppleWatch)、服务service、特征值characteristic的关系如下:
每个外设下都有多个服务,每个服务里面有多个特征值。服务和特征值都有一个唯一识别码UUID。与特征值交互的模式常用有三种:读取(read)、写入(write)、还有监听(notify)。我们需要根据与硬件工程师所订的协议找到对应服务里面的特征值,读取或写入这个特征值。例如,我们需要知道外设的硬件的电量,我们需要读取约定好的服务里的特征值,来获取电量。如果我们需要向外设发送指令,只需要找到对应的特征值,写入数据。
2.主设备模式流程及相关代码
这里简单介绍一下系统CoreBluetooth使用的方法及代理。以便对后面使用第三方库LGBluetooth更好地理解及使用和修改第三方内部的方法符合业务场景需求。
1.建立主设备模式
#import <CoreBluetooth/CoreBluetooth.h> CBCentralManager *manager = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
2.扫描外设(discover)
//扫描设备 [manager scanForPeripheralsWithServices:nil options:nil]; //扫描到设备会进入方法 -(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI;
3.连接外设(connect)
[manager connectPeripheral:peripheral options:nil]; //连接外设成功的委托 - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral; //外设连接失败的委托 - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error; //断开外设的委托 - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;
4.扫描外设中的服务和特征(discover)
- 4.1 获取外设的services - 4.2 获取外设的Characteristics,获取Characteristics的值
//扫描到服务 -(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error; //找到服务后,扫描到服务里面的特征值 -(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error;
5.与外设做数据交互(字节处理)
//在特征值写数据 [peripheral writeValue:value forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
6.订阅Characteristic的通知
//订阅通知 [peripheral setNotifyValue:YES forCharacteristic:characteristic];
7.断开连接(disconnect)
//断开连接的回调 -(void)disconnectPeripheral:(CBCentralManager *)centralManager peripheral:(CBPeripheral *)peripheral { //停止扫描 [centralManager stopScan]; //断开连接 [centralManager cancelPeripheralConnection:peripheral]; }
3.基于第三方LGBlueTooth蓝牙开发
1.在Appdelegate初始化LGCentralManager
#import <LGBluetooth/LGBluetooth.h> [LGCentralManager sharedInstance]
2.对LGBlueTooth封装一个类,用来处理业务的蓝牙指令(CommunicationManager)
\\连接设备 - (void)connectPeripheral:(LGPeripheral *)peripheral completion:(CompletionBlock)block { self.lgPeripheral = peripheral; self.connectBlock = block; __weak CommunicationManager *weakSelf = self; [peripheral connectWithCompletion:^(NSError *error) { if (!error) { weakSelf.shouldRetryConnect = YES; [weakSelf setupServicesWithPeripheral:peripheral completion:block]; } else { block(NO); } }]; } \\连接设备成功后,遍历外设的服务,保存约定好的需要读写的特征值 - (void)setupServicesWithPeripheral:(LGPeripheral *)peripheral completion:(CompletionBlock)block { self.connectBlock = block; [self defaultCharacteristicSetting]; self.lgPeripheral = peripheral; __weak CommunicationManager *weakSelf = self; [peripheral discoverServicesWithCompletion:^(NSArray *services, NSError *error) { for (LGService *service in services) { NSLog(@"serve uuidString:%@", service.UUIDString); if ([service.UUIDString isEqualToString:kNewOperationService]) { [service discoverCharacteristicsWithCompletion:^(NSArray *characteristics, NSError *error) { for (LGCharacteristic *characteristic in characteristics) { NSLog(@"characteristic:%@", characteristic.UUIDString); if ([characteristic.UUIDString isEqualToString:kNewWriteCharacteristic]) { weakSelf.deviceNewWriteCharacterstic = characteristic; [weakSelf checkIfAllReady]; } else if ([characteristic.UUIDString isEqualToString:kNewNotifyCharacteristic]) { weakSelf.deviceNewNotifyCharacterstic = characteristic; [characteristic setNotifyValue:YES completion:nil onUpdate:^(NSData *data, NSError *error) { [weakSelf handleData:data]; [weakSelf checkIfAllReady]; }]; } else if ([characteristic.UUIDString isEqualToString:kNewReadCharacteristic]) { weakSelf.deviceNewReadCharacterstic = characteristic; [characteristic readValueWithBlock:^(NSData *data, NSError *error) { if (!error) { peripheral.macAddress = [self convertNewMacAddressWithData:data]; NSLog(@"mac data:%@", peripheral.macAddress); [weakSelf checkIfAllReady]; } }]; } } }]; } } }]; }
3.发送蓝牙指令(OperationType是业务的蓝牙指令枚举,例如查电量、关机、重启、设备版本信息、设备更名等指令)
- (void)performOperationType:(OperationType)operationType object:(id)object completionBlock:(OperationBlock)block { self.operationBlock = block; //根据不同的蓝牙指令处理蓝牙数据 NSData *data = [self dataWithOperationType:operationType object:object]; if (data == nil) { return; } //写入特征值 [self.writeCharacteristic writeValue:data completion:^(NSError *error) { NSLog(@"functionCode:%d",[self getFunctionCodeByOperationType:operationType]); if (!error) { NSLog(@"成功发送特征值数据"); } }]; //之后会根据监听约定好的特征值返回到蓝牙指令执行结果作进一步处理 }
结语
感谢阅读,希望对大家认识蓝牙开发的思路有所帮助,蓝牙里面开发还涉及到更加复杂的功能及优化,譬如设备搜索筛选、设备重连实现、设备固件升级优化等,由于时间关系,只作流程性的蓝牙开发的介绍。谢谢。