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

This commit is contained in:
Adam Dunkels 2011-03-03 06:22:41 +01:00
commit bb86392ea0
44 changed files with 1014 additions and 742 deletions

0
apps/rest-coap/Makefile.rest-coap Executable file → Normal file
View file

0
apps/rest-common/Makefile.rest-common Executable file → Normal file
View file

0
apps/rest-common/rest.c Executable file → Normal file
View file

0
apps/rest-common/rest.h Executable file → Normal file
View file

0
apps/rest-http/Makefile.rest-http Executable file → Normal file
View file

0
apps/rest-http/http-common.c Executable file → Normal file
View file

0
apps/rest-http/http-common.h Executable file → Normal file
View file

0
apps/rest-http/http-server.c Executable file → Normal file
View file

0
apps/rest-http/http-server.h Executable file → Normal file
View file

0
core/cfs/cfs-coffee.c Executable file → Normal file
View file

View file

@ -459,6 +459,8 @@ dao_input(void)
uint8_t prefixlen; uint8_t prefixlen;
uint8_t flags; uint8_t flags;
uint8_t subopt_type; uint8_t subopt_type;
uint8_t pathcontrol;
uint8_t pathsequence;
uip_ipaddr_t prefix; uip_ipaddr_t prefix;
uip_ds6_route_t *rep; uip_ds6_route_t *rep;
uint8_t buffer_length; uint8_t buffer_length;
@ -523,7 +525,9 @@ dao_input(void)
break; break;
case RPL_DIO_SUBOPT_TRANSIT: case RPL_DIO_SUBOPT_TRANSIT:
/* path sequence and control ignored */ /* path sequence and control ignored */
lifetime = get32(buffer, i + 4); pathcontrol = buffer[i + 3];
pathsequence = buffer[i + 4];
lifetime = buffer[i + 5];
/* parent address also ignored */ /* parent address also ignored */
break; break;
} }
@ -571,7 +575,7 @@ dao_input(void)
PRINTF("RPL: Could not add a route after receiving a DAO\n"); PRINTF("RPL: Could not add a route after receiving a DAO\n");
return; return;
} else { } else {
rep->state.lifetime = lifetime; rep->state.lifetime = lifetime * dag->lifetime_unit;
rep->state.learned_from = learned_from; rep->state.learned_from = learned_from;
} }
@ -637,13 +641,13 @@ dao_output(rpl_parent_t *n, uint32_t lifetime)
memcpy(buffer + pos, &prefix, (prefixlen + 7) / CHAR_BIT); memcpy(buffer + pos, &prefix, (prefixlen + 7) / CHAR_BIT);
pos += ((prefixlen + 7) / CHAR_BIT); pos += ((prefixlen + 7) / CHAR_BIT);
/* create a transit information subopt */ /* create a transit information subopt (RPL-18)*/
buffer[pos++] = RPL_DIO_SUBOPT_TRANSIT; buffer[pos++] = RPL_DIO_SUBOPT_TRANSIT;
buffer[pos++] = 6; buffer[pos++] = 4;
buffer[pos++] = 0; /* path seq - ignored */ buffer[pos++] = 0; /* flags - ignored */
buffer[pos++] = 0; /* path control - ignored */ buffer[pos++] = 0; /* path control - ignored */
set32(buffer, pos, lifetime); buffer[pos++] = 0; /* path seq - ignored */
pos += 4; buffer[pos++] = (lifetime / dag->lifetime_unit) & 0xff;
if(n == NULL) { if(n == NULL) {
uip_create_linklocal_rplnodes_mcast(&addr); uip_create_linklocal_rplnodes_mcast(&addr);

View file

@ -205,7 +205,8 @@ handle_dao_timer(void *ptr)
fan-out as being under investigation. */ fan-out as being under investigation. */
if(dag->preferred_parent != NULL) { if(dag->preferred_parent != NULL) {
PRINTF("RPL: handle_dao_timer - sending DAO\n"); PRINTF("RPL: handle_dao_timer - sending DAO\n");
dao_output(dag->preferred_parent, DEFAULT_ROUTE_LIFETIME); /* set time to maxtime */
dao_output(dag->preferred_parent, dag->lifetime_unit * 0xffUL);
} else { } else {
PRINTF("RPL: Could not find a parent to send a DAO to \n"); PRINTF("RPL: Could not find a parent to send a DAO to \n");
} }

View file

@ -54,14 +54,24 @@ void uip_debug_lladdr_print(const uip_lladdr_t *addr);
#if (DEBUG) & DEBUG_ANNOTATE #if (DEBUG) & DEBUG_ANNOTATE
#include <stdio.h> #include <stdio.h>
#ifdef __AVR__
#include <avr/pgmspace.h>
#define ANNOTATE(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
#else
#define ANNOTATE(...) printf(__VA_ARGS__) #define ANNOTATE(...) printf(__VA_ARGS__)
#endif
#else #else
#define ANNOTATE(...) #define ANNOTATE(...)
#endif /* (DEBUG) & DEBUG_ANNOTATE */ #endif /* (DEBUG) & DEBUG_ANNOTATE */
#if (DEBUG) & DEBUG_PRINT #if (DEBUG) & DEBUG_PRINT
#include <stdio.h> #include <stdio.h>
#ifdef __AVR__
#include <avr/pgmspace.h>
#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
#else
#define PRINTF(...) printf(__VA_ARGS__) #define PRINTF(...) printf(__VA_ARGS__)
#endif
#define PRINT6ADDR(addr) uip_debug_ipaddr_print(addr) #define PRINT6ADDR(addr) uip_debug_ipaddr_print(addr)
#define PRINTLLADDR(lladdr) uip_debug_lladdr_print(lladdr) #define PRINTLLADDR(lladdr) uip_debug_lladdr_print(lladdr)
#else #else

0
core/net/uip-ds6.c Executable file → Normal file
View file

0
core/net/uip-ds6.h Executable file → Normal file
View file

0
examples/ipso-ipv6-raven/Makefile Executable file → Normal file
View file

0
examples/ipso-ipv6-raven/Makefile.ipso Executable file → Normal file
View file

0
examples/ipso-ipv6-raven/ipso.c Executable file → Normal file
View file

0
examples/ipv6/rpl-udp/rpl-udp.csc Executable file → Normal file
View file

0
examples/sky/test-coffee.c Executable file → Normal file
View file

View file

@ -31,15 +31,13 @@
* @(#)$$ * @(#)$$
*/ */
#define ANNOUNCE_BOOT 1 //adds about 600 bytes to program size #define ANNOUNCE_BOOT 1 //adds about 600 bytes to program size
#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
#define DEBUG 0 #define DEBUG 0
#if DEBUG #if DEBUG
#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) #define PRINTFD(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
#define PRINTSHORT(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
#else #else
#define PRINTF(...) #define PRINTFD(...)
#define PRINTSHORT(...)
#endif #endif
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
@ -95,6 +93,22 @@
#include "net/rime.h" #include "net/rime.h"
/* Test rtimers, also for pings, stack monitor, neighbor/route printout and time stamps */
#define TESTRTIMER 0
#if TESTRTIMER
//#define PINGS 64
#define ROUTES 64
#define STAMPS 30
#define STACKMONITOR 128
uint8_t rtimerflag=1;
uint16_t rtime;
struct rtimer rt;
void rtimercycle(void) {rtimerflag=1;}
static void ipaddr_add(const uip_ipaddr_t *addr);
#endif /* TESTRTIMER */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/*----------------------Configuration of the .elf file---------------------*/ /*----------------------Configuration of the .elf file---------------------*/
typedef struct {unsigned char B2;unsigned char B1;unsigned char B0;} __signature_t; typedef struct {unsigned char B2;unsigned char B1;unsigned char B0;} __signature_t;
@ -166,13 +180,6 @@ void initialize(void)
watchdog_init(); watchdog_init();
watchdog_start(); watchdog_start();
#define CONFIG_STACK_MONITOR 1
#if CONFIG_STACK_MONITOR
extern uint16_t __bss_end;
__bss_end = 0x4242;
*(uint16_t *)(&__bss_end+100) = 0x4242;
#endif
#ifdef RAVEN_LCD_INTERFACE #ifdef RAVEN_LCD_INTERFACE
/* First rs232 port for Raven 3290 port */ /* First rs232 port for Raven 3290 port */
rs232_init(RS232_PORT_0, USART_BAUD_38400,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8); rs232_init(RS232_PORT_0, USART_BAUD_38400,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8);
@ -185,16 +192,31 @@ extern uint16_t __bss_end;
/* Redirect stdout to second port */ /* Redirect stdout to second port */
rs232_redirect_stdout(RS232_PORT_1); rs232_redirect_stdout(RS232_PORT_1);
clock_init(); clock_init();
#if STACKMONITOR
/* Simple stack pointer highwater monitor. Checks for magic numbers in the main
* loop. In conjuction with TESTRTIMER, never-used stack will be printed
* every STACKMONITOR seconds.
*/
{
extern uint16_t __bss_end;
uint16_t p=(uint16_t)&__bss_end;
do {
*(uint16_t *)p = 0x4242;
p+=10;
} while (p<SP-10); //don't overwrite our own stack
}
#endif
#define CONF_CALIBRATE_OSCCAL 0 #define CONF_CALIBRATE_OSCCAL 0
#if CONF_CALIBRATE_OSCCAL #if CONF_CALIBRATE_OSCCAL
{ {
extern uint8_t osccal_calibrated; extern uint8_t osccal_calibrated;
uint8_t i; uint8_t i;
printf_P(PSTR("\nBefore calibration OSCCAL=%x\n"),OSCCAL); PRINTF("\nBefore calibration OSCCAL=%x\n",OSCCAL);
for (i=0;i<10;i++) { for (i=0;i<10;i++) {
calibrate_rc_osc_32k(); calibrate_rc_osc_32k();
printf_P(PSTR("Calibrated=%x\n"),osccal_calibrated); PRINTF("Calibrated=%x\n",osccal_calibrated);
//#include <util/delay_basic.h> //#include <util/delay_basic.h>
//#define delay_us( us ) ( _delay_loop_2(1+(us*F_CPU)/4000000UL) ) //#define delay_us( us ) ( _delay_loop_2(1+(us*F_CPU)/4000000UL) )
// delay_us(50000); // delay_us(50000);
@ -204,7 +226,7 @@ uint8_t i;
#endif #endif
#if ANNOUNCE_BOOT #if ANNOUNCE_BOOT
printf_P(PSTR("\n*******Booting %s*******\n"),CONTIKI_VERSION_STRING); PRINTF("\n*******Booting %s*******\n",CONTIKI_VERSION_STRING);
#endif #endif
/* rtimers needed for radio cycling */ /* rtimers needed for radio cycling */
@ -239,7 +261,7 @@ uint8_t i;
rimeaddr_set_node_addr(&addr); rimeaddr_set_node_addr(&addr);
PRINTF("MAC address %x:%x:%x:%x:%x:%x:%x:%x\n",addr.u8[0],addr.u8[1],addr.u8[2],addr.u8[3],addr.u8[4],addr.u8[5],addr.u8[6],addr.u8[7]); PRINTFD("MAC address %x:%x:%x:%x:%x:%x:%x:%x\n",addr.u8[0],addr.u8[1],addr.u8[2],addr.u8[3],addr.u8[4],addr.u8[5],addr.u8[6],addr.u8[7]);
/* Initialize stack protocols */ /* Initialize stack protocols */
queuebuf_init(); queuebuf_init();
@ -248,27 +270,31 @@ uint8_t i;
NETSTACK_NETWORK.init(); NETSTACK_NETWORK.init();
#if ANNOUNCE_BOOT #if ANNOUNCE_BOOT
printf_P(PSTR("%s %s, channel %u"),NETSTACK_MAC.name, NETSTACK_RDC.name,rf230_get_channel()); PRINTF("%s %s, channel %u",NETSTACK_MAC.name, NETSTACK_RDC.name,rf230_get_channel());
if (NETSTACK_RDC.channel_check_interval) {//function pointer is zero for sicslowmac if (NETSTACK_RDC.channel_check_interval) {//function pointer is zero for sicslowmac
unsigned short tmp; unsigned short tmp;
tmp=CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval == 0 ? 1:\ tmp=CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval == 0 ? 1:\
NETSTACK_RDC.channel_check_interval()); NETSTACK_RDC.channel_check_interval());
if (tmp<65535) printf_P(PSTR(", check rate %u Hz"),tmp); if (tmp<65535) printf_P(PSTR(", check rate %u Hz"),tmp);
} }
printf_P(PSTR("\n")); PRINTF("\n");
#if UIP_CONF_IPV6_RPL
PRINTF("RPL Enabled\n");
#endif
#if UIP_CONF_ROUTER
PRINTF("Routing Enabled\n");
#endif #endif
#if UIP_CONF_ROUTER #endif /* ANNOUNCE_BOOT */
#if ANNOUNCE_BOOT
printf_P(PSTR("Routing Enabled\n")); // rime_init(rime_udp_init(NULL));
#endif
// rime_init(rime_udp_init(NULL));
// uip_router_register(&rimeroute); // uip_router_register(&rimeroute);
#endif
process_start(&tcpip_process, NULL); process_start(&tcpip_process, NULL);
#else #else
/* Original RF230 combined mac/radio driver */
/* mac process must be started before tcpip process! */ /* mac process must be started before tcpip process! */
process_start(&mac_process, NULL); process_start(&mac_process, NULL);
process_start(&tcpip_process, NULL); process_start(&tcpip_process, NULL);
@ -288,13 +314,13 @@ uint8_t i;
#if COFFEE_FILES #if COFFEE_FILES
int fa = cfs_open( "/index.html", CFS_READ); int fa = cfs_open( "/index.html", CFS_READ);
if (fa<0) { //Make some default web content if (fa<0) { //Make some default web content
printf_P(PSTR("No index.html file found, creating upload.html!\n")); PRINTF("No index.html file found, creating upload.html!\n");
printf_P(PSTR("Formatting FLASH file system for coffee...")); PRINTF("Formatting FLASH file system for coffee...");
cfs_coffee_format(); cfs_coffee_format();
printf_P(PSTR("Done!\n")); PRINTF("Done!\n");
fa = cfs_open( "/index.html", CFS_WRITE); fa = cfs_open( "/index.html", CFS_WRITE);
int r = cfs_write(fa, &"It works!", 9); int r = cfs_write(fa, &"It works!", 9);
if (r<0) printf_P(PSTR("Can''t create /index.html!\n")); if (r<0) PRINTF("Can''t create /index.html!\n");
cfs_close(fa); cfs_close(fa);
// fa = cfs_open("upload.html"), CFW_WRITE); // fa = cfs_open("upload.html"), CFW_WRITE);
// <html><body><form action="upload.html" enctype="multipart/form-data" method="post"><input name="userfile" type="file" size="50" /><input value="Upload" type="submit" /></form></body></html> // <html><body><form action="upload.html" enctype="multipart/form-data" method="post"><input name="userfile" type="file" size="50" /><input value="Upload" type="submit" /></form></body></html>
@ -322,53 +348,38 @@ uint8_t i;
for (i=0;i<UIP_DS6_ADDR_NB;i++) { for (i=0;i<UIP_DS6_ADDR_NB;i++) {
if (uip_ds6_if.addr_list[i].isused) { if (uip_ds6_if.addr_list[i].isused) {
httpd_cgi_sprint_ip6(uip_ds6_if.addr_list[i].ipaddr,buf); httpd_cgi_sprint_ip6(uip_ds6_if.addr_list[i].ipaddr,buf);
printf_P(PSTR("IPv6 Address: %s\n"),buf); PRINTF("IPv6 Address: %s\n",buf);
} }
} }
eeprom_read_block (buf,server_name, sizeof(server_name)); eeprom_read_block (buf,server_name, sizeof(server_name));
buf[sizeof(server_name)]=0; buf[sizeof(server_name)]=0;
printf_P(PSTR("%s"),buf); PRINTF("%s",buf);
eeprom_read_block (buf,domain_name, sizeof(domain_name)); eeprom_read_block (buf,domain_name, sizeof(domain_name));
buf[sizeof(domain_name)]=0; buf[sizeof(domain_name)]=0;
size=httpd_fs_get_size(); size=httpd_fs_get_size();
#ifndef COFFEE_FILES #ifndef COFFEE_FILES
printf_P(PSTR(".%s online with fixed %u byte web content\n"),buf,size); PRINTF(".%s online with fixed %u byte web content\n",buf,size);
#elif COFFEE_FILES==1 #elif COFFEE_FILES==1
printf_P(PSTR(".%s online with static %u byte EEPROM file system\n"),buf,size); PRINTF(".%s online with static %u byte EEPROM file system\n",buf,size);
#elif COFFEE_FILES==2 #elif COFFEE_FILES==2
printf_P(PSTR(".%s online with dynamic %u KB EEPROM file system\n"),buf,size>>10); PRINTF(".%s online with dynamic %u KB EEPROM file system\n",buf,size>>10);
#elif COFFEE_FILES==3 #elif COFFEE_FILES==3
printf_P(PSTR(".%s online with static %u byte program memory file system\n"),buf,size); PRINTF(".%s online with static %u byte program memory file system\n",buf,size);
#elif COFFEE_FILES==4 #elif COFFEE_FILES==4
printf_P(PSTR(".%s online with dynamic %u KB program memory file system\n"),buf,size>>10); PRINTF(".%s online with dynamic %u KB program memory file system\n",buf,size>>10);
#endif /* COFFEE_FILES */ #endif /* COFFEE_FILES */
#else #else
printf_P(PSTR("Online\n")); PRINTF("Online\n");
#endif /* WEBSERVER */ #endif /* WEBSERVER */
#endif /* ANNOUNCE_BOOT */ #endif /* ANNOUNCE_BOOT */
} }
/*---------------------------------------------------------------------------*/
void log_message(char *m1, char *m2)
{
printf_P(PSTR("%s%s\n"), m1, m2);
}
/* Test rtimers, also useful for pings and time stamps in simulator */
#define TESTRTIMER 0
#if TESTRTIMER
#define PINGS 60
#define STAMPS 30
uint8_t rtimerflag=1;
uint16_t rtime;
struct rtimer rt;
void rtimercycle(void) {rtimerflag=1;}
#endif /* TESTRTIMER */
#if RF230BB #if RF230BB
extern char rf230_interrupt_flag, rf230processflag; extern char rf230_interrupt_flag, rf230processflag;
#endif #endif
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/*------------------------- Main Scheduler loop----------------------------*/ /*------------------------- Main Scheduler loop----------------------------*/
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -379,68 +390,130 @@ main(void)
while(1) { while(1) {
process_run(); process_run();
watchdog_periodic();
#if CONFIG_STACK_MONITOR
extern uint16_t __bss_end; #if 0
if (*(uint16_t *)(&__bss_end+100) != 0x4242) { /* Various entry points for debugging in the AVR Studio simulator.
printf_P(PSTR("\nStack Warning, overflow within 100 bytes!\n")); * Set as next statement and step into the routine.
if (__bss_end != 0x4242) { */
__bss_end = 0x4242; NETSTACK_RADIO.send(packetbuf_hdrptr(), 42);
printf_P(PSTR("\n!!!!!!!Stack Overflow!!!!!!!!\n")); process_poll(&rf230_process);
} packetbuf_clear();
*(uint16_t *)(&__bss_end+100) = 0x4242; len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);
} packetbuf_set_datalen(42);
NETSTACK_RDC.input();
#endif #endif
#if 0 #if 0
/* Clock.c can trigger a periodic RF PLL calibration */ /* Clock.c can trigger a periodic PLL calibration in the RF230BB driver.
extern uint8_t rf230_calibrated; * This can show when that happens.
*/
extern uint8_t rf230_calibrated;
if (rf230_calibrated) { if (rf230_calibrated) {
printf_P(PSTR("\nRF230 calibrated!")); PRINTF("\nRF230 calibrated!\n");
rf230_calibrated=0; rf230_calibrated=0;
} }
#endif #endif
//Various entry points for debugging in AVR simulator
// NETSTACK_RADIO.send(packetbuf_hdrptr(), 42);
// process_poll(&rf230_process);
// packetbuf_clear();
// len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);
// packetbuf_set_datalen(42);
// NETSTACK_RDC.input();
watchdog_periodic();
#if TESTRTIMER #if TESTRTIMER
if (rtimerflag) { //8 seconds is maximum interval, my raven 6% slow /* Timeout can be increased up to 8 seconds maximum.
* A one second cycle is convenient for triggering the various debug printouts.
* The triggers are staggered to avoid printing everything at once.
* My raven is 6% slow.
*/
if (rtimerflag) {
rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL);
rtimerflag=0; rtimerflag=0;
#if STAMPS #if STAMPS
if ((rtime%STAMPS)==0) { if ((rtime%STAMPS)==0) {
printf("%us ",rtime); PRINTF("%us ",rtime);
} }
#endif #endif
rtime+=1; rtime+=1;
#if PINGS #if PINGS
if ((rtime%PINGS)==0) { if ((rtime%PINGS)==1) {
PRINTF("**Ping\n"); PRINTF("**Ping\n");
raven_ping6(); raven_ping6();
} }
#endif #endif
#if ROUTES
if ((rtime%ROUTES)==2) {
//#if UIP_CONF_IPV6_RPL
//#include "rpl.h"
extern uip_ds6_nbr_t uip_ds6_nbr_cache[];
extern uip_ds6_route_t uip_ds6_routing_table[];
extern uip_ds6_netif_t uip_ds6_if;
uint8_t i,j;
PRINTF("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB);
for (i=0;i<UIP_DS6_ADDR_NB;i++) {
if (uip_ds6_if.addr_list[i].isused) {
ipaddr_add(&uip_ds6_if.addr_list[i].ipaddr);
PRINTF("\n");
} }
}
PRINTF("\nNeighbors [%u max]\n",UIP_DS6_NBR_NB);
for(i = 0,j=1; i < UIP_DS6_NBR_NB; i++) {
if(uip_ds6_nbr_cache[i].isused) {
ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr);
PRINTF("\n");
j=0;
}
}
if (j) PRINTF(" <none>");
PRINTF("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB);
for(i = 0,j=1; i < UIP_DS6_ROUTE_NB; i++) {
if(uip_ds6_routing_table[i].isused) {
ipaddr_add(&uip_ds6_routing_table[i].ipaddr);
PRINTF("/%u (via ", uip_ds6_routing_table[i].length);
ipaddr_add(&uip_ds6_routing_table[i].nexthop);
// if(uip_ds6_routing_table[i].state.lifetime < 600) {
PRINTF(") %lus\n", uip_ds6_routing_table[i].state.lifetime);
// } else {
// PRINTF(")\n");
// }
j=0;
}
}
if (j) PRINTF(" <none>");
PRINTF("\n---------\n");
}
#endif #endif
#if STACKMONITOR
if ((rtime%STACKMONITOR)==3) {
extern uint16_t __bss_end;
uint16_t p=(uint16_t)&__bss_end;
do {
if (*(uint16_t *)p != 0x4242) {
PRINTF("Never-used stack > %d bytes\n",p-(uint16_t)&__bss_end);
break;
}
p+=10;
} while (p<RAMEND-10);
}
#endif
}
#endif /* TESTRTIMER */
//Use with RF230BB DEBUGFLOW to show path through driver //Use with RF230BB DEBUGFLOW to show path through driver
#if RF230BB&&0 #if RF230BB&&0
extern uint8_t debugflowsize,debugflow[]; extern uint8_t debugflowsize,debugflow[];
if (debugflowsize) { if (debugflowsize) {
debugflow[debugflowsize]=0; debugflow[debugflowsize]=0;
printf("%s",debugflow); PRINTF("%s",debugflow);
debugflowsize=0; debugflowsize=0;
} }
#endif #endif
#if RF230BB&&0 #if RF230BB&&0
if (rf230processflag) { if (rf230processflag) {
printf("rf230p%d",rf230processflag); PRINTF("rf230p%d",rf230processflag);
rf230processflag=0; rf230processflag=0;
} }
#endif #endif
@ -448,7 +521,7 @@ extern uint8_t debugflowsize,debugflow[];
#if RF230BB&&0 #if RF230BB&&0
if (rf230_interrupt_flag) { if (rf230_interrupt_flag) {
// if (rf230_interrupt_flag!=11) { // if (rf230_interrupt_flag!=11) {
PRINTSHORT("**RI%u",rf230_interrupt_flag); PRINTF("**RI%u",rf230_interrupt_flag);
// } // }
rf230_interrupt_flag=0; rf230_interrupt_flag=0;
} }
@ -456,3 +529,32 @@ extern uint8_t debugflowsize,debugflow[];
} }
return 0; return 0;
} }
/*---------------------------------------------------------------------------*/
void log_message(char *m1, char *m2)
{
PRINTF("%s%s\n", m1, m2);
}
#if ROUTES
static void
ipaddr_add(const uip_ipaddr_t *addr)
{
uint16_t a;
int8_t i, f;
for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
a = (addr->u8[i] << 8) + addr->u8[i + 1];
if(a == 0 && f >= 0) {
if(f++ == 0) PRINTF("::");
} else {
if(f > 0) {
f = -1;
} else if(i > 0) {
PRINTF(":");
}
PRINTF("%x",a);
}
}
}
#endif

0
platform/micaz/Makefile.micaz Executable file → Normal file
View file

0
platform/micaz/apps/Makefile Executable file → Normal file
View file

0
platform/micaz/apps/mts310/Makefile Executable file → Normal file
View file

0
platform/micaz/apps/mts310/accel-test.c Executable file → Normal file
View file

0
platform/micaz/apps/mts310/magnet-test.c Executable file → Normal file
View file

0
platform/micaz/apps/mts310/mic-test.c Executable file → Normal file
View file

0
platform/micaz/dev/adc.c Executable file → Normal file
View file

0
platform/micaz/dev/adc.h Executable file → Normal file
View file

0
platform/micaz/dev/ds2401.h Executable file → Normal file
View file

0
platform/micaz/dev/sensors/battery-sensor.c Executable file → Normal file
View file

0
platform/msb430/dev/sd-arch.c Executable file → Normal file
View file

0
platform/msb430/dev/sd-arch.h Executable file → Normal file
View file

0
platform/msb430/dev/sd.c Executable file → Normal file
View file

View file

0
tools/cooja/examples/jni_test/mac_users/nmandsize Normal file → Executable file
View file

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009, Swedish Institute of Computer Science. * Copyright (c) 2010, Swedish Institute of Computer Science.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -32,9 +32,13 @@
package se.sics.cooja.plugins; package se.sics.cooja.plugins;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.MouseEvent; import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Observable; import java.util.Observable;
import java.util.Observer; import java.util.Observer;
@ -42,12 +46,14 @@ import javax.swing.DefaultCellEditor;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JComboBox; import javax.swing.JComboBox;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTable; import javax.swing.JTable;
import javax.swing.ListSelectionModel; import javax.swing.ListSelectionModel;
import javax.swing.SpinnerNumberModel; import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellEditor;
@ -60,8 +66,12 @@ import se.sics.cooja.Mote;
import se.sics.cooja.PluginType; import se.sics.cooja.PluginType;
import se.sics.cooja.Simulation; import se.sics.cooja.Simulation;
import se.sics.cooja.VisPlugin; import se.sics.cooja.VisPlugin;
import se.sics.cooja.interfaces.Radio;
import se.sics.cooja.radiomediums.AbstractRadioMedium;
import se.sics.cooja.radiomediums.DGRMDestinationRadio;
import se.sics.cooja.radiomediums.DirectedGraphMedium; import se.sics.cooja.radiomediums.DirectedGraphMedium;
import se.sics.cooja.radiomediums.DirectedGraphMedium.DGRMDestinationRadio; import se.sics.cooja.radiomediums.DirectedGraphMedium.Edge;
import se.sics.cooja.util.StringUtils;
/** /**
* Simple user interface for configuring edges for the Directed Graph * Simple user interface for configuring edges for the Directed Graph
@ -70,18 +80,19 @@ import se.sics.cooja.radiomediums.DirectedGraphMedium.DGRMDestinationRadio;
* @see DirectedGraphMedium * @see DirectedGraphMedium
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
@ClassDescription("DGRM Configurator") @ClassDescription("DGRM Links")
@PluginType(PluginType.SIM_PLUGIN) @PluginType(PluginType.SIM_PLUGIN)
public class DGRMConfigurator extends VisPlugin { public class DGRMConfigurator extends VisPlugin {
private static Logger logger = Logger.getLogger(DGRMConfigurator.class); private static final long serialVersionUID = 4769638341635882051L;
private static Logger logger = Logger.getLogger(DGRMConfigurator.class);
private final static int IDX_SRC = 0; private final static int IDX_SRC = 0;
private final static int IDX_DST = 1; private final static int IDX_DST = 1;
private final static int IDX_RATIO = 2; private final static int IDX_RATIO = 2;
private final static int IDX_DELAY = 3; private final static int IDX_SIGNAL = 3;
private final static int IDX_DEL = 4; private final static int IDX_DELAY = 4;
private final static String[] columns = new String[] { private final static String[] COLUMN_NAMES = new String[] {
"Source", "Destination", "Success Ratio (%)", "Delay (ms)", "Delete" "Source", "Destination", "RX Ratio", "RSSI", "Delay"
}; };
private GUI gui = null; private GUI gui = null;
@ -89,12 +100,11 @@ public class DGRMConfigurator extends VisPlugin {
private Observer radioMediumObserver; private Observer radioMediumObserver;
private JTable graphTable = null; private JTable graphTable = null;
private JComboBox combo = new JComboBox(); private JComboBox combo = new JComboBox();
private JButton removeButton;
public DGRMConfigurator(Simulation sim, GUI gui) { public DGRMConfigurator(Simulation sim, GUI gui) {
super("DGRM Configurator", gui); super("DGRM Configurator", gui);
this.gui = gui; this.gui = gui;
radioMedium = (DirectedGraphMedium) sim.getRadioMedium(); radioMedium = (DirectedGraphMedium) sim.getRadioMedium();
/* Listen for graph updates */ /* Listen for graph updates */
@ -106,55 +116,53 @@ public class DGRMConfigurator extends VisPlugin {
/* Represent directed graph by table */ /* Represent directed graph by table */
graphTable = new JTable(model) { graphTable = new JTable(model) {
public TableCellEditor getCellEditor(int row, int column) { private static final long serialVersionUID = -4680013510092815210L;
public TableCellEditor getCellEditor(int row, int column) {
combo.removeAllItems();
if (column == IDX_RATIO) { if (column == IDX_RATIO) {
combo.removeAllItems(); for (double d=1.0; d >= 0.0; d -= 0.1) {
combo.addItem(1.0); combo.addItem(d);
combo.addItem(0.9); }
combo.addItem(0.8); } else if (column == IDX_SIGNAL) {
combo.addItem(0.7); for (double d=AbstractRadioMedium.SS_STRONG; d >= AbstractRadioMedium.SS_WEAK; d -= 1) {
combo.addItem(0.6); combo.addItem((int) d);
combo.addItem(0.5); }
combo.addItem(0.4); } else if (column == IDX_DELAY) {
combo.addItem(0.3); for (double d=0; d <= 5; d++) {
combo.addItem(0.2); combo.addItem(d);
combo.addItem(0.1); }
combo.addItem(0.0);
} }
if (column == IDX_DELAY) {
combo.removeAllItems();
combo.addItem(0);
combo.addItem(1);
combo.addItem(2);
combo.addItem(3);
combo.addItem(4);
combo.addItem(5);
}
return super.getCellEditor(row, column); return super.getCellEditor(row, column);
} }
public String getToolTipText(MouseEvent e) {
java.awt.Point p = e.getPoint();
int row = rowAtPoint(p);
int col = convertColumnIndexToModel(columnAtPoint(p));
/* TODO */
return super.getToolTipText();
}
}; };
graphTable.setFillsViewportHeight(true);
combo.setEditable(true); combo.setEditable(true);
graphTable.getColumnModel().getColumn(IDX_RATIO).setCellRenderer(new DefaultTableCellRenderer() { graphTable.getColumnModel().getColumn(IDX_RATIO).setCellRenderer(new DefaultTableCellRenderer() {
public void setValue(Object value) { private static final long serialVersionUID = 4470088575039698508L;
public void setValue(Object value) {
if (!(value instanceof Double)) { if (!(value instanceof Double)) {
setText(value.toString()); setText(value.toString());
return; return;
} }
double v = ((Double) value).doubleValue(); double v = ((Double) value).doubleValue();
setText((Math.round(v*1000.0) / 10.0) + "%"); setText(String.format("%1.1f%%", 100*v));
}
});
graphTable.getColumnModel().getColumn(IDX_SIGNAL).setCellRenderer(new DefaultTableCellRenderer() {
private static final long serialVersionUID = -7170745293267593460L;
public void setValue(Object value) {
if (!(value instanceof Long)) {
setText(value.toString());
return;
}
double v = ((Double) value).doubleValue();
setText(String.format("%1.1f dBm", v));
} }
}); });
graphTable.getColumnModel().getColumn(IDX_DELAY).setCellRenderer(new DefaultTableCellRenderer() { graphTable.getColumnModel().getColumn(IDX_DELAY).setCellRenderer(new DefaultTableCellRenderer() {
public void setValue(Object value) { private static final long serialVersionUID = -4669897764928372246L;
public void setValue(Object value) {
if (!(value instanceof Long)) { if (!(value instanceof Long)) {
setText(value.toString()); setText(value.toString());
return; return;
@ -164,21 +172,50 @@ public class DGRMConfigurator extends VisPlugin {
} }
}); });
graphTable.getColumnModel().getColumn(IDX_RATIO).setCellEditor(new DefaultCellEditor(combo)); graphTable.getColumnModel().getColumn(IDX_RATIO).setCellEditor(new DefaultCellEditor(combo));
graphTable.getColumnModel().getColumn(IDX_SIGNAL).setCellEditor(new DefaultCellEditor(combo));
graphTable.getColumnModel().getColumn(IDX_DELAY).setCellEditor(new DefaultCellEditor(combo)); graphTable.getColumnModel().getColumn(IDX_DELAY).setCellEditor(new DefaultCellEditor(combo));
graphTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); graphTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
graphTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); graphTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JPanel southPanel = new JPanel(new GridLayout(1, 3));
JButton button = new JButton("Add"); JButton button = new JButton("Add");
button.addActionListener(new ActionListener() { button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
doAddLink(); doAddLink();
} }
}); });
final JScrollPane scrollPane = new JScrollPane(graphTable); southPanel.add(button);
button = new JButton("Remove");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
doRemoveSelectedLink();
}
});
removeButton = button;
removeButton.setEnabled(false);
southPanel.add(button);
button = new JButton("Import");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
doImportFromFile();
}
});
southPanel.add(button);
getContentPane().setLayout(new BorderLayout()); getContentPane().setLayout(new BorderLayout());
add(BorderLayout.CENTER, scrollPane); add(BorderLayout.CENTER, new JScrollPane(graphTable));
add(BorderLayout.SOUTH, button); add(BorderLayout.SOUTH, southPanel);
graphTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
if (e.getValueIsAdjusting()) {
return;
}
removeButton.setEnabled(!lsm.isSelectionEmpty());
}
});
model.fireTableDataChanged(); model.fireTableDataChanged();
setSize(400, 300); setSize(400, 300);
@ -186,29 +223,18 @@ public class DGRMConfigurator extends VisPlugin {
private void doAddLink() { private void doAddLink() {
JComboBox source = new JComboBox(); JComboBox source = new JComboBox();
for (int i=0; i < gui.getSimulation().getMotesCount(); i++) {
source.addItem(gui.getSimulation().getMote(i));
}
JComboBox dest = new JComboBox(); JComboBox dest = new JComboBox();
for (int i=0; i < gui.getSimulation().getMotesCount(); i++) { for (Mote m: gui.getSimulation().getMotes()) {
dest.addItem(gui.getSimulation().getMote(i)); source.addItem(m);
dest.addItem(m);
} }
dest.addItem("ALL");
JSpinner ratio = new JSpinner(new SpinnerNumberModel(1.0, 0.0, 1.0, 0.01));
JSpinner delay = new JSpinner(new SpinnerNumberModel(0, 0, 100, 1));
/* User input */ /* User input */
Object description[] = { Object description[] = {
columns[0], COLUMN_NAMES[0],
source, source,
columns[1], COLUMN_NAMES[1],
dest, dest
columns[2],
ratio,
columns[3],
delay
}; };
JOptionPane optionPane = new JOptionPane(); JOptionPane optionPane = new JOptionPane();
optionPane.setMessage(description); optionPane.setMessage(description);
@ -216,34 +242,20 @@ public class DGRMConfigurator extends VisPlugin {
String options[] = new String[] {"Cancel", "Add"}; String options[] = new String[] {"Cancel", "Add"};
optionPane.setOptions(options); optionPane.setOptions(options);
optionPane.setInitialValue(options[1]); optionPane.setInitialValue(options[1]);
JDialog dialog = optionPane.createDialog(gui.getTopParentContainer(), title); JDialog dialog = optionPane.createDialog(this, title);
dialog.setTitle("Add new link"); dialog.setTitle("Add graph edge");
dialog.setVisible(true); dialog.setVisible(true);
if (optionPane.getValue() == null || !optionPane.getValue().equals("Add")) { if (optionPane.getValue() == null || !optionPane.getValue().equals("Add")) {
return; return;
} }
/* Register new edge with radio medium */ /* Register new edge with radio medium */
DirectedGraphMedium.Edge newEdge; DirectedGraphMedium.Edge newEdge = new DirectedGraphMedium.Edge(
if (dest.getSelectedItem() instanceof Mote) { ((Mote) source.getSelectedItem()).getInterfaces().getRadio(),
newEdge = new DirectedGraphMedium.Edge( new DGRMDestinationRadio(
((Mote) source.getSelectedItem()).getInterfaces().getRadio(), ((Mote) dest.getSelectedItem()).getInterfaces().getRadio()
new DGRMDestinationRadio( )
((Mote) dest.getSelectedItem()).getInterfaces().getRadio(), );
((Number)ratio.getValue()).doubleValue(),
((Number)delay.getValue()).longValue()
)
);
} else {
newEdge = new DirectedGraphMedium.Edge(
((Mote) source.getSelectedItem()).getInterfaces().getRadio(),
new DGRMDestinationRadio(
null,
((Number)ratio.getValue()).doubleValue(),
((Number)delay.getValue()).longValue()
)
);
}
radioMedium.addEdge(newEdge); radioMedium.addEdge(newEdge);
model.fireTableDataChanged(); model.fireTableDataChanged();
} }
@ -252,98 +264,180 @@ public class DGRMConfigurator extends VisPlugin {
radioMedium.removeEdge(edge); radioMedium.removeEdge(edge);
model.fireTableDataChanged(); model.fireTableDataChanged();
} }
private void doRemoveSelectedLink() {
int firstIndex = graphTable.getSelectedRow();
if (firstIndex < 0) {
return;
}
final AbstractTableModel model = new AbstractTableModel() { doRemoveLink(radioMedium.getEdges()[firstIndex]);
public String getColumnName(int column) { }
if (column < 0 || column >= columns.length) { private void doImportFromFile() {
logger.fatal("Unknown column: " + column); /* Delete existing edges */
return ""; if (radioMedium.getEdges().length > 0) {
String[] options = new String[] { "Remove", "Cancel" };
int n = JOptionPane.showOptionDialog(
GUI.getTopParentContainer(),
"Importing edges will remove all your existing edges.",
"Clear edge table?", JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE, null, options, options[0]);
if (n != JOptionPane.YES_OPTION) {
return;
}
for (DirectedGraphMedium.Edge e: radioMedium.getEdges()) {
radioMedium.removeEdge(e);
} }
return columns[column];
} }
/* Select file to import edges from */
JFileChooser fc = new JFileChooser();
File suggest = new File(GUI.getExternalToolsSetting("DGRM_IMPORT_LINKS_FILE", "cooja_dgrm_links.dat"));
fc.setSelectedFile(suggest);
int returnVal = fc.showOpenDialog(GUI.getTopParentContainer());
if (returnVal != JFileChooser.APPROVE_OPTION) {
return;
}
File file = fc.getSelectedFile();
if (file == null || !file.exists() || !file.canRead()) {
logger.fatal("No read access to file: " + file);
return;
}
GUI.setExternalToolsSetting("DGRM_IMPORT_LINKS_FILE", file.getPath());
/* Parse and import edges */
try {
importEdges(parseDGRMLinksFile(file, gui.getSimulation()));
} catch (Exception e) {
GUI.showErrorDialog(this, "Error when importing DGRM links from " + file.getName(), e, false);
}
}
private void importEdges(DirectedGraphMedium.Edge[] edges) {
Arrays.sort(edges, new Comparator<DirectedGraphMedium.Edge>() {
public int compare(Edge o1, Edge o2) {
return o1.source.getMote().getID() - o2.source.getMote().getID();
}
});
for (DirectedGraphMedium.Edge e: edges) {
radioMedium.addEdge(e);
}
logger.info("Imported " + edges.length + " DGRM edges");
}
static final int INDEX_SRC = 0;
static final int INDEX_DST = 1;
static final int INDEX_PRR = 2;
static final int INDEX_PRR_CI = 3;
static final int INDEX_NUM_TX = 4;
static final int INDEX_NUM_RX = 5;
static final int INDEX_RSSI_MEDIAN = 6;
static final int INDEX_RSSI_MIN = 7;
static final int INDEX_RSSI_MAX = 8;
public static DirectedGraphMedium.Edge[] parseDGRMLinksFile(File file, Simulation simulation) {
String fileContents = StringUtils.loadFromFile(file);
ArrayList<DirectedGraphMedium.Edge> edges = new ArrayList<DirectedGraphMedium.Edge>();
/* format: # [src] [dst] [prr] [prr_ci] [num_tx] [num_rx] [rssi] [rssi_min] [rssi_max] */
for (String l: fileContents.split("\n")) {
l = l.trim();
if (l.startsWith("#")) {
continue;
}
Mote m;
String[] arr = l.split(" ");
int source = Integer.parseInt(arr[INDEX_SRC]);
m = simulation.getMoteWithID(source);
if (m == null) {
throw new RuntimeException("No simulation mote with ID " + source);
}
Radio sourceRadio = m.getInterfaces().getRadio();
int dst = Integer.parseInt(arr[INDEX_DST]);
m = simulation.getMoteWithID(dst);
if (m == null) {
throw new RuntimeException("No simulation mote with ID " + dst);
}
DGRMDestinationRadio destRadio = new DGRMDestinationRadio(m.getInterfaces().getRadio());
double prr = Double.parseDouble(arr[INDEX_PRR]);
/*double prrConfidence = Double.parseDouble(arr[INDEX_PRR_CI]);*/
/*int numTX <- INDEX_NUM_TX;*/
/*int numRX <- INDEX_NUM_RX;*/
double rssi = Double.parseDouble(arr[INDEX_RSSI_MEDIAN]);
/*int rssiMin <- INDEX_RSSI_MIN;*/
/*int rssiMax <- INDEX_RSSI_MAX;*/
DirectedGraphMedium.Edge edge = new DirectedGraphMedium.Edge(sourceRadio, destRadio);
destRadio.delay = 0;
destRadio.ratio = prr;
/*destRadio.prrConfidence = prrConfidence;*/
destRadio.signal = rssi;
edges.add(edge);
}
return edges.toArray(new DirectedGraphMedium.Edge[0]);
}
final AbstractTableModel model = new AbstractTableModel() {
private static final long serialVersionUID = 9101118401527171218L;
public String getColumnName(int column) {
if (column < 0 || column >= COLUMN_NAMES.length) {
return "";
}
return COLUMN_NAMES[column];
}
public int getRowCount() { public int getRowCount() {
return radioMedium.getEdges().length; return radioMedium.getEdges().length;
} }
public int getColumnCount() { public int getColumnCount() {
return columns.length; return COLUMN_NAMES.length;
} }
public Object getValueAt(int row, int column) { public Object getValueAt(int row, int column) {
if (row < 0 || row >= radioMedium.getEdges().length) { if (row < 0 || row >= radioMedium.getEdges().length) {
logger.fatal("Unknown row: " + row);
return ""; return "";
} }
if (column < 0 || column >= columns.length) { if (column < 0 || column >= COLUMN_NAMES.length) {
logger.fatal("Unknown column: " + column);
return ""; return "";
} }
DirectedGraphMedium.Edge edge = radioMedium.getEdges()[row]; DirectedGraphMedium.Edge edge = radioMedium.getEdges()[row];
if (column == IDX_SRC) { if (column == IDX_SRC) {
if (edge.source == null) {
return "?";
}
return edge.source.getMote(); return edge.source.getMote();
} }
if (column == IDX_DST) { if (column == IDX_DST) {
if (edge.superDest.toAll) {
return "ALL";
}
return edge.superDest.radio.getMote(); return edge.superDest.radio.getMote();
} }
if (column == IDX_RATIO) { if (column == IDX_RATIO) {
return ((DGRMDestinationRadio)edge.superDest).ratio; return ((DGRMDestinationRadio)edge.superDest).ratio;
} }
if (column == IDX_SIGNAL) {
return ((DGRMDestinationRadio)edge.superDest).signal;
}
if (column == IDX_DELAY) { if (column == IDX_DELAY) {
return ((DGRMDestinationRadio)edge.superDest).delay / Simulation.MILLISECOND; return ((DGRMDestinationRadio)edge.superDest).delay / Simulation.MILLISECOND;
} }
if (column == IDX_DEL) { return "";
return new Boolean(false);
}
logger.debug("Column data not implemented: " + column);
return "?";
} }
public void setValueAt(Object value, int row, int column) { public void setValueAt(Object value, int row, int column) {
if (row < 0 || row >= radioMedium.getEdges().length) { if (row < 0 || row >= radioMedium.getEdges().length) {
logger.fatal("Unknown row: " + row);
return; return;
} }
if (column < 0 || column >= columns.length) { if (column < 0 || column >= COLUMN_NAMES.length) {
logger.fatal("Unknown column: " + column);
return; return;
} }
DirectedGraphMedium.Edge edge = radioMedium.getEdges()[row]; DirectedGraphMedium.Edge edge = radioMedium.getEdges()[row];
if (column == IDX_RATIO) { try {
/* Success ratio */ if (column == IDX_RATIO) {
try { ((DGRMDestinationRadio)edge.superDest).ratio = ((Number)value).doubleValue();
((DGRMDestinationRadio)edge.superDest).ratio = } else if (column == IDX_SIGNAL) {
((Number)value).doubleValue(); ((DGRMDestinationRadio)edge.superDest).signal = ((Number)value).doubleValue();
radioMedium.requestEdgeAnalysis(); } else if (column == IDX_DELAY) {
} catch (ClassCastException e) { ((DGRMDestinationRadio)edge.superDest).delay =
} ((Number)value).longValue() * Simulation.MILLISECOND;
return; } else {
super.setValueAt(value, row, column);
}
radioMedium.requestEdgeAnalysis();
} catch (ClassCastException e) {
} }
if (column == IDX_DELAY) {
/* Propagation delay (ms) */
try {
((DGRMDestinationRadio)edge.superDest).delay =
((Number)value).longValue() * Simulation.MILLISECOND;
radioMedium.requestEdgeAnalysis();
} catch (ClassCastException e) {
}
return;
}
if (column == IDX_DEL) {
/* Delete link */
doRemoveLink(edge);
return;
}
super.setValueAt(value, row, column);
} }
public boolean isCellEditable(int row, int column) { public boolean isCellEditable(int row, int column) {
@ -357,24 +451,22 @@ public class DGRMConfigurator extends VisPlugin {
return false; return false;
} }
if (column == IDX_DST) { if (column == IDX_DST) {
if (!radioMedium.getEdges()[row].superDest.toAll) { gui.signalMoteHighlight(radioMedium.getEdges()[row].superDest.radio.getMote());
gui.signalMoteHighlight(radioMedium.getEdges()[row].superDest.radio.getMote());
}
return false; return false;
} }
if (column == IDX_RATIO) { if (column == IDX_RATIO) {
return true; return true;
} }
if (column == IDX_DELAY) { if (column == IDX_SIGNAL) {
return true; return true;
} }
if (column == IDX_DEL) { if (column == IDX_DELAY) {
return true; return true;
} }
return false; return false;
} }
public Class getColumnClass(int c) { public Class<? extends Object> getColumnClass(int c) {
return getValueAt(0, c).getClass(); return getValueAt(0, c).getClass();
} }
}; };

