Characteristic.value 来自 Swift 中的蓝牙读取
Characteristic.value from Bluetooth reading in Swift
我正在尝试读取来自 BT 设备的读数并将其转换为字符串。
<CBCharacteristic: 0x1700a2e80, UUID = 2A9D, properties = 0x20, value = <02ac08e1 07010a14 0029>, notifying = YES>
基于我在网上找到的示例
let u16 = (characteristic.value! as NSData).bytes.bindMemory(to: Int.self, capacity: characteristic.value!.count).pointee
但是我的 u16 是空的,即使 characteristic.value 包含
(lldb) dp characteristic.value! as NSData
<02ac08e1 07010a14 0029>
谁能给我指出正确的方向?
这并不容易。
你可能需要这样写:
let data = Data([0x02,0xac,0x08,0xe1,0x07,0x01,0x0a,0x14,0x00,0x29])
struct DataReader {
var data: Data
var offset: Int = 0
mutating func read() -> UInt8 {
let result = data[offset]
offset += MemoryLayout<UInt8>.size
return result
}
mutating func read() -> UInt16 {
let subdata = data.subdata(in: offset..<offset+MemoryLayout<UInt16>.size)
let result: UInt16 = subdata.withUnsafeBytes {(bytes: UnsafePointer<UInt16>) in
bytes.pointee.littleEndian
}
offset += MemoryLayout<UInt16>.size
return result
}
}
typealias BLEUserID = UInt8
struct BLEDateTime {
var year: UInt16
var month: UInt8
var day: UInt8
var hours: UInt8
var minutes: UInt8
var seconds: UInt8
}
extension DataReader {
mutating func read() -> BLEDateTime {
let year: UInt16 = read()
let month: UInt8 = read()
let day: UInt8 = read()
let hours: UInt8 = read()
let minutes: UInt8 = read()
let seconds: UInt8 = read()
return BLEDateTime(year: year, month: month, day: day, hours: hours, minutes: minutes, seconds: seconds)
}
}
struct WeightMeasurement: CustomStringConvertible {
struct Flags: OptionSet {
var rawValue: UInt8
init(rawValue: UInt8) {
self.rawValue = rawValue
}
static let measurementImperial = Flags(rawValue: 1<<0)
static let timeStampPresent = Flags(rawValue: 1<<1)
static let userIDPresent = Flags(rawValue: 1<<2)
static let bmiAndHeightPresent = Flags(rawValue: 1<<3)
}
var isMeasuremntImperial: Bool
var weight: Decimal
var timeStamp: BLEDateTime?
var userID: BLEUserID?
var bmi: Decimal?
var height: Decimal?
var description: String {
return weight.description
}
}
extension DataReader {
mutating func read() -> WeightMeasurement {
let flags = WeightMeasurement.Flags(rawValue: read())
let isMeasuremntImperial = flags.contains(.measurementImperial)
let weight: Decimal
if isMeasuremntImperial {
weight = Decimal(read() as UInt16) * Decimal(string: "0.01")!
} else {
//SI
weight = Decimal(read() as UInt16) * Decimal(string: "0.005")!
}
var timeStamp: BLEDateTime?
if flags.contains(.timeStampPresent) {
timeStamp = read()
}
var userID: BLEUserID?
if flags.contains(.userIDPresent) {
userID = read()
}
var bmi: Decimal?
var height: Decimal?
if flags.contains(.bmiAndHeightPresent) {
bmi = Decimal(read() as UInt16) * Decimal(string: "0.1")!
if isMeasuremntImperial {
height = Decimal(read() as UInt16) * Decimal(string: "0.1")!
} else {
//SI
height = Decimal(read() as UInt16) * Decimal(string: "0.001")!
}
}
return WeightMeasurement(isMeasuremntImperial: isMeasuremntImperial, weight: weight, timeStamp: timeStamp, userID: userID, bmi: bmi, height: height)
}
}
var reader = DataReader(data: data, offset: 0)
let weightMeasurement: WeightMeasurement = reader.read()
print(weightMeasurement) //->11.1
print(weightMeasurement.timeStamp!) //->BLEDateTime(year: 2017, month: 1, day: 10, hours: 20, minutes: 0, seconds: 41)
(抱歉,尚未完全测试,您可能需要进行一些修改。)
我正在尝试读取来自 BT 设备的读数并将其转换为字符串。
<CBCharacteristic: 0x1700a2e80, UUID = 2A9D, properties = 0x20, value = <02ac08e1 07010a14 0029>, notifying = YES>
基于我在网上找到的示例
let u16 = (characteristic.value! as NSData).bytes.bindMemory(to: Int.self, capacity: characteristic.value!.count).pointee
但是我的 u16 是空的,即使 characteristic.value 包含
(lldb) dp characteristic.value! as NSData
<02ac08e1 07010a14 0029>
谁能给我指出正确的方向?
这并不容易。
你可能需要这样写:
let data = Data([0x02,0xac,0x08,0xe1,0x07,0x01,0x0a,0x14,0x00,0x29])
struct DataReader {
var data: Data
var offset: Int = 0
mutating func read() -> UInt8 {
let result = data[offset]
offset += MemoryLayout<UInt8>.size
return result
}
mutating func read() -> UInt16 {
let subdata = data.subdata(in: offset..<offset+MemoryLayout<UInt16>.size)
let result: UInt16 = subdata.withUnsafeBytes {(bytes: UnsafePointer<UInt16>) in
bytes.pointee.littleEndian
}
offset += MemoryLayout<UInt16>.size
return result
}
}
typealias BLEUserID = UInt8
struct BLEDateTime {
var year: UInt16
var month: UInt8
var day: UInt8
var hours: UInt8
var minutes: UInt8
var seconds: UInt8
}
extension DataReader {
mutating func read() -> BLEDateTime {
let year: UInt16 = read()
let month: UInt8 = read()
let day: UInt8 = read()
let hours: UInt8 = read()
let minutes: UInt8 = read()
let seconds: UInt8 = read()
return BLEDateTime(year: year, month: month, day: day, hours: hours, minutes: minutes, seconds: seconds)
}
}
struct WeightMeasurement: CustomStringConvertible {
struct Flags: OptionSet {
var rawValue: UInt8
init(rawValue: UInt8) {
self.rawValue = rawValue
}
static let measurementImperial = Flags(rawValue: 1<<0)
static let timeStampPresent = Flags(rawValue: 1<<1)
static let userIDPresent = Flags(rawValue: 1<<2)
static let bmiAndHeightPresent = Flags(rawValue: 1<<3)
}
var isMeasuremntImperial: Bool
var weight: Decimal
var timeStamp: BLEDateTime?
var userID: BLEUserID?
var bmi: Decimal?
var height: Decimal?
var description: String {
return weight.description
}
}
extension DataReader {
mutating func read() -> WeightMeasurement {
let flags = WeightMeasurement.Flags(rawValue: read())
let isMeasuremntImperial = flags.contains(.measurementImperial)
let weight: Decimal
if isMeasuremntImperial {
weight = Decimal(read() as UInt16) * Decimal(string: "0.01")!
} else {
//SI
weight = Decimal(read() as UInt16) * Decimal(string: "0.005")!
}
var timeStamp: BLEDateTime?
if flags.contains(.timeStampPresent) {
timeStamp = read()
}
var userID: BLEUserID?
if flags.contains(.userIDPresent) {
userID = read()
}
var bmi: Decimal?
var height: Decimal?
if flags.contains(.bmiAndHeightPresent) {
bmi = Decimal(read() as UInt16) * Decimal(string: "0.1")!
if isMeasuremntImperial {
height = Decimal(read() as UInt16) * Decimal(string: "0.1")!
} else {
//SI
height = Decimal(read() as UInt16) * Decimal(string: "0.001")!
}
}
return WeightMeasurement(isMeasuremntImperial: isMeasuremntImperial, weight: weight, timeStamp: timeStamp, userID: userID, bmi: bmi, height: height)
}
}
var reader = DataReader(data: data, offset: 0)
let weightMeasurement: WeightMeasurement = reader.read()
print(weightMeasurement) //->11.1
print(weightMeasurement.timeStamp!) //->BLEDateTime(year: 2017, month: 1, day: 10, hours: 20, minutes: 0, seconds: 41)
(抱歉,尚未完全测试,您可能需要进行一些修改。)