From 9f42e1e261160b819239c7bb768157d5e3aafb79 Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Mon, 4 Jun 2012 17:37:29 +0200 Subject: [PATCH 01/19] bugfix: use new setSpeedLimit(ratio) method in simulation instead of old setDelayTime() --- tools/cooja/contiki_tests/rest_rpl_coap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/cooja/contiki_tests/rest_rpl_coap.js b/tools/cooja/contiki_tests/rest_rpl_coap.js index c98dfb2aa..93773f21a 100644 --- a/tools/cooja/contiki_tests/rest_rpl_coap.js +++ b/tools/cooja/contiki_tests/rest_rpl_coap.js @@ -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"); From fd2e238d995e206222c6ba1852aa1ac9b4783765 Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Mon, 4 Jun 2012 17:41:12 +0200 Subject: [PATCH 02/19] The __delay_cycles() function in the latest mspgcc takes an unsigned long argument but does not allow it to be larger than 65536. --- platform/exp5438/clock.c | 2 +- platform/exp5438/hal_lcd.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/platform/exp5438/clock.c b/platform/exp5438/clock.c index f701af9b7..4d0896ba9 100644 --- a/platform/exp5438/clock.c +++ b/platform/exp5438/clock.c @@ -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"); diff --git a/platform/exp5438/hal_lcd.c b/platform/exp5438/hal_lcd.c index e2475010f..fdaf32203 100644 --- a/platform/exp5438/hal_lcd.c +++ b/platform/exp5438/hal_lcd.c @@ -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; From ad8941bc5df5958abdabd2167569a81fd32bc8c5 Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Mon, 4 Jun 2012 17:45:43 +0200 Subject: [PATCH 03/19] added hello world simulation tests for exp5438, z1, and wismote. extracted test script to a separate hello-world.js, and updated the remaining hello world tests accordingly. --- .../cooja/contiki_tests/cooja_helloworld.csc | 213 ++++++++---------- tools/cooja/contiki_tests/esb_helloworld.csc | 208 +++++++---------- .../contiki_tests/exp5438_helloworld.csc | 83 +++++++ tools/cooja/contiki_tests/hello-world.js | 9 + .../cooja/contiki_tests/micaz_helloworld.csc | 199 +++++++--------- tools/cooja/contiki_tests/sky_helloworld.csc | 162 ++++++------- .../contiki_tests/wismote_helloworld.csc | 84 +++++++ tools/cooja/contiki_tests/z1_helloworld.csc | 83 +++++++ 8 files changed, 603 insertions(+), 438 deletions(-) create mode 100644 tools/cooja/contiki_tests/exp5438_helloworld.csc create mode 100644 tools/cooja/contiki_tests/hello-world.js create mode 100644 tools/cooja/contiki_tests/wismote_helloworld.csc create mode 100644 tools/cooja/contiki_tests/z1_helloworld.csc diff --git a/tools/cooja/contiki_tests/cooja_helloworld.csc b/tools/cooja/contiki_tests/cooja_helloworld.csc index 8d7f6fa5a..ce8961801 100644 --- a/tools/cooja/contiki_tests/cooja_helloworld.csc +++ b/tools/cooja/contiki_tests/cooja_helloworld.csc @@ -1,113 +1,100 @@ - - - ../apps/mrm - ../apps/mspsim - ../apps/avrora - ../apps/native_gateway - - My simulation - 0 - generated - 1000000 - - se.sics.cooja.radiomediums.UDGM - 50.0 - 100.0 - 1.0 - 1.0 - - - se.sics.cooja.contikimote.ContikiMoteType - mtype82 - Contiki Mote Type #1 - ../../../examples/hello-world/hello-world.c - make hello-world.cooja TARGET=cooja - se.sics.cooja.interfaces.Position - se.sics.cooja.interfaces.Battery - se.sics.cooja.contikimote.interfaces.ContikiVib - se.sics.cooja.contikimote.interfaces.ContikiMoteID - se.sics.cooja.contikimote.interfaces.ContikiRS232 - se.sics.cooja.contikimote.interfaces.ContikiBeeper - se.sics.cooja.contikimote.interfaces.ContikiIPAddress - se.sics.cooja.contikimote.interfaces.ContikiRadio - se.sics.cooja.contikimote.interfaces.ContikiButton - se.sics.cooja.contikimote.interfaces.ContikiPIR - se.sics.cooja.contikimote.interfaces.ContikiClock - se.sics.cooja.contikimote.interfaces.ContikiLED - se.sics.cooja.contikimote.interfaces.ContikiCFS - se.sics.cooja.interfaces.Mote2MoteRelations - se.sics.cooja.interfaces.RimeAddress - false - Rime - - - se.sics.cooja.contikimote.ContikiMote - mtype82 - - se.sics.cooja.interfaces.Position - 69.64867743029201 - 69.2570131081022 - 0.0 - - - se.sics.cooja.interfaces.Battery - false - - - se.sics.cooja.contikimote.interfaces.ContikiMoteID - 1 - - - - - se.sics.cooja.plugins.Visualizer - - Mote IDs - Log output: printf()'s - - 259 - 1 - 198 - 2 - 203 - false - - - se.sics.cooja.plugins.LogListener - - - - 259 - 2 - 217 - 2 - 403 - false - - - se.sics.cooja.plugins.SimControl - 259 - 3 - 200 - 2 - 3 - false - - - se.sics.cooja.plugins.ScriptRunner - - - true - - 592 - 0 - 618 - 264 - 3 - false - - - + + + + Hello World test (Cooja motes) + generated + 1000000 + + se.sics.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.contikimote.ContikiMoteType + mtype725 + Contiki Mote Type #1 + [CONTIKI_DIR]/examples/hello-world/hello-world.c + make hello-world.cooja TARGET=cooja + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.Battery + se.sics.cooja.contikimote.interfaces.ContikiVib + se.sics.cooja.contikimote.interfaces.ContikiMoteID + se.sics.cooja.contikimote.interfaces.ContikiRS232 + se.sics.cooja.contikimote.interfaces.ContikiBeeper + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.contikimote.interfaces.ContikiIPAddress + se.sics.cooja.contikimote.interfaces.ContikiRadio + se.sics.cooja.contikimote.interfaces.ContikiButton + se.sics.cooja.contikimote.interfaces.ContikiPIR + se.sics.cooja.contikimote.interfaces.ContikiClock + se.sics.cooja.contikimote.interfaces.ContikiLED + se.sics.cooja.contikimote.interfaces.ContikiCFS + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + false + + + + se.sics.cooja.interfaces.Position + 69.64867743029201 + 69.2570131081022 + 0.0 + + + se.sics.cooja.contikimote.interfaces.ContikiMoteID + 1 + + mtype725 + + + + se.sics.cooja.plugins.Visualizer + + se.sics.cooja.plugins.skins.IDVisualizerSkin + se.sics.cooja.plugins.skins.LogVisualizerSkin + 0.9090909090909091 0.0 0.0 0.9090909090909091 59.68302051791636 6.039078992634368 + + 259 + 1 + 198 + 2 + 203 + + + se.sics.cooja.plugins.LogListener + + + + 259 + 2 + 217 + 2 + 403 + + + se.sics.cooja.plugins.SimControl + 259 + 3 + 200 + 2 + 3 + + + se.sics.cooja.plugins.ScriptRunner + + [CONFIG_DIR]/hello-world.js + true + + 592 + 0 + 618 + 318 + 61 + + + diff --git a/tools/cooja/contiki_tests/esb_helloworld.csc b/tools/cooja/contiki_tests/esb_helloworld.csc index 8fa3806fe..0124455fc 100644 --- a/tools/cooja/contiki_tests/esb_helloworld.csc +++ b/tools/cooja/contiki_tests/esb_helloworld.csc @@ -1,125 +1,83 @@ - - - [CONTIKI_DIR]/tools/cooja/apps/mrm - [CONTIKI_DIR]/tools/cooja/apps/mspsim - [CONTIKI_DIR]/tools/cooja/apps/avrora - - My simulation - 0 - generated - 1000000 - - se.sics.cooja.radiomediums.UDGM - 50.0 - 100.0 - 1.0 - 1.0 - - - 40000 - - - se.sics.cooja.mspmote.ESBMoteType - esb1 - ESB Mote Type #esb1 - [CONTIKI_DIR]/examples/hello-world/hello-world.c - make clean TARGET=esb -make hello-world.esb TARGET=esb - [CONTIKI_DIR]/examples/hello-world/hello-world.esb - se.sics.cooja.interfaces.Position - se.sics.cooja.interfaces.RimeAddress - se.sics.cooja.interfaces.IPAddress - se.sics.cooja.mspmote.interfaces.MspSerial - se.sics.cooja.mspmote.interfaces.MspClock - se.sics.cooja.mspmote.interfaces.ESBLED - se.sics.cooja.mspmote.interfaces.ESBButton - se.sics.cooja.mspmote.interfaces.MspMoteID - se.sics.cooja.mspmote.interfaces.TR1001Radio - se.sics.cooja.interfaces.Mote2MoteRelations - - - se.sics.cooja.mspmote.ESBMote - - - se.sics.cooja.interfaces.Position - 57.296459690977144 - 73.20759478605089 - 0.0 - - - se.sics.cooja.mspmote.interfaces.MspMoteID - 1 - - esb1 - - - - se.sics.cooja.plugins.SimControl - 259 - 6 - 184 - 60 - 60 - false - - - se.sics.cooja.plugins.Visualizer - - se.sics.cooja.plugins.skins.IDVisualizerSkin - se.sics.cooja.plugins.skins.LogVisualizerSkin - 0.9090909090909091 0.0 0.0 0.9090909090909091 91.91230937183896 53.4476411035901 - - 300 - 3 - 300 - 945 - 0 - false - - - se.sics.cooja.plugins.LogListener - - - - 1245 - 5 - 150 - 0 - 530 - false - - - se.sics.cooja.plugins.TimeLine - - 0 - - - - 109 - 9 - - 1245 - 1 - 150 - 0 - 680 - false - - - se.sics.cooja.plugins.ScriptRunner - - - true - - 600 - 0 - 453 - 337 - 25 - false - - - + + + + Hello World (ESB) + generated + 1000000 + + se.sics.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.mspmote.ESBMoteType + esb1 + ESB Mote Type #esb1 + [CONTIKI_DIR]/examples/hello-world/hello-world.c + make hello-world.esb TARGET=esb + [CONTIKI_DIR]/examples/hello-world/hello-world.esb + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.interfaces.IPAddress + se.sics.cooja.mspmote.interfaces.MspSerial + se.sics.cooja.mspmote.interfaces.MspClock + se.sics.cooja.mspmote.interfaces.ESBLED + se.sics.cooja.mspmote.interfaces.ESBButton + se.sics.cooja.mspmote.interfaces.MspMoteID + se.sics.cooja.mspmote.interfaces.TR1001Radio + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + + + + + se.sics.cooja.interfaces.Position + 57.296459690977144 + 73.20759478605089 + 0.0 + + + se.sics.cooja.mspmote.interfaces.MspMoteID + 1 + + esb1 + + + + se.sics.cooja.plugins.LogListener + + + + 623 + 1 + 270 + 29 + 256 + + + se.sics.cooja.plugins.ScriptRunner + + [CONFIG_DIR]/hello-world.js + true + + 600 + 0 + 453 + 337 + 25 + + + se.sics.cooja.plugins.SimControl + 280 + 2 + 160 + 20 + 23 + + + diff --git a/tools/cooja/contiki_tests/exp5438_helloworld.csc b/tools/cooja/contiki_tests/exp5438_helloworld.csc new file mode 100644 index 000000000..e2672c7a5 --- /dev/null +++ b/tools/cooja/contiki_tests/exp5438_helloworld.csc @@ -0,0 +1,83 @@ + + + + Hello World (Exp5438) + generated + 1000000 + + se.sics.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.mspmote.Exp5438MoteType + exp5438#1 + Exp5438 Mote Type exp5438#1 + [CONTIKI_DIR]/examples/hello-world/hello-world.c + make hello-world.exp5438 TARGET=exp5438 + [CONTIKI_DIR]/examples/hello-world/hello-world.exp5438 + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.interfaces.IPAddress + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + se.sics.cooja.mspmote.interfaces.MspClock + se.sics.cooja.mspmote.interfaces.MspMoteID + se.sics.cooja.mspmote.interfaces.Msp802154Radio + se.sics.cooja.mspmote.interfaces.UsciA1Serial + se.sics.cooja.mspmote.interfaces.Exp5438LED + se.sics.cooja.mspmote.interfaces.MspDebugOutput + + + + + se.sics.cooja.interfaces.Position + 26.321738050614275 + 34.93092009073432 + 0.0 + + + se.sics.cooja.mspmote.interfaces.MspMoteID + 1 + + exp5438#1 + + + + se.sics.cooja.plugins.SimControl + 280 + 2 + 160 + 38 + 49 + + + se.sics.cooja.plugins.LogListener + + + + 680 + 1 + 240 + 86 + 384 + + + se.sics.cooja.plugins.ScriptRunner + + [CONFIG_DIR]/hello-world.js + true + + 600 + 0 + 700 + 347 + 21 + + + diff --git a/tools/cooja/contiki_tests/hello-world.js b/tools/cooja/contiki_tests/hello-world.js new file mode 100644 index 000000000..5afaabe18 --- /dev/null +++ b/tools/cooja/contiki_tests/hello-world.js @@ -0,0 +1,9 @@ +TIMEOUT(5000); + +while(true) { + log.log("> " + msg + "\n"); + if (msg.equals('Hello, world')) { + log.testOK(); + } + YIELD(); +} diff --git a/tools/cooja/contiki_tests/micaz_helloworld.csc b/tools/cooja/contiki_tests/micaz_helloworld.csc index 4906774f9..c8c9a04d8 100644 --- a/tools/cooja/contiki_tests/micaz_helloworld.csc +++ b/tools/cooja/contiki_tests/micaz_helloworld.csc @@ -1,120 +1,79 @@ - - - ../apps/mrm - ../apps/mspsim - ../apps/avrora - - My simulation - 0 - generated - 1000000 - - se.sics.cooja.radiomediums.UDGM - 50.0 - 100.0 - 1.0 - 1.0 - - - 40000 - - - se.sics.cooja.avrmote.MicaZMoteType - micaz1 - MicaZ Mote Type #micaz1 - ../../../examples/hello-world/hello-world.c - make clean TARGET=micaz -make hello-world.elf TARGET=micaz - ../../../examples/hello-world/hello-world.elf - se.sics.cooja.interfaces.Position - se.sics.cooja.avrmote.interfaces.MicaZID - se.sics.cooja.avrmote.interfaces.MicaZLED - se.sics.cooja.avrmote.interfaces.MicaZRadio - se.sics.cooja.avrmote.interfaces.MicaClock - se.sics.cooja.avrmote.interfaces.MicaSerial - - - se.sics.cooja.avrmote.MicaZMote - micaz1 - - se.sics.cooja.interfaces.Position - 68.44103812985554 - 35.6791174319418 - 0.0 - - - se.sics.cooja.avrmote.interfaces.MicaZID - 1 - - - - - se.sics.cooja.plugins.SimControl - 259 - 4 - 184 - 0 - 0 - false - - - se.sics.cooja.plugins.Visualizer - - se.sics.cooja.plugins.skins.IDVisualizerSkin - se.sics.cooja.plugins.skins.LogVisualizerSkin - 0.9090909090909091 0.0 0.0 0.9090909090909091 81.78087442740406 87.56443869823474 - - 300 - 1 - 300 - 456 - 0 - false - - - se.sics.cooja.plugins.LogListener - - - - 756 - 2 - 150 - 0 - 286 - false - - - se.sics.cooja.plugins.TimeLine - - 0 - - - - 109 - 9 - - 756 - 3 - 150 - 0 - 436 - false - - - se.sics.cooja.plugins.ScriptRunner - - - true - - 600 - 0 - 305 - 89 - 211 - false - - - + + + + Hello World (MicaZ) + generated + 1000000 + + se.sics.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.avrmote.MicaZMoteType + micaz1 + MicaZ Mote Type #micaz1 + [CONTIKI_DIR]/examples/hello-world/hello-world.c + make hello-world.elf TARGET=micaz + [CONTIKI_DIR]/examples/hello-world/hello-world.elf + se.sics.cooja.interfaces.Position + se.sics.cooja.avrmote.interfaces.MicaZID + se.sics.cooja.avrmote.interfaces.MicaZLED + se.sics.cooja.avrmote.interfaces.MicaZRadio + se.sics.cooja.avrmote.interfaces.MicaClock + se.sics.cooja.avrmote.interfaces.MicaSerial + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + + + + se.sics.cooja.interfaces.Position + 36.478849033811386 + 97.17795415366507 + 0.0 + + + se.sics.cooja.avrmote.interfaces.MicaZID + 1 + + micaz1 + + + + se.sics.cooja.plugins.SimControl + 280 + 2 + 160 + 17 + 16 + + + se.sics.cooja.plugins.LogListener + + + + 680 + 1 + 240 + 20 + 285 + + + se.sics.cooja.plugins.ScriptRunner + + [CONFIG_DIR]/hello-world.js + true + + 600 + 0 + 535 + 403 + 23 + + + diff --git a/tools/cooja/contiki_tests/sky_helloworld.csc b/tools/cooja/contiki_tests/sky_helloworld.csc index e97b4f6d7..fb216a3ee 100644 --- a/tools/cooja/contiki_tests/sky_helloworld.csc +++ b/tools/cooja/contiki_tests/sky_helloworld.csc @@ -1,80 +1,82 @@ - - - ../apps/mrm - ../apps/mspsim - ../apps/avrora - ../apps/native_gateway - - Hello World (Sky) - 0 - generated - 1000000 - - se.sics.cooja.radiomediums.UDGM - 50.0 - 100.0 - 1.0 - 1.0 - - - se.sics.cooja.mspmote.SkyMoteType - sky1 - Sky Mote Type #1 - ../../../examples/hello-world/hello-world.c - make clean TARGET=sky -make hello-world.sky TARGET=sky - ../../../examples/hello-world/hello-world.sky - se.sics.cooja.interfaces.Position - se.sics.cooja.interfaces.IPAddress - se.sics.cooja.interfaces.Mote2MoteRelations - se.sics.cooja.mspmote.interfaces.MspClock - se.sics.cooja.mspmote.interfaces.MspMoteID - se.sics.cooja.mspmote.interfaces.SkyButton - se.sics.cooja.mspmote.interfaces.SkyFlash - se.sics.cooja.mspmote.interfaces.SkyByteRadio - se.sics.cooja.mspmote.interfaces.SkySerial - se.sics.cooja.mspmote.interfaces.SkyLED - - - se.sics.cooja.mspmote.SkyMote - sky1 - - - se.sics.cooja.interfaces.Position - 64.11203103628397 - 93.06735634828134 - 0.0 - - - se.sics.cooja.mspmote.interfaces.MspMoteID - 1 - - - - - se.sics.cooja.plugins.SimControl - 248 - 1 - 200 - 0 - 0 - false - - - se.sics.cooja.plugins.ScriptRunner - - - true - - 541 - 0 - 448 - 248 - -1 - false - - - + + + + Hello World test (Sky) + generated + 1000000 + + se.sics.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.mspmote.SkyMoteType + sky1 + Sky Mote Type #1 + [CONTIKI_DIR]/examples/hello-world/hello-world.c + make hello-world.sky TARGET=sky + [CONTIKI_DIR]/examples/hello-world/hello-world.sky + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.IPAddress + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.mspmote.interfaces.MspClock + se.sics.cooja.mspmote.interfaces.MspMoteID + se.sics.cooja.mspmote.interfaces.SkyButton + se.sics.cooja.mspmote.interfaces.SkyFlash + se.sics.cooja.mspmote.interfaces.Msp802154Radio + se.sics.cooja.mspmote.interfaces.MspSerial + se.sics.cooja.mspmote.interfaces.SkyLED + + + + + se.sics.cooja.interfaces.Position + 64.11203103628397 + 93.06735634828134 + 0.0 + + + se.sics.cooja.mspmote.interfaces.MspMoteID + 1 + + sky1 + + + + se.sics.cooja.plugins.ScriptRunner + + [CONFIG_DIR]/hello-world.js + true + + 541 + 0 + 448 + 299 + 7 + + + se.sics.cooja.plugins.SimControl + 280 + 2 + 160 + 7 + 10 + + + se.sics.cooja.plugins.LogListener + + + + 680 + 1 + 240 + 51 + 288 + + + diff --git a/tools/cooja/contiki_tests/wismote_helloworld.csc b/tools/cooja/contiki_tests/wismote_helloworld.csc new file mode 100644 index 000000000..52a16396e --- /dev/null +++ b/tools/cooja/contiki_tests/wismote_helloworld.csc @@ -0,0 +1,84 @@ + + + + Hello World (Wismote) + generated + 1000000 + + se.sics.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.mspmote.WismoteMoteType + wismote1 + Wismote Mote Type #wismote1 + [CONTIKI_DIR]/examples/hello-world/hello-world.c + make hello-world.wismote TARGET=wismote + [CONTIKI_DIR]/examples/hello-world/hello-world.wismote + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.interfaces.IPAddress + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + se.sics.cooja.mspmote.interfaces.MspClock + se.sics.cooja.mspmote.interfaces.MspMoteID + se.sics.cooja.mspmote.interfaces.MspButton + se.sics.cooja.mspmote.interfaces.Msp802154Radio + se.sics.cooja.mspmote.interfaces.MspDefaultSerial + se.sics.cooja.mspmote.interfaces.MspLED + se.sics.cooja.mspmote.interfaces.MspDebugOutput + + + + + se.sics.cooja.interfaces.Position + 36.76551518369201 + 29.330591009779383 + 0.0 + + + se.sics.cooja.mspmote.interfaces.MspMoteID + 1 + + wismote1 + + + + se.sics.cooja.plugins.SimControl + 280 + 2 + 160 + 22 + 14 + + + se.sics.cooja.plugins.LogListener + + + + 680 + 1 + 240 + 84 + 408 + + + se.sics.cooja.plugins.ScriptRunner + + [CONFIG_DIR]/hello-world.js + true + + 600 + 0 + 548 + 335 + 22 + + + diff --git a/tools/cooja/contiki_tests/z1_helloworld.csc b/tools/cooja/contiki_tests/z1_helloworld.csc new file mode 100644 index 000000000..3af73dc00 --- /dev/null +++ b/tools/cooja/contiki_tests/z1_helloworld.csc @@ -0,0 +1,83 @@ + + + + Hello World (Z1) + generated + 1000000 + + se.sics.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.mspmote.Z1MoteType + z11 + Z1 Mote Type #z11 + [CONTIKI_DIR]/examples/hello-world/hello-world.c + make hello-world.z1 TARGET=z1 + [CONTIKI_DIR]/examples/hello-world/hello-world.z1 + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.interfaces.IPAddress + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + se.sics.cooja.mspmote.interfaces.MspClock + se.sics.cooja.mspmote.interfaces.MspMoteID + se.sics.cooja.mspmote.interfaces.Msp802154Radio + se.sics.cooja.mspmote.interfaces.MspDefaultSerial + se.sics.cooja.mspmote.interfaces.MspLED + se.sics.cooja.mspmote.interfaces.MspDebugOutput + + + + + se.sics.cooja.interfaces.Position + 94.96401380574989 + 21.247662337471553 + 0.0 + + + se.sics.cooja.mspmote.interfaces.MspMoteID + 1 + + z11 + + + + se.sics.cooja.plugins.SimControl + 280 + 2 + 160 + 38 + 13 + + + se.sics.cooja.plugins.LogListener + + + + 680 + 1 + 240 + 109 + 377 + + + se.sics.cooja.plugins.ScriptRunner + + [CONFIG_DIR]/hello-world.js + true + + 600 + 0 + 700 + 330 + 24 + + + From 997baa67d1b18f0327836ecfbc55652eba1218f2 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Thu, 31 May 2012 16:00:11 +0200 Subject: [PATCH 04/19] No longer any need to specify memory when loading firmware --- tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java index 27a213e91..315611eba 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java @@ -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);*/ From d83b46165483d12ed56329a9865c93428908ffb8 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Mon, 4 Jun 2012 13:39:26 +0200 Subject: [PATCH 05/19] Added check if the interface is not available --- .../cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java index 315611eba..497132c87 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java @@ -416,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); } } From cce3628440f8b469fa9c0c3351d0985562656273 Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Tue, 5 Jun 2012 08:07:10 +0200 Subject: [PATCH 06/19] Bugfix: viewers were not correctly ticked off in the menu when a simulation was loaded from file. The current fix feels like a hack through. --- .../java/se/sics/cooja/plugins/Visualizer.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java b/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java index 6034e5ae1..a1d7e9c93 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java +++ b/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java @@ -572,7 +572,9 @@ public class Visualizer extends VisPlugin implements HasQuickHelp { simulation.getGUI().tryLoadClass(this, VisualizerSkin.class, skin); generateAndActivateSkin(skinClass); } + populateSkinMenu(viewMenu); + } public VisualizerSkin[] getCurrentSkins() { @@ -1338,6 +1340,18 @@ public class Visualizer extends VisPlugin implements HasQuickHelp { skinButton.setVisible(false); } } + + /* + * This is a hack: since the viewers are activated through an invokeLater + * mechanism (see above), we'll have to invoke the + * populateSkinMenu(viewMenu) later too. Lets just hope the invokation of + * populateSkinMenu() is done later than the activation of the viewers... + */ + SwingUtilities.invokeLater(new Runnable() { + public void run() { + populateSkinMenu(viewMenu); + } + }); return true; } From bd86a807c82e5ccebc0b8e24a2dd5f1ffecdfc3b Mon Sep 17 00:00:00 2001 From: Adam Dunkels Date: Tue, 5 Jun 2012 08:07:47 +0200 Subject: [PATCH 07/19] Rewrote the traffic history visualization with blue arrows that fade away based on their age. Age is calculated from the simulation time so the fade depends on the simulation speed. --- .../plugins/skins/TrafficVisualizerSkin.java | 178 +++++++++++------- 1 file changed, 107 insertions(+), 71 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/plugins/skins/TrafficVisualizerSkin.java b/tools/cooja/java/se/sics/cooja/plugins/skins/TrafficVisualizerSkin.java index 7d9a954b8..79533d31e 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/skins/TrafficVisualizerSkin.java +++ b/tools/cooja/java/se/sics/cooja/plugins/skins/TrafficVisualizerSkin.java @@ -34,6 +34,7 @@ package se.sics.cooja.plugins.skins; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; +import java.awt.Polygon; import java.util.ArrayDeque; import java.util.Observable; import java.util.Observer; @@ -72,25 +73,23 @@ import se.sics.cooja.radiomediums.AbstractRadioMedium; @ClassDescription("Radio traffic") 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 Simulation simulation = null; private Visualizer visualizer = null; private Box counters; - private final static int HISTORY_SIZE = 16; - private boolean showHistory = false; - private ArrayDeque history = new ArrayDeque(); + private final int MAX_HISTORY_SIZE = 200; + private boolean showHistory = true; + private ArrayDeque history = new ArrayDeque(); private AbstractRadioMedium radioMedium; private Observer radioObserver, radioMediumObserver; - public void setActive(Simulation simulation, Visualizer vis) { + public void setActive(final Simulation simulation, Visualizer vis) { if (!(simulation.getRadioMedium() instanceof AbstractRadioMedium)) { - logger.fatal("Radio medium type not supported: " + simulation.getRadioMedium()); + logger.fatal("Radio medium type not supported: " + + simulation.getRadioMedium()); return; } this.radioMedium = (AbstractRadioMedium) simulation.getRadioMedium(); @@ -99,7 +98,8 @@ public class TrafficVisualizerSkin implements VisualizerSkin { 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); + final JLabel interferedCounter = new JLabel("INT: " + + radioMedium.COUNTER_INTERFERED); counters = Box.createHorizontalBox(); counters.add(txCounter); @@ -108,22 +108,19 @@ public class TrafficVisualizerSkin implements VisualizerSkin { counters.add(Box.createHorizontalStrut(10)); counters.add(interferedCounter); - /* visualizer.getCurrentCanvas().add(counters);*/ + /* 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); + 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(); - } + if (last != null && history.size() < MAX_HISTORY_SIZE) { + history.add(new RadioConnectionArrow(last)); } } visualizer.repaint(); @@ -141,6 +138,7 @@ public class TrafficVisualizerSkin implements VisualizerSkin { r.addObserver(radioObserver); } } + public void moteWasRemoved(Mote mote) { Radio r = mote.getInterfaces().getRadio(); if (r != null) { @@ -149,13 +147,33 @@ public class TrafficVisualizerSkin implements VisualizerSkin { history.clear(); } }); - for (Mote mote: simulation.getMotes()) { + for (Mote mote : simulation.getMotes()) { Radio r = mote.getInterfaces().getRadio(); if (r != null) { r.addObserver(radioObserver); } } + simulation.addMillisecondObserver(new Observer() { + public void update(Observable obs, Object obj) { + if((simulation.getSimulationTimeMillis() % 100) == 0) { + RadioConnectionArrow[] historyArr = history.toArray(new RadioConnectionArrow[0]); + if(historyArr.length > 0) { + visualizer.repaint(); + } + for (RadioConnectionArrow connArrow : historyArr) { + if (connArrow == null) { + continue; + } + connArrow.increaseAge(); + if(connArrow.getAge() >= connArrow.getMaxAge()) { + history.remove(connArrow); + } + } + } + + } + }); /* Register menu actions */ visualizer.registerSimulationMenuAction(ToggleHistoryAction.class); } @@ -170,7 +188,7 @@ public class TrafficVisualizerSkin implements VisualizerSkin { /* Stop observing radio medium and radios */ radioMedium.deleteRadioMediumObserver(radioMediumObserver); - for (Mote mote: simulation.getMotes()) { + for (Mote mote : simulation.getMotes()) { Radio r = mote.getInterfaces().getRadio(); if (r != null) { r.addObserver(radioObserver); @@ -182,35 +200,38 @@ public class TrafficVisualizerSkin implements VisualizerSkin { } 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; } + 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) { if (simulation == null) { /* Skin was never activated */ @@ -219,18 +240,20 @@ public class TrafficVisualizerSkin implements VisualizerSkin { if (showHistory) { /* Paint history in gray */ - RadioConnection[] historyArr = history.toArray(new RadioConnection[0]); - for (RadioConnection conn : historyArr) { - if (conn == null) { + RadioConnectionArrow[] historyArr = history.toArray(new RadioConnectionArrow[0]); + for (RadioConnectionArrow connArrow : historyArr) { + if (connArrow == null) { continue; } - g.setColor(COLOR_HISTORY); - Radio source = conn.getSource(); - Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition()); - for (Radio destRadio : conn.getDestinations()) { + 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 : connArrow.getConnection().getDestinations()) { Position destPos = destRadio.getPosition(); - Point destPoint = visualizer.transformPositionToPixel(destPos); - g.drawLine(sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y); + Point destPoint = visualizer.transformPositionToPixel(destPos); + drawArrow(g, sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y, 8); } } } @@ -244,24 +267,15 @@ public class TrafficVisualizerSkin implements VisualizerSkin { continue; } Radio source = conn.getSource(); - Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition()); + 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); } } } @@ -269,7 +283,7 @@ 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; @@ -278,9 +292,9 @@ public class TrafficVisualizerSkin implements VisualizerSkin { public String getDescription(Visualizer visualizer, Simulation simulation) { VisualizerSkin[] skins = visualizer.getCurrentSkins(); boolean showing = false; - for (VisualizerSkin skin: skins) { + for (VisualizerSkin skin : skins) { if (skin instanceof TrafficVisualizerSkin) { - showing = ((TrafficVisualizerSkin)skin).showHistory; + showing = ((TrafficVisualizerSkin) skin).showHistory; } } if (showing) { @@ -291,9 +305,9 @@ public class TrafficVisualizerSkin implements VisualizerSkin { public void doAction(Visualizer visualizer, Simulation simulation) { VisualizerSkin[] skins = visualizer.getCurrentSkins(); - for (VisualizerSkin skin: skins) { + for (VisualizerSkin skin : skins) { if (skin instanceof TrafficVisualizerSkin) { - ((TrafficVisualizerSkin)skin).showHistory = !((TrafficVisualizerSkin)skin).showHistory; + ((TrafficVisualizerSkin) skin).showHistory = !((TrafficVisualizerSkin) skin).showHistory; visualizer.repaint(); } } @@ -303,4 +317,26 @@ public class TrafficVisualizerSkin implements VisualizerSkin { public Visualizer getVisualizer() { return visualizer; } + + private class RadioConnectionArrow { + private RadioConnection conn; + private int age; + private final int MAX_AGE = 10; + RadioConnectionArrow(RadioConnection conn) { + this.conn = conn; + this.age = 0; + } + public void increaseAge() { + age++; + } + public int getAge() { + return age; + } + public RadioConnection getConnection() { + return conn; + } + public int getMaxAge() { + return MAX_AGE; + } + } } From c276f9024781e39d530b1ab174c7df109cfce10d Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Tue, 5 Jun 2012 09:25:45 +0200 Subject: [PATCH 08/19] removed unused code including simulation observers, making the code cleaner and more efficient --- .../plugins/skins/TrafficVisualizerSkin.java | 278 +++++------------- 1 file changed, 80 insertions(+), 198 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/plugins/skins/TrafficVisualizerSkin.java b/tools/cooja/java/se/sics/cooja/plugins/skins/TrafficVisualizerSkin.java index 79533d31e..303cb4728 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/skins/TrafficVisualizerSkin.java +++ b/tools/cooja/java/se/sics/cooja/plugins/skins/TrafficVisualizerSkin.java @@ -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; @@ -35,168 +33,115 @@ import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.Polygon; -import java.util.ArrayDeque; +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 Simulation simulation = null; - private Visualizer visualizer = null; - - private Box counters; private final int MAX_HISTORY_SIZE = 200; - private boolean showHistory = true; - private ArrayDeque history = new ArrayDeque(); - private AbstractRadioMedium radioMedium; - private Observer radioObserver, radioMediumObserver; + private boolean active = false; + private Simulation simulation = null; + private Visualizer visualizer = null; + private AbstractRadioMedium radioMedium = null; + + private ArrayList history = new ArrayList(); + + private Observer radioMediumObserver = new Observer() { + public void update(Observable obs, Object obj) { + RadioConnection last = radioMedium.getLastConnection(); + if (last != null && history.size() < MAX_HISTORY_SIZE) { + history.add(new RadioConnectionArrow(last)); + visualizer.repaint(); + } + } + }; + private TimeEvent ageArrowsTimeEvent = new TimeEvent(0) { + public void execute(long t) { + if (!active) { + return; + } + + if (history.size() > 0) { + boolean hasOld = false; + + /* Increase age */ + for (RadioConnectionArrow connArrow : history) { + connArrow.increaseAge(); + if(connArrow.getAge() >= connArrow.getMaxAge()) { + hasOld = true; + } + } + + /* Remove too old arrows */ + if (hasOld) { + RadioConnectionArrow[] historyArr = history.toArray(new RadioConnectionArrow[0]); + for (RadioConnectionArrow connArrow : historyArr) { + if(connArrow.getAge() >= connArrow.getMaxAge()) { + history.remove(connArrow); + } + } + } + + visualizer.repaint(); + } + + /* Reschedule myself */ + simulation.scheduleEvent(this, t + 100*Simulation.MILLISECOND); + } + }; public void setActive(final Simulation simulation, Visualizer vis) { - if (!(simulation.getRadioMedium() instanceof AbstractRadioMedium)) { - logger.fatal("Radio medium type not supported: " - + simulation.getRadioMedium()); - return; - } this.radioMedium = (AbstractRadioMedium) simulation.getRadioMedium(); this.simulation = simulation; this.visualizer = vis; + this.active = true; + history.clear(); - 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() { + /* Start observing radio medium for transmissions */ + radioMedium.addRadioMediumObserver(radioMediumObserver); - counters = Box.createHorizontalBox(); - counters.add(txCounter); - counters.add(Box.createHorizontalStrut(10)); - counters.add(rxCounter); - counters.add(Box.createHorizontalStrut(10)); - counters.add(interferedCounter); - - /* 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.size() < MAX_HISTORY_SIZE) { - history.add(new RadioConnectionArrow(last)); - } - } - 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); - } - } - - simulation.addMillisecondObserver(new Observer() { - public void update(Observable obs, Object obj) { - if((simulation.getSimulationTimeMillis() % 100) == 0) { - RadioConnectionArrow[] historyArr = history.toArray(new RadioConnectionArrow[0]); - if(historyArr.length > 0) { - visualizer.repaint(); - } - for (RadioConnectionArrow connArrow : historyArr) { - if (connArrow == null) { - continue; - } - connArrow.increaseAge(); - if(connArrow.getAge() >= connArrow.getMaxAge()) { - history.remove(connArrow); - } - } - } - - } - }); - /* 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) { @@ -232,51 +177,18 @@ public class TrafficVisualizerSkin implements VisualizerSkin { 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 */ - return; - } - - if (showHistory) { - /* Paint history in gray */ - RadioConnectionArrow[] historyArr = history.toArray(new RadioConnectionArrow[0]); - for (RadioConnectionArrow connArrow : historyArr) { - if (connArrow == null) { - continue; - } - 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 : connArrow.getConnection().getDestinations()) { - Position destPos = destRadio.getPosition(); - Point destPoint = visualizer.transformPositionToPixel(destPos); - drawArrow(g, sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y, 8); - } - } - } - - /* 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); - drawArrow(g, sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y, 8); - } + RadioConnectionArrow[] historyArr = history.toArray(new RadioConnectionArrow[0]); + for (RadioConnectionArrow connArrow : historyArr) { + 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 : connArrow.getConnection().getDestinations()) { + Position destPos = destRadio.getPosition(); + Point destPoint = visualizer.transformPositionToPixel(destPos); + drawArrow(g, sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y, 8); } } } @@ -284,41 +196,11 @@ 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 class RadioConnectionArrow { + + private static class RadioConnectionArrow { private RadioConnection conn; private int age; private final int MAX_AGE = 10; From 9c05689be07b0b152b1b830292d674a50d549f69 Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Tue, 5 Jun 2012 10:03:47 +0200 Subject: [PATCH 09/19] simplified skin menu implementation, removed unused skin button code --- .../se/sics/cooja/plugins/Visualizer.java | 92 +++++++------------ 1 file changed, 31 insertions(+), 61 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java b/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java index a1d7e9c93..7ff2a7192 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java +++ b/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java @@ -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; @@ -68,7 +67,6 @@ import java.util.Observable; import java.util.Observer; import javax.swing.AbstractAction; -import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; import javax.swing.JMenuBar; @@ -80,6 +78,8 @@ import javax.swing.JSeparator; 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 +87,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 +160,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> visualizerSkins = new ArrayList>(); static { @@ -222,10 +221,20 @@ public class Visualizer extends VisPlugin implements HasQuickHelp { /* Menus */ 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); menuBar.add(zoomMenu); @@ -280,20 +289,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 */ @@ -524,7 +519,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. */ this.setLocation(1, 1); - this.setSize(400, 400); + this.setSize(400, 400); } private void generateAndActivateSkin(Class skinClass) { @@ -550,9 +545,6 @@ public class Visualizer extends VisPlugin implements HasQuickHelp { } catch (IllegalAccessException e1) { e1.printStackTrace(); } - - skinButton.setText("Select visualizer " + - "(" + currentSkins.size() + "/" + visualizerSkins.size() + ")"); repaint(); } @@ -572,9 +564,6 @@ public class Visualizer extends VisPlugin implements HasQuickHelp { simulation.getGUI().tryLoadClass(this, VisualizerSkin.class, skin); generateAndActivateSkin(skinClass); } - - populateSkinMenu(viewMenu); - } public VisualizerSkin[] getCurrentSkins() { @@ -700,11 +689,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 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 */ @@ -749,23 +742,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); } } } @@ -845,7 +830,7 @@ public class Visualizer extends VisPlugin implements HasQuickHelp { newZoom, newZoom ); - + /*Position moved = transformPixelToPosition(zoomingPixel); viewportTransform.translate( moved.getXCoordinate() - zoomingPosition.getXCoordinate(), @@ -919,7 +904,7 @@ public class Visualizer extends VisPlugin implements HasQuickHelp { } /* Restore cursor */ canvas.setCursor(Cursor.getDefaultCursor()); - + /* Move mote */ if (moveStartTime < 0 || System.currentTimeMillis() - moveStartTime > 300) { @@ -1296,7 +1281,7 @@ public class Visualizer extends VisPlugin implements HasQuickHelp { } public boolean setConfigXML(Collection configXML, boolean visAvailable) { - loadedConfig = true; + loadedConfig = true; for (Element element : configXML) { if (element.getName().equals("skin")) { @@ -1337,21 +1322,8 @@ 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); } } - - /* - * This is a hack: since the viewers are activated through an invokeLater - * mechanism (see above), we'll have to invoke the - * populateSkinMenu(viewMenu) later too. Lets just hope the invokation of - * populateSkinMenu() is done later than the activation of the viewers... - */ - SwingUtilities.invokeLater(new Runnable() { - public void run() { - populateSkinMenu(viewMenu); - } - }); return true; } @@ -1503,11 +1475,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() { From 69457c50396aaee1f728a4a7b8f9b8ecd46fcff0 Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Tue, 5 Jun 2012 12:45:43 +0200 Subject: [PATCH 10/19] removed unnecessary warning --- .../contikimote/interfaces/ContikiClock.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/contikimote/interfaces/ContikiClock.java b/tools/cooja/java/se/sics/cooja/contikimote/interfaces/ContikiClock.java index 4ef74ee9d..03470c71d 100644 --- a/tools/cooja/java/se/sics/cooja/contikimote/interfaces/ContikiClock.java +++ b/tools/cooja/java/se/sics/cooja/contikimote/interfaces/ContikiClock.java @@ -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; @@ -74,7 +75,7 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB private long moteTime; /* Microseconds */ private long timeDrift; /* Microseconds */ - + /** * @param mote Mote * @@ -117,9 +118,9 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB /* Update time */ setTime(mote.getSimulation().getSimulationTime() + timeDrift); } - + public void doActionsAfterTick() { - + /* Request next tick for remaining events / timers */ int processRunValue = moteMem.getIntValueOf("simProcessRunValue"); if (processRunValue != 0) { @@ -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); } From a8a3c7b01a5a6f9cdc026ce1432801137839a5d1 Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Tue, 5 Jun 2012 12:48:21 +0200 Subject: [PATCH 11/19] fixed menu bug that caused menu items to be enabled although script was active reinstated title that shows whether script is active or not fixed Ctrl+R hotkey bug that triggered an error dialog when script was inactive remember last script disk file --- .../se/sics/cooja/plugins/ScriptRunner.java | 109 ++++++++++-------- 1 file changed, 63 insertions(+), 46 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java b/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java index 67ff28c34..f7db90b55 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java +++ b/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java @@ -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,10 +69,13 @@ 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; import jsyntaxpane.actions.DefaultSyntaxAction; +import jsyntaxpane.actions.ScriptRunnerAction; import org.apache.log4j.Logger; import org.jdom.Element; @@ -110,15 +111,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 +125,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 +139,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 +158,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"); @@ -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,12 +202,28 @@ 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(); @@ -226,13 +234,21 @@ public class ScriptRunner extends VisPlugin { 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()); - actionLinkFile.setMenuText("Link script to disk file"); - actionLinkFile.putValue("ScriptRunner", this); - } + if (!(c instanceof JMenuItem)) { + continue; + } + if (((JMenuItem) c).getAction() == null) { + continue; + } + Action a = ((JMenuItem) c).getAction(); + if (a instanceof JSyntaxLinkFile) { + actionLinkFile = (JSyntaxLinkFile)(((JMenuItem) c).getAction()); + actionLinkFile.setMenuText("Link script to disk file"); + actionLinkFile.putValue("ScriptRunner", this); + } else if (a instanceof ScriptRunnerAction) { + /* XXX Disable run action */ + ScriptRunnerAction sra = (ScriptRunnerAction) ((JMenuItem) c).getAction(); + sra.setEnabled(false); } } } @@ -241,10 +257,6 @@ public class ScriptRunner extends VisPlugin { 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 +292,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 +370,9 @@ public class ScriptRunner extends VisPlugin { engine.activateScript(codeEditor.getText()); if (!headless) { - actionLinkFile.setEnabled(false); - /* toggleButton.setText("Deactivate");*/ - /*examplesButton.setEnabled(false);*/ + if (actionLinkFile != null) { + actionLinkFile.setEnabled(false); + } logTextArea.setText(""); codeEditor.setEnabled(false); updateTitle(); @@ -402,9 +415,9 @@ public class ScriptRunner extends VisPlugin { } if (!headless) { - actionLinkFile.setEnabled(true); - /*toggleButton.setText("Activate")*/; - /*examplesButton.setEnabled(linkedFile==null?true:false);*/ + if (actionLinkFile != null) { + actionLinkFile.setEnabled(true); + } codeEditor.setEnabled(true); updateTitle(); } @@ -413,14 +426,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 +622,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 +704,12 @@ public class ScriptRunner extends VisPlugin { } 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.setDialogTitle("Select script file"); fileChooser.setFileFilter(new FileFilter() { From afcc7559a5c33625607523603b395745034a3e47 Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Tue, 5 Jun 2012 13:16:09 +0200 Subject: [PATCH 12/19] improved repaint efficiency and fixed concurrent modification bug --- .../plugins/skins/TrafficVisualizerSkin.java | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/plugins/skins/TrafficVisualizerSkin.java b/tools/cooja/java/se/sics/cooja/plugins/skins/TrafficVisualizerSkin.java index 303cb4728..11c01dcb1 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/skins/TrafficVisualizerSkin.java +++ b/tools/cooja/java/se/sics/cooja/plugins/skins/TrafficVisualizerSkin.java @@ -69,14 +69,16 @@ public class TrafficVisualizerSkin implements VisualizerSkin { private Visualizer visualizer = null; private AbstractRadioMedium radioMedium = null; - private ArrayList history = new ArrayList(); + private ArrayList historyList = new ArrayList(); + private RadioConnectionArrow[] history = null; private Observer radioMediumObserver = new Observer() { public void update(Observable obs, Object obj) { RadioConnection last = radioMedium.getLastConnection(); - if (last != null && history.size() < MAX_HISTORY_SIZE) { - history.add(new RadioConnectionArrow(last)); - visualizer.repaint(); + if (last != null && historyList.size() < MAX_HISTORY_SIZE) { + historyList.add(new RadioConnectionArrow(last)); + history = historyList.toArray(new RadioConnectionArrow[0]); + visualizer.repaint(500); } } }; @@ -86,11 +88,11 @@ public class TrafficVisualizerSkin implements VisualizerSkin { return; } - if (history.size() > 0) { + if (historyList.size() > 0) { boolean hasOld = false; /* Increase age */ - for (RadioConnectionArrow connArrow : history) { + for (RadioConnectionArrow connArrow : historyList) { connArrow.increaseAge(); if(connArrow.getAge() >= connArrow.getMaxAge()) { hasOld = true; @@ -99,15 +101,16 @@ public class TrafficVisualizerSkin implements VisualizerSkin { /* Remove too old arrows */ if (hasOld) { - RadioConnectionArrow[] historyArr = history.toArray(new RadioConnectionArrow[0]); + RadioConnectionArrow[] historyArr = historyList.toArray(new RadioConnectionArrow[0]); for (RadioConnectionArrow connArrow : historyArr) { if(connArrow.getAge() >= connArrow.getMaxAge()) { - history.remove(connArrow); + historyList.remove(connArrow); } } + historyArr = historyList.toArray(new RadioConnectionArrow[0]); } - visualizer.repaint(); + visualizer.repaint(500); } /* Reschedule myself */ @@ -120,10 +123,12 @@ public class TrafficVisualizerSkin implements VisualizerSkin { this.simulation = simulation; this.visualizer = vis; this.active = true; - history.clear(); simulation.invokeSimulationThread(new Runnable() { public void run() { + historyList.clear(); + history = null; + /* Start observing radio medium for transmissions */ radioMedium.addRadioMediumObserver(radioMediumObserver); @@ -179,8 +184,11 @@ public class TrafficVisualizerSkin implements VisualizerSkin { } public void paintBeforeMotes(Graphics g) { - RadioConnectionArrow[] historyArr = history.toArray(new RadioConnectionArrow[0]); - for (RadioConnectionArrow connArrow : historyArr) { + RadioConnectionArrow[] historyCopy = history; + if (historyCopy == null) { + return; + } + 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(); @@ -203,13 +211,15 @@ public class TrafficVisualizerSkin implements VisualizerSkin { private static class RadioConnectionArrow { private RadioConnection conn; private int age; - private final int MAX_AGE = 10; + private static final int MAX_AGE = 10; RadioConnectionArrow(RadioConnection conn) { this.conn = conn; this.age = 0; } public void increaseAge() { - age++; + if (age < MAX_AGE) { + age++; + } } public int getAge() { return age; From 5c2ecd1def46764eec87a339e87f11aa22f69964 Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Tue, 5 Jun 2012 13:39:21 +0200 Subject: [PATCH 13/19] improved workaround to disable the code editor pane's built in run functionality: remove keyboard shortcut instead of disabling action --- tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java b/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java index f7db90b55..96dc544fd 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java +++ b/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java @@ -75,7 +75,6 @@ import javax.swing.filechooser.FileFilter; import jsyntaxpane.DefaultSyntaxKit; import jsyntaxpane.actions.DefaultSyntaxAction; -import jsyntaxpane.actions.ScriptRunnerAction; import org.apache.log4j.Logger; import org.jdom.Element; @@ -169,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"); } } @@ -229,6 +229,7 @@ public class ScriptRunner extends VisPlugin { 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(); @@ -242,13 +243,9 @@ public class ScriptRunner extends VisPlugin { } Action a = ((JMenuItem) c).getAction(); if (a instanceof JSyntaxLinkFile) { - actionLinkFile = (JSyntaxLinkFile)(((JMenuItem) c).getAction()); + actionLinkFile = (JSyntaxLinkFile) a; actionLinkFile.setMenuText("Link script to disk file"); actionLinkFile.putValue("ScriptRunner", this); - } else if (a instanceof ScriptRunnerAction) { - /* XXX Disable run action */ - ScriptRunnerAction sra = (ScriptRunnerAction) ((JMenuItem) c).getAction(); - sra.setEnabled(false); } } } From 49b949f9dbdb6456362cb31b9890e5caad50920f Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Tue, 5 Jun 2012 14:06:30 +0200 Subject: [PATCH 14/19] implemented zoom menu and added keyboard shortcuts fixed typos in quick help --- .../se/sics/cooja/plugins/Visualizer.java | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java b/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java index 7ff2a7192..320942fef 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java +++ b/tools/cooja/java/se/sics/cooja/plugins/Visualizer.java @@ -53,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; @@ -67,6 +68,7 @@ import java.util.Observable; import java.util.Observer; import javax.swing.AbstractAction; +import javax.swing.Action; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; import javax.swing.JMenuBar; @@ -75,6 +77,7 @@ 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; @@ -240,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"); @@ -820,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); - viewportTransform.translate( - moved.getXCoordinate() - zoomingPosition.getXCoordinate(), - moved.getYCoordinate() - zoomingPosition.getYCoordinate() - );*/ + Position newCenter = transformPixelToPosition( + new Point(canvas.getWidth()/2, canvas.getHeight()/2) + ); + viewportTransform.translate( + newCenter.getXCoordinate() - center.getXCoordinate(), + newCenter.getYCoordinate() - center.getYCoordinate() + ); repaint(); - } private void handleMouseMove(MouseEvent e, boolean stop) { @@ -1509,10 +1522,10 @@ public class Visualizer extends VisPlugin implements HasQuickHelp { public String getQuickHelp() { return "Network " + - "

