-
Notifications
You must be signed in to change notification settings - Fork 3k
platform/ATCmdParser #9592
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Internal Jira reference: https://jira.arm.com/browse/MBOCUSTRIA-828 |
Critiques of the "line by default" from co-worker
Basically: recv handles everything in 1 function vs. 2/3 |
@ARMmbed/mbed-os-wan Fyi Possibly also @kjbracey-arm and @bulislaw / @donatieng |
Some good thoughts here - the It would certainly be nice to not have to install loads of oob handlers for every possible response. That oob facility was added first for actual URCs, and the On line endings, the intent is that any type of line ending (CR, LF, CR+LF, LF+CR) gets normalised automatically to
Not quite clear on this. There must be some termination condition of a greedy match on a stream, right? It's either a delimiter character, or the end of line itself. Are you wanting to terminate and match an incomplete line just on a timeout? |
I had assumed the backwards compatibility was a major factor (as I was writing the set of questions it very quickly became clear that it could be quite difficult to make several of the changes in a backwards compatible manner. Something I didn't think about until putting thoughts on paper so to speak)
This for me has been one of the best changes I've made, although I did figure out the URC/abort thing (again during/after putting thoughts on paper). The difficulty would be what to return from recv when it triggers (is it the same as a timeout?). This could be a relatively simple modification (add one function to set it, one callback to store it, add a call into recv if not NULL, and maybe add a default handler) if treating it the same as a timeout.
I probably miss-understood something in the implementation. Most of my experience is with a very out of date version of the Parser and I was checking issues I found against the current implementation by eye. Looking again, I was likely incorrect :/
I think I used the incorrect wording there (not greedy). Responses can be unterminated and this caused trouble for my greedy implementation until I wrked out what was going on I can't see a reasonable way to do a full line-greedy implementation without breaking backwards compatibility (due largely to how URC handlers are set up). Even with a seperate function, URC's still have to be checked and the recv halted for a matching line. I will see what I can do about cleaning up I2 (recv_match) & I3 (end of command predicate) which can probably avoid any backwards compatibility issues. I4 (no copying/reformatting the recv format / double scanf) is worth exploring but likely has too many edge cases (the best solution is probably a simplified scanf alike function that reports the required information, but that is quite a task) |
It can only trigger if you've requested it it, so there's no backwards compatibility problem with adding new response values if necessary.
Again, how can a response be unterminated? If there's no termination, how do you know the response is complete, and we need to go back to standard parse state? The only possibilities I'm aware of are:
I can't currently think of a case that the parser doesn't handle, or isn't just rather out-of-scope. You've always got the freedom to run your own interpretation code on the stream for a custom termination condition before going back to using the parser. |
@Crzyrndm Shall this issue be closed (no update since the last response) ? |
Uh oh!
There was an error while loading. Please reload this page.
Description
Relevant links:
Into my third usage/re-implementation/derivation of this parser, the following is based on experience in implementation and API consumption. If features are considered desirable, PR('s) may follow.
A little background
I use mbed entirely offline with ARM GCC 7.2/IDE (VS Code mostly). Most mbed classes are not used directly in my code (either wrapped for additional type/lifetime safety or portability, or reimplemented for reduced locking / additional features / simplicity / etc.). ATCmdParser is one of the ones that eventually got reimplemented (twice. In C the second time due to limitations on project tooling)
API
As a user, ATCmdParser was exactly what I needed when I got started. For sending commands I still can't fault the simple printf style approach, the simple "recv" seems to work really well, and it handles URC/OOB messages cleanly.
"recv" is definitely the weak link here though, and for a couple of reasons.
-- How to write a recv call that matches "OK\r\n" or "0\r" (success with verbose on/off on the modems I was targeting). I never did work this one out, you had to write against a single command mode (which isn't that bad, but...)
-- Errors / multiple possible responses. Got an Error instead of an OK when you've got a long timeout command? Requires multiple "abort" URCs to cover the possible responses. Rare but not exactly nice to try and handle.
-- For what reason doesn't it read an entire line before attempting a match? (I'm assuming there is a modem which doesn't put a newline before a large chunk of data in some response).
-- Greedy line simplifies oob handlers IMO (pass the line to the handler instead of the handler having to read the rest of the line) and less likely to accidentally start doing recursive work
-- my workaround was to end the format with "%d%*[\r]" (match int then match and discard '\r'). The '\n' is definitely more obvious, but greedy by default wins for ease of use and minimal surprises.
-- Dead simple fix with a greedy/line by line receiver (check the recv format before checking urc's)
Other minor annoyances
Implementation
Some suggestions from my implementation experience.
-- fixes: some scanf hackery
-- enables: recv overriding registered oob, oobs having to read remainder of line (tempting recursive parsing -> stack overflow)
-- optimsation: single pass for each received line helps when lots of OOBs are registered
-- enables: allowing for multiple responses to be matched successfully
-- callback takes ptr/len for received char array + va_list to scanf into if required (void* is probably better than va_list, but I haven't got around to trying it yet). Int return instead of bool allows the match to be ID'd if required (e.g. was this an error or OK). I've used a zero return to indicate no-match to the [arser but not entirely happy with that yet (I strongly prefer types rather than convention when I can)
-- bool(const char*, int); // return true if the received line indicates "end of command"
-- my check order after receiving a line is: format parameter -> OOBs -> end of command
-- recv returns an enum (match / timeout / eoc) wrapper which converts to bool (true for match only)
Is there interest in taking any of this further?
EDIT
Note that I use Oob and URC interchangably to refer to the same concept (URC is how most modem docs refer to these messages)
Reading through this again, there are two major points/questions that almost everything else becomes a sub-question of
Issue request type
The text was updated successfully, but these errors were encountered: