Search code examples
iosswiftbluetooth-lowenergyswift5.7

NSError domain: "CBATTErrorDomain" - code: 128 0x0000000282b111a0


I am writing a code in swift to get data from a BLE device (Omron BP7000). I am able to pair with it and get the other service and read the data. But I am unable to get the data of the blood pressure, in didUpdateValueFor characteristic:. Other delegate of CoreBluetooth have been used and are working as expected. Just when it comes to read/write data to Current time and read data from the Blood pressure characteristic I get the issue. If anyone can post some suggest of how should I proceed will be helpful.

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")
    }
    


  [1]: https://i.sstatic.net/fYaxj.png

Solution

  • I have found the answer for this issue. I was using Data() and instead of that when I used NSMutableData() it started working and connected to the BLE device (Omron BP 7000). Following is the code for the answer I have used.

    // Define the CurrentTime structure
    struct DateAndTime {
        var year: UInt16
        var month: UInt8
        var day: UInt8
        var hours: UInt8
        var minutes: UInt8
        var seconds: UInt8
    }
    
    struct CurrentTime {
        var dateData : DateAndTime
        var dayOfWeek: UInt8
        var fractions256: UInt8
        var adjustReason: UInt8
    }
    
    
    
    func writeCurrentTime(to characteristic: CBCharacteristic, in peripheral: CBPeripheral){
            // Get the current date and time
            let currentDate = Date()
            let calendar = Calendar.current
            let components = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second, .weekday, .nanosecond], from: currentDate)
            // Send the bytes to the BLE device
            let data = NSMutableData()
            
            let time = DateAndTime(year: UInt16(components.year!), month: (UInt8(components.month!) + 1), day: (UInt8(components.day!)), hours: (UInt8(components.hour!)), minutes: (UInt8(components.minute!)), seconds: (UInt8(components.second!)))
            
            
            // Create an instance of CurrentTime with current date and time
            let currentTime = CurrentTime(dateData: time, dayOfWeek: (components.btDayOfWeek), fractions256: UInt8(components.nanosecond! * 256 / Int(NSEC_PER_SEC)), adjustReason: 0)    // Replace with the actual year
            
            // Convert the CurrentTime structure to Data
            let currentTimeData = withUnsafeBytes(of: currentTime) { Data($0) }
            data.append(currentTimeData)
            // Write the value to the Current Time characteristic
            peripheral.writeValue(data as Data, for: characteristic, type: .withResponse)
        }