iOS ble4.0获取外设MAC地址

因为公司提出新的需求,需要在不做连接的时候获取外设的MAC地址。后来跟公司的硬件工程师讨论后,得出下面一个方法可以在不连接的时候就可以获取外设的MAC地址了。其实方法有多种。下面这篇文章有提到两种方法:(http://www.jianshu.com/p/1d6a8fc8134f) ,那么不多废话,介绍我现在使用的一种方法。
我们都知道在这个方法中可以得到扫描周围外设的相关信息(不清楚的请点击):
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI

那么在advertisementData中有个字段kCBAdvDataLocalName",这个字段可以放你外设的名字。那么我们当时就尝试在这个字段中把MAC地址也写进来,然后iOS这边在做一点相关的字符串的筛选就行了。
直接在didDiscoverPeripheral:中添加此方法:
// 筛选设备
[self sendPeripheralArrName:advertisementData[@“kCBAdvDataLocalName”]];

具体实现sendPeripheralArrName:方法:
-(void)sendPeripheralArrName:(NSString *)peripheralName{

NSString *newStr = [peripheralName substringWithRange:NSMakeRange(0, 4)];
// 用来判断的条件,这个具体得看你们硬件的名字
if ([newStr isEqualToString:@"C100"] || [newStr isEqualToString:@"C200"] || [newStr isEqualToString:@"C300"] || [newStr isEqualToString:@"D100"]) {
    if (![self.deviceArr containsObject:peripheralName]) {
        [self.deviceArr addObject:peripheralName];
    }
    for (NSString *nameStr in self.deviceArr) {
        if (nameStr.length >= 20) {
  //            截取C1000263 即前8位,这个前8位就是我们公司产品的名字。
            NSString *devieceStr = [nameStr substringWithRange:NSMakeRange(0, 8)];
          //  截取后面拼接的MAC地址
            NSString *mac1 = [nameStr substringWithRange:NSMakeRange(18, 2)];
            NSString *mac2 = [nameStr substringWithRange:NSMakeRange(16, 2)];
            NSString *mac3 = [nameStr substringWithRange:NSMakeRange(14, 2)];
            NSString *mac4 = [nameStr substringWithRange:NSMakeRange(12, 2)];
            NSString *mac5 = [nameStr substringWithRange:NSMakeRange(10, 2)];
            NSString *mac6 = [nameStr substringWithRange:NSMakeRange(8, 2)];
            //得到的MAC地址。
            NSString *macStr = [NSString stringWithFormat:@"%@:%@:%@:%@:%@:%@",mac1,mac2,mac3,mac4,mac5,mac6];
            
            [self.peripheralName addObject:devieceStr];
            [self.peripheralMac addObject:macStr];
            
        }
    
    }
}
[self.deviceTableView reloadData];
NSLog(@"外设名字数组%@",self.deviceArr);

}

作者:YW_Drenched
链接:https://www.jianshu.com/p/d0132c88b567
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

写在前面:
很久没有做记录,一方面是因为工作比较忙,另一方面也是因为最近在准备马拉松,所以平时空余的时间训练的比较多,个人觉得这一辈子起码要完成一次马拉松嘛~虽然只是个半程=、= 但是对于我等整天坐在公司、躺在家里的程序员们来说,挑战还是不小的,所以平时的训练也不敢懈怠。
在马拉松结束后,差不多也要到明年一月初了,计划的项目会稍微少一些,打算那个时候把这几个月关于BLE的学习与遇到的问题做个汇总。在此立个flag!
为何要获取蓝牙外设的Mac地址?
蓝牙外设的Mac地址,简而言之就是这个物理地址,每个设备都是唯一的,可以理解为省份证号。
一般在做BLE的开发中,会遇到通过app去绑定一个蓝牙外设的需求,由于在app关闭后,BLE就会断开连接,所以第二次打开app的时候,就需要通过绑定时保存在本地或者数据库中的这个外设的信息,来进行定向扫描以及绑定。所以这里就涉及到了这个外设信息的唯一性的问题,如果不能保证保存的这个外设信息的唯一性的话,可能我第二次打开app就连接不到之前的设备,或者连接到别的设备。
然而万恶的苹果在原生的CoreBluetooth中,将设备的Mac进行了封装(通过外设的Mac地址和手机的Mac地址进行了加密计算),最后对外提供了一个UUID,在一台手机上,一般情况,UUID就可以作为这个外设的唯一标识了,但是如果换了一台手机的话,可能就会发生变化,所以如果需求是需要在多台手机上的话,UUID可能就不太实用了。
特别是需要兼容安卓的情况下,安卓是可以获取到Mac地址的,所以我们就只能想办法获取外设的Mac地址了。
这里提供两种方法来获取Mac地址,获取的时机也不一样:
1.在连接后获取
这里参考了这个博客,博主自己对原生的CoreBluetooth做了分装,并且用自己的封装类去实现的,这里我们转换为原生下的Mac获取
//连接成功

  • (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
    {
    peripheral.delegate = self;
    //查找mac地址
    [peripheral discoverServices:@[[CBUUID UUIDWithString:@“180A”]]];
    }

#pragma mark - CBPeripheralDelegate
//发现到服务

  • (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    CBService *service = peripheral.services.firstObject;
    [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@“2A23”]] forService:service];
    }

