53

I am currently working on an iOS application based on bluetooth low energy devices. In order to get a unique identifier to compare the peripherals got, I have to get the MAC address of the peripherals.

It is observed that the UUID property of a peripheral device varies across iOS devices and also for the peripheral device to get a UUID, it will have to get connected to a master device at least once. Since I have to deal with check-in's I don't want to establish a connection. As I went through the bluetooth services portal, I found that the device information itself is a service, which couldn't be retrieved unless a connection has been established between the master iOS device and the peripheral bluetooth low energy device.

I found that in Android we get the entire information of the device, including its MAC address (using getAddress()) when we get the response from the device on scanning itself.

I didn't find any properties in CBPeripheral class related to the device address. Another way to get a unique parameter would be to customize the advertisement data to send additional information regarding the device, which requires more work on firmware side.

So is there any way in iOS that I could get the MAC address of the bluetooth low energy peripheral without establishing a connection?

Any help would be greatly appreciated.

4

5 回答 5

30

CBPeripheral 的 identifier 属性将服务于您的目的,可从 CBCentralManager 的 didDiscoverPeripheral 委托方法中仍未连接的设备获得:

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

CBPeripheral *peripheral ...

NSUUID* serverId = [peripheral identifier];

我有六台我正在试验的 LE 设备,包括多组相同的设备。我刚刚确认,在两个 iOS 设备上,所有这些 LE 小部件的标识符都是不同的,但对于每个 iOS 设备,每个小部件的标识符在应用程序启动甚至应用程序删除和重新安装时都会保留。我会说这明确地证明了操作系统在内部存储了足够的信息,对于给定的 iThing,您将能够区分并重新识别您的应用程序遇到的所有外围设备,而无需实际连接到它们。另请注意,advertisementData在连接之前也可用,其中充满了有用的信息,例如 CBAdvertisementDataLocalNameKeyCBAdvertisementDataManufacturerDataKeyCBAdvertisementDataServiceUUIDsKeyCBAdvertisementDataSolicitedServiceUUIDsKey和其他信息,尽管没有像 [peripheral identifier] 那样确定唯一标识设备的信息。

我没有尝试进行设备备份和恢复来证明 UUID 被保留,但我敢打赌它们是,如果不是,Apple 会认为这是一个错误。

于 2013-11-20T05:06:53.113 回答
15

更新答案:-

iOS 12之后我们可以获取UDID

   print(UIDevice.current.identifierForVendor)

   print(UIDevice.current.identifierForVendor?.uuidString)

iOS 12 之前**

没有公共 API 可以获取此信息。

如果这是一个内部或越狱应用程序,您可以通过liblockdown.dylib获取 kLockdownBluetoothAddressKey 密钥的值

于 2013-09-24T04:56:03.927 回答
12

低能耗外围设备可能会使用隐藏 MAC 地址的隐私功能,因此在连接或绑定之前甚至不一定可以获得地址。如果您以某种方式获得了无线传输的 MAC 地址,则您需要处理隐私或存在互操作性问题。

Apple 使用 UUID 将这些隐私功能抽象出来,因此用户无需担心这些。

像您写的那样做的正确方法是将一些供应商特定的数据添加到广告数据包或使用设备信息服务。

于 2013-09-24T08:23:51.473 回答
11

代表其他专业人士的讨论,我发现了一些事实,这些事实表明 -

“<em>iOS 隐藏了设备的 MAC 地址并生成了一个 UUID。iOS 上的 UUID 由 iOS 设备生成。不同的 iOS 设备会为同一个外围设备获得不同的 UUID。MAC 地址通常基于硬件。如果我们都有 iPhone 并扫描相同的外围设备,我们将看到不同的 UUID。iOS 在设备上生成 UUID 并隐藏 MAC 地址。摘要 - iOS 不会让你获取设备的 MAC 地址,而是给你一个随机的 UUID。” </p>

来源 - https://github.com/don/cordova-plugin-ble-central/issues/77

根据上述研究,我发现到目前为止还没有一种独特的方式来连接到开发板,每个开发板都有一个 MAC 地址,在(仅)Android 中不会更改且易于访问,而 iOS 不会t 允许访问外围设备的 MAC 地址,但是 iOS 使用此 MAC 地址来创建外围设备标识符 (UUID),该标识符仅在(唯一)设备上是唯一的。单个板的外围标识符对于不同的 iPhone 设备是不同的(但在单个设备上是唯一的)。

但是,我们可以通过使用 Peripheral 的蓝牙服务 UUID 搜索来连接到板,但该服务 UUID 对于所有板都相同,例如“Adafruit Feather M0”。这意味着应用程序将查看相同类型的 BLE 板(“Adafruit Feather M0”),并将连接到其中的任何一个。到目前为止,由于 MAC 的不可访问性和在 iOS 中提供随机 UUID,为了将特定用户连接到特定板似乎是不可能的。

于 2017-12-27T09:27:05.480 回答
0

您可以在 iOS 12 中毫无问题地访问 MAC 地址。要获取 mac 地址,您必须按照以下步骤操作。

  1. 将 BLE 设备接收到的数据解析为字符串。
extension Data{
func hexEncodedString() -> String {
        let hexDigits = Array("0123456789abcdef".utf16)
        var hexChars = [UTF16.CodeUnit]()
        hexChars.reserveCapacity(count * 2)

        for byte in self {
            let (index1, index2) = Int(byte).quotientAndRemainder(dividingBy: 16)
            hexChars.insert(hexDigits[index2], at: 0)
            hexChars.insert(hexDigits[index1], at: 0)
        }
        return String(utf16CodeUnits: hexChars, count: hexChars.count)
    }
}

  1. 在地址中添加分隔符“:”。
extension String {
    func separate(every stride: Int = 4, with separator: Character = " ") -> String {
        return String(enumerated().map { $0 > 0 && $0 % stride == 0 ? [separator, $1] : [$1]}.joined())
    }
}
  1. 在didReadValueForCharacteristic(characteristic: CBCharacteritic)中可以使用前面2个函数来获取mac地址。
func didReadValueForCharacteristic(_ characteristic: CBCharacteristic) {
if characteristic.uuid == BleDeviceProfile.MAC_ADDRESS, let mac_address = characteristic.value?.hexEncodedString().uppercased(){
            let macAddress = mac_address.separate(every: 2, with: ":")
            print("MAC_ADDRESS: \(macAddress)")
        }
}
  1. 享受你的mac地址:“MAC_ADDRESS: 00:0A:57:4E:86:F2”
于 2019-08-29T11:11:50.100 回答