2013-12-23 42 views
1

我正在研究bluetooth iOS项目,并设法从bluetooth设备获取一些数据。 但是,我正在努力将这些数据转换为一些有用的数据,例如NSString。每当我尝试NSLogNSStringNSData转换而来,它是一堆gibberish。输出是:将NSData转换为NSString返回随机字符

ēဥ၆䄀 

蓝牙设备是在亚洲制造商心脏监护,他们提供了关于如何使该设备的调用协议引用。他们在协议中提到的一件事:

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. 

谁能告诉我我做错了什么?我尝试了我所知道的一切,包括苹果文档中的每一种编码以及initWithDatainitWithBytes。谢谢!

-(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 ēဥ၆䄀 

} 
+1

“16位数据包”应该代表人类可读的文本吗? – Joni

+0

@Joni我相信这是。我正在尝试读取心率监视器上的值。还有其他建议吗?谢谢 – Teddy13

+0

Joni提到:你不会说这些16字节数据包的规格是什么。大多数BT协议不通过无线电发送HR数据,因为这会浪费大量时间。这16个字节可能是4个32位双变量(IEEE 754)等等。您可能可以通过串行控制台(TeraTerm,CoolTerm)链接到此BT设备,并试用此功能。 –

回答

3

你这里是什么原始数据的不能直接转换成一个人类可读的字符串 - 除非你认为十六进制表示是人类可读:)

要使您需要掌握协议规范或准备反向工程几个小时(有时)的数据。

该字节序列可以由标准格式化的多个值组成(float IEEE 754uint8_tuint16_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浮点数或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, 

例如,如果你知道字节6和字节7表示uint16_t值可以从原始字节计算的话:

value = uint16_t((bytes[6]<<8)+bytes[7]); 

或者( - 字节序):

value = uint16_t((bytes[7]<<8)+bytes[6]); 

还有一点需要注意:使用简单sizeof(float)有点危险,因为float在一个平台上可以是32位,在另一个平台上可以是64位。

+1

真棒回答:) – Teddy13

+0

谢谢!希望它会有用:) –