The network windo shows the positions of simulated motes. " + + "

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. " + - "

The network window suppors different views. " + + "

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. "; From b322eda91a37b7754cde83f561d815c49cf7cdb5 Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Tue, 5 Jun 2012 14:45:16 +0200 Subject: [PATCH 15/19] added support for mote interface requirements in SupportedArguments annotation NativeIPGateway plugin now requires an IP address mote interface --- .../sics/cooja/plugins/NativeIPGateway.java | 17 +++--- tools/cooja/java/se/sics/cooja/GUI.java | 60 +++++++++++++------ .../se/sics/cooja/SupportedArguments.java | 5 ++ 3 files changed, 57 insertions(+), 25 deletions(-) diff --git a/tools/cooja/apps/native_gateway/java/se/sics/cooja/plugins/NativeIPGateway.java b/tools/cooja/apps/native_gateway/java/se/sics/cooja/plugins/NativeIPGateway.java index 9a28a9022..83f9e34a1 100644 --- a/tools/cooja/apps/native_gateway/java/se/sics/cooja/plugins/NativeIPGateway.java +++ b/tools/cooja/apps/native_gateway/java/se/sics/cooja/plugins/NativeIPGateway.java @@ -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); @@ -238,7 +241,7 @@ public class NativeIPGateway extends VisPlugin implements MotePlugin { } /* Detect selected network interface */ - NetworkInterfaceW intf = + NetworkInterfaceW intf = (NetworkInterfaceW) ((JComboBox)e.getSource()).getSelectedItem(); if (networkInterface == intf) { /* Already selected */ @@ -546,7 +549,7 @@ public class NativeIPGateway extends VisPlugin implements MotePlugin { final JDialog progressDialog; if (GUI.isVisualized()) { progressDialog = new JDialog( - (Window)GUI.getTopParentContainer(), + (Window)GUI.getTopParentContainer(), "Starting Native IP Gateway plugin" ); } else { @@ -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; @@ -613,7 +616,7 @@ public class NativeIPGateway extends VisPlugin implements MotePlugin { } }); Runtime.getRuntime().addShutdownHook(shutdownHook); - + /* Waiting some time - otherwise pcap may not discover the new interface */ Thread.sleep(250); @@ -622,7 +625,7 @@ public class NativeIPGateway extends VisPlugin implements MotePlugin { logger.fatal("Error when creating tap0: " + e.getMessage()); logger.fatal("Try using an already existing network interface"); } - + /* Hide progress bar */ if (GUI.isVisualized()) { new RunnableInEDT() { @@ -1007,7 +1010,7 @@ public class NativeIPGateway extends VisPlugin implements MotePlugin { } deleteTunInterface(); - + if (shutdownHook != null) { Runtime.getRuntime().removeShutdownHook(shutdownHook); shutdownHook = null; diff --git a/tools/cooja/java/se/sics/cooja/GUI.java b/tools/cooja/java/se/sics/cooja/GUI.java index 29ef99eb2..3ef3b2217 100644 --- a/tools/cooja/java/se/sics/cooja/GUI.java +++ b/tools/cooja/java/se/sics/cooja/GUI.java @@ -2031,30 +2031,54 @@ public class GUI extends Observable { menuItem.putClientProperty("class", motePluginClass); menuItem.putClientProperty("mote", mote); - /* Check if mote plugin depends on any particular type of mote */ + /* Check mote plugin requirements */ boolean enableMenuItem = true; if (motePluginClass.getAnnotation(SupportedArguments.class) != null) { - enableMenuItem = false; - Class[] motes = motePluginClass.getAnnotation(SupportedArguments.class).motes(); - StringBuilder sb = new StringBuilder(); - sb.append( - "

