From 6d5597b070c7bedce15047c7c560249965cc0bfc Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 25 Jan 2016 18:19:48 +0100 Subject: [PATCH 01/12] Avoid multiple concurrent compile/upload operations Disable Compile/Run buttons as they get press, and reenable only on function exit. The launched upload process has now a 2minutes timeout before being terminated forcefully. 10 second after pressing "Upload" the button comes pressable again, but this time the previous upload command gets killed explicitely --- app/src/processing/app/Editor.java | 29 +++++++++++++++++-- app/src/processing/app/EditorToolbar.java | 11 +++++-- .../src/cc/arduino/packages/Uploader.java | 13 +++++++-- .../packages/uploaders/SerialUploader.java | 8 ++++- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 8da903bcb..12560e5bf 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -146,6 +146,8 @@ public class Editor extends JFrame implements RunnerListener { private int numTools = 0; + public boolean avoidMultipleOperations = false; + private final EditorToolbar toolbar; // these menus are shared so that they needn't be rebuilt for all windows // each time a sketch is created, renamed, or moved. @@ -198,7 +200,7 @@ public class Editor extends JFrame implements RunnerListener { private Runnable stopHandler; Runnable exportHandler; private Runnable exportAppHandler; - + private Runnable timeoutUploadHandler; public Editor(Base ibase, File file, int[] storedLocation, int[] defaultLocation, Platform platform) throws Exception { super("Arduino"); @@ -1648,6 +1650,7 @@ public class Editor extends JFrame implements RunnerListener { stopHandler = new DefaultStopHandler(); exportHandler = new DefaultExportHandler(); exportAppHandler = new DefaultExportAppHandler(); + timeoutUploadHandler = new TimeoutUploadHandler(); } @@ -1979,6 +1982,7 @@ public class Editor extends JFrame implements RunnerListener { status.unprogress(); toolbar.deactivateRun(); + avoidMultipleOperations = false; } } @@ -2367,6 +2371,7 @@ public class Editor extends JFrame implements RunnerListener { console.clear(); status.progress(tr("Uploading to I/O Board...")); + new Thread(timeoutUploadHandler).start(); new Thread(usingProgrammer ? exportAppHandler : exportHandler).start(); } @@ -2406,6 +2411,7 @@ public class Editor extends JFrame implements RunnerListener { e.printStackTrace(); } finally { populatePortMenu(); + avoidMultipleOperations = false; } status.unprogress(); uploading = false; @@ -2500,6 +2506,7 @@ public class Editor extends JFrame implements RunnerListener { } catch (Exception e) { e.printStackTrace(); } finally { + avoidMultipleOperations = false; populatePortMenu(); } status.unprogress(); @@ -2514,6 +2521,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() { if(serialPlotter != null) { @@ -2558,7 +2579,7 @@ public class Editor extends JFrame implements RunnerListener { // If currently uploading, disable the monitor (it will be later // enabled when done uploading) - if (uploading) { + if (uploading || avoidMultipleOperations) { try { serialMonitor.suspend(); } catch (Exception e) { @@ -2582,8 +2603,10 @@ public class Editor extends JFrame implements RunnerListener { } try { - serialMonitor.open(); serialMonitor.setVisible(true); + if (!avoidMultipleOperations) { + serialMonitor.open(); + } success = true; } catch (ConnectException e) { statusError(tr("Unable to connect: is the sketch using the bridge?")); diff --git a/app/src/processing/app/EditorToolbar.java b/app/src/processing/app/EditorToolbar.java index a6b8bce60..a4d18b5f7 100644 --- a/app/src/processing/app/EditorToolbar.java +++ b/app/src/processing/app/EditorToolbar.java @@ -341,7 +341,10 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key switch (sel) { case RUN: - editor.handleRun(false, editor.presentHandler, editor.runHandler); + if (!editor.avoidMultipleOperations) { + editor.handleRun(false, editor.presentHandler, editor.runHandler); + editor.avoidMultipleOperations = true; + } break; // case STOP: @@ -370,7 +373,11 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key break; 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; case SERIAL: diff --git a/arduino-core/src/cc/arduino/packages/Uploader.java b/arduino-core/src/cc/arduino/packages/Uploader.java index d58d29504..1d1967c36 100644 --- a/arduino-core/src/cc/arduino/packages/Uploader.java +++ b/arduino-core/src/cc/arduino/packages/Uploader.java @@ -44,6 +44,7 @@ import java.io.File; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.concurrent.TimeUnit; import static processing.app.I18n.tr; @@ -102,6 +103,9 @@ public abstract class Uploader implements MessageConsumer { return null; } + // static field for last executed programmer process ID + static protected Process programmerPid; + protected boolean executeUploadCommand(Collection command) throws Exception { return executeUploadCommand(command.toArray(new String[command.size()])); } @@ -121,11 +125,16 @@ public abstract class Uploader implements MessageConsumer { System.out.println(); } Process process = ProcessUtils.exec(command); + programmerPid = process; new MessageSiphon(process.getInputStream(), this, 100); new MessageSiphon(process.getErrorStream(), this, 100); - // wait for the process to finish. - result = process.waitFor(); + // wait for the process to finish, but not forever + // kill the flasher process after 2 minutes to avoid 100% cpu spinning + if (!process.waitFor(2, TimeUnit.MINUTES)) { + process.destroyForcibly(); + } + result = process.exitValue(); } catch (Exception e) { e.printStackTrace(); } diff --git a/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java b/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java index 971bfb8c6..64b66862d 100644 --- a/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java +++ b/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java @@ -78,6 +78,11 @@ public class SerialUploader extends Uploader { } 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 // bootloader and upload using the selected programmer. if (usingProgrammer || prefs.get("upload.protocol") == null) { @@ -134,7 +139,7 @@ public class SerialUploader extends Uploader { // Scanning for available ports seems to open the port or // otherwise assert DTR, which would cancel the WDT reset if // 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); } } catch (SerialException e) { @@ -213,6 +218,7 @@ public class SerialUploader extends Uploader { finalUploadPort = userSelectedUploadPort; } BaseNoGui.selectSerialPort(finalUploadPort); + return uploadResult; } From c11ceb7daeb3de2ea5403cb990094270c335e4a3 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 25 Jan 2016 18:29:25 +0100 Subject: [PATCH 02/12] Fix NPE when replacing unexisting strings --- arduino-core/src/processing/app/helpers/StringReplacer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arduino-core/src/processing/app/helpers/StringReplacer.java b/arduino-core/src/processing/app/helpers/StringReplacer.java index f51bfd7b6..fae77155a 100644 --- a/arduino-core/src/processing/app/helpers/StringReplacer.java +++ b/arduino-core/src/processing/app/helpers/StringReplacer.java @@ -94,7 +94,9 @@ public class StringReplacer { String rightDelimiter) { for (Map.Entry entry : map.entrySet()) { String keyword = leftDelimiter + entry.getKey() + rightDelimiter; - src = src.replace(keyword, entry.getValue()); + if (entry.getValue() != null && keyword != null) { + src = src.replace(keyword, entry.getValue()); + } } return src; } From 243fc68763058be1f6037fc4072a3f3b2a9dbaf1 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 25 Jan 2016 18:31:27 +0100 Subject: [PATCH 03/12] Rework Serial ports handling and add Board info menu This commit introduces the concept of stateful board list (vs. original stateless) and board serial number. The board is now an "entity" composed by the triplet port/vid/pid. These informations come from libListSerial "light" function. When the board list changes, it triggers a request for the additional infos to libListSerial. These information contains the serial number of the boards. These brings a lighter and faster scanning process. Some logic has been introduced to handle a board with the S/N only exposed in the bootloader (like 32u4). In this case the disappearing port acquires the bootloader's S/N A menu (under Ports menu) shows the currently connected port info and can be used for bugreporting --- app/src/processing/app/Editor.java | 49 ++++++++++ app/src/processing/app/EditorLineStatus.java | 5 + .../src/cc/arduino/packages/BoardPort.java | 36 +++++++ .../src/cc/arduino/packages/Discovery.java | 1 + .../cc/arduino/packages/DiscoveryManager.java | 27 +++++- .../discoverers/NetworkDiscovery.java | 7 ++ .../packages/discoverers/SerialDiscovery.java | 34 +++++-- .../serial/SerialBoardsLister.java | 96 +++++++++++++++---- .../packages/uploaders/SerialUploader.java | 21 ++-- .../src/processing/app/BaseNoGui.java | 4 + arduino-core/src/processing/app/Platform.java | 19 +++- 11 files changed, 259 insertions(+), 40 deletions(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 12560e5bf..07af0a1c1 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -814,6 +814,9 @@ public class Editor extends JFrame implements RunnerListener { portMenu = new JMenu(tr("Port")); populatePortMenu(); toolsMenu.add(portMenu); + item = new JMenuItem(tr("Get Board Info")); + item.addActionListener(e -> handleBoardInfo()); + toolsMenu.add(item); toolsMenu.addSeparator(); base.rebuildProgrammerMenu(); @@ -2753,6 +2756,52 @@ public class Editor extends JFrame implements RunnerListener { }).start(); } + private void handleBoardInfo() { + console.clear(); + + String selectedPort = PreferencesData.get("serial.port"); + List ports = Base.getDiscoveryManager().discovery(); + + String label = ""; + String vid = ""; + String pid = ""; + String iserial = ""; + boolean found = false; + + for (BoardPort port : ports) { + if (port.getAddress().equals(selectedPort)) { + label = port.getBoardName(); + vid = port.getVID(); + pid = port.getPID(); + iserial = port.getISerial(); + found = true; + break; + } + } + + if (!found) { + statusNotice(tr("Please select a port to obtain board 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 → Page Setup. diff --git a/app/src/processing/app/EditorLineStatus.java b/app/src/processing/app/EditorLineStatus.java index b68b74b46..506e8f56d 100644 --- a/app/src/processing/app/EditorLineStatus.java +++ b/app/src/processing/app/EditorLineStatus.java @@ -52,6 +52,7 @@ public class EditorLineStatus extends JComponent { String text = ""; String name = ""; String serialport = ""; + String serialnumber = ""; public EditorLineStatus() { background = Theme.getColor("linestatus.bgcolor"); @@ -129,6 +130,10 @@ public class EditorLineStatus extends JComponent { this.serialport = serialport; } + public void setSerialNumber(String serialnumber) { + this.serialnumber = serialnumber; + } + public Dimension getPreferredSize() { return scale(new Dimension(300, height)); } diff --git a/arduino-core/src/cc/arduino/packages/BoardPort.java b/arduino-core/src/cc/arduino/packages/BoardPort.java index e2c16c43e..0e85ffe13 100644 --- a/arduino-core/src/cc/arduino/packages/BoardPort.java +++ b/arduino-core/src/cc/arduino/packages/BoardPort.java @@ -36,8 +36,12 @@ public class BoardPort { private String address; private String protocol; private String boardName; + private String vid; + private String pid; + private String iserial; private String label; private final PreferencesMap prefs; + private boolean online; public BoardPort() { this.prefs = new PreferencesMap(); @@ -79,4 +83,36 @@ public class BoardPort { 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; + } } diff --git a/arduino-core/src/cc/arduino/packages/Discovery.java b/arduino-core/src/cc/arduino/packages/Discovery.java index eb4b41da2..911fcc2f6 100644 --- a/arduino-core/src/cc/arduino/packages/Discovery.java +++ b/arduino-core/src/cc/arduino/packages/Discovery.java @@ -51,5 +51,6 @@ public interface Discovery { * @return */ List listDiscoveredBoards(); + List listDiscoveredBoards(boolean complete); } diff --git a/arduino-core/src/cc/arduino/packages/DiscoveryManager.java b/arduino-core/src/cc/arduino/packages/DiscoveryManager.java index add7d0671..2632386d4 100644 --- a/arduino-core/src/cc/arduino/packages/DiscoveryManager.java +++ b/arduino-core/src/cc/arduino/packages/DiscoveryManager.java @@ -40,11 +40,13 @@ import static processing.app.I18n.tr; public class DiscoveryManager { private final List discoverers; + private final SerialDiscovery serialDiscoverer = new SerialDiscovery(); + private final NetworkDiscovery networkDiscoverer = new NetworkDiscovery(); public DiscoveryManager() { discoverers = new ArrayList(); - discoverers.add(new SerialDiscovery()); - discoverers.add(new NetworkDiscovery()); + discoverers.add(serialDiscoverer); + discoverers.add(networkDiscoverer); // Start all discoverers for (Discovery d : discoverers) { @@ -69,6 +71,10 @@ public class DiscoveryManager { Runtime.getRuntime().addShutdownHook(closeHook); } + public SerialDiscovery getSerialDiscoverer() { + return serialDiscoverer; + } + public List discovery() { List res = new ArrayList(); for (Discovery d : discoverers) { @@ -77,6 +83,14 @@ public class DiscoveryManager { return res; } + public List discovery(boolean complete) { + List res = new ArrayList(); + for (Discovery d : discoverers) { + res.addAll(d.listDiscoveredBoards(complete)); + } + return res; + } + public BoardPort find(String address) { for (BoardPort boardPort : discovery()) { if (boardPort.getAddress().equals(address)) { @@ -86,4 +100,13 @@ public class DiscoveryManager { return null; } + public BoardPort find(String address, boolean complete) { + for (BoardPort boardPort : discovery(complete)) { + if (boardPort.getAddress().equals(address)) { + return boardPort; + } + } + return null; + } + } diff --git a/arduino-core/src/cc/arduino/packages/discoverers/NetworkDiscovery.java b/arduino-core/src/cc/arduino/packages/discoverers/NetworkDiscovery.java index ebbb8c50d..e88568a1e 100644 --- a/arduino-core/src/cc/arduino/packages/discoverers/NetworkDiscovery.java +++ b/arduino-core/src/cc/arduino/packages/discoverers/NetworkDiscovery.java @@ -67,6 +67,13 @@ public class NetworkDiscovery implements Discovery, ServiceListener, cc.arduino. } } + @Override + public List listDiscoveredBoards(boolean complete) { + synchronized (reachableBoardPorts) { + return new LinkedList<>(reachableBoardPorts); + } + } + public void setReachableBoardPorts(List newReachableBoardPorts) { synchronized (reachableBoardPorts) { this.reachableBoardPorts.clear(); diff --git a/arduino-core/src/cc/arduino/packages/discoverers/SerialDiscovery.java b/arduino-core/src/cc/arduino/packages/discoverers/SerialDiscovery.java index 9c3efdc52..565e80e90 100644 --- a/arduino-core/src/cc/arduino/packages/discoverers/SerialDiscovery.java +++ b/arduino-core/src/cc/arduino/packages/discoverers/SerialDiscovery.java @@ -41,6 +41,7 @@ public class SerialDiscovery implements Discovery { private Timer serialBoardsListerTimer; private final List serialBoardPorts; + private SerialBoardsLister serialBoardsLister = new SerialBoardsLister(this);; public SerialDiscovery() { this.serialBoardPorts = new LinkedList<>(); @@ -48,26 +49,43 @@ public class SerialDiscovery implements Discovery { @Override public List listDiscoveredBoards() { - return getSerialBoardPorts(); + return getSerialBoardPorts(false); } - private List getSerialBoardPorts() { - synchronized (serialBoardPorts) { - return new LinkedList<>(serialBoardPorts); - } + public List listDiscoveredBoards(boolean complete) { + return getSerialBoardPorts(complete); + } + + private List getSerialBoardPorts(boolean complete) { + if (complete) { + return new LinkedList<>(serialBoardPorts); + } + List onlineBoardPorts = new LinkedList<>(); + for (BoardPort port : serialBoardPorts) { + if (port.isOnline() == true) { + onlineBoardPorts.add(port); + } + } + return onlineBoardPorts; } public void setSerialBoardPorts(List newSerialBoardPorts) { - synchronized (serialBoardPorts) { serialBoardPorts.clear(); serialBoardPorts.addAll(newSerialBoardPorts); - } + } + + public void forceRefresh() { + serialBoardsLister.retriggerDiscovery(); + } + + public void setUploadInProgress(boolean param) { + serialBoardsLister.uploadInProgress = param; } @Override public void start() { this.serialBoardsListerTimer = new Timer(SerialBoardsLister.class.getName()); - new SerialBoardsLister(this).start(serialBoardsListerTimer); + serialBoardsLister.start(serialBoardsListerTimer); } @Override diff --git a/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java b/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java index 5ca99819b..b4ac2da9d 100644 --- a/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java +++ b/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java @@ -31,9 +31,9 @@ package cc.arduino.packages.discoverers.serial; import cc.arduino.packages.BoardPort; import cc.arduino.packages.discoverers.SerialDiscovery; +import cc.arduino.packages.uploaders.SerialUploader; import processing.app.BaseNoGui; import processing.app.Platform; -import processing.app.Serial; import processing.app.debug.TargetBoard; import java.util.*; @@ -41,6 +41,10 @@ import java.util.*; public class SerialBoardsLister extends TimerTask { private final SerialDiscovery serialDiscovery; + private final List boardPorts = new LinkedList<>(); + private List oldPorts = new LinkedList<>(); + public boolean uploadInProgress = false; + private BoardPort oldUploadBoardPort = null; public SerialBoardsLister(SerialDiscovery serialDiscovery) { this.serialDiscovery = serialDiscovery; @@ -50,8 +54,7 @@ public class SerialBoardsLister extends TimerTask { timer.schedule(this, 0, 1000); } - @Override - public void run() { + public void retriggerDiscovery() { while (BaseNoGui.packages == null) { try { Thread.sleep(1000); @@ -59,34 +62,79 @@ public class SerialBoardsLister extends TimerTask { // noop } } - Platform platform = BaseNoGui.getPlatform(); if (platform == null) { return; } - List boardPorts = new LinkedList<>(); - - List ports = Serial.list(); - - String devicesListOutput = null; - if (!ports.isEmpty()) { - devicesListOutput = platform.preListAllCandidateDevices(); + List ports = platform.listSerials(); + if (ports.equals(oldPorts)) { + return; } - for (String port : ports) { - Map boardData = platform.resolveDeviceByVendorIdProductId(port, BaseNoGui.packages, devicesListOutput); + // if (updating) {} + // a port will disappear, another will appear + // use this information to "merge" the boards + // updating must be signaled by SerialUpload class - BoardPort boardPort = new BoardPort(); + 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]; + + Map 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.setProtocol("serial"); + boardPort.setOnlineStatus(true); String label = port; if (boardData != null) { boardPort.getPrefs().put("vid", boardData.get("vid").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"); if (board != null) { @@ -96,13 +144,25 @@ public class SerialBoardsLister extends TimerTask { } boardPort.setBoardName(boardName); } + } else { + if (parts[1] != "0000") { + boardPort.setVIDPID(parts[1], parts[2]); + } else { + boardPort.setVIDPID("0000", "0000"); + boardPort.setISerial(""); + } } boardPort.setLabel(label); - - boardPorts.add(boardPort); + if (!updatingInfos) { + boardPorts.add(boardPort); + } } - serialDiscovery.setSerialBoardPorts(boardPorts); } + + @Override + public void run() { + retriggerDiscovery(); + } } diff --git a/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java b/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java index 64b66862d..064e04cfa 100644 --- a/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java +++ b/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java @@ -44,6 +44,8 @@ import processing.app.helpers.OSUtils; import processing.app.helpers.PreferencesMap; import processing.app.helpers.StringReplacer; +import cc.arduino.packages.discoverers.SerialDiscovery; + import java.io.File; import java.util.ArrayList; import java.util.List; @@ -156,13 +158,12 @@ public class SerialUploader extends Uploader { } else { prefs.put("serial.port.file", actualUploadPort); } - } - BoardPort boardPort = BaseNoGui.getDiscoveryManager().find(PreferencesData.get("serial.port")); - try { - prefs.put("serial.port.iserial", boardPort.getPrefs().getOrExcept("iserial")); - } catch (Exception e) { - // if serial port does not contain an iserial field + // retrigger a discovery + BaseNoGui.getDiscoveryManager().getSerialDiscoverer().setUploadInProgress(true); + Thread.sleep(100); + BaseNoGui.getDiscoveryManager().getSerialDiscoverer().forceRefresh(); + Thread.sleep(100); } prefs.put("build.path", buildPath); @@ -184,6 +185,8 @@ public class SerialUploader extends Uploader { throw new RunnerException(e); } + BaseNoGui.getDiscoveryManager().getSerialDiscoverer().setUploadInProgress(false); + String finalUploadPort = null; if (uploadResult && doTouch) { try { @@ -196,15 +199,13 @@ public class SerialUploader extends Uploader { long started = System.currentTimeMillis(); while (System.currentTimeMillis() - started < 2000) { List portList = Serial.list(); - if (portList.contains(actualUploadPort)) { - finalUploadPort = actualUploadPort; - break; - } else if (portList.contains(userSelectedUploadPort)) { + if (portList.contains(userSelectedUploadPort)) { finalUploadPort = userSelectedUploadPort; break; } Thread.sleep(250); } + finalUploadPort = actualUploadPort; } } catch (InterruptedException ex) { // noop diff --git a/arduino-core/src/processing/app/BaseNoGui.java b/arduino-core/src/processing/app/BaseNoGui.java index a2eab2559..f1d9d9f7d 100644 --- a/arduino-core/src/processing/app/BaseNoGui.java +++ b/arduino-core/src/processing/app/BaseNoGui.java @@ -33,6 +33,8 @@ import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; +import cc.arduino.packages.BoardPort; + import static processing.app.I18n.tr; import static processing.app.helpers.filefilters.OnlyDirs.ONLY_DIRS; @@ -1119,6 +1121,8 @@ public class BaseNoGui { public static void selectSerialPort(String port) { PreferencesData.set("serial.port", port); + BoardPort boardPort = getDiscoveryManager().find(port, true); + PreferencesData.set("serial.port.iserial", boardPort.getPrefs().get("iserial")); String portFile = port; if (port.startsWith("/dev/")) { portFile = portFile.substring(5); diff --git a/arduino-core/src/processing/app/Platform.java b/arduino-core/src/processing/app/Platform.java index 29e5e733d..b999c8264 100644 --- a/arduino-core/src/processing/app/Platform.java +++ b/arduino-core/src/processing/app/Platform.java @@ -35,6 +35,8 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.ArrayList; +import java.util.Arrays; 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() { return null; } - public Map resolveDeviceByVendorIdProductId(String serial, Map packages, String devicesListOutput) { + public List listSerials(){ + return new ArrayList(Arrays.asList(this.listSerialsNative())); + } + + public List listSerialsNames(){ + List list = new LinkedList<>(); + for (String port : this.listSerialsNative()) { + list.add(port.split("_")[0]); + } + return list; + } + + public Map resolveDeviceByVendorIdProductId(String serial, Map packages) { String vid_pid_iSerial = resolveDeviceAttachedToNative(serial); for (TargetPackage targetPackage : packages.values()) { for (TargetPlatform targetPlatform : targetPackage.getPlatforms().values()) { From e23bbf76c112fe13fc9aabd36eaf5b1a0793cd53 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 5 Feb 2016 12:53:32 +0100 Subject: [PATCH 04/12] avoid NPE in CLI mode (boardInfo not yet initialized) --- arduino-core/src/processing/app/BaseNoGui.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arduino-core/src/processing/app/BaseNoGui.java b/arduino-core/src/processing/app/BaseNoGui.java index f1d9d9f7d..a431a19d7 100644 --- a/arduino-core/src/processing/app/BaseNoGui.java +++ b/arduino-core/src/processing/app/BaseNoGui.java @@ -1122,7 +1122,9 @@ public class BaseNoGui { public static void selectSerialPort(String port) { PreferencesData.set("serial.port", port); BoardPort boardPort = getDiscoveryManager().find(port, true); - PreferencesData.set("serial.port.iserial", boardPort.getPrefs().get("iserial")); + if (boardPort != null) { + PreferencesData.set("serial.port.iserial", boardPort.getPrefs().get("iserial")); + } String portFile = port; if (port.startsWith("/dev/")) { portFile = portFile.substring(5); From 821c665460373d681973733eaece93fa2185e871 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 3 Mar 2016 10:48:50 +0100 Subject: [PATCH 05/12] Change message if requiring infos from Network port --- app/src/processing/app/Editor.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 07af0a1c1..aef2bcdb8 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -2766,6 +2766,7 @@ public class Editor extends JFrame implements RunnerListener { String vid = ""; String pid = ""; String iserial = ""; + String protocol = ""; boolean found = false; for (BoardPort port : ports) { @@ -2774,6 +2775,7 @@ public class Editor extends JFrame implements RunnerListener { vid = port.getVID(); pid = port.getPID(); iserial = port.getISerial(); + protocol = port.getProtocol(); found = true; break; } @@ -2784,6 +2786,11 @@ public class Editor extends JFrame implements RunnerListener { 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; From 52ef55380d824da016d0562d396ceabe88b7edd1 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 23 Feb 2016 15:59:21 +0100 Subject: [PATCH 06/12] avoid NPE if serial monitor is waiting too long for opening --- app/src/processing/app/Editor.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index aef2bcdb8..d018b69b2 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -2442,13 +2442,14 @@ public class Editor extends JFrame implements RunnerListener { } } try { - if (serialMonitor != null) - serialMonitor.resume(boardPort); - if (boardPort == null) { - serialMonitor.close(); - handleSerial(); - } else { + if (serialMonitor != null) { serialMonitor.resume(boardPort); + if (boardPort == null) { + serialMonitor.close(); + handleSerial(); + } else { + serialMonitor.resume(boardPort); + } } } catch (Exception e) { statusError(e); From ad74288e5aea89ec88fa25005bf2e9c779ff5b27 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 8 Mar 2016 10:20:51 +0100 Subject: [PATCH 07/12] Fix randomic NPE when pressing menus during operations --- arduino-core/src/cc/arduino/packages/Uploader.java | 6 +++++- arduino-core/src/processing/app/Platform.java | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arduino-core/src/cc/arduino/packages/Uploader.java b/arduino-core/src/cc/arduino/packages/Uploader.java index 1d1967c36..cd9a11a45 100644 --- a/arduino-core/src/cc/arduino/packages/Uploader.java +++ b/arduino-core/src/cc/arduino/packages/Uploader.java @@ -134,7 +134,11 @@ public abstract class Uploader implements MessageConsumer { if (!process.waitFor(2, TimeUnit.MINUTES)) { process.destroyForcibly(); } - result = process.exitValue(); + if (!process.isAlive()) { + result = process.exitValue(); + } else { + result = 0; + } } catch (Exception e) { e.printStackTrace(); } diff --git a/arduino-core/src/processing/app/Platform.java b/arduino-core/src/processing/app/Platform.java index b999c8264..0c2c1d8cb 100644 --- a/arduino-core/src/processing/app/Platform.java +++ b/arduino-core/src/processing/app/Platform.java @@ -181,7 +181,7 @@ public class Platform { return list; } - public Map resolveDeviceByVendorIdProductId(String serial, Map packages) { + public synchronized Map resolveDeviceByVendorIdProductId(String serial, Map packages) { String vid_pid_iSerial = resolveDeviceAttachedToNative(serial); for (TargetPackage targetPackage : packages.values()) { for (TargetPlatform targetPlatform : targetPackage.getPlatforms().values()) { From ea405ea534771b695054aa1227c20109ee89cf47 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 25 Mar 2016 13:39:13 +0100 Subject: [PATCH 08/12] avoid NPE for synchronization issues on board list --- .../arduino/packages/discoverers/serial/SerialBoardsLister.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java b/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java index b4ac2da9d..4de3626f6 100644 --- a/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java +++ b/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java @@ -54,7 +54,7 @@ public class SerialBoardsLister extends TimerTask { timer.schedule(this, 0, 1000); } - public void retriggerDiscovery() { + public synchronized void retriggerDiscovery() { while (BaseNoGui.packages == null) { try { Thread.sleep(1000); From c5d88f09aecf35ee16ec09fa3c78495ab1817dcb Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 25 Mar 2016 17:02:19 +0100 Subject: [PATCH 09/12] add a flag to pause polling for serial port --- .../cc/arduino/packages/discoverers/SerialDiscovery.java | 4 +++- .../packages/discoverers/serial/SerialBoardsLister.java | 9 +++++++-- .../cc/arduino/packages/uploaders/SerialUploader.java | 9 +++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/arduino-core/src/cc/arduino/packages/discoverers/SerialDiscovery.java b/arduino-core/src/cc/arduino/packages/discoverers/SerialDiscovery.java index 565e80e90..3e6646d67 100644 --- a/arduino-core/src/cc/arduino/packages/discoverers/SerialDiscovery.java +++ b/arduino-core/src/cc/arduino/packages/discoverers/SerialDiscovery.java @@ -75,13 +75,15 @@ public class SerialDiscovery implements Discovery { } public void forceRefresh() { - serialBoardsLister.retriggerDiscovery(); + serialBoardsLister.retriggerDiscovery(false); } public void setUploadInProgress(boolean param) { serialBoardsLister.uploadInProgress = param; } + public void pausePolling(boolean param) { serialBoardsLister.pausePolling = param;} + @Override public void start() { this.serialBoardsListerTimer = new Timer(SerialBoardsLister.class.getName()); diff --git a/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java b/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java index 4de3626f6..0cafed956 100644 --- a/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java +++ b/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java @@ -44,6 +44,7 @@ public class SerialBoardsLister extends TimerTask { private final List boardPorts = new LinkedList<>(); private List oldPorts = new LinkedList<>(); public boolean uploadInProgress = false; + public boolean pausePolling = false; private BoardPort oldUploadBoardPort = null; public SerialBoardsLister(SerialDiscovery serialDiscovery) { @@ -54,7 +55,7 @@ public class SerialBoardsLister extends TimerTask { timer.schedule(this, 0, 1000); } - public synchronized void retriggerDiscovery() { + public synchronized void retriggerDiscovery(boolean polled) { while (BaseNoGui.packages == null) { try { Thread.sleep(1000); @@ -67,6 +68,10 @@ public class SerialBoardsLister extends TimerTask { return; } + if (polled && pausePolling) { + return; + } + List ports = platform.listSerials(); if (ports.equals(oldPorts)) { return; @@ -163,6 +168,6 @@ public class SerialBoardsLister extends TimerTask { @Override public void run() { - retriggerDiscovery(); + retriggerDiscovery(true); } } diff --git a/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java b/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java index 064e04cfa..19d8a802d 100644 --- a/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java +++ b/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java @@ -91,6 +91,8 @@ public class SerialUploader extends Uploader { return uploadUsingProgrammer(buildPath, className); } + BaseNoGui.getDiscoveryManager().getSerialDiscoverer().pausePolling(true); + if (noUploadPort) { prefs.put("build.path", buildPath); @@ -107,6 +109,8 @@ public class SerialUploader extends Uploader { uploadResult = executeUploadCommand(cmd); } catch (Exception e) { throw new RunnerException(e); + } finally { + BaseNoGui.getDiscoveryManager().getSerialDiscoverer().pausePolling(false); } return uploadResult; } @@ -148,6 +152,8 @@ public class SerialUploader extends Uploader { throw new RunnerException(e); } catch (InterruptedException e) { throw new RunnerException(e.getMessage()); + } finally { + BaseNoGui.getDiscoveryManager().getSerialDiscoverer().pausePolling(false); } if (actualUploadPort == null) { actualUploadPort = userSelectedUploadPort; @@ -183,9 +189,12 @@ public class SerialUploader extends Uploader { throw e; } catch (Exception e) { throw new RunnerException(e); + } finally { + BaseNoGui.getDiscoveryManager().getSerialDiscoverer().pausePolling(false); } BaseNoGui.getDiscoveryManager().getSerialDiscoverer().setUploadInProgress(false); + BaseNoGui.getDiscoveryManager().getSerialDiscoverer().pausePolling(false); String finalUploadPort = null; if (uploadResult && doTouch) { From a6a623658d97036b1a45ea038c2ebefcc5bebef3 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 1 Apr 2016 11:40:32 +0200 Subject: [PATCH 10/12] update libListSerials to 1.1.0 --- build/build.xml | 25 +++++++++++++------------ build/liblistSerials-1.0.5.zip.sha | 1 - build/liblistSerials-1.1.0.zip.sha | 1 + 3 files changed, 14 insertions(+), 13 deletions(-) delete mode 100644 build/liblistSerials-1.0.5.zip.sha create mode 100644 build/liblistSerials-1.1.0.zip.sha diff --git a/build/build.xml b/build/build.xml index 43464da19..444c6502b 100644 --- a/build/build.xml +++ b/build/build.xml @@ -78,6 +78,7 @@ + @@ -436,12 +437,12 @@ - - - + + + - + @@ -639,12 +640,12 @@ - - - + + + - + @@ -908,12 +909,12 @@ - - - + + + - + diff --git a/build/liblistSerials-1.0.5.zip.sha b/build/liblistSerials-1.0.5.zip.sha deleted file mode 100644 index 6484b2fbc..000000000 --- a/build/liblistSerials-1.0.5.zip.sha +++ /dev/null @@ -1 +0,0 @@ -edb1c858a243e465f5797d7e5d0baa66daa1eba0 diff --git a/build/liblistSerials-1.1.0.zip.sha b/build/liblistSerials-1.1.0.zip.sha new file mode 100644 index 000000000..f4bc4a9a2 --- /dev/null +++ b/build/liblistSerials-1.1.0.zip.sha @@ -0,0 +1 @@ +05e942bc85e46a2b59e01fe1333dd9472e465654 From 72c337d88df24b980268df844dfa920d73939d69 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 5 Apr 2016 19:08:16 +0200 Subject: [PATCH 11/12] avoid losing the sketch serial port on 1200bps touch --- .../src/cc/arduino/packages/uploaders/SerialUploader.java | 1 - 1 file changed, 1 deletion(-) diff --git a/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java b/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java index 19d8a802d..a850e23f7 100644 --- a/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java +++ b/arduino-core/src/cc/arduino/packages/uploaders/SerialUploader.java @@ -214,7 +214,6 @@ public class SerialUploader extends Uploader { } Thread.sleep(250); } - finalUploadPort = actualUploadPort; } } catch (InterruptedException ex) { // noop From bf11c7f3950c2bea4a4cd2ec9b8e8a870c5730f2 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 6 Apr 2016 17:52:24 +0200 Subject: [PATCH 12/12] avoid queuing a lot of threads while waiting for platform --- .../discoverers/serial/SerialBoardsLister.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java b/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java index 0cafed956..77d2922e7 100644 --- a/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java +++ b/arduino-core/src/cc/arduino/packages/discoverers/serial/SerialBoardsLister.java @@ -56,13 +56,6 @@ public class SerialBoardsLister extends TimerTask { } public synchronized void retriggerDiscovery(boolean polled) { - while (BaseNoGui.packages == null) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // noop - } - } Platform platform = BaseNoGui.getPlatform(); if (platform == null) { return; @@ -103,6 +96,11 @@ public class SerialBoardsLister extends TimerTask { String[] parts = newPort.split("_"); String port = parts[0]; + if (parts.length != 3) { + // something went horribly wrong + continue; + } + Map boardData = platform.resolveDeviceByVendorIdProductId(port, BaseNoGui.packages); BoardPort boardPort = null; @@ -168,6 +166,9 @@ public class SerialBoardsLister extends TimerTask { @Override public void run() { + if (BaseNoGui.packages == null) { + return; + } retriggerDiscovery(true); } }