Skip to content

Commit acb22b5

Browse files
Initial PluggableDiscovery using BoardPort for JSON
1 parent 6901862 commit acb22b5

File tree

1 file changed

+131
-19
lines changed

1 file changed

+131
-19
lines changed

arduino-core/src/cc/arduino/packages/discoverers/PluggableDiscovery.java

Lines changed: 131 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,66 +30,178 @@
3030
package cc.arduino.packages.discoverers;
3131

3232
import java.util.ArrayList;
33+
import java.util.LinkedList;
3334
import java.util.List;
35+
import java.io.InputStream;
36+
import java.io.OutputStream;
3437

3538
import cc.arduino.packages.BoardPort;
3639
import cc.arduino.packages.Discovery;
3740
import processing.app.legacy.PApplet;
3841

42+
import com.fasterxml.jackson.databind.ObjectMapper;
43+
import com.fasterxml.jackson.databind.DeserializationFeature;
44+
import com.fasterxml.jackson.core.JsonFactory;
45+
import com.fasterxml.jackson.core.JsonParser;
46+
3947
public class PluggableDiscovery implements Discovery {
4048

41-
private String discoveryName;
49+
private final String discoveryName;
50+
private final String[] cmd;
51+
private final List<BoardPort> portList;
52+
private Process program=null;
53+
private Thread pollingThread;
4254

4355
public PluggableDiscovery(String discoveryName, String[] cmd) {
56+
this.cmd = cmd;
4457
this.discoveryName = discoveryName;
58+
portList = new LinkedList<>();
4559
System.out.println("Starting: " + PApplet.join(cmd, " "));
4660
}
4761

4862
@Override
4963
public void run() {
50-
// TODO this method is started as a new thread, it will constantly
51-
// communicate with the discovery tool and keep track of the discovered
52-
// port to be returned from listDiscoveredBoard()
64+
// this method is started as a new thread, it will constantly listen
65+
// to the discovery tool and keep track of the discovered ports
5366
try {
5467
start();
55-
while (true) { // TODO: Find a better way to terminate discovery
56-
System.out.println(discoveryName + ": looping...");
57-
Thread.sleep(500);
68+
InputStream input = program.getInputStream();
69+
JsonFactory factory = new JsonFactory();
70+
JsonParser parser = factory.createParser(input);
71+
ObjectMapper mapper = new ObjectMapper();
72+
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
73+
74+
while (program != null && program.isAlive()) {
75+
BoardPort port = mapper.readValue(parser, BoardPort.class);
76+
if (port != null) {
77+
System.out.println(discoveryName + " received json");
78+
//
79+
// TODO: check for START_SYNC not supported, call startPolling()
80+
//
81+
update(port);
82+
}
5883
}
59-
// stop();
84+
System.out.println("thread exit normally");
6085
} catch (InterruptedException e) {
86+
System.out.println("thread exit by interrupt");
6187
e.printStackTrace();
6288
} catch (Exception e) {
89+
System.out.println("thread exit other exception");
6390
e.printStackTrace();
6491
}
92+
try {
93+
stop();
94+
} catch (Exception e) {
95+
}
6596
}
6697

6798
@Override
6899
public void start() throws Exception {
69-
// TODO send a START_SYNC command to the discovery tool
70-
// or fallback to START if not available
100+
System.out.println(discoveryName + ": start");
101+
try {
102+
program = Runtime.getRuntime().exec(cmd);
103+
} catch (Exception e) {
104+
program = null;
105+
return;
106+
}
107+
write("START_SYNC\n");
108+
pollingThread = null;
109+
}
110+
111+
private void startPolling() {
112+
// Discovery tools not supporting START_SYNC require a periodic
113+
// LIST command. A second thread is created to send these
114+
// commands, while the run() thread above listens for the
115+
// discovery tool output.
116+
write("START\n");
117+
Thread pollingThread = new Thread() {
118+
public void run() {
119+
try {
120+
while (program != null && program.isAlive()) {
121+
write("LIST\n");
122+
sleep(2500);
123+
}
124+
} catch (Exception e) {
125+
}
126+
}
127+
};
128+
pollingThread.start();
71129
}
72130

73131
@Override
74132
public void stop() throws Exception {
75-
// TODO send a STOP to the discovery
133+
if (pollingThread != null) {
134+
pollingThread.interrupt();
135+
pollingThread = null;
136+
}
137+
write("STOP\n");
138+
if (program != null) {
139+
program.destroy();
140+
program = null;
141+
}
142+
}
143+
144+
private void write(String command) {
145+
if (program != null && program.isAlive()) {
146+
OutputStream out = program.getOutputStream();
147+
try {
148+
out.write(command.getBytes());
149+
out.flush();
150+
} catch (Exception e) {
151+
}
152+
}
153+
}
154+
155+
private synchronized void update(BoardPort port) {
156+
// Update the list of discovered ports, which may involve
157+
// adding a new port, replacing the info for a previously
158+
// discovered port, or removing a port. This function
159+
// must be synchronized with listDiscoveredBoards(), to
160+
// avoid changing the list while it's being accessed by
161+
// another thread.
162+
String address = port.getAddress();
163+
if (address == null) {
164+
return; // address is required
165+
}
166+
for (BoardPort bp : portList) {
167+
if (address.equals(bp.getAddress())) {
168+
// if address already on the list, discard old info
169+
portList.remove(bp);
170+
}
171+
}
172+
if (port.isOnline()) {
173+
if (port.getLabel() == null) {
174+
// if no label, use address
175+
port.setLabel(address);
176+
}
177+
if (port.getProtocol() == null) {
178+
// if no protocol, assume serial
179+
port.setProtocol("serial");
180+
}
181+
portList.add(port);
182+
}
76183
}
77184

78185
@Override
79-
public List<BoardPort> listDiscoveredBoards() {
80-
// TODO return the ports discovered so far
81-
final List<BoardPort> empty = new ArrayList<>();
82-
return empty;
186+
public synchronized List<BoardPort> listDiscoveredBoards() {
187+
// return the ports discovered so far. Because the list of
188+
// ports may change at any moment, a copy of the list is
189+
// returned for use by the rest of the IDE. This copy
190+
// operation must be synchronized with update() to assure
191+
// a clean copy.
192+
final List<BoardPort> portListCopy = new ArrayList<>();
193+
for (BoardPort bp : portList) {
194+
//portListCopy.add(new BoardPort(bp));
195+
portListCopy.add(bp);
196+
}
197+
return portListCopy;
83198
}
84199

85200
@Override
86201
public List<BoardPort> listDiscoveredBoards(boolean complete) {
87202
// XXX: parameter "complete "is really needed?
88203
// should be checked on all existing discoveries
89-
90-
// TODO
91-
final List<BoardPort> empty = new ArrayList<>();
92-
return empty;
204+
return listDiscoveredBoards();
93205
}
94206

95207
@Override

0 commit comments

Comments
 (0)