2013-12-23 39 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

謝謝!希望它會有用:) –