iosswiftcore-bluetoothcbperipheralcharacteristics

How to write a value to characteristc for BLE Device in ios swift


I'm working on iOS BLE app to charge a mobile phone. I did everything correct up to discover characteristics. First Scanning peripheral and connected to it. Discover the services(FFB0) and characteristics(FFB1, FFB2) which having notify and write without response properties.

I found the Client Characteristic Configuration Descriptor. I want to send the command to PCB to unlock for charging I want write value to FFB2 characteristics but peripheral doesn't respond. Here is my code.

I have searched everything related to this but I didn't find any solution If anybody gives solution to this problem it will be helpful to me.

This is Document Provided by client:

There is a BLE4.0 Bluetooth module on each of the PCB, each Bluetooth module has a solo 12 bytes length address code, The PCB data channel, Service UUID is OxFFBO, including two eigenvalues, it is OxFFBI and OxFFB2, The length of communication data is 1--20 bytes. OxFFB1 is the channel for APP data download.OxFBB2 is the channel for Bluetooth upload the data.

Power-up into idle mode, when in idle mode, the two lights will flash.it will send an ID code(a byte)to the phone, the APP in the phone will get the ID code(a byte). ID code can be set by phone settings. it means sending the corresponding unlock instruction by ID code.

The unlock instruction is 0x55,0xe1,(ID0+1),time,Following is the explain of unlock instruction:

ID0 is a ID code,"time" is the user unlock time(5-120 min), please pay attention to it is binary-to-hexadecimal conversion, time==05 means 5 min, time==6 means 6 min, time ==A means 10 min ,and so on. If the ID0 of the PCB is 0xff, unlock the pcb 60min is:0x55,0xe1,0x00,0x3c; If the ID0 of the PCB is 0x05, unlock the pcb 10 min is :0x55 , 0xe1 ,0x06 , 0x0a

It will start open output and timing when the MCU on the PCB receives the unlock instruction. The system goes into idle mode again when timing time is out. In idle mode, long press the key goes into shut down sleeping time mode.

The baud rate of uart is set at 9,600. The inquiry command that APP send to MCU is 0x55 0x01 MCU should reply to the APP's information format: 0x55, 0x02, bat_level, xH, XL (xH XL represents the current voltage value of the battery, xH - represents the high 8 bits, and XL--- represents the low 8 bits)

import CoreBluetooth

let batteryServiceCBUUID = CBUUID(string: "FFB0")
let batteryServiceRequestCBUUID = CBUUID(string: "FFB1")
let batteryServiceRequestCBUUID2 = CBUUID(string: "FFB2")

 class ChargingViewController: UIViewController , CBPeripheralDelegate 
 ,CBCentralManagerDelegate {    

  override func viewDidLoad() {
    super.viewDidLoad()
 centralManager = CBCentralManager(delegate: self, queue: nil, options: nil)  
 }
 func centralManagerDidUpdateState(_ central: CBCentralManager) {

    switch central.state {
    case .unknown:
        print("central.state is .unknown")
    case .resetting:
        print("central.state is .resetting")
    case .unsupported:
        print("central.state is .unsupported")
    case .unauthorised:
        print("central.state is .unauthorised")
    case .poweredOff:
        print("central.state is .poweredOff")
    case .poweredOn:


        centralManager.scanForPeripherals(withServices: [batteryServiceCBUUID])

        print("central.state is .poweredOn")
    @unknown default:
        fatalError()
    }

    print("state: \(central.state)")

 }
 func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, 
 advertisementData: [String : Any], rssi RSSI: NSNumber) {

    print(peripheral)
    batteryServicePeripheral = peripheral
    batteryServicePeripheral.delegate = self
    centralManager.stopScan()
    centralManager.connect(batteryServicePeripheral)

 }
  func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {

    print("Connected=======>\(String(describing: batteryServicePeripheral))")
    batteryServicePeripheral.delegate = self
    batteryServicePeripheral.discoverServices([batteryServiceCBUUID])

}

func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, 
 error: Error?) {

    print("Fail To Connect=======>\(String(describing: error))")
}


func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: 
CBPeripheral, error: Error?) {

    if error == nil {

        print("Disconnected========>\(peripheral)")
    }else {

        print("Disconnected========>\(String(describing: error))")
    }
 }
