美文网首页iOS BLE2017iOS物联网
iOS 获取蓝牙外设的Mac地址的两种方法

iOS 获取蓝牙外设的Mac地址的两种方法

作者: 开小飞 | 来源:发表于2016-12-07 00:37 被阅读7954次

写在前面:

很久没有做记录,一方面是因为工作比较忙,另一方面也是因为最近在准备马拉松,所以平时空余的时间训练的比较多,个人觉得这一辈子起码要完成一次马拉松嘛~虽然只是个半程=、= 但是对于我等整天坐在公司、躺在家里的程序员们来说,挑战还是不小的,所以平时的训练也不敢懈怠。
在马拉松结束后,差不多也要到明年一月初了,计划的项目会稍微少一些,打算那个时候把这几个月关于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地址的方法,如果有什么更好的方法,也麻烦评论告诉我~大家一起学习!

以上!

相关文章

网友评论

  • 睿少:您好,请问应该怎么通过 mac 连接到蓝牙设备
  • 孙好运:BleDevice 这个是什么?没有demo吗
  • 阿福lfy:楼主您好,NSString *value = [NSString stringWithFormat:@"%@",characteristic.value];
    我们的蓝牙模块value值<00>,然后由于字符串不够长就闪退了,您遇到过这种情况吗?
    ForestL:@阿福lfy 嗯嗯,多谢!
    阿福lfy:@ForestL 你看看Mac地址隐藏在kCBAdvDataManufacturerData里面吗?没有的话,就获取不到了,就让硬件改改协议吧!
    ForestL:你好,我也遇到这种情况了,请问你解决了吗?
  • 爱超越的欢:这篇文章对我很有用,谢谢楼主分享
    开小飞:搬运工而已:beers:
  • 妈哟你再说一遍:[NSStringTool convertToNSStringWithNSData:data];这个方法内容是什么?
    开小飞:@妈哟你再说一遍 评论中找一下~
  • 9a6f4c00fe70:您好~
    請問didDiscoverCharacteristicsForService
    readValue要帶入的 Characteristic 是在哪呢?
    我在service沒有取到Characteristic
    9a6f4c00fe70:現在180A服務裡面只有看到2A24 2A25 2A26 2A28, T0T 都沒看到MAC位址
  • 62413c82a3ba:博主可以留个QQ吗
  • Little_Shaun:大神,我想问下,如果设备不对外发送广播,但是我知道设备的mac地址,怎么和他去连接呢?
    开小飞:@Little_Shaun 不可以的哦,这是安卓数实现连接的方法
  • 杏仁丶:想问下iOS可以获取到本机的蓝牙Mac地址吗
    开小飞:@杏仁丶 这个我没研究过,但是应该是不可以的。你看看一些私有方法可以不
    杏仁丶:@开小飞 对,就是自己的蓝牙Mac地址
    开小飞:@杏仁丶 你是说获取iPhone的蓝牙Mac地址么?
  • 周二可:楼主[NSStringTool convertToNSStringWithNSData] 这个是怎么转换的呢?
    静静的coding:携带mac地址的服务的UDID 180A 是固定死的吗
    7d7d20040712:@开小飞 楼主,我用你的第二种方法再降data转换为不带<>的字符串,报错-[__NSDictionaryM bytes]: unrecognized selector sent to instance 0x17516e30
    开小飞:将data转换为不带<>的字符串:
    + (NSString *)convertToNSStringWithNSData:(NSData *)data
    {
    NSMutableString *strTemp = [NSMutableString stringWithCapacity:[data length]*2];

    const unsigned char *szBuffer = [data bytes];

    for (NSInteger i=0; i < [data length]; ++i) {

    [strTemp appendFormat:@"%02lx",(unsigned long)szBuffer[i]];

    }

    return strTemp;
    }
  • ShineYangGod:我获取不到mac地址啊?怎么回事啊
    刻舟求鉴:@神地创造 我也用的那个现在获取到了嘛?
    ShineYangGod:@开小飞 我用的第三方的BabyBluetooth获取不到啊
    开小飞:@神地创造 你用的是哪种方法?

本文标题:iOS 获取蓝牙外设的Mac地址的两种方法

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