ios 错误域:“CBATTEErrorDomain”-代码:128 0x000000282b111a0

qco9c6ql  于 2023-06-25  发布在  iOS
关注(0)|答案(1)|浏览(74)

我正在用Swift写一段代码,从BLE设备(欧姆龙BP 7000)获取数据。我能够与它配对,并获得其他服务和读取数据。但是我无法得到血压的数据,在didUpdateValueFor characteristic:。CoreBluetooth的其他代表已经使用,并按预期工作。只是当谈到读/写数据到当前时间和读数据从血压特性,我得到的问题。如果任何人可以张贴一些建议,我应该如何进行将是有帮助的。

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
      switch characteristic.uuid {
    
      case batteryLevelCBUUID:
          print("Battery level: \(characteristic.value![0])")
          let valueBattery = characteristic.value?[0]
          batteryLabel.text = "Battery Level =" + " " + String(describing: characteristic.value!      [0]) + "%"
          centerView.isHidden = false
      case currentTimeCBUUID:
          peripheral.readValue(for: characteristic)
          let currentDate = Date()
          //           Write the date and time to the characteristic
          writeCurrentTime(to: characteristic, in: peripheral)
          //          print("\(characteristic.value as Any) gives Current Time String  ")
          if let dateTime = extractDateTime(from: characteristic) {
              print("Date and Time:", dateTime)
          } else {
              print("Unable to extract date and time from the characteristic.")
          }
       case bloodPressureMeasurementCBUUID:
          decodeBloodPressureMeasurementData(from: characteristic)
          print("\(characteristic.value as Any) gives 2A35 ")
       default:
          print("")

}
}

    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        if let error = error {
            // Handle write error
            print("Error writing value: \(error.localizedDescription)")
        } else {
            // Handle successful write
            print("Value written successfully")

            // Check if the characteristic supports notifications
            if characteristic.properties.contains(.notify) {
                peripheral.setNotifyValue(true, for: characteristic)
            }
        }
    }

    func writeCurrentTime(to characteristic: CBCharacteristic, in peripheral: CBPeripheral) {
        // Get the current date and time
        let currentDate = Date()
        let calendar = Calendar.current
        var components = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second, .weekday, .nanosecond], from: currentDate)
        
        // Create the value to be written
        var value = Data()
        value.append(Data(bytes: &components.year!, count: 2)) // Year (2 bytes)
        value.append(Data(bytes: "", count: 0))
        value.append(UInt8(components.month!)) // Month (1 byte)
        value.append(UInt8(components.day!)) // Day (1 byte)
        value.append(UInt8(components.hour!)) // Hours (1 byte)
        value.append(UInt8(components.minute!)) // Minutes (1 byte)
        value.append(UInt8(components.second!)) // Seconds (1 byte)
        value.append(UInt8(components.weekday!)) // Day of Week (1 byte)
        value.append(contentsOf: components.nanosecond!.bytes(2)) // Fractions of a second (2 bytes)
        
        // Write the value to the Current Time characteristic
        peripheral.writeValue(value, for: characteristic, type: .withResponse)
    }

    
    func decodeBloodPressureMeasurementData(from characteristic: CBCharacteristic) {
        guard let data = characteristic.value else {
            print("No data available for decoding.")
            return
        }

        let flags = data[0] // Flags byte
        let unitFlags = (flags & 0b00000001) // Bit 0 indicates the unit of blood pressure values
        let timestampFlags = (flags & 0b00000010) // Bit 1 indicates the presence of timestamp

        // Decode systolic, diastolic, and mean arterial pressure values
        let systolicPressure = (data[1] + (data[2] << 8))
        let diastolicPressure = (data[3] + (data[4] << 8))
        let meanArterialPressure = (data[5] + (data[6] << 8))

        // Decode pulse rate value
        let pulseRate = (data[7] + (data[8] << 8))

        // Decode unit of blood pressure values
        let unit: String = (unitFlags != 0) ? "kPa" : "mmHg"

        // Process and use the decoded values as needed
        print("Systolic Pressure: \(systolicPressure) \(unit)")
        print("Diastolic Pressure: \(diastolicPressure) \(unit)")
        print("Mean Arterial Pressure: \(meanArterialPressure) \(unit)")
        print("Pulse Rate: \(pulseRate) bpm")
    }
mbskvtky

mbskvtky1#

我假设您的当前时间是Current Time Service的一部分。错误代码128(0x 80)表示“数据字段被忽略”。因此,您发送的是设备不支持的字段,或者发送的内容超出了范围。文档还解释了所有的值都是little-endian。
规范指出,当前时间可以选择写入(有响应),不允许在没有响应的情况下写入。所以你写回应是正确的。由于您得到的是0x 80而不是一般的写入失败,因此我将假设该特性在此设备上是可写的。
现在,请参阅GSS v9的第3.62节,了解有关当前时间特性的详细信息。结构为10个八位字节,精确时间256(9个八位字节),后面跟着调整原因(1个八位字节)。
现在,转到定义精确时间256的第3.90节。它是一个Day Date Time结构(3.71节),后面跟着Factions 256 uint 8。
你懂的一步一步地通过规范来构建格式。不要猜测。永远不要认为这是显而易见的。按照规范操作。我将跳过一些步骤并组装整个格式:

year        : 16 (little-endian)
month       : 8
day         : 8
hour        : 8
minute      : 8
second      : 8
dayOfWeek   : 8 (1=Monday, 7=Sunday, 0=Unknown)
fractions256: 8 (factional part of seconds in units of 1/256)
adjustReason: 8 (0=manual, 1=reference update, 2=TZ change, 3=DST)

为了方便起见,我经常在FixedWidthIntegers上使用这个扩展:

enum ByteOrder {
    case littleEndian, bigEndian
}

extension FixedWidthInteger {
    func data(byteOrder: ByteOrder) -> Data {
        switch byteOrder {
        case .littleEndian: return withUnsafeBytes(of: self.littleEndian) { Data($0) }
        case .bigEndian: return withUnsafeBytes(of: self.bigEndian) { Data($0) }
        }
    }
}

蓝牙的工作日与Foundation的不同:

extension DateComponents {
    // Monday=1 to Sunday=7, 0=unknown
    var btDayOfWeek: UInt8 {
        guard let dow = self.weekday else { return 0 }
        return dow == 1 ? 7 : UInt8(dow - 1)
    }
}

有了这些,我相信这将是正确的包:

var data = Data()
data.append(UInt16(c.year!).data(byteOrder: .littleEndian))
data.append(UInt8(c.month!))
data.append(UInt8(c.day!))
data.append(UInt8(c.hour!))
data.append(UInt8(c.minute!))
data.append(UInt8(c.second!))
data.append(c.btDayOfWeek)
data.append(UInt8(c.nanosecond! * 256 / Int(NSEC_PER_SEC)))
data.append(0) // Adjust reason. 0 == Manual Time Update

所以你在解码血压。当它们是medfloat 16时,看起来像是将它们当作整数来对待,而忽略了文档中的比例因子。从GSS的2.3节开始,它解释了如何解释一般的数值,特别是2.3.2节中关于标量的数值。然后参见第3.31节,详细解释了血压测量特性。您可能会发现Personal Health Devices Transcoding白色很有帮助。“medfloat 16”通常被称为SFLOAT,因此您可以阅读白皮书的第2.2.2节以了解详细信息和示例编码。
如果你在阅读以上内容后有关于血压的问题,可以针对你的具体问题打开一个新的问题。输入是什么?输出应该是什么?您得到的是什么输出?

相关问题