中心设备连接外设流程
1. 初始化中心设备管理器
2. 检测蓝牙开启的状态
3. 蓝牙可用情况下扫描外设
4. 接收到外设广播
5. 连接外设
6. 扫描外设中的服务和特征
7.与外设数据交互
8. 订阅Characteristic的通知
9.断开连接
1. 建立中心设备管理器
#import <CoreBluetooth/CoreBluetooth.h>
#define CHARACTERISTIC_UUID @"1801"
#define SERVICE_BIKE_UUID @"FFA0"
@interface ViewController ()<CBCentralManagerDelegate,CBPeripheralDelegate>
@property (nonatomic, strong) CBCentralManager *centerMgr;
@property (nonatomic, strong) NSMutableArray *peripherals;
@property (nonatomic, strong) CBPeripheral *peripheral;
@property (nonatomic, strong) CBCharacteristic *characteristic;
@property (nonatomic, weak) IBOutlet UITextField *dataTextField;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.peripherals = [[NSMutableArray alloc] init];
self.centerMgr = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
}
2. 检测蓝牙状态
扫描时services参数为nil时扫描出所有的外设 2.根据指定的服务UUID扫描出对设 (遇到情况制定了UUID之后扫描不到外设了,不知道为什么!!)
#pragma mark - CBCentralManagerDelegate -
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
/*
CBManagerStateUnknown = 0, // 未知
CBManagerStateResetting, // 重置中
CBManagerStateUnsupported, // 不支持
CBManagerStateUnauthorized, // 未验证
CBManagerStatePoweredOff, // 关闭
CBManagerStatePoweredOn, // 开启
*/
if(central.state == CBManagerStatePoweredOn) {
//扫描外设
// [central scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:SERVICE_BIKE_UUID]] options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
[central scanForPeripheralsWithServices:nil
options:nil];
}
}
3. 发现外设之后,连接外设,并根据服务的UUID找到特征值
每个外设都有一个UUID,为identifier.UUIDString,这个UUID根据手机的不同而不同,但每一台手机的identifier.UUIDString都是一样
// 当发现外设后回调
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI {
//连接外设
//过滤出自己需要的外设,可根据设备的名称,设备的ServiceUUID 或者mac地址
if ([peripheral.name isEqualToString:@"名称"]) {
self.peripheral = peripheral; //过滤出来的外设需要保存下来,持有它,可用来读写数据
[self.centerMgr connectPeripheral:peripheral options:nil];
}
[self.peripherals addObject:peripheral];
NSLog(@"peripheral:%@%@",peripheral.name,peripheral.identifier.UUIDString);
}
4.连接外设之后对应的回调
// 当外设被连接以后回调
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
peripheral.delegate = self;
//扫描外设中的服务
[peripheral discoverServices:@[[CBUUID UUIDWithString:SERVICE_BIKE_UUID]]];
}
//断开连接的情况下发起重连
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error {
[central connectPeripheral:peripheral options:nil];
}
5. 连接外设,读取外设值 CBPeripheralDelegate
// 当外设的服务被发现后回调
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error {
//扫描服务中的指定特征
for (CBService *service in peripheral.services) {
[peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:CHARACTERISTIC_UUID]] forService:service];
}
}
// 当我们发现特征后回调
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error {
//便利特征进行交互
for (CBCharacteristic *c in service.characteristics) {
if ([c.UUID isEqual:[CBUUID UUIDWithString:@"1801"]]) {
self.characteristic = c;
[self.peripheral readValueForCharacteristic:c];
//设为YES之后 外设特征值有变化就会执行 didUpdateValueForCharacteristic回调方法
[self.peripheral setNotifyValue:YES forCharacteristic:c];
}
}
}
// 具体某个特征值发生改变后回调
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error {
NSLog(@"didUpdateValueForCharacteristic:%@",characteristic.value);
// NSString *ssss = [[NSString alloc] initWithData:[characteristic value] encoding:NSUTF8StringEncoding];
//
Byte * resultByte = (Byte *)[characteristic.value bytes];
for(int i=0;i < [characteristic.value length];i++) {
printf("testByteFF02[%d] = %d\n",i,resultByte[i]);
self.dataTextField.text = [NSString stringWithFormat:@"%d",resultByte[i]];
}
}
// 当某个特征值被写入时回调
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error {
NSLog(@"didWriteValueForCharacteristic:%@",characteristic.value);
[self.peripheral readValueForCharacteristic:characteristic];
}
与硬件交互都是以Byte[]数组来交互
6.中心设备向外设发送指令
- (IBAction)writeData:(id)sender {
// 写入数据 发送一个0702(清除数据的指令)
Byte byte[] = {7,2};
// 需要有响应 CBCharacteristicWriteWithResponse 会执行didWriteValueForCharacteristic回调
[self.peripheral writeValue:[NSData dataWithBytes:byte length:2]
forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
}
7.订阅characteristic
-(void)notifyCharacteristic:(CBPeripheral *)peripheral
characteristic:(CBCharacteristic *)characteristic{
//设置通知,数据通知会进入:didUpdateValueForCharacteristic方法
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//取消通知
-(void)cancelNotifyCharacteristic:(CBPeripheral *)peripheral
characteristic:(CBCharacteristic *)characteristic{
[peripheral setNotifyValue:NO forCharacteristic:characteristic];
}