【发布时间】:2016-04-15 19:13:14
【问题描述】:
我正在尝试连接到蓝牙 LE / 蓝牙智能 / BLE 健康设备的健康温度计服务 (0x1809),正式描述如下:https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.health_thermometer.xml。具体来说,我正在请求来自健康温度计特征 (0x2A1C) 的通知,并在此处提供说明:https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml。
我有不错的 Swift 2 背景,但我从未与 NSData、字节或按位运算符密切合作,而且我对 Little Endian 与 Big Endian 完全陌生,所以这对我和我来说都是新的可以使用一些帮助。该特性有一些内置的逻辑,可以确定您将收到哪些数据。到目前为止,我 100% 的时间都按照标志、温度测量值和时间戳的顺序收到了数据,但不幸的是,我总是会得到“010”的控制逻辑,这意味着我错误地读取了标志。事实上,我认为我错误地引入了时间戳之外的所有内容。我在代码 cmets 中包含了我看到的数据。
我尝试了多种获取此二进制数据的方法。标志是带有位运算符的单字节。温度测量本身是一个浮点数,我花了一些时间才意识到它不是一个 Swift 浮点数,而是一个 ISO/IEEE 标准“IEEE-11073 32 位浮点数”,BLE 规范说“没有指数值” “这里:https://www.bluetooth.com/specifications/assigned-numbers/format-types。我什至不知道那是什么意思。这是我的 didUpdateValueForCharacteristic() 函数的代码,您可以在其中查看我在尝试新尝试时注释掉的多次尝试:
// Parse Characteristic Response
let stream = NSInputStream( data: characteristic.value! )
stream.open() // IMPORTANT
// Retrieve Flags
var readBuffer = Array<UInt8>( count: 1, repeatedValue: 0 )
stream.read( &readBuffer, maxLength: readBuffer.count )
var flags = String( readBuffer[ 0 ], radix: 2 )
flags = String( count: 8 - flags.characters.count, repeatedValue: Character( "0" ) ) + flags
flags = String( flags.characters.reverse() )
print( "FLAGS: \( flags )" )
// Example data:
// ["01000000"]
//
// This appears to be wrong. I should be getting "10000000" according to spec
// Bluetooth FLOAT-TYPE is defined in ISO/IEEE Std. 11073
// FLOATs are 32 bit
// Format [8bit exponent][24bit mantissa]
/* Attempt 1 - Read in a Float - Doesn't work since it's an IEEE Float
readBuffer = Array<UInt8>( count: 4, repeatedValue: 0 )
stream.read( &readBuffer, maxLength: readBuffer.count )
var tempData = UnsafePointer<Float>( readBuffer ).memory
// Attempt 2 - Inverted bytes- Doesn't work since it's wrong and it's an IEEE Float
let readBuffer2 = [ readBuffer[ 3 ], readBuffer[ 2 ], readBuffer[ 1 ], readBuffer[ 0 ] ]
var tempValue = UnsafePointer<Float>( readBuffer2 ).memory
print( "TEMP: \( tempValue )" )
// Attempt 3 - Doesn't work for 1 or 2 since it's an IEEE Float
var f:Float = 0.0
memccpy(&f, readBuffer, 4, 4)
print( "TEMP: \( f )" )
var f2:Float = 0.0
memccpy(&f2, readBuffer2, 4, 4)
print( "TEMP: \( f2 )" )
// Attempt 4 - Trying to Read an Exponent and a Mantissa - Didn't work
readBuffer = Array<UInt8>( count: 1, repeatedValue: 0 )
stream.read( &readBuffer, maxLength: readBuffer.count )
let exponent = UnsafePointer<Int8>( readBuffer ).memory
readBuffer = Array<UInt8>( count: 3, repeatedValue: 0 )
stream.read( &readBuffer, maxLength: readBuffer.count )
let mantissa = UnsafePointer<Int16>( readBuffer ).memory
let temp = NSDecimalNumber( mantissa: mantissa, exponent: exponent, isNegative: false )
print( "TEMP: \( temp )" )
// Attempt 5 - Invert bytes - Doesn't work
readBuffer = Array<UInt8>( count: 4, repeatedValue: 0 )
stream.read( &readBuffer, maxLength: readBuffer.count )
let exponentBuffer = [ readBuffer[ 3 ] ]
let mantissaBuffer = [ readBuffer[ 2 ], readBuffer[ 1 ], readBuffer[ 0 ] ]
let exponent = UnsafePointer<Int16>( exponentBuffer ).memory
let mantissa = UnsafePointer<UInt64>( mantissaBuffer ).memory
let temp = NSDecimalNumber( mantissa: mantissa, exponent: exponent, isNegative: false )
print( "TEMP: \( temp )" )
// Attempt 6 - Tried a bitstream frontwards and backwards - Doesn't work
readBuffer = Array<UInt8>( count: 4, repeatedValue: 0 )
stream.read( &readBuffer, maxLength: readBuffer.count )
var bitBuffer: [String] = Array<String>( count:4, repeatedValue: "" )
for var i = 0; i < bitBuffer.count; i++ {
bitBuffer[ i ] = String( readBuffer[ i ], radix: 2 )
bitBuffer[ i ] = String( count: 8 - bitBuffer[ i ].characters.count, repeatedValue: Character( "0" ) ) + bitBuffer[ i ]
//bitBuffer[ i ] = String( bitBuffer[ i ].characters.reverse() )
}
print( "TEMP: \( bitBuffer )" )
// Attempt 7 - More like the Obj. C code - Doesn't work
readBuffer = Array<UInt8>( count: 4, repeatedValue: 0 )
stream.read( &readBuffer, maxLength: readBuffer.count )
let value = UnsafePointer<UInt32>( readBuffer ).memory
let tempData = CFSwapInt32LittleToHost( value )
let exponent = tempData >> 24
let mantissa = tempData & 0x00FFFFFF
if ( tempData == 0x007FFFFF ) {
print(" *** INVALID *** ")
return
}
let tempValue = Double( mantissa ) * pow( 10.0, Double( exponent ) )
print( "TEMP: \( tempValue )" )
// Attempt 8 - Saw that BLE spec says "NO Exponent" - Doesnt' work
readBuffer = Array<UInt8>( count: 1, repeatedValue: 0 )
stream.read( &readBuffer, maxLength: readBuffer.count )
readBuffer = Array<UInt8>( count: 3, repeatedValue: 0 )
stream.read( &readBuffer, maxLength: readBuffer.count )
let tempValue = UnsafePointer<Float>( readBuffer ).memory
print( "TEMP: \( tempValue )" )
// Example data:
// ["00110110", "00000001", "00000000", "11111111"]
//
// Only the first byte appears to ever change.
*/
// Timestamp - Year - works
readBuffer = Array<UInt8>( count: 2, repeatedValue: 0 )
stream.read( &readBuffer, maxLength: readBuffer.count )
let year = UnsafePointer<UInt16>( readBuffer ).memory
// Timestamp Remainder - works
readBuffer = Array<UInt8>( count: 5, repeatedValue: 0 )
stream.read( &readBuffer, maxLength: readBuffer.count )
let month = readBuffer[ 0 ]
let day = readBuffer[ 1 ]
let hour = readBuffer[ 2 ]
let minute = readBuffer[ 3 ]
let second = readBuffer[ 4 ]
print( "TIMESTAMP: \( month )/\( day )/\( year ) \( hour ):\( minute ):\( second )" )
我在 Objective C 中找到了这个示例,但我不知道 (https://github.com/AngelSensor/angel-sdk/blob/b7459d9c86c6a5c72d8e58b696345b642286b876/iOS/SDK/Services/HealthThermometer/ANHTTemperatureMeasurmentCharacteristic.m),并且我尝试过使用它,但我不清楚到底发生了什么:
// flags
uint8_t flags = dataPointer[0];
dataPointer++;
// temperature
uint32_t tempData = (uint32_t)CFSwapInt32LittleToHost(*(uint32_t *)dataPointer);
dataPointer += 4;
int8_t exponent = (int8_t)(tempData >> 24);
int32_t mantissa = (int32_t)(tempData & 0x00FFFFFF);
if (tempData == 0x007FFFFF) {
return;
}
float tempValue = (float)(mantissa*pow(10, exponent));
如果有人能帮助我了解如何从这个 BLE 特性中提取标志和温度计测量值,我将不胜感激。谢谢。
我被要求在下面提供示例数据。这是我的示例数据(总共 12 个字节):
["00000010", "00110011", "00000001", "00000000", "11111111", "11100000", "00000111", "00000100", "00001111", "00000001", "00000101", "00101100"]
-OR-
<025e0100 ffe00704 0f11150f>
【问题讨论】:
-
你能发布一个输入数据的例子吗?
-
包括在上面。让我知道你是否还有别的意思。谢谢。
-
那么您是从 BLE 接收到的位创建一个字符串数组?我对您刚刚发布的最后一个功能的目的感到困惑。
-
这是我检索这些位的方式,但我删除了它以避免混淆。
标签: swift swift2 bluetooth-lowenergy binaryfiles core-bluetooth