Merge pull request #4792 from facchinm/solve_serial_windows

Rework serial ports handling
This commit is contained in:
Martino Facchin 2016-04-06 18:03:45 +02:00
commit f6880fe617
16 changed files with 369 additions and 74 deletions

View File

@ -146,6 +146,8 @@ public class Editor extends JFrame implements RunnerListener {
private int numTools = 0; private int numTools = 0;
public boolean avoidMultipleOperations = false;
private final EditorToolbar toolbar; private final EditorToolbar toolbar;
// these menus are shared so that they needn't be rebuilt for all windows // these menus are shared so that they needn't be rebuilt for all windows
// each time a sketch is created, renamed, or moved. // each time a sketch is created, renamed, or moved.
@ -198,7 +200,7 @@ public class Editor extends JFrame implements RunnerListener {
private Runnable stopHandler; private Runnable stopHandler;
Runnable exportHandler; Runnable exportHandler;
private Runnable exportAppHandler; private Runnable exportAppHandler;
private Runnable timeoutUploadHandler;
public Editor(Base ibase, File file, int[] storedLocation, int[] defaultLocation, Platform platform) throws Exception { public Editor(Base ibase, File file, int[] storedLocation, int[] defaultLocation, Platform platform) throws Exception {
super("Arduino"); super("Arduino");
@ -812,6 +814,9 @@ public class Editor extends JFrame implements RunnerListener {
portMenu = new JMenu(tr("Port")); portMenu = new JMenu(tr("Port"));
populatePortMenu(); populatePortMenu();
toolsMenu.add(portMenu); toolsMenu.add(portMenu);
item = new JMenuItem(tr("Get Board Info"));
item.addActionListener(e -> handleBoardInfo());
toolsMenu.add(item);
toolsMenu.addSeparator(); toolsMenu.addSeparator();
base.rebuildProgrammerMenu(); base.rebuildProgrammerMenu();
@ -1661,6 +1666,7 @@ public class Editor extends JFrame implements RunnerListener {
stopHandler = new DefaultStopHandler(); stopHandler = new DefaultStopHandler();
exportHandler = new DefaultExportHandler(); exportHandler = new DefaultExportHandler();
exportAppHandler = new DefaultExportAppHandler(); exportAppHandler = new DefaultExportAppHandler();
timeoutUploadHandler = new TimeoutUploadHandler();
} }
@ -1992,6 +1998,7 @@ public class Editor extends JFrame implements RunnerListener {
status.unprogress(); status.unprogress();
toolbar.deactivateRun(); toolbar.deactivateRun();
avoidMultipleOperations = false;
} }
} }
@ -2380,6 +2387,7 @@ public class Editor extends JFrame implements RunnerListener {
console.clear(); console.clear();
status.progress(tr("Uploading to I/O Board...")); status.progress(tr("Uploading to I/O Board..."));
new Thread(timeoutUploadHandler).start();
new Thread(usingProgrammer ? exportAppHandler : exportHandler).start(); new Thread(usingProgrammer ? exportAppHandler : exportHandler).start();
} }
@ -2419,6 +2427,7 @@ public class Editor extends JFrame implements RunnerListener {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
populatePortMenu(); populatePortMenu();
avoidMultipleOperations = false;
} }
status.unprogress(); status.unprogress();
uploading = false; uploading = false;
@ -2446,13 +2455,14 @@ public class Editor extends JFrame implements RunnerListener {
} }
} }
try { try {
if (serialMonitor != null) if (serialMonitor != null) {
serialMonitor.resume(boardPort);
if (boardPort == null) {
serialMonitor.close();
handleSerial();
} else {
serialMonitor.resume(boardPort); serialMonitor.resume(boardPort);
if (boardPort == null) {
serialMonitor.close();
handleSerial();
} else {
serialMonitor.resume(boardPort);
}
} }
} catch (Exception e) { } catch (Exception e) {
statusError(e); statusError(e);
@ -2513,6 +2523,7 @@ public class Editor extends JFrame implements RunnerListener {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
avoidMultipleOperations = false;
populatePortMenu(); populatePortMenu();
} }
status.unprogress(); status.unprogress();
@ -2527,6 +2538,20 @@ public class Editor extends JFrame implements RunnerListener {
} }
} }
class TimeoutUploadHandler implements Runnable {
public void run() {
try {
//10 seconds, than reactivate upload functionality and let the programmer pid being killed
Thread.sleep(1000 * 10);
if (uploading) {
avoidMultipleOperations = false;
}
} catch (InterruptedException e) {
// noop
}
}
}
public void handleSerial() { public void handleSerial() {
if(serialPlotter != null) { if(serialPlotter != null) {
@ -2571,7 +2596,7 @@ public class Editor extends JFrame implements RunnerListener {
// If currently uploading, disable the monitor (it will be later // If currently uploading, disable the monitor (it will be later
// enabled when done uploading) // enabled when done uploading)
if (uploading) { if (uploading || avoidMultipleOperations) {
try { try {
serialMonitor.suspend(); serialMonitor.suspend();
} catch (Exception e) { } catch (Exception e) {
@ -2595,8 +2620,10 @@ public class Editor extends JFrame implements RunnerListener {
} }
try { try {
serialMonitor.open();
serialMonitor.setVisible(true); serialMonitor.setVisible(true);
if (!avoidMultipleOperations) {
serialMonitor.open();
}
success = true; success = true;
} catch (ConnectException e) { } catch (ConnectException e) {
statusError(tr("Unable to connect: is the sketch using the bridge?")); statusError(tr("Unable to connect: is the sketch using the bridge?"));
@ -2743,6 +2770,59 @@ public class Editor extends JFrame implements RunnerListener {
}).start(); }).start();
} }
private void handleBoardInfo() {
console.clear();
String selectedPort = PreferencesData.get("serial.port");
List<BoardPort> ports = Base.getDiscoveryManager().discovery();
String label = "";
String vid = "";
String pid = "";
String iserial = "";
String protocol = "";
boolean found = false;
for (BoardPort port : ports) {
if (port.getAddress().equals(selectedPort)) {
label = port.getBoardName();
vid = port.getVID();
pid = port.getPID();
iserial = port.getISerial();
protocol = port.getProtocol();
found = true;
break;
}
}
if (!found) {
statusNotice(tr("Please select a port to obtain board info"));
return;
}
if (protocol.equals("network")) {
statusNotice(tr("Network port, can't obtain info"));
return;
}
if (vid == null || vid.equals("") || vid.equals("0000")) {
statusNotice(tr("Native serial port, can't obtain info"));
return;
}
if (iserial == null || iserial.equals("")) {
iserial = tr("Upload any sketch to obtain it");
}
if (label == null) {
label = tr("Unknown board");
}
String infos = I18n.format("BN: {0}\nVID: {1}\nPID: {2}\nSN: {3}", label, vid, pid, iserial);
JTextArea textArea = new JTextArea(infos);
JOptionPane.showMessageDialog(this, textArea, tr("Board Info"), JOptionPane.PLAIN_MESSAGE);
}
/** /**
* Handler for File &rarr; Page Setup. * Handler for File &rarr; Page Setup.

View File

@ -52,6 +52,7 @@ public class EditorLineStatus extends JComponent {
String text = ""; String text = "";
String name = ""; String name = "";
String serialport = ""; String serialport = "";
String serialnumber = "";
public EditorLineStatus() { public EditorLineStatus() {
background = Theme.getColor("linestatus.bgcolor"); background = Theme.getColor("linestatus.bgcolor");
@ -129,6 +130,10 @@ public class EditorLineStatus extends JComponent {
this.serialport = serialport; this.serialport = serialport;
} }
public void setSerialNumber(String serialnumber) {
this.serialnumber = serialnumber;
}
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
return scale(new Dimension(300, height)); return scale(new Dimension(300, height));
} }

View File

@ -341,7 +341,10 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
switch (sel) { switch (sel) {
case RUN: case RUN:
editor.handleRun(false, editor.presentHandler, editor.runHandler); if (!editor.avoidMultipleOperations) {
editor.handleRun(false, editor.presentHandler, editor.runHandler);
editor.avoidMultipleOperations = true;
}
break; break;
// case STOP: // case STOP:
@ -370,7 +373,11 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
break; break;
case EXPORT: case EXPORT:
editor.handleExport(e.isShiftDown()); // launch a timeout timer which can reenable to upload button functionality an
if (!editor.avoidMultipleOperations) {
editor.handleExport(e.isShiftDown());
editor.avoidMultipleOperations = true;
}
break; break;
case SERIAL: case SERIAL:

View File

@ -36,8 +36,12 @@ public class BoardPort {
private String address; private String address;
private String protocol; private String protocol;
private String boardName; private String boardName;
private String vid;
private String pid;
private String iserial;
private String label; private String label;
private final PreferencesMap prefs; private final PreferencesMap prefs;
private boolean online;
public BoardPort() { public BoardPort() {
this.prefs = new PreferencesMap(); this.prefs = new PreferencesMap();
@ -79,4 +83,36 @@ public class BoardPort {
return label; return label;
} }
public void setOnlineStatus(boolean online) {
this.online = online;
}
public boolean isOnline() {
return online;
}
public void setVIDPID(String vid, String pid) {
this.vid = vid;
this.pid = pid;
}
public String getVID() {
return vid;
}
public String getPID() {
return pid;
}
public void setISerial(String iserial) {
this.iserial = iserial;
}
public String getISerial() {
return iserial;
}
@Override
public String toString() {
return this.address+"_"+this.vid+"_"+this.pid;
}
} }

View File

@ -51,5 +51,6 @@ public interface Discovery {
* @return * @return
*/ */
List<BoardPort> listDiscoveredBoards(); List<BoardPort> listDiscoveredBoards();
List<BoardPort> listDiscoveredBoards(boolean complete);
} }

View File

@ -40,11 +40,13 @@ import static processing.app.I18n.tr;
public class DiscoveryManager { public class DiscoveryManager {
private final List<Discovery> discoverers; private final List<Discovery> discoverers;
private final SerialDiscovery serialDiscoverer = new SerialDiscovery();
private final NetworkDiscovery networkDiscoverer = new NetworkDiscovery();
public DiscoveryManager() { public DiscoveryManager() {
discoverers = new ArrayList<Discovery>(); discoverers = new ArrayList<Discovery>();
discoverers.add(new SerialDiscovery()); discoverers.add(serialDiscoverer);
discoverers.add(new NetworkDiscovery()); discoverers.add(networkDiscoverer);
// Start all discoverers // Start all discoverers
for (Discovery d : discoverers) { for (Discovery d : discoverers) {
@ -69,6 +71,10 @@ public class DiscoveryManager {
Runtime.getRuntime().addShutdownHook(closeHook); Runtime.getRuntime().addShutdownHook(closeHook);
} }
public SerialDiscovery getSerialDiscoverer() {
return serialDiscoverer;
}
public List<BoardPort> discovery() { public List<BoardPort> discovery() {
List<BoardPort> res = new ArrayList<BoardPort>(); List<BoardPort> res = new ArrayList<BoardPort>();
for (Discovery d : discoverers) { for (Discovery d : discoverers) {
@ -77,6 +83,14 @@ public class DiscoveryManager {
return res; return res;
} }
public List<BoardPort> discovery(boolean complete) {
List<BoardPort> res = new ArrayList<BoardPort>();
for (Discovery d : discoverers) {
res.addAll(d.listDiscoveredBoards(complete));
}
return res;
}
public BoardPort find(String address) { public BoardPort find(String address) {
for (BoardPort boardPort : discovery()) { for (BoardPort boardPort : discovery()) {
if (boardPort.getAddress().equals(address)) { if (boardPort.getAddress().equals(address)) {
@ -86,4 +100,13 @@ public class DiscoveryManager {
return null; return null;
} }
public BoardPort find(String address, boolean complete) {
for (BoardPort boardPort : discovery(complete)) {
if (boardPort.getAddress().equals(address)) {
return boardPort;
}
}
return null;
}
} }

View File

@ -44,6 +44,7 @@ import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import static processing.app.I18n.tr; import static processing.app.I18n.tr;
@ -102,6 +103,9 @@ public abstract class Uploader implements MessageConsumer {
return null; return null;
} }
// static field for last executed programmer process ID
static protected Process programmerPid;
protected boolean executeUploadCommand(Collection<String> command) throws Exception { protected boolean executeUploadCommand(Collection<String> command) throws Exception {
return executeUploadCommand(command.toArray(new String[command.size()])); return executeUploadCommand(command.toArray(new String[command.size()]));
} }
@ -121,11 +125,20 @@ public abstract class Uploader implements MessageConsumer {
System.out.println(); System.out.println();
} }
Process process = ProcessUtils.exec(command); Process process = ProcessUtils.exec(command);
programmerPid = process;
new MessageSiphon(process.getInputStream(), this, 100); new MessageSiphon(process.getInputStream(), this, 100);
new MessageSiphon(process.getErrorStream(), this, 100); new MessageSiphon(process.getErrorStream(), this, 100);
// wait for the process to finish. // wait for the process to finish, but not forever
result = process.waitFor(); // kill the flasher process after 2 minutes to avoid 100% cpu spinning
if (!process.waitFor(2, TimeUnit.MINUTES)) {
process.destroyForcibly();
}
if (!process.isAlive()) {
result = process.exitValue();
} else {
result = 0;
}
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -67,6 +67,13 @@ public class NetworkDiscovery implements Discovery, ServiceListener, cc.arduino.
} }
} }
@Override
public List<BoardPort> listDiscoveredBoards(boolean complete) {
synchronized (reachableBoardPorts) {
return new LinkedList<>(reachableBoardPorts);
}
}
public void setReachableBoardPorts(List<BoardPort> newReachableBoardPorts) { public void setReachableBoardPorts(List<BoardPort> newReachableBoardPorts) {
synchronized (reachableBoardPorts) { synchronized (reachableBoardPorts) {
this.reachableBoardPorts.clear(); this.reachableBoardPorts.clear();

View File

@ -41,6 +41,7 @@ public class SerialDiscovery implements Discovery {
private Timer serialBoardsListerTimer; private Timer serialBoardsListerTimer;
private final List<BoardPort> serialBoardPorts; private final List<BoardPort> serialBoardPorts;
private SerialBoardsLister serialBoardsLister = new SerialBoardsLister(this);;
public SerialDiscovery() { public SerialDiscovery() {
this.serialBoardPorts = new LinkedList<>(); this.serialBoardPorts = new LinkedList<>();
@ -48,26 +49,45 @@ public class SerialDiscovery implements Discovery {
@Override @Override
public List<BoardPort> listDiscoveredBoards() { public List<BoardPort> listDiscoveredBoards() {
return getSerialBoardPorts(); return getSerialBoardPorts(false);
} }
private List<BoardPort> getSerialBoardPorts() { public List<BoardPort> listDiscoveredBoards(boolean complete) {
synchronized (serialBoardPorts) { return getSerialBoardPorts(complete);
return new LinkedList<>(serialBoardPorts); }
}
private List<BoardPort> getSerialBoardPorts(boolean complete) {
if (complete) {
return new LinkedList<>(serialBoardPorts);
}
List<BoardPort> onlineBoardPorts = new LinkedList<>();
for (BoardPort port : serialBoardPorts) {
if (port.isOnline() == true) {
onlineBoardPorts.add(port);
}
}
return onlineBoardPorts;
} }
public void setSerialBoardPorts(List<BoardPort> newSerialBoardPorts) { public void setSerialBoardPorts(List<BoardPort> newSerialBoardPorts) {
synchronized (serialBoardPorts) {
serialBoardPorts.clear(); serialBoardPorts.clear();
serialBoardPorts.addAll(newSerialBoardPorts); serialBoardPorts.addAll(newSerialBoardPorts);
}
} }
public void forceRefresh() {
serialBoardsLister.retriggerDiscovery(false);
}
public void setUploadInProgress(boolean param) {
serialBoardsLister.uploadInProgress = param;
}
public void pausePolling(boolean param) { serialBoardsLister.pausePolling = param;}
@Override @Override
public void start() { public void start() {
this.serialBoardsListerTimer = new Timer(SerialBoardsLister.class.getName()); this.serialBoardsListerTimer = new Timer(SerialBoardsLister.class.getName());
new SerialBoardsLister(this).start(serialBoardsListerTimer); serialBoardsLister.start(serialBoardsListerTimer);
} }
@Override @Override

View File

@ -31,9 +31,9 @@ package cc.arduino.packages.discoverers.serial;
import cc.arduino.packages.BoardPort; import cc.arduino.packages.BoardPort;
import cc.arduino.packages.discoverers.SerialDiscovery; import cc.arduino.packages.discoverers.SerialDiscovery;
import cc.arduino.packages.uploaders.SerialUploader;
import processing.app.BaseNoGui; import processing.app.BaseNoGui;
import processing.app.Platform; import processing.app.Platform;
import processing.app.Serial;
import processing.app.debug.TargetBoard; import processing.app.debug.TargetBoard;
import java.util.*; import java.util.*;
@ -41,6 +41,11 @@ import java.util.*;
public class SerialBoardsLister extends TimerTask { public class SerialBoardsLister extends TimerTask {
private final SerialDiscovery serialDiscovery; private final SerialDiscovery serialDiscovery;
private final List<BoardPort> boardPorts = new LinkedList<>();
private List<String> oldPorts = new LinkedList<>();
public boolean uploadInProgress = false;
public boolean pausePolling = false;
private BoardPort oldUploadBoardPort = null;
public SerialBoardsLister(SerialDiscovery serialDiscovery) { public SerialBoardsLister(SerialDiscovery serialDiscovery) {
this.serialDiscovery = serialDiscovery; this.serialDiscovery = serialDiscovery;
@ -50,43 +55,89 @@ public class SerialBoardsLister extends TimerTask {
timer.schedule(this, 0, 1000); timer.schedule(this, 0, 1000);
} }
@Override public synchronized void retriggerDiscovery(boolean polled) {
public void run() {
while (BaseNoGui.packages == null) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// noop
}
}
Platform platform = BaseNoGui.getPlatform(); Platform platform = BaseNoGui.getPlatform();
if (platform == null) { if (platform == null) {
return; return;
} }
List<BoardPort> boardPorts = new LinkedList<>(); if (polled && pausePolling) {
return;
List<String> ports = Serial.list();
String devicesListOutput = null;
if (!ports.isEmpty()) {
devicesListOutput = platform.preListAllCandidateDevices();
} }
for (String port : ports) { List<String> ports = platform.listSerials();
Map<String, Object> boardData = platform.resolveDeviceByVendorIdProductId(port, BaseNoGui.packages, devicesListOutput); if (ports.equals(oldPorts)) {
return;
}
BoardPort boardPort = new BoardPort(); // if (updating) {}
// a port will disappear, another will appear
// use this information to "merge" the boards
// updating must be signaled by SerialUpload class
oldPorts.clear();
oldPorts.addAll(ports);
for (BoardPort board : boardPorts) {
if (ports.contains(board.toString())) {
if (board.isOnline()) {
ports.remove(ports.indexOf(board.toString()));
}
} else {
if (uploadInProgress && board.isOnline()) {
oldUploadBoardPort = board;
}
board.setOnlineStatus(false);
}
}
for (String newPort : ports) {
String[] parts = newPort.split("_");
String port = parts[0];
if (parts.length != 3) {
// something went horribly wrong
continue;
}
Map<String, Object> boardData = platform.resolveDeviceByVendorIdProductId(port, BaseNoGui.packages);
BoardPort boardPort = null;
boolean updatingInfos = false;
int i = 0;
// create new board or update existing
for (BoardPort board : boardPorts) {
if (board.toString().equals(newPort)) {
updatingInfos = true;
boardPort = boardPorts.get(i);
break;
}
i++;
}
if (!updatingInfos) {
boardPort = new BoardPort();
}
boardPort.setAddress(port); boardPort.setAddress(port);
boardPort.setProtocol("serial"); boardPort.setProtocol("serial");
boardPort.setOnlineStatus(true);
String label = port; String label = port;
if (boardData != null) { if (boardData != null) {
boardPort.getPrefs().put("vid", boardData.get("vid").toString()); boardPort.getPrefs().put("vid", boardData.get("vid").toString());
boardPort.getPrefs().put("pid", boardData.get("pid").toString()); boardPort.getPrefs().put("pid", boardData.get("pid").toString());
boardPort.getPrefs().put("iserial", boardData.get("iserial").toString()); boardPort.setVIDPID(parts[1], parts[2]);
String iserial = boardData.get("iserial").toString();
if (iserial.length() >= 10) {
boardPort.getPrefs().put("iserial", iserial);
boardPort.setISerial(iserial);
}
if (uploadInProgress && oldUploadBoardPort!=null) {
oldUploadBoardPort.getPrefs().put("iserial", iserial);
oldUploadBoardPort.setISerial(iserial);
}
TargetBoard board = (TargetBoard) boardData.get("board"); TargetBoard board = (TargetBoard) boardData.get("board");
if (board != null) { if (board != null) {
@ -96,13 +147,28 @@ public class SerialBoardsLister extends TimerTask {
} }
boardPort.setBoardName(boardName); boardPort.setBoardName(boardName);
} }
} else {
if (parts[1] != "0000") {
boardPort.setVIDPID(parts[1], parts[2]);
} else {
boardPort.setVIDPID("0000", "0000");
boardPort.setISerial("");
}
} }
boardPort.setLabel(label); boardPort.setLabel(label);
if (!updatingInfos) {
boardPorts.add(boardPort); boardPorts.add(boardPort);
}
} }
serialDiscovery.setSerialBoardPorts(boardPorts); serialDiscovery.setSerialBoardPorts(boardPorts);
} }
@Override
public void run() {
if (BaseNoGui.packages == null) {
return;
}
retriggerDiscovery(true);
}
} }

View File

@ -44,6 +44,8 @@ import processing.app.helpers.OSUtils;
import processing.app.helpers.PreferencesMap; import processing.app.helpers.PreferencesMap;
import processing.app.helpers.StringReplacer; import processing.app.helpers.StringReplacer;
import cc.arduino.packages.discoverers.SerialDiscovery;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -78,12 +80,19 @@ public class SerialUploader extends Uploader {
} }
prefs.putAll(targetPlatform.getTool(tool)); prefs.putAll(targetPlatform.getTool(tool));
if (programmerPid != null && programmerPid.isAlive()) {
// kill the previous programmer
programmerPid.destroyForcibly();
}
// if no protocol is specified for this board, assume it lacks a // if no protocol is specified for this board, assume it lacks a
// bootloader and upload using the selected programmer. // bootloader and upload using the selected programmer.
if (usingProgrammer || prefs.get("upload.protocol") == null) { if (usingProgrammer || prefs.get("upload.protocol") == null) {
return uploadUsingProgrammer(buildPath, className); return uploadUsingProgrammer(buildPath, className);
} }
BaseNoGui.getDiscoveryManager().getSerialDiscoverer().pausePolling(true);
if (noUploadPort) if (noUploadPort)
{ {
prefs.put("build.path", buildPath); prefs.put("build.path", buildPath);
@ -100,6 +109,8 @@ public class SerialUploader extends Uploader {
uploadResult = executeUploadCommand(cmd); uploadResult = executeUploadCommand(cmd);
} catch (Exception e) { } catch (Exception e) {
throw new RunnerException(e); throw new RunnerException(e);
} finally {
BaseNoGui.getDiscoveryManager().getSerialDiscoverer().pausePolling(false);
} }
return uploadResult; return uploadResult;
} }
@ -134,7 +145,7 @@ public class SerialUploader extends Uploader {
// Scanning for available ports seems to open the port or // Scanning for available ports seems to open the port or
// otherwise assert DTR, which would cancel the WDT reset if // otherwise assert DTR, which would cancel the WDT reset if
// it happened within 250 ms. So we wait until the reset should // it happened within 250 ms. So we wait until the reset should
// have already occured before we start scanning. // have already occurred before we start scanning.
actualUploadPort = waitForUploadPort(userSelectedUploadPort, before); actualUploadPort = waitForUploadPort(userSelectedUploadPort, before);
// on OS X, if the port is opened too quickly after it is detected, // on OS X, if the port is opened too quickly after it is detected,
@ -146,6 +157,8 @@ public class SerialUploader extends Uploader {
throw new RunnerException(e); throw new RunnerException(e);
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new RunnerException(e.getMessage()); throw new RunnerException(e.getMessage());
} finally {
BaseNoGui.getDiscoveryManager().getSerialDiscoverer().pausePolling(false);
} }
if (actualUploadPort == null) { if (actualUploadPort == null) {
actualUploadPort = userSelectedUploadPort; actualUploadPort = userSelectedUploadPort;
@ -156,13 +169,12 @@ public class SerialUploader extends Uploader {
} else { } else {
prefs.put("serial.port.file", actualUploadPort); prefs.put("serial.port.file", actualUploadPort);
} }
}
BoardPort boardPort = BaseNoGui.getDiscoveryManager().find(PreferencesData.get("serial.port")); // retrigger a discovery
try { BaseNoGui.getDiscoveryManager().getSerialDiscoverer().setUploadInProgress(true);
prefs.put("serial.port.iserial", boardPort.getPrefs().getOrExcept("iserial")); Thread.sleep(100);
} catch (Exception e) { BaseNoGui.getDiscoveryManager().getSerialDiscoverer().forceRefresh();
// if serial port does not contain an iserial field Thread.sleep(100);
} }
prefs.put("build.path", buildPath); prefs.put("build.path", buildPath);
@ -182,8 +194,13 @@ public class SerialUploader extends Uploader {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
throw new RunnerException(e); throw new RunnerException(e);
} finally {
BaseNoGui.getDiscoveryManager().getSerialDiscoverer().pausePolling(false);
} }
BaseNoGui.getDiscoveryManager().getSerialDiscoverer().setUploadInProgress(false);
BaseNoGui.getDiscoveryManager().getSerialDiscoverer().pausePolling(false);
String finalUploadPort = null; String finalUploadPort = null;
if (uploadResult && doTouch) { if (uploadResult && doTouch) {
try { try {
@ -196,10 +213,7 @@ public class SerialUploader extends Uploader {
long started = System.currentTimeMillis(); long started = System.currentTimeMillis();
while (System.currentTimeMillis() - started < 2000) { while (System.currentTimeMillis() - started < 2000) {
List<String> portList = Serial.list(); List<String> portList = Serial.list();
if (portList.contains(actualUploadPort)) { if (portList.contains(userSelectedUploadPort)) {
finalUploadPort = actualUploadPort;
break;
} else if (portList.contains(userSelectedUploadPort)) {
finalUploadPort = userSelectedUploadPort; finalUploadPort = userSelectedUploadPort;
break; break;
} }
@ -218,6 +232,7 @@ public class SerialUploader extends Uploader {
finalUploadPort = userSelectedUploadPort; finalUploadPort = userSelectedUploadPort;
} }
BaseNoGui.selectSerialPort(finalUploadPort); BaseNoGui.selectSerialPort(finalUploadPort);
return uploadResult; return uploadResult;
} }

View File

@ -33,6 +33,8 @@ import java.util.*;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import cc.arduino.packages.BoardPort;
import static processing.app.I18n.tr; import static processing.app.I18n.tr;
import static processing.app.helpers.filefilters.OnlyDirs.ONLY_DIRS; import static processing.app.helpers.filefilters.OnlyDirs.ONLY_DIRS;
@ -1119,6 +1121,10 @@ public class BaseNoGui {
public static void selectSerialPort(String port) { public static void selectSerialPort(String port) {
PreferencesData.set("serial.port", port); PreferencesData.set("serial.port", port);
BoardPort boardPort = getDiscoveryManager().find(port, true);
if (boardPort != null) {
PreferencesData.set("serial.port.iserial", boardPort.getPrefs().get("iserial"));
}
String portFile = port; String portFile = port;
if (port.startsWith("/dev/")) { if (port.startsWith("/dev/")) {
portFile = portFile.substring(5); portFile = portFile.substring(5);

View File

@ -35,6 +35,8 @@ import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ArrayList;
import java.util.Arrays;
import static processing.app.I18n.tr; import static processing.app.I18n.tr;
@ -160,13 +162,26 @@ public class Platform {
} }
} }
public native String resolveDeviceAttachedToNative(String serial); private native String resolveDeviceAttachedToNative(String serial);
private native String[] listSerialsNative();
public String preListAllCandidateDevices() { public String preListAllCandidateDevices() {
return null; return null;
} }
public Map<String, Object> resolveDeviceByVendorIdProductId(String serial, Map<String, TargetPackage> packages, String devicesListOutput) { public List<String> listSerials(){
return new ArrayList(Arrays.asList(this.listSerialsNative()));
}
public List<String> listSerialsNames(){
List<String> list = new LinkedList<>();
for (String port : this.listSerialsNative()) {
list.add(port.split("_")[0]);
}
return list;
}
public synchronized Map<String, Object> resolveDeviceByVendorIdProductId(String serial, Map<String, TargetPackage> packages) {
String vid_pid_iSerial = resolveDeviceAttachedToNative(serial); String vid_pid_iSerial = resolveDeviceAttachedToNative(serial);
for (TargetPackage targetPackage : packages.values()) { for (TargetPackage targetPackage : packages.values()) {
for (TargetPlatform targetPlatform : targetPackage.getPlatforms().values()) { for (TargetPlatform targetPlatform : targetPackage.getPlatforms().values()) {

View File

@ -78,6 +78,7 @@
<property name="portable" value="false" /> <property name="portable" value="false" />
<property name="ARDUINO-BUILDER-VERSION" value="1.3.15" /> <property name="ARDUINO-BUILDER-VERSION" value="1.3.15" />
<property name="LIBLISTSERIAL-VERSION" value="1.1.0" />
<!-- Libraries required for running arduino --> <!-- Libraries required for running arduino -->
<fileset dir=".." id="runtime.jars"> <fileset dir=".." id="runtime.jars">
@ -436,12 +437,12 @@
<chmod perm="755" file="macosx/work/${staging_hardware_folder}/../lib/libastylej.dylib" /> <chmod perm="755" file="macosx/work/${staging_hardware_folder}/../lib/libastylej.dylib" />
<antcall target="unzip"> <antcall target="unzip">
<param name="archive_file" value="./liblistSerials-1.0.5.zip" /> <param name="archive_file" value="./liblistSerials-${LIBLISTSERIAL-VERSION}.zip" />
<param name="archive_url" value="http://downloads.arduino.cc/liblistSerials/liblistSerials-1.0.5.zip" /> <param name="archive_url" value="http://downloads.arduino.cc/liblistSerials/liblistSerials-${LIBLISTSERIAL-VERSION}.zip" />
<param name="final_folder" value="${staging_folder}/liblistSerials-1.0.5" /> <param name="final_folder" value="${staging_folder}/liblistSerials-${LIBLISTSERIAL-VERSION}" />
<param name="dest_folder" value="${staging_folder}" /> <param name="dest_folder" value="${staging_folder}" />
</antcall> </antcall>
<copy file="macosx/liblistSerials-1.0.5/osx/liblistSerialsj.dylib" todir="macosx/work/${staging_hardware_folder}/../lib/" /> <copy file="macosx/liblistSerials-${LIBLISTSERIAL-VERSION}/osx/liblistSerialsj.dylib" todir="macosx/work/${staging_hardware_folder}/../lib/" />
<chmod perm="755" file="macosx/work/${staging_hardware_folder}/../lib/liblistSerialsj.dylib" /> <chmod perm="755" file="macosx/work/${staging_hardware_folder}/../lib/liblistSerialsj.dylib" />
<delete dir="${staging_folder}/arduino-builder-macosx" includeemptydirs="true"/> <delete dir="${staging_folder}/arduino-builder-macosx" includeemptydirs="true"/>
@ -639,12 +640,12 @@
</antcall> </antcall>
<antcall target="unzip"> <antcall target="unzip">
<param name="archive_file" value="./liblistSerials-1.0.5.zip" /> <param name="archive_file" value="./liblistSerials-${LIBLISTSERIAL-VERSION}.zip" />
<param name="archive_url" value="http://downloads.arduino.cc/liblistSerials/liblistSerials-1.0.5.zip" /> <param name="archive_url" value="http://downloads.arduino.cc/liblistSerials/liblistSerials-${LIBLISTSERIAL-VERSION}.zip" />
<param name="final_folder" value="${staging_folder}/liblistSerials-1.0.5" /> <param name="final_folder" value="${staging_folder}/liblistSerials-${LIBLISTSERIAL-VERSION}" />
<param name="dest_folder" value="${staging_folder}" /> <param name="dest_folder" value="${staging_folder}" />
</antcall> </antcall>
<copy file="linux/liblistSerials-1.0.5/linux${arch-bits}/liblistSerialsj.so" todir="linux/work/lib/" /> <copy file="linux/liblistSerials-${LIBLISTSERIAL-VERSION}/linux${arch-bits}/liblistSerialsj.so" todir="linux/work/lib/" />
<chmod perm="755" file="linux/work/lib/liblistSerialsj.so" /> <chmod perm="755" file="linux/work/lib/liblistSerialsj.so" />
</target> </target>
@ -908,12 +909,12 @@
<copy file="windows/msvcr100.dll" todir="windows/work" /> <copy file="windows/msvcr100.dll" todir="windows/work" />
<antcall target="unzip"> <antcall target="unzip">
<param name="archive_file" value="./liblistSerials-1.0.5.zip" /> <param name="archive_file" value="./liblistSerials-${LIBLISTSERIAL-VERSION}.zip" />
<param name="archive_url" value="http://downloads.arduino.cc/liblistSerials/liblistSerials-1.0.5.zip" /> <param name="archive_url" value="http://downloads.arduino.cc/liblistSerials/liblistSerials-${LIBLISTSERIAL-VERSION}.zip" />
<param name="final_folder" value="${staging_folder}/liblistSerials-1.0.5" /> <param name="final_folder" value="${staging_folder}/liblistSerials-${LIBLISTSERIAL-VERSION}" />
<param name="dest_folder" value="${staging_folder}" /> <param name="dest_folder" value="${staging_folder}" />
</antcall> </antcall>
<copy file="windows/liblistSerials-1.0.5/windows/listSerialsj.dll" todir="windows/work/lib/" /> <copy file="windows/liblistSerials-${LIBLISTSERIAL-VERSION}/windows/listSerialsj.dll" todir="windows/work/lib/" />
<chmod perm="755" file="windows/work/lib/listSerialsj.dll" /> <chmod perm="755" file="windows/work/lib/listSerialsj.dll" />
<delete dir="${staging_folder}/arduino-builder-windows" includeemptydirs="true"/> <delete dir="${staging_folder}/arduino-builder-windows" includeemptydirs="true"/>

View File

@ -1 +0,0 @@
edb1c858a243e465f5797d7e5d0baa66daa1eba0

View File

@ -0,0 +1 @@
05e942bc85e46a2b59e01fe1333dd9472e465654