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
U0CSR = UCSR_MODE; /* UART mode */
U0UCR = 0x80; /* Flush */
U0UCR |= 0x80; /* Flush */
UART0_RX_EN();
UART0_RX_INT(1);

View file

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

View file

@ -381,7 +381,12 @@ void halLcdActive(void)
// Wait a minimum of 25ms after issuing "start oscillation"
// 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] &= ~BIT0;

View file

@ -214,10 +214,9 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
this.myCpu.setMonitorExec(true);
this.myCpu.setTrace(0); /* TODO Enable */
int[] memory = myCpu.memory;
logger.info("Loading firmware from: " + fileELF.getAbsolutePath());
GUI.setProgressMessage("Loading " + fileELF.getName());
node.loadFirmware(((MspMoteType)getType()).getELF(), memory);
node.loadFirmware(((MspMoteType)getType()).getELF());
/* Throw exceptions at bad memory access */
/*myCpu.setThrowIfWarning(true);*/
@ -417,6 +416,10 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
}
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);
}
}

View file

@ -69,18 +69,21 @@ import org.jdom.Element;
import se.sics.cooja.ClassDescription;
import se.sics.cooja.GUI;
import se.sics.cooja.GUI.RunnableInEDT;
import se.sics.cooja.Mote;
import se.sics.cooja.MotePlugin;
import se.sics.cooja.PluginType;
import se.sics.cooja.Simulation;
import se.sics.cooja.SupportedArguments;
import se.sics.cooja.VisPlugin;
import se.sics.cooja.GUI.RunnableInEDT;
import se.sics.cooja.dialogs.CompileContiki;
import se.sics.cooja.dialogs.MessageList;
import se.sics.cooja.interfaces.IPAddress;
import se.sics.cooja.interfaces.SerialPort;
@ClassDescription("Open Native IP Gateway")
@PluginType(PluginType.MOTE_PLUGIN)
@SupportedArguments(moteInterfaces = {IPAddress.class})
public class NativeIPGateway extends VisPlugin implements MotePlugin {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(NativeIPGateway.class);
@ -564,7 +567,7 @@ public class NativeIPGateway extends VisPlugin implements MotePlugin {
progressDialog.getContentPane().add(BorderLayout.NORTH, progressBar);
progressDialog.getContentPane().add(BorderLayout.CENTER, new JScrollPane(output));
progressDialog.setSize(350, 150);
progressDialog.setLocationRelativeTo((Window)GUI.getTopParentContainer());
progressDialog.setLocationRelativeTo(GUI.getTopParentContainer());
progressDialog.setVisible(true);
GUI.setProgressMessage("Compiling hello-world.minimal-net (Native IP Gateway)");
return true;

View file

@ -4,7 +4,6 @@ KEYBOARD_SHORTCUTS = \
<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+Shift+R:</i> Reload current simulation with another random seed\
<br><i>Ctrl+X:</i> Quit COOJA\
<br>\
<br><i>F1:</i> Toggle quick help

View file

@ -1,12 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project>../apps/mrm</project>
<project>../apps/mspsim</project>
<project>../apps/avrora</project>
<project>../apps/native_gateway</project>
<simulation>
<title>My simulation</title>
<delaytime>0</delaytime>
<title>Hello World test (Cooja motes)</title>
<randomseed>generated</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
@ -16,11 +11,14 @@
<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.contikimote.ContikiMoteType
<identifier>mtype82</identifier>
<identifier>mtype725</identifier>
<description>Contiki Mote Type #1</description>
<contikiapp>../../../examples/hello-world/hello-world.c</contikiapp>
<source>[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
<commands>make hello-world.cooja TARGET=cooja</commands>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Battery</moteinterface>
@ -28,6 +26,7 @@
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>se.sics.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiButton</moteinterface>
@ -36,41 +35,35 @@
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>se.sics.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>se.sics.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>se.sics.cooja.interfaces.MoteAttributes</moteinterface>
<symbols>false</symbols>
<commstack>Rime</commstack>
</motetype>
<mote>
se.sics.cooja.contikimote.ContikiMote
<motetype_identifier>mtype82</motetype_identifier>
<interface_config>
se.sics.cooja.interfaces.Position
<x>69.64867743029201</x>
<y>69.2570131081022</y>
<z>0.0</z>
</interface_config>
<interface_config>
se.sics.cooja.interfaces.Battery
<infinite>false</infinite>
</interface_config>
<interface_config>
se.sics.cooja.contikimote.interfaces.ContikiMoteID
<id>1</id>
</interface_config>
<motetype_identifier>mtype725</motetype_identifier>
</mote>
</simulation>
<plugin>
se.sics.cooja.plugins.Visualizer
<plugin_config>
<skin>Mote IDs</skin>
<skin>Log output: printf()'s</skin>
<skin>se.sics.cooja.plugins.skins.IDVisualizerSkin</skin>
<skin>se.sics.cooja.plugins.skins.LogVisualizerSkin</skin>
<viewport>0.9090909090909091 0.0 0.0 0.9090909090909091 59.68302051791636 6.039078992634368</viewport>
</plugin_config>
<width>259</width>
<z>1</z>
<height>198</height>
<location_x>2</location_x>
<location_y>203</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.LogListener
@ -82,7 +75,6 @@
<height>217</height>
<location_x>2</location_x>
<location_y>403</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.SimControl
@ -91,23 +83,18 @@
<height>200</height>
<location_x>2</location_x>
<location_y>3</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.equals('Hello, world'));
log.testOK();</script>
<scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile>
<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>
<location_x>318</location_x>
<location_y>61</location_y>
</plugin>
</simconf>

View file

@ -1,11 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project>[CONTIKI_DIR]/tools/cooja/apps/mrm</project>
<project>[CONTIKI_DIR]/tools/cooja/apps/mspsim</project>
<project>[CONTIKI_DIR]/tools/cooja/apps/avrora</project>
<simulation>
<title>My simulation</title>
<delaytime>0</delaytime>
<title>Hello World (ESB)</title>
<randomseed>generated</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
@ -22,10 +18,9 @@
se.sics.cooja.mspmote.ESBMoteType
<identifier>esb1</identifier>
<description>ESB Mote Type #esb1</description>
<source>[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
<commands>make clean TARGET=esb
make hello-world.esb TARGET=esb</commands>
<firmware>[CONTIKI_DIR]/examples/hello-world/hello-world.esb</firmware>
<source EXPORT="discard">[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
<commands EXPORT="discard">make hello-world.esb TARGET=esb</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/hello-world/hello-world.esb</firmware>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
<moteinterface>se.sics.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface>
@ -36,9 +31,9 @@ make hello-world.esb TARGET=esb</commands>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.TR1001Radio</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>se.sics.cooja.interfaces.MoteAttributes</moteinterface>
</motetype>
<mote>
se.sics.cooja.mspmote.ESBMote
<breakpoints />
<interface_config>
se.sics.cooja.interfaces.Position
@ -53,65 +48,21 @@ make hello-world.esb TARGET=esb</commands>
<motetype_identifier>esb1</motetype_identifier>
</mote>
</simulation>
<plugin>
se.sics.cooja.plugins.SimControl
<width>259</width>
<z>6</z>
<height>184</height>
<location_x>60</location_x>
<location_y>60</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.Visualizer
<plugin_config>
<skin>se.sics.cooja.plugins.skins.IDVisualizerSkin</skin>
<skin>se.sics.cooja.plugins.skins.LogVisualizerSkin</skin>
<viewport>0.9090909090909091 0.0 0.0 0.9090909090909091 91.91230937183896 53.4476411035901</viewport>
</plugin_config>
<width>300</width>
<z>3</z>
<height>300</height>
<location_x>945</location_x>
<location_y>0</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.LogListener
<plugin_config>
<filter />
</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>
<width>623</width>
<z>1</z>
<height>150</height>
<location_x>0</location_x>
<location_y>680</location_y>
<minimized>false</minimized>
<height>270</height>
<location_x>29</location_x>
<location_y>256</location_y>
</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>
<scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile>
<active>true</active>
</plugin_config>
<width>600</width>
@ -119,7 +70,14 @@ log.testOK();</script>
<height>453</height>
<location_x>337</location_x>
<location_y>25</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.SimControl
<width>280</width>
<z>2</z>
<height>160</height>
<location_x>20</location_x>
<location_y>23</location_y>
</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,11 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project>../apps/mrm</project>
<project>../apps/mspsim</project>
<project>../apps/avrora</project>
<simulation>
<title>My simulation</title>
<delaytime>0</delaytime>
<title>Hello World (MicaZ)</title>
<randomseed>generated</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
@ -22,99 +18,62 @@
se.sics.cooja.avrmote.MicaZMoteType
<identifier>micaz1</identifier>
<description>MicaZ Mote Type #micaz1</description>
<source>../../../examples/hello-world/hello-world.c</source>
<commands>make clean TARGET=micaz
make hello-world.elf TARGET=micaz</commands>
<firmware>../../../examples/hello-world/hello-world.elf</firmware>
<source>[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
<commands>make hello-world.elf TARGET=micaz</commands>
<firmware>[CONTIKI_DIR]/examples/hello-world/hello-world.elf</firmware>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
<moteinterface>se.sics.cooja.avrmote.interfaces.MicaZID</moteinterface>
<moteinterface>se.sics.cooja.avrmote.interfaces.MicaZLED</moteinterface>
<moteinterface>se.sics.cooja.avrmote.interfaces.MicaZRadio</moteinterface>
<moteinterface>se.sics.cooja.avrmote.interfaces.MicaClock</moteinterface>
<moteinterface>se.sics.cooja.avrmote.interfaces.MicaSerial</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>se.sics.cooja.interfaces.MoteAttributes</moteinterface>
</motetype>
<mote>
se.sics.cooja.avrmote.MicaZMote
<motetype_identifier>micaz1</motetype_identifier>
<interface_config>
se.sics.cooja.interfaces.Position
<x>68.44103812985554</x>
<y>35.6791174319418</y>
<x>36.478849033811386</x>
<y>97.17795415366507</y>
<z>0.0</z>
</interface_config>
<interface_config>
se.sics.cooja.avrmote.interfaces.MicaZID
<id>1</id>
</interface_config>
<motetype_identifier>micaz1</motetype_identifier>
</mote>
</simulation>
<plugin>
se.sics.cooja.plugins.SimControl
<width>259</width>
<z>4</z>
<height>184</height>
<location_x>0</location_x>
<location_y>0</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.Visualizer
<plugin_config>
<skin>se.sics.cooja.plugins.skins.IDVisualizerSkin</skin>
<skin>se.sics.cooja.plugins.skins.LogVisualizerSkin</skin>
<viewport>0.9090909090909091 0.0 0.0 0.9090909090909091 81.78087442740406 87.56443869823474</viewport>
</plugin_config>
<width>300</width>
<z>1</z>
<height>300</height>
<location_x>456</location_x>
<location_y>0</location_y>
<minimized>false</minimized>
<width>280</width>
<z>2</z>
<height>160</height>
<location_x>17</location_x>
<location_y>16</location_y>
</plugin>
<plugin>
se.sics.cooja.plugins.LogListener
<plugin_config>
<filter />
</plugin_config>
<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>
<width>680</width>
<z>1</z>
<height>240</height>
<location_x>20</location_x>
<location_y>285</location_y>
</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>
<scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile>
<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>
<height>535</height>
<location_x>403</location_x>
<location_y>23</location_y>
</plugin>
</simconf>

View file

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

View file

@ -1,12 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project>../apps/mrm</project>
<project>../apps/mspsim</project>
<project>../apps/avrora</project>
<project>../apps/native_gateway</project>
<simulation>
<title>Hello World (Sky)</title>
<delaytime>0</delaytime>
<title>Hello World test (Sky)</title>
<randomseed>generated</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
@ -16,14 +11,16 @@
<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.SkyMoteType
<identifier>sky1</identifier>
<description>Sky Mote Type #1</description>
<source>../../../examples/hello-world/hello-world.c</source>
<commands>make clean TARGET=sky
make hello-world.sky TARGET=sky</commands>
<firmware>../../../examples/hello-world/hello-world.sky</firmware>
<source EXPORT="discard">[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
<commands EXPORT="discard">make hello-world.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/hello-world/hello-world.sky</firmware>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
<moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
@ -31,13 +28,11 @@ make hello-world.sky TARGET=sky</commands>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyByteRadio</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkySerial</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyLED</moteinterface>
</motetype>
<mote>
se.sics.cooja.mspmote.SkyMote
<motetype_identifier>sky1</motetype_identifier>
<breakpoints />
<interface_config>
se.sics.cooja.interfaces.Position
@ -49,32 +44,39 @@ make hello-world.sky TARGET=sky</commands>
se.sics.cooja.mspmote.interfaces.MspMoteID
<id>1</id>
</interface_config>
<motetype_identifier>sky1</motetype_identifier>
</mote>
</simulation>
<plugin>
se.sics.cooja.plugins.SimControl
<width>248</width>
<z>1</z>
<height>200</height>
<location_x>0</location_x>
<location_y>0</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.equals('Hello, world'));
log.testOK();</script>
<scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile>
<active>true</active>
</plugin_config>
<width>541</width>
<z>0</z>
<height>448</height>
<location_x>248</location_x>
<location_y>-1</location_y>
<minimized>false</minimized>
<location_x>299</location_x>
<location_y>7</location_y>
</plugin>
<plugin>
se.sics.cooja.plugins.SimControl
<width>280</width>
<z>2</z>
<height>160</height>
<location_x>7</location_x>
<location_y>10</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>51</location_x>
<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.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
@ -296,12 +297,12 @@ public class GUI extends Observable {
protected GUIEventHandler guiEventHandler = new GUIEventHandler();
private JMenu toolsMenu, menuMoteTypeClasses, menuMoteTypes;
private JMenu menuMoteTypeClasses, menuMoteTypes;
private JMenu menuOpenSimulation;
private boolean hasFileHistoryChanged;
private Vector<Class<? extends Plugin>> menuMotePluginClasses;
private Vector<Class<? extends Plugin>> menuMotePluginClasses = new Vector<Class<? extends Plugin>>();
private JDesktopPane myDesktopPane;
@ -369,17 +370,6 @@ public class GUI extends Observable {
myGUI = this;
mySimulation = null;
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 */
quickHelpTextPane = new JTextPane();
@ -703,7 +693,7 @@ public class GUI extends Observable {
JMenu fileMenu = new JMenu("File");
JMenu simulationMenu = new JMenu("Simulation");
JMenu motesMenu = new JMenu("Motes");
/* toolsMenu = new JMenu("Tools"); */
final JMenu toolsMenu = new JMenu("Tools");
JMenu settingsMenu = new JMenu("Settings");
JMenu helpMenu = new JMenu("Help");
@ -931,57 +921,119 @@ public class GUI extends Observable {
motesMenu.add(new JMenuItem(removeAllMotesAction));
// Tools menu
/* Tools menu */
toolsMenu.addMenuListener(new MenuListener() {
public void menuSelected(MenuEvent e) {
for (Component menuComponent: toolsMenu.getMenuComponents()) {
if (!(menuComponent instanceof JMenuItem)) {
continue;
}
JMenuItem menuItem = (JMenuItem) menuComponent;
Class<? extends Plugin> pluginClass = (Class<? extends Plugin>) menuItem.getClientProperty("class");
int pluginType;
if (pluginClass.isAnnotationPresent(PluginType.class)) {
pluginType = pluginClass.getAnnotation(PluginType.class).value();
} else {
pluginType = PluginType.UNDEFINED_PLUGIN;
private 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);
}
};
private JMenuItem createMenuItem(Class<? extends Plugin> newPluginClass, int pluginType) {
String description = getDescriptionOf(newPluginClass);
JMenuItem menuItem = new JMenuItem(description + "...");
menuItem.putClientProperty("class", newPluginClass);
menuItem.addActionListener(menuItemListener);
/* No simulation -> deactivate non-GUI plugins */
String tooltip = "<html><pre>";
if (pluginType == PluginType.COOJA_PLUGIN || pluginType == PluginType.COOJA_STANDARD_PLUGIN) {
menuItem.setEnabled(true);
continue;
}
/* 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;
}
tooltip += "Cooja plugin: ";
} else if (pluginType == PluginType.SIM_PLUGIN || pluginType == PluginType.SIM_STANDARD_PLUGIN) {
tooltip += "Simulation plugin: ";
if (getSimulation() == null) {
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 */
if (pluginClass.getAnnotation(SupportedArguments.class) != null) {
menuItem.setEnabled(false);
Class<? extends RadioMedium>[] radioMediums = pluginClass.getAnnotation(SupportedArguments.class).radioMediums();
if (pluginType == PluginType.SIM_PLUGIN || pluginType == PluginType.SIM_STANDARD_PLUGIN) {
if (newPluginClass.getAnnotation(SupportedArguments.class) != null) {
boolean active = false;
Class<? extends RadioMedium>[] radioMediums = newPluginClass.getAnnotation(SupportedArguments.class).radioMediums();
for (Class<? extends Object> o: radioMediums) {
if (o.isAssignableFrom(getSimulation().getRadioMedium().getClass())) {
menuItem.setEnabled(true);
active = true;
break;
}
}
} else {
menuItem.setEnabled(true);
if (!active) {
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 menuCanceled(MenuEvent e) {
@ -1051,10 +1103,6 @@ public class GUI extends Observable {
menuItem.setEnabled(false);
helpMenu.add(menuItem);
// Mote plugins popup menu (not available via menu bar)
if (menuMotePluginClasses == null) {
menuMotePluginClasses = new Vector<Class<? extends Plugin>>();
}
return menuBar;
}
@ -1504,9 +1552,9 @@ public class GUI extends Observable {
}
// Register plugins
registerPlugin(SimControl.class, false); // Not in menu
registerPlugin(SimInformation.class, false); // Not in menu
registerPlugin(MoteTypeInformation.class, false); // Not in menu
registerPlugin(SimControl.class);
registerPlugin(SimInformation.class);
registerPlugin(MoteTypeInformation.class);
String[] pluginClassNames = projectConfig.getStringArrayValue(GUI.class,
"PLUGINS");
if (pluginClassNames != null) {
@ -1816,155 +1864,54 @@ public class GUI extends Observable {
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.
*
* @param pluginClass Plugin class
*/
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);
menuMotePluginClasses.remove(pluginClass);
}
/**
* Register a plugin to be included in the GUI.
*
* @param newPluginClass
* New plugin to register
* @param addToMenu
* Should this plugin be added to the dedicated plugins menubar?
* @param pluginClass New plugin to register
* @return True if this plugin was registered ok, false otherwise
*/
private boolean registerPlugin(final Class<? extends Plugin> newPluginClass,
boolean addToMenu) {
public boolean registerPlugin(final Class<? extends Plugin> pluginClass) {
// Get description annotation (if any)
final String description = getDescriptionOf(newPluginClass);
// Get plugin type annotation (required)
/* Check plugin type */
final int pluginType;
if (newPluginClass.isAnnotationPresent(PluginType.class)) {
pluginType = newPluginClass.getAnnotation(PluginType.class).value();
if (pluginClass.isAnnotationPresent(PluginType.class)) {
pluginType = pluginClass.getAnnotation(PluginType.class).value();
} else {
pluginType = PluginType.UNDEFINED_PLUGIN;
}
// Check that plugin type is valid and constructor exists
try {
if (pluginType == PluginType.MOTE_PLUGIN) {
newPluginClass.getConstructor(new Class[] { Mote.class,
Simulation.class, GUI.class });
} else if (pluginType == PluginType.SIM_PLUGIN
|| pluginType == PluginType.SIM_STANDARD_PLUGIN) {
newPluginClass.getConstructor(new Class[] { Simulation.class, GUI.class });
} else if (pluginType == PluginType.COOJA_PLUGIN
|| pluginType == PluginType.COOJA_STANDARD_PLUGIN) {
newPluginClass.getConstructor(new Class[] { GUI.class });
} else {
logger.fatal("Could not find valid plugin type annotation in class " + newPluginClass);
logger.fatal("Could not register plugin, no plugin type found: " + pluginClass);
return false;
}
/* Check plugin constructor */
try {
if (pluginType == PluginType.COOJA_PLUGIN || pluginType == PluginType.COOJA_STANDARD_PLUGIN) {
pluginClass.getConstructor(new Class[] { GUI.class });
} else if (pluginType == PluginType.SIM_PLUGIN || pluginType == PluginType.SIM_STANDARD_PLUGIN) {
pluginClass.getConstructor(new Class[] { Simulation.class, GUI.class });
} else if (pluginType == PluginType.MOTE_PLUGIN) {
pluginClass.getConstructor(new Class[] { Mote.class, Simulation.class, GUI.class });
menuMotePluginClasses.add(pluginClass);
} else {
logger.fatal("Could not register plugin, bad plugin type: " + pluginType);
return false;
}
pluginClasses.add(pluginClass);
} catch (NoClassDefFoundError e) {
logger.fatal("No plugin class: " + newPluginClass + ": " + e.getMessage());
logger.fatal("No plugin class: " + pluginClass + ": " + e.getMessage());
return false;
} catch (NoSuchMethodException e) {
logger.fatal("No plugin class constructor: " + newPluginClass + ": " + e.getMessage());
logger.fatal("No plugin class constructor: " + pluginClass + ": " + e.getMessage());
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;
}
@ -1972,16 +1919,7 @@ public class GUI extends Observable {
* Unregister all plugin classes
*/
public void unregisterPlugins() {
if (toolsMenu != null) {
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();
}
@ -2016,6 +1954,107 @@ public class GUI extends Observable {
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.
*
@ -2026,38 +2065,15 @@ public class GUI extends Observable {
JMenu menuMotePlugins = new JMenu("Mote tools for " + mote);
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);
menuItem.putClientProperty("class", motePluginClass);
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);
}
return menuMotePlugins;
@ -2607,6 +2623,7 @@ public class GUI extends Observable {
mySimulation.addMote(newMote);
}
}
updateGUIComponentState();
} else {
logger.warn("No simulation active");
@ -4521,6 +4538,7 @@ public class GUI extends Observable {
return getSimulation() != null;
}
}
GUIAction removeAllMotesAction = new GUIAction("Remove all motes") {
private static final long serialVersionUID = 4709776747913364419L;
public void actionPerformed(ActionEvent e) {

View file

@ -61,4 +61,9 @@ public @interface SupportedArguments {
* @return List of accepted radio medium classes.
*/
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
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ContikiClock.java,v 1.13 2010/02/05 08:49:18 fros4943 Exp $
*/
package se.sics.cooja.contikimote.interfaces;
import java.util.Collection;
import javax.swing.JPanel;
import org.apache.log4j.Logger;
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.ContikiMoteInterface;
import se.sics.cooja.interfaces.Clock;
@ -137,12 +138,12 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
/* Request tick next wakeup time */
int nextExpirationTime = moteMem.getIntValueOf("simNextExpirationTime");
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);
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
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ScriptRunner.java,v 1.28 2010/08/17 15:03:52 fros4943 Exp $
*/
package se.sics.cooja.plugins;
@ -71,6 +69,8 @@ import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.filechooser.FileFilter;
import jsyntaxpane.DefaultSyntaxKit;
@ -110,15 +110,13 @@ public class ScriptRunner extends VisPlugin {
};
private Simulation simulation;
private LogScriptEngine engine = null;
private LogScriptEngine engine;
private static BufferedWriter logWriter = null; /* For non-GUI tests */
private JEditorPane codeEditor = null;
private JTextArea logTextArea = null;
/*private JButton toggleButton = null;*/
private JEditorPane codeEditor;
private JTextArea logTextArea;
private JSplitPane centerPanel;
private JSyntaxLinkFile actionLinkFile = null;
private File linkedFile = null;
@ -126,6 +124,7 @@ public class ScriptRunner extends VisPlugin {
public ScriptRunner(Simulation simulation, GUI gui) {
super("Simulation script editor", gui, false);
this.simulation = simulation;
this.engine = null;
/* Menus */
JMenuBar menuBar = new JMenuBar();
@ -139,9 +138,8 @@ public class ScriptRunner extends VisPlugin {
this.setJMenuBar(menuBar);
/* Examples popup menu */
JMenu examplesMenu = new JMenu("Load example script");
/* Example scripts */
final JMenu examplesMenu = new JMenu("Load example script");
for (int i=0; i < EXAMPLE_SCRIPTS.length; i += 2) {
final String file = EXAMPLE_SCRIPTS[i];
JMenuItem exampleItem = new JMenuItem(EXAMPLE_SCRIPTS[i+1]);
@ -159,11 +157,10 @@ public class ScriptRunner extends VisPlugin {
});
examplesMenu.add(exampleItem);
}
fileMenu.add(examplesMenu);
{
/* Workaround to configure jsyntaxpane */
/* XXX Workaround to configure jsyntaxpane */
JEditorPane e = new JEditorPane();
new JScrollPane(e);
e.setContentType("text/javascript");
@ -171,6 +168,7 @@ public class ScriptRunner extends VisPlugin {
DefaultSyntaxKit kit = (DefaultSyntaxKit) e.getEditorKit();
kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,linkfile");
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.setCursor(null);
/*toggleButton = new JButton("Activate");*/
JCheckBoxMenuItem activateMenuItem = new JCheckBoxMenuItem("Activate");
final JCheckBoxMenuItem activateMenuItem = new JCheckBoxMenuItem("Activate");
activateMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
try {
if (!isActive()) {
setScriptActive(true);
} else {
setScriptActive(false);
}
setScriptActive(!isActive());
} catch (Exception e) {
logger.fatal("Error: " + e.getMessage(), e);
}
@ -200,8 +193,7 @@ public class ScriptRunner extends VisPlugin {
});
runMenu.add(activateMenuItem);
/*JButton runTestButton = new JButton("Run without GUI");*/
JMenuItem runTestMenuItem = new JMenuItem("Save simulation and run with script");
final JMenuItem runTestMenuItem = new JMenuItem("Save simulation and run with script");
runMenu.add(runTestMenuItem);
runTestMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
@ -210,41 +202,58 @@ public class ScriptRunner extends VisPlugin {
});
doLayout();
JSplitPane centerPanel = new JSplitPane(
centerPanel = new JSplitPane(
JSplitPane.VERTICAL_SPLIT,
new JScrollPane(codeEditor),
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");
if (codeEditor.getEditorKit() instanceof DefaultSyntaxKit) {
DefaultSyntaxKit kit = (DefaultSyntaxKit) codeEditor.getEditorKit();
kit.setProperty("PopupMenu", "copy-to-clipboard,-,find,find-next,goto-line,-,linkfile");
kit.setProperty("Action.linkfile", JSyntaxLinkFile.class.getName());
kit.setProperty("Action.execute-script", "jsyntaxpane.actions.ScriptRunnerAction");
}
JPopupMenu p = codeEditor.getComponentPopupMenu();
if (p != null) {
for (Component c: p.getComponents()) {
if (c instanceof JMenuItem) {
if (((JMenuItem) c).getAction() != null &&
((JMenuItem) c).getAction() instanceof JSyntaxLinkFile) {
actionLinkFile = (JSyntaxLinkFile)(((JMenuItem) c).getAction());
if (!(c instanceof JMenuItem)) {
continue;
}
if (((JMenuItem) c).getAction() == null) {
continue;
}
Action a = ((JMenuItem) c).getAction();
if (a instanceof JSyntaxLinkFile) {
actionLinkFile = (JSyntaxLinkFile) a;
actionLinkFile.setMenuText("Link script to disk file");
actionLinkFile.putValue("ScriptRunner", this);
}
}
}
}
centerPanel.setOneTouchExpandable(true);
centerPanel.setResizeWeight(0.5);
JPanel buttonPanel = new JPanel(new BorderLayout());
/*buttonPanel.add(BorderLayout.CENTER, toggleButton);*/
/* buttonPanel.add(BorderLayout.EAST, runTestButton);*/
JPanel southPanel = new JPanel(new BorderLayout());
southPanel.add(BorderLayout.EAST, buttonPanel);
@ -280,6 +289,7 @@ public class ScriptRunner extends VisPlugin {
codeEditor.setEditable(true);
} else {
updateScript(linkedFile);
GUI.setExternalToolsSetting("SCRIPTRUNNER_LAST_SCRIPTFILE", source.getAbsolutePath());
if (actionLinkFile != null) {
actionLinkFile.setMenuText("Unlink script: " + source.getName());
@ -357,9 +367,9 @@ public class ScriptRunner extends VisPlugin {
engine.activateScript(codeEditor.getText());
if (!headless) {
if (actionLinkFile != null) {
actionLinkFile.setEnabled(false);
/* toggleButton.setText("Deactivate");*/
/*examplesButton.setEnabled(false);*/
}
logTextArea.setText("");
codeEditor.setEnabled(false);
updateTitle();
@ -402,9 +412,9 @@ public class ScriptRunner extends VisPlugin {
}
if (!headless) {
if (actionLinkFile != null) {
actionLinkFile.setEnabled(true);
/*toggleButton.setText("Activate")*/;
/*examplesButton.setEnabled(linkedFile==null?true:false);*/
}
codeEditor.setEnabled(true);
updateTitle();
}
@ -413,14 +423,14 @@ public class ScriptRunner extends VisPlugin {
}
private void updateTitle() {
/*String title = "Contiki Test Editor ";
String title = "Simulation script editor ";
if (linkedFile != null) {
title += ": " + linkedFile.getName() + " ";
title += "(" + linkedFile.getName() + ") ";
}
if (isActive()) {
title += "(ACTIVE) ";
title += "*active*";
}
setTitle(title);*/
setTitle(title);
}
private void exportAndRun() {
@ -609,7 +619,6 @@ public class ScriptRunner extends VisPlugin {
element = new Element("scriptfile");
element.setText(simulation.getGUI().createPortablePath(linkedFile).getPath().replace('\\', '/'));
config.add(element);
/*StringUtils.saveToFile(scriptFile, scriptTextArea.getText());*/
} else {
element = new Element("script");
element.setText(codeEditor.getText());
@ -692,7 +701,12 @@ public class ScriptRunner extends VisPlugin {
}
JFileChooser fileChooser = new JFileChooser();
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.setDialogTitle("Select script file");
fileChooser.setFileFilter(new FileFilter() {

View file

@ -37,7 +37,6 @@ import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.RenderingHints;
@ -54,6 +53,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
@ -68,7 +68,7 @@ import java.util.Observable;
import java.util.Observer;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.Action;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
@ -77,9 +77,12 @@ import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.KeyStroke;
import javax.swing.MenuElement;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.plaf.basic.BasicInternalFrameUI;
import org.apache.log4j.Logger;
@ -87,16 +90,16 @@ import org.jdom.Element;
import se.sics.cooja.ClassDescription;
import se.sics.cooja.GUI;
import se.sics.cooja.GUI.MoteRelation;
import se.sics.cooja.HasQuickHelp;
import se.sics.cooja.Mote;
import se.sics.cooja.MoteInterface;
import se.sics.cooja.PluginType;
import se.sics.cooja.RadioMedium;
import se.sics.cooja.SimEventCentral.MoteCountListener;
import se.sics.cooja.Simulation;
import se.sics.cooja.SupportedArguments;
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.Position;
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);
/* Visualizers */
private final JButton skinButton = new JButton("Select visualizer skins");
private static ArrayList<Class<? extends VisualizerSkin>> visualizerSkins =
new ArrayList<Class<? extends VisualizerSkin>>();
static {
@ -224,6 +226,16 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
JMenuBar menuBar = new JMenuBar();
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");
menuBar.add(viewMenu);
@ -231,20 +243,28 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
this.setJMenuBar(menuBar);
JMenuItem zoomInItem = new JMenuItem("Zoom in");
zoomInItem.addActionListener(new ActionListener() {
Action zoomInAction = new AbstractAction("Zoom in") {
public void actionPerformed(ActionEvent e) {
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);
JMenuItem zoomOutItem = new JMenuItem("Zoom out");
zoomOutItem.addActionListener(new ActionListener() {
Action zoomOutAction = new AbstractAction("Zoom out") {
public void actionPerformed(ActionEvent e) {
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);
JMenuItem resetViewportItem = new JMenuItem("Reset viewport");
@ -280,20 +300,6 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
canvas.setBackground(Color.WHITE);
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);
/* Observe simulation and mote positions */
@ -550,9 +556,6 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
} catch (IllegalAccessException e1) {
e1.printStackTrace();
}
skinButton.setText("Select visualizer " +
"(" + currentSkins.size() + "/" + visualizerSkins.size() + ")");
repaint();
}
@ -572,7 +575,6 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
simulation.getGUI().tryLoadClass(this, VisualizerSkin.class, skin);
generateAndActivateSkin(skinClass);
}
populateSkinMenu(viewMenu);
}
public VisualizerSkin[] getCurrentSkins() {
@ -698,11 +700,15 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
menu.setVisible(true);
}
private void populateSkinMenu(MenuElement skinMenu) {
JCheckBoxMenuItem item;
private void populateSkinMenu(MenuElement menu) {
for (Class<? extends VisualizerSkin> skinClass: visualizerSkins) {
/* Should skin be enabled in this simulation? */
if (!isSkinCompatible(skinClass)) {
continue;
}
String description = GUI.getDescriptionOf(skinClass);
item = new JCheckBoxMenuItem(description, false);
JCheckBoxMenuItem item = new JCheckBoxMenuItem(description, false);
item.putClientProperty("skinclass", skinClass);
/* Select skin if active */
@ -747,23 +753,15 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
skinToDeactivate.setInactive();
repaint();
currentSkins.remove(skinToDeactivate);
skinButton.setText("Select visualizers " +
"(" + currentSkins.size() + "/" + visualizerSkins.size() + ")");
}
}
});
/* Should skin be enabled in this simulation? */
if (!isSkinCompatible(skinClass)) {
continue;
if (menu instanceof JMenu) {
((JMenu)menu).add(item);
}
if (skinMenu instanceof JMenu) {
((JMenu)skinMenu).add(item);
}
if (skinMenu instanceof JPopupMenu) {
((JPopupMenu)skinMenu).add(item);
if (menu instanceof JPopupMenu) {
((JPopupMenu)menu).add(item);
}
}
}
@ -833,24 +831,26 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
repaint();
}
private double zoomFactor()
{
private double zoomFactor() {
return viewportTransform.getScaleX();
}
private void zoomToFactor(double newZoom) {
Position center = transformPixelToPosition(
new Point(canvas.getWidth()/2, canvas.getHeight()/2)
);
viewportTransform.setToScale(
newZoom,
newZoom
);
/*Position moved = transformPixelToPosition(zoomingPixel);
Position newCenter = transformPixelToPosition(
new Point(canvas.getWidth()/2, canvas.getHeight()/2)
);
viewportTransform.translate(
moved.getXCoordinate() - zoomingPosition.getXCoordinate(),
moved.getYCoordinate() - zoomingPosition.getYCoordinate()
);*/
newCenter.getXCoordinate() - center.getXCoordinate(),
newCenter.getYCoordinate() - center.getYCoordinate()
);
repaint();
}
private void handleMouseMove(MouseEvent e, boolean stop) {
@ -1335,7 +1335,6 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
} else if (element.getName().equals("hidden")) {
BasicInternalFrameUI ui = (BasicInternalFrameUI) getUI();
ui.getNorthPane().setPreferredSize(new Dimension(0,0));
skinButton.setVisible(false);
}
}
return true;
@ -1489,11 +1488,9 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
ui.getNorthPane().getPreferredSize().height == 0) {
/* Restore window decorations */
ui.getNorthPane().setPreferredSize(null);
visualizer.skinButton.setVisible(true);
} else {
/* Hide window decorations */
ui.getNorthPane().setPreferredSize(new Dimension(0,0));
visualizer.skinButton.setVisible(false);
}
visualizer.revalidate();
SwingUtilities.invokeLater(new Runnable() {
@ -1525,10 +1522,10 @@ public class Visualizer extends VisPlugin implements HasQuickHelp {
public String getQuickHelp() {
return
"<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. " +
"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. " +
"Multiple views can be active at the same time. " +
"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.
*
* 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
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: TrafficVisualizerSkin.java,v 1.5 2010/02/26 07:46:26 nifi Exp $
*/
package se.sics.cooja.plugins.skins;
@ -34,235 +32,171 @@ package se.sics.cooja.plugins.skins;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayDeque;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import javax.swing.Box;
import javax.swing.JLabel;
import org.apache.log4j.Logger;
import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote;
import se.sics.cooja.RadioConnection;
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.Radio;
import se.sics.cooja.plugins.Visualizer;
import se.sics.cooja.plugins.VisualizerSkin;
import se.sics.cooja.plugins.Visualizer.SimulationMenuAction;
import se.sics.cooja.radiomediums.AbstractRadioMedium;
/**
* Radio traffic 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.
* Radio traffic history visualizer skin.
*
* @see UDGMVisualizerSkin
* @author Fredrik Osterlind
*/
@ClassDescription("Radio traffic")
@SupportedArguments(radioMediums = {AbstractRadioMedium.class})
public class TrafficVisualizerSkin implements VisualizerSkin {
private static Logger logger = Logger.getLogger(TrafficVisualizerSkin.class);
private static final boolean DRAW_ARROWS = true;
private static final Color COLOR_HISTORY = new Color(100, 100, 100, 100);
private final int MAX_HISTORY_SIZE = 200;
private boolean active = false;
private Simulation simulation = 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 boolean showHistory = false;
private ArrayDeque<RadioConnection> history = new ArrayDeque<RadioConnection>();
private AbstractRadioMedium radioMedium;
private Observer radioObserver, radioMediumObserver;
public void setActive(Simulation simulation, Visualizer vis) {
if (!(simulation.getRadioMedium() instanceof AbstractRadioMedium)) {
logger.fatal("Radio medium type not supported: " + simulation.getRadioMedium());
private Observer radioMediumObserver = new Observer() {
public void update(Observable obs, Object obj) {
RadioConnection last = radioMedium.getLastConnection();
if (last != null && historyList.size() < MAX_HISTORY_SIZE) {
historyList.add(new RadioConnectionArrow(last));
history = historyList.toArray(new RadioConnectionArrow[0]);
visualizer.repaint(500);
}
}
};
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.simulation = simulation;
this.visualizer = vis;
this.active = true;
final JLabel txCounter = new JLabel("TX: " + radioMedium.COUNTER_TX);
final JLabel rxCounter = new JLabel("RX: " + radioMedium.COUNTER_RX);
final JLabel interferedCounter = new JLabel("INT: " + radioMedium.COUNTER_INTERFERED);
simulation.invokeSimulationThread(new Runnable() {
public void run() {
historyList.clear();
history = null;
counters = Box.createHorizontalBox();
counters.add(txCounter);
counters.add(Box.createHorizontalStrut(10));
counters.add(rxCounter);
counters.add(Box.createHorizontalStrut(10));
counters.add(interferedCounter);
/* Start observing radio medium for transmissions */
radioMedium.addRadioMediumObserver(radioMediumObserver);
/* visualizer.getCurrentCanvas().add(counters);*/
/* 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();
/* Fade away arrows */
simulation.scheduleEvent(ageArrowsTimeEvent, simulation.getSimulationTime() + 100*Simulation.MILLISECOND);
}
});
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() {
this.active = false;
if (simulation == null) {
/* Skin was never activated */
return;
}
visualizer.getCurrentCanvas().remove(counters);
/* Stop observing radio medium and radios */
/* Stop observing radio medium */
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) {
if (simulation == null) {
/* Skin was never activated */
return null;
}
Radio moteRadio = mote.getInterfaces().getRadio();
if (moteRadio == 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);
}
if (!moteRadio.isRadioOn()) {
return new Color[] { Color.GRAY };
private int yCor(int len, double dir) {
return (int)(0.5 + len * Math.cos(dir));
}
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;
private int xCor(int len, double dir) {
return (int)(0.5 + len * Math.sin(dir));
}
public void paintBeforeMotes(Graphics g) {
if (simulation == null) {
/* Skin was never activated */
RadioConnectionArrow[] historyCopy = history;
if (historyCopy == null) {
return;
}
if (showHistory) {
/* Paint history in gray */
RadioConnection[] historyArr = history.toArray(new RadioConnection[0]);
for (RadioConnection conn : historyArr) {
if (conn == null) {
continue;
}
g.setColor(COLOR_HISTORY);
Radio source = conn.getSource();
for (RadioConnectionArrow connArrow : historyCopy) {
float colorHistoryIndex = (float)connArrow.getAge() / (float)connArrow.getMaxAge();
g.setColor(new Color(colorHistoryIndex, colorHistoryIndex, 1.0f));
Radio source = connArrow.getConnection().getSource();
Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition());
for (Radio destRadio : conn.getDestinations()) {
for (Radio destRadio : connArrow.getConnection().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);
}
}
drawArrow(g, sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y, 8);
}
}
}
@ -270,37 +204,31 @@ public class TrafficVisualizerSkin implements VisualizerSkin {
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() {
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;
}
}
}