承接上文:iOS关于蓝牙框架BLE的开发--基础用法(上)
上文提及到对特征码CBCharacteristic
进行操作,现在聊聊对应不同的操作的后续吧...
操作特征码后的回调——订阅/读取回调与失败回调
1.订阅/读取成功
按正常流程,通过特征码的订阅或读取,成功之后,都会通过这个方法获取对应的数据:
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
其中characteristic.value
就是订阅/读取特征码对应的数据,我们可以通过代理或者block把这个value传到需要用到的地方,全部代码如下:
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
if (error) {
NSLog(@"error:%s,%@",PRETTY_FUNCTION,error);
return;
}
else {
NSLog(@"peripheral value == %@",characteristic.value);
if (_delegate && [_delegate respondsToSelector:@selector(receiveData:data:)]) {
[_delegate receiveData:peripheral data:characteristic.value];
}
}
}
而大家看到,如果订阅/读取失败的话,就有error,所以我在这个方法判断一下error是否存在,如果存在就做相应的事情并且返回;
2.向设备写入数据或发送指令回调
当需求需要中心设备向外设写入数据或发送指令,如果使用的方法是CBCharacteristicWriteWithResponse
的话,就会进入-(void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
这个代理方法里面去:
-(void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
if (error) {
NSLog(@"写入命令失败=====%@",error.userInfo);
}
else{
NSLog(@"写入命令成功");
}
}
再略略展开一下讲讲,一般有几种情况会用到写入方法,已经遇到过的情况先列举一下,日后可能还会增加
- 有些外设,在获取数据前会让中心设备先在规定时间内发送认证指令,增加安全性.这样的话,我们订阅或读取特征码的方法,就要放到这个方法里面来了;
- 有些外设,有一些例如同步时间啊,打开/关闭某个功能开关,修改设备名或者修改某个功能.这个时候,我们就要对不同的需求在这个地方做不同的操作,一般情况下,就写个代理或者block在其他地方实现.
3.读取外设信号
这点算是补充说明吧,在旧的iOS版本下,设备peripheral有个属性叫做RSSI,可以拿到外设的信号,而新的(忘记了在哪个)版本下,这个属性被废弃了,想要获取,就要通过[peripheral ReadRSSI]
的方法来获取,执行这个方法后,将进入-(void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error
这个代理方法,流程就和订阅和写入回调一样,就不详细讲了,不过这个方法,好像不用连接外设,只要搜索到了就可以用了
-(void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error{
if (_delegate && [_delegate respondsToSelector:@selector(SG_readPeripheralRSSI:peripheral: error:)]) {
[_delegate SG_readPeripheralRSSI:RSSI peripheral:peripheral error:error];
}
}
一些补充
苹果的框架下,没有提供方法让我们拿到外设的MAC地址的.但是,我们通过和硬件工程师的协商,把MAC地址暴露出来,就可以获取得到,而方法却比较苛刻.
在iOS关于蓝牙框架BLE的开发--基础用法(上)搜索外设的步骤中,代理方法-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI
有个很奇怪的东西混了进来,名字叫advertisementData
,仔细一看,是个字典,而苹果是允许外设在成功连接前把要广播的数据存在这里,而通过指定keykCBAdvDataManufacturerData
,在没连接成功的情况下获取里面包的内容,于是,我们就可以把MAC地址放进去,让我们中心设备拿到MAC地址了,我遇到的情况,就是要通过这个MAC地址和一些指定协议,来生成认证指令,发送到外设去;一般情况下,如果不过滤的话,搜索后蓝牙列表会有很多奇奇怪怪的设备,于是,我们会通过
advertisementData
这个广播包或者设备名字来进行过滤,把一些APP不需要展示的外设过滤掉,或者根据不同的名字和型号,兼容不同的设备并对其做不一样的操作.-
在我的具体项目,认证指令需要通过异或计算,把十六进制数据异或之后生成一个校验,什么是异或计算,怎么异或计算,本人也是直接谷歌的,就直接上代码吧:
.h文件:
#import <Foundation/Foundation.h>@interface ExclusiveOr : NSObject /** 添加数组 */ +(NSString *)exclusiveOrArray:(NSArray *)array; /** 两个数进行异或 */ +(NSString *)pinxCreator:(NSString *)pan withPinv:(NSString *)pinv; @end
.m文件:
#import "ExclusiveOr.h"
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
@implementation ExclusiveOr
+(NSString *)exclusiveOrArray:(NSArray *)exclusive{
if (exclusive.count !=0) {
NSString *exclusiveString = exclusive.lastObject;
for (int i =0; i<exclusive.count - 1; i++) {
if (i==0) {
NSString *pan = [exclusive[i] uppercaseString];
NSString *pinv = [exclusive[i+1] uppercaseString];
exclusiveString = [ExclusiveOr pinxCreator:pan withPinv:pinv];
}
else{
NSString *pinv = [exclusive[i+1] uppercaseString];
exclusiveString = [ExclusiveOr pinxCreator:exclusiveString withPinv:pinv];
}
}
return exclusiveString;
}
else{
return @"";
}
}
+ (NSString *)pinxCreator:(NSString *)pan withPinv:(NSString *)pinv {
if (pan.length != pinv.length) {
return nil;
}
const char *panchar = [pan UTF8String];
const char *pinvchar = [pinv UTF8String];
NSString *temp = [[NSString alloc] init];
for (int i = 0; i < pan.length; i++) {
int panValue = [ExclusiveOr charToint:panchar[i]];
int pinvValue = [ExclusiveOr charToint:pinvchar[i]];
temp = [temp stringByAppendingString:[NSString stringWithFormat:@"%X",panValue^pinvValue]];
}
return temp;
}
+ (int)charToint:(char)tempChar {
if (tempChar >= '0' && tempChar <='9') {
return tempChar - '0';
}
else if (tempChar >= 'A' && tempChar <= 'F') {
return tempChar - 'A' + 10;
}
return 0;
}
@end
到这里,我们对BLE开发基本就讲完了,或许后面,我会把一些简单的操作,如自动重连,刷新蓝牙列表,绑定设备之类的功能简单实现,骚骚期待一下吧...
Demo在想要不要发出来好...没人看就算了