//获得某服务的特征

  • (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    [peripheral readValueForCharacteristic:characteristic];
    }

  • (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
    {
    NSString *value = [NSString stringWithFormat:@"%@",characteristic.value];
    NSMutableString *macString = [[NSMutableString alloc] init];
    [macString appendString:[[value substringWithRange:NSMakeRange(16, 2)] uppercaseString]];
    [macString appendString:@":"];
    [macString appendString:[[value substringWithRange:NSMakeRange(14, 2)] uppercaseString]];
    [macString appendString:@":"];
    [macString appendString:[[value substringWithRange:NSMakeRange(12, 2)] uppercaseString]];
    [macString appendString:@":"];
    [macString appendString:[[value substringWithRange:NSMakeRange(5, 2)] uppercaseString]];
    [macString appendString:@":"];
    [macString appendString:[[value substringWithRange:NSMakeRange(3, 2)] uppercaseString]];
    [macString appendString:@":"];
    [macString appendString:[[value substringWithRange:NSMakeRange(1, 2)] uppercaseString]];
    DLog(@“mac == %@”,macString);
    }

用自家的几台设备做了测试,都可以获取到Mac地址,建议在使用前先demo测试下。
这种情况实在连接上了设备之后,通过读取他的180A服务里的2A23特征值,再去进行剪切和拼接的方法来获取Mac地址。那么问题来了,有些时候我的周边有很多蓝牙设备,我不可能一台一台去连接然后获取Mac地址,再判断是不是我保存的设备!这样太耗时了,而且可能会导致一些莫民奇妙的bug,所以我们的需求就变成了如何仅仅在扫描的过程中就获取到每台外设的Mac地址呢?扫描的过程是很快的,可以在短短几秒钟内就可以找到周围的上百台设备。
这个时候我们就只有使用第二种方法了,但是这种方法需要你么硬件工程师的支持了。
2.在扫描的过程中就获取设备的Mac地址
在发现设备的回调里面:

  • (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI

可以看到有一个 advertisementData ,这个字典类型的就是广播包,这里面会有一些设备的属性,比如设备的名字啊,服务啊等,但是都是被苹果限制了的,所以并不是你硬件工程师想广播什么都可以的。
这个字典里有一个:

key:kCBAdvDataManufacturerData

只有这个key是可以放入信息的,所以叫硬件工程师将Mac地址写到这个字段里去,这样你就可以在发现设备的过程中得到Mac地址了~!
//查找到正在广播的指定外设

  • (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData: (NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
    {
    if (peripheral.name != nil ) {
    if (![self.deviceArr containsObject:peripheral]) {
    [self.deviceArr addObject:peripheral];

          BleDevice *device = [[manridyBleDevice alloc] initWith:peripheral andAdvertisementData:advertisementData andRSSI:RSSI];
      }
    

    }
    }

//BleDevice.m

  • (instancetype)initWith:(CBPeripheral *)cbPeripheral andAdvertisementData:(NSDictionary *)advertisementData andRSSI:(NSNumber *)RSSI
    {
    BleDevice *per = [[BleDevice alloc] init];

    per.peripheral = cbPeripheral;
    per.deviceName = cbPeripheral.name;
    per.uuidString = cbPeripheral.identifier.UUIDString;
    NSData *data = [advertisementData objectForKey:@“kCBAdvDataManufacturerData”];
    NSString *mac = [NSStringTool convertToNSStringWithNSData:data];
    mac = [mac stringByReplacingOccurrencesOfString:@" " withString:@""];
    per.macAddress = mac;
    per.RSSI = RSSI;

    return per;
    }

这就是我目前发现的两种获得蓝牙外设Mac地址的方法,如果有什么更好的方法,也麻烦评论告诉我~大家一起学习!

作者:开小飞
链接:https://www.jianshu.com/p/1d6a8fc8134f
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

发布了138 篇原创文章 · 获赞 83 · 访问量 88万+

猜你喜欢

转载自blog.csdn.net/kunga0814/article/details/90217264