Merge branch 'master' of ssh://contiki.git.sourceforge.net/gitroot/contiki/contiki

This commit is contained in:
Nicolas Tsiftes 2012-06-07 09:26:57 +02:00
commit 66f0a1bc95
21 changed files with 1135 additions and 997 deletions

View file

@ -56,7 +56,7 @@ uart0_init()
#endif #endif
U0CSR = UCSR_MODE; /* UART mode */ U0CSR = UCSR_MODE; /* UART mode */
U0UCR = 0x80; /* Flush */ U0UCR |= 0x80; /* Flush */
UART0_RX_EN(); UART0_RX_EN();
UART0_RX_INT(1); UART0_RX_INT(1);

View file

@ -201,7 +201,7 @@ clock_delay(unsigned int i)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#ifdef __GNUC__ #ifdef __GNUC__
void void
__delay_cycles(int c) __delay_cycles(unsigned long c)
{ {
c /= 4; c /= 4;
asm("add #-1, r15"); asm("add #-1, r15");

View file

@ -381,7 +381,12 @@ void halLcdActive(void)
// Wait a minimum of 25ms after issuing "start oscillation" // Wait a minimum of 25ms after issuing "start oscillation"
// command (to accomodate for MCLK up to 25MHz) // command (to accomodate for MCLK up to 25MHz)
__delay_cycles(250000); {
int i;
for(i = 0; i < 5; ++i) {
__delay_cycles(50000);
}
}
LcdInitMacro[3 * 6 + 5] |= BIT3; LcdInitMacro[3 * 6 + 5] |= BIT3;
LcdInitMacro[3 * 6 + 5] &= ~BIT0; LcdInitMacro[3 * 6 + 5] &= ~BIT0;

View file

@ -214,10 +214,9 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
this.myCpu.setMonitorExec(true); this.myCpu.setMonitorExec(true);
this.myCpu.setTrace(0); /* TODO Enable */ this.myCpu.setTrace(0); /* TODO Enable */
int[] memory = myCpu.memory;
logger.info("Loading firmware from: " + fileELF.getAbsolutePath()); logger.info("Loading firmware from: " + fileELF.getAbsolutePath());
GUI.setProgressMessage("Loading " + fileELF.getName()); GUI.setProgressMessage("Loading " + fileELF.getName());
node.loadFirmware(((MspMoteType)getType()).getELF(), memory); node.loadFirmware(((MspMoteType)getType()).getELF());
/* Throw exceptions at bad memory access */ /* Throw exceptions at bad memory access */
/*myCpu.setThrowIfWarning(true);*/ /*myCpu.setThrowIfWarning(true);*/
@ -417,6 +416,10 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
} }
MoteInterface moteInterface = getInterfaces().getInterfaceOfType(moteInterfaceClass); MoteInterface moteInterface = getInterfaces().getInterfaceOfType(moteInterfaceClass);
if (moteInterface == null) {
logger.fatal("Could not find mote interface of class: " + moteInterfaceClass);
return false;
}
moteInterface.setConfigXML(element.getChildren(), visAvailable); moteInterface.setConfigXML(element.getChildren(), visAvailable);
} }
} }

View file

