AzraelPwnz AzraelPwnz - 3 years ago 190
iOS Question

Little-Endian Byte Order (iOS, BLE scan response)

In basic terms, I am using nativescript for a cross platform application. This application interacts with BLE devices. The BLE devices send a scan response after the advertisement packet, which I am able to retrieve as an NSData object on the iOS side.

Here is the (pseudo) output from the description property: <54fca267 0b00>.

The output represents the hardware address of the peripheral.

The hardware guys are telling me this is in little-endian, and I know it is a 48-bit string. It is coming from the peripheral, which has its firmware written in C.

I have been trying for a few days to convert this into a string (with the correct endianness) so that I can store the hardware address on our back-end, but am unable to come up with an elegant solution.

One solution I did come up with was reading the :description property of the NSData object, and then manually (in javascript) 'decoding' it. I just do not feel like this solution is proper enough for a production environment, and would like to use native utilities instead.

I have tried using :

NSString.alloc().initWithDataEncoding(mac, NSUTF8StringEncoding);

..with every encoding type from THIS page of the documentation. I am either getting nil in return, or incorrect characters.

Like I previously stated, this is being written in NativeScript; however, I have a decent understanding of objective C, so I should be able to convert any examples provided in that language.

Any input would be greatly appreciated. Thanks in advance!

Answer Source

CRD's answer is on the right track, but I'm guessing is not what you're asking for. You want a result that looks like "54:fc:a2:67:0b:00" (a Bluetooth/MAC address), right? Here's a simple, brute force approach (you could do this in a loop or the like, but not worth it IMO).

// Just for testing; you already have data.
uint8_t address[6] = { 0x54, 0xfc, 0xa2, 0x67, 0x0b, 0x00 };
NSData *data = [NSData dataWithBytes:address length:6];

// Check the length before proceeding (maybe return an error rather than crash :D)
assert([data length] == 6);

// Grab the bytes
const uint8_t *bytes = data.bytes;

// Format them
NSString *addressString = [NSString stringWithFormat:@"%02x:%02x:%02x:%02x:%02x:%02x",
                           bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]];

// 3. Profit
NSLog(@"%@", addressString);


I'm not quite certain what the engineer means here by "little-endian." 54:fc:a2 isn't an assigned manufacturer code. Typically, I would assume "little-endian" means that they've byte-swapped the 16-bit words (which I've run into on CSR platforms), and so this should be fc:54:67, but that isn't assigned either. Treating the whole thing as completely backwards gives us 00:0b:67 which is assigned to TopView, who makes Bluetooth cameras, so I'm betting that's what "little-endian" means here (which makes sense, because the normal way to write MAC addresses on the wire is exactly backwards of that, and is "big-endian").

So that would change the code to:

NSString *addressString = [NSString stringWithFormat:@"%02x:%02x:%02x:%02x:%02x:%02x",
                           bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0]];

Is the address 00:b0:67:a2:fc:54?

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download