new experimental feature: possibility to change mote types when loading a simulation

made compile dialogs only select mote interfaces specified in the loaded configuration
This commit is contained in:
Fredrik Osterlind 2012-05-23 14:59:41 +02:00
parent c651604a4f
commit 50caa3650c
7 changed files with 170 additions and 97 deletions

View file

@ -117,7 +117,7 @@ $(CONTIKI_APP).cooja: $(JNILIB)
cp $(JNILIB) $@ cp $(JNILIB) $@
rm $(CONTIKI_APP_OBJ) rm $(CONTIKI_APP_OBJ)
mtype%.o: contiki-cooja-main.o %.o: contiki-cooja-main.o
mv contiki-cooja-main.o $@ mv contiki-cooja-main.o $@
symbols.c: symbols.c:

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009, Swedish Institute of Computer Science. * Copyright (c) 2012, Swedish Institute of Computer Science.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -25,8 +25,6 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*
* $Id: MicaZCompileDialog.java,v 1.1 2009/09/17 10:45:14 fros4943 Exp $
*/ */
package se.sics.cooja.avrmote; package se.sics.cooja.avrmote;
@ -64,17 +62,10 @@ public class MicaZCompileDialog extends AbstractCompileDialog {
private MicaZCompileDialog(Container parent, Simulation simulation, MoteType moteType) { private MicaZCompileDialog(Container parent, Simulation simulation, MoteType moteType) {
super(parent, simulation, moteType); super(parent, simulation, moteType);
}
/* Add all available MicaZ mote interfaces public Class<? extends MoteInterface>[] getDefaultMoteInterfaces() {
* Selected by default unless interfaces already configured */ return ((MicaZMoteType)moteType).getAllMoteInterfaceClasses();
boolean selected = true;
if (moteIntfBox.getComponentCount() > 0) {
selected = false;
}
for (Class<? extends MoteInterface> intfClass: ((MicaZMoteType)moteType).getAllMoteInterfaceClasses()) {
addMoteInterface(intfClass, selected);
}
} }
public boolean canLoadFirmware(File file) { public boolean canLoadFirmware(File file) {
@ -98,7 +89,7 @@ public class MicaZCompileDialog extends AbstractCompileDialog {
public void writeSettingsToMoteType() { public void writeSettingsToMoteType() {
/* Nothing to do */ /* Nothing to do */
} }
protected String getTargetName() { protected String getTargetName() {
return "micaz"; return "micaz";
} }

View file

@ -45,7 +45,7 @@ import se.sics.cooja.dialogs.AbstractCompileDialog;
public class MspCompileDialog extends AbstractCompileDialog { public class MspCompileDialog extends AbstractCompileDialog {
private static final long serialVersionUID = -7273193946433145019L; private static final long serialVersionUID = -7273193946433145019L;
private static String target; private final String target;
public static boolean showDialog( public static boolean showDialog(
Container parent, Container parent,
@ -53,7 +53,6 @@ public class MspCompileDialog extends AbstractCompileDialog {
MspMoteType moteType, MspMoteType moteType,
String target) { String target) {
MspCompileDialog.target = target;
final AbstractCompileDialog dialog = new MspCompileDialog(parent, simulation, moteType, target); final AbstractCompileDialog dialog = new MspCompileDialog(parent, simulation, moteType, target);
/* Show dialog and wait for user */ /* Show dialog and wait for user */
@ -68,18 +67,13 @@ public class MspCompileDialog extends AbstractCompileDialog {
private MspCompileDialog(Container parent, Simulation simulation, MspMoteType moteType, String target) { private MspCompileDialog(Container parent, Simulation simulation, MspMoteType moteType, String target) {
super(parent, simulation, moteType); super(parent, simulation, moteType);
this.target = target;
setTitle("Create Mote Type: Compile Contiki for " + target); setTitle("Create Mote Type: Compile Contiki for " + target);
addCompilationTipsTab(tabbedPane);
/* Select all mote interfaces */ }
boolean selected = true;
if (moteIntfBox.getComponentCount() > 0) {
selected = false;
}
for (Class<? extends MoteInterface> intfClass: moteType.getAllMoteInterfaceClasses()) {
addMoteInterface(intfClass, selected);
}
addCompilationTipsTab(tabbedPane); public Class<? extends MoteInterface>[] getDefaultMoteInterfaces() {
return ((MspMoteType)moteType).getAllMoteInterfaceClasses();
} }
private void addCompilationTipsTab(JTabbedPane parent) { private void addCompilationTipsTab(JTabbedPane parent) {
@ -89,10 +83,10 @@ public class MspCompileDialog extends AbstractCompileDialog {
"DEFINES=NETSTACK_MAC=nullmac_driver,NETSTACK_RDC=nullrdc_noframer_driver,CC2420_CONF_AUTOACK=0\n" + "DEFINES=NETSTACK_MAC=nullmac_driver,NETSTACK_RDC=nullrdc_noframer_driver,CC2420_CONF_AUTOACK=0\n" +
"# (remember to \"make clean\" after changing compilation flags)" "# (remember to \"make clean\" after changing compilation flags)"
); );
parent.addTab("Tips", null, new JScrollPane(textArea), "Compilation tips"); parent.addTab("Tips", null, new JScrollPane(textArea), "Compilation tips");
} }
public boolean canLoadFirmware(File file) { public boolean canLoadFirmware(File file) {
if (file.getName().endsWith("." + target)) { if (file.getName().endsWith("." + target)) {
return true; return true;
@ -106,7 +100,7 @@ public class MspCompileDialog extends AbstractCompileDialog {
public String getDefaultCompileCommands(File source) { public String getDefaultCompileCommands(File source) {
/* TODO Split into String[] */ /* TODO Split into String[] */
return return
GUI.getExternalToolsSetting("PATH_MAKE") + " " + GUI.getExternalToolsSetting("PATH_MAKE") + " " +
getExpectedFirmwareFile(source).getName() + " TARGET=" + target; getExpectedFirmwareFile(source).getName() + " TARGET=" + target;
} }
@ -117,7 +111,7 @@ public class MspCompileDialog extends AbstractCompileDialog {
public void writeSettingsToMoteType() { public void writeSettingsToMoteType() {
/* Nothing to do */ /* Nothing to do */
} }
protected String getTargetName() { protected String getTargetName() {
/* Override me */ /* Override me */
return target; return target;

View file

@ -37,6 +37,8 @@ import java.util.Observer;
import java.util.Random; import java.util.Random;
import java.util.Vector; import java.util.Vector;
import javax.swing.JOptionPane;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.jdom.Element; import org.jdom.Element;
@ -56,7 +58,7 @@ public class Simulation extends Observable implements Runnable {
public static final long MILLISECOND = 1000*MICROSECOND; public static final long MILLISECOND = 1000*MICROSECOND;
/*private static long EVENT_COUNTER = 0;*/ /*private static long EVENT_COUNTER = 0;*/
private Vector<Mote> motes = new Vector<Mote>(); private Vector<Mote> motes = new Vector<Mote>();
private Vector<MoteType> moteTypes = new Vector<MoteType>(); private Vector<MoteType> moteTypes = new Vector<MoteType>();
@ -109,7 +111,7 @@ public class Simulation extends Observable implements Runnable {
* Request poll from simulation thread. * Request poll from simulation thread.
* Poll requests are prioritized over simulation events, and are * Poll requests are prioritized over simulation events, and are
* executed between each simulation event. * executed between each simulation event.
* *
* @param r Simulation thread action * @param r Simulation thread action
*/ */
public void invokeSimulationThread(Runnable r) { public void invokeSimulationThread(Runnable r) {
@ -127,7 +129,7 @@ public class Simulation extends Observable implements Runnable {
} }
return r; return r;
} }
/** /**
* Add millisecond observer. * Add millisecond observer.
* This observer is notified once every simulated millisecond. * This observer is notified once every simulated millisecond.
@ -143,7 +145,7 @@ public class Simulation extends Observable implements Runnable {
public void run() { public void run() {
if (!millisecondEvent.isScheduled()) { if (!millisecondEvent.isScheduled()) {
scheduleEvent( scheduleEvent(
millisecondEvent, millisecondEvent,
currentSimulationTime - (currentSimulationTime % MILLISECOND) + MILLISECOND); currentSimulationTime - (currentSimulationTime % MILLISECOND) + MILLISECOND);
} }
} }
@ -173,7 +175,7 @@ public class Simulation extends Observable implements Runnable {
* Already scheduled events must be removed before they are rescheduled. * Already scheduled events must be removed before they are rescheduled.
* *
* If the simulation is running, this method may only be called from the simulation thread. * If the simulation is running, this method may only be called from the simulation thread.
* *
* @see #invokeSimulationThread(Runnable) * @see #invokeSimulationThread(Runnable)
* *
* @param e Event * @param e Event
@ -237,12 +239,12 @@ public class Simulation extends Observable implements Runnable {
return "MILLISECOND: " + millisecondObservable.countObservers(); return "MILLISECOND: " + millisecondObservable.countObservers();
} }
}; };
public void clearEvents() { public void clearEvents() {
eventQueue.removeAll(); eventQueue.removeAll();
pollRequests.clear(); pollRequests.clear();
} }
public void run() { public void run() {
long lastStartTime = System.currentTimeMillis(); long lastStartTime = System.currentTimeMillis();
logger.info("Simulation main loop started, system time: " + lastStartTime); logger.info("Simulation main loop started, system time: " + lastStartTime);
@ -261,7 +263,7 @@ public class Simulation extends Observable implements Runnable {
while (hasPollRequests) { while (hasPollRequests) {
popSimulationInvokes().run(); popSimulationInvokes().run();
} }
/* Handle one simulation event, and update simulation time */ /* Handle one simulation event, and update simulation time */
nextEvent = eventQueue.popFirst(); nextEvent = eventQueue.popFirst();
if (nextEvent == null) { if (nextEvent == null) {
@ -303,7 +305,7 @@ public class Simulation extends Observable implements Runnable {
this.setChanged(); this.setChanged();
this.notifyObservers(this); this.notifyObservers(this);
logger.info("Simulation main loop stopped, system time: " + System.currentTimeMillis() + logger.info("Simulation main loop stopped, system time: " + System.currentTimeMillis() +
"\tDuration: " + (System.currentTimeMillis() - lastStartTime) + "\tDuration: " + (System.currentTimeMillis() - lastStartTime) +
" ms" + " ms" +
"\tSimulated time " + getSimulationTimeMillis() + "\tSimulated time " + getSimulationTimeMillis() +
@ -333,9 +335,9 @@ public class Simulation extends Observable implements Runnable {
/** /**
* Stop simulation * Stop simulation
* *
* @param block Block until simulation has stopped, with timeout (100ms) * @param block Block until simulation has stopped, with timeout (100ms)
* *
* @see #stopSimulation() * @see #stopSimulation()
*/ */
public void stopSimulation(boolean block) { public void stopSimulation(boolean block) {
@ -363,7 +365,7 @@ public class Simulation extends Observable implements Runnable {
/** /**
* Stop simulation (blocks). * Stop simulation (blocks).
* Calls stopSimulation(true). * Calls stopSimulation(true).
* *
* @see #stopSimulation(boolean) * @see #stopSimulation(boolean)
*/ */
public void stopSimulation() { public void stopSimulation() {
@ -454,7 +456,7 @@ public class Simulation extends Observable implements Runnable {
public SimEventCentral getEventCentral() { public SimEventCentral getEventCentral() {
return eventCentral; return eventCentral;
} }
/** /**
* Returns the current simulation config represented by XML elements. This * Returns the current simulation config represented by XML elements. This
* config also includes the current radio medium, all mote types and motes. * config also includes the current radio medium, all mote types and motes.
@ -525,12 +527,12 @@ public class Simulation extends Observable implements Runnable {
if (moteConfig == null) { if (moteConfig == null) {
moteConfig = new ArrayList<Element>(); moteConfig = new ArrayList<Element>();
} }
/* Add mote type identifier */ /* Add mote type identifier */
Element typeIdentifier = new Element("motetype_identifier"); Element typeIdentifier = new Element("motetype_identifier");
typeIdentifier.setText(mote.getType().getIdentifier()); typeIdentifier.setText(mote.getType().getIdentifier());
moteConfig.add(typeIdentifier); moteConfig.add(typeIdentifier);
element.addContent(moteConfig); element.addContent(moteConfig);
config.add(element); config.add(element);
} }
@ -540,7 +542,7 @@ public class Simulation extends Observable implements Runnable {
/** /**
* Sets the current simulation config depending on the given configuration. * Sets the current simulation config depending on the given configuration.
* *
* @param configXML Simulation configuration * @param configXML Simulation configuration
* @param visAvailable True if simulation is allowed to show visualizers * @param visAvailable True if simulation is allowed to show visualizers
* @param manualRandomSeed Simulation random seed. May be null, in which case the configuration is used * @param manualRandomSeed Simulation random seed. May be null, in which case the configuration is used
@ -566,7 +568,7 @@ public class Simulation extends Observable implements Runnable {
// Random seed // Random seed
if (element.getName().equals("randomseed")) { if (element.getName().equals("randomseed")) {
long newSeed; long newSeed;
if (element.getText().equals("generated")) { if (element.getText().equals("generated")) {
randomSeedGenerated = true; randomSeedGenerated = true;
newSeed = new Random().nextLong(); newSeed = new Random().nextLong();
@ -634,6 +636,25 @@ public class Simulation extends Observable implements Runnable {
if (element.getName().equals("motetype")) { if (element.getName().equals("motetype")) {
String moteTypeClassName = element.getText().trim(); String moteTypeClassName = element.getText().trim();
/* Try to recreate simulation using a different mote type */
if (visAvailable) {
String[] availableMoteTypes = getGUI().getProjectConfig().getStringArrayValue("se.sics.cooja.GUI.MOTETYPES");
String newClass = (String) JOptionPane.showInputDialog(
GUI.getTopParentContainer(),
"The simulation is about to load '" + moteTypeClassName + "'\n" +
"You may try to load the simulation using a different mote type.\n",
"Loading mote type",
JOptionPane.QUESTION_MESSAGE,
null,
availableMoteTypes,
moteTypeClassName
);
if (newClass != null && !newClass.equals(moteTypeClassName)) {
logger.warn("Changing mote type class: " + moteTypeClassName + " -> " + newClass);
moteTypeClassName = newClass;
}
}
Class<? extends MoteType> moteTypeClass = myGUI.tryLoadClass(this, Class<? extends MoteType> moteTypeClass = myGUI.tryLoadClass(this,
MoteType.class, moteTypeClassName); MoteType.class, moteTypeClassName);
@ -672,7 +693,7 @@ public class Simulation extends Observable implements Runnable {
if (moteType == null) { if (moteType == null) {
throw new Exception("No mote type specified for mote"); throw new Exception("No mote type specified for mote");
} }
/* Create mote using mote type */ /* Create mote using mote type */
Mote mote = moteType.generateMote(this); Mote mote = moteType.generateMote(this);
if (mote.setConfigXML(this, element.getChildren(), visAvailable)) { if (mote.setConfigXML(this, element.getChildren(), visAvailable)) {
@ -694,12 +715,12 @@ public class Simulation extends Observable implements Runnable {
setChanged(); setChanged();
notifyObservers(this); notifyObservers(this);
/* Execute simulation thread events now, before simulation starts */ /* Execute simulation thread events now, before simulation starts */
while (hasPollRequests) { while (hasPollRequests) {
popSimulationInvokes().run(); popSimulationInvokes().run();
} }
return true; return true;
} }
@ -716,7 +737,7 @@ public class Simulation extends Observable implements Runnable {
public void run() { public void run() {
motes.remove(mote); motes.remove(mote);
currentRadioMedium.unregisterMote(mote, Simulation.this); currentRadioMedium.unregisterMote(mote, Simulation.this);
/* Dispose mote interface resources */ /* Dispose mote interface resources */
mote.removed(); mote.removed();
for (MoteInterface i: mote.getInterfaces().getInterfaces()) { for (MoteInterface i: mote.getInterfaces().getInterfaces()) {
@ -747,7 +768,7 @@ public class Simulation extends Observable implements Runnable {
/* Remove mote from simulation thread */ /* Remove mote from simulation thread */
invokeSimulationThread(removeMote); invokeSimulationThread(removeMote);
} }
getGUI().closeMotePlugins(mote); getGUI().closeMotePlugins(mote);
} }
@ -760,14 +781,14 @@ public class Simulation extends Observable implements Runnable {
if (currentRadioMedium != null) { if (currentRadioMedium != null) {
currentRadioMedium.removed(); currentRadioMedium.removed();
} }
/* Remove all motes */ /* Remove all motes */
Mote[] motes = getMotes(); Mote[] motes = getMotes();
for (Mote m: motes) { for (Mote m: motes) {
removeMote(m); removeMote(m);
} }
} }
/** /**
* Adds a mote to this simulation * Adds a mote to this simulation
* *
@ -787,7 +808,7 @@ public class Simulation extends Observable implements Runnable {
mote.getInterfaces().getClock().setDrift(-getSimulationTime()); mote.getInterfaces().getClock().setDrift(-getSimulationTime());
} }
} }
motes.add(mote); motes.add(mote);
currentRadioMedium.registerMote(mote, Simulation.this); currentRadioMedium.registerMote(mote, Simulation.this);
@ -795,12 +816,12 @@ public class Simulation extends Observable implements Runnable {
for (MoteInterface i: mote.getInterfaces().getInterfaces()) { for (MoteInterface i: mote.getInterfaces().getInterfaces()) {
i.added(); i.added();
} }
setChanged(); setChanged();
notifyObservers(mote); notifyObservers(mote);
} }
}; };
if (!isRunning()) { if (!isRunning()) {
/* Simulation is stopped, add mote immediately */ /* Simulation is stopped, add mote immediately */
addMote.run(); addMote.run();
@ -821,10 +842,10 @@ public class Simulation extends Observable implements Runnable {
public Mote getMote(int pos) { public Mote getMote(int pos) {
return motes.get(pos); return motes.get(pos);
} }
/** /**
* Returns simulation with with given ID. * Returns simulation with with given ID.
* *
* @param id ID * @param id ID
* @return Mote or null * @return Mote or null
* @see Mote#getID() * @see Mote#getID()
@ -899,7 +920,7 @@ public class Simulation extends Observable implements Runnable {
/** /**
* Remove given mote type from simulation. * Remove given mote type from simulation.
* *
* @param type Mote type * @param type Mote type
*/ */
public void removeMoteType(MoteType type) { public void removeMoteType(MoteType type) {
@ -907,7 +928,7 @@ public class Simulation extends Observable implements Runnable {
logger.fatal("Mote type is not registered: " + type); logger.fatal("Mote type is not registered: " + type);
return; return;
} }
/* Remove motes */ /* Remove motes */
for (Mote m: getMotes()) { for (Mote m: getMotes()) {
if (m.getType() == type) { if (m.getType() == type) {
@ -925,15 +946,15 @@ public class Simulation extends Observable implements Runnable {
* The simulation loop delays given value every simulated millisecond. * The simulation loop delays given value every simulated millisecond.
* If the value is zero there is no delay. * If the value is zero there is no delay.
* If the value is negative, the simulation loop delays 1ms every (-time) simulated milliseconds. * If the value is negative, the simulation loop delays 1ms every (-time) simulated milliseconds.
* *
* Examples: * Examples:
* time=0: no sleeping (simulation runs as fast as possible). * time=0: no sleeping (simulation runs as fast as possible).
* time=10: simulation delays 10ms every simulated millisecond. * time=10: simulation delays 10ms every simulated millisecond.
* time=-5: simulation delays 1ms every 5 simulated milliseconds. * time=-5: simulation delays 1ms every 5 simulated milliseconds.
* *
* Special case: * Special case:
* time=Integer.MIN_VALUE: simulation tries to execute at real time. * time=Integer.MIN_VALUE: simulation tries to execute at real time.
* *
* @param time New delay time value * @param time New delay time value
*/ */
public void setDelayTime(int time) { public void setDelayTime(int time) {
@ -949,12 +970,12 @@ public class Simulation extends Observable implements Runnable {
delayTime = time; delayTime = time;
delayPeriod = 1; /* minimum */ delayPeriod = 1; /* minimum */
} }
invokeSimulationThread(new Runnable() { invokeSimulationThread(new Runnable() {
public void run() { public void run() {
if (!delayEvent.isScheduled()) { if (!delayEvent.isScheduled()) {
scheduleEvent( scheduleEvent(
delayEvent, delayEvent,
currentSimulationTime - (currentSimulationTime % MILLISECOND) + MILLISECOND); currentSimulationTime - (currentSimulationTime % MILLISECOND) + MILLISECOND);
} }
Simulation.this.setChanged(); Simulation.this.setChanged();
@ -975,7 +996,7 @@ public class Simulation extends Observable implements Runnable {
if (delayPeriod == Integer.MIN_VALUE) { if (delayPeriod == Integer.MIN_VALUE) {
return Integer.MIN_VALUE; return Integer.MIN_VALUE;
} }
if (delayPeriod > 1) { if (delayPeriod > 1) {
return -delayPeriod; return -delayPeriod;
} }
@ -1007,7 +1028,7 @@ public class Simulation extends Observable implements Runnable {
/** /**
* Returns current simulation time rounded to milliseconds. * Returns current simulation time rounded to milliseconds.
* *
* @see #getSimulationTime() * @see #getSimulationTime()
* @return Time rounded to milliseconds * @return Time rounded to milliseconds
*/ */

View file

@ -1306,7 +1306,7 @@ public class ContikiMoteType implements MoteType {
element.setText(getDescription()); element.setText(getDescription());
config.add(element); config.add(element);
element = new Element("contikiapp"); element = new Element("source");
File file = simulation.getGUI().createPortablePath(getContikiSourceFile()); File file = simulation.getGUI().createPortablePath(getContikiSourceFile());
element.setText(file.getPath().replaceAll("\\\\", "/")); element.setText(file.getPath().replaceAll("\\\\", "/"));
config.add(element); config.add(element);
@ -1350,7 +1350,7 @@ public class ContikiMoteType implements MoteType {
identifier = element.getText(); identifier = element.getText();
} else if (name.equals("description")) { } else if (name.equals("description")) {
description = element.getText(); description = element.getText();
} else if (name.equals("contikiapp")) { } else if (name.equals("contikiapp") || name.equals("source")) {
File file = new File(element.getText()); File file = new File(element.getText());
if (!file.exists()) { if (!file.exists()) {
file = simulation.getGUI().restorePortablePath(file); file = simulation.getGUI().restorePortablePath(file);

View file

@ -25,27 +25,58 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*
* $Id: AbstractCompileDialog.java,v 1.9 2010/03/08 14:26:12 fros4943 Exp $
*/ */
package se.sics.cooja.dialogs; package se.sics.cooja.dialogs;
import java.awt.*; import java.awt.BorderLayout;
import java.awt.event.*; import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import javax.swing.*; import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener; import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileFilter;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import se.sics.cooja.*; import se.sics.cooja.GUI;
import se.sics.cooja.dialogs.MessageList; import se.sics.cooja.MoteInterface;
import se.sics.cooja.MoteType;
import se.sics.cooja.Simulation;
import se.sics.cooja.interfaces.MoteID; import se.sics.cooja.interfaces.MoteID;
import se.sics.cooja.interfaces.Position; import se.sics.cooja.interfaces.Position;
@ -259,7 +290,7 @@ public abstract class AbstractCompileDialog extends JDialog {
compileButton = new JButton(compileAction); compileButton = new JButton(compileAction);
getRootPane().setDefaultButton(compileButton); getRootPane().setDefaultButton(compileButton);
createButton = new JButton("Create"); createButton = new JButton("Create");
createButton.addActionListener(new ActionListener() { createButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
@ -330,10 +361,24 @@ public abstract class AbstractCompileDialog extends JDialog {
} }
/* Restore mote interface classes */ /* Restore mote interface classes */
for (Component c : moteIntfBox.getComponents()) {
if (!(c instanceof JCheckBox)) {
continue;
}
((JCheckBox) c).setSelected(false);
}
if (moteType.getMoteInterfaceClasses() != null) { if (moteType.getMoteInterfaceClasses() != null) {
for (Class<? extends MoteInterface> intfClass: getDefaultMoteInterfaces()) {
addMoteInterface(intfClass, false);
}
for (Class<? extends MoteInterface> intf: moteType.getMoteInterfaceClasses()) { for (Class<? extends MoteInterface> intf: moteType.getMoteInterfaceClasses()) {
addMoteInterface(intf, true); addMoteInterface(intf, true);
} }
} else {
/* Select default mote interfaces */
for (Class<? extends MoteInterface> intfClass: getDefaultMoteInterfaces()) {
addMoteInterface(intfClass, true);
}
} }
/* Restore compile commands */ /* Restore compile commands */
@ -536,11 +581,11 @@ public abstract class AbstractCompileDialog extends JDialog {
compileButton.setEnabled(false); compileButton.setEnabled(false);
createButton.setEnabled(false); createButton.setEnabled(false);
commandsArea.setEnabled(false); commandsArea.setEnabled(false);
setCompileCommands("");
break; break;
case SELECTED_SOURCE: case SELECTED_SOURCE:
if (!sourceFile.exists()) { if (!sourceFile.exists()) {
logger.warn("Could not find Contiki source: " + sourceFile.getAbsolutePath());
setDialogState(DialogState.NO_SELECTION); setDialogState(DialogState.NO_SELECTION);
return; return;
} }
@ -561,6 +606,7 @@ public abstract class AbstractCompileDialog extends JDialog {
case AWAITING_COMPILATION: case AWAITING_COMPILATION:
if (!sourceFile.exists()) { if (!sourceFile.exists()) {
logger.warn("Could not find Contiki source: " + sourceFile.getAbsolutePath());
setDialogState(DialogState.NO_SELECTION); setDialogState(DialogState.NO_SELECTION);
return; return;
} }
@ -569,10 +615,10 @@ public abstract class AbstractCompileDialog extends JDialog {
return; return;
} }
cleanButton.setEnabled(true); cleanButton.setEnabled(true);
compileButton.setEnabled(true); compileButton.setEnabled(true);
createButton.setEnabled(false); createButton.setEnabled(false);
commandsArea.setEnabled(true); commandsArea.setEnabled(true);
break; break;
case IS_COMPILING: case IS_COMPILING:
@ -635,11 +681,34 @@ public abstract class AbstractCompileDialog extends JDialog {
private void addMoteInterfacesTab(JTabbedPane parent) { private void addMoteInterfacesTab(JTabbedPane parent) {
moteIntfBox = Box.createVerticalBox(); moteIntfBox = Box.createVerticalBox();
JPanel panel = new JPanel(new BorderLayout()); JPanel panel = new JPanel(new BorderLayout());
panel.add(BorderLayout.NORTH, new JLabel("COOJA interacts with simulated motes via mote interfaces. You normally do not need to change these settings!")); JLabel label = new JLabel("COOJA interacts with simulated motes via mote interfaces. You normally do not need to change these settings!");
Box b = Box.createHorizontalBox();
b.add(new JButton(defaultAction));
b.add(label);
panel.add(BorderLayout.NORTH, b);
panel.add(BorderLayout.CENTER, new JScrollPane(moteIntfBox)); panel.add(BorderLayout.CENTER, new JScrollPane(moteIntfBox));
parent.addTab("Mote interfaces", null, panel, "Mote interfaces"); parent.addTab("Mote interfaces", null, panel, "Mote interfaces");
} }
private Action defaultAction = new AbstractAction("Use default") {
public void actionPerformed(ActionEvent e) {
/* Unselect all */
for (Component c : moteIntfBox.getComponents()) {
if (!(c instanceof JCheckBox)) {
continue;
}
((JCheckBox) c).setSelected(false);
}
/* Select default */
for (Class<? extends MoteInterface> moteIntf : getDefaultMoteInterfaces()) {
addMoteInterface(moteIntf, true);
}
}
};
public abstract Class<? extends MoteInterface>[] getDefaultMoteInterfaces();
/** /**
* @return Currently selected mote interface classes * @return Currently selected mote interface classes
*/ */
@ -679,7 +748,7 @@ public abstract class AbstractCompileDialog extends JDialog {
* @param selected If true, interface will initially be selected * @param selected If true, interface will initially be selected
*/ */
public void addMoteInterface(Class<? extends MoteInterface> intfClass, boolean selected) { public void addMoteInterface(Class<? extends MoteInterface> intfClass, boolean selected) {
/* If mote interface was already added, do nothing */ /* If mote interface was already added */
for (Component c : moteIntfBox.getComponents()) { for (Component c : moteIntfBox.getComponents()) {
if (!(c instanceof JCheckBox)) { if (!(c instanceof JCheckBox)) {
continue; continue;
@ -694,6 +763,7 @@ public abstract class AbstractCompileDialog extends JDialog {
} }
if (existingClass == intfClass) { if (existingClass == intfClass) {
((JCheckBox) c).setSelected(selected);
return; return;
} }
} }

View file

@ -37,6 +37,7 @@ import java.awt.Container;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.Box; import javax.swing.Box;
@ -100,7 +101,6 @@ public class ContikiMoteCompileDialog extends AbstractCompileDialog {
} }
/* Add Contiki mote type specifics */ /* Add Contiki mote type specifics */
addMoteInterfaceClasses();
addAdvancedTab(tabbedPane); addAdvancedTab(tabbedPane);
} }
@ -171,7 +171,7 @@ public class ContikiMoteCompileDialog extends AbstractCompileDialog {
moteType, moteType,
env env
); );
String[] envOneDimension = new String[env.length]; String[] envOneDimension = new String[env.length];
for (int i=0; i < env.length; i++) { for (int i=0; i < env.length; i++) {
envOneDimension[i] = env[i][0] + "=" + env[i][1]; envOneDimension[i] = env[i][0] + "=" + env[i][1];
@ -200,14 +200,10 @@ public class ContikiMoteCompileDialog extends AbstractCompileDialog {
return ContikiMoteType.getExpectedFirmwareFile(source); return ContikiMoteType.getExpectedFirmwareFile(source);
} }
private void addMoteInterfaceClasses() { public Class<? extends MoteInterface>[] getDefaultMoteInterfaces() {
ProjectConfig projectConfig = moteType.getConfig(); ProjectConfig projectConfig = moteType.getConfig();
String[] intfNames = projectConfig.getStringArrayValue(ContikiMoteType.class, "MOTE_INTERFACES"); String[] intfNames = projectConfig.getStringArrayValue(ContikiMoteType.class, "MOTE_INTERFACES");
ArrayList<Class<? extends MoteInterface>> classes = new ArrayList<Class<? extends MoteInterface>>();
boolean selected = true;
if (moteIntfBox.getComponentCount() > 0) {
selected = false;
}
/* Load mote interface classes */ /* Load mote interface classes */
for (String intfName : intfNames) { for (String intfName : intfNames) {
@ -219,8 +215,9 @@ public class ContikiMoteCompileDialog extends AbstractCompileDialog {
continue; continue;
} }
addMoteInterface(intfClass, selected); classes.add(intfClass);
} }
return classes.toArray(new Class[0]);
} }
private void addAdvancedTab(JTabbedPane parent) { private void addAdvancedTab(JTabbedPane parent) {
@ -274,7 +271,7 @@ public class ContikiMoteCompileDialog extends AbstractCompileDialog {
netStackBox.add(netStackComboBox); netStackBox.add(netStackComboBox);
netStackHeaderBox.setVisible((NetworkStack)netStackComboBox.getSelectedItem() == NetworkStack.MANUAL); netStackHeaderBox.setVisible((NetworkStack)netStackComboBox.getSelectedItem() == NetworkStack.MANUAL);
/* Advanced tab */ /* Advanced tab */
Box box = Box.createVerticalBox(); Box box = Box.createVerticalBox();
box.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); box.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
@ -381,7 +378,7 @@ public class ContikiMoteCompileDialog extends AbstractCompileDialog {
/* Start compiling */ /* Start compiling */
super.compileContiki(); super.compileContiki();
} }
protected String getTargetName() { protected String getTargetName() {
return "cooja"; return "cooja";
} }