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

ⅰ亾dé卋堺 提交于 2019-12-11 07:16:56

问题


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!


回答1:


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);

But....

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?




回答2:


You appear to have an NSData object containing 6 bytes, the first byte is the least significant one (little-endian). Don't try to use the character representation, this is binary data, process it as such.

Use the bytes property of NSData to get a pointer to the first byte and save it to an Byte * variable, say, bPtr. Now just index the bytes in turn and insert them into a 64-bit unsigned integer variable in order. You can do this by bit shifting the integer and or'ing in the next byte - start at bPtr[5] down to bPtr[0] and shift the integer left 8 each time.

HTH



来源:https://stackoverflow.com/questions/46504035/little-endian-byte-order-ios-ble-scan-response

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!