Refactored port (Serial and Network) discovery.

This commit is contained in:
Cristian Maglie 2013-06-02 19:02:57 +02:00
parent 22a84c69d3
commit ab6eb0843c
11 changed files with 306 additions and 113 deletions

View File

@ -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;
}
}

View File

@ -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<BoardPort> discovery();
}

View File

@ -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<Discovery> discoverers = new ArrayList<Discovery>();
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<BoardPort> discovery() {
List<BoardPort> res = new ArrayList<BoardPort>();
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();
}
});
}

View File

@ -0,0 +1,5 @@
package cc.arduino.packages;
public interface Uploader {
}

View File

@ -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<BoardPort> ports = new CopyOnWriteArrayList<BoardPort>();
@Override
public List<BoardPort> 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);
}
}

View File

@ -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<BoardPort> discovery() {
Platform os = Base.getPlatform();
String devicesListOutput = os.preListAllCandidateDevices();
List<BoardPort> res = new ArrayList<BoardPort>();
@SuppressWarnings("unchecked")
Enumeration<CommPortIdentifier> 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() {
}
}

View File

@ -0,0 +1,7 @@
package cc.arduino.packages.uploaders;
import cc.arduino.packages.Uploader;
public class SerialUploader implements Uploader {
}

View File

@ -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<String, Object> board = new HashMap<String, Object>();
board.put("addresses", serviceEvent.getInfo().getInet4Addresses());
board.put("type", serviceEvent.getType());
Base.this.boardsViaNetwork.put(serviceEvent.getName(), board);
}
});
}
public Map<String, Map<String, Object>> getBoardsViaNetwork() {
@ -2912,4 +2898,8 @@ public class Base {
FileUtils.recursiveDelete(tmpFolder);
}
}
public static DiscoveryManager getDiscoveryManager() {
return discoveryManager;
}
}

View File

@ -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<BoardPort> 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<String, Map<String, Object>> 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."));

View File

@ -1,11 +0,0 @@
package processing.app.zeroconf;
import javax.jmdns.ServiceEvent;
public interface BoardListener {
void boardOffline(ServiceEvent serviceEvent);
void boardOnline(ServiceEvent serviceEvent);
}

View File

@ -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);
}
}