12

I need to take target mac address from input connection and outgoing connection from CBPeripheral And CBCenter. identifier dose not define in them. look was remove from iOS 7. Is there any other way?

https://developer.apple.com/library/prerelease/ios/documentation/CoreBluetooth/Reference/CBPeripheral_Class/index.html

Omid Mafakher
  • 1,389
  • 1
  • 16
  • 40

2 Answers2

18

You can't get the MAC address for a CBPeripheral but you can get the identifier property, which is a UUID that iOS computes from the MAC amongst other information.

This value can be safely stored and used to identify the same peripheral in the future on this particular iOS device.

It cannot be used on another iOS device to identify the same peripheral.

Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • I didn't found any proves of your words about "iOS computes from the MAC", maybe you can share the link to prove it? I've checked and different iPhones show different UUIDs for the same BLE device. Maybe this can identify the device for current iOs device, but not in general. – Dmitry Soloviov Aug 10 '18 at 12:16
  • I should clarify my answer; the identifier can only be used on the same device. It cannot be used across devices – Paulw11 Aug 10 '18 at 12:54
  • But in android you can get MacAddress for my BLE device – Vivek Gajbe Aug 27 '20 at 10:50
  • 1
    Yes. But on iOS you can't. – Paulw11 Aug 27 '20 at 11:23
-3

You can access to the MAC ADDRESS without problem in iOS 12. To get the mac address you have to follow the next steps.

  1. Parse the Data received by the BLE device to String.
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. Add a separator ":" to the address.
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. In didReadValueForCharacteristic( characteristic: CBCharacteritic) you can use the previous 2 functions to get the mac address.
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. enjoy your mac address: "MAC_ADDRESS: 00:0A:57:4E:86:F2"
jlandyr
  • 99
  • 1
  • 6
  • Thanks a lot for the excellent workaround Can you please explain what exactly is this BleDeviceProfile.MAC_ADDRESS – Taimur Ajmal Sep 30 '19 at 10:43
  • In my example, the MAC ADDRESS of the BLE Device came inside a characteristic – jlandyr Sep 30 '19 at 14:04
  • 7
    In this example, it seems like you had exposed intentionally the MAC as a characteristic. Is it that all BLE Devices exposed their mac as a Characteristic? – Bangonkali Oct 28 '19 at 11:20
  • It does appear this is what he is doing and no, peripherals don't implement this characteristic. It is a custom characteristic and as far as I can tell is the only way to get the peripheral MAC address on iOS (Android makes it available via getAddress() method on the BLE device). This appears to be one more thing that is not exposed in the CoreBluetooth API. I had to implement a similar solution in order to obtain the MTU size. Again a simple thing to receive on Android but impossible in iOS forcing a workaround. – Lehrian Apr 10 '22 at 20:33
  • @Lehrian Does it still work today? – Keselme Aug 09 '23 at 12:48
  • I'm not sure what you are asking. Does creating a custom characteristic on the peripheral to use to expose the MAC address of the peripheral to the central still work? Sure, you can create any custom characteristic and put anything in it you want. But on iOS it is useless anyway except for your own identification purposes because iOS doesn't provide an interface to connect to a MAC address or even to their UUID identifier as far as I can tell. A scan is always required. – Lehrian Aug 24 '23 at 23:04
  • And if you want to use the MAC address to find the same device a second time you would need to put the MAC address into the advertising data of your peripheral in order to compare with the MAC you retrieved from your custom characteristic the previous time you connected in the method: `- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)rssi{ }` – Lehrian Aug 24 '23 at 23:04