diff --git a/app/src/cc/arduino/packages/BoardPort.java b/app/src/cc/arduino/packages/BoardPort.java new file mode 100644 index 000000000..3e636b5cb --- /dev/null +++ b/app/src/cc/arduino/packages/BoardPort.java @@ -0,0 +1,44 @@ +package cc.arduino.packages; + +import processing.app.helpers.PreferencesMap; + +public class BoardPort { + + private String address; + private String protocol; + private String boardName; + private PreferencesMap prefs; + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getBoardName() { + return boardName; + } + + public void setBoardName(String boardName) { + this.boardName = boardName; + } + + public void setPrefs(PreferencesMap prefs) { + this.prefs = prefs; + } + + public PreferencesMap getPrefs() { + return prefs; + } + +} diff --git a/app/src/cc/arduino/packages/Discovery.java b/app/src/cc/arduino/packages/Discovery.java new file mode 100644 index 000000000..60cb54708 --- /dev/null +++ b/app/src/cc/arduino/packages/Discovery.java @@ -0,0 +1,35 @@ +package cc.arduino.packages; + +import java.util.List; + +import processing.app.helpers.PreferencesMap; + +public interface Discovery { + + /** + * Set discovery preferences + * + * @param options + */ + public void setPreferences(PreferencesMap options); + + /** + * Start discovery service + * + * @throws Exception + */ + public void start() throws Exception; + + /** + * Stop discovery service + */ + public void stop(); + + /** + * Return the list of discovered ports. + * + * @return + */ + public List discovery(); + +} diff --git a/app/src/cc/arduino/packages/DiscoveryManager.java b/app/src/cc/arduino/packages/DiscoveryManager.java new file mode 100644 index 000000000..4a002755f --- /dev/null +++ b/app/src/cc/arduino/packages/DiscoveryManager.java @@ -0,0 +1,46 @@ +package cc.arduino.packages; + +import static processing.app.I18n._; + +import java.util.ArrayList; +import java.util.List; + +import cc.arduino.packages.discoverers.NetworkDiscovery; +import cc.arduino.packages.discoverers.SerialDiscovery; + +public class DiscoveryManager { + + private List discoverers = new ArrayList(); + + public DiscoveryManager() { + discoverers.add(new SerialDiscovery()); + discoverers.add(new NetworkDiscovery()); + + // Start all discoverers + for (Discovery d : discoverers) { + try { + d.start(); + } catch (Exception e) { + System.err.println(_("Error starting discovery method: ") + d.getClass()); + e.printStackTrace(); + } + } + + Runtime.getRuntime().addShutdownHook(closeHook); + } + + public List discovery() { + List res = new ArrayList(); + for (Discovery d : discoverers) + res.addAll(d.discovery()); + return res; + } + + private Thread closeHook = new Thread(new Runnable() { + @Override + public void run() { + for (Discovery d : discoverers) + d.stop(); + } + }); +} diff --git a/app/src/cc/arduino/packages/Uploader.java b/app/src/cc/arduino/packages/Uploader.java new file mode 100644 index 000000000..f7e862104 --- /dev/null +++ b/app/src/cc/arduino/packages/Uploader.java @@ -0,0 +1,5 @@ +package cc.arduino.packages; + +public interface Uploader { + +} diff --git a/app/src/cc/arduino/packages/discoverers/NetworkDiscovery.java b/app/src/cc/arduino/packages/discoverers/NetworkDiscovery.java new file mode 100644 index 000000000..ae05f8366 --- /dev/null +++ b/app/src/cc/arduino/packages/discoverers/NetworkDiscovery.java @@ -0,0 +1,87 @@ +package cc.arduino.packages.discoverers; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.jmdns.JmDNS; +import javax.jmdns.NetworkTopologyDiscovery; +import javax.jmdns.ServiceEvent; +import javax.jmdns.ServiceInfo; +import javax.jmdns.ServiceListener; +import javax.jmdns.impl.DNSTaskStarter; + +import processing.app.helpers.PreferencesMap; +import processing.app.zeroconf.jmdns.ArduinoDNSTaskStarter; +import cc.arduino.packages.BoardPort; +import cc.arduino.packages.Discovery; + +public class NetworkDiscovery implements Discovery, ServiceListener { + + private JmDNS jmDNS; + private List ports = new CopyOnWriteArrayList(); + + @Override + public List discovery() { + return ports; + } + + @Override + public void setPreferences(PreferencesMap options) { + } + + @Override + public void start() throws IOException { + DNSTaskStarter.Factory.setClassDelegate(new ArduinoDNSTaskStarter()); + for (InetAddress addr : NetworkTopologyDiscovery.Factory.getInstance() + .getInetAddresses()) { + jmDNS = JmDNS.create(addr); + jmDNS.addServiceListener("_arduino._tcp.local.", this); + } + } + + @Override + public void stop() { + try { + jmDNS.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void serviceAdded(ServiceEvent serviceEvent) { + String type = serviceEvent.getType(); + String name = serviceEvent.getName(); + + JmDNS dns = serviceEvent.getDNS(); + + dns.requestServiceInfo(type, name); + ServiceInfo serviceInfo = dns.getServiceInfo(type, name); + if (serviceInfo != null) + dns.requestServiceInfo(type, name); + } + + @Override + public void serviceRemoved(ServiceEvent serviceEvent) { + String name = serviceEvent.getName(); + for (BoardPort port : ports) { + if (port.getBoardName().equals(name)) + ports.remove(port); + } + } + + @Override + public void serviceResolved(ServiceEvent serviceEvent) { + String address = serviceEvent.getInfo().getInet4Addresses()[0].getHostAddress(); + String name = serviceEvent.getName(); + + BoardPort port = new BoardPort(); + port.setAddress(address); + port.setBoardName(name); + port.setProtocol("network"); + ports.add(port); + } + +} diff --git a/app/src/cc/arduino/packages/discoverers/SerialDiscovery.java b/app/src/cc/arduino/packages/discoverers/SerialDiscovery.java new file mode 100644 index 000000000..a94e21287 --- /dev/null +++ b/app/src/cc/arduino/packages/discoverers/SerialDiscovery.java @@ -0,0 +1,55 @@ +package cc.arduino.packages.discoverers; + +import gnu.io.CommPortIdentifier; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import processing.app.Base; +import processing.app.Platform; +import processing.app.helpers.PreferencesMap; +import cc.arduino.packages.BoardPort; +import cc.arduino.packages.Discovery; + +public class SerialDiscovery implements Discovery { + + @Override + public List discovery() { + Platform os = Base.getPlatform(); + String devicesListOutput = os.preListAllCandidateDevices(); + + List res = new ArrayList(); + @SuppressWarnings("unchecked") + Enumeration ports = CommPortIdentifier + .getPortIdentifiers(); + while (ports.hasMoreElements()) { + CommPortIdentifier commPort = ports.nextElement(); + if (commPort.getPortType() != CommPortIdentifier.PORT_SERIAL) + continue; + + String address = commPort.getName(); + String boardName = os.resolveDeviceAttachedTo(address, Base.packages, + devicesListOutput); + BoardPort port = new BoardPort(); + port.setAddress(address); + port.setProtocol("serial"); + port.setBoardName(boardName); + res.add(port); + } + return res; + } + + @Override + public void setPreferences(PreferencesMap options) { + } + + @Override + public void start() { + } + + @Override + public void stop() { + } + +} diff --git a/app/src/cc/arduino/packages/uploaders/SerialUploader.java b/app/src/cc/arduino/packages/uploaders/SerialUploader.java new file mode 100644 index 000000000..7f05860f3 --- /dev/null +++ b/app/src/cc/arduino/packages/uploaders/SerialUploader.java @@ -0,0 +1,7 @@ +package cc.arduino.packages.uploaders; + +import cc.arduino.packages.Uploader; + +public class SerialUploader implements Uploader { + +} diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 1a103562f..cb2767534 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -29,12 +29,13 @@ import java.util.*; import java.util.List; import java.util.concurrent.ConcurrentHashMap; -import javax.jmdns.ServiceEvent; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import org.apache.commons.logging.impl.LogFactoryImpl; import org.apache.commons.logging.impl.NoOpLog; + +import cc.arduino.packages.DiscoveryManager; import processing.app.debug.TargetBoard; import processing.app.debug.TargetPackage; import processing.app.debug.TargetPlatform; @@ -46,8 +47,6 @@ import processing.app.helpers.filefilters.OnlyFilesWithExtension; import processing.app.packages.Library; import processing.app.packages.LibraryList; import processing.app.tools.ZipDeflater; -import processing.app.zeroconf.BoardListener; -import processing.app.zeroconf.Discovery; import processing.core.*; import static processing.app.I18n._; @@ -80,6 +79,8 @@ public class Base { } static Platform platform; + private static DiscoveryManager discoveryManager = new DiscoveryManager(); + static private boolean commandLine; // A single instance of the preferences window @@ -411,21 +412,6 @@ public class Base { if (Preferences.getBoolean("update.check")) { new UpdateCheck(this); } - - new Discovery(new BoardListener() { - @Override - public void boardOffline(ServiceEvent serviceEvent) { - Base.this.boardsViaNetwork.remove(serviceEvent.getName()); - } - - @Override - public void boardOnline(ServiceEvent serviceEvent) { - Map board = new HashMap(); - board.put("addresses", serviceEvent.getInfo().getInet4Addresses()); - board.put("type", serviceEvent.getType()); - Base.this.boardsViaNetwork.put(serviceEvent.getName(), board); - } - }); } public Map> getBoardsViaNetwork() { @@ -2912,4 +2898,8 @@ public class Base { FileUtils.recursiveDelete(tmpFolder); } } + + public static DiscoveryManager getDiscoveryManager() { + return discoveryManager; + } } diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 84ed3afd7..e768a22b1 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -43,7 +43,7 @@ import javax.swing.event.*; import javax.swing.text.*; import javax.swing.undo.*; -import gnu.io.*; +import cc.arduino.packages.BoardPort; /** * Main editor panel for the Processing Development Environment. @@ -710,7 +710,7 @@ public class Editor extends JFrame implements RunnerListener { if (serialMenu == null) serialMenu = new JMenu(_("Port")); - populateSerialMenu(); + populatePortMenu(); menu.add(serialMenu); menu.addSeparator(); @@ -731,7 +731,7 @@ public class Editor extends JFrame implements RunnerListener { public void menuDeselected(MenuEvent e) {} public void menuSelected(MenuEvent e) { //System.out.println("Tools menu selected."); - populateSerialMenu(); + populatePortMenu(); } }); @@ -978,42 +978,22 @@ public class Editor extends JFrame implements RunnerListener { } - protected void populateSerialMenu() { + protected void populatePortMenu() { serialMenu.removeAll(); + + String selectedPort = Preferences.get("serial.port"); + + List ports = Base.getDiscoveryManager().discovery(); + for (BoardPort port : ports) { + String address = port.getAddress(); + String name = port.getBoardName(); - try - { - String devicesListOutput = Base.getPlatform().preListAllCandidateDevices(); - for (Enumeration enumeration = CommPortIdentifier.getPortIdentifiers(); enumeration.hasMoreElements();) - { - CommPortIdentifier commportidentifier = (CommPortIdentifier)enumeration.nextElement(); - //System.out.println("Found communication port: " + commportidentifier); - if (commportidentifier.getPortType() == CommPortIdentifier.PORT_SERIAL) { - //System.out.println("Adding port to serial port menu: " + commportidentifier); - String curr_port = commportidentifier.getName(); - - String description = curr_port; - String additionalDescription = Base.getPlatform().resolveDeviceAttachedTo(curr_port, Base.packages, devicesListOutput); - if (additionalDescription != null) { - description += " (" + additionalDescription + ")"; - } - JCheckBoxMenuItem rbMenuItem = new JCheckBoxMenuItem(description, curr_port.equals(Preferences.get("serial.port"))); - rbMenuItem.addActionListener(new SerialMenuListener(curr_port)); - //serialGroup.add(rbMenuItem); - serialMenu.add(rbMenuItem); - } - } - } catch (Exception exception) { - System.out.println(_("error retrieving port list")); - exception.printStackTrace(); - } - - for (Map.Entry> entry : base.getBoardsViaNetwork().entrySet()) { - Inet4Address[] addresses = (Inet4Address[]) entry.getValue().get("addresses"); - String label = addresses[0].getHostAddress() + " (" + entry.getKey() + ")"; - JCheckBoxMenuItem rbMenuItem = new JCheckBoxMenuItem(label, label.equals(Preferences.get("serial.port"))); - rbMenuItem.addActionListener(new SerialMenuListener(label)); - serialMenu.add(rbMenuItem); + String label = address; + if (name != null) + label += " (" + name + ")"; + JCheckBoxMenuItem item = new JCheckBoxMenuItem(label, address.equals(selectedPort)); + item.addActionListener(new SerialMenuListener(address)); + serialMenu.add(item); } serialMenu.setEnabled(serialMenu.getMenuComponentCount() > 0); @@ -2417,7 +2397,7 @@ public class Editor extends JFrame implements RunnerListener { // error message will already be visible } } catch (SerialNotFoundException e) { - populateSerialMenu(); + populatePortMenu(); if (serialMenu.getItemCount() == 0) statusError(e); else if (serialPrompt()) run(); else statusNotice(_("Upload canceled.")); @@ -2453,7 +2433,7 @@ public class Editor extends JFrame implements RunnerListener { // error message will already be visible } } catch (SerialNotFoundException e) { - populateSerialMenu(); + populatePortMenu(); if (serialMenu.getItemCount() == 0) statusError(e); else if (serialPrompt()) run(); else statusNotice(_("Upload canceled.")); diff --git a/app/src/processing/app/zeroconf/BoardListener.java b/app/src/processing/app/zeroconf/BoardListener.java deleted file mode 100644 index dae2d4125..000000000 --- a/app/src/processing/app/zeroconf/BoardListener.java +++ /dev/null @@ -1,11 +0,0 @@ -package processing.app.zeroconf; - -import javax.jmdns.ServiceEvent; - -public interface BoardListener { - - void boardOffline(ServiceEvent serviceEvent); - - void boardOnline(ServiceEvent serviceEvent); - -} diff --git a/app/src/processing/app/zeroconf/Discovery.java b/app/src/processing/app/zeroconf/Discovery.java deleted file mode 100644 index 71d54c5a7..000000000 --- a/app/src/processing/app/zeroconf/Discovery.java +++ /dev/null @@ -1,45 +0,0 @@ -package processing.app.zeroconf; - -import processing.app.zeroconf.jmdns.ArduinoDNSTaskStarter; - -import javax.jmdns.*; -import javax.jmdns.impl.DNSTaskStarter; -import java.io.IOException; -import java.net.InetAddress; - -public class Discovery implements ServiceListener { - - private final BoardListener listener; - - static { - DNSTaskStarter.Factory.setClassDelegate(new ArduinoDNSTaskStarter()); - } - - public Discovery(BoardListener listener) throws IOException { - this.listener = listener; - for (InetAddress addr : NetworkTopologyDiscovery.Factory.getInstance().getInetAddresses()) { - JmDNS jmDNS = JmDNS.create(addr); - jmDNS.addServiceListener("_arduino._tcp.local.", this); - } - } - - @Override - public void serviceAdded(ServiceEvent serviceEvent) { - serviceEvent.getDNS().requestServiceInfo(serviceEvent.getType(), serviceEvent.getName()); - ServiceInfo serviceInfo = serviceEvent.getDNS().getServiceInfo(serviceEvent.getType(), serviceEvent.getName()); - if (serviceInfo != null) { - serviceEvent.getDNS().requestServiceInfo(serviceEvent.getType(), serviceEvent.getName()); - } - } - - @Override - public void serviceRemoved(ServiceEvent serviceEvent) { - listener.boardOffline(serviceEvent); - } - - @Override - public void serviceResolved(ServiceEvent serviceEvent) { - listener.boardOnline(serviceEvent); - } - -}