Skip to content

Commit 7186213

Browse files
committed
Slightly changed pluggable discovery json parsing
The json input is now parsed into a JsonTree that can probed for the 'eventType' node value so we can understand the type of message to decode to.
1 parent 349af4b commit 7186213

File tree

2 files changed

+137
-66
lines changed

2 files changed

+137
-66
lines changed

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

Lines changed: 129 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -29,36 +29,43 @@
2929

3030
package cc.arduino.packages.discoverers;
3131

32-
import java.util.ArrayList;
33-
import java.util.LinkedList;
34-
import java.util.List;
32+
import static processing.app.I18n.format;
33+
3534
import java.io.InputStream;
3635
import java.io.OutputStream;
36+
import java.util.ArrayList;
37+
import java.util.List;
3738

38-
import cc.arduino.packages.BoardPort;
39-
import cc.arduino.packages.Discovery;
40-
import processing.app.legacy.PApplet;
41-
42-
import com.fasterxml.jackson.databind.ObjectMapper;
43-
import com.fasterxml.jackson.databind.DeserializationFeature;
39+
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
40+
import com.fasterxml.jackson.annotation.PropertyAccessor;
4441
import com.fasterxml.jackson.core.JsonFactory;
4542
import com.fasterxml.jackson.core.JsonParser;
46-
import com.fasterxml.jackson.annotation.PropertyAccessor;
47-
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
43+
import com.fasterxml.jackson.core.JsonProcessingException;
44+
import com.fasterxml.jackson.databind.DeserializationFeature;
45+
import com.fasterxml.jackson.databind.JsonNode;
46+
import com.fasterxml.jackson.databind.ObjectMapper;
47+
48+
import cc.arduino.packages.BoardPort;
49+
import cc.arduino.packages.Discovery;
50+
import processing.app.PreferencesData;
51+
import processing.app.helpers.StringUtils;
4852

