Skip to content

Commit f6880fe

Browse files
committed
Merge pull request #4792 from facchinm/solve_serial_windows
Rework serial ports handling
2 parents 4c901d3 + bf11c7f commit f6880fe

16 files changed

+367
-72
lines changed

app/src/processing/app/Editor.java

+89-9
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ public boolean test(Sketch sketch) {
146146

147147
private int numTools = 0;
148148

149+
public boolean avoidMultipleOperations = false;
150+
149151
private final EditorToolbar toolbar;
150152
// these menus are shared so that they needn't be rebuilt for all windows
151153
// each time a sketch is created, renamed, or moved.
@@ -198,7 +200,7 @@ public boolean test(Sketch sketch) {
198200
private Runnable stopHandler;
199201
Runnable exportHandler;
200202
private Runnable exportAppHandler;
201-
203+
private Runnable timeoutUploadHandler;
202204

203205
public Editor(Base ibase, File file, int[] storedLocation, int[] defaultLocation, Platform platform) throws Exception {
204206
super("Arduino");
@@ -812,6 +814,9 @@ public void actionPerformed(ActionEvent e) {
812814
portMenu = new JMenu(tr("Port"));
813815
populatePortMenu();
814816
toolsMenu.add(portMenu);
817+
item = new JMenuItem(tr("Get Board Info"));
818+
item.addActionListener(e -> handleBoardInfo());
819+
toolsMenu.add(item);
815820
toolsMenu.addSeparator();
816821

817822
base.rebuildProgrammerMenu();
@@ -1661,6 +1666,7 @@ private void resetHandlers() {
16611666
stopHandler = new DefaultStopHandler();
16621667
exportHandler = new DefaultExportHandler();
16631668
exportAppHandler = new DefaultExportAppHandler();
1669+
timeoutUploadHandler = new TimeoutUploadHandler();
16641670
}
16651671

16661672

@@ -1992,6 +1998,7 @@ public void run() {
19921998

19931999
status.unprogress();
19942000
toolbar.deactivateRun();
2001+
avoidMultipleOperations = false;
19952002
}
19962003
}
19972004

@@ -2380,6 +2387,7 @@ synchronized public void handleExport(final boolean usingProgrammer) {
23802387
console.clear();
23812388
status.progress(tr("Uploading to I/O Board..."));
23822389

2390+
new Thread(timeoutUploadHandler).start();
23832391
new Thread(usingProgrammer ? exportAppHandler : exportHandler).start();
23842392
}
23852393

@@ -2419,6 +2427,7 @@ public void run() {
24192427
e.printStackTrace();
24202428
} finally {
24212429
populatePortMenu();
2430+
avoidMultipleOperations = false;
24222431
}
24232432
status.unprogress();
24242433
uploading = false;
@@ -2446,13 +2455,14 @@ private void resumeOrCloseSerialMonitor() {
24462455
}
24472456
}
24482457
try {
2449-
if (serialMonitor != null)
2450-
serialMonitor.resume(boardPort);
2451-
if (boardPort == null) {
2452-
serialMonitor.close();
2453-
handleSerial();
2454-
} else {
2458+
if (serialMonitor != null) {
24552459
serialMonitor.resume(boardPort);
2460+
if (boardPort == null) {
2461+
serialMonitor.close();
2462+
handleSerial();
2463+
} else {
2464+
serialMonitor.resume(boardPort);
2465+
}
24562466
}
24572467
} catch (Exception e) {
24582468
statusError(e);
@@ -2513,6 +2523,7 @@ public void run() {
25132523
} catch (Exception e) {
25142524
e.printStackTrace();
25152525
} finally {
2526+
avoidMultipleOperations = false;
25162527
populatePortMenu();
25172528
}
25182529
status.unprogress();
@@ -2527,6 +2538,20 @@ public void run() {
25272538
}
25282539
}
25292540

2541+
class TimeoutUploadHandler implements Runnable {
2542+
2543+
public void run() {
2544+
try {
2545+
//10 seconds, than reactivate upload functionality and let the programmer pid being killed
2546+
Thread.sleep(1000 * 10);
2547+
if (uploading) {
2548+
avoidMultipleOperations = false;
2549+
}
2550+
} catch (InterruptedException e) {
2551+
// noop
2552+
}
2553+
}
2554+
}
25302555

25312556
public void handleSerial() {
25322557
if(serialPlotter != null) {
@@ -2571,7 +2596,7 @@ public void handleSerial() {
25712596

25722597
// If currently uploading, disable the monitor (it will be later
25732598
// enabled when done uploading)
2574-
if (uploading) {
2599+
if (uploading || avoidMultipleOperations) {
25752600
try {
25762601
serialMonitor.suspend();
25772602
} catch (Exception e) {
@@ -2595,8 +2620,10 @@ public void handleSerial() {
25952620
}
25962621

25972622
try {
2598-
serialMonitor.open();
25992623
serialMonitor.setVisible(true);
2624+
if (!avoidMultipleOperations) {
2625+
serialMonitor.open();
2626+
}
26002627
success = true;
26012628
} catch (ConnectException e) {
26022629
statusError(tr("Unable to connect: is the sketch using the bridge?"));
@@ -2743,6 +2770,59 @@ private void handleBurnBootloader() {
27432770
}).start();
27442771
}
27452772

2773+
private void handleBoardInfo() {
2774+
console.clear();
2775+
2776+
String selectedPort = PreferencesData.get("serial.port");
2777+
List<BoardPort> ports = Base.getDiscoveryManager().discovery();
2778+
2779+
String label = "";
2780+
String vid = "";
2781+
String pid = "";
2782+
String iserial = "";
2783+
String protocol = "";
2784+
boolean found = false;
2785+
2786+
for (BoardPort port : ports) {
2787+
if (port.getAddress().equals(selectedPort)) {
2788+
label = port.getBoardName();
2789+
vid = port.getVID();
2790+
pid = port.getPID();
2791+
iserial = port.getISerial();
2792+
protocol = port.getProtocol();
2793+
found = true;
2794+
break;
2795+
}
2796+
}
2797+
2798+
if (!found) {
2799+
statusNotice(tr("Please select a port to obtain board info"));
2800+
return;
2801+
}
2802+
2803+
if (protocol.equals("network")) {
2804+
statusNotice(tr("Network port, can't obtain info"));
2805+
return;
2806+
}
2807+
2808+
if (vid == null || vid.equals("") || vid.equals("0000")) {
2809+
statusNotice(tr("Native serial port, can't obtain info"));
2810+
return;
2811+
}
2812+
2813+
if (iserial == null || iserial.equals("")) {
2814+
iserial = tr("Upload any sketch to obtain it");
2815+
}
2816+
2817+
if (label == null) {
2818+
label = tr("Unknown board");
2819+
}
2820+
2821+
String infos = I18n.format("BN: {0}\nVID: {1}\nPID: {2}\nSN: {3}", label, vid, pid, iserial);
2822+
JTextArea textArea = new JTextArea(infos);
2823+
2824+
JOptionPane.showMessageDialog(this, textArea, tr("Board Info"), JOptionPane.PLAIN_MESSAGE);
2825+
}
27462826

27472827
/**
27482828
* Handler for File &rarr; Page Setup.

app/src/processing/app/EditorLineStatus.java

+5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public class EditorLineStatus extends JComponent {
5252
String text = "";
5353
String name = "";
5454
String serialport = "";
55+
String serialnumber = "";
5556

5657
public EditorLineStatus() {
5758
background = Theme.getColor("linestatus.bgcolor");
@@ -129,6 +130,10 @@ public void setSerialPort(String serialport) {
129130
this.serialport = serialport;
130131
}
131132

133+
public void setSerialNumber(String serialnumber) {
134+
this.serialnumber = serialnumber;
135+
}
136+
132137
public Dimension getPreferredSize() {
133138
return scale(new Dimension(300, height));
134139
}

app/src/processing/app/EditorToolbar.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,10 @@ public void mousePressed(MouseEvent e) {
341341

342342
switch (sel) {
343343
case RUN:
344-
editor.handleRun(false, editor.presentHandler, editor.runHandler);
344+
if (!editor.avoidMultipleOperations) {
345+
editor.handleRun(false, editor.presentHandler, editor.runHandler);
346+
editor.avoidMultipleOperations = true;
347+
}
345348
break;
346349

347350
// case STOP:
@@ -370,7 +373,11 @@ public void mousePressed(MouseEvent e) {
370373
break;
371374

372375
case EXPORT:
373-
editor.handleExport(e.isShiftDown());
376+
// launch a timeout timer which can reenable to upload button functionality an
377+
if (!editor.avoidMultipleOperations) {
378+
editor.handleExport(e.isShiftDown());
379+
editor.avoidMultipleOperations = true;
380+
}
374381
break;
375382

376383
case SERIAL:

arduino-core/src/cc/arduino/packages/BoardPort.java

+36
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,12 @@ public class BoardPort {
3636
private String address;
3737
private String protocol;
3838
private String boardName;
39+
private String vid;
40+
private String pid;
41+
private String iserial;
3942
private String label;
4043
private final PreferencesMap prefs;
44+
private boolean online;
4145

4246
public BoardPort() {
4347
this.prefs = new PreferencesMap();
@@ -79,4 +83,36 @@ public String getLabel() {
7983
return label;
8084
}
8185

86+
public void setOnlineStatus(boolean online) {
87+
this.online = online;
88+
}
89+
90+
public boolean isOnline() {
91+
return online;
92+
}
93+
94+
public void setVIDPID(String vid, String pid) {
95+
this.vid = vid;
96+
this.pid = pid;
97+
}
98+
99+
public String getVID() {
100+
return vid;
101+
}
102+
103+
public String getPID() {
104+
return pid;
105+
}
106+
107+
public void setISerial(String iserial) {
108+
this.iserial = iserial;
109+
}
110+
public String getISerial() {
111+
return iserial;
112+
}
113+
114+
@Override
115+
public String toString() {
116+
return this.address+"_"+this.vid+"_"+this.pid;
117+
}
82118
}

arduino-core/src/cc/arduino/packages/Discovery.java

+1
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,6 @@ public interface Discovery {
5151
* @return
5252
*/
5353
List<BoardPort> listDiscoveredBoards();
54+
List<BoardPort> listDiscoveredBoards(boolean complete);
5455

5556
}

arduino-core/src/cc/arduino/packages/DiscoveryManager.java

+25-2
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@
4040
public class DiscoveryManager {
4141

4242
private final List<Discovery> discoverers;
43+
private final SerialDiscovery serialDiscoverer = new SerialDiscovery();
44+
private final NetworkDiscovery networkDiscoverer = new NetworkDiscovery();
4345

4446
public DiscoveryManager() {
4547
discoverers = new ArrayList<Discovery>();
46-
discoverers.add(new SerialDiscovery());
47-
discoverers.add(new NetworkDiscovery());
48+
discoverers.add(serialDiscoverer);
49+
discoverers.add(networkDiscoverer);
4850

4951
// Start all discoverers
5052
for (Discovery d : discoverers) {
@@ -69,6 +71,10 @@ public DiscoveryManager() {
6971
Runtime.getRuntime().addShutdownHook(closeHook);
7072
}
7173

74+
public SerialDiscovery getSerialDiscoverer() {
75+
return serialDiscoverer;
76+
}
77+
7278
public List<BoardPort> discovery() {
7379
List<BoardPort> res = new ArrayList<BoardPort>();
7480
for (Discovery d : discoverers) {
@@ -77,6 +83,14 @@ public List<BoardPort> discovery() {
7783
return res;
7884
}
7985

86+
public List<BoardPort> discovery(boolean complete) {
87+
List<BoardPort> res = new ArrayList<BoardPort>();
88+
for (Discovery d : discoverers) {
89+
res.addAll(d.listDiscoveredBoards(complete));
90+
}
91+
return res;
92+
}
93+
8094
public BoardPort find(String address) {
8195
for (BoardPort boardPort : discovery()) {
8296
if (boardPort.getAddress().equals(address)) {
@@ -86,4 +100,13 @@ public BoardPort find(String address) {
86100
return null;
87101
}
88102

103+
public BoardPort find(String address, boolean complete) {
104+
for (BoardPort boardPort : discovery(complete)) {
105+
if (boardPort.getAddress().equals(address)) {
106+
return boardPort;
107+
}
108+
}
109+
return null;
110+
}
111+
89112
}

arduino-core/src/cc/arduino/packages/Uploader.java

+15-2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import java.util.Arrays;
4545
import java.util.Collection;
4646
import java.util.List;
47+
import java.util.concurrent.TimeUnit;
4748

4849
import static processing.app.I18n.tr;
4950

@@ -102,6 +103,9 @@ public String getAuthorizationKey() {
102103
return null;
103104
}
104105

106+
// static field for last executed programmer process ID
107+
static protected Process programmerPid;
108+
105109
protected boolean executeUploadCommand(Collection<String> command) throws Exception {
106110
return executeUploadCommand(command.toArray(new String[command.size()]));
107111
}
@@ -121,11 +125,20 @@ protected boolean executeUploadCommand(String command[]) throws Exception {
121125
System.out.println();
122126
}
123127
Process process = ProcessUtils.exec(command);
128+
programmerPid = process;
124129
new MessageSiphon(process.getInputStream(), this, 100);
125130
new MessageSiphon(process.getErrorStream(), this, 100);
126131

127-
// wait for the process to finish.
128-
result = process.waitFor();
132+
// wait for the process to finish, but not forever
133+
// kill the flasher process after 2 minutes to avoid 100% cpu spinning
134+
if (!process.waitFor(2, TimeUnit.MINUTES)) {
135+
process.destroyForcibly();
136+
}
137+
if (!process.isAlive()) {
138+
result = process.exitValue();
139+
} else {
140+
result = 0;
141+
}
129142
} catch (Exception e) {
130143
e.printStackTrace();
131144
}

0 commit comments

Comments
 (0)