@@ -28,7 +28,7 @@ command_result net_open(CommandableIf *t)
2828 if (out.find (" +QISTATE: 0" ) != std::string::npos) {
2929 ESP_LOGV (TAG, " %s" , out.data () );
3030 ESP_LOGD (TAG, " Already there" );
31- return command_result::OK ;
31+ return command_result::FAIL ;
3232 } else if (out.empty ()) {
3333 return dce_commands::generic_command (t, " AT+QIACT=1\r " , " OK" , " ERROR" , 150000 );
3434 }
@@ -38,6 +38,8 @@ command_result net_open(CommandableIf *t)
3838command_result net_close (CommandableIf *t)
3939{
4040 ESP_LOGV (TAG, " %s" , __func__ );
41+ dce_commands::generic_command (t, " AT+QICLOSE=0\r " , " OK" , " ERROR" , 10000 );
42+ esp_modem::Task::Delay (1000 );
4143 return dce_commands::generic_command (t, " AT+QIDEACT=1\r " , " OK" , " ERROR" , 40000 );
4244}
4345
@@ -104,103 +106,131 @@ command_result get_ip(CommandableIf *t, std::string &ip)
104106
105107namespace sock_dce {
106108
107- void Listener ::start_sending (size_t len)
109+ void Responder ::start_sending (size_t len)
108110{
109111 data_to_send = len;
110112 send_stat = 0 ;
111113 send_cmd (" AT+QISEND=0," + std::to_string (len) + " \r " );
112114}
113115
114- void Listener ::start_receiving (size_t len)
116+ void Responder ::start_receiving (size_t len)
115117{
116- send_cmd (" AT+QIRD=0," + std::to_string (size ) + " \r " );
118+ send_cmd (" AT+QIRD=0," + std::to_string (len ) + " \r " );
117119}
118120
119- bool Listener ::start_connecting (std::string host, int port)
121+ bool Responder ::start_connecting (std::string host, int port)
120122{
121123 send_cmd (R"( AT+QIOPEN=1,0,"TCP",")" + host + " \" ," + std::to_string (port) + " \r " );
122124 return true ;
123125}
124126
125- Listener::state Listener ::recv (uint8_t *data, size_t len)
127+ Responder::ret Responder ::recv (uint8_t *data, size_t len)
126128{
127- const size_t MIN_MESSAGE = 6 ;
128- const std::string_view head = " +QIRD: " ;
129- auto head_pos = (char *)std::search (data, data + len, head.begin (), head.end ());
130- if (head_pos == nullptr ) {
131- return state::FAIL;
132- }
129+ const int MIN_MESSAGE = 6 ;
130+ size_t actual_len = 0 ;
131+ auto *recv_data = (char *)data;
132+ if (data_to_recv == 0 ) {
133+ const std::string_view head = " +QIRD: " ;
134+ auto head_pos = std::search (recv_data, recv_data + len, head.begin (), head.end ());
135+ if (head_pos == nullptr ) {
136+ return ret::FAIL;
137+ }
133138
134- auto next_nl = (char *)memchr (head_pos + head.size (), ' \n ' , MIN_MESSAGE);
135- if (next_nl == nullptr ) {
136- return state ::FAIL;
137- }
139+ auto next_nl = (char *)memchr (head_pos + head.size (), ' \n ' , MIN_MESSAGE);
140+ if (next_nl == nullptr ) {
141+ return ret ::FAIL;
142+ }
138143
139- size_t actual_len;
140- if (std::from_chars (head_pos + head.size (), next_nl, actual_len).ec == std::errc::invalid_argument) {
141- ESP_LOGE (TAG, " cannot convert" );
142- return state::FAIL;
143- }
144+ if (std::from_chars (head_pos + head.size (), next_nl, actual_len).ec == std::errc::invalid_argument) {
145+ ESP_LOGE (TAG, " cannot convert" );
146+ return ret::FAIL;
147+ }
144148
145- ESP_LOGD (TAG, " Received: actual len=%d" , actual_len);
146- if (actual_len == 0 ) {
147- ESP_LOGD (TAG, " no data received" );
148- return state::FAIL;
149- }
149+ ESP_LOGD (TAG, " Received: actual len=%d" , actual_len);
150+ if (actual_len == 0 ) {
151+ ESP_LOGD (TAG, " no data received" );
152+ return ret::FAIL;
153+ }
154+
155+ if (actual_len > buffer_size) {
156+ ESP_LOGE (TAG, " TOO BIG" );
157+ return ret::FAIL;
158+ }
150159
151- // TODO improve : compare *actual_len* & data size (to be sure that received data is equal to *actual_len*)
152- if (actual_len > size) {
153- ESP_LOGE (TAG, " TOO BIG" );
154- return state::FAIL;
160+ recv_data = next_nl + 1 ;
161+ auto first_data_len = len - (recv_data - (char *)data) /* minus size of the command marker */ ;
162+ if (actual_len > first_data_len) {
163+ ::send (sock, recv_data, first_data_len, 0 );
164+ data_to_recv = actual_len - first_data_len;
165+ return ret::NEED_MORE_DATA;
166+ }
167+ ::send (sock, recv_data, actual_len, 0 );
168+ } else if (data_to_recv > len) { // continue sending
169+ ::send (sock, recv_data, len, 0 );
170+ data_to_recv -= len;
171+ return ret::NEED_MORE_DATA;
172+ } else if (data_to_recv <= len) { // last read -> looking for "OK" marker
173+ ::send (sock, recv_data, data_to_recv, 0 );
174+ actual_len = data_to_recv;
155175 }
156- ::send (sock, next_nl + 1 , actual_len, 0 );
157176
158177 // "OK" after the data
159- auto last_pos = (char *)memchr (next_nl + 1 + actual_len, ' O' , MIN_MESSAGE);
160- if (last_pos == nullptr || last_pos[1 ] != ' K' ) {
161- return state::FAIL;
178+ char *last_pos = nullptr ;
179+ if (actual_len + 1 + 2 /* OK */ > len) {
180+ last_pos = (char *)memchr (recv_data + 1 + actual_len, ' O' , MIN_MESSAGE);
181+ if (last_pos == nullptr || last_pos[1 ] != ' K' ) {
182+ data_to_recv = 0 ;
183+ return ret::FAIL;
184+ }
162185 }
163- if ((char *)data + len - last_pos > MIN_MESSAGE) {
186+ if (last_pos != nullptr && (char *)data + len - last_pos - 2 > MIN_MESSAGE) {
164187 // check for async replies after the Recv header
165188 std::string_view response ((char *)last_pos + 2 /* OK */ , (char *)data + len - last_pos);
166- check_async_replies (response);
189+ check_async_replies (status::RECEIVING, response);
167190 }
168- return state::OK;
191+ // check if some other data?
192+ start_receiving (0 );
193+ data_to_recv = 0 ;
194+ return ret::OK;
169195}
170196
171197
172- Listener::state Listener ::send (uint8_t *data, size_t len)
198+ Responder::ret Responder ::send (uint8_t *data, size_t len)
173199{
174- if (send_stat == 0 ) {
200+ if (send_stat < 3 ) {
175201 if (memchr (data, ' >' , len) == NULL ) {
202+ if (send_stat++ < 2 ) {
203+ return Responder::ret::NEED_MORE_DATA;
204+ }
176205 ESP_LOGE (TAG, " Missed >" );
177- return state ::FAIL;
206+ return ret ::FAIL;
178207 }
179208 auto written = dte->write (&buffer[0 ], data_to_send);
180209 if (written != data_to_send) {
181210 ESP_LOGE (TAG, " written %d (%d)..." , written, len);
182- return state ::FAIL;
211+ return ret ::FAIL;
183212 }
184213 data_to_send = 0 ;
185- send_stat++ ;
214+ send_stat = 3 ;
186215 }
187- return Listener::state ::IN_PROGRESS;
216+ return Responder::ret ::IN_PROGRESS;
188217}
189218
190- Listener::state Listener ::send (std::string_view response)
219+ Responder::ret Responder ::send (std::string_view response)
191220{
192- if (send_stat == 1 ) {
221+ if (send_stat == 3 ) {
193222 if (response.find (" SEND OK" ) != std::string::npos) {
194223 send_cmd (" AT+QISEND=0,0\r " );
195224 send_stat++;
225+ return ret::IN_PROGRESS;
196226 } else if (response.find (" SEND FAIL" ) != std::string::npos) {
197227 ESP_LOGE (TAG, " Sending buffer full" );
198- return state ::FAIL;
228+ return ret ::FAIL;
199229 } else if (response.find (" ERROR" ) != std::string::npos) {
200230 ESP_LOGE (TAG, " Failed to sent" );
201- return state ::FAIL;
231+ return ret ::FAIL;
202232 }
203- } else if (send_stat == 2 ) {
233+ } else if (send_stat == 4 ) {
204234 constexpr std::string_view head = " +QISEND: " ;
205235 if (response.find (head) != std::string::npos) {
206236 // Parsing +QISEND: <total_send_length>,<ackedbytes>,<unackedbytes>
@@ -215,7 +245,7 @@ Listener::state Listener::send(std::string_view response)
215245 size_t value;
216246 if (std::from_chars (response.data (), next_comma, value).ec == std::errc::invalid_argument) {
217247 ESP_LOGE (TAG, " cannot convert" );
218- return state ::FAIL;
248+ return ret ::FAIL;
219249 }
220250
221251 switch (property++) {
@@ -224,49 +254,94 @@ Listener::state Listener::send(std::string_view response)
224254 case 1 : ack = value;
225255 break ;
226256 default :
227- return state ::FAIL;
257+ return ret ::FAIL;
228258 }
229259 response = response.substr (pos + 1 );
230260 }
231261 if (std::from_chars (response.data (), response.data () + pos, unack).ec == std::errc::invalid_argument) {
232- return state ::FAIL;
262+ return ret ::FAIL;
233263 }
234264
235- // TODO improve : need check *total* & *ack* values, or loop (every 5 sec) with 90s or 120s timeout
236265 if (ack < total) {
237- ESP_LOGE (TAG, " all sending data are not ack (missing %d bytes acked)" , (total - ack));
266+ ESP_LOGD (TAG, " all sending data are not ack (missing %d bytes acked)" , (total - ack));
267+ if (total - ack > 64 ) {
268+ ESP_LOGW (TAG, " Need a pause: missing %d bytes acked" , (total - ack));
269+ return ret::NEED_MORE_TIME;
270+ }
238271 }
239- return state::OK;
272+ send_stat = 0 ;
273+ return ret::OK;
240274 } else if (response.find (" ERROR" ) != std::string::npos) {
241275 ESP_LOGE (TAG, " Failed to check sending" );
242- return state ::FAIL;
276+ return ret ::FAIL;
243277 }
244278
245279 }
246- return Listener::state ::IN_PROGRESS;
280+ return Responder::ret ::IN_PROGRESS;
247281}
248282
249- Listener::state Listener ::connect (std::string_view response)
283+ Responder::ret Responder ::connect (std::string_view response)
250284{
251285 if (response.find (" +QIOPEN: 0,0" ) != std::string::npos) {
252286 ESP_LOGI (TAG, " Connected!" );
253- return state ::OK;
287+ return ret ::OK;
254288 }
255289 if (response.find (" ERROR" ) != std::string::npos) {
256290 ESP_LOGE (TAG, " Failed to open" );
257- return state ::FAIL;
291+ return ret ::FAIL;
258292 }
259- return Listener::state ::IN_PROGRESS;
293+ return Responder::ret ::IN_PROGRESS;
260294}
261295
262- void Listener ::check_async_replies (std::string_view &response) const
296+ Responder::ret Responder ::check_async_replies (status state, std::string_view &response)
263297{
264298 ESP_LOGD (TAG, " response %.*s" , static_cast <int >(response.size ()), response.data ());
265299 if (response.find (" +QIURC: \" recv\" ,0" ) != std::string::npos) {
266300 uint64_t data_ready = 1 ;
267301 write (data_ready_fd, &data_ready, sizeof (data_ready));
268302 ESP_LOGD (TAG, " Got data on modem!" );
303+ } else if (response.find (" +QIRD: " ) != std::string::npos) {
304+ static constexpr std::string_view head = " +QIRD: " ;
305+ size_t head_pos = response.find (head);
306+ // Parsing +QIURC: <total_receive_length>,<have_read_length>,<unread_length>
307+ response = response.substr (head_pos + head.size ());
308+ int next_cr = response.find (' \r ' );
309+ if (next_cr != std::string::npos) {
310+ response = response.substr (next_cr - 2 , next_cr);
311+ if (response.find (" ,0" ) != std::string::npos) {
312+ ESP_LOGV (TAG, " Receiving done" );
313+ } else {
314+ uint64_t data_ready = 1 ;
315+ write (data_ready_fd, &data_ready, sizeof (data_ready));
316+ ESP_LOGD (TAG, " Got data on modem!" );
317+ }
318+ }
319+ } else if (response.find (" +QIURC: \" closed\" ,0" ) != std::string::npos) {
320+ return ret::FAIL;
321+ }
322+ if (state == status::SENDING) {
323+ return send (response);
324+ } else if (state == status::CONNECTING) {
325+ return connect (response);
326+ }
327+ return ret::IN_PROGRESS;
328+ }
329+
330+ Responder::ret Responder::process_data (status state, uint8_t *data, size_t len)
331+ {
332+ if (state == status::SENDING) {
333+ return send (data, len);
334+ }
335+ if (state == status::RECEIVING) {
336+ return recv (data, len);
269337 }
338+ return Responder::ret::IN_PROGRESS;
339+ }
340+
341+ status Responder::pending ()
342+ {
343+ send_cmd (" AT+QISEND=0,0\r " );
344+ return status::SENDING;
270345}
271346
272347
0 commit comments