34
34
import org .slf4j .LoggerFactory ;
35
35
import java .io .IOException ;
36
36
import java .text .MessageFormat ;
37
+ import java .util .ArrayDeque ;
37
38
import java .util .ArrayList ;
38
39
import java .util .Collections ;
39
40
import java .util .HashMap ;
40
41
import java .util .HashSet ;
41
42
import java .util .LinkedHashSet ;
42
43
import java .util .List ;
43
44
import java .util .Map ;
45
+ import java .util .Queue ;
44
46
import java .util .Set ;
45
47
import java .util .concurrent .Executors ;
46
48
import java .util .concurrent .atomic .AtomicBoolean ;
@@ -60,6 +62,7 @@ public class FirmataDevice implements IODevice {
60
62
private FiniteStateMachine protocol ;
61
63
private final Set <IODeviceEventListener > listeners = Collections .synchronizedSet (new LinkedHashSet <IODeviceEventListener >());
62
64
private final List <FirmataPin > pins = Collections .synchronizedList (new ArrayList <FirmataPin >());
65
+ private final Queue <Byte > pinStateRequestQueue = new ArrayDeque <>();
63
66
private final AtomicBoolean started = new AtomicBoolean (false );
64
67
private final AtomicBoolean ready = new AtomicBoolean (false );
65
68
private final AtomicInteger initializedPins = new AtomicInteger (0 );
@@ -92,6 +95,7 @@ public FirmataDevice(TransportInterface transport) {
92
95
protocol .addHandler (PROTOCOL_MESSAGE , onProtocolReceive );
93
96
protocol .addHandler (FIRMWARE_MESSAGE , onFirmwareReceive );
94
97
protocol .addHandler (PIN_CAPABILITIES_MESSAGE , onCapabilitiesReceive );
98
+ protocol .addHandler (PIN_CAPABILITIES_FINISHED , onCapabilitiesFinished );
95
99
protocol .addHandler (PIN_STATE , onPinStateReceive );
96
100
protocol .addHandler (ANALOG_MAPPING_MESSAGE , onAnalogMappingReceive );
97
101
protocol .addHandler (ANALOG_MESSAGE_RESPONSE , onAnalogMessageReceive );
@@ -367,24 +371,29 @@ public void accept(Event event) {
367
371
initializedPins .incrementAndGet ();
368
372
} else {
369
373
// if the pin supports some modes, we ask for its current mode and value
374
+ pinStateRequestQueue .add (pinId );
375
+ }
376
+ }
377
+ };
378
+
379
+ /**
380
+ * Called when capabilities for the all the pins are received.
381
+ */
382
+ private final Consumer <Event > onCapabilitiesFinished = new Consumer <Event >() {
383
+ @ Override
384
+ public void accept (Event t ) {
385
+ if (initializedPins .get () == pins .size ()) {
386
+ try {
387
+ sendMessage (FirmataMessageFactory .ANALOG_MAPPING_REQUEST );
388
+ } catch (IOException e ) {
389
+ LOGGER .error ("Error requesting of the analog mapping" , e );
390
+ }
391
+ } else {
392
+ byte pinId = pinStateRequestQueue .poll ();
370
393
try {
371
394
sendMessage (FirmataMessageFactory .pinStateRequest (pinId ));
372
- if (pinId > 0 && pinId % 14 == 0 ) { // 14 pins on Arduino UNO get initialized without delay
373
- /* If the pin count is too high (i.e. Arduino Mega), then
374
- * too many firmata requests in a row can overflow the
375
- * device's serial input buffer.
376
- * One solution is to yield a little time between
377
- * requests to allow the device to respond. The response
378
- * may then safely sit in the host's much larger serial
379
- * input buffer until it is dealt with by onPinStateReceive
380
- */
381
- Thread .sleep (100 );
382
- }
383
395
} catch (IOException ex ) {
384
- LOGGER .error (String .format ("Error requesting state of pin %d" , pin .getIndex ()), ex );
385
- } catch (InterruptedException ex ) {
386
- Thread .currentThread ().interrupt ();
387
- LOGGER .warn ("Delay between capability requests was interrupted" , ex );
396
+ LOGGER .error (String .format ("Error requesting state of pin %d" , pinId ), ex );
388
397
}
389
398
}
390
399
}
@@ -404,11 +413,19 @@ public void accept(Event event) {
404
413
} else {
405
414
pin .updateValue ((Long ) event .getBodyItem (PIN_VALUE ));
406
415
}
416
+ if (!pinStateRequestQueue .isEmpty ()) {
417
+ byte pid = pinStateRequestQueue .poll ();
418
+ try {
419
+ sendMessage (FirmataMessageFactory .pinStateRequest (pid )); // request the following pin state
420
+ } catch (IOException ex ) {
421
+ LOGGER .error (String .format ("Error requesting state of pin %d" , pid ), ex );
422
+ }
423
+ }
407
424
if (initializedPins .incrementAndGet () == pins .size ()) {
408
425
try {
409
426
sendMessage (FirmataMessageFactory .ANALOG_MAPPING_REQUEST );
410
427
} catch (IOException e ) {
411
- LOGGER .error ("Error on request analog mapping" , e );
428
+ LOGGER .error ("Error requesting of the analog mapping" , e );
412
429
}
413
430
}
414
431
}
0 commit comments