@@ -117,129 +117,199 @@ typedef enum {
117117bool ModemClass::read_by_size_finished (string &rx) {
118118/* -------------------------------------------------------------------------- */
119119 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- }
171120 return rv;
172121}
173122
174123
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+ };
175136
176137/* -------------------------------------------------------------------------- */
177138bool ModemClass::buf_read (const string &prompt, string &data_res) {
178139/* -------------------------------------------------------------------------- */
179140 bool res = false ;
180- bool found = false ;
181-
141+
182142 if (_serial_debug && _debug_level >= 1 ) {
183143 _serial_debug->print (" RAW: " );
184144 }
185145
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+
186153 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 ()) {
189161 char c = _serial->read ();
190- data_res += c;
191-
192162 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);
208177 }
178+ // _serial_debug->print((int)state);
179+ // _serial_debug->print('\n');
209180 }
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;
223292 }
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;
242305 }
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 ;
243313 }
244314 }
245315 }
@@ -248,7 +318,6 @@ bool ModemClass::buf_read(const string &prompt, string &data_res) {
248318 trim (data_res);
249319 }
250320 trim_results = true ;
251- read_by_size = false ;
252321
253322 if (_serial_debug && _debug_level >= 1 ) {
254323 _serial_debug->print (" <-RAW END" );
0 commit comments