Android转Swift:Omron BP7000 BLE写入时间失败(错误码128)
修正Omron BP7000时间写入的Swift代码(解决CBATTErrorDomain Code 128)
问题背景
将Android平台下向Omron BP7000血压计写入当前时间的代码转成iOS Swift代码时,触发蓝牙ATT错误:NSError domain: "CBATTErrorDomain" - code: 128。这个错误本质是写入的数据格式不符合外设协议要求。以下是原Android工作代码、你写的Swift代码、两者生成的字节数组对比,以及针对性的修正方案。
原Android工作代码
// 生成时间字节数组的方法 private byte[] getTimeBytes() { Calendar calendar = Calendar.getInstance(); int year = calendar.get(Calendar.YEAR) - 2000; // 取2000年后的偏移量 int month = calendar.get(Calendar.MONTH) + 1; // 月份从1开始 int day = calendar.get(Calendar.DAY_OF_MONTH); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); byte[] timeBytes = new byte[7]; timeBytes[0] = (byte) 0x01; // 命令标识 timeBytes[1] = (byte) year; timeBytes[2] = (byte) month; timeBytes[3] = (byte) day; timeBytes[4] = (byte) hour; timeBytes[5] = (byte) minute; timeBytes[6] = (byte) second; return timeBytes; } // 写入操作示例 BluetoothGattCharacteristic characteristic = ...; // 对应时间写入的特征值 characteristic.setValue(getTimeBytes()); gatt.writeCharacteristic(characteristic);
待修正的Swift代码
// 生成时间字节数组的方法 func getTimeBytes() -> Data { let calendar = Calendar.current let year = calendar.component(.year, from: Date()) - 2000 let month = calendar.component(.month, from: Date()) let day = calendar.component(.day, from: Date()) let hour = calendar.component(.hour, from: Date()) let minute = calendar.component(.minute, from: Date()) let second = calendar.component(.second, from: Date()) var timeBytes = [UInt8]() timeBytes.append(0x01) timeBytes.append(UInt8(year)) timeBytes.append(UInt8(month)) timeBytes.append(UInt8(day)) timeBytes.append(UInt8(hour)) timeBytes.append(UInt8(minute)) timeBytes.append(UInt8(second)) return Data(timeBytes) } // 写入操作示例 if let characteristic = ... { // 对应时间写入的特征值 peripheral.writeValue(getTimeBytes(), for: characteristic, type: .withoutResponse) // 或尝试.withResponse? }
字节数组对比(以2024年5月20日14:30:45为例)
- Android生成的字节数组:
[0x01, 0x18, 0x05, 0x14, 0x0E, 0x1E, 0x2D]
(注:2024-2000=24→0x18;5→0x05;20→0x14;14→0x0E;30→0x1E;45→0x2D) - Swift生成的字节数组:
[0x01, 0x18, 0x05, 0x14, 0x0E, 0x1E, 0x2D]
(表面数值一致,但存在写入类型、字节符号性的潜在差异)
错误分析与修正方案
CBATTError 128属于应用层协议错误,核心是数据或写入方式不符合外设要求,以下是具体修复点:
1. 修正蓝牙写入类型
Android的writeCharacteristic默认用带响应的写入(对应Swift的.withResponse),你当前Swift代码用的.withoutResponse可能导致外设无法正确处理请求。
修正代码:
peripheral.writeValue(getTimeBytes(), for: characteristic, type: .withResponse)
2. 统一字节符号性
Android的byte是有符号类型(范围-128127),Swift的`UInt8`是无符号类型(0255)。虽然当前年份偏移量24<127不会触发问题,但为了完全匹配Android的字节格式,建议统一用有符号字节:
修正代码:
// 生成字节数组时改用Int8 let timeBytes: [Int8] = [ 0x01, Int8(year), Int8(month), Int8(day), Int8(hour), Int8(minute), Int8(second) ] return Data(bytes: timeBytes, count: timeBytes.count)
3. 确认特征值权限
确保目标CBCharacteristic具备WRITE权限,可通过打印验证:
print("Characteristic properties: \(characteristic.properties.rawValue)") // 输出需包含.write或.writeWithoutResponse
最终修正后的完整Swift代码
func getTimeBytes() -> Data { let calendar = Calendar.current let now = Date() let year = calendar.component(.year, from: now) - 2000 let month = calendar.component(.month, from: now) let day = calendar.component(.day, from: now) let hour = calendar.component(.hour, from: now) let minute = calendar.component(.minute, from: now) let second = calendar.component(.second, from: now) // 用Int8匹配Android有符号byte格式 let timeBytes: [Int8] = [ 0x01, Int8(year), Int8(month), Int8(day), Int8(hour), Int8(minute), Int8(second) ] return Data(bytes: timeBytes, count: timeBytes.count) } // 写入操作 if let characteristic = targetCharacteristic, characteristic.properties.contains(.write) { peripheral.writeValue(getTimeBytes(), for: characteristic, type: .withResponse) } else { print("目标特征值不支持写入操作") }
内容的提问来源于stack exchange,提问作者Kshitij876
相关产品推荐
相关产品推荐

