Writing BLE Commands on a Loop Doesn't Get All Responses - Swift

Viewed 220

I am working on a project (Swift) to connect to OBDII Devices. Currently my issue is with a BLE device.

I am able to send commands (write) successfully, when I send them individually:

private func sendBT_Command(theCommand: String) {
    
    if let myPeripheral = myPeripheral,
       let writeCharacteristic = writeCharacteristic {

        let completeCommand  = "\(theCommand)\r\n"
        let commandData = Data(completeCommand.utf8)

        myPeripheral.writeValue(commandData, for: writeCharacteristic, type: .withResponse)
        
    } else {
        
        print("NO CONNECTION")
        
    }
    
}

The commands I send individually are :

ATZ, ATST32, ATH1, ATE0 .... and others.

In the didUpdateValues delegate...

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
    
    
    if let value = characteristic.value {
        
        let resultString = String(decoding: value, as: UTF8.self)
        
        if hasTermination(aResponse: resultString) {
            receivedResponse = true
        }
        
        let finalString = resultString.replacingOccurrences(of: "\n", with: "")
            .replacingOccurrences(of: "\r", with: "")
            .replacingOccurrences(of: ">", with: "")

        if !finalString.isEmpty {
            print("Data received : \(finalString)")
        }
        
    }
}

I receive the data fine, as long as I send commands one by one (I'm using a table view right now)

The Issue!!!

If I create a loop to send the commands, like following, multiple commands are sent but only one response is received. I can even see my device blinking sending the data.

    while runLoop == true {
        
        // Even If I make it sleep for a second, doesn't wok
        // Thread.sleep(forTimeInterval: 1.0)
        sendBT_Command(theCommand: "0105")
        
    }

Any idea why I can send and receive the responses when using LOOP?

Thanks in advance!

1 Answers

This device has an AT protocol, which suggests its a serial-like characteristic. You're sending the next value before you've received the response confirming the write. iOS sees this as "set value to 1, no set it to 2, no set it to 3" and it may only send 3 in that case. Adding sleep doesn't help at all because that just prevents the message from being sent (you're sleeping the thread that sends the message).

Instead, you need to queue these up into an array, and as you get each response (didUpdateValueFor...), send the next one.

Related