美文网首页
iOS关于蓝牙框架BLE的开发--基础用法(下)

iOS关于蓝牙框架BLE的开发--基础用法(下)

作者: 左眼见到肠 | 来源:发表于2017-03-29 11:25 被阅读290次

    承接上文: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在想要不要发出来好...没人看就算了

    相关文章

      网友评论

          本文标题:iOS关于蓝牙框架BLE的开发--基础用法(下)

          本文链接:https://www.haomeiwen.com/subject/vwheottx.html