@@ -51,18 +51,6 @@ bool ESP8266::startup(int mode)
51
51
52
52
_parser.oob (" +IPD" , this , &ESP8266::_packet_handler);
53
53
54
- _parser.oob (" 0,CONNECT" , this , &ESP8266::_incoming_socket_opened0);
55
- _parser.oob (" 1,CONNECT" , this , &ESP8266::_incoming_socket_opened1);
56
- _parser.oob (" 2,CONNECT" , this , &ESP8266::_incoming_socket_opened2);
57
- _parser.oob (" 3,CONNECT" , this , &ESP8266::_incoming_socket_opened3);
58
- _parser.oob (" 4,CONNECT" , this , &ESP8266::_incoming_socket_opened4);
59
-
60
- _parser.oob (" 0,CLOSED" , this , &ESP8266::_incoming_socket_closed0);
61
- _parser.oob (" 1,CLOSED" , this , &ESP8266::_incoming_socket_closed1);
62
- _parser.oob (" 2,CLOSED" , this , &ESP8266::_incoming_socket_closed2);
63
- _parser.oob (" 3,CLOSED" , this , &ESP8266::_incoming_socket_closed3);
64
- _parser.oob (" 4,CLOSED" , this , &ESP8266::_incoming_socket_closed4);
65
-
66
54
return success;
67
55
}
68
56
@@ -253,6 +241,10 @@ void ESP8266::_packet_handler()
253
241
254
242
int32_t ESP8266::recv (int id, void *data, uint32_t amount)
255
243
{
244
+ bool exit_when_not_found = false ;
245
+
246
+ bool is_incoming_socket = _incoming_socket_status[id];
247
+
256
248
while (true ) {
257
249
// check if any packets are ready for us
258
250
for (struct packet **p = &_packets; *p; p = &(*p)->next ) {
@@ -281,10 +273,37 @@ int32_t ESP8266::recv(int id, void *data, uint32_t amount)
281
273
}
282
274
}
283
275
284
- // Wait for inbound packet
285
- if (!_parser.recv (" OK" )) {
276
+ if (exit_when_not_found) {
286
277
return -1 ;
287
278
}
279
+
280
+ // Here's a problem... recv() blocks for forever, but it might be that the underlying socket closes in the meantime.
281
+ // We know when it happens (due to monitoring the RX IRQ channel)
282
+ // but there's no way of signaling this thread and actually abort the request...
283
+
284
+ if (is_incoming_socket) {
285
+ int timeout = _parser.getTimeout ();
286
+ _parser.setTimeout (1000 );
287
+
288
+ if (!_parser.recv (" OK" )) {
289
+ _parser.setTimeout (timeout);
290
+
291
+ // socket gone
292
+ if (!_incoming_socket_status[id]) return NSAPI_ERROR_NO_SOCKET;
293
+
294
+ // otherwise, just continue trying to get data...
295
+ continue ;
296
+ }
297
+ }
298
+ else {
299
+ // Wait for inbound packet
300
+ if (!_parser.recv (" OK" )) {
301
+ // so this is weird... the message just received by the parser could actually be one of ours (in TCPServer mode)...
302
+ // so do one more pass...
303
+ exit_when_not_found = true ;
304
+ continue ;
305
+ }
306
+ }
288
307
}
289
308
}
290
309
@@ -316,7 +335,7 @@ bool ESP8266::writeable()
316
335
return _serial.writeable ();
317
336
}
318
337
319
- void ESP8266::attach (Callback<void ()> func)
338
+ void ESP8266::attach (Callback<void (int )> func)
320
339
{
321
340
_serial.attach (func);
322
341
}
@@ -335,20 +354,68 @@ bool ESP8266::recv_ap(nsapi_wifi_ap_t *ap)
335
354
336
355
bool ESP8266::bind (const SocketAddress& address)
337
356
{
357
+ // we need an event queue to dispatch from serial RX IRQ -> non-IRQ thread
358
+ event_queue = new EventQueue ();
359
+ event_thread = new Thread (osPriorityNormal, 2048 );
360
+ if (!event_queue || !event_thread) {
361
+ return NSAPI_ERROR_NO_MEMORY;
362
+ }
363
+ event_thread->start (callback (event_queue, &EventQueue::dispatch_forever));
364
+
365
+ // buffer to store RX data in
366
+ rx_buffer = (char *)malloc (1024 );
367
+ rx_ix = 0 ;
368
+ if (!rx_buffer) {
369
+ return NSAPI_ERROR_NO_MEMORY;
370
+ }
371
+
372
+ // clear incoming socket status
373
+ memset (_incoming_socket_status, 0 , sizeof (_incoming_socket_status));
374
+
375
+ // attach to the serial
376
+ _serial.attach (callback (this , &ESP8266::attach_rx));
377
+
378
+ // and start the actual server
338
379
return _parser.send (" AT+CIPSERVER=1,%d" , address.get_port ())
339
380
&& _parser.recv (" OK" );
340
381
}
341
382
342
- void ESP8266::_incoming_socket_opened (int8_t socket_id)
343
- {
344
- printf (" Incoming socket opened %d\n " , socket_id);
383
+ void ESP8266::process_command (char * cmd, size_t size) {
384
+ if (size == 9 /* 0,CONNECT */
385
+ && (cmd[0 ] >= ' 0' && cmd[0 ] <= ' 9' )
386
+ && (cmd[1 ] == ' ,' )
387
+ && (strcmp (&cmd[2 ], " CONNECT" ) == 0 )) {
388
+
389
+ _incoming_socket_status[cmd[0 ] - ' 0' ] = true ;
390
+
391
+ _signalingCallback (ESP8266_SOCKET_CONNECT, cmd[0 ] - ' 0' );
392
+ }
393
+ else if (size == 8 /* 0,CLOSED */
394
+ && (cmd[0 ] >= ' 0' && cmd[0 ] <= ' 9' )
395
+ && (cmd[1 ] == ' ,' )
396
+ && (strcmp (&cmd[2 ], " CLOSED" ) == 0 )) {
345
397
346
- _signalingCallback (ESP8266_SOCKET_CONNECT, socket_id);
398
+ _incoming_socket_status[cmd[0 ] - ' 0' ] = false ;
399
+
400
+ _signalingCallback (ESP8266_SOCKET_CLOSE, cmd[0 ] - ' 0' );
401
+ }
402
+ free (cmd);
347
403
}
348
404
349
- void ESP8266::_incoming_socket_closed (int8_t socket_id)
350
- {
351
- printf (" Incoming socket closed %d\n " , socket_id);
405
+ void ESP8266::attach_rx (int c) {
406
+ // store value in buffer
407
+ rx_buffer[rx_ix] = c;
408
+ rx_buffer[rx_ix + 1 ] = 0 ;
409
+
410
+ if (rx_ix > 0 && c == ' \n ' ) {
411
+ // got a whole command
412
+ char * cmd = (char *)calloc (rx_ix, 1 );
413
+ memcpy (cmd, rx_buffer, rx_ix - 1 );
414
+ event_queue->call (callback (this , &ESP8266::process_command), cmd, rx_ix - 1 );
415
+
416
+ rx_ix = 0 ;
417
+ return ;
418
+ }
352
419
353
- _signalingCallback (ESP8266_SOCKET_CLOSE, socket_id) ;
420
+ rx_ix++ ;
354
421
}
0 commit comments