Swift中解析Arduino通过BLE发送的结构体数据求助
Swift解析BLE传输的Arduino结构体数据
核心解决思路
避开直接绑定结构体可能出现的内存对齐、字节序不兼容问题,通过Data的字节偏移精准提取每个字段,保证解析准确性。
可行代码示例
// 给Data扩展字段提取方法,方便复用 extension Data { // 提取指定偏移量开始的8字节设备ID func getDeviceID(startAt offset: Int) -> [UInt8] { guard count >= offset + 8 else { return [] } var idArray = [UInt8](repeating: 0, count: 8) copyBytes(to: &idArray, from: offset..<offset+8) return idArray } // 提取小端字节序的Float(匹配Arduino默认字节序) func getLittleEndianFloat(startAt offset: Int) -> Float? { guard count >= offset + 4 else { return nil } var rawValue: UInt32 = 0 copyBytes(to: &rawValue, from: offset..<offset+4) return Float(bitPattern: UInt32(littleEndian: rawValue)) } } // 定义你已有的结构体(保持原有结构) struct ArduinoData { var deviceid = Array(repeating: 0, count: 8) var temperature: Float var wind: Float var pressure: Float } // 解析BLE数据的核心函数 func parseBLEReceivedData(_ rawData: Data) -> ArduinoData? { // 先校验数据长度是否符合20字节(8+4+4+4) guard rawData.count == 20 else { return nil } let deviceID = rawData.getDeviceID(startAt: 0) guard let temp = rawData.getLittleEndianFloat(startAt: 8), let windSpeed = rawData.getLittleEndianFloat(startAt: 12), let barPressure = rawData.getLittleEndianFloat(startAt: 16) else { return nil } return ArduinoData(deviceid: deviceID, temperature: temp, wind: windSpeed, pressure: barPressure) } // 使用示例(替换成你获取到的characteristic.value) if let receivedData = characteristic.value, let parsedResult = parseBLEReceivedData(receivedData) { print("设备ID: \(parsedResult.deviceid.map { String(format: "%02X", $0) }.joined())") print("温度: \(parsedResult.temperature)℃") print("风速: \(parsedResult.wind)m/s") print("气压: \(parsedResult.pressure)hPa") }
关键注意点
- 字节序适配:Arduino默认采用小端字节序存储数据,解析Float时必须做小端转换;若你的Arduino代码修改过字节序,需将
littleEndian替换为bigEndian。 - 边界校验:始终先检查数据长度是否为20字节,避免越界访问导致崩溃。
内容的提问来源于stack exchange,提问作者i-developer
相关产品推荐
相关产品推荐