View file

@ -48,9 +48,9 @@ import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.Radio;
import se.sics.cooja.plugins.Visualizer; import se.sics.cooja.plugins.Visualizer;
import se.sics.cooja.plugins.VisualizerSkin; import se.sics.cooja.plugins.VisualizerSkin;
import se.sics.cooja.radiomediums.DGRMDestinationRadio;
import se.sics.cooja.radiomediums.DestinationRadio;
import se.sics.cooja.radiomediums.DirectedGraphMedium; import se.sics.cooja.radiomediums.DirectedGraphMedium;
import se.sics.cooja.radiomediums.DirectedGraphMedium.DGRMDestinationRadio;
import se.sics.cooja.radiomediums.DirectedGraphMedium.DestinationRadio;
@ClassDescription("Radio environment (DGRM)") @ClassDescription("Radio environment (DGRM)")
public class DGRMVisualizerSkin implements VisualizerSkin { public class DGRMVisualizerSkin implements VisualizerSkin {
@ -142,16 +142,15 @@ public class DGRMVisualizerSkin implements VisualizerSkin {
if (prob == 0.0d) { if (prob == 0.0d) {
continue; continue;
} }
msg = (double)(((int)(1000*prob))/10.0) + "%"; msg = String.format("%1.1f%%", 100.0*prob);
Position pos = r.radio.getPosition(); Position pos = r.radio.getPosition();
Point pixel = visualizer.transformPositionToPixel(pos); Point pixel = visualizer.transformPositionToPixel(pos);
msgWidth = fm.stringWidth(msg); msgWidth = fm.stringWidth(msg);
g.setColor(Color.LIGHT_GRAY); g.setColor(new Color(1-(float)prob, (float)prob, 0.0f));
g.drawLine(x, y, pixel.x, pixel.y); g.drawLine(x, y, pixel.x, pixel.y);
g.setColor(Color.BLACK); g.setColor(Color.BLACK);
g.drawString(msg, pixel.x - msgWidth/2, pixel.y + 2*Visualizer.MOTE_RADIUS + 3); g.drawString(msg, pixel.x - msgWidth/2, pixel.y + 2*Visualizer.MOTE_RADIUS + 3);
} }
} }
public void paintAfterMotes(Graphics g) { public void paintAfterMotes(Graphics g) {

View file

@ -0,0 +1,95 @@
/*
* Copyright (c) 2010, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* 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: DirectedGraphMedium.java,v 1.8 2010/12/02 15:25:50 fros4943 Exp $
*/
package se.sics.cooja.radiomediums;
import java.util.Collection;
import org.jdom.Element;
import se.sics.cooja.Simulation;
import se.sics.cooja.interfaces.Radio;
public class DGRMDestinationRadio extends DestinationRadio {
public double ratio = 1.0; /* Link success ratio (per packet). */
public double signal = AbstractRadioMedium.SS_STRONG; /* RSSI */
public long delay = 0; /* EXPERIMENTAL: Propagation delay (us). */
public DGRMDestinationRadio() {
super();
}
public DGRMDestinationRadio(Radio dest) {
super(dest);
}
protected Object clone() {
DGRMDestinationRadio clone = new DGRMDestinationRadio(this.radio);
clone.ratio = this.ratio;
clone.delay = this.delay;
clone.signal = this.signal;
return clone;
}
public Collection<Element> getConfigXML() {
Collection<Element> config = super.getConfigXML();
Element element;
element = new Element("ratio");
element.setText("" + ratio);
config.add(element);
element = new Element("signal");
element.setText("" + signal);
config.add(element);
element = new Element("delay");
element.setText("" + delay);
config.add(element);
return config;
}
public boolean setConfigXML(final Collection<Element> configXML, Simulation simulation) {
if (!super.setConfigXML(configXML, simulation)) {
return false;
}
for (Element element : configXML) {
if (element.getName().equals("ratio")) {
ratio = Double.parseDouble(element.getText());
} else if (element.getName().equals("signal")) {
signal = Double.parseDouble(element.getText());
} else if (element.getName().equals("delay")) {
delay = Long.parseLong(element.getText());
}
}
return true;
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2010, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* 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: DirectedGraphMedium.java,v 1.8 2010/12/02 15:25:50 fros4943 Exp $
*/
package se.sics.cooja.radiomediums;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.Simulation;
import se.sics.cooja.interfaces.Radio;
public class DestinationRadio {
private static Logger logger = Logger.getLogger(DestinationRadio.class);
public Radio radio; /* destination radio */
public DestinationRadio() {
}
public DestinationRadio(Radio dest) {
this.radio = dest;
}
public String toString() {
return radio.getMote().toString();
}
public Collection<Element> getConfigXML() {
ArrayList<Element> config = new ArrayList<Element>();
Element element;
element = new Element("radio");
element.setText("" + radio.getMote().getID());
config.add(element);
return config;
}
public boolean setConfigXML(Collection<Element> configXML, Simulation simulation) {
for (Element element : configXML) {
if (element.getName().equals("radio")) {
radio = simulation.getMoteWithID(Integer.parseInt(element.getText())).getInterfaces().getRadio();
if (radio == null) {
throw new RuntimeException("No mote with ID " + element.getText());
}
}
}
return true;
}
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009, Swedish Institute of Computer Science. * Copyright (c) 2010, Swedish Institute of Computer Science.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -36,13 +36,11 @@ import java.util.Collection;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Random; import java.util.Random;
import java.util.Vector;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.jdom.Element; import org.jdom.Element;
import se.sics.cooja.ClassDescription; import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote;
import se.sics.cooja.RadioConnection; import se.sics.cooja.RadioConnection;
import se.sics.cooja.Simulation; import se.sics.cooja.Simulation;
import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.Radio;
@ -57,496 +55,390 @@ import se.sics.cooja.plugins.skins.DGRMVisualizerSkin;
* as a basis for other radio medium implementations. * as a basis for other radio medium implementations.
* *
* The stand-alone radio medium supports propagation delays and * The stand-alone radio medium supports propagation delays and
* and single-value per-link transmission success ratio. * and per-link transmission success ratio/RSSI.
* *
* @see UDGM * @see AbstractRadioMedium
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
@ClassDescription("Directed Graph Radio Medium (DGRM)") @ClassDescription("Directed Graph Radio Medium (DGRM)")
public class DirectedGraphMedium extends AbstractRadioMedium { public class DirectedGraphMedium extends AbstractRadioMedium {
private static Logger logger = Logger.getLogger(DirectedGraphMedium.class); private static Logger logger = Logger.getLogger(DirectedGraphMedium.class);
private Simulation simulation; private Simulation simulation;
private Random random; private Random random;
private ArrayList<Edge> edges = new ArrayList<Edge>(); private ArrayList<Edge> edges = new ArrayList<Edge>();
private boolean edgesDirty = true; private boolean edgesDirty = true;
/* Used for optimizing lookup time */ /* Used for optimizing lookup time */
private Hashtable<Radio,DestinationRadio[]> edgesTable = new Hashtable<Radio,DestinationRadio[]>(); private Hashtable<Radio,DestinationRadio[]> edgesTable = new Hashtable<Radio,DestinationRadio[]>();
public DirectedGraphMedium() { public DirectedGraphMedium() {
/* Do not initialize radio medium: use only for hash table */ /* Do not initialize radio medium: use only for hash table */
super(null); super(null);
Visualizer.registerVisualizerSkin(DGRMVisualizerSkin.class); Visualizer.registerVisualizerSkin(DGRMVisualizerSkin.class);
} }
public DirectedGraphMedium(Simulation simulation) { public DirectedGraphMedium(Simulation simulation) {
super(simulation); super(simulation);
this.simulation = simulation; this.simulation = simulation;
random = simulation.getRandomGenerator(); random = simulation.getRandomGenerator();
requestEdgeAnalysis(); requestEdgeAnalysis();
/* Register plugin and visualizer skin */ /* Register plugin and visualizer skin */
simulation.getGUI().registerPlugin(DGRMConfigurator.class); simulation.getGUI().registerPlugin(DGRMConfigurator.class);
Visualizer.registerVisualizerSkin(DGRMVisualizerSkin.class); Visualizer.registerVisualizerSkin(DGRMVisualizerSkin.class);
} }
public void removed() { public void removed() {
super.removed(); super.removed();
/* Unregister plugin and visualizer skin */ /* Unregister plugin and visualizer skin */
simulation.getGUI().unregisterPlugin(DGRMConfigurator.class); simulation.getGUI().unregisterPlugin(DGRMConfigurator.class);
Visualizer.unregisterVisualizerSkin(DGRMVisualizerSkin.class); Visualizer.unregisterVisualizerSkin(DGRMVisualizerSkin.class);
} }
public void addEdge(Edge e) { public void addEdge(Edge e) {
edges.add(e); edges.add(e);
requestEdgeAnalysis(); requestEdgeAnalysis();
((AbstractRadioMedium.RadioMediumObservable) ((AbstractRadioMedium.RadioMediumObservable)
this.getRadioMediumObservable()).setRadioMediumChangedAndNotify(); this.getRadioMediumObservable()).setRadioMediumChangedAndNotify();
} }
public void removeEdge(Edge edge) { public void removeEdge(Edge edge) {
if (!edges.contains(edge)) { if (!edges.contains(edge)) {
logger.fatal("Cannot remove edge: " + edge); logger.fatal("Cannot remove edge: " + edge);
return; return;
} }
edges.remove(edge); edges.remove(edge);
requestEdgeAnalysis(); requestEdgeAnalysis();
((AbstractRadioMedium.RadioMediumObservable) ((AbstractRadioMedium.RadioMediumObservable)
this.getRadioMediumObservable()).setRadioMediumChangedAndNotify(); this.getRadioMediumObservable()).setRadioMediumChangedAndNotify();
} }
public void clearEdges() { public void clearEdges() {
edges.clear(); edges.clear();
requestEdgeAnalysis(); requestEdgeAnalysis();
((AbstractRadioMedium.RadioMediumObservable) ((AbstractRadioMedium.RadioMediumObservable)
this.getRadioMediumObservable()).setRadioMediumChangedAndNotify(); this.getRadioMediumObservable()).setRadioMediumChangedAndNotify();
} }
public Edge[] getEdges() { public Edge[] getEdges() {
return edges.toArray(new Edge[0]); return edges.toArray(new Edge[0]);
} }
/** /**
* Signal that the configuration changed, and needs to be re-analyzed * Signal that the configuration changed, and needs to be re-analyzed
* before used. * before used.
*/ */
public void requestEdgeAnalysis() { public void requestEdgeAnalysis() {
edgesDirty = true; edgesDirty = true;
} }
public boolean needsEdgeAnalysis() { public boolean needsEdgeAnalysis() {
return edgesDirty; return edgesDirty;
} }
public void registerRadioInterface(Radio radio, Simulation sim) { public void unregisterRadioInterface(Radio radio, Simulation sim) {
super.registerRadioInterface(radio, sim); super.unregisterRadioInterface(radio, sim);
for (Edge edge: getEdges()) { for (Edge edge: getEdges()) {
if (edge.delayedLoadConfig == null) { if (edge.source == radio || edge.superDest.radio == radio) {
continue; removeEdge(edge);
} requestEdgeAnalysis();
}
/* Try to configure edge now */ }
if (edge.setConfigXML(edge.delayedLoadConfig, sim)) { }
edge.delayedLoadConfig = null;
} public void updateSignalStrengths() {
}
/* Reset signal strengths */
requestEdgeAnalysis(); for (Radio radio : getRegisteredRadios()) {
} radio.setCurrentSignalStrength(SS_NOTHING);
}
public void unregisterRadioInterface(Radio radio, Simulation sim) {
super.unregisterRadioInterface(radio, sim); /* Set signal strengths */
RadioConnection[] conns = getActiveConnections();
if (radio == null) { for (RadioConnection conn : conns) {
return; if (conn.getSource().getCurrentSignalStrength() < SS_STRONG) {
} conn.getSource().setCurrentSignalStrength(SS_STRONG);
for (Edge edge: getEdges()) { }
if (edge.source == radio || edge.superDest.radio == radio) { for (Radio dstRadio : conn.getDestinations()) {
removeEdge(edge); if (dstRadio.getCurrentSignalStrength() < SS_STRONG) {
} dstRadio.setCurrentSignalStrength(SS_STRONG);
} }
}
requestEdgeAnalysis(); }
}
/* Set signal strength to weak on interfered */
public void updateSignalStrengths() { for (RadioConnection conn : conns) {
for (Radio intfRadio : conn.getInterfered()) {
/* Reset signal strengths */ if (intfRadio.getCurrentSignalStrength() < SS_STRONG) {
for (Radio radio : getRegisteredRadios()) { intfRadio.setCurrentSignalStrength(SS_STRONG);
radio.setCurrentSignalStrength(SS_NOTHING); }
}
if (!intfRadio.isInterfered()) {
/* Set signal strengths */ /*logger.warn("Radio was not interfered");*/
RadioConnection[] conns = getActiveConnections(); intfRadio.interfereAnyReception();
for (RadioConnection conn : conns) { }
if (conn.getSource().getCurrentSignalStrength() < SS_STRONG) { }
conn.getSource().setCurrentSignalStrength(SS_STRONG); }
} }
for (Radio dstRadio : conn.getDestinations()) {
if (dstRadio.getCurrentSignalStrength() < SS_STRONG) {
dstRadio.setCurrentSignalStrength(SS_STRONG);
} /**
} * Generates hash table using current edges for efficient lookup.
} */
protected void analyzeEdges() {
/* Set signal strength to weak on interfered */ Hashtable<Radio,ArrayList<DestinationRadio>> listTable =
for (RadioConnection conn : conns) { new Hashtable<Radio,ArrayList<DestinationRadio>>();
for (Radio intfRadio : conn.getInterfered()) {
if (intfRadio.getCurrentSignalStrength() < SS_STRONG) { /* Fill edge hash table with all edges */
intfRadio.setCurrentSignalStrength(SS_STRONG); for (Edge edge: getEdges()) {
} ArrayList<DestinationRadio> destRadios;
if (!listTable.containsKey(edge.source)) {
if (!intfRadio.isInterfered()) { destRadios = new ArrayList<DestinationRadio>();
/*logger.warn("Radio was not interfered");*/ } else {
intfRadio.interfereAnyReception(); destRadios = listTable.get(edge.source);
} }
}
} destRadios.add(edge.superDest);
} listTable.put(edge.source, destRadios);
}
public static class DestinationRadio {
public Radio radio; /* destination radio */ /* Convert to arrays */
public boolean toAll; /* to all destinations */ Hashtable<Radio,DestinationRadio[]> arrTable = new Hashtable<Radio,DestinationRadio[]>();
Enumeration<Radio> sources = listTable.keys();
public DestinationRadio(Radio dest) { while (sources.hasMoreElements()) {
this.radio = dest; Radio source = sources.nextElement();
toAll = (radio == null); DestinationRadio[] arr = listTable.get(source).toArray(new DestinationRadio[0]);
} arrTable.put(source, arr);
}
public String toString() {
return radio.getMote().toString(); this.edgesTable = arrTable;
} edgesDirty = false;
}
protected Object clone() {
return new DestinationRadio(radio); /**
} * Returns all potential destination radios, i.e. all radios "within reach".
} * Does not consider radio channels, transmission success ratios etc.
*
public static class DGRMDestinationRadio extends DestinationRadio { * @param source Source radio
public double ratio; /* Link success ratio (per packet). */ * @return All potential destination radios
public long delay; /* EXPERIMENTAL: Propagation delay (us). */ */
public DestinationRadio[] getPotentialDestinations(Radio source) {
public DGRMDestinationRadio(Radio dest, double ratio, long delay) { if (edgesDirty) {
super(dest); analyzeEdges();
this.ratio = ratio; }
this.delay = delay; return edgesTable.get(source);
} }
protected Object clone() { public RadioConnection createConnections(Radio source) {
return new DGRMDestinationRadio(radio, ratio, delay); if (edgesDirty) {
} analyzeEdges();
} }
if (edgesDirty) {
/** logger.fatal("Error when analyzing edges, aborting new radio connection");
* Generates hash table using current edges for efficient lookup. return new RadioConnection(source);
*/ }
protected void analyzeEdges() {
Hashtable<Radio,ArrayList<DestinationRadio>> listTable = /* Create new radio connection using edge hash table */
new Hashtable<Radio,ArrayList<DestinationRadio>>(); RadioConnection newConn = new RadioConnection(source);
DestinationRadio[] destinations = getPotentialDestinations(source);
/* Fill edge hash table with all edges */ if (destinations == null || destinations.length == 0) {
for (Edge edge: getEdges()) { /* No destinations */
if (edge.source == null) { /*logger.info(sendingRadio + ": No dest");*/
/* XXX Wait until edge configuration has been loaded */ return newConn;
logger.warn("DGRM edges not loaded"); }
return;
} /*logger.info(source + ": " + destinations.length + " potential destinations");*/
for (DestinationRadio d: destinations) {
ArrayList<DestinationRadio> destRadios; DGRMDestinationRadio dest = (DGRMDestinationRadio) d;
if (!listTable.containsKey(edge.source)) { if (dest.radio == source) {
/* Create new source */ /* Fail: cannot receive our own transmission */
destRadios = new ArrayList<DestinationRadio>(); /*logger.info(source + ": Fail, receiver is sender");*/
} else { continue;
/* Extend source radio with another destination */ }
destRadios = listTable.get(edge.source);
} /* Fail if radios are on different (but configured) channels */
if (source.getChannel() >= 0 &&
/* Explode special rule: to all radios */ dest.radio.getChannel() >= 0 &&
if (edge.superDest.toAll) { source.getChannel() != dest.radio.getChannel()) {
for (Radio r: getRegisteredRadios()) { continue;
if (edge.source == r) { }
continue;
} if (!dest.radio.isReceiverOn()) {
DestinationRadio d = (DestinationRadio) edge.superDest.clone(); /* Fail: radio is off */
d.radio = r; /*logger.info(source + ": Fail, off");*/
d.toAll = false; newConn.addInterfered(dest.radio);
destRadios.add(d); continue;
} }
} else {
destRadios.add(edge.superDest); if (dest.ratio < 1.0 && random.nextDouble() > dest.ratio) {
} /*logger.info(source + ": Fail, randomly");*/
listTable.put(edge.source, destRadios); /* TODO Interfere now? */
} newConn.addInterfered(dest.radio);
/* Convert to arrays */ dest.radio.interfereAnyReception();
Hashtable<Radio,DestinationRadio[]> arrTable = RadioConnection otherConnection = null;
new Hashtable<Radio,DestinationRadio[]>(); for (RadioConnection conn : getActiveConnections()) {
Enumeration<Radio> sources = listTable.keys(); for (Radio dstRadio : conn.getDestinations()) {
while (sources.hasMoreElements()) { if (dstRadio == dest.radio) {
Radio source = sources.nextElement(); otherConnection = conn;
DestinationRadio[] arr = break;
listTable.get(source).toArray(new DestinationRadio[0]); }
arrTable.put(source, arr); }
} }
if (otherConnection != null) {
this.edgesTable = arrTable; otherConnection.addInterfered(dest.radio);
edgesDirty = false; }
} continue;
}
/**
* Returns all potential destination radios, i.e. all radios "within reach". if (dest.radio.isReceiving()) {
* Does not consider radio channels, transmission success ratios etc. /* Fail: radio is already actively receiving */
* /*logger.info(source + ": Fail, receiving");*/
* @param source Source radio newConn.addInterfered(dest.radio);
* @return All potential destination radios
*/ /* We will also interfere with the other connection */
public DestinationRadio[] getPotentialDestinations(Radio source) { dest.radio.interfereAnyReception();
if (edgesDirty) { RadioConnection otherConnection = null;
analyzeEdges(); for (RadioConnection conn : getActiveConnections()) {
} for (Radio dstRadio : conn.getDestinations()) {
return edgesTable.get(source); if (dstRadio == dest.radio) {
} otherConnection = conn;
break;
public RadioConnection createConnections(Radio source) { }
if (edgesDirty) { }
analyzeEdges(); }
} if (otherConnection != null) {
if (edgesDirty) { otherConnection.addInterfered(dest.radio);
logger.fatal("Error when analyzing edges, aborting new radio connection"); }
return new RadioConnection(source); continue;
} }
/* Create new radio connection using edge hash table */ if (dest.radio.isInterfered()) {
RadioConnection newConn = new RadioConnection(source); /* Fail: radio is interfered in another connection */
DestinationRadio[] destinations = getPotentialDestinations(source); /*logger.info(source + ": Fail, interfered");*/
if (destinations == null || destinations.length == 0) { newConn.addInterfered(dest.radio);
/* No destinations */ continue;
/*logger.info(sendingRadio + ": No dest");*/ }
return newConn;
} /* Success: radio starts receiving */
/*logger.info(source + ": OK: " + dest.radio);*/
/*logger.info(source + ": " + destinations.length + " potential destinations");*/ newConn.addDestination(dest.radio, dest.delay);
for (DestinationRadio d: destinations) { }
DGRMDestinationRadio dest = (DGRMDestinationRadio) d;
if (dest.radio == source) { return newConn;
/* Fail: cannot receive our own transmission */ }
/*logger.info(source + ": Fail, receiver is sender");*/
continue; public Collection<Element> getConfigXML() {
} ArrayList<Element> config = new ArrayList<Element>();
Element element;
/* Fail if radios are on different (but configured) channels */
if (source.getChannel() >= 0 && for (Edge edge: getEdges()) {
dest.radio.getChannel() >= 0 && element = new Element("edge");
source.getChannel() != dest.radio.getChannel()) { element.addContent(edge.getConfigXML());
continue; config.add(element);
} }
if (!dest.radio.isReceiverOn()) { return config;
/* Fail: radio is off */ }
/*logger.info(source + ": Fail, off");*/
newConn.addInterfered(dest.radio); private Collection<Element> delayedConfiguration = null;
continue; public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
} random = simulation.getRandomGenerator();
if (dest.ratio < 1.0 && random.nextDouble() > dest.ratio) { /* Wait until simulation has been loaded */
/*logger.info(source + ": Fail, randomly");*/ delayedConfiguration = configXML;
/* TODO Interfere now? */ return true;
newConn.addInterfered(dest.radio); }
public void simulationFinishedLoading() {
dest.radio.interfereAnyReception(); if (delayedConfiguration == null) {
RadioConnection otherConnection = null; return;
for (RadioConnection conn : getActiveConnections()) { }
for (Radio dstRadio : conn.getDestinations()) {
if (dstRadio == dest.radio) { boolean warnedOldConfig = false;
otherConnection = conn; for (Element element : delayedConfiguration) {
break; if (element.getName().equals("edge")) {
} Collection<Element> edgeConfig = element.getChildren();
} Radio source = null;
} DestinationRadio dest = null;
if (otherConnection != null) { for (Element edgeElement : edgeConfig) {
otherConnection.addInterfered(dest.radio); if (edgeElement.getName().equals("src")) {
} /* Old version, ignore edge */
continue; if (!warnedOldConfig) {
} logger.fatal("Old simulation config detected: DGRM links will not be imported");
warnedOldConfig = true;
if (dest.radio.isReceiving()) { }
/* Fail: radio is already actively receiving */ return;
/*logger.info(source + ": Fail, receiving");*/ } else if (edgeElement.getName().equals("source")) {
newConn.addInterfered(dest.radio); source = simulation.getMoteWithID(
Integer.parseInt(edgeElement.getText())).getInterfaces().getRadio();
/* We will also interfere with the other connection */ } else if (edgeElement.getName().equals("dest")) {
dest.radio.interfereAnyReception(); String destClassName = edgeElement.getText().trim();
RadioConnection otherConnection = null; if (destClassName == null || destClassName.isEmpty()) {
for (RadioConnection conn : getActiveConnections()) { continue;
for (Radio dstRadio : conn.getDestinations()) { }
if (dstRadio == dest.radio) { Class<? extends DestinationRadio> destClass =
otherConnection = conn; simulation.getGUI().tryLoadClass(this, DestinationRadio.class, destClassName);
break; if (destClass == null) {
} throw new RuntimeException("Could not load class: " + destClassName);
} }
} try {
if (otherConnection != null) { dest = destClass.newInstance();
otherConnection.addInterfered(dest.radio); dest.setConfigXML(edgeElement.getChildren(), simulation);
} } catch (Exception e) {
continue; throw (RuntimeException)
} new RuntimeException("Unknown class: " + destClassName).initCause(e);
}
if (dest.radio.isInterfered()) { }
/* Fail: radio is interfered in another connection */ }
/*logger.info(source + ": Fail, interfered");*/ if (source == null || dest == null) {
newConn.addInterfered(dest.radio); if (!warnedOldConfig) {
continue; logger.fatal("Old simulation config detected: DGRM links will not be imported");
} warnedOldConfig = true;
}
/* Success: radio starts receiving */ } else {
/*logger.info(source + ": OK: " + dest.radio);*/ addEdge(new Edge(source, dest));
newConn.addDestination(dest.radio, dest.delay); }
} }
}
return newConn; requestEdgeAnalysis();
} delayedConfiguration = null;
}
public Collection<Element> getConfigXML() {
ArrayList<Element> config = new ArrayList<Element>(); public static class Edge {
Element element; public Radio source = null;
public DestinationRadio superDest = null;
for (Edge edge: getEdges()) {
element = new Element("edge"); public Edge(Radio source, DestinationRadio dest) {
element.addContent(edge.getConfigXML()); this.source = source;
config.add(element); this.superDest = dest;
} }
return config; private Collection<Element> getConfigXML() {
} ArrayList<Element> config = new ArrayList<Element>();
Element element;
public boolean setConfigXML(final Collection<Element> configXML, boolean visAvailable) {
random = simulation.getRandomGenerator(); element = new Element("source");
element.setText("" + source.getMote().getID());
for (Element element : configXML) { config.add(element);
if (element.getName().equals("edge")) {
Edge edge = new Edge(); element = new Element("dest");
edge.delayedLoadConfig = element.getChildren(); element.setText(superDest.getClass().getName());
addEdge(edge); Collection<Element> destConfig = superDest.getConfigXML();
} if (destConfig != null) {
} element.addContent(destConfig);
config.add(element);
requestEdgeAnalysis(); }
return true;
} return config;
}
public static class Edge { }
public Radio source;
public DestinationRadio superDest;
private Edge() {
/* Internal constructor: await config */
source = null;
superDest = null;
}
public Edge(Radio source, DestinationRadio dest) {
this.source = source;
this.superDest = dest;
}
/* Internal methods */
private Collection<Element> delayedLoadConfig = null; /* Used for restoring edges from config */
private Collection<Element> getConfigXML() {
Vector<Element> config = new Vector<Element>();
Element element;
element = new Element("src");
element.setText(source.getMote().toString());
config.add(element);
element = new Element("dest");
if (superDest.toAll) {
element.setText("ALL");
} else {
element.setText(superDest.radio.getMote().toString());
}
config.add(element);
if (superDest instanceof DGRMDestinationRadio) {
element = new Element("ratio");
element.setText("" + ((DGRMDestinationRadio)superDest).ratio);
config.add(element);
element = new Element("delay");
element.setText("" + ((DGRMDestinationRadio)superDest).delay);
config.add(element);
}
return config;
}
private boolean setConfigXML(Collection<Element> configXML, Simulation simulation) {
Radio dest = null;
double ratio = -1;
long delay = -1;
for (Element element : configXML) {
if (element.getName().equals("src")) {
String moteDescription = element.getText();
boolean foundMote = false;
for (Mote m: simulation.getMotes()) {
if (moteDescription.equals(m.toString())) {
foundMote = true;
source = m.getInterfaces().getRadio();
break;
}
}
if (!foundMote) {
return false;
}
}
if (element.getName().equals("dest")) {
String moteDescription = element.getText();
if (moteDescription.equals("ALL")) {
dest = null; /* ALL */
} else {
boolean foundMote = false;
for (Mote m: simulation.getMotes()) {
if (moteDescription.equals(m.toString())) {
foundMote = true;
dest = m.getInterfaces().getRadio();
break;
}
}
if (!foundMote) {
return false;
}
}
}
if (element.getName().equals("ratio")) {
ratio = Double.parseDouble(element.getText());
}
if (element.getName().equals("delay")) {
delay = Long.parseLong(element.getText());
}
}
if (ratio < 0 || delay < 0) {
return false;
}
superDest = new DGRMDestinationRadio(dest, ratio, delay);
return true;
}
}
} }

View file

@ -43,13 +43,12 @@ import org.jdom.Element;
import se.sics.cooja.ClassDescription; import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote; import se.sics.cooja.Mote;
import se.sics.cooja.RadioConnection; import se.sics.cooja.RadioConnection;
import se.sics.cooja.Simulation;
import se.sics.cooja.SimEventCentral.MoteCountListener; import se.sics.cooja.SimEventCentral.MoteCountListener;
import se.sics.cooja.Simulation;
import se.sics.cooja.interfaces.Position; import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.Radio;
import se.sics.cooja.plugins.Visualizer; import se.sics.cooja.plugins.Visualizer;
import se.sics.cooja.plugins.skins.UDGMVisualizerSkin; import se.sics.cooja.plugins.skins.UDGMVisualizerSkin;
import se.sics.cooja.radiomediums.DirectedGraphMedium.DestinationRadio;
/** /**
* The Unit Disk Graph Radio Medium abstracts radio transmission range as circles. * The Unit Disk Graph Radio Medium abstracts radio transmission range as circles.
@ -184,7 +183,6 @@ public class UDGM extends AbstractRadioMedium {
Position senderPos = sender.getPosition(); Position senderPos = sender.getPosition();
for (DestinationRadio dest: potentialDestinations) { for (DestinationRadio dest: potentialDestinations) {
Radio recv = dest.radio; Radio recv = dest.radio;
Position recvPos = recv.getPosition();
/* Fail if radios are on different (but configured) channels */ /* Fail if radios are on different (but configured) channels */
if (sender.getChannel() >= 0 && if (sender.getChannel() >= 0 &&
@ -192,6 +190,7 @@ public class UDGM extends AbstractRadioMedium {
sender.getChannel() != recv.getChannel()) { sender.getChannel() != recv.getChannel()) {
continue; continue;
} }
Position recvPos = recv.getPosition();
/* Fail if radio is turned off */ /* Fail if radio is turned off */
// if (!recv.isReceiverOn()) { // if (!recv.isReceiverOn()) {

View file