This plugin:\n" +
-            motePluginClass.getName() +
-            "\ndoes not support motes of type:\n" +
-            mote.getClass().getName() +
-            "\n\nIt only supports motes of types:\n"
+        /* Check mote interfaces */
+        boolean moteInterfacesOK = true;
+        Class[] 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 o: motes) {
-          sb.append(o.getName() + "\n");
-          if (o.isAssignableFrom(mote.getClass())) {
-            enableMenuItem = true;
-            break;
+        for (Class requiredMoteInterface: moteInterfaces) {
+          moteTypeInterfacesError.append(getDescriptionOf(requiredMoteInterface) + "\n");
+          if (mote.getInterfaces().getInterfaceOfType(requiredMoteInterface) == null) {
+            moteInterfacesOK = false;
           }
         }
-        sb.append("");
-        if (!enableMenuItem) {
-          menuItem.setToolTipText(sb.toString());
+
+        /* Check mote type */
+        boolean moteTypeOK = false;
+        Class[] 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 supportedMote: motes) {
+          moteTypeError.append(getDescriptionOf(supportedMote) + "\n");
+          if (supportedMote.isAssignableFrom(mote.getClass())) {
+            moteTypeOK = true;
+          }
         }
+
+        if (!moteInterfacesOK) {
+          menuItem.setToolTipText(
+              "
" + moteTypeInterfacesError + ""
+          );
+        }
+        if (!moteTypeOK) {
+          menuItem.setToolTipText(
+              "
" + moteTypeError + ""
+          );
+        }
+        enableMenuItem = moteInterfacesOK && moteTypeOK;
       }
 
       menuItem.setEnabled(enableMenuItem);
diff --git a/tools/cooja/java/se/sics/cooja/SupportedArguments.java b/tools/cooja/java/se/sics/cooja/SupportedArguments.java
index fa09710cb..0b1d5ceed 100644
--- a/tools/cooja/java/se/sics/cooja/SupportedArguments.java
+++ b/tools/cooja/java/se/sics/cooja/SupportedArguments.java
@@ -61,4 +61,9 @@ public @interface SupportedArguments {
    * @return List of accepted radio medium classes.
    */
   Class[] radioMediums() default { RadioMedium.class };
+
+  /**
+   * @return List of required mote interfaces.
+   */
+  Class[] moteInterfaces() default { MoteInterface.class };
 }

From e78c77c965497f9fe3383ac3b69b87942b5c880d Mon Sep 17 00:00:00 2001
From: Fredrik Osterlind 
Date: Tue, 5 Jun 2012 14:51:47 +0200
Subject: [PATCH 16/19] minor bugfix: start/stop simulation keyboard shortcut
 was not enabled correctly

---
 tools/cooja/java/se/sics/cooja/GUI.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/cooja/java/se/sics/cooja/GUI.java b/tools/cooja/java/se/sics/cooja/GUI.java
index 3ef3b2217..07cbdc7f4 100644
--- a/tools/cooja/java/se/sics/cooja/GUI.java
+++ b/tools/cooja/java/se/sics/cooja/GUI.java
@@ -2631,6 +2631,7 @@ public class GUI extends Observable {
           mySimulation.addMote(newMote);
         }
       }
