我正在处理 bluetooth iOS
项目并设法从 bluetooth
获取一些数据设备。
但是,我正在努力将这些数据转换为有用的东西,例如 NSString
.每当我尝试 NSLog
NSString
从 NSData
转换而来收到了,是一堆gibberish
.输出是:
ēဥ၆䄀
蓝牙设备是亚洲制造商的心脏监测器,他们提供了有关如何调用该设备的协议(protocol)引用。他们在协议(protocol)引用中提到的这一件事:
The PC send 16-byte packets to the device, then the device sent back the 16-byte packets. Except for some special commands, all others can use this communication mode.
谁能告诉我我做错了什么?我已经尝试了我所知道的一切,包括苹果文档中的每一个编码以及
initWithData
和 initWithBytes
.谢谢!-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error {
if (error)
{
NSLog(@"erorr in read is %@", error.description);
return;
}
NSData *data= characteristic.value;
NSString *myString = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF16StringEncoding];
NSLog(@"Value from device is %@", myString); //OUTPUT IS ēဥ၆䄀
}
最佳答案
您在这里拥有的是无法直接转换为人类可读字符串的原始数据字符串 - 除非您认为十六进制表示是人类可读的:)
要理解这些数据,您需要手头有协议(protocol)规范或准备数小时(有时)数天的逆向工程。
这个字节序列可以由标准格式的多个值组成(浮点数 IEEE 754,uint8_t
,uint16_t
...)甚至专有格式。
与外界交流时要考虑的一件重要事情也是endianness (即:多字节格式中的“最大”字节是第一个还是最后一个)。
有很多方法可以处理这些数据。要获取原始字节数组,您可以执行以下操作:
NSData *rxData = ...
uint8_t *bytes = (uint8_t *)[rxData bytes];
然后,如果(例如)第一个字节告诉您字符串包含的有效负载类型,您可以像这样切换:
switch (bytes[0])
{
case 0x00:
//first byte 0x00: do the parsing
break;
case 0x01:
//first byte 0x01: do the parsing
break;
// ...
default:
break;
}
以下是解析数据的示例,其中包括:
字节 0:保存一些位编码标志的字节
字节 1,2,3,4:32 位浮点数
字节 5,6:uint16_t
bool bitFlag0;
bool bitFlag1;
bool bitFlag2;
bool bitFlag3;
uint8_t firstByte;
float theFloat;
uint16_t theInteger;
NSData *rxData = ...
uint8_t *bytes = (uint8_t *)[rxData bytes];
// getting the flags
firstByte = bytes[0];
bitFlag0 = firstByte & 0x01;
bitFlag1 = firstByte & 0x02;
bitFlag2 = firstByte & 0x04;
bitFlag3 = firstByte & 0x08;
//getting the float
[[rxData subdataWithRange:NSMakeRange(1, 4)] getBytes:&theFloat length:sizeof(float)];
NSLog (@"the float is &.2f",theFloat);
//getting the unsigned integer
[[data subdataWithRange:NSMakeRange(6, 2)] getBytes:&theInteger length:sizeof(uint16_t)];
NSLog (@"the integer is %u",theInteger);
注意:根据字节顺序,您可能需要在转换之前反转 4-float 或 2-uint16_t 字节。转换此字节数组也可以使用联合来完成。
union bytesToFloat
{
uint8_t b[4];
float f;
};
进而:
bytesToFloat conv;
//float would be written on bytes b1b2b3b4 in protocol
conv.b[0] = bytes[1]; //or bytes[4] .. endianness!
conv.b[1] = bytes[2]; //or bytes[3] .. endianness!
conv.b[2] = bytes[3]; //or bytes[2] .. endianness!
conv.b[3] = bytes[4]; //or bytes[1] .. endianness!
theFloat = conv.f,
例如,如果您知道 byte6 和 byte7 代表
uint16_t
值,您可以从原始字节计算它:value = uint16_t((bytes[6]<<8)+bytes[7]);
或(再次 - 字节序):
value = uint16_t((bytes[7]<<8)+bytes[6]);
另一个注意事项:简单地使用
sizeof(float)
有点冒险,因为 float 在一个平台上可以是 32 位,而在另一个平台上可以是 64 位。
关于ios - 将 NSData 转换为 NSString 返回随机字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20739167/