@@ -170,207 +170,209 @@ ModemClass::ParseResult ModemClass::buf_read(const string &prompt, string &data_
170
170
unsigned long start_time = millis ();
171
171
while (state != at_parse_state_t ::Completed &&
172
172
state != at_parse_state_t ::ParseError) {
173
+
173
174
if (millis () - start_time > _timeout) {
174
175
res = Timeout;
175
176
break ;
176
177
}
177
178
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);
196
198
}
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 = " " ;
200
225
}
226
+ // if we uncomment this we can force strict response matching
227
+ // else {
228
+ // state = at_parse_state_t::ParseError;
229
+ // }
201
230
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 = " " ;
250
246
}
247
+ state = at_parse_state_t ::Data;
251
248
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
+ }
275
254
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?
283
276
data_res += c;
277
+ }
284
278
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
+ }
293
296
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
+ */
330
329
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
+ }
333
333
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;
349
342
}
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
+ */
350
349
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;
353
356
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;
364
357
if (restart) {
365
358
state = at_parse_state_t ::Begin;
366
359
restart = false ;
367
360
} else {
368
361
state = at_parse_state_t ::Completed;
369
362
}
370
- break ;
371
- case at_parse_state_t ::Completed:
372
- break ;
373
363
}
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 ;
374
376
}
375
377
}
376
378
0 commit comments