@@ -117,129 +117,199 @@ typedef enum {
117
117
bool ModemClass::read_by_size_finished (string &rx) {
118
118
/* -------------------------------------------------------------------------- */
119
119
bool rv = false ;
120
- static bool first_call = true ;
121
- static ReadBySizeSt_t st = IDLE;
122
- static int data_to_be_received = 0 ;
123
- static int data_received = 0 ;
124
- if (first_call) {
125
- first_call = false ;
126
- st = WAIT_FOR_SIZE;
127
- }
128
-
129
- switch (st) {
130
- case IDLE:
131
-
132
- break ;
133
- case WAIT_FOR_SIZE: {
134
- int pos = rx.find (" |" );
135
- int pos_space = rx.find (" " );
136
- if (pos != string::npos && pos_space != string::npos) {
137
- string n = rx.substr (pos_space,pos);
138
- int to_be_rx = atoi (n.c_str ());
139
- if (to_be_rx <= 0 ) {
140
- while ( _serial->available () ){
141
- _serial->read ();
142
- }
143
- rv = true ;
144
- first_call = true ;
145
- st = IDLE;
146
- }
147
- else {
148
- /* add 4 because OK\r\n is always added at the end of data */
149
- data_to_be_received = to_be_rx + 4 ;
150
- data_received = 0 ;
151
- st = WAIT_FOR_DATA;
152
- }
153
- rx.clear ();
154
- }
155
- }
156
- break ;
157
-
158
- case WAIT_FOR_DATA:
159
- data_received++;
160
- if (data_received == data_to_be_received) {
161
- rv = true ;
162
- first_call = true ;
163
- st = IDLE;
164
- }
165
- break ;
166
-
167
- default :
168
- st = IDLE;
169
- break ;
170
- }
171
120
return rv;
172
121
}
173
122
174
123
124
+ enum class at_parse_state_t {
125
+ Begin,
126
+ Cmd,
127
+ Data,
128
+ Sized,
129
+ ResWaitLF,
130
+ Res,
131
+ Error,
132
+ ParseError,
133
+ Ok,
134
+ Completed,
135
+ };
175
136
176
137
/* -------------------------------------------------------------------------- */
177
138
bool ModemClass::buf_read (const string &prompt, string &data_res) {
178
139
/* -------------------------------------------------------------------------- */
179
140
bool res = false ;
180
- bool found = false ;
181
-
141
+
182
142
if (_serial_debug && _debug_level >= 1 ) {
183
143
_serial_debug->print (" RAW: " );
184
144
}
185
145
146
+ at_parse_state_t state = at_parse_state_t ::Begin;
147
+ std::string commandName;
148
+
149
+ unsigned int sized_read_size = 0 ;
150
+ unsigned int sized_read_count = 0 ;
151
+ unsigned int result_parse = 1 ;
152
+
186
153
unsigned long start_time = millis ();
187
- while ((millis () - start_time < _timeout) && !found){
188
- while ( _serial->available () ){
154
+ while (state != at_parse_state_t ::Completed) {
155
+ if (millis () - start_time > _timeout) {
156
+ _serial_debug->println (" Timeout" );
157
+ break ;
158
+ }
159
+
160
+ while (_serial->available ()) {
189
161
char c = _serial->read ();
190
- data_res += c;
191
-
192
162
if (_serial_debug && _debug_level >= 1 ) {
193
- _serial_debug->print (c);
194
- }
195
-
196
-
197
- if (read_by_size) {
198
- if (read_by_size_finished (data_res)) {
199
- found = true ;
200
- read_by_size = false ;
201
- res = true ;
202
- if (data_res.size () > 0 ) {
203
- data_res = data_res.substr (0 , data_res.length () - (sizeof (RESULT_OK) - 1 ));
204
- }
205
- else {
206
- break ;
207
- }
163
+ // _serial_debug->print(c);
164
+
165
+ if (c == ' \n ' ) {
166
+ _serial_debug->print (" <LF>" );
167
+ } else if (c == ' \r ' ) {
168
+ _serial_debug->print (" <CR>" );
169
+ } else if (c == ' ' ) {
170
+ _serial_debug->print (" <SP>" );
171
+ } else if (c < ' ' ) {
172
+ _serial_debug->print (" <" );
173
+ _serial_debug->print ((int )c);
174
+ _serial_debug->print (" >" );
175
+ } else {
176
+ _serial_debug->print (c);
208
177
}
178
+ // _serial_debug->print((int)state);
179
+ // _serial_debug->print('\n');
209
180
}
210
- else {
211
- if (string::npos != data_res.rfind (RESULT_DATA)) {
212
- found = true ;
213
- data_res = data_res.substr (0 , data_res.length () - (sizeof (RESULT_DATA) - 1 ));
214
- if (prompt != DO_NOT_CHECK_CMD) {
215
- if (removeAtBegin (data_res, prompt)) {
216
- res = true ;
217
- }
218
- }
219
- else {
220
- res = true ;
221
- }
222
- break ;
181
+
182
+ switch (state) {
183
+ case at_parse_state_t ::Begin:
184
+ if (c == ' +' ) {
185
+ _serial_debug->println (" \n New State: Command parse" );
186
+ state = at_parse_state_t ::Cmd;
187
+ } else if (c == RESULT_OK[0 ]) { // OK response
188
+ _serial_debug->println (" \n New State: OK" );
189
+
190
+ state = at_parse_state_t ::Ok;
191
+ } else if (c == RESULT_ERROR[0 ]) { // Error response
192
+ _serial_debug->println (" \n New State: Error" );
193
+
194
+ state = at_parse_state_t ::Error;
195
+ } else {
196
+ state = at_parse_state_t ::ParseError;
197
+ }
198
+
199
+ break ;
200
+ case at_parse_state_t ::Cmd:
201
+
202
+ if (c == ' :' || c == ' =' ) {
203
+ // TODO verify command is matching prompt
204
+ // _serial_debug->print("\"\nData: \"");
205
+ _serial_debug->println (" \n New State: Data parse" );
206
+
207
+ state = at_parse_state_t ::Data;
208
+ } else { // avoid the first ' ' space
209
+ // _serial_debug->print(c);
210
+ commandName += c; // TODO verify command name
211
+ }
212
+
213
+ break ;
214
+ case at_parse_state_t ::Data:
215
+ if (c == ' |' ) { // sized read, the previous parameter is the length
216
+ _serial_debug->print (" \n New State: Sized " );
217
+
218
+ state = at_parse_state_t ::Sized;
219
+ sized_read_size = atoi (data_res.c_str ());
220
+ _serial_debug->println (sized_read_size);
221
+ data_res.clear ();
222
+ } else if (c == ' \r ' && data_res == " OK" ) { // FIXME
223
+ result_parse = 3 ;
224
+
225
+ _serial_debug->println (" \n New State: OK" );
226
+ state = at_parse_state_t ::Ok;
227
+ } else if (c == ' \r ' && data_res == " ERROR" ) { // FIXME
228
+ result_parse = 6 ;
229
+ _serial_debug->println (" \n New State: ERROR" );
230
+ state = at_parse_state_t ::Error;
231
+ } else if (c == ' \r ' ) {
232
+ _serial_debug->println (" \n New State: ResWaitLF" );
233
+ state = at_parse_state_t ::ResWaitLF;
234
+ } else if (c == ' \n ' ) {
235
+ _serial_debug->println (" \n New State: RES" );
236
+
237
+ state = at_parse_state_t ::Res;
238
+ } else if (c != ' ' ) { // FIXME should space be eliminated?
239
+ data_res += c;
240
+ }
241
+
242
+ break ;
243
+ case at_parse_state_t ::Sized:
244
+ data_res += c;
245
+
246
+ _serial_debug->print (sized_read_count);
247
+ _serial_debug->print (" , " );
248
+ _serial_debug->print (sized_read_size);
249
+
250
+ if (++sized_read_count == sized_read_size) {
251
+ _serial_debug->println (" \n New State: RES" );
252
+ state = at_parse_state_t ::Res;
253
+ // do not consume another character, but parse the current one instead
254
+ continue ;
255
+ }
256
+ break ;
257
+ case at_parse_state_t ::ResWaitLF:
258
+ if (c == ' \n ' ) {
259
+ _serial_debug->println (" \n New State: RES" );
260
+ state = at_parse_state_t ::Res;
261
+ } else {
262
+ _serial_debug->println (" A" );
263
+ state = at_parse_state_t ::ParseError;
264
+ }
265
+ break ;
266
+ case at_parse_state_t ::Res:
267
+ if (c == RESULT_OK[0 ]) { // OK response
268
+ _serial_debug->println (" \n New State: OK" );
269
+
270
+ state = at_parse_state_t ::Ok;
271
+ } else if (c == RESULT_ERROR[0 ]) { // Error response
272
+ _serial_debug->println (" \n New State: Error" );
273
+
274
+ state = at_parse_state_t ::Error;
275
+ }
276
+ // else {
277
+ // state = at_parse_state_t::ParseError;
278
+ // // do not consume another character
279
+ // continue;
280
+ // }
281
+ break ;
282
+ case at_parse_state_t ::Ok: // Conusme the buffer abd verify that it contains "K"
283
+ res = true ;
284
+
285
+ if (c != RESULT_OK[result_parse++]) {
286
+ _serial_debug->println (" C" );
287
+ state = at_parse_state_t ::ParseError;
288
+ }
289
+
290
+ if (result_parse >= strlen (RESULT_OK)) {
291
+ state = at_parse_state_t ::Completed;
223
292
}
224
- else if (string::npos != data_res.rfind (RESULT_OK)){
225
- found = true ;
226
- data_res = data_res.substr (0 , data_res.length () - (sizeof (RESULT_OK) - 1 ) );
227
- if (prompt != DO_NOT_CHECK_CMD) {
228
- if (removeAtBegin (data_res, prompt)) {
229
- res = true ;
230
- }
231
- }
232
- else {
233
- res = true ;
234
- }
235
- break ;
236
- }
237
- else if (string::npos != data_res.rfind (RESULT_ERROR)) {
238
- found = true ;
239
- data_res.substr (0 , data_res.length () - (sizeof (RESULT_ERROR) - 1 ));
240
- res = false ;
241
- break ;
293
+ break ;
294
+ case at_parse_state_t ::Error: // Conusme the buffer and verify that it contains "RROR"
295
+ res = false ;
296
+
297
+ if (c != RESULT_ERROR[result_parse++]) {
298
+ _serial_debug->println (" D" );
299
+
300
+ state = at_parse_state_t ::ParseError;
301
+ }
302
+
303
+ if (result_parse >= strlen (RESULT_ERROR)) {
304
+ state = at_parse_state_t ::Completed;
242
305
}
306
+ break ;
307
+ case at_parse_state_t ::ParseError:
308
+ _serial_debug->println (" ParseError" );
309
+ state = at_parse_state_t ::Completed;
310
+ break ;
311
+ case at_parse_state_t ::Completed:
312
+ break ;
243
313
}
244
314
}
245
315
}
@@ -248,7 +318,6 @@ bool ModemClass::buf_read(const string &prompt, string &data_res) {
248
318
trim (data_res);
249
319
}
250
320
trim_results = true ;
251
- read_by_size = false ;
252
321
253
322
if (_serial_debug && _debug_level >= 1 ) {
254
323
_serial_debug->print (" <-RAW END" );
0 commit comments