![](/img/trans.png)
[英]iOS BLE Bluetooth 8.1 and lower BLE subscribed characteristic notification no response
[英]BLE cadence characteristic parsing iOS bluetooth Swift
我正在嘗試創建一個讀取節奏傳感器(Wahoo 健身節奏)的 iOS 應用程序。 這是藍牙特性0x2A5B(CSC 測量) 。 在這個例子中,踏頻是自行車上踏板旋轉的速度。
我在 Swift 中使用下面的代碼從傳感器讀取特性:版本 1:
private func cadence(from characteristic: CBCharacteristic) -> Int {
guard let characteristicData = characteristic.value else {return -1 }
let byteArray = [UInt8](characteristicData)
print(byteArray)
let firstBitValue = byteArray[1] & 0x01 //set bit 1 (not 0)
if firstBitValue == 1 { //IF crank revolution data is present, 1==true
return Int(byteArray[2])
} else {
return 0
}
}
當我打印 byteArray 時,我得到“[2, 1, 0, 152, 11]”。 “2”和“0”永遠不會改變。 “1”位置增加並且從不減少。 “152”和“11”的位置似乎是完全隨機的,永遠不會變為0。當曲柄完全停止時,它們也不會改變。 在閱讀文檔時,我預計“11”是最后一個事件啟動時間。 但不管我旋轉傳感器有多慢,它似乎都沒有改變。
如何使用此數據從傳感器獲取節奏?
在 Paul 的幫助下,我對代碼進行了更改,結果如下:
版本 2
func cadence(from characteristic:CBCharacteristic, previousRotations:Int = 0) -> (rpm:Double, rotations:Int)? {
guard let characteristicData = characteristic.value else {
return nil
}
let byteArray = [UInt8](characteristicData)
if byteArray[0] & 0x02 == 2 {
// contains cadence data
let rotations = (Int(byteArray[2]) << 8) + Int(byteArray[1])
var deltaRotations = rotations - previousRotations
if deltaRotations < 0 {
deltaRotations += 65535
}
let timeInt = (Int(byteArray[4]) << 8) + Int(byteArray[3])
let timeMins = Double(timeInt) / 1024.0 / 60.0
let rpm = Double(deltaRotations) / timeMins
return (rpm:rpm, rotations: rotations)
}
return nil
}
返回的 RPM 當前低於預期值,最高約為 53,最低為 3。 這些值與傳感器開發人員的應用程序進行比較,該應用程序指示大約 50-70 rpm。
版本 3:
func cadence(from characteristic:CBCharacteristic, previousTime: Int=0, previousRotations:Int = 0) -> (rpm:Double, time: Int, rotations:Int)? {
guard let characteristicData = characteristic.value else {
return nil
}
let byteArray = [UInt8](characteristicData)
if byteArray[0] & 0x02 == 2 {
// contains cadence data
let rotations = Int(byteArray[2])<<8 + Int(byteArray[1])
var deltaRotations = rotations - previousRotations
if deltaRotations < 0 {
deltaRotations += 65535
}
let timeInt = Int(byteArray[4])<<8 + Int(byteArray[3])
var timeDelta = timeInt - previousTime
if (timeDelta < 0) {
timeDelta += 65535
}
let timeMins = Double(timeDelta) / 1024.0 / 60
let rpm = Double(deltaRotations) / timeMins
return (rpm:rpm, time: timeInt, rotations: rotations)
}
return nil
}
這就是我最終做的
func onCSC(from characteristic: CBCharacteristic) -> Double{
guard let characteristicData = characteristic.value else { return -1 }
let byteArray = [UInt8](characteristicData)
let firstBitValue = byteArray[0] & 0x01 // Bit1 [2] == 0010 & 0000 == 0000 == 0 (Dec) Wheel Rev FALSE (For Spd)
let secondBitValue = byteArray[0] & 0x02 // Bit2 [2] == 0010 & 0010 == 0010 == 2 (Dec) Crank Rev TRUE (For Cad)
if firstBitValue > 0 {
// Since using Wahoo RPM cadence only sensor. (Revisit Later)
}
if secondBitValue > 0 {
let cumCrankRev = Int(byteArray[2])<<8 + Int(byteArray[1])
let lastCrankTime = Int(byteArray[4])<<8 + Int(byteArray[3])
var deltaRotations = cumCrankRev - prevCumCrankRev
if deltaRotations < 0 { deltaRotations += 65535 }
var timeDelta = lastCrankTime - prevCrankTime
if (timeDelta < 0) { timeDelta += 65535 }
// In Case Cad Drops, we use PrevRPM
// to substitute (up to 2 seconds before reporting 0)
if (timeDelta != 0) {
prevCrankStaleness = 0
let timeMins = Double(timeDelta) / 1024.0 / 60
rpm = Double(deltaRotations) / timeMins
prevRPM = rpm
} else if (timeDelta == 0 && prevCrankStaleness < 2 ) {
rpm = prevRPM
prevCrankStaleness += 1
} else if (prevCrankStaleness >= 2) {
rpm = 0.0
}
prevCumCrankRev = cumCrankRev
prevCrankTime = lastCrankTime
return rpm
}
return -1
}
根據 bluetooth.com 的規格
// byte1 uint8: flags
// bit 0 = 1: Wheel Revolution Data is present
// bit 1 = 1: Crank Revolution Data is present
//
// byte2/3 The next two fields are present only if bit 0 above is 1:
// uint32: Cumulative Wheel Revolutions
// uint16: Last Wheel Event Time, in 1024ths of a second
//
// byte 3/4 The next two fields are present only if bit 10 above is 1:
// uint16: Cumulative Crank Revolutions
// uint16: Last Crank Event Time, in 1024ths of a second
// Flag : 2 (0x2)
// CumWheel : 6 (0x6)
// LastWheel : 0 (0x0)
// CumCrank : 231 (0xe7)
// LastCrankTm: 30 (0x1e)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.