1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.chabala.brick.controllab;
20
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import java.io.IOException;
25 import java.util.concurrent.CountDownLatch;
26 import java.util.concurrent.TimeUnit;
27
28 import static java.nio.charset.StandardCharsets.ISO_8859_1;
29
30
31
32
33 class SerialListener implements SerialPortEventListener {
34
35 private final Logger log = LoggerFactory.getLogger(getClass());
36 private final SerialPort serialPort;
37 private final InputManager inputManager;
38 private final boolean ignoreBadHandshake;
39
40 private boolean handshakeSeen = false;
41 private CountDownLatch handshakeLatch = new CountDownLatch(1);
42 private StringBuilder handshakeBuilder = new StringBuilder();
43
44 SerialListener(SerialPort serialPort, InputManager inputManager) {
45 this.serialPort = serialPort;
46 this.inputManager = inputManager;
47 ignoreBadHandshake = Boolean.valueOf(
48 System.getProperty("brick-control-lab.ignoreBadHandshake", "false"));
49 }
50
51 @Override
52 public boolean isHandshakeSeen() {
53 boolean returnedEarly = false;
54 try {
55 returnedEarly = handshakeLatch.await(1, TimeUnit.SECONDS);
56 } catch (InterruptedException e) {
57 log.error(e.getMessage(), e);
58 Thread.currentThread().interrupt();
59 }
60 return handshakeSeen || returnedEarly;
61 }
62
63 private void setHandshakeSeen() {
64 handshakeSeen = true;
65 handshakeLatch.countDown();
66 handshakeBuilder = null;
67 }
68
69
70 @Override
71 public void serialEventRXCHAR(int availableBytes) {
72 if (!handshakeSeen) {
73 processHandshake(availableBytes);
74 } else {
75 if (availableBytes >= Protocol.FRAME_SIZE) {
76 try {
77 byte[] buffer = serialPort.readBytes(Protocol.FRAME_SIZE);
78 inputManager.processInputSensors(buffer);
79 } catch (IOException e) {
80 log.error(e.getMessage(), e);
81 }
82 }
83 }
84 }
85
86 private void processHandshake(int availableBytes) {
87 try {
88 while (!handshakeSeen && availableBytes > 0) {
89 availableBytes--;
90 handshakeBuilder.append(new String(serialPort.readBytes(1), ISO_8859_1));
91 if (handshakeBuilder.length() >= Protocol.HANDSHAKE_RESPONSE.length()) {
92 String handshake = handshakeBuilder.toString();
93 if (handshake.endsWith(Protocol.HANDSHAKE_RESPONSE)) {
94 log.info("RX <- {}", handshake);
95 setHandshakeSeen();
96 } else {
97 log.error("Bad handshake: {}", handshake);
98 if (ignoreBadHandshake) {
99 setHandshakeSeen();
100 } else {
101 serialPort.close();
102 return;
103 }
104 }
105 }
106 }
107 if (!handshakeSeen) {
108 log.debug("Current handshake: {}", handshakeBuilder);
109 }
110 } catch (IOException e) {
111 log.error(e.getMessage(), e);
112 }
113 }
114 }