@ -69,18 +69,21 @@ import org.jdom.Element;
import se.sics.cooja.ClassDescription; import se.sics.cooja.ClassDescription;
import se.sics.cooja.GUI; import se.sics.cooja.GUI;
import se.sics.cooja.GUI.RunnableInEDT;
import se.sics.cooja.Mote; import se.sics.cooja.Mote;
import se.sics.cooja.MotePlugin; import se.sics.cooja.MotePlugin;
import se.sics.cooja.PluginType; import se.sics.cooja.PluginType;
import se.sics.cooja.Simulation; import se.sics.cooja.Simulation;
import se.sics.cooja.SupportedArguments;
import se.sics.cooja.VisPlugin; import se.sics.cooja.VisPlugin;
import se.sics.cooja.GUI.RunnableInEDT;
import se.sics.cooja.dialogs.CompileContiki; import se.sics.cooja.dialogs.CompileContiki;
import se.sics.cooja.dialogs.MessageList; import se.sics.cooja.dialogs.MessageList;
import se.sics.cooja.interfaces.IPAddress;
import se.sics.cooja.interfaces.SerialPort; import se.sics.cooja.interfaces.SerialPort;
@ClassDescription("Open Native IP Gateway") @ClassDescription("Open Native IP Gateway")
@PluginType(PluginType.MOTE_PLUGIN) @PluginType(PluginType.MOTE_PLUGIN)
@SupportedArguments(moteInterfaces = {IPAddress.class})
public class NativeIPGateway extends VisPlugin implements MotePlugin { public class NativeIPGateway extends VisPlugin implements MotePlugin {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(NativeIPGateway.class); private static Logger logger = Logger.getLogger(NativeIPGateway.class);
@ -238,7 +241,7 @@ public class NativeIPGateway extends VisPlugin implements MotePlugin {
} }
/* Detect selected network interface */ /* Detect selected network interface */
NetworkInterfaceW intf = NetworkInterfaceW intf =
(NetworkInterfaceW) ((JComboBox)e.getSource()).getSelectedItem(); (NetworkInterfaceW) ((JComboBox)e.getSource()).getSelectedItem();
if (networkInterface == intf) { if (networkInterface == intf) {
/* Already selected */ /* Already selected */
@ -546,7 +549,7 @@ public class NativeIPGateway extends VisPlugin implements MotePlugin {
final JDialog progressDialog; final JDialog progressDialog;
if (GUI.isVisualized()) { if (GUI.isVisualized()) {
progressDialog = new JDialog( progressDialog = new JDialog(
(Window)GUI.getTopParentContainer(), (Window)GUI.getTopParentContainer(),
"Starting Native IP Gateway plugin" "Starting Native IP Gateway plugin"
); );
} else { } else {
@ -564,7 +567,7 @@ public class NativeIPGateway extends VisPlugin implements MotePlugin {
progressDialog.getContentPane().add(BorderLayout.NORTH, progressBar); progressDialog.getContentPane().add(BorderLayout.NORTH, progressBar);
progressDialog.getContentPane().add(BorderLayout.CENTER, new JScrollPane(output)); progressDialog.getContentPane().add(BorderLayout.CENTER, new JScrollPane(output));
progressDialog.setSize(350, 150); progressDialog.setSize(350, 150);
progressDialog.setLocationRelativeTo((Window)GUI.getTopParentContainer()); progressDialog.setLocationRelativeTo(GUI.getTopParentContainer());
progressDialog.setVisible(true); progressDialog.setVisible(true);
GUI.setProgressMessage("Compiling hello-world.minimal-net (Native IP Gateway)"); GUI.setProgressMessage("Compiling hello-world.minimal-net (Native IP Gateway)");
return true; return true;
@ -613,7 +616,7 @@ public class NativeIPGateway extends VisPlugin implements MotePlugin {
} }
}); });
Runtime.getRuntime().addShutdownHook(shutdownHook); Runtime.getRuntime().addShutdownHook(shutdownHook);
/* Waiting some time - otherwise pcap may not discover the new interface */ /* Waiting some time - otherwise pcap may not discover the new interface */
Thread.sleep(250); Thread.sleep(250);
@ -622,7 +625,7 @@ public class NativeIPGateway extends VisPlugin implements MotePlugin {
logger.fatal("Error when creating tap0: " + e.getMessage()); logger.fatal("Error when creating tap0: " + e.getMessage());
logger.fatal("Try using an already existing network interface"); logger.fatal("Try using an already existing network interface");
} }
/* Hide progress bar */ /* Hide progress bar */
if (GUI.isVisualized()) { if (GUI.isVisualized()) {
new RunnableInEDT<Boolean>() { new RunnableInEDT<Boolean>() {
@ -1007,7 +1010,7 @@ public class NativeIPGateway extends VisPlugin implements MotePlugin {
} }
deleteTunInterface(); deleteTunInterface();
if (shutdownHook != null) { if (shutdownHook != null) {
Runtime.getRuntime().removeShutdownHook(shutdownHook); Runtime.getRuntime().removeShutdownHook(shutdownHook);
shutdownHook = null; shutdownHook = null;

View file

@ -4,7 +4,6 @@ KEYBOARD_SHORTCUTS = \
<br><i>Ctrl+S:</i> Start/pause simulation\ <br><i>Ctrl+S:</i> Start/pause simulation\
<br><i>Ctrl+R:</i> Reload current simulation. If no simulation exists, the last used simulation config is loaded\ <br><i>Ctrl+R:</i> Reload current simulation. If no simulation exists, the last used simulation config is loaded\
<br><i>Ctrl+Shift+R:</i> Reload current simulation with another random seed\ <br><i>Ctrl+Shift+R:</i> Reload current simulation with another random seed\
<br><i>Ctrl+X:</i> Quit COOJA\
<br>\ <br>\
<br><i>F1:</i> Toggle quick help <br><i>F1:</i> Toggle quick help

View file

@ -1,113 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<simconf> <simconf>
<project>../apps/mrm</project> <simulation>
<project>../apps/mspsim</project> <title>Hello World test (Cooja motes)</title>
<project>../apps/avrora</project> <randomseed>generated</randomseed>
<project>../apps/native_gateway</project> <motedelay_us>1000000</motedelay_us>
<simulation> <radiomedium>
<title>My simulation</title> se.sics.cooja.radiomediums.UDGM
<delaytime>0</delaytime> <transmitting_range>50.0</transmitting_range>
<randomseed>generated</randomseed> <interference_range>100.0</interference_range>
<motedelay_us>1000000</motedelay_us> <success_ratio_tx>1.0</success_ratio_tx>
<radiomedium> <success_ratio_rx>1.0</success_ratio_rx>
se.sics.cooja.radiomediums.UDGM </radiomedium>
<transmitting_range>50.0</transmitting_range> <events>
<interference_range>100.0</interference_range> <logoutput>40000</logoutput>
<success_ratio_tx>1.0</success_ratio_tx> </events>
<success_ratio_rx>1.0</success_ratio_rx> <motetype>
</radiomedium> se.sics.cooja.contikimote.ContikiMoteType
<motetype> <identifier>mtype725</identifier>
se.sics.cooja.contikimote.ContikiMoteType <description>Contiki Mote Type #1</description>
<identifier>mtype82</identifier> <source>[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
<description>Contiki Mote Type #1</description> <commands>make hello-world.cooja TARGET=cooja</commands>
<contikiapp>../../../examples/hello-world/hello-world.c</contikiapp> <moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
<commands>make hello-world.cooja TARGET=cooja</commands> <moteinterface>se.sics.cooja.interfaces.Battery</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface> <moteinterface>se.sics.cooja.contikimote.interfaces.ContikiVib</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Battery</moteinterface> <moteinterface>se.sics.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiVib</moteinterface> <moteinterface>se.sics.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiMoteID</moteinterface> <moteinterface>se.sics.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiRS232</moteinterface> <moteinterface>se.sics.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiBeeper</moteinterface> <moteinterface>se.sics.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface> <moteinterface>se.sics.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiRadio</moteinterface> <moteinterface>se.sics.cooja.contikimote.interfaces.ContikiButton</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiButton</moteinterface> <moteinterface>se.sics.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiPIR</moteinterface> <moteinterface>se.sics.cooja.contikimote.interfaces.ContikiClock</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiClock</moteinterface> <moteinterface>se.sics.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiLED</moteinterface> <moteinterface>se.sics.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiCFS</moteinterface> <moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface> <moteinterface>se.sics.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>se.sics.cooja.interfaces.RimeAddress</moteinterface> <symbols>false</symbols>
<symbols>false</symbols> </motetype>
<commstack>Rime</commstack> <mote>
</motetype> <interface_config>
<mote> se.sics.cooja.interfaces.Position
se.sics.cooja.contikimote.ContikiMote <x>69.64867743029201</x>
<motetype_identifier>mtype82</motetype_identifier> <y>69.2570131081022</y>
<interface_config> <z>0.0</z>
se.sics.cooja.interfaces.Position </interface_config>
<x>69.64867743029201</x> <interface_config>
<y>69.2570131081022</y> se.sics.cooja.contikimote.interfaces.ContikiMoteID
<z>0.0</z> <id>1</id>
</interface_config> </interface_config>
<interface_config> <motetype_identifier>mtype725</motetype_identifier>
se.sics.cooja.interfaces.Battery </mote>
<infinite>false</infinite> </simulation>
</interface_config> <plugin>
<interface_config> se.sics.cooja.plugins.Visualizer
se.sics.cooja.contikimote.interfaces.ContikiMoteID <plugin_config>
<id>1</id> <skin>se.sics.cooja.plugins.skins.IDVisualizerSkin</skin>
</interface_config> <skin>se.sics.cooja.plugins.skins.LogVisualizerSkin</skin>
</mote> <viewport>0.9090909090909091 0.0 0.0 0.9090909090909091 59.68302051791636 6.039078992634368</viewport>
</simulation> </plugin_config>
<plugin> <width>259</width>
se.sics.cooja.plugins.Visualizer <z>1</z>
<plugin_config> <height>198</height>
<skin>Mote IDs</skin> <location_x>2</location_x>
<skin>Log output: printf()'s</skin> <location_y>203</location_y>
</plugin_config> </plugin>
<width>259</width> <plugin>
<z>1</z> se.sics.cooja.plugins.LogListener
<height>198</height> <plugin_config>
<location_x>2</location_x> <filter />
<location_y>203</location_y> </plugin_config>
<minimized>false</minimized> <width>259</width>
</plugin> <z>2</z>
<plugin> <height>217</height>
se.sics.cooja.plugins.LogListener <location_x>2</location_x>
<plugin_config> <location_y>403</location_y>
<filter /> </plugin>
</plugin_config> <plugin>
<width>259</width> se.sics.cooja.plugins.SimControl
<z>2</z> <width>259</width>
<height>217</height> <z>3</z>
<location_x>2</location_x> <height>200</height>
<location_y>403</location_y> <location_x>2</location_x>
<minimized>false</minimized> <location_y>3</location_y>
</plugin> </plugin>
<plugin> <plugin>
se.sics.cooja.plugins.SimControl se.sics.cooja.plugins.ScriptRunner
<width>259</width> <plugin_config>
<z>3</z> <scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile>
<height>200</height> <active>true</active>
<location_x>2</location_x> </plugin_config>
<location_y>3</location_y> <width>592</width>
<minimized>false</minimized> <z>0</z>
</plugin> <height>618</height>
<plugin> <location_x>318</location_x>
se.sics.cooja.plugins.ScriptRunner <location_y>61</location_y>
<plugin_config> </plugin>
<script>TIMEOUT(2000, log.log("last message: " + msg + "\n")); </simconf>
WAIT_UNTIL(msg.equals('Hello, world'));
log.testOK();</script>
<active>true</active>
</plugin_config>
<width>592</width>
<z>0</z>
<height>618</height>
<location_x>264</location_x>
<location_y>3</location_y>
<minimized>false</minimized>
</plugin>
</simconf>

View file

@ -1,125 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<simconf> <simconf>
<project>[CONTIKI_DIR]/tools/cooja/apps/mrm</project> <simulation>
<project>[CONTIKI_DIR]/tools/cooja/apps/mspsim</project> <title>Hello World (ESB)</title>
<project>[CONTIKI_DIR]/tools/cooja/apps/avrora</project> <randomseed>generated</randomseed>
<simulation> <motedelay_us>1000000</motedelay_us>
<title>My simulation</title> <radiomedium>
<delaytime>0</delaytime> se.sics.cooja.radiomediums.UDGM
<randomseed>generated</randomseed> <transmitting_range>50.0</transmitting_range>
<motedelay_us>1000000</motedelay_us> <interference_range>100.0</interference_range>
<radiomedium> <success_ratio_tx>1.0</success_ratio_tx>
se.sics.cooja.radiomediums.UDGM <success_ratio_rx>1.0</success_ratio_rx>
<transmitting_range>50.0</transmitting_range> </radiomedium>
<interference_range>100.0</interference_range> <events>
<success_ratio_tx>1.0</success_ratio_tx> <logoutput>40000</logoutput>
<success_ratio_rx>1.0</success_ratio_rx> </events>
</radiomedium> <motetype>
<events> se.sics.cooja.mspmote.ESBMoteType
<logoutput>40000</logoutput> <identifier>esb1</identifier>
</events> <description>ESB Mote Type #esb1</description>
<motetype> <source EXPORT="discard">[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
se.sics.cooja.mspmote.ESBMoteType <commands EXPORT="discard">make hello-world.esb TARGET=esb</commands>
<identifier>esb1</identifier> <firmware EXPORT="copy">[CONTIKI_DIR]/examples/hello-world/hello-world.esb</firmware>
<description>ESB Mote Type #esb1</description> <moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
<source>[CONTIKI_DIR]/examples/hello-world/hello-world.c</source> <moteinterface>se.sics.cooja.interfaces.RimeAddress</moteinterface>
<commands>make clean TARGET=esb <moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface>
make hello-world.esb TARGET=esb</commands> <moteinterface>se.sics.cooja.mspmote.interfaces.MspSerial</moteinterface>
<firmware>[CONTIKI_DIR]/examples/hello-world/hello-world.esb</firmware> <moteinterface>se.sics.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface> <moteinterface>se.sics.cooja.mspmote.interfaces.ESBLED</moteinterface>
<moteinterface>se.sics.cooja.interfaces.RimeAddress</moteinterface> <moteinterface>se.sics.cooja.mspmote.interfaces.ESBButton</moteinterface>
<moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface> <moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspSerial</moteinterface> <moteinterface>se.sics.cooja.mspmote.interfaces.TR1001Radio</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspClock</moteinterface> <moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.ESBLED</moteinterface> <moteinterface>se.sics.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.ESBButton</moteinterface> </motetype>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface> <mote>
<moteinterface>se.sics.cooja.mspmote.interfaces.TR1001Radio</moteinterface> <breakpoints />
<moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface> <interface_config>
</motetype> se.sics.cooja.interfaces.Position
<mote> <x>57.296459690977144</x>
se.sics.cooja.mspmote.ESBMote <y>73.20759478605089</y>
<breakpoints /> <z>0.0</z>
<interface_config> </interface_config>
se.sics.cooja.interfaces.Position <interface_config>
<x>57.296459690977144</x> se.sics.cooja.mspmote.interfaces.MspMoteID
<y>73.20759478605089</y> <id>1</id>
<z>0.0</z> </interface_config>
</interface_config> <motetype_identifier>esb1</motetype_identifier>
<interface_config> </mote>
se.sics.cooja.mspmote.interfaces.MspMoteID </simulation>
<id>1</id> <plugin>
</interface_config> se.sics.cooja.plugins.LogListener
<motetype_identifier>esb1</motetype_identifier> <plugin_config>
</mote> <filter />
</simulation> </plugin_config>
<plugin> <width>623</width>
se.sics.cooja.plugins.SimControl <z>1</z>
<width>259</width> <height>270</height>
<z>6</z> <location_x>29</location_x>
<height>184</height> <location_y>256</location_y>
<location_x>60</location_x> </plugin>
<location_y>60</location_y> <plugin>
<minimized>false</minimized> se.sics.cooja.plugins.ScriptRunner
</plugin> <plugin_config>
<plugin> <scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile>
se.sics.cooja.plugins.Visualizer <active>true</active>
<plugin_config> </plugin_config>
<skin>se.sics.cooja.plugins.skins.IDVisualizerSkin</skin> <width>600</width>
<skin>se.sics.cooja.plugins.skins.LogVisualizerSkin</skin> <z>0</z>
<viewport>0.9090909090909091 0.0 0.0 0.9090909090909091 91.91230937183896 53.4476411035901</viewport> <height>453</height>
</plugin_config> <location_x>337</location_x>
<width>300</width> <location_y>25</location_y>
<z>3</z> </plugin>
<height>300</height> <plugin>
<location_x>945</location_x> se.sics.cooja.plugins.SimControl
<location_y>0</location_y> <width>280</width>
<minimized>false</minimized> <z>2</z>
</plugin> <height>160</height>
<plugin> <location_x>20</location_x>
se.sics.cooja.plugins.LogListener <location_y>23</location_y>
<plugin_config> </plugin>
<filter /> </simconf>
</plugin_config>
<width>1245</width>
<z>5</z>
<height>150</height>
<location_x>0</location_x>
<location_y>530</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.TimeLine
<plugin_config>
<mote>0</mote>
<showRadioRXTX />
<showRadioHW />
<showLEDs />
<split>109</split>
<zoom>9</zoom>
</plugin_config>
<width>1245</width>
<z>1</z>
<height>150</height>
<location_x>0</location_x>
<location_y>680</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.ScriptRunner
<plugin_config>
<script>TIMEOUT(5000, log.log("last message: " + msg + "\n"));
WAIT_UNTIL(msg.equals('Hello, world'));
log.testOK();</script>
<active>true</active>
</plugin_config>
<width>600</width>
<z>0</z>
<height>453</height>
<location_x>337</location_x>
<location_y>25</location_y>
<minimized>false</minimized>
</plugin>
</simconf>

View file

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<simulation>
<title>Hello World (Exp5438)</title>
<randomseed>generated</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
se.sics.cooja.radiomediums.UDGM
<transmitting_range>50.0</transmitting_range>
<interference_range>100.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<events>
<logoutput>40000</logoutput>
</events>
<motetype>
se.sics.cooja.mspmote.Exp5438MoteType
<identifier>exp5438#1</identifier>
<description>Exp5438 Mote Type exp5438#1</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
<commands EXPORT="discard">make hello-world.exp5438 TARGET=exp5438</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/hello-world/hello-world.exp5438</firmware>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
<moteinterface>se.sics.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>se.sics.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.UsciA1Serial</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.Exp5438LED</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
</motetype>
<mote>
<breakpoints />
<interface_config>
se.sics.cooja.interfaces.Position
<x>26.321738050614275</x>
<y>34.93092009073432</y>
<z>0.0</z>
</interface_config>
<interface_config>
se.sics.cooja.mspmote.interfaces.MspMoteID
<id>1</id>
</interface_config>
<motetype_identifier>exp5438#1</motetype_identifier>
</mote>
</simulation>
<plugin>
se.sics.cooja.plugins.SimControl
<width>280</width>
<z>2</z>
<height>160</height>
<location_x>38</location_x>
<location_y>49</location_y>
</plugin>
<plugin>
se.sics.cooja.plugins.LogListener
<plugin_config>
<filter />
</plugin_config>
<width>680</width>
<z>1</z>
<height>240</height>
<location_x>86</location_x>
<location_y>384</location_y>
</plugin>
<plugin>
se.sics.cooja.plugins.ScriptRunner
<plugin_config>
<scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile>
<active>true</active>
</plugin_config>
<width>600</width>
<z>0</z>
<height>700</height>
<location_x>347</location_x>
<location_y>21</location_y>
</plugin>
</simconf>

View file

@ -0,0 +1,9 @@
TIMEOUT(5000);
while(true) {
log.log("> " + msg + "\n");
if (msg.equals('Hello, world')) {
log.testOK();
}
YIELD();
}

View file

@ -1,120 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<simconf> <simconf>
<project>../apps/mrm</project> <simulation>
<project>../apps/mspsim</project> <title>Hello World (MicaZ)</title>
<project>../apps/avrora</project> <randomseed>generated</randomseed>
<simulation> <motedelay_us>1000000</motedelay_us>
<title>My simulation</title> <radiomedium>
<delaytime>0</delaytime> se.sics.cooja.radiomediums.UDGM
<randomseed>generated</randomseed> <transmitting_range>50.0</transmitting_range>
<motedelay_us>1000000</motedelay_us> <interference_range>100.0</interference_range>
<radiomedium> <success_ratio_tx>1.0</success_ratio_tx>
se.sics.cooja.radiomediums.UDGM <success_ratio_rx>1.0</success_ratio_rx>
<transmitting_range>50.0</transmitting_range> </radiomedium>
<interference_range>100.0</interference_range> <events>
<success_ratio_tx>1.0</success_ratio_tx> <logoutput>40000</logoutput>
<success_ratio_rx>1.0</success_ratio_rx> </events>
</radiomedium> <motetype>
<events> se.sics.cooja.avrmote.MicaZMoteType
<logoutput>40000</logoutput> <identifier>micaz1</identifier>
</events> <description>MicaZ Mote Type #micaz1</description>
<motetype> <source>[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
se.sics.cooja.avrmote.MicaZMoteType <commands>make hello-world.elf TARGET=micaz</commands>
<identifier>micaz1</identifier> <firmware>[CONTIKI_DIR]/examples/hello-world/hello-world.elf</firmware>
<description>MicaZ Mote Type #micaz1</description> <moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
<source>../../../examples/hello-world/hello-world.c</source> <moteinterface>se.sics.cooja.avrmote.interfaces.MicaZID</moteinterface>
<commands>make clean TARGET=micaz <moteinterface>se.sics.cooja.avrmote.interfaces.MicaZLED</moteinterface>
make hello-world.elf TARGET=micaz</commands> <moteinterface>se.sics.cooja.avrmote.interfaces.MicaZRadio</moteinterface>
<firmware>../../../examples/hello-world/hello-world.elf</firmware> <moteinterface>se.sics.cooja.avrmote.interfaces.MicaClock</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface> <moteinterface>se.sics.cooja.avrmote.interfaces.MicaSerial</moteinterface>
<moteinterface>se.sics.cooja.avrmote.interfaces.MicaZID</moteinterface> <moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>se.sics.cooja.avrmote.interfaces.MicaZLED</moteinterface> <moteinterface>se.sics.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>se.sics.cooja.avrmote.interfaces.MicaZRadio</moteinterface> </motetype>
<moteinterface>se.sics.cooja.avrmote.interfaces.MicaClock</moteinterface> <mote>
<moteinterface>se.sics.cooja.avrmote.interfaces.MicaSerial</moteinterface> <interface_config>
</motetype> se.sics.cooja.interfaces.Position
<mote> <x>36.478849033811386</x>
se.sics.cooja.avrmote.MicaZMote <y>97.17795415366507</y>
<motetype_identifier>micaz1</motetype_identifier> <z>0.0</z>
<interface_config> </interface_config>
se.sics.cooja.interfaces.Position <interface_config>
<x>68.44103812985554</x> se.sics.cooja.avrmote.interfaces.MicaZID
<y>35.6791174319418</y> <id>1</id>
<z>0.0</z> </interface_config>
</interface_config> <motetype_identifier>micaz1</motetype_identifier>
<interface_config> </mote>
se.sics.cooja.avrmote.interfaces.MicaZID </simulation>
<id>1</id> <plugin>
</interface_config> se.sics.cooja.plugins.SimControl
</mote> <width>280</width>
</simulation> <z>2</z>
<plugin> <height>160</height>
se.sics.cooja.plugins.SimControl <location_x>17</location_x>
<width>259</width> <location_y>16</location_y>
<z>4</z> </plugin>
<height>184</height> <plugin>
<location_x>0</location_x> se.sics.cooja.plugins.LogListener
<location_y>0</location_y> <plugin_config>
<minimized>false</minimized> <filter />
</plugin> </plugin_config>
<plugin> <width>680</width>
se.sics.cooja.plugins.Visualizer <z>1</z>
<plugin_config> <height>240</height>
<skin>se.sics.cooja.plugins.skins.IDVisualizerSkin</skin> <location_x>20</location_x>
<skin>se.sics.cooja.plugins.skins.LogVisualizerSkin</skin> <location_y>285</location_y>
<viewport>0.9090909090909091 0.0 0.0 0.9090909090909091 81.78087442740406 87.56443869823474</viewport> </plugin>
</plugin_config> <plugin>
<width>300</width> se.sics.cooja.plugins.ScriptRunner
<z>1</z> <plugin_config>
<height>300</height> <scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile>
<location_x>456</location_x> <active>true</active>
<location_y>0</location_y> </plugin_config>
<minimized>false</minimized> <width>600</width>
</plugin> <z>0</z>
<plugin> <height>535</height>
se.sics.cooja.plugins.LogListener <location_x>403</location_x>
<plugin_config> <location_y>23</location_y>
<filter /> </plugin>
</plugin_config> </simconf>
<width>756</width>
<z>2</z>
<height>150</height>
<location_x>0</location_x>
<location_y>286</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.TimeLine
<plugin_config>
<mote>0</mote>
<showRadioRXTX />
<showRadioHW />
<showLEDs />
<split>109</split>
<zoom>9</zoom>
</plugin_config>
<width>756</width>
<z>3</z>
<height>150</height>
<location_x>0</location_x>
<location_y>436</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.ScriptRunner
<plugin_config>
<script>TIMEOUT(2000, log.log("last message: " + msg + "\n"));
WAIT_UNTIL(msg.startsWith('Hello, world'));
log.testOK();</script>
<active>true</active>
</plugin_config>
<width>600</width>
<z>0</z>
<height>305</height>
<location_x>89</location_x>
<location_y>211</location_y>
<minimized>false</minimized>
</plugin>
</simconf>

View file

@ -15,8 +15,8 @@ msg = "";
GENERATE_MSG(5000, "continue"); GENERATE_MSG(5000, "continue");
WAIT_UNTIL(msg.equals("continue")); WAIT_UNTIL(msg.equals("continue"));
/* override simulation delay to realtime */ /* override simulation speed limit to realtime */
sim.setDelayTime(java.lang.Integer.MIN_VALUE); sim.setSpeedLimit(1.0);
/* create tunnel interface */ /* create tunnel interface */
log.log("create tunnel interface\n"); log.log("create tunnel interface\n");

View file

@ -1,80 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<simconf> <simconf>
<project>../apps/mrm</project> <simulation>
<project>../apps/mspsim</project> <title>Hello World test (Sky)</title>
<project>../apps/avrora</project> <randomseed>generated</randomseed>
<project>../apps/native_gateway</project> <motedelay_us>1000000</motedelay_us>
<simulation> <radiomedium>
<title>Hello World (Sky)</title> se.sics.cooja.radiomediums.UDGM
<delaytime>0</delaytime> <transmitting_range>50.0</transmitting_range>
<randomseed>generated</randomseed> <interference_range>100.0</interference_range>
<motedelay_us>1000000</motedelay_us> <success_ratio_tx>1.0</success_ratio_tx>
<radiomedium> <success_ratio_rx>1.0</success_ratio_rx>
se.sics.cooja.radiomediums.UDGM </radiomedium>
<transmitting_range>50.0</transmitting_range> <events>
<interference_range>100.0</interference_range> <logoutput>40000</logoutput>
<success_ratio_tx>1.0</success_ratio_tx> </events>
<success_ratio_rx>1.0</success_ratio_rx> <motetype>
</radiomedium> se.sics.cooja.mspmote.SkyMoteType
<motetype> <identifier>sky1</identifier>
se.sics.cooja.mspmote.SkyMoteType <description>Sky Mote Type #1</description>
<identifier>sky1</identifier> <source EXPORT="discard">[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
<description>Sky Mote Type #1</description> <commands EXPORT="discard">make hello-world.sky TARGET=sky</commands>
<source>../../../examples/hello-world/hello-world.c</source> <firmware EXPORT="copy">[CONTIKI_DIR]/examples/hello-world/hello-world.sky</firmware>
<commands>make clean TARGET=sky <moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
make hello-world.sky TARGET=sky</commands> <moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface>
<firmware>../../../examples/hello-world/hello-world.sky</firmware> <moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface> <moteinterface>se.sics.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface> <moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface> <moteinterface>se.sics.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspClock</moteinterface> <moteinterface>se.sics.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface> <moteinterface>se.sics.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyButton</moteinterface> <moteinterface>se.sics.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyFlash</moteinterface> <moteinterface>se.sics.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyByteRadio</moteinterface> </motetype>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkySerial</moteinterface> <mote>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyLED</moteinterface> <breakpoints />
</motetype> <interface_config>
<mote> se.sics.cooja.interfaces.Position
se.sics.cooja.mspmote.SkyMote <x>64.11203103628397</x>
<motetype_identifier>sky1</motetype_identifier> <y>93.06735634828134</y>
<breakpoints /> <z>0.0</z>
<interface_config> </interface_config>
se.sics.cooja.interfaces.Position <interface_config>
<x>64.11203103628397</x> se.sics.cooja.mspmote.interfaces.MspMoteID
<y>93.06735634828134</y> <id>1</id>
<z>0.0</z> </interface_config>
</interface_config> <motetype_identifier>sky1</motetype_identifier>
<interface_config> </mote>
se.sics.cooja.mspmote.interfaces.MspMoteID </simulation>
<id>1</id> <plugin>
</interface_config> se.sics.cooja.plugins.ScriptRunner
</mote> <plugin_config>
</simulation> <scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile>
<plugin> <active>true</active>
se.sics.cooja.plugins.SimControl </plugin_config>
<width>248</width> <width>541</width>
<z>1</z> <z>0</z>
<height>200</height> <height>448</height>
<location_x>0</location_x> <location_x>299</location_x>
<location_y>0</location_y> <location_y>7</location_y>
<minimized>false</minimized> </plugin>
</plugin> <plugin>
<plugin> se.sics.cooja.plugins.SimControl
se.sics.cooja.plugins.ScriptRunner <width>280</width>
<plugin_config> <z>2</z>
<script>TIMEOUT(2000, log.log("last message: " + msg + "\n")); <height>160</height>
<location_x>7</location_x>
WAIT_UNTIL(msg.equals('Hello, world')); <location_y>10</location_y>
log.testOK();</script> </plugin>
<active>true</active> <plugin>
</plugin_config> se.sics.cooja.plugins.LogListener
<width>541</width> <plugin_config>
<z>0</z> <filter />
<height>448</height> </plugin_config>
<location_x>248</location_x> <width>680</width>
<location_y>-1</location_y> <z>1</z>
<minimized>false</minimized> <height>240</height>
</plugin> <location_x>51</location_x>
</simconf> <location_y>288</location_y>
</plugin>
</simconf>

View file

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<simulation>
<title>Hello World (Wismote)</title>
<randomseed>generated</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
se.sics.cooja.radiomediums.UDGM
<transmitting_range>50.0</transmitting_range>
<interference_range>100.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<events>
<logoutput>40000</logoutput>
</events>
<motetype>
se.sics.cooja.mspmote.WismoteMoteType
<identifier>wismote1</identifier>
<description>Wismote Mote Type #wismote1</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
<commands EXPORT="discard">make hello-world.wismote TARGET=wismote</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/hello-world/hello-world.wismote</firmware>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
<moteinterface>se.sics.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>se.sics.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspButton</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspDefaultSerial</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspLED</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
</motetype>
<mote>
<breakpoints />
<interface_config>
se.sics.cooja.interfaces.Position
<x>36.76551518369201</x>
<y>29.330591009779383</y>
<z>0.0</z>
</interface_config>
<interface_config>
se.sics.cooja.mspmote.interfaces.MspMoteID
<id>1</id>
</interface_config>
<motetype_identifier>wismote1</motetype_identifier>
</mote>
</simulation>
<plugin>
se.sics.cooja.plugins.SimControl
<width>280</width>
<z>2</z>
<height>160</height>
<location_x>22</location_x>
<location_y>14</location_y>
</plugin>
<plugin>
se.sics.cooja.plugins.LogListener
<plugin_config>
<filter />
</plugin_config>
<width>680</width>
<z>1</z>
<height>240</height>
<location_x>84</location_x>
<location_y>408</location_y>
</plugin>
<plugin>
se.sics.cooja.plugins.ScriptRunner
<plugin_config>
<scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile>
<active>true</active>
</plugin_config>
<width>600</width>
<z>0</z>
<height>548</height>
<location_x>335</location_x>
<location_y>22</location_y>
</plugin>
</simconf>

View file

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<simulation>
<title>Hello World (Z1)</title>
<randomseed>generated</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
se.sics.cooja.radiomediums.UDGM
<transmitting_range>50.0</transmitting_range>
<interference_range>100.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<events>
<logoutput>40000</logoutput>
</events>
<motetype>
se.sics.cooja.mspmote.Z1MoteType
<identifier>z11</identifier>
<description>Z1 Mote Type #z11</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
<commands EXPORT="discard">make hello-world.z1 TARGET=z1</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/hello-world/hello-world.z1</firmware>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
<moteinterface>se.sics.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>se.sics.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspDefaultSerial</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspLED</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
</motetype>
<mote>
<breakpoints />
<interface_config>
se.sics.cooja.interfaces.Position
<x>94.96401380574989</x>
<y>21.247662337471553</y>
<z>0.0</z>
</interface_config>
<interface_config>
se.sics.cooja.mspmote.interfaces.MspMoteID
<id>1</id>
</interface_config>
<motetype_identifier>z11</motetype_identifier>
</mote>
</simulation>
<plugin>
se.sics.cooja.plugins.SimControl
<width>280</width>
<z>2</z>
<height>160</height>
<location_x>38</location_x>
<location_y>13</location_y>
</plugin>
<plugin>
se.sics.cooja.plugins.LogListener
<plugin_config>
<filter />
</plugin_config>
<width>680</width>
<z>1</z>
<height>240</height>
<location_x>109</location_x>
<location_y>377</location_y>
</plugin>
<plugin>
se.sics.cooja.plugins.ScriptRunner
<plugin_config>
<scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile>
<active>true</active>
</plugin_config>
<width>600</width>
<z>0</z>
<height>700</height>
<location_x>330</location_x>
<location_y>24</location_y>
</plugin>
</simconf>

View file

@ -39,6 +39,7 @@ import java.awt.Dimension;
import java.awt.Frame; import java.awt.Frame;
import java.awt.GraphicsDevice; import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Window; import java.awt.Window;
@ -296,12 +297,12 @@ public class GUI extends Observable {
protected GUIEventHandler guiEventHandler = new GUIEventHandler(); protected GUIEventHandler guiEventHandler = new GUIEventHandler();
private JMenu toolsMenu, menuMoteTypeClasses, menuMoteTypes; private JMenu menuMoteTypeClasses, menuMoteTypes;
private JMenu menuOpenSimulation; private JMenu menuOpenSimulation;
private boolean hasFileHistoryChanged; private boolean hasFileHistoryChanged;
private Vector<Class<? extends Plugin>> menuMotePluginClasses; private Vector<Class<? extends Plugin>> menuMotePluginClasses = new Vector<Class<? extends Plugin>>();
private JDesktopPane myDesktopPane; private JDesktopPane myDesktopPane;
@ -369,17 +370,6 @@ public class GUI extends Observable {
myGUI = this; myGUI = this;
mySimulation = null; mySimulation = null;
myDesktopPane = desktop; myDesktopPane = desktop;
if (toolsMenu == null) {
toolsMenu = new JMenu("Tools");
toolsMenu.removeAll();
/* COOJA/GUI plugins at top, simulation plugins in middle, mote plugins at bottom */
/*toolsMenu.addSeparator();
toolsMenu.addSeparator();*/
}
if (menuMotePluginClasses == null) {
menuMotePluginClasses = new Vector<Class<? extends Plugin>>();
}
/* Help panel */ /* Help panel */
quickHelpTextPane = new JTextPane(); quickHelpTextPane = new JTextPane();
@ -703,7 +693,7 @@ public class GUI extends Observable {
JMenu fileMenu = new JMenu("File"); JMenu fileMenu = new JMenu("File");
JMenu simulationMenu = new JMenu("Simulation"); JMenu simulationMenu = new JMenu("Simulation");
JMenu motesMenu = new JMenu("Motes"); JMenu motesMenu = new JMenu("Motes");
/* toolsMenu = new JMenu("Tools"); */ final JMenu toolsMenu = new JMenu("Tools");
JMenu settingsMenu = new JMenu("Settings"); JMenu settingsMenu = new JMenu("Settings");
JMenu helpMenu = new JMenu("Help"); JMenu helpMenu = new JMenu("Help");
@ -931,56 +921,118 @@ public class GUI extends Observable {
motesMenu.add(new JMenuItem(removeAllMotesAction)); motesMenu.add(new JMenuItem(removeAllMotesAction));
// Tools menu /* Tools menu */
toolsMenu.addMenuListener(new MenuListener() { toolsMenu.addMenuListener(new MenuListener() {
public void menuSelected(MenuEvent e) { private ActionListener menuItemListener = new ActionListener() {
for (Component menuComponent: toolsMenu.getMenuComponents()) { public void actionPerformed(ActionEvent e) {
if (!(menuComponent instanceof JMenuItem)) { Object pluginClass = ((JMenuItem)e.getSource()).getClientProperty("class");
continue; Object mote = ((JMenuItem)e.getSource()).getClientProperty("mote");
} tryStartPlugin((Class<? extends Plugin>) pluginClass, myGUI, getSimulation(), (Mote)mote);
JMenuItem menuItem = (JMenuItem) menuComponent; }
Class<? extends Plugin> pluginClass = (Class<? extends Plugin>) menuItem.getClientProperty("class"); };
int pluginType; private JMenuItem createMenuItem(Class<? extends Plugin> newPluginClass, int pluginType) {
if (pluginClass.isAnnotationPresent(PluginType.class)) { String description = getDescriptionOf(newPluginClass);
pluginType = pluginClass.getAnnotation(PluginType.class).value(); JMenuItem menuItem = new JMenuItem(description + "...");
} else { menuItem.putClientProperty("class", newPluginClass);
pluginType = PluginType.UNDEFINED_PLUGIN; menuItem.addActionListener(menuItemListener);
}
/* No simulation -> deactivate non-GUI plugins */ String tooltip = "<html><pre>";
if (pluginType == PluginType.COOJA_PLUGIN || pluginType == PluginType.COOJA_STANDARD_PLUGIN) { if (pluginType == PluginType.COOJA_PLUGIN || pluginType == PluginType.COOJA_STANDARD_PLUGIN) {
menuItem.setEnabled(true); tooltip += "Cooja plugin: ";
continue; } else if (pluginType == PluginType.SIM_PLUGIN || pluginType == PluginType.SIM_STANDARD_PLUGIN) {
} tooltip += "Simulation plugin: ";
/* Mote plugin -> not accessed from this menu */
if (pluginType == PluginType.MOTE_PLUGIN) {
menuItem.setEnabled(false);
continue;
}
if (pluginType != PluginType.SIM_PLUGIN && pluginType != PluginType.SIM_STANDARD_PLUGIN) {
/* Unknown */
menuItem.setEnabled(false);
continue;
}
if (getSimulation() == null) { if (getSimulation() == null) {
menuItem.setEnabled(false); menuItem.setEnabled(false);
continue;
} }
} else if (pluginType == PluginType.MOTE_PLUGIN) {
tooltip += "Mote plugin: ";
}
tooltip += description + " (" + newPluginClass.getName() + ")";
/* Check if simulation plugin depends on any particular radio medium */ /* Check if simulation plugin depends on any particular radio medium */
if (pluginClass.getAnnotation(SupportedArguments.class) != null) { if (pluginType == PluginType.SIM_PLUGIN || pluginType == PluginType.SIM_STANDARD_PLUGIN) {
menuItem.setEnabled(false); if (newPluginClass.getAnnotation(SupportedArguments.class) != null) {
Class<? extends RadioMedium>[] radioMediums = pluginClass.getAnnotation(SupportedArguments.class).radioMediums(); boolean active = false;
Class<? extends RadioMedium>[] radioMediums = newPluginClass.getAnnotation(SupportedArguments.class).radioMediums();
for (Class<? extends Object> o: radioMediums) { for (Class<? extends Object> o: radioMediums) {
if (o.isAssignableFrom(getSimulation().getRadioMedium().getClass())) { if (o.isAssignableFrom(getSimulation().getRadioMedium().getClass())) {
menuItem.setEnabled(true); active = true;
break; break;
} }
} }
} else { if (!active) {
menuItem.setEnabled(true); menuItem.setVisible(false);
}
} }
} }
/* Check if plugin was imported by a extension directory */
File project =
getProjectConfig().getUserProjectDefining(GUI.class, "PLUGINS", newPluginClass.getName());
if (project != null) {
tooltip += "\nLoaded by extension: " + project.getPath();
}
tooltip += "</html>";
/*menuItem.setToolTipText(tooltip);*/
return menuItem;
}
public void menuSelected(MenuEvent e) {
/* Populate tools menu */
toolsMenu.removeAll();
/* Cooja plugins */
boolean hasCoojaPlugins = false;
for (Class<? extends Plugin> pluginClass: pluginClasses) {
int pluginType = pluginClass.getAnnotation(PluginType.class).value();
if (pluginType != PluginType.COOJA_PLUGIN && pluginType != PluginType.COOJA_STANDARD_PLUGIN) {
continue;
}
toolsMenu.add(createMenuItem(pluginClass, pluginType));
hasCoojaPlugins = true;
}
/* Simulation plugins */
boolean hasSimPlugins = false;
for (Class<? extends Plugin> pluginClass: pluginClasses) {
if (pluginClass.equals(SimControl.class)) {
continue; /* ignore */
}
if (pluginClass.equals(SimInformation.class)) {
continue; /* ignore */
}
if (pluginClass.equals(MoteTypeInformation.class)) {
continue; /* ignore */
}
int pluginType = pluginClass.getAnnotation(PluginType.class).value();
if (pluginType != PluginType.SIM_PLUGIN && pluginType != PluginType.SIM_STANDARD_PLUGIN) {
continue;
}
if (hasCoojaPlugins) {
hasCoojaPlugins = false;
toolsMenu.addSeparator();
}
toolsMenu.add(createMenuItem(pluginClass, pluginType));
hasSimPlugins = true;
}
for (Class<? extends Plugin> pluginClass: pluginClasses) {
int pluginType = pluginClass.getAnnotation(PluginType.class).value();
if (pluginType != PluginType.MOTE_PLUGIN) {
continue;
}
if (hasSimPlugins) {
hasSimPlugins = false;
toolsMenu.addSeparator();
}
toolsMenu.add(createMotePluginsSubmenu(pluginClass));
}
} }
public void menuDeselected(MenuEvent e) { public void menuDeselected(MenuEvent e) {
} }
@ -1051,10 +1103,6 @@ public class GUI extends Observable {
menuItem.setEnabled(false); menuItem.setEnabled(false);
helpMenu.add(menuItem); helpMenu.add(menuItem);
// Mote plugins popup menu (not available via menu bar)
if (menuMotePluginClasses == null) {
menuMotePluginClasses = new Vector<Class<? extends Plugin>>();
}
return menuBar; return menuBar;
} }
@ -1504,9 +1552,9 @@ public class GUI extends Observable {
} }
// Register plugins // Register plugins
registerPlugin(SimControl.class, false); // Not in menu registerPlugin(SimControl.class);
registerPlugin(SimInformation.class, false); // Not in menu registerPlugin(SimInformation.class);
registerPlugin(MoteTypeInformation.class, false); // Not in menu registerPlugin(MoteTypeInformation.class);
String[] pluginClassNames = projectConfig.getStringArrayValue(GUI.class, String[] pluginClassNames = projectConfig.getStringArrayValue(GUI.class,
"PLUGINS"); "PLUGINS");
if (pluginClassNames != null) { if (pluginClassNames != null) {
@ -1816,155 +1864,54 @@ public class GUI extends Observable {
return plugin; return plugin;
} }
/**
* Register a plugin to be included in the GUI. The plugin will be visible in
* the menubar.
*
* @param newPluginClass
* New plugin to register
* @return True if this plugin was registered ok, false otherwise
*/
public boolean registerPlugin(Class<? extends Plugin> newPluginClass) {
return registerPlugin(newPluginClass, true);
}
/** /**
* Unregister a plugin class. Removes any plugin menu items links as well. * Unregister a plugin class. Removes any plugin menu items links as well.
* *
* @param pluginClass Plugin class * @param pluginClass Plugin class
*/ */
public void unregisterPlugin(Class<? extends Plugin> pluginClass) { public void unregisterPlugin(Class<? extends Plugin> pluginClass) {
/* Remove from menu */
for (Component menuComponent : toolsMenu.getMenuComponents()) {
if (!(menuComponent instanceof JMenuItem)) {
continue;
}
JMenuItem menuItem = (JMenuItem) menuComponent;
if (menuItem.getClientProperty("class").equals(pluginClass)) {
toolsMenu.remove(menuItem);
}
}
menuMotePluginClasses.remove(pluginClass);
pluginClasses.remove(pluginClass); pluginClasses.remove(pluginClass);
menuMotePluginClasses.remove(pluginClass);
} }
/** /**
* Register a plugin to be included in the GUI. * Register a plugin to be included in the GUI.
* *
* @param newPluginClass * @param pluginClass New plugin to register
* New plugin to register
* @param addToMenu
* Should this plugin be added to the dedicated plugins menubar?
* @return True if this plugin was registered ok, false otherwise * @return True if this plugin was registered ok, false otherwise
*/ */
private boolean registerPlugin(final Class<? extends Plugin> newPluginClass, public boolean registerPlugin(final Class<? extends Plugin> pluginClass) {
boolean addToMenu) {
// Get description annotation (if any) /* Check plugin type */
final String description = getDescriptionOf(newPluginClass);
// Get plugin type annotation (required)
final int pluginType; final int pluginType;
if (newPluginClass.isAnnotationPresent(PluginType.class)) { if (pluginClass.isAnnotationPresent(PluginType.class)) {
pluginType = newPluginClass.getAnnotation(PluginType.class).value(); pluginType = pluginClass.getAnnotation(PluginType.class).value();
} else { } else {
pluginType = PluginType.UNDEFINED_PLUGIN; logger.fatal("Could not register plugin, no plugin type found: " + pluginClass);
return false;
} }
// Check that plugin type is valid and constructor exists /* Check plugin constructor */
try { try {
if (pluginType == PluginType.MOTE_PLUGIN) { if (pluginType == PluginType.COOJA_PLUGIN || pluginType == PluginType.COOJA_STANDARD_PLUGIN) {
newPluginClass.getConstructor(new Class[] { Mote.class, pluginClass.getConstructor(new Class[] { GUI.class });
Simulation.class, GUI.class }); } else if (pluginType == PluginType.SIM_PLUGIN || pluginType == PluginType.SIM_STANDARD_PLUGIN) {
} else if (pluginType == PluginType.SIM_PLUGIN pluginClass.getConstructor(new Class[] { Simulation.class, GUI.class });
|| pluginType == PluginType.SIM_STANDARD_PLUGIN) { } else if (pluginType == PluginType.MOTE_PLUGIN) {
newPluginClass.getConstructor(new Class[] { Simulation.class, GUI.class }); pluginClass.getConstructor(new Class[] { Mote.class, Simulation.class, GUI.class });
} else if (pluginType == PluginType.COOJA_PLUGIN menuMotePluginClasses.add(pluginClass);
|| pluginType == PluginType.COOJA_STANDARD_PLUGIN) {
newPluginClass.getConstructor(new Class[] { GUI.class });
} else { } else {
logger.fatal("Could not find valid plugin type annotation in class " + newPluginClass); logger.fatal("Could not register plugin, bad plugin type: " + pluginType);
return false; return false;
} }
pluginClasses.add(pluginClass);
} catch (NoClassDefFoundError e) { } catch (NoClassDefFoundError e) {
logger.fatal("No plugin class: " + newPluginClass + ": " + e.getMessage()); logger.fatal("No plugin class: " + pluginClass + ": " + e.getMessage());
return false; return false;
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
logger.fatal("No plugin class constructor: " + newPluginClass + ": " + e.getMessage()); logger.fatal("No plugin class constructor: " + pluginClass + ": " + e.getMessage());
return false; return false;
} }
if (addToMenu && toolsMenu != null) {
new RunnableInEDT<Boolean>() {
public Boolean work() {
// Create 'start plugin'-menu item
JMenuItem menuItem;
String tooltip = "<html><pre>";
/* Sort menu according to plugin type */
int itemIndex=0;
if (pluginType == PluginType.COOJA_PLUGIN || pluginType == PluginType.COOJA_STANDARD_PLUGIN) {
for (; itemIndex < toolsMenu.getItemCount(); itemIndex++) {
if (toolsMenu.getItem(itemIndex) == null /* separator */) {
break;
}
}
tooltip += "Cooja plugin: " + newPluginClass.getName();
menuItem = new JMenuItem(description);
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tryStartPlugin(newPluginClass, myGUI, null, null);
}
});
} else if (pluginType == PluginType.SIM_PLUGIN || pluginType == PluginType.SIM_STANDARD_PLUGIN) {
for (; itemIndex < toolsMenu.getItemCount(); itemIndex++) {
if (toolsMenu.getItem(itemIndex) == null /* separator */) {
break;
}
}
itemIndex++;
for (; itemIndex < toolsMenu.getItemCount(); itemIndex++) {
if (toolsMenu.getItem(itemIndex) == null /* separator */) {
break;
}
}
tooltip += "Simulation plugin: " + newPluginClass.getName();
GUIAction guiAction = new StartPluginGUIAction(description);
menuItem = new JMenuItem(guiAction);
guiActions.add(guiAction);
} else if (pluginType == PluginType.MOTE_PLUGIN) {
// Disable previous menu item and add new item to mote plugins menu
menuItem = new JMenuItem(description);
menuItem.setEnabled(false);
tooltip += "Mote plugin: " + newPluginClass.getName();
tooltip += "\nStart mote plugins by right-clicking a mote in the simulation visualizer";
menuMotePluginClasses.add(newPluginClass);
itemIndex = toolsMenu.getItemCount();
} else {
logger.warn("Unknown plugin type: " + pluginType);
return false;
}
/* Check if plugin was imported by a extension directory */
File project =
getProjectConfig().getUserProjectDefining(GUI.class, "PLUGINS", newPluginClass.getName());
if (project != null) {
tooltip += "\nLoaded by extension: " + project.getPath();
}
tooltip += "</html>";
/*menuItem.setToolTipText(tooltip); */
menuItem.putClientProperty("class", newPluginClass);
toolsMenu.add(menuItem, itemIndex);
return true;
}
}.invokeAndWait();
}
pluginClasses.add(newPluginClass);
return true; return true;
} }
@ -1972,16 +1919,7 @@ public class GUI extends Observable {
* Unregister all plugin classes * Unregister all plugin classes
*/ */
public void unregisterPlugins() { public void unregisterPlugins() {
if (toolsMenu != null) { menuMotePluginClasses.clear();
toolsMenu.removeAll();
/* COOJA/GUI plugins at top, simulation plugins in middle, mote plugins at bottom */
toolsMenu.addSeparator();
toolsMenu.addSeparator();
}
if (menuMotePluginClasses != null) {
menuMotePluginClasses.clear();
}
pluginClasses.clear(); pluginClasses.clear();
} }
@ -2016,6 +1954,107 @@ public class GUI extends Observable {
return startedPlugins.toArray(new Plugin[0]); return startedPlugins.toArray(new Plugin[0]);
} }
private boolean isMotePluginCompatible(Class<? extends Plugin> motePluginClass, Mote mote) {
if (motePluginClass.getAnnotation(SupportedArguments.class) == null) {
return true;
}
/* Check mote interfaces */
boolean moteInterfacesOK = true;
Class<? extends MoteInterface>[] moteInterfaces =
motePluginClass.getAnnotation(SupportedArguments.class).moteInterfaces();
StringBuilder moteTypeInterfacesError = new StringBuilder();
moteTypeInterfacesError.append(
"The plugin:\n" +
getDescriptionOf(motePluginClass) +
"\nrequires the following mote interfaces:\n"
);
for (Class<? extends MoteInterface> requiredMoteInterface: moteInterfaces) {
moteTypeInterfacesError.append(getDescriptionOf(requiredMoteInterface) + "\n");
if (mote.getInterfaces().getInterfaceOfType(requiredMoteInterface) == null) {
moteInterfacesOK = false;
}
}
/* Check mote type */
boolean moteTypeOK = false;
Class<? extends Mote>[] motes =
motePluginClass.getAnnotation(SupportedArguments.class).motes();
StringBuilder moteTypeError = new StringBuilder();
moteTypeError.append(
"The plugin:\n" +
getDescriptionOf(motePluginClass) +
"\ndoes not support motes of type:\n" +
getDescriptionOf(mote) +
"\n\nIt only supports motes of types:\n"
);
for (Class<? extends Mote> supportedMote: motes) {
moteTypeError.append(getDescriptionOf(supportedMote) + "\n");
if (supportedMote.isAssignableFrom(mote.getClass())) {
moteTypeOK = true;
}
}
/*if (!moteInterfacesOK) {
menuItem.setToolTipText(
"<html><pre>" + moteTypeInterfacesError + "</html>"
);
}
if (!moteTypeOK) {
menuItem.setToolTipText(
"<html><pre>" + moteTypeError + "</html>"
);
}*/
return moteInterfacesOK && moteTypeOK;
}
public JMenu createMotePluginsSubmenu(Class<? extends Plugin> pluginClass) {
JMenu menu = new JMenu(getDescriptionOf(pluginClass));
if (getSimulation() == null || getSimulation().getMotesCount() == 0) {
menu.setEnabled(false);
return menu;
}
ActionListener menuItemListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object pluginClass = ((JMenuItem)e.getSource()).getClientProperty("class");
Object mote = ((JMenuItem)e.getSource()).getClientProperty("mote");
tryStartPlugin((Class<? extends Plugin>) pluginClass, myGUI, getSimulation(), (Mote)mote);
}
};
final int MAX_PER_ROW = 30;
final int MAX_COLUMNS = 5;
int added = 0;
for (Mote mote: getSimulation().getMotes()) {
if (!isMotePluginCompatible(pluginClass, mote)) {
continue;
}
JMenuItem menuItem = new JMenuItem(mote.toString() + "...");
menuItem.putClientProperty("class", pluginClass);
menuItem.putClientProperty("mote", mote);
menuItem.addActionListener(menuItemListener);
menu.add(menuItem);
added++;
if (added == MAX_PER_ROW) {
menu.getPopupMenu().setLayout(new GridLayout(MAX_PER_ROW, MAX_COLUMNS));
}
if (added >= MAX_PER_ROW*MAX_COLUMNS) {
break;
}
}
if (added == 0) {
menu.setEnabled(false);
}
return menu;
}
/** /**
* Return a mote plugins submenu for given mote. * Return a mote plugins submenu for given mote.
* *
@ -2026,38 +2065,15 @@ public class GUI extends Observable {
JMenu menuMotePlugins = new JMenu("Mote tools for " + mote); JMenu menuMotePlugins = new JMenu("Mote tools for " + mote);
for (Class<? extends Plugin> motePluginClass: menuMotePluginClasses) { for (Class<? extends Plugin> motePluginClass: menuMotePluginClasses) {
GUIAction guiAction = new StartPluginGUIAction(getDescriptionOf(motePluginClass)); if (!isMotePluginCompatible(motePluginClass, mote)) {
continue;
}
GUIAction guiAction = new StartPluginGUIAction(getDescriptionOf(motePluginClass) + "...");
JMenuItem menuItem = new JMenuItem(guiAction); JMenuItem menuItem = new JMenuItem(guiAction);
menuItem.putClientProperty("class", motePluginClass); menuItem.putClientProperty("class", motePluginClass);
menuItem.putClientProperty("mote", mote); menuItem.putClientProperty("mote", mote);
/* Check if mote plugin depends on any particular type of mote */
boolean enableMenuItem = true;
if (motePluginClass.getAnnotation(SupportedArguments.class) != null) {
enableMenuItem = false;
Class<? extends Mote>[] motes = motePluginClass.getAnnotation(SupportedArguments.class).motes();
StringBuilder sb = new StringBuilder();
sb.append(
"<html><pre>This plugin:\n" +
motePluginClass.getName() +
"\ndoes not support motes of type:\n" +
mote.getClass().getName() +
"\n\nIt only supports motes of types:\n"
);
for (Class<? extends Object> o: motes) {
sb.append(o.getName() + "\n");
if (o.isAssignableFrom(mote.getClass())) {
enableMenuItem = true;
break;
}
}
sb.append("</html>");
if (!enableMenuItem) {
menuItem.setToolTipText(sb.toString());
}
}
menuItem.setEnabled(enableMenuItem);
menuMotePlugins.add(menuItem); menuMotePlugins.add(menuItem);
} }
return menuMotePlugins; return menuMotePlugins;
@ -2607,6 +2623,7 @@ public class GUI extends Observable {
mySimulation.addMote(newMote); mySimulation.addMote(newMote);
} }
} }
updateGUIComponentState();
} else { } else {
logger.warn("No simulation active"); logger.warn("No simulation active");
@ -4503,8 +4520,8 @@ public class GUI extends Observable {
} }
}; };
class StartPluginGUIAction extends GUIAction { class StartPluginGUIAction extends GUIAction {
private static final long serialVersionUID = 7368495576372376196L; private static final long serialVersionUID = 7368495576372376196L;
public StartPluginGUIAction(String name) { public StartPluginGUIAction(String name) {
super(name); super(name);
} }
public void actionPerformed(final ActionEvent e) { public void actionPerformed(final ActionEvent e) {
@ -4521,6 +4538,7 @@ public class GUI extends Observable {
return getSimulation() != null; return getSimulation() != null;
} }
} }
GUIAction removeAllMotesAction = new GUIAction("Remove all motes") { GUIAction removeAllMotesAction = new GUIAction("Remove all motes") {
private static final long serialVersionUID = 4709776747913364419L; private static final long serialVersionUID = 4709776747913364419L;
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {

View file

@ -61,4 +61,9 @@ public @interface SupportedArguments {
* @return List of accepted radio medium classes. * @return List of accepted radio medium classes.
*/ */
Class<? extends RadioMedium>[] radioMediums() default { RadioMedium.class }; Class<? extends RadioMedium>[] radioMediums() default { RadioMedium.class };
/**
* @return List of required mote interfaces.
*/
Class<? extends MoteInterface>[] moteInterfaces() default { MoteInterface.class };
} }

View file

@ -25,19 +25,20 @@
* 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: ContikiClock.java,v 1.13 2010/02/05 08:49:18 fros4943 Exp $
*/ */
package se.sics.cooja.contikimote.interfaces; package se.sics.cooja.contikimote.interfaces;
import java.util.Collection; import java.util.Collection;
import javax.swing.JPanel; import javax.swing.JPanel;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.jdom.Element; import org.jdom.Element;
import se.sics.cooja.*; import se.sics.cooja.Mote;
import se.sics.cooja.SectionMoteMemory;
import se.sics.cooja.Simulation;
import se.sics.cooja.contikimote.ContikiMote; import se.sics.cooja.contikimote.ContikiMote;
import se.sics.cooja.contikimote.ContikiMoteInterface; import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.Clock; import se.sics.cooja.interfaces.Clock;
@ -74,7 +75,7 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
private long moteTime; /* Microseconds */ private long moteTime; /* Microseconds */
private long timeDrift; /* Microseconds */ private long timeDrift; /* Microseconds */
/** /**
* @param mote Mote * @param mote Mote
* *
@ -117,9 +118,9 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
/* Update time */ /* Update time */
setTime(mote.getSimulation().getSimulationTime() + timeDrift); setTime(mote.getSimulation().getSimulationTime() + timeDrift);
} }
public void doActionsAfterTick() { public void doActionsAfterTick() {
/* Request next tick for remaining events / timers */ /* Request next tick for remaining events / timers */
int processRunValue = moteMem.getIntValueOf("simProcessRunValue"); int processRunValue = moteMem.getIntValueOf("simProcessRunValue");
if (processRunValue != 0) { if (processRunValue != 0) {
@ -137,12 +138,12 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
/* Request tick next wakeup time */ /* Request tick next wakeup time */
int nextExpirationTime = moteMem.getIntValueOf("simNextExpirationTime"); int nextExpirationTime = moteMem.getIntValueOf("simNextExpirationTime");
if (nextExpirationTime <= 0) { if (nextExpirationTime <= 0) {
logger.warn("Event timer already expired, but has been delayed: " + nextExpirationTime); /*logger.warn("Event timer already expired, but has been delayed: " + nextExpirationTime);*/
mote.scheduleNextWakeup(simulation.getSimulationTime() + Simulation.MILLISECOND); mote.scheduleNextWakeup(simulation.getSimulationTime() + Simulation.MILLISECOND);
return; return;
} }
mote.scheduleNextWakeup(simulation.getSimulationTime() + Simulation.MILLISECOND*(long)nextExpirationTime); mote.scheduleNextWakeup(simulation.getSimulationTime() + Simulation.MILLISECOND*nextExpirationTime);
} }

View file

@ -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: ScriptRunner.java,v 1.28 2010/08/17 15:03:52 fros4943 Exp $
*/ */
package se.sics.cooja.plugins; package se.sics.cooja.plugins;
@ -71,6 +69,8 @@ import javax.swing.JPopupMenu;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JSplitPane; import javax.swing.JSplitPane;
import javax.swing.JTextArea; import javax.swing.JTextArea;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileFilter;
import jsyntaxpane.DefaultSyntaxKit; import jsyntaxpane.DefaultSyntaxKit;
@ -110,15 +110,13 @@ public class ScriptRunner extends VisPlugin {
}; };
private Simulation simulation; private Simulation simulation;
private LogScriptEngine engine;
private LogScriptEngine engine = null;
private static BufferedWriter logWriter = null; /* For non-GUI tests */ private static BufferedWriter logWriter = null; /* For non-GUI tests */
private JEditorPane codeEditor = null; private JEditorPane codeEditor;
private JTextArea logTextArea;
private JTextArea logTextArea = null; private JSplitPane centerPanel;
/*private JButton toggleButton = null;*/
private JSyntaxLinkFile actionLinkFile = null; private JSyntaxLinkFile actionLinkFile = null;
private File linkedFile = null; private File linkedFile = null;
@ -126,6 +124,7 @@ public class ScriptRunner extends VisPlugin {
public ScriptRunner(Simulation simulation, GUI gui) { public ScriptRunner(Simulation simulation, GUI gui) {
super("Simulation script editor", gui, false); super("Simulation script editor", gui, false);
this.simulation = simulation; this.simulation = simulation;
this.engine = null;
/* Menus */ /* Menus */
JMenuBar menuBar = new JMenuBar(); JMenuBar menuBar = new JMenuBar();
@ -139,9 +138,8 @@ public class ScriptRunner extends VisPlugin {
this.setJMenuBar(menuBar); this.setJMenuBar(menuBar);
/* Examples popup menu */ /* Example scripts */
JMenu examplesMenu = new JMenu("Load example script"); final JMenu examplesMenu = new JMenu("Load example script");
for (int i=0; i < EXAMPLE_SCRIPTS.length; i += 2) { for (int i=0; i < EXAMPLE_SCRIPTS.length; i += 2) {
final String file = EXAMPLE_SCRIPTS[i]; final String file = EXAMPLE_SCRIPTS[i];
JMenuItem exampleItem = new JMenuItem(EXAMPLE_SCRIPTS[i+1]); JMenuItem exampleItem = new JMenuItem(EXAMPLE_SCRIPTS[i+1]);
@ -159,11 +157,10 @@ public class ScriptRunner extends VisPlugin {
}); });
examplesMenu.add(exampleItem); examplesMenu.add(exampleItem);
} }
fileMenu.add(examplesMenu); fileMenu.add(examplesMenu);
{ {
/* Workaround to configure jsyntaxpane */ /* XXX Workaround to configure jsyntaxpane */
JEditorPane e = new JEditorPane(); JEditorPane e = new JEditorPane();
new JScrollPane(e); new JScrollPane(e);
e.setContentType("text/javascript"); e.setContentType("text/javascript");
@ -171,6 +168,7 @@ public class ScriptRunner extends VisPlugin {
DefaultSyntaxKit kit = (DefaultSyntaxKit) e.getEditorKit(); DefaultSyntaxKit kit = (DefaultSyntaxKit) e.getEditorKit();
kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,linkfile"); kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,linkfile");
kit.setProperty("Action.linkfile", JSyntaxLinkFile.class.getName()); kit.setProperty("Action.linkfile", JSyntaxLinkFile.class.getName());
kit.setProperty("Action.execute-script", "jsyntaxpane.actions.ScriptRunnerAction");
} }
} }
@ -183,16 +181,11 @@ public class ScriptRunner extends VisPlugin {
logTextArea.setEditable(true); logTextArea.setEditable(true);
logTextArea.setCursor(null); logTextArea.setCursor(null);
/*toggleButton = new JButton("Activate");*/ final JCheckBoxMenuItem activateMenuItem = new JCheckBoxMenuItem("Activate");
JCheckBoxMenuItem activateMenuItem = new JCheckBoxMenuItem("Activate");
activateMenuItem.addActionListener(new ActionListener() { activateMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) { public void actionPerformed(ActionEvent ev) {
try { try {
if (!isActive()) { setScriptActive(!isActive());
setScriptActive(true);
} else {
setScriptActive(false);
}
} catch (Exception e) { } catch (Exception e) {
logger.fatal("Error: " + e.getMessage(), e); logger.fatal("Error: " + e.getMessage(), e);
} }
@ -200,8 +193,7 @@ public class ScriptRunner extends VisPlugin {
}); });
runMenu.add(activateMenuItem); runMenu.add(activateMenuItem);
/*JButton runTestButton = new JButton("Run without GUI");*/ final JMenuItem runTestMenuItem = new JMenuItem("Save simulation and run with script");
JMenuItem runTestMenuItem = new JMenuItem("Save simulation and run with script");
runMenu.add(runTestMenuItem); runMenu.add(runTestMenuItem);
runTestMenuItem.addActionListener(new ActionListener() { runTestMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
@ -210,29 +202,50 @@ public class ScriptRunner extends VisPlugin {
}); });
doLayout(); doLayout();
JSplitPane centerPanel = new JSplitPane( centerPanel = new JSplitPane(
JSplitPane.VERTICAL_SPLIT, JSplitPane.VERTICAL_SPLIT,
new JScrollPane(codeEditor), new JScrollPane(codeEditor),
new JScrollPane(logTextArea) new JScrollPane(logTextArea)
); );
MenuListener toggleMenuItems = new MenuListener() {
public void menuSelected(MenuEvent e) {
activateMenuItem.setSelected(isActive());
runTestMenuItem.setEnabled(!isActive());
examplesMenu.setEnabled(!isActive());
}
public void menuDeselected(MenuEvent e) {
}
public void menuCanceled(MenuEvent e) {
}
};
fileMenu.addMenuListener(toggleMenuItems);
editMenu.addMenuListener(toggleMenuItems);
runMenu.addMenuListener(toggleMenuItems);
codeEditor.setContentType("text/javascript"); codeEditor.setContentType("text/javascript");
if (codeEditor.getEditorKit() instanceof DefaultSyntaxKit) { if (codeEditor.getEditorKit() instanceof DefaultSyntaxKit) {
DefaultSyntaxKit kit = (DefaultSyntaxKit) codeEditor.getEditorKit(); DefaultSyntaxKit kit = (DefaultSyntaxKit) codeEditor.getEditorKit();
kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,linkfile"); kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,linkfile");
kit.setProperty("Action.linkfile", JSyntaxLinkFile.class.getName()); kit.setProperty("Action.linkfile", JSyntaxLinkFile.class.getName());
kit.setProperty("Action.execute-script", "jsyntaxpane.actions.ScriptRunnerAction");
} }
JPopupMenu p = codeEditor.getComponentPopupMenu(); JPopupMenu p = codeEditor.getComponentPopupMenu();
if (p != null) { if (p != null) {
for (Component c: p.getComponents()) { for (Component c: p.getComponents()) {
if (c instanceof JMenuItem) { if (!(c instanceof JMenuItem)) {
if (((JMenuItem) c).getAction() != null && continue;
((JMenuItem) c).getAction() instanceof JSyntaxLinkFile) { }
actionLinkFile = (JSyntaxLinkFile)(((JMenuItem) c).getAction()); if (((JMenuItem) c).getAction() == null) {
actionLinkFile.setMenuText("Link script to disk file"); continue;
actionLinkFile.putValue("ScriptRunner", this); }
} Action a = ((JMenuItem) c).getAction();
if (a instanceof JSyntaxLinkFile) {
actionLinkFile = (JSyntaxLinkFile) a;
actionLinkFile.setMenuText("Link script to disk file");
actionLinkFile.putValue("ScriptRunner", this);
} }
} }
} }
@ -241,10 +254,6 @@ public class ScriptRunner extends VisPlugin {
centerPanel.setResizeWeight(0.5); centerPanel.setResizeWeight(0.5);
JPanel buttonPanel = new JPanel(new BorderLayout()); JPanel buttonPanel = new JPanel(new BorderLayout());
/*buttonPanel.add(BorderLayout.CENTER, toggleButton);*/
/* buttonPanel.add(BorderLayout.EAST, runTestButton);*/
JPanel southPanel = new JPanel(new BorderLayout()); JPanel southPanel = new JPanel(new BorderLayout());
southPanel.add(BorderLayout.EAST, buttonPanel); southPanel.add(BorderLayout.EAST, buttonPanel);
@ -280,6 +289,7 @@ public class ScriptRunner extends VisPlugin {
codeEditor.setEditable(true); codeEditor.setEditable(true);
} else { } else {
updateScript(linkedFile); updateScript(linkedFile);
GUI.setExternalToolsSetting("SCRIPTRUNNER_LAST_SCRIPTFILE", source.getAbsolutePath());
if (actionLinkFile != null) { if (actionLinkFile != null) {
actionLinkFile.setMenuText("Unlink script: " + source.getName()); actionLinkFile.setMenuText("Unlink script: " + source.getName());
@ -357,9 +367,9 @@ public class ScriptRunner extends VisPlugin {
engine.activateScript(codeEditor.getText()); engine.activateScript(codeEditor.getText());
if (!headless) { if (!headless) {
actionLinkFile.setEnabled(false); if (actionLinkFile != null) {
/* toggleButton.setText("Deactivate");*/ actionLinkFile.setEnabled(false);
/*examplesButton.setEnabled(false);*/ }
logTextArea.setText(""); logTextArea.setText("");
codeEditor.setEnabled(false); codeEditor.setEnabled(false);
updateTitle(); updateTitle();
@ -402,9 +412,9 @@ public class ScriptRunner extends VisPlugin {
} }
if (!headless) { if (!headless) {
actionLinkFile.setEnabled(true); if (actionLinkFile != null) {
/*toggleButton.setText("Activate")*/; actionLinkFile.setEnabled(true);
/*examplesButton.setEnabled(linkedFile==null?true:false);*/ }
codeEditor.setEnabled(true); codeEditor.setEnabled(true);
updateTitle(); updateTitle();
} }
@ -413,14 +423,14 @@ public class ScriptRunner extends VisPlugin {
} }
private void updateTitle() { private void updateTitle() {
/*String title = "Contiki Test Editor "; String title = "Simulation script editor ";
if (linkedFile != null) { if (linkedFile != null) {
title += ": " + linkedFile.getName() + " "; title += "(" + linkedFile.getName() + ") ";
} }
if (isActive()) { if (isActive()) {
title += "(ACTIVE) "; title += "*active*";
} }
setTitle(title);*/ setTitle(title);
} }
private void exportAndRun() { private void exportAndRun() {
@ -609,7 +619,6 @@ public class ScriptRunner extends VisPlugin {
element = new Element("scriptfile"); element = new Element("scriptfile");
element.setText(simulation.getGUI().createPortablePath(linkedFile).getPath().replace('\\', '/')); element.setText(simulation.getGUI().createPortablePath(linkedFile).getPath().replace('\\', '/'));
config.add(element); config.add(element);
/*StringUtils.saveToFile(scriptFile, scriptTextArea.getText());*/
} else { } else {
element = new Element("script"); element = new Element("script");
element.setText(codeEditor.getText()); element.setText(codeEditor.getText());
@ -692,7 +701,12 @@ public class ScriptRunner extends VisPlugin {
} }
JFileChooser fileChooser = new JFileChooser(); JFileChooser fileChooser = new JFileChooser();
fileChooser.setCurrentDirectory(new java.io.File(".")); String suggest = GUI.getExternalToolsSetting("SCRIPTRUNNER_LAST_SCRIPTFILE", null);
if (suggest != null) {
fileChooser.setSelectedFile(new File(suggest));
} else {
fileChooser.setCurrentDirectory(new java.io.File("."));
}
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setDialogTitle("Select script file"); fileChooser.setDialogTitle("Select script file");
fileChooser.setFileFilter(new FileFilter() { fileChooser.setFileFilter(new FileFilter() {

View file

@ -37,7 +37,6 @@ import java.awt.Cursor;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point; import java.awt.Point;
import java.awt.Polygon; import java.awt.Polygon;
import java.awt.RenderingHints; import java.awt.RenderingHints;
@ -54,6 +53,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.ItemEvent; import java.awt.event.ItemEvent;
import java.awt.event.ItemListener; import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener; import java.awt.event.MouseMotionListener;
@ -68,7 +68,7 @@ import java.util.Observable;
import java.util.Observer; import java.util.Observer;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.JButton; import javax.swing.Action;
import javax.swing.JCheckBoxMenuItem; import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu; import javax.swing.JMenu;
import javax.swing.JMenuBar; import javax.swing.JMenuBar;
@ -77,9 +77,12 @@ import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JPopupMenu; import javax.swing.JPopupMenu;
import javax.swing.JSeparator; import javax.swing.JSeparator;
import javax.swing.KeyStroke;
import javax.swing.MenuElement; import javax.swing.MenuElement;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.Timer; import javax.swing.Timer;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.plaf.basic.BasicInternalFrameUI; import javax.swing.plaf.basic.BasicInternalFrameUI;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -87,16 +90,16 @@ import org.jdom.Element;
import se.sics.cooja.ClassDescription; import se.sics.cooja.ClassDescription;
import se.sics.cooja.GUI; import se.sics.cooja.GUI;
import se.sics.cooja.GUI.MoteRelation;
import se.sics.cooja.HasQuickHelp; import se.sics.cooja.HasQuickHelp;
import se.sics.cooja.Mote; import se.sics.cooja.Mote;
import se.sics.cooja.MoteInterface; import se.sics.cooja.MoteInterface;
import se.sics.cooja.PluginType; import se.sics.cooja.PluginType;
import se.sics.cooja.RadioMedium; import se.sics.cooja.RadioMedium;
import se.sics.cooja.SimEventCentral.MoteCountListener;
import se.sics.cooja.Simulation; import se.sics.cooja.Simulation;
import se.sics.cooja.SupportedArguments; import se.sics.cooja.SupportedArguments;
import se.sics.cooja.VisPlugin; import se.sics.cooja.VisPlugin;
import se.sics.cooja.GUI.MoteRelation;
import se.sics.cooja.SimEventCentral.MoteCountListener;
import se.sics.cooja.interfaces.LED; import se.sics.cooja.interfaces.LED;
import se.sics.cooja.interfaces.Position; import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.SerialPort; import se.sics.cooja.interfaces.SerialPort;
@ -160,7 +163,6 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
private Cursor moveCursor = new Cursor(Cursor.MOVE_CURSOR); private Cursor moveCursor = new Cursor(Cursor.MOVE_CURSOR);
/* Visualizers */ /* Visualizers */
private final JButton skinButton = new JButton("Select visualizer skins");
private static ArrayList<Class<? extends VisualizerSkin>> visualizerSkins = private static ArrayList<Class<? extends VisualizerSkin>> visualizerSkins =
new ArrayList<Class<? extends VisualizerSkin>>(); new ArrayList<Class<? extends VisualizerSkin>>();
static { static {
@ -222,29 +224,47 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
/* Menus */ /* Menus */
JMenuBar menuBar = new JMenuBar(); JMenuBar menuBar = new JMenuBar();
viewMenu = new JMenu("View"); viewMenu = new JMenu("View");
viewMenu.addMenuListener(new MenuListener() {
public void menuSelected(MenuEvent e) {
viewMenu.removeAll();
populateSkinMenu(viewMenu);
}
public void menuDeselected(MenuEvent e) {
}
public void menuCanceled(MenuEvent e) {
}
});
JMenu zoomMenu = new JMenu("Zoom"); JMenu zoomMenu = new JMenu("Zoom");
menuBar.add(viewMenu); menuBar.add(viewMenu);
menuBar.add(zoomMenu); menuBar.add(zoomMenu);
this.setJMenuBar(menuBar); this.setJMenuBar(menuBar);
JMenuItem zoomInItem = new JMenuItem("Zoom in"); Action zoomInAction = new AbstractAction("Zoom in") {
zoomInItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
zoomToFactor(zoomFactor() * 1.2); zoomToFactor(zoomFactor() * 1.2);
} }
}); };
zoomInAction.putValue(
Action.ACCELERATOR_KEY,
KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, ActionEvent.CTRL_MASK)
);
JMenuItem zoomInItem = new JMenuItem(zoomInAction);
zoomMenu.add(zoomInItem); zoomMenu.add(zoomInItem);
JMenuItem zoomOutItem = new JMenuItem("Zoom out"); Action zoomOutAction = new AbstractAction("Zoom out") {
zoomOutItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
zoomToFactor(zoomFactor() / 1.2); zoomToFactor(zoomFactor() / 1.2);
} }
}); };
zoomOutAction.putValue(
Action.ACCELERATOR_KEY,
KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, ActionEvent.CTRL_MASK)
);
JMenuItem zoomOutItem = new JMenuItem(zoomOutAction);
zoomMenu.add(zoomOutItem); zoomMenu.add(zoomOutItem);
JMenuItem resetViewportItem = new JMenuItem("Reset viewport"); JMenuItem resetViewportItem = new JMenuItem("Reset viewport");
@ -280,20 +300,6 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
canvas.setBackground(Color.WHITE); canvas.setBackground(Color.WHITE);
viewportTransform = new AffineTransform(); viewportTransform = new AffineTransform();
/* Skin selector */
skinButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Point mouse = MouseInfo.getPointerInfo().getLocation();
JPopupMenu skinPopupMenu = new JPopupMenu();
populateSkinMenu(skinPopupMenu);
skinPopupMenu.setLocation(mouse);
skinPopupMenu.setInvoker(skinButton);
skinPopupMenu.setVisible(true);
}
});
/*this.add(BorderLayout.NORTH, skinButton);*/
this.add(BorderLayout.CENTER, canvas); this.add(BorderLayout.CENTER, canvas);
/* Observe simulation and mote positions */ /* Observe simulation and mote positions */
@ -524,7 +530,7 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
/* XXX HACK: here we set the position and size of the window when it appears on a blank simulation screen. */ /* XXX HACK: here we set the position and size of the window when it appears on a blank simulation screen. */
this.setLocation(1, 1); this.setLocation(1, 1);
this.setSize(400, 400); this.setSize(400, 400);
} }
private void generateAndActivateSkin(Class<? extends VisualizerSkin> skinClass) { private void generateAndActivateSkin(Class<? extends VisualizerSkin> skinClass) {
@ -550,9 +556,6 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
} catch (IllegalAccessException e1) { } catch (IllegalAccessException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
skinButton.setText("Select visualizer " +
"(" + currentSkins.size() + "/" + visualizerSkins.size() + ")");
repaint(); repaint();
} }
@ -572,7 +575,6 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
simulation.getGUI().tryLoadClass(this, VisualizerSkin.class, skin); simulation.getGUI().tryLoadClass(this, VisualizerSkin.class, skin);
generateAndActivateSkin(skinClass); generateAndActivateSkin(skinClass);
} }
populateSkinMenu(viewMenu);
} }
public VisualizerSkin[] getCurrentSkins() { public VisualizerSkin[] getCurrentSkins() {
@ -698,11 +700,15 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
menu.setVisible(true); menu.setVisible(true);
} }
private void populateSkinMenu(MenuElement skinMenu) { private void populateSkinMenu(MenuElement menu) {
JCheckBoxMenuItem item;
for (Class<? extends VisualizerSkin> skinClass: visualizerSkins) { for (Class<? extends VisualizerSkin> skinClass: visualizerSkins) {
/* Should skin be enabled in this simulation? */
if (!isSkinCompatible(skinClass)) {
continue;
}
String description = GUI.getDescriptionOf(skinClass); String description = GUI.getDescriptionOf(skinClass);
item = new JCheckBoxMenuItem(description, false); JCheckBoxMenuItem item = new JCheckBoxMenuItem(description, false);
item.putClientProperty("skinclass", skinClass); item.putClientProperty("skinclass", skinClass);
/* Select skin if active */ /* Select skin if active */
@ -747,23 +753,15 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
skinToDeactivate.setInactive(); skinToDeactivate.setInactive();
repaint(); repaint();
currentSkins.remove(skinToDeactivate); currentSkins.remove(skinToDeactivate);
skinButton.setText("Select visualizers " +
"(" + currentSkins.size() + "/" + visualizerSkins.size() + ")");
} }
} }
}); });
if (menu instanceof JMenu) {
/* Should skin be enabled in this simulation? */ ((JMenu)menu).add(item);
if (!isSkinCompatible(skinClass)) {
continue;
} }
if (menu instanceof JPopupMenu) {
if (skinMenu instanceof JMenu) { ((JPopupMenu)menu).add(item);
((JMenu)skinMenu).add(item);
}
if (skinMenu instanceof JPopupMenu) {
((JPopupMenu)skinMenu).add(item);
} }
} }
} }
@ -833,24 +831,26 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
repaint(); repaint();
} }
private double zoomFactor() private double zoomFactor() {
{
return viewportTransform.getScaleX(); return viewportTransform.getScaleX();
} }
private void zoomToFactor(double newZoom) { private void zoomToFactor(double newZoom) {
Position center = transformPixelToPosition(
new Point(canvas.getWidth()/2, canvas.getHeight()/2)
);
viewportTransform.setToScale( viewportTransform.setToScale(
newZoom, newZoom,
newZoom newZoom
); );
Position newCenter = transformPixelToPosition(
/*Position moved = transformPixelToPosition(zoomingPixel); new Point(canvas.getWidth()/2, canvas.getHeight()/2)
viewportTransform.translate( );
moved.getXCoordinate() - zoomingPosition.getXCoordinate(), viewportTransform.translate(
moved.getYCoordinate() - zoomingPosition.getYCoordinate() newCenter.getXCoordinate() - center.getXCoordinate(),
);*/ newCenter.getYCoordinate() - center.getYCoordinate()
);
repaint(); repaint();
} }
private void handleMouseMove(MouseEvent e, boolean stop) { private void handleMouseMove(MouseEvent e, boolean stop) {
@ -917,7 +917,7 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
} }
/* Restore cursor */ /* Restore cursor */
canvas.setCursor(Cursor.getDefaultCursor()); canvas.setCursor(Cursor.getDefaultCursor());
/* Move mote */ /* Move mote */
if (moveStartTime < 0 || System.currentTimeMillis() - moveStartTime > 300) { if (moveStartTime < 0 || System.currentTimeMillis() - moveStartTime > 300) {
@ -1294,7 +1294,7 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
} }
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) { public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
loadedConfig = true; loadedConfig = true;
for (Element element : configXML) { for (Element element : configXML) {
if (element.getName().equals("skin")) { if (element.getName().equals("skin")) {
@ -1335,7 +1335,6 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
} else if (element.getName().equals("hidden")) { } else if (element.getName().equals("hidden")) {
BasicInternalFrameUI ui = (BasicInternalFrameUI) getUI(); BasicInternalFrameUI ui = (BasicInternalFrameUI) getUI();
ui.getNorthPane().setPreferredSize(new Dimension(0,0)); ui.getNorthPane().setPreferredSize(new Dimension(0,0));
skinButton.setVisible(false);
} }
} }
return true; return true;
@ -1489,11 +1488,9 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
ui.getNorthPane().getPreferredSize().height == 0) { ui.getNorthPane().getPreferredSize().height == 0) {
/* Restore window decorations */ /* Restore window decorations */
ui.getNorthPane().setPreferredSize(null); ui.getNorthPane().setPreferredSize(null);
visualizer.skinButton.setVisible(true);
} else { } else {
/* Hide window decorations */ /* Hide window decorations */
ui.getNorthPane().setPreferredSize(new Dimension(0,0)); ui.getNorthPane().setPreferredSize(new Dimension(0,0));
visualizer.skinButton.setVisible(false);
} }
visualizer.revalidate(); visualizer.revalidate();
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@ -1525,10 +1522,10 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
public String getQuickHelp() { public String getQuickHelp() {
return return
"<b>Network</b> " + "<b>Network</b> " +
"<p>The network windo shows the positions of simulated motes. " + "<p>The network window shows the positions of simulated motes. " +
"It is possible to zoom (CRTL+Mouse drag) and pan (Shift+Mouse drag) the current view. Motes can be moved by dragging them. " + "It is possible to zoom (CRTL+Mouse drag) and pan (Shift+Mouse drag) the current view. Motes can be moved by dragging them. " +
"Mouse right-click motes for options. " + "Mouse right-click motes for options. " +
"<p>The network window suppors different views. " + "<p>The network window supports different views. " +
"Each view provides some specific information, such as the IP addresses of motes. " + "Each view provides some specific information, such as the IP addresses of motes. " +
"Multiple views can be active at the same time. " + "Multiple views can be active at the same time. " +
"Use the View menu to select views. "; "Use the View menu to select views. ";

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: TrafficVisualizerSkin.java,v 1.5 2010/02/26 07:46:26 nifi Exp $
*/ */
package se.sics.cooja.plugins.skins; package se.sics.cooja.plugins.skins;
@ -34,273 +32,203 @@ package se.sics.cooja.plugins.skins;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Point; import java.awt.Point;
import java.util.ArrayDeque; import java.awt.Polygon;
import java.util.ArrayList;
import java.util.Observable; import java.util.Observable;
import java.util.Observer; import java.util.Observer;
import javax.swing.Box;
import javax.swing.JLabel;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import se.sics.cooja.ClassDescription; import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote; import se.sics.cooja.Mote;
import se.sics.cooja.RadioConnection; import se.sics.cooja.RadioConnection;
import se.sics.cooja.Simulation; import se.sics.cooja.Simulation;
import se.sics.cooja.SimEventCentral.MoteCountListener; import se.sics.cooja.SupportedArguments;
import se.sics.cooja.TimeEvent;
import se.sics.cooja.interfaces.Position; import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.Radio;
import se.sics.cooja.plugins.Visualizer; import se.sics.cooja.plugins.Visualizer;
import se.sics.cooja.plugins.VisualizerSkin; import se.sics.cooja.plugins.VisualizerSkin;
import se.sics.cooja.plugins.Visualizer.SimulationMenuAction;
import se.sics.cooja.radiomediums.AbstractRadioMedium; import se.sics.cooja.radiomediums.AbstractRadioMedium;
/** /**
* Radio traffic visualizer skin. * Radio traffic history visualizer skin.
* *
* Transmitting motes are painted blue. Receiving motes are painted green.
* Interfered motes are painted red. Motes without radios are painted gray. All
* other motes are painted white.
*
* In contrast to the {@link UDGMVisualizerSkin}, this skin listens to all mote
* radios, not to the radio medium. The radio traffic skin also displays a
* history.
*
* @see UDGMVisualizerSkin * @see UDGMVisualizerSkin
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
@ClassDescription("Radio traffic") @ClassDescription("Radio traffic")
@SupportedArguments(radioMediums = {AbstractRadioMedium.class})
public class TrafficVisualizerSkin implements VisualizerSkin { public class TrafficVisualizerSkin implements VisualizerSkin {
private static Logger logger = Logger.getLogger(TrafficVisualizerSkin.class); private static Logger logger = Logger.getLogger(TrafficVisualizerSkin.class);
private static final boolean DRAW_ARROWS = true; private final int MAX_HISTORY_SIZE = 200;
private static final Color COLOR_HISTORY = new Color(100, 100, 100, 100);
private boolean active = false;
private Simulation simulation = null; private Simulation simulation = null;
private Visualizer visualizer = null; private Visualizer visualizer = null;
private AbstractRadioMedium radioMedium = null;
private Box counters; private ArrayList<RadioConnectionArrow> historyList = new ArrayList<RadioConnectionArrow>();
private RadioConnectionArrow[] history = null;
private final static int HISTORY_SIZE = 16; private Observer radioMediumObserver = new Observer() {
private boolean showHistory = false; public void update(Observable obs, Object obj) {
private ArrayDeque<RadioConnection> history = new ArrayDeque<RadioConnection>(); RadioConnection last = radioMedium.getLastConnection();
if (last != null && historyList.size() < MAX_HISTORY_SIZE) {
private AbstractRadioMedium radioMedium; historyList.add(new RadioConnectionArrow(last));
private Observer radioObserver, radioMediumObserver; history = historyList.toArray(new RadioConnectionArrow[0]);
visualizer.repaint(500);
public void setActive(Simulation simulation, Visualizer vis) { }
if (!(simulation.getRadioMedium() instanceof AbstractRadioMedium)) {
logger.fatal("Radio medium type not supported: " + simulation.getRadioMedium());
return;
} }
};
private TimeEvent ageArrowsTimeEvent = new TimeEvent(0) {
public void execute(long t) {
if (!active) {
return;
}
if (historyList.size() > 0) {
boolean hasOld = false;
/* Increase age */
for (RadioConnectionArrow connArrow : historyList) {
connArrow.increaseAge();
if(connArrow.getAge() >= connArrow.getMaxAge()) {
hasOld = true;
}
}
/* Remove too old arrows */
if (hasOld) {
RadioConnectionArrow[] historyArr = historyList.toArray(new RadioConnectionArrow[0]);
for (RadioConnectionArrow connArrow : historyArr) {
if(connArrow.getAge() >= connArrow.getMaxAge()) {
historyList.remove(connArrow);
}
}
historyArr = historyList.toArray(new RadioConnectionArrow[0]);
}
visualizer.repaint(500);
}
/* Reschedule myself */
simulation.scheduleEvent(this, t + 100*Simulation.MILLISECOND);
}
};
public void setActive(final Simulation simulation, Visualizer vis) {
this.radioMedium = (AbstractRadioMedium) simulation.getRadioMedium(); this.radioMedium = (AbstractRadioMedium) simulation.getRadioMedium();
this.simulation = simulation; this.simulation = simulation;
this.visualizer = vis; this.visualizer = vis;
this.active = true;
final JLabel txCounter = new JLabel("TX: " + radioMedium.COUNTER_TX); simulation.invokeSimulationThread(new Runnable() {
final JLabel rxCounter = new JLabel("RX: " + radioMedium.COUNTER_RX); public void run() {
final JLabel interferedCounter = new JLabel("INT: " + radioMedium.COUNTER_INTERFERED); historyList.clear();
history = null;
counters = Box.createHorizontalBox(); /* Start observing radio medium for transmissions */
counters.add(txCounter); radioMedium.addRadioMediumObserver(radioMediumObserver);
counters.add(Box.createHorizontalStrut(10));
counters.add(rxCounter);
counters.add(Box.createHorizontalStrut(10));
counters.add(interferedCounter);
/* visualizer.getCurrentCanvas().add(counters);*/ /* Fade away arrows */
simulation.scheduleEvent(ageArrowsTimeEvent, simulation.getSimulationTime() + 100*Simulation.MILLISECOND);
/* Start observing radio medium and radios */
radioMedium.addRadioMediumObserver(radioMediumObserver = new Observer() {
public void update(Observable obs, Object obj) {
txCounter.setText("TX: " + radioMedium.COUNTER_TX);
rxCounter.setText("RX: " + radioMedium.COUNTER_RX);
interferedCounter.setText("INT: " + + radioMedium.COUNTER_INTERFERED);
if (showHistory) {
RadioConnection last = radioMedium.getLastConnection();
if (last != null) {
history.add(last);
while (history.size() > HISTORY_SIZE) {
history.removeFirst();
}
}
}
visualizer.repaint();
} }
}); });
radioObserver = new Observer() {
public void update(Observable o, Object arg) {
visualizer.repaint();
}
};
simulation.getEventCentral().addMoteCountListener(new MoteCountListener() {
public void moteWasAdded(Mote mote) {
Radio r = mote.getInterfaces().getRadio();
if (r != null) {
r.addObserver(radioObserver);
}
}
public void moteWasRemoved(Mote mote) {
Radio r = mote.getInterfaces().getRadio();
if (r != null) {
r.deleteObserver(radioObserver);
}
history.clear();
}
});
for (Mote mote: simulation.getMotes()) {
Radio r = mote.getInterfaces().getRadio();
if (r != null) {
r.addObserver(radioObserver);
}
}
/* Register menu actions */
visualizer.registerSimulationMenuAction(ToggleHistoryAction.class);
} }
public void setInactive() { public void setInactive() {
this.active = false;
if (simulation == null) { if (simulation == null) {
/* Skin was never activated */ /* Skin was never activated */
return; return;
} }
visualizer.getCurrentCanvas().remove(counters); /* Stop observing radio medium */
/* Stop observing radio medium and radios */
radioMedium.deleteRadioMediumObserver(radioMediumObserver); radioMedium.deleteRadioMediumObserver(radioMediumObserver);
for (Mote mote: simulation.getMotes()) {
Radio r = mote.getInterfaces().getRadio();
if (r != null) {
r.addObserver(radioObserver);
}
}
/* Unregister menu actions */
visualizer.unregisterSimulationMenuAction(ToggleHistoryAction.class);
} }
public Color[] getColorOf(Mote mote) { public Color[] getColorOf(Mote mote) {
if (simulation == null) {
/* Skin was never activated */
return null;
}
Radio moteRadio = mote.getInterfaces().getRadio();
if (moteRadio == null) {
return null;
}
if (!moteRadio.isRadioOn()) {
return new Color[] { Color.GRAY };
}
if (moteRadio.isTransmitting()) {
return new Color[] { Color.BLUE };
}
if (moteRadio.isInterfered()) {
return new Color[] { Color.RED };
}
if (moteRadio.isReceiving()) {
return new Color[] { Color.GREEN };
}
return null; return null;
} }
private Polygon arrowPoly = new Polygon();
private void drawArrow(Graphics g, int xSource, int ySource, int xDest, int yDest, int delta) {
double dx = xSource - xDest;
double dy = ySource - yDest;
double dir = Math.atan2(dx, dy);
double len = Math.sqrt(dx * dx + dy * dy);
dx /= len;
dy /= len;
len -= delta;
xDest = xSource - (int) (dx * len);
yDest = ySource - (int) (dy * len);
g.drawLine(xDest, yDest, xSource, ySource);
final int size = 8;
arrowPoly.reset();
arrowPoly.addPoint(xDest, yDest);
arrowPoly.addPoint(xDest + xCor(size, dir + 0.5), yDest + yCor(size, dir + 0.5));
arrowPoly.addPoint(xDest + xCor(size, dir - 0.5), yDest + yCor(size, dir - 0.5));
arrowPoly.addPoint(xDest, yDest);
g.fillPolygon(arrowPoly);
}
private int yCor(int len, double dir) {
return (int)(0.5 + len * Math.cos(dir));
}
private int xCor(int len, double dir) {
return (int)(0.5 + len * Math.sin(dir));
}
public void paintBeforeMotes(Graphics g) { public void paintBeforeMotes(Graphics g) {
if (simulation == null) { RadioConnectionArrow[] historyCopy = history;
/* Skin was never activated */ if (historyCopy == null) {
return; return;
} }
for (RadioConnectionArrow connArrow : historyCopy) {
if (showHistory) { float colorHistoryIndex = (float)connArrow.getAge() / (float)connArrow.getMaxAge();
/* Paint history in gray */ g.setColor(new Color(colorHistoryIndex, colorHistoryIndex, 1.0f));
RadioConnection[] historyArr = history.toArray(new RadioConnection[0]); Radio source = connArrow.getConnection().getSource();
for (RadioConnection conn : historyArr) { Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition());
if (conn == null) { for (Radio destRadio : connArrow.getConnection().getDestinations()) {
continue; Position destPos = destRadio.getPosition();
} Point destPoint = visualizer.transformPositionToPixel(destPos);
g.setColor(COLOR_HISTORY); drawArrow(g, sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y, 8);
Radio source = conn.getSource();
Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition());
for (Radio destRadio : conn.getDestinations()) {
Position destPos = destRadio.getPosition();
Point destPoint = visualizer.transformPositionToPixel(destPos);
g.drawLine(sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y);
}
}
}
/* Paint active connections in black */
RadioConnection[] conns = radioMedium.getActiveConnections();
if (conns != null) {
g.setColor(Color.BLACK);
for (RadioConnection conn : conns) {
if (conn == null) {
continue;
}
Radio source = conn.getSource();
Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition());
for (Radio destRadio : conn.getDestinations()) {
if (destRadio == null) {
continue;
}
Position destPos = destRadio.getPosition();
Point destPoint = visualizer.transformPositionToPixel(destPos);
g.drawLine(sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y);
/* Draw arrows */
if (DRAW_ARROWS) {
Point centerPoint = new Point(
destPoint.x/2 + sourcePoint.x/2,
destPoint.y/2 + sourcePoint.y/2
);
int startAngle = (int) (-180 * Math.atan2(destPoint.y - sourcePoint.y, destPoint.x - sourcePoint.x)/Math.PI - 90);
g.drawArc(centerPoint.x-5, centerPoint.y-5, 10, 10, startAngle, 180);
}
}
} }
} }
} }
public void paintAfterMotes(Graphics g) { public void paintAfterMotes(Graphics g) {
} }
public static class ToggleHistoryAction implements SimulationMenuAction {
public boolean isEnabled(Visualizer visualizer, Simulation simulation) {
return true;
}
public String getDescription(Visualizer visualizer, Simulation simulation) {
VisualizerSkin[] skins = visualizer.getCurrentSkins();
boolean showing = false;
for (VisualizerSkin skin: skins) {
if (skin instanceof TrafficVisualizerSkin) {
showing = ((TrafficVisualizerSkin)skin).showHistory;
}
}
if (showing) {
return "Hide traffic history";
}
return "Show traffic history";
}
public void doAction(Visualizer visualizer, Simulation simulation) {
VisualizerSkin[] skins = visualizer.getCurrentSkins();
for (VisualizerSkin skin: skins) {
if (skin instanceof TrafficVisualizerSkin) {
((TrafficVisualizerSkin)skin).showHistory = !((TrafficVisualizerSkin)skin).showHistory;
visualizer.repaint();
}
}
}
};
public Visualizer getVisualizer() { public Visualizer getVisualizer() {
return visualizer; return visualizer;
} }
private static class RadioConnectionArrow {
private RadioConnection conn;
private int age;
private static final int MAX_AGE = 10;
RadioConnectionArrow(RadioConnection conn) {
this.conn = conn;
this.age = 0;
}
public void increaseAge() {
if (age < MAX_AGE) {
age++;
}
}
public int getAge() {
return age;
}
public RadioConnection getConnection() {
return conn;
}
public int getMaxAge() {
return MAX_AGE;
}
}
} }