开头
- 这是分篇章,整篇请看零基础iOS开发学习日记
BabyBluetooth
蓝牙开发步骤
- 扫描外设
- 发现外设
- 连接外设
- 获取外设读写特征
- 获取外设发出的信息和向外设发信息
- 基于上面的步骤,通过block函数进行实现
- 有些名词可以看Bluetooth蓝牙
基本使用
- 这里的案例是我最近的蓝牙项目,通过
tableView
显示被扫描到的设备,中心设备连接一个蓝牙设备,通过写特征值进行发数据,通过监听特征值进行消息监听 - 创建baby对象
self.baby = [BabyBluetooth shareBabyBluetooth];
复制代码
- 开始扫描
self.baby.scanForPeripherals().begin();
复制代码
- 连接设备
[self.baby cancelScan];
//取消所有外设连接
[self.baby cancelAllPeripheralsConnection];
//建立连接且发现服务和特征值
//pp为目标外设
self.baby.having(pp).and.then.connectToPeripherals().discoverServices().discoverCharacteristics().readValueForCharacteristic().discoverDescriptorsForCharacteristic().readValueForDescriptors().begin();
复制代码
- 发送数据
//通过已连接的外设调用
[self.connectPeripheral writeValue:data forCharacteristic:self.writeCharacteristic type:CBCharacteristicWriteWithResponse];
复制代码
- 初始化baby对象,就是设置对应的block函数
[self babyDelegate];
复制代码
- babyDelegate中,配置block
//弱引用self,防止blcok中调用外部属性,导致循环引用
__weak typeof(self) weakSelf = self;
//确定中心设备状态是否可以扫描
[self.baby setBlockOnCentralManagerDidUpdateState:^(CBCentralManager *central) {
if (central.state == CBManagerStatePoweredOn) {
[SVProgressHUD showInfoWithStatus:@"设备打开成功,开始扫描设备"];
}
NSLog(@"%@", central);
}];
//扫描到外设的blcok,并且添加到一个数组中,方面以后续的处理
[self.baby setBlockOnDiscoverToPeripherals:^(CBCentralManager *central, CBPeripheral *peripheral, NSDictionary *advertisementData, NSNumber *RSSI) {
// NSLog(@"搜索到了设备:%@",peripheral.name);
if (![weakSelf.peripheralArray containsObject:peripheral]) {
[weakSelf.peripheralArray addObject:peripheral];
//通过代理,进行界面刷新
if ([weakSelf.delegate respondsToSelector:@selector(reloadData)]) {
[weakSelf.delegate reloadData];
}
}
NSLog(@"%@", weakSelf.peripheralArray);
}];
//连接成功
[self.baby setBlockOnConnected:^(CBCentralManager *central, CBPeripheral *peripheral) {
[SVProgressHUD showInfoWithStatus:@"连接成功"];
//保存连接上的外设
weakSelf.connectPeripheral = peripheral;
}];
//读取所有特征值
[self.baby setBlockOnReadValueForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
NSLog(@"characteristic name:%@ value is:%@",characteristics.UUID,characteristics.value);
}];
//获取读和监听的特征值,根据服务进行筛选
[self.baby setBlockOnDiscoverCharacteristics:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
NSLog(@"service name: %@", service);
NSLog(@"service uuidstring name: %@", service.UUID.UUIDString);
NSLog(@"%@", service.characteristics);
//确定服务
if([service.UUID.UUIDString isEqualToString:@"6E400001-B5A3-F393-E0A9-E50E24DCCA9E"]) {
for (CBCharacteristic * tempChara in service.characteristics) {
NSLog(@"%@", tempChara);
//确定监听特征值
if ([tempChara.UUID.UUIDString isEqualToString:@"6E400003-B5A3-F393-E0A9-E50E24DCCA9E"]) {
weakSelf.notifyCharacteristic = tempChara;
NSLog(@"self.notifyCharacteristic : %@", weakSelf.notifyCharacteristic);
//对监听特征值进行订阅,并将监听到的数据进行处理
[weakSelf.baby notify:peripheral characteristic:weakSelf.notifyCharacteristic block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
NSLog(@"notify %@", characteristics.value);
NSLog(@"notify Str %@", [[NSString alloc] initWithData:characteristics.value encoding:NSUTF8StringEncoding]);
//处理数据
[weakSelf handleData:characteristics.value];
}];
}
//保存写特征值
else if ([tempChara.UUID.UUIDString isEqualToString:@"6E400002-B5A3-F393-E0A9-E50E24DCCA9E"]) {
weakSelf.writeCharacteristic = tempChara;
NSLog(@"self.writeCharacteristic : %@", weakSelf.writeCharacteristic);
}
}
}
}];
//设置查找设备的过滤器
[self.baby setFilterOnDiscoverPeripherals:^BOOL(NSString *peripheralName, NSDictionary *advertisementData, NSNumber *RSSI) {
//最常用的场景是查找某一个前缀开头的设备
// if ([peripheralName hasPrefix:@"Pxxxx"] ) {
// return YES;
// }
// return NO;
//mac地址
// NSData *data = advertisementData[@""];
// NSLog(@"%@", advertisementData);
//设置查找规则是名称大于0 , the search rule is peripheral.name length > 0
if (peripheralName.length >0) {
return YES;
}
return NO;
}];
//写入成功
[self.baby setBlockOnDidWriteValueForCharacteristic:^(CBCharacteristic *characteristic, NSError *error) {
[SVProgressHUD showSuccessWithStatus:@"写入成功"];
[SVProgressHUD dismissWithDelay:1];
}];
//断开设备
[self.baby setBlockOnDisconnect:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
[SVProgressHUD showInfoWithStatus:@"断开链接"];
[SVProgressHUD dismissWithDelay:1];
//界面处理
if ([weakSelf.delegate respondsToSelector:@selector(disconnect)]) {
[weakSelf.delegate disconnect];
}
}];
//取消所有设备连接
[self.baby setBlockOnCancelAllPeripheralsConnectionBlock:^(CBCentralManager *centralManager) {
NSLog(@"setBlockOnCancelAllPeripheralsConnectionBlock");
}];
//取消扫描
[self.baby setBlockOnCancelScanBlock:^(CBCentralManager *centralManager) {
NSLog(@"setBlockOnCancelScanBlock");
}];
//设置babyOptions
//扫描选项->CBCentralManagerScanOptionAllowDuplicatesKey:忽略同一个Peripheral端的多个发现事件被聚合成一个发现事件
NSDictionary *scanForPeripheralsWithOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@YES};
/*连接选项->
CBConnectPeripheralOptionNotifyOnConnectionKey :当应用挂起时,如果有一个连接成功时,如果我们想要系统为指定的peripheral显示一个提示时,就使用这个key值。
CBConnectPeripheralOptionNotifyOnDisconnectionKey :当应用挂起时,如果连接断开时,如果我们想要系统为指定的peripheral显示一个断开连接的提示时,就使用这个key值。
CBConnectPeripheralOptionNotifyOnNotificationKey:
当应用挂起时,使用该key值表示只要接收到给定peripheral端的通知就显示一个提
*/
NSDictionary *connectOptions = @{CBConnectPeripheralOptionNotifyOnConnectionKey:@YES,
CBConnectPeripheralOptionNotifyOnDisconnectionKey:@YES,
CBConnectPeripheralOptionNotifyOnNotificationKey:@YES};
//连接设备->
[self.baby setBabyOptionsWithScanForPeripheralsWithOptions:scanForPeripheralsWithOptions
connectPeripheralWithOptions:connectOptions
scanForPeripheralsWithServices:nil
discoverWithServices:nil
discoverWithCharacteristics:nil];
复制代码
数据转换
- 对于蓝牙外设来说,一般的数据为16进制的,所以会涉及到数据格式的转换,而对于iOS来说,便于处理的数据格式肯定是数据,可以根据帧结构进行不同的处理
- 这个数组中的每个元素都以NSNumber的形式存储
- NSArray转成NSData
- (NSData *)convertArrayToDataWithArray:(NSArray *)array {
NSUInteger len = array.count;
UInt8 buffer[len];
for (int i = 0; i < len; i++)
{
buffer[i] = [[array objectAtIndex:i] unsignedCharValue];
}
NSData *data = [NSData dataWithBytes:buffer length:len];
return data;
}
复制代码
- NSData转NSArray
- (NSArray *)convertDataToArrayWithData:(NSData *)data{
//把读到的数据复制一份
NSData *recvBuffer = [NSData dataWithData:data];
NSUInteger recvLen = [recvBuffer length];
UInt8 *recv = (UInt8 *)[recvBuffer bytes];
if (recvLen > 1000) {
return nil;
}
//把接收到的数据存放在recvData数组中
NSMutableArray *recvData = [[NSMutableArray alloc] init];
NSUInteger j = 0;
while (j < recvLen) {
[recvData addObject:[NSNumber numberWithUnsignedChar:recv[j]]];
j++;
}
return recvData;
}
复制代码
- 往数组内添加数据的形式
[dataArr addObject:[NSNumber numberWithUnsignedInteger:0x00]];
复制代码
- 数组中的内容进行16进制的比较
[dataArr[0] unsignedIntValue] == 0x81
复制代码
总结
- 这里仅仅进行的单设备连接,据说可以进行多设备连接,找机会把坑补上
- 以上总结的仅仅是我在项目中的用到的状态,还可以监听挺多蓝牙状态的,挖个坑
- 具体使用上,是封装了一层Manager管理类。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END