@@ -170,207 +170,209 @@ ModemClass::ParseResult ModemClass::buf_read(const string &prompt, string &data_
170170 unsigned long start_time = millis ();
171171 while (state != at_parse_state_t ::Completed &&
172172 state != at_parse_state_t ::ParseError) {
173+
173174 if (millis () - start_time > _timeout) {
174175 res = Timeout;
175176 break ;
176177 }
177178
178- while (_serial->available () &&
179- state != at_parse_state_t ::Completed &&
180- state != at_parse_state_t ::ParseError) {
181- char c = _serial->read ();
182- if (_serial_debug && _debug_level >= 1 ) {
183- if (c == ' \n ' ) {
184- _serial_debug->print (" <LF>" );
185- } else if (c == ' \r ' ) {
186- _serial_debug->print (" <CR>" );
187- } else if (c == ' ' ) {
188- _serial_debug->print (" <SP>" );
189- } else if (c < ' ' ) {
190- _serial_debug->print (" <" );
191- _serial_debug->print ((int )c);
192- _serial_debug->print (" >" );
193- } else {
194- _serial_debug->print (c);
195- }
179+ if (!_serial->available ()) {
180+ // if there is nothing available, go to the beginning of the cycle
181+ continue ;
182+ }
183+
184+ char c = _serial->read ();
185+ if (_serial_debug && _debug_level >= 1 ) {
186+ if (c == ' \n ' ) {
187+ _serial_debug->print (" <LF>" );
188+ } else if (c == ' \r ' ) {
189+ _serial_debug->print (" <CR>" );
190+ } else if (c == ' ' ) {
191+ _serial_debug->print (" <SP>" );
192+ } else if (c < ' ' ) {
193+ _serial_debug->print (" <" );
194+ _serial_debug->print ((int )c);
195+ _serial_debug->print (" >" );
196+ } else {
197+ _serial_debug->print (c);
196198 }
197- if (_serial_debug && _debug_level >= 3 ) {
198- _serial_debug->print (" State " );
199- _serial_debug->println ((int )state);
199+ }
200+ if (_serial_debug && _debug_level >= 3 ) {
201+ _serial_debug->print (" State " );
202+ _serial_debug->println ((int )state);
203+ }
204+
205+ switch (state) {
206+ case at_parse_state_t ::Begin:
207+ /*
208+ * In this state we wait for a '+' character, which will mark the beginning of a response
209+ * or the status response code "ERROR<CR><LF>" or "OK<CR><LF>"
210+ * we need to consume the available buffer if it doesn't match the expected response,
211+ * in order to avoiding dealing with previous responses which were not parsed successfully
212+ */
213+
214+ if (c == ' +' ) {
215+ commandName += c; // prompt includes also '+'
216+ state = at_parse_state_t ::Cmd;
217+ } else if (c == RESULT_OK[result_parse]) { // FIXME this should also account for following characters
218+ state = at_parse_state_t ::Ok;
219+ result_parse++;
220+ } else if (c == RESULT_ERROR[result_parse]) { // FIXME this should also account for following characters
221+ state = at_parse_state_t ::Error;
222+ result_parse++;
223+ } else {
224+ data_res = " " ;
200225 }
226+ // if we uncomment this we can force strict response matching
227+ // else {
228+ // state = at_parse_state_t::ParseError;
229+ // }
201230
202- switch (state) {
203- case at_parse_state_t ::Begin:
204- /*
205- * In this state we wait for a '+' character, which will mark the beginning of a response
206- * or the status response code "ERROR<CR><LF>" or "OK<CR><LF>"
207- * we need to consume the available buffer if it doesn't match the expected response,
208- * in order to avoiding dealing with previous responses which were not parsed successfully
209- */
210-
211- if (c == ' +' ) {
212- commandName += c; // prompt includes also '+'
213- state = at_parse_state_t ::Cmd;
214- } else if (c == RESULT_OK[result_parse]) { // FIXME this should also account for following characters
215- state = at_parse_state_t ::Ok;
216- result_parse++;
217- } else if (c == RESULT_ERROR[result_parse]) { // FIXME this should also account for following characters
218- state = at_parse_state_t ::Error;
219- result_parse++;
220- } else {
221- data_res = " " ;
222- }
223- // if we uncomment this we can force strict response matching
224- // else {
225- // state = at_parse_state_t::ParseError;
226- // }
227-
228- break ;
229- case at_parse_state_t ::Cmd:
230- /*
231- * In this state we parse the command prompt and wait for either ':' or '=' characters
232- * in order to go the next state
233- */
234-
235- if (c == ' :' || c == ' =' ) {
236- commandName += c; // prompt includes also ':'
237-
238- if (prompt != DO_NOT_CHECK_CMD && commandName != prompt) {
239- // the response we got is not the one we were expecting, parse the wrong response till the end
240- // and start the parse of the next response
241- restart = true ;
242- commandName = " " ;
243- }
244- state = at_parse_state_t ::Data;
245-
246- data_res = " " ;
247- // state = at_parse_state_t::Data;
248- } else if (c != ' ' ) { // FIXME should we keep the space?
249- commandName += c;
231+ break ;
232+ case at_parse_state_t ::Cmd:
233+ /*
234+ * In this state we parse the command prompt and wait for either ':' or '=' characters
235+ * in order to go the next state
236+ */
237+
238+ if (c == ' :' || c == ' =' ) {
239+ commandName += c; // prompt includes also ':'
240+
241+ if (prompt != DO_NOT_CHECK_CMD && commandName != prompt) {
242+ // the response we got is not the one we were expecting, parse the wrong response till the end
243+ // and start the parse of the next response
244+ restart = true ;
245+ commandName = " " ;
250246 }
247+ state = at_parse_state_t ::Data;
251248
252- break ;
253- case at_parse_state_t ::Data:
254- /*
255- * In this state we parse response parameters and push them into data_res
256- * in case multiple parameters separated by ',' are sent, they will be present in data_res
257- * - if we encounter <CR> we need to wait for <LF>
258- * - if we encounter <LF> we need to parse the response status
259- * - if we encounter '|', the next token will contain binary sized data, the current value in
260- * in data_res contains the length of the next token
261- */
262-
263- if (c == ' |' ) { // sized read, the previous parameter is the length
264- state = at_parse_state_t ::Sized;
265-
266- sized_read_size = atoi (data_res.c_str ());
267- data_res.clear ();
268- } else if (c == ' \r ' ) {
269- state = at_parse_state_t ::ResWaitLF;
270- } else if (c == ' \n ' ) {
271- state = at_parse_state_t ::Res;
272- } else if (c != ' ' ) { // FIXME should we keep the space?
273- data_res += c;
274- }
249+ data_res = " " ;
250+ // state = at_parse_state_t::Data;
251+ } else if (c != ' ' ) { // FIXME should we keep the space?
252+ commandName += c;
253+ }
275254
276- break ;
277- case at_parse_state_t ::Sized:
278- /*
279- * In this state we collect exactly sized_read_size characters into data_res
280- * when we consume all of them we go into Result parse state, where we supposedly
281- * wait for 'OK'
282- */
255+ break ;
256+ case at_parse_state_t ::Data:
257+ /*
258+ * In this state we parse response parameters and push them into data_res
259+ * in case multiple parameters separated by ',' are sent, they will be present in data_res
260+ * - if we encounter <CR> we need to wait for <LF>
261+ * - if we encounter <LF> we need to parse the response status
262+ * - if we encounter '|', the next token will contain binary sized data, the current value in
263+ * in data_res contains the length of the next token
264+ */
265+
266+ if (c == ' |' ) { // sized read, the previous parameter is the length
267+ state = at_parse_state_t ::Sized;
268+
269+ sized_read_size = atoi (data_res.c_str ());
270+ data_res.clear ();
271+ } else if (c == ' \r ' ) {
272+ state = at_parse_state_t ::ResWaitLF;
273+ } else if (c == ' \n ' ) {
274+ state = at_parse_state_t ::Res;
275+ } else if (c != ' ' ) { // FIXME should we keep the space?
283276 data_res += c;
277+ }
284278
285- if (++sized_read_count == sized_read_size) {
286- state = at_parse_state_t ::Res;
287- }
288- break ;
289- case at_parse_state_t ::ResWaitLF:
290- if (c == ' \n ' ) {
291- state = at_parse_state_t ::Res;
292- }
279+ break ;
280+ case at_parse_state_t ::Sized:
281+ /*
282+ * In this state we collect exactly sized_read_size characters into data_res
283+ * when we consume all of them we go into Result parse state, where we supposedly
284+ * wait for 'OK'
285+ */
286+ data_res += c;
287+
288+ if (++sized_read_count == sized_read_size) {
289+ state = at_parse_state_t ::Res;
290+ }
291+ break ;
292+ case at_parse_state_t ::ResWaitLF:
293+ if (c == ' \n ' ) {
294+ state = at_parse_state_t ::Res;
295+ }
293296
294- /*
295- * break is volountary not present, to cover for cases where the response status is in the
296- * following form: '...<CR>OK<CR><LF>' '<CR>ERROR<CR><LF>'
297- */
298- case at_parse_state_t ::Res:
299- /*
300- * In this state we wait for either an 'O' or an 'E', in order to get an 'OK<CR><LF>'
301- * or 'ERROR<CR><LF>'
302- */
303-
304- if (data_res == " OK" ) { // FIXME make it constant
305- res = Ok;
306- state = at_parse_state_t ::Completed;
307- } else if (data_res == " ERROR" ) { // FIXME make it constant
308- res = Error;
309- state = at_parse_state_t ::Completed;
310- } if (c == RESULT_OK[0 ]) { // OK response
311- state = at_parse_state_t ::Ok;
312- result_parse = 1 ;
313- } else if (c == RESULT_ERROR[0 ]) { // Error response
314- state = at_parse_state_t ::Error;
315- result_parse = 1 ;
316- }
317- // if we uncomment this we can force strict response matching
318- // else {
319- // state = at_parse_state_t::ParseError;
320- // }
321- break ;
322- case at_parse_state_t ::Ok:
323- /*
324- * In this state we want to match the exact 'K<CR><LF>' response
325- */
326-
327- if (c != RESULT_OK[result_parse++]) {
328- state = at_parse_state_t ::ParseError;
329- }
297+ /*
298+ * break is volountary not present, to cover for cases where the response status is in the
299+ * following form: '...<CR>OK<CR><LF>' '<CR>ERROR<CR><LF>'
300+ */
301+ case at_parse_state_t ::Res:
302+ /*
303+ * In this state we wait for either an 'O' or an 'E', in order to get an 'OK<CR><LF>'
304+ * or 'ERROR<CR><LF>'
305+ */
306+
307+ if (data_res == " OK" ) { // FIXME make it constant
308+ res = Ok;
309+ state = at_parse_state_t ::Completed;
310+ } else if (data_res == " ERROR" ) { // FIXME make it constant
311+ res = Error;
312+ state = at_parse_state_t ::Completed;
313+ } if (c == RESULT_OK[0 ]) { // OK response
314+ state = at_parse_state_t ::Ok;
315+ result_parse = 1 ;
316+ } else if (c == RESULT_ERROR[0 ]) { // Error response
317+ state = at_parse_state_t ::Error;
318+ result_parse = 1 ;
319+ }
320+ // if we uncomment this we can force strict response matching
321+ // else {
322+ // state = at_parse_state_t::ParseError;
323+ // }
324+ break ;
325+ case at_parse_state_t ::Ok:
326+ /*
327+ * In this state we want to match the exact 'K<CR><LF>' response
328+ */
330329
331- if (result_parse == strlen (RESULT_OK)) {
332- res = Ok;
330+ if (c != RESULT_OK[result_parse++]) {
331+ state = at_parse_state_t ::ParseError;
332+ }
333333
334- if (restart) {
335- state = at_parse_state_t ::Begin;
336- restart = false ;
337- } else {
338- state = at_parse_state_t ::Completed;
339- }
340- }
341- break ;
342- case at_parse_state_t ::Error:
343- /*
344- * In this state we want to match the exact 'RROR<CR><LF>' response
345- */
346-
347- if (c != RESULT_ERROR[result_parse++]) {
348- state = at_parse_state_t ::ParseError;
334+ if (result_parse == strlen (RESULT_OK)) {
335+ res = Ok;
336+
337+ if (restart) {
338+ state = at_parse_state_t ::Begin;
339+ restart = false ;
340+ } else {
341+ state = at_parse_state_t ::Completed;
349342 }
343+ }
344+ break ;
345+ case at_parse_state_t ::Error:
346+ /*
347+ * In this state we want to match the exact 'RROR<CR><LF>' response
348+ */
350349
351- if (result_parse == strlen (RESULT_ERROR)) {
352- res = Error;
350+ if (c != RESULT_ERROR[result_parse++]) {
351+ state = at_parse_state_t ::ParseError;
352+ }
353+
354+ if (result_parse == strlen (RESULT_ERROR)) {
355+ res = Error;
353356
354- if (restart) {
355- state = at_parse_state_t ::Begin;
356- restart = false ;
357- } else {
358- state = at_parse_state_t ::Completed;
359- }
360- }
361- break ;
362- case at_parse_state_t ::ParseError:
363- res = ParseError;
364357 if (restart) {
365358 state = at_parse_state_t ::Begin;
366359 restart = false ;
367360 } else {
368361 state = at_parse_state_t ::Completed;
369362 }
370- break ;
371- case at_parse_state_t ::Completed:
372- break ;
373363 }
364+ break ;
365+ case at_parse_state_t ::ParseError:
366+ res = ParseError;
367+ if (restart) {
368+ state = at_parse_state_t ::Begin;
369+ restart = false ;
370+ } else {
371+ state = at_parse_state_t ::Completed;
372+ }
373+ break ;
374+ case at_parse_state_t ::Completed:
375+ break ;
374376 }
375377 }
376378
0 commit comments