ORSSerialPort icon indicating copy to clipboard operation
ORSSerialPort copied to clipboard

Responses with newlines

Open bgueth opened this issue 6 years ago • 1 comments

I got a device which sends upon a request things like this:

     0; 18.10.13; 10:40:24;        2; 00:51:33;      150;     2804;     1465;        2.96;       -7.87;       14.72;Bernhard Gueth  ;Advance Alpha 5 ;not-set     \r\n         
     1; 18.10.12; 11:35:32;        2; 01:54:59;      132;     2845;      644;        5.63;       -6.31;       16.37;Bernhard Gueth  ;Advance Alpha 5 ;not-set     \r\n
Done\r\n

Every line is 168 bytes long. If I send a request to the device using the following code

func sendCommand(_ : String) {

        let commandString = String("ACT_20_00\r\n");
        let command = commandString.data(using: .ascii)!
        let responseExp = try? NSRegularExpression(pattern: "(.{166}\r\n)*Done\r\n", options: .caseInsensitive)
        let responseDescriptor = ORSSerialPacketDescriptor(regularExpression: responseExp!, maximumPacketLength: 1024, userInfo: nil)
        let request = ORSSerialRequest(
            dataToSend: command,
            userInfo: FlytecRequestType.readFlightbook.rawValue,
            timeoutInterval: 1.5,
            responseDescriptor: responseDescriptor)
        self.serialPort?.send(request)
}

I'd expect it to read the all the lines. However, when i inspect the response

func serialPort(_ serialPort: ORSSerialPort, didReceiveResponse responseData: Data, to request: ORSSerialRequest) {
        guard let receivedString = String(data: responseData, encoding: .ascii) else {
            return
        }
        print(receivedString)
}

I only get the last line ("Done\r\n") but not the other ones. I fiddled out, that it seems, that responses are broken up when a newline is read from the device. Is there any way to work around this?

With best regards

Bernhard

bgueth avatar Jan 22 '19 09:01 bgueth

Hi Bernhard, I'd have to dig into this with some tests. I would think what you've got should work. Not sure why it's not. I wonder what happens if you try:

func sendCommand(_ string: String) {

    let commandString = "ACT_20_00\r\n"
    let command = commandString.data(using: .ascii)!
    let responseDescriptor = ORSSerialPacketDescriptor(maximumPacketLength: 169, userInfo: nil) { (data) -> Bool in
        guard let string = data.flatMap({ String(data: $0, encoding: .ascii) }) else { return false }
        return string.count >= 168 && string.hasSuffix("\n")
    }
    let request = ORSSerialRequest(
        dataToSend: command,
        userInfo: FlytecRequestType.readFlightbook.rawValue,
        timeoutInterval: 1.5,
        responseDescriptor: responseDescriptor)
    self.serialPort?.send(request)
}

Here, instead of relying on the RegEx to work, I explicitly check the length and end delimiter for the incoming packet. The caveat here is that you won't get the "Done\r\n" because of the length requirement, but if you need that, you could of course special case it in the packet evaluator closure.

(Incidentally, this will become easier when I implement #89.)

armadsen avatar Feb 07 '19 17:02 armadsen