Skip to content

Commit 40a326a

Browse files
[WIP] Improving parse function in modem class
1 parent c78fd2b commit 40a326a

File tree

1 file changed

+173
-104
lines changed

1 file changed

+173
-104
lines changed

libraries/WiFiS3/src/Modem.cpp

+173-104
Original file line numberDiff line numberDiff line change
@@ -117,129 +117,199 @@ typedef enum {
117117
bool 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
/* -------------------------------------------------------------------------- */
177138
bool 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("\nNew State: Command parse");
186+
state = at_parse_state_t::Cmd;
187+
} else if(c == RESULT_OK[0]) { // OK response
188+
_serial_debug->println("\nNew State: OK");
189+
190+
state = at_parse_state_t::Ok;
191+
} else if(c == RESULT_ERROR[0]) { // Error response
192+
_serial_debug->println("\nNew 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("\nNew 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("\nNew 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("\nNew 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("\nNew State: ERROR");
230+
state = at_parse_state_t::Error;
231+
} else if(c == '\r') {
232+
_serial_debug->println("\nNew State: ResWaitLF");
233+
state = at_parse_state_t::ResWaitLF;
234+
} else if(c == '\n') {
235+
_serial_debug->println("\nNew 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("\nNew 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("\nNew 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("\nNew State: OK");
269+
270+
state = at_parse_state_t::Ok;
271+
} else if(c == RESULT_ERROR[0]) { // Error response
272+
_serial_debug->println("\nNew 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

Comments
 (0)