4953
public class PluggableDiscovery implements Discovery {
5054

5155
private final String discoveryName;
5256
private final String[] cmd;
53-
private final List<BoardPort> portList;
57+
private final List<BoardPort> portList = new ArrayList<>();
5458
private Process program=null;
5559
private Thread pollingThread;
5660

61+
private void debug(String x) {
62+
if (PreferencesData.getBoolean("discovery.debug"))
63+
System.out.println(discoveryName + ": " + x);
64+
}
65+
5766
public PluggableDiscovery(String discoveryName, String[] cmd) {
5867
this.cmd = cmd;
5968
this.discoveryName = discoveryName;
60-
portList = new LinkedList<>();
61-
System.out.println(discoveryName + ": Starting: " + PApplet.join(cmd, " "));
6269
}
6370

6471
@Override
@@ -76,30 +83,23 @@ public void run() {
7683
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
7784

7885
while (program != null && program.isAlive()) {
79-
PluggableDiscoveryMessage msg = mapper.readValue(parser, PluggableDiscoveryMessage.class);
80-
if (msg != null) {
81-
System.out.println(discoveryName + ": received json: " + msg.getPrefs());
82-
String event = msg.getEventType();
83-
if (event != null) {
84-
if (event.equals("Error: START_SYNC not supported")) {
85-
if (pollingThread == null) {
86-
startPolling();
87-
}
88-
} else {
89-
if (event.equals("add")) {
90-
msg.searchMatchingBoard();
91-
}
92-
update(msg);
93-
}
86+
JsonNode tree = mapper.readTree(parser);
87+
if (tree == null) {
88+
if (program != null && program.isAlive()) {
89+
System.err.println(format("{0}: Invalid json message", discoveryName));
9490
}
91+
break;
9592
}
93+
debug("Received json: " + tree);
94+
95+
processJsonNode(mapper, tree);
9696
}
97-
System.out.println(discoveryName + ": thread exit normally");
97+
debug("thread exit normally");
9898
} catch (InterruptedException e) {
99-
System.out.println(discoveryName + ": thread exit by interrupt");
99+
debug("thread exit by interrupt");
100100
e.printStackTrace();
101101
} catch (Exception e) {
102-
System.out.println(discoveryName + ": thread exit other exception");
102+
debug("thread exit other exception");
103103
e.printStackTrace();
104104
}
105105
try {
@@ -108,15 +108,89 @@ public void run() {
108108
}
109109
}
110110

111+
private void processJsonNode(ObjectMapper mapper, JsonNode node) {
112+
JsonNode eventTypeNode = node.get("eventType");
113+
if (eventTypeNode == null) {
114+
System.err.println(format("{0}: Invalid message, missing eventType", discoveryName));
115+
return;
116+
}
117+
118+
switch (eventTypeNode.asText()) {
119+
case "error":
120+
try {
121+
PluggableDiscoveryMessage msg = mapper.treeToValue(node, PluggableDiscoveryMessage.class);
122+
debug("error: " + msg.getMessage());
123+
if (msg.getMessage().contains("START_SYNC")) {
124+
startPolling();
125+
}
126+
} catch (JsonProcessingException e) {
127+
e.printStackTrace();
128+
}
129+
return;
130+
131+
case "list":
132+
JsonNode portsNode = node.get("ports");
133+
if (portsNode == null) {
134+
System.err.println(format("{0}: Invalid message, missing ports list", discoveryName));
135+
return;
136+
}
137+
if (!portsNode.isArray()) {
138+
System.err.println(format("{0}: Invalid message, ports list should be an array", discoveryName));
139+
return;
140+
}
141+
142+
portList.clear();
143+
portsNode.forEach(portNode -> {
144+
try {
145+
BoardPort port = mapper.treeToValue(portNode, BoardPort.class);
146+
port.searchMatchingBoard();
147+
addOrUpdate(port);
148+
} catch (JsonProcessingException e) {
149+
System.err.println(format("{0}: Invalid BoardPort message", discoveryName));
150+
e.printStackTrace();
151+
}
152+
});
153+
return;
154+
155+
// Messages for SYNC updates
156+
157+
case "add":
158+
try {
159+
BoardPort port = mapper.treeToValue(node, BoardPort.class);
160+
port.searchMatchingBoard();
161+
addOrUpdate(port);
162+
} catch (JsonProcessingException e) {
163+
System.err.println(format("{0}: Invalid BoardPort message", discoveryName));
164+
e.printStackTrace();
165+
}
166+
return;
167+
168+
case "remove":
169+
try {
170+
BoardPort port = mapper.treeToValue(node, BoardPort.class);
171+
remove(port);
172+
} catch (JsonProcessingException e) {
173+
System.err.println(format("{0}: Invalid BoardPort message", discoveryName));
174+
e.printStackTrace();
175+
}
176+
return;
177+
178+
default:
179+
debug("Invalid event: " + eventTypeNode.asText());
180+
return;
181+
}
182+
}
183+
111184
@Override
112185
public void start() throws Exception {
113-
System.out.println(discoveryName + ": start");
114186
try {
187+
debug("Starting: " + StringUtils.join(cmd, " "));
115188
program = Runtime.getRuntime().exec(cmd);
116189
} catch (Exception e) {
117190
program = null;
118191
return;
119192
}
193+
debug("START_SYNC");
120194
write("START_SYNC\n");
121195
pollingThread = null;
122196
}
@@ -126,11 +200,13 @@ private void startPolling() {
126200
// LIST command. A second thread is created to send these
127201
// commands, while the run() thread above listens for the
128202
// discovery tool output.
203+
debug("START");
129204
write("START\n");
130205
Thread pollingThread = new Thread() {
131206
public void run() {
132207
try {
133208
while (program != null && program.isAlive()) {
209+
debug("LIST");
134210
write("LIST\n");
135211
sleep(2500);
136212
}
@@ -165,37 +241,32 @@ private void write(String command) {
165241
}
166242
}
167243

168-
private synchronized void update(PluggableDiscoveryMessage port) {
244+
private synchronized void addOrUpdate(BoardPort port) {
169245
// Update the list of discovered ports, which may involve
170246
// adding a new port, replacing the info for a previously
171247
// discovered port, or removing a port. This function
172248
// must be synchronized with listDiscoveredBoards(), to
173249
// avoid changing the list while it's being accessed by
174250
// another thread.
175251
String address = port.getAddress();
176-
if (address == null) return; // address required for "add" & "remove"
177-
for (BoardPort bp : portList) {
178-
if (address.equals(bp.getAddress())) {
179-
// if address already on the list, discard old info
180-
portList.remove(bp);
181-
}
182-
}
183-
if (port.getEventType().equals("add")) {
184-
if (port.getLabel() == null) {
185-
// if no label, use address & name, or just address if no name
186-
String name = port.getBoardName();
187-
if (name == null) {
188-
port.setLabel(address);
189-
} else {
190-
port.setLabel(address + " (" + name + ")");
191-
}
192-
}
193-
if (port.getProtocol() == null) {
194-
// if no protocol, assume serial
195-
port.setProtocol("serial");
196-
}
197-
portList.add(port);
252+
if (address == null)
253+
return; // address required for "add" & "remove"
254+
255+
// if address already on the list, discard old info
256+
portList.removeIf(bp -> address.equals(bp.getAddress()));
257+
258+
// if no label, use address
259+
if (port.getLabel() == null) {
260+
port.setLabel(address);
198261
}
262+
portList.add(port);
263+
}
264+
265+
private synchronized void remove(BoardPort port) {
266+
String address = port.getAddress();
267+
if (address == null)
268+
return; // address required for "add" & "remove"
269+
portList.removeIf(bp -> address.equals(bp.getAddress()));
199270
}
200271

201272
@Override
@@ -205,18 +276,14 @@ public synchronized List<BoardPort> listDiscoveredBoards() {
205276
// returned for use by the rest of the IDE. This copy
206277
// operation must be synchronized with update() to assure
207278
// a clean copy.
208-
final List<BoardPort> portListCopy = new ArrayList<>();
209-
for (BoardPort bp : portList) {
210-
portListCopy.add(new BoardPort(bp));
211-
}
212-
return portListCopy;
279+
return new ArrayList<>(portList);
213280
}
214281

215282
@Override
216283
public List<BoardPort> listDiscoveredBoards(boolean complete) {
217284
// XXX: parameter "complete "is really needed?
218285
// should be checked on all existing discoveries
219-
return listDiscoveredBoards();
286+
return new ArrayList<>(portList);
220287
}
221288

222289
@Override

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,16 @@
2828
*/
2929

3030
package cc.arduino.packages.discoverers;
31-
import cc.arduino.packages.BoardPort;
3231

33-
public class PluggableDiscoveryMessage extends BoardPort {
34-
private String eventType; // "add", "remove", "Error: START_SYNC not supported"
32+
public class PluggableDiscoveryMessage {
33+
private String eventType; // "add", "remove", "error"
34+
private String message; // optional message, e.g. "START_SYNC not supported"
35+
3536
public String getEventType() {
3637
return eventType;
3738
}
38-
}
3939

40+
public String getMessage() {
41+
return message;
42+
}
43+
}

0 commit comments

Comments
 (0)