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()) {