FactbirdHQ / atat

no_std crate for parsing AT commands
Apache License 2.0
109 stars 29 forks source link

Response without leading '\r\n' is eaten by echo detector #184

Open ijager opened 9 months ago

ijager commented 9 months ago

I have encountered a specific case in which the response on a command is removed by digest::parser::echo:

"\r\n+QMTRECV: 1,0\r\n+QMTRECV: 1,0,\"t/dev/commands\",16,\"{\"cmd\": \"blink\"}\"\r\n\r\nOK\r\n"

First \r\n+QMTRECV: 1,0\r\n is correctly detected as an URC.

Then we are left with:

"+QMTRECV: 1,0,\"t/dev/commands\",16,\"{\"cmd\": \"blink\"}\"\r\n\r\nOK\r\n"

Because there is no \r\n in front, this will not be detected as an URC, which is good because this is actually a response to the "AT+QMTRECV" command.

However digest::parser::echo parses this as an echo and removes it. echo removes everything up to the next newline.

If I change echo to detect an echo as: `AT.....\r\n' like this:

/// Matches a full AT echo. Eg `AT+USORD=3,16\r\n`
    pub fn echo(buf: &[u8]) -> IResult<&[u8], &[u8]> {
        if buf.len() < 2 {
            return Ok((buf, &[]));
        }
        // commented out original
        // recognize(nom::bytes::complete::take_until("\r\n"))(buf)

        recognize(
            tuple((
                tag("AT"),
                nom::bytes::complete::take_until("\r\n")
            ))
        )(buf)

    }

Then I can parse my input, however there are 2 failing tests:

test digest::test::mm_echo_removal ... FAILED
test digest::test::garbage_cleanup ... FAILED

It seems like the echo parser also has the responsibility to remove garbage. That means the issue comes down to differentiating between a response without a leading '\r\n' and garbage. But that is very hard when echo is on. Because for example with prompts there is no leading AT.

ijager commented 9 months ago

I feel like the only way to properly deal with this is if the Digester knows about the commands that have been sent so you can specifically match echoes (if enabled) and expect a specific response.

b-zee commented 8 months ago

I am seeing an issue that is related. I noticed a URC missing in my software. This is transmitted by a ESP-01 (empty lines are \r\n):

AT+CIPSEND=0,3

OK
> 
Recv 3 bytes

SEND OK
0,CLOSED

(3 bytes are sent with CIPSEND after >, which aren't echoed by the ESP.)

The last 0,CLOSED\r\n is shown as 'echo or whitespace'. I assume the bug is the same as @ijager describes. The \r\nSEND OK\r\n is properly processed, but then 0,CLOSED\r\n remains.

This means the parser will only get to parse \r\n:

let mut digester = AtDigester::<MyParser>::new();
let (res, bytes) = digester.digest(b"0,CLOSED\r\n"); // `MyParser::parser` is passed only b"\r\n"