// MARK: -  CBPeripheral Delegate Methods

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {

    guard let services = peripheral.services else { return }

    for service in services {

        print("SPAKA:PERIPHERALSERVICES============>\(service)")
        peripheral.discoverCharacteristics(nil, for: service)

    }

}

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {

    if let characteristics = service.characteristics {
        //else { return }

        for characteristic in characteristics {

            print(characteristic)


            if characteristic.uuid == batteryServiceCBUUID {

               peripheral.setNotifyValue(true, for: characteristic)

            }

            if characteristic.uuid == batteryServiceRequestCBUUID2 {

                batteryCharacteristics = characteristic


                let str1 = "55e100"
                let data = String(format: "%@%@",str1,hexTimeForChar)

                guard let valueString = data.data(using: String.Encoding.utf8)  else 
    {return}



                peripheral.writeValue(valueString, for: characteristic , type: 
        CBCharacteristicWriteType.withoutResponse)
                print("Value String===>\(valueString.debugDescription)")
                peripheral.setNotifyValue(true, for: characteristic)

            }

        }
    }
    peripheral.discoverDescriptors(for: batteryCharacteristics)
}


func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {

    if error == nil {
        print("Message sent=======>\(String(describing: characteristic.value))")
    }else{

        print("Message Not sent=======>\(String(describing: error))")
    }




}

func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: 
CBCharacteristic, error: Error?) {

    if error == nil {
        print("SPAKA : IS NOTIFYING UPDATED STATE ======>\(characteristic.isNotifying)")
        print("SPAKA : UPDATED DESCRIPTION ======>\(String(describing: 
 characteristic.description))")


    }else{
        print("SPAKA : ERRORUPDATEDNOTIFICATION\(String(describing: error))")
    }


}


func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {

    print("SPAKA: UPDATED VALUE RECEIVED========>\(String(describing: characteristic.value))")
    print("characteristic UUID: \(characteristic.uuid), value: \(characteristic.value)")

    guard let str = characteristic.value else { return  }

    if let string = String(bytes: str, encoding: .utf8) {
        print("SPAKA==========>:::\(string)")
    } else {
        print("not a valid UTF-8 sequence")
    }



}

func peripheral(_ peripheral: CBPeripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) {

    guard let desc = batteryCharacteristics.descriptors else { return }


    for des in desc {

        print("BEGIN:SPAKA DESCRIPTOR========>\(des)")
        discoveredDescriptor = des

        print("Descriptor Present Value and uuid: \(des.uuid), value: \(String(describing: des.value))")
        peripheral.readValue(for: discoveredDescriptor)


    }


}

func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) {
    if let error = error {
        print("Failed… error: \(error)")
        return
    }

    print("Descriptor Write Value uuid: \(descriptor.uuid), value: \(String(describing: descriptor.value))")
}

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor descriptor: CBDescriptor, error: Error?) {

    if let error = error {
        print("Failed… error: \(error)")
        return
    }

    print("Descriptor Updated Value uuid: \(descriptor.uuid), value: \(String(describing: descriptor.value))")

}
}

Solution

  • The information about the PDB is somewhat difficult to decipher but contains good information. It sounds as if the PCBs contain a Bluetooth-to-UART module. One characteristic is for sending data to the PCB, one characteristic is for receiving data from the PCB.

    I still don't understand the commands that need to be sent to the PCB. If you have access to the Android code, then you can find the answers there.

    Below is the minimal code that could potentially:

    let batteryServiceUUID = CBUUID(string: "FFB0")
    let rxCharacteristicUUID = CBUUID(string: "FFB1")
    let txCharacteristicUUID = CBUUID(string: "FFB2")
    
    var centralManager: CBCentralManager!
    var batteryPeripheral: CBPeripheral? = nil
    var batteryService: CBService? = nil
    var txCharacteristic: CBCharacteristic? = nil
    var rxCharacteristic: CBCharacteristic? = nil
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            centralManager.scanForPeripherals(withServices: [batteryServiceUUID])
        }
    }
    
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        batteryPeripheral = peripheral
        batteryPeripheral!.delegate = self
        centralManager.stopScan()
        centralManager.connect(batteryPeripheral!)
    }
    
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        batteryPeripheral!.discoverServices([batteryServiceUUID])
    }
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        peripheral.discoverCharacteristics(nil, for: peripheral.services![0])
    }
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        for characteristic in service.characteristics! {
            if characteristic.uuid == rxCharacteristicUUID {
                rxCharacteristic = characteristic
                peripheral.setNotifyValue(true, for: rxCharacteristic!)
            } else if (characteristic.uuid == txCharacteristicUUID) {
                txCharacteristic = characteristic
            }
        }
        sendInitialCommand()
    }
    
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        if let value = characteristic.value {
            print("Data received")
            print(value as NSData)
        }
    }
    
    func sendInitialCommand() {
        let cmdBytes: [UInt8] = [0x55, 0xe1, 0x00, 0x0a]
        let cmd = Data(cmdBytes)
        batteryPeripheral!.writeValue(cmd, for: txCharacteristic!, type: .withoutResponse)
    }