+      updateGUIComponentState();
 
     } else {
       logger.warn("No simulation active");

From a523127b6fa57dda73fb2b9d0cff292afab3279c Mon Sep 17 00:00:00 2001
From: Fredrik Osterlind 
Date: Tue, 5 Jun 2012 16:52:58 +0200
Subject: [PATCH 17/19] removed obsolete exit cooja keyboard shortcut from
 quick help

---
 tools/cooja/config/quickhelp.txt | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tools/cooja/config/quickhelp.txt b/tools/cooja/config/quickhelp.txt
index 18786b82d..cc6de2210 100644
--- a/tools/cooja/config/quickhelp.txt
+++ b/tools/cooja/config/quickhelp.txt
@@ -4,7 +4,6 @@ KEYBOARD_SHORTCUTS = \
 
Ctrl+S: Start/pause simulation\
Ctrl+R: Reload current simulation. If no simulation exists, the last used simulation config is loaded\
Ctrl+Shift+R: Reload current simulation with another random seed\ -
Ctrl+X: Quit COOJA\
\
F1: Toggle quick help From 26d7a8b4923c767e8b47fe46a05a80d7f5e4a4bd Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Tue, 5 Jun 2012 17:03:07 +0200 Subject: [PATCH 18/19] rewrote tools menu code to allow access to mote tools directly from the main menu mote tools can still be started from the network visualizer --- tools/cooja/java/se/sics/cooja/GUI.java | 479 ++++++++++++------------ 1 file changed, 236 insertions(+), 243 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/GUI.java b/tools/cooja/java/se/sics/cooja/GUI.java index 07cbdc7f4..603517821 100644 --- a/tools/cooja/java/se/sics/cooja/GUI.java +++ b/tools/cooja/java/se/sics/cooja/GUI.java @@ -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> menuMotePluginClasses; + private Vector> menuMotePluginClasses = new Vector>(); 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>(); - } /* 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,56 +921,118 @@ 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 pluginClass = (Class) 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) pluginClass, myGUI, getSimulation(), (Mote)mote); + } + }; + private JMenuItem createMenuItem(Class 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 */ - 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; - } + String tooltip = "
";
+        if (pluginType == PluginType.COOJA_PLUGIN || pluginType == PluginType.COOJA_STANDARD_PLUGIN) {
+          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[] radioMediums = pluginClass.getAnnotation(SupportedArguments.class).radioMediums();
+        /* Check if simulation plugin depends on any particular radio medium */
+        if (pluginType == PluginType.SIM_PLUGIN || pluginType == PluginType.SIM_STANDARD_PLUGIN) {
+          if (newPluginClass.getAnnotation(SupportedArguments.class) != null) {
+            boolean active = false;
+            Class[] radioMediums = newPluginClass.getAnnotation(SupportedArguments.class).radioMediums();
             for (Class 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 += "";
+        /*menuItem.setToolTipText(tooltip);*/
+        return menuItem;
+      }
+
+      public void menuSelected(MenuEvent e) {
+        /* Populate tools menu */
+        toolsMenu.removeAll();
+
+        /* Cooja plugins */
+        boolean hasCoojaPlugins = false;
+        for (Class 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 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 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) {
       }
@@ -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>();
-    }
     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 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 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 newPluginClass,
-      boolean addToMenu) {
+  public boolean registerPlugin(final Class 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;
+      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 {
-      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 });
+      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 find valid plugin type annotation in class " + newPluginClass);
+        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() {
-        public Boolean work() {
-          // Create 'start plugin'-menu item
-          JMenuItem menuItem;
-          String tooltip = "
";
-
-          /* 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 += "";
-          /*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();
-    }
+    menuMotePluginClasses.clear();
     pluginClasses.clear();
   }
 
@@ -2016,6 +1954,107 @@ public class GUI extends Observable {
     return startedPlugins.toArray(new Plugin[0]);
   }
 
+  private boolean isMotePluginCompatible(Class motePluginClass, Mote mote) {
+    if (motePluginClass.getAnnotation(SupportedArguments.class) == null) {
+      return true;
+    }
+
+    /* Check mote interfaces */
+    boolean moteInterfacesOK = true;
+    Class[] 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 requiredMoteInterface: moteInterfaces) {
+      moteTypeInterfacesError.append(getDescriptionOf(requiredMoteInterface) + "\n");
+      if (mote.getInterfaces().getInterfaceOfType(requiredMoteInterface) == null) {
+        moteInterfacesOK = false;
+      }
+    }
+
+    /* Check mote type */
+    boolean moteTypeOK = false;
+    Class[] 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 supportedMote: motes) {
+      moteTypeError.append(getDescriptionOf(supportedMote) + "\n");
+      if (supportedMote.isAssignableFrom(mote.getClass())) {
+        moteTypeOK = true;
+      }
+    }
+
+    /*if (!moteInterfacesOK) {
+      menuItem.setToolTipText(
+          "
" + moteTypeInterfacesError + ""
+      );
+    }
+    if (!moteTypeOK) {
+      menuItem.setToolTipText(
+          "
" + moteTypeError + ""
+      );
+    }*/
+
+    return moteInterfacesOK && moteTypeOK;
+  }
+
+  public JMenu createMotePluginsSubmenu(Class 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) 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,62 +2065,15 @@ public class GUI extends Observable {
     JMenu menuMotePlugins = new JMenu("Mote tools for " + mote);
 
     for (Class 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 mote plugin requirements */
-      boolean enableMenuItem = true;
-      if (motePluginClass.getAnnotation(SupportedArguments.class) != null) {
-        /* Check mote interfaces */
-        boolean moteInterfacesOK = true;
-        Class[] 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 requiredMoteInterface: moteInterfaces) {
-          moteTypeInterfacesError.append(getDescriptionOf(requiredMoteInterface) + "\n");
-          if (mote.getInterfaces().getInterfaceOfType(requiredMoteInterface) == null) {
-            moteInterfacesOK = false;
-          }
-        }
-
-        /* Check mote type */
-        boolean moteTypeOK = false;
-        Class[] 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 supportedMote: motes) {
-          moteTypeError.append(getDescriptionOf(supportedMote) + "\n");
-          if (supportedMote.isAssignableFrom(mote.getClass())) {
-            moteTypeOK = true;
-          }
-        }
-
-        if (!moteInterfacesOK) {
-          menuItem.setToolTipText(
-              "
" + moteTypeInterfacesError + ""
-          );
-        }
-        if (!moteTypeOK) {
-          menuItem.setToolTipText(
-              "
" + moteTypeError + ""
-          );
-        }
-        enableMenuItem = moteInterfacesOK && moteTypeOK;
-      }
-
-      menuItem.setEnabled(enableMenuItem);
       menuMotePlugins.add(menuItem);
     }
     return menuMotePlugins;
@@ -4528,8 +4520,8 @@ public class GUI extends Observable {
     }
   };
   class StartPluginGUIAction extends GUIAction {
-		private static final long serialVersionUID = 7368495576372376196L;
-		public StartPluginGUIAction(String name) {
+               private static final long serialVersionUID = 7368495576372376196L;
+               public StartPluginGUIAction(String name) {
       super(name);
     }
     public void actionPerformed(final ActionEvent e) {
@@ -4546,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) {

From 47db06503460f6cf49265be11628b883966d10d9 Mon Sep 17 00:00:00 2001
From: George Oikonomou 
Date: Wed, 6 Jun 2012 15:25:57 +0100
Subject: [PATCH 19/19] Bugfixed the cc253x UART0 init (Thanks, Deng Jian)

The flush instruction was resetting the stop bit level to 'low'
---
 cpu/cc253x/dev/uart0.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cpu/cc253x/dev/uart0.c b/cpu/cc253x/dev/uart0.c
index 85d0402c7..0e8ddb1d1 100644
--- a/cpu/cc253x/dev/uart0.c
+++ b/cpu/cc253x/dev/uart0.c
@@ -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);