Merge branch 'master' of ssh://contiki.git.sourceforge.net/gitroot/contiki/contiki
This commit is contained in:
commit
7f3c198a78
20 changed files with 669 additions and 617 deletions
|
@ -96,6 +96,7 @@ enum {
|
||||||
RADIO_TX_OK,
|
RADIO_TX_OK,
|
||||||
RADIO_TX_ERR,
|
RADIO_TX_ERR,
|
||||||
RADIO_TX_COLLISION,
|
RADIO_TX_COLLISION,
|
||||||
|
RADIO_TX_NOACK,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __RADIO_H__ */
|
#endif /* __RADIO_H__ */
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "net/mac/nullrdc.h"
|
#include "net/mac/nullrdc.h"
|
||||||
#include "net/packetbuf.h"
|
#include "net/packetbuf.h"
|
||||||
#include "net/netstack.h"
|
#include "net/netstack.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@ -59,6 +60,14 @@
|
||||||
#endif /* NULLRDC_CONF_802154_AUTOACK */
|
#endif /* NULLRDC_CONF_802154_AUTOACK */
|
||||||
#endif /* NULLRDC_802154_AUTOACK */
|
#endif /* NULLRDC_802154_AUTOACK */
|
||||||
|
|
||||||
|
#ifndef NULLRDC_802154_AUTOACK_HW
|
||||||
|
#ifdef NULLRDC_CONF_802154_AUTOACK_HW
|
||||||
|
#define NULLRDC_802154_AUTOACK_HW NULLRDC_CONF_802154_AUTOACK_HW
|
||||||
|
#else
|
||||||
|
#define NULLRDC_802154_AUTOACK_HW 0
|
||||||
|
#endif /* NULLRDC_CONF_802154_AUTOACK_HW */
|
||||||
|
#endif /* NULLRDC_802154_AUTOACK_HW */
|
||||||
|
|
||||||
#if NULLRDC_802154_AUTOACK
|
#if NULLRDC_802154_AUTOACK
|
||||||
#include "sys/rtimer.h"
|
#include "sys/rtimer.h"
|
||||||
#include "dev/watchdog.h"
|
#include "dev/watchdog.h"
|
||||||
|
@ -66,7 +75,9 @@
|
||||||
#define ACK_WAIT_TIME RTIMER_SECOND / 2500
|
#define ACK_WAIT_TIME RTIMER_SECOND / 2500
|
||||||
#define AFTER_ACK_DETECTED_WAIT_TIME RTIMER_SECOND / 1500
|
#define AFTER_ACK_DETECTED_WAIT_TIME RTIMER_SECOND / 1500
|
||||||
#define ACK_LEN 3
|
#define ACK_LEN 3
|
||||||
|
#endif /* NULLRDC_802154_AUTOACK */
|
||||||
|
|
||||||
|
#if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW
|
||||||
struct seqno {
|
struct seqno {
|
||||||
rimeaddr_t sender;
|
rimeaddr_t sender;
|
||||||
uint8_t seqno;
|
uint8_t seqno;
|
||||||
|
@ -79,7 +90,7 @@ struct seqno {
|
||||||
#endif /* NETSTACK_CONF_MAC_SEQNO_HISTORY */
|
#endif /* NETSTACK_CONF_MAC_SEQNO_HISTORY */
|
||||||
|
|
||||||
static struct seqno received_seqnos[MAX_SEQNOS];
|
static struct seqno received_seqnos[MAX_SEQNOS];
|
||||||
#endif /* NULLRDC_802154_AUTOACK */
|
#endif /* NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW */
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
|
@ -87,9 +98,9 @@ send_packet(mac_callback_t sent, void *ptr)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
|
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
|
||||||
#if NULLRDC_802154_AUTOACK
|
#if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
|
packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
|
||||||
#endif /* NULLRDC_802154_AUTOACK */
|
#endif /* NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW */
|
||||||
|
|
||||||
if(NETSTACK_FRAMER.create() == 0) {
|
if(NETSTACK_FRAMER.create() == 0) {
|
||||||
/* Failed to allocate space for headers */
|
/* Failed to allocate space for headers */
|
||||||
|
@ -171,6 +182,9 @@ send_packet(mac_callback_t sent, void *ptr)
|
||||||
case RADIO_TX_COLLISION:
|
case RADIO_TX_COLLISION:
|
||||||
ret = MAC_TX_COLLISION;
|
ret = MAC_TX_COLLISION;
|
||||||
break;
|
break;
|
||||||
|
case RADIO_TX_NOACK:
|
||||||
|
ret = MAC_TX_NOACK;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ret = MAC_TX_ERR;
|
ret = MAC_TX_ERR;
|
||||||
break;
|
break;
|
||||||
|
@ -193,7 +207,7 @@ packet_input(void)
|
||||||
if(NETSTACK_FRAMER.parse() == 0) {
|
if(NETSTACK_FRAMER.parse() == 0) {
|
||||||
PRINTF("nullrdc: failed to parse %u\n", packetbuf_datalen());
|
PRINTF("nullrdc: failed to parse %u\n", packetbuf_datalen());
|
||||||
} else {
|
} else {
|
||||||
#if NULLRDC_802154_AUTOACK
|
#if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW
|
||||||
/* Check for duplicate packet by comparing the sequence number
|
/* Check for duplicate packet by comparing the sequence number
|
||||||
of the incoming packet with the last few ones we saw. */
|
of the incoming packet with the last few ones we saw. */
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static volatile uint8_t tx_complete;
|
static volatile uint8_t tx_complete;
|
||||||
|
static volatile uint8_t tx_status;
|
||||||
|
|
||||||
/* contiki mac driver */
|
/* contiki mac driver */
|
||||||
|
|
||||||
|
@ -98,11 +99,11 @@ static process_event_t event_data_ready;
|
||||||
static volatile packet_t prepped_p;
|
static volatile packet_t prepped_p;
|
||||||
|
|
||||||
int contiki_maca_init(void) {
|
int contiki_maca_init(void) {
|
||||||
trim_xtal();
|
// trim_xtal();
|
||||||
vreg_init();
|
// vreg_init();
|
||||||
contiki_maca_init();
|
// contiki_maca_init();
|
||||||
set_channel(0); /* channel 11 */
|
// set_channel(0); /* channel 11 */
|
||||||
set_power(0x12); /* 0x12 is the highest, not documented */
|
// set_power(0x12); /* 0x12 is the highest, not documented */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,8 +229,6 @@ int contiki_maca_transmit(unsigned short transmit_len) {
|
||||||
|
|
||||||
#if BLOCKING_TX
|
#if BLOCKING_TX
|
||||||
/* block until tx_complete, set by contiki_maca_tx_callback */
|
/* block until tx_complete, set by contiki_maca_tx_callback */
|
||||||
/* there are many places in contiki that rely on the */
|
|
||||||
/* transmit call to block */
|
|
||||||
while(!tx_complete && (tx_head != 0));
|
while(!tx_complete && (tx_head != 0));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -237,7 +236,18 @@ int contiki_maca_transmit(unsigned short transmit_len) {
|
||||||
int contiki_maca_send(const void *payload, unsigned short payload_len) {
|
int contiki_maca_send(const void *payload, unsigned short payload_len) {
|
||||||
contiki_maca_prepare(payload, payload_len);
|
contiki_maca_prepare(payload, payload_len);
|
||||||
contiki_maca_transmit(payload_len);
|
contiki_maca_transmit(payload_len);
|
||||||
return RADIO_TX_OK;
|
switch(tx_status) {
|
||||||
|
case SUCCESS:
|
||||||
|
case CRC_FAILED: /* CRC_FAILED is usually an ack */
|
||||||
|
PRINTF("TXOK\n\r");
|
||||||
|
return RADIO_TX_OK;
|
||||||
|
case NO_ACK:
|
||||||
|
PRINTF("NOACK\n\r");
|
||||||
|
return RADIO_TX_NOACK;
|
||||||
|
default:
|
||||||
|
PRINTF("TXERR\n\r");
|
||||||
|
return RADIO_TX_ERR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PROCESS(contiki_maca_process, "maca process");
|
PROCESS(contiki_maca_process, "maca process");
|
||||||
|
@ -254,12 +264,12 @@ PROCESS_THREAD(contiki_maca_process, ev, data)
|
||||||
/* check if there is a request to turn the radio on or off */
|
/* check if there is a request to turn the radio on or off */
|
||||||
if(contiki_maca_request_on == 1) {
|
if(contiki_maca_request_on == 1) {
|
||||||
contiki_maca_request_on = 0;
|
contiki_maca_request_on = 0;
|
||||||
maca_on();
|
// maca_on();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(contiki_maca_request_off == 1) {
|
if(contiki_maca_request_off == 1) {
|
||||||
contiki_maca_request_off = 0;
|
contiki_maca_request_off = 0;
|
||||||
maca_off();
|
// maca_off();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx_head != NULL) {
|
if (rx_head != NULL) {
|
||||||
|
@ -270,6 +280,10 @@ PROCESS_THREAD(contiki_maca_process, ev, data)
|
||||||
NETSTACK_RDC.input();
|
NETSTACK_RDC.input();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Call ourself again to handle remaining packets in the queue */
|
||||||
|
if (rx_head != NULL) {
|
||||||
|
process_poll(&contiki_maca_process);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -284,5 +298,6 @@ void maca_rx_callback(volatile packet_t *p __attribute((unused))) {
|
||||||
#if BLOCKING_TX
|
#if BLOCKING_TX
|
||||||
void maca_tx_callback(volatile packet_t *p __attribute((unused))) {
|
void maca_tx_callback(volatile packet_t *p __attribute((unused))) {
|
||||||
tx_complete = 1;
|
tx_complete = 1;
|
||||||
|
tx_status = p->status;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,7 +18,7 @@ FIQ_STACK_SIZE = 256;
|
||||||
SVC_STACK_SIZE = 256;
|
SVC_STACK_SIZE = 256;
|
||||||
ABT_STACK_SIZE = 16;
|
ABT_STACK_SIZE = 16;
|
||||||
UND_STACK_SIZE = 16;
|
UND_STACK_SIZE = 16;
|
||||||
HEAP_SIZE = 1024;
|
HEAP_SIZE = 2048;
|
||||||
|
|
||||||
/* Read-only sections, merged into text segment: */
|
/* Read-only sections, merged into text segment: */
|
||||||
PROVIDE (__executable_start = 0x00400000); . = 0x00400000;
|
PROVIDE (__executable_start = 0x00400000); . = 0x00400000;
|
||||||
|
|
|
@ -84,7 +84,8 @@
|
||||||
#define CONTIKI_MACA_RAW_MODE 0
|
#define CONTIKI_MACA_RAW_MODE 0
|
||||||
#define USE_32KHZ_XTAL 0
|
#define USE_32KHZ_XTAL 0
|
||||||
|
|
||||||
#define BLOCKING_TX 0
|
#define BLOCKING_TX 1
|
||||||
|
#define NULLRDC_CONF_802154_AUTOACK_HW 1
|
||||||
|
|
||||||
/* end of mc1322x specific config. */
|
/* end of mc1322x specific config. */
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
#include "contiki-maca.h"
|
#include "contiki-maca.h"
|
||||||
#include "contiki-uart.h"
|
#include "contiki-uart.h"
|
||||||
|
|
||||||
#define DEBUG 1
|
#define DEBUG 0
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#define PRINTF(...) printf(__VA_ARGS__)
|
#define PRINTF(...) printf(__VA_ARGS__)
|
||||||
|
@ -86,14 +86,6 @@
|
||||||
#define RIMEADDR_NBYTES 8
|
#define RIMEADDR_NBYTES 8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PLATFORM_DEBUG 1
|
|
||||||
#if PLATFORM_DEBUG
|
|
||||||
#define PRINTF(...) printf(__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define PRINTF(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if UIP_CONF_ROUTER
|
#if UIP_CONF_ROUTER
|
||||||
|
|
||||||
#ifndef UIP_ROUTER_MODULE
|
#ifndef UIP_ROUTER_MODULE
|
||||||
|
@ -236,30 +228,27 @@ void iab_to_eui64(rimeaddr_t *eui64, uint32_t oui, uint16_t iab, uint32_t ext) {
|
||||||
eui64->u8[1] = 0x50;
|
eui64->u8[1] = 0x50;
|
||||||
eui64->u8[2] = 0xc2;
|
eui64->u8[2] = 0xc2;
|
||||||
|
|
||||||
/* EUI64 field */
|
|
||||||
eui64->u8[3] = 0xff;
|
|
||||||
eui64->u8[4] = 0xfe;
|
|
||||||
|
|
||||||
/* IAB */
|
/* IAB */
|
||||||
eui64->u8[5] = (iab >> 4) & 0xff;
|
eui64->u8[3] = (iab >> 4) & 0xff;
|
||||||
eui64->u8[6] = (iab & 0xf) << 4;
|
eui64->u8[4] = (iab & 0xf) << 4;
|
||||||
|
|
||||||
/* EXT */
|
/* EXT */
|
||||||
eui64->u8[6] |= ((ext >> 8) & 0xf);
|
|
||||||
eui64->u8[7] = ext & 0xff;
|
eui64->u8[4] = (ext >> 24) & 0xff;
|
||||||
|
eui64->u8[5] = (ext >> 16) & 0xff;
|
||||||
|
eui64->u8[6] = (ext >> 8) & 0xff;
|
||||||
|
eui64->u8[7] = ext & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void oui_to_eui64(rimeaddr_t *eui64, uint32_t oui, uint32_t ext) {
|
void oui_to_eui64(rimeaddr_t *eui64, uint32_t oui, uint64_t ext) {
|
||||||
/* OUI */
|
/* OUI */
|
||||||
eui64->u8[0] = (oui >> 16) & 0xff;
|
eui64->u8[0] = (oui >> 16) & 0xff;
|
||||||
eui64->u8[1] = (oui >> 8) & 0xff;
|
eui64->u8[1] = (oui >> 8) & 0xff;
|
||||||
eui64->u8[2] = oui & 0xff;
|
eui64->u8[2] = oui & 0xff;
|
||||||
|
|
||||||
/* EUI64 field */
|
|
||||||
eui64->u8[3] = 0xff;
|
|
||||||
eui64->u8[4] = 0xfe;
|
|
||||||
|
|
||||||
/* EXT */
|
/* EXT */
|
||||||
|
eui64->u8[3] = (ext >> 32) & 0xff;
|
||||||
|
eui64->u8[4] = (ext >> 24) & 0xff;
|
||||||
eui64->u8[5] = (ext >> 16) & 0xff;
|
eui64->u8[5] = (ext >> 16) & 0xff;
|
||||||
eui64->u8[6] = (ext >> 8) & 0xff;
|
eui64->u8[6] = (ext >> 8) & 0xff;
|
||||||
eui64->u8[7] = ext & 0xff;
|
eui64->u8[7] = ext & 0xff;
|
||||||
|
@ -293,7 +282,7 @@ set_rimeaddr(rimeaddr_t *addr)
|
||||||
iab_to_eui64(&eui64, OUI, IAB, EXT_ID);
|
iab_to_eui64(&eui64, OUI, IAB, EXT_ID);
|
||||||
#else /* ifdef EXT_ID */
|
#else /* ifdef EXT_ID */
|
||||||
PRINTF("address in flash blank, setting to defined IAB with a random extension.\n\r");
|
PRINTF("address in flash blank, setting to defined IAB with a random extension.\n\r");
|
||||||
iab_to_eui64(&eui64, OUI, IAB, *MACA_RANDOM & 0xfff);
|
iab_to_eui64(&eui64, OUI, IAB, *MACA_RANDOM);
|
||||||
#endif /* ifdef EXT_ID */
|
#endif /* ifdef EXT_ID */
|
||||||
|
|
||||||
#else /* ifdef IAB */
|
#else /* ifdef IAB */
|
||||||
|
@ -303,7 +292,7 @@ set_rimeaddr(rimeaddr_t *addr)
|
||||||
oui_to_eui64(&eui64, OUI, EXT_ID);
|
oui_to_eui64(&eui64, OUI, EXT_ID);
|
||||||
#else /*ifdef EXT_ID */
|
#else /*ifdef EXT_ID */
|
||||||
PRINTF("address in flash blank, setting to defined OUI with a random extension.\n\r");
|
PRINTF("address in flash blank, setting to defined OUI with a random extension.\n\r");
|
||||||
oui_to_eui64(&eui64, OUI, *MACA_RANDOM & 0xffffff);
|
oui_to_eui64(&eui64, OUI, ((*MACA_RANDOM << 32) | *MACA_RANDOM));
|
||||||
#endif /*endif EXTID */
|
#endif /*endif EXTID */
|
||||||
|
|
||||||
#endif /* ifdef IAB */
|
#endif /* ifdef IAB */
|
||||||
|
@ -422,6 +411,27 @@ main(void)
|
||||||
RF_CHANNEL);
|
RF_CHANNEL);
|
||||||
#endif /* WITH_UIP6 */
|
#endif /* WITH_UIP6 */
|
||||||
|
|
||||||
|
*MACA_MACPANID = 0xcdab; /* this is the hardcoded contiki pan, register is PACKET order */
|
||||||
|
*MACA_MAC16ADDR = 0xffff; /* short addressing isn't used, set this to 0xffff for now */
|
||||||
|
|
||||||
|
*MACA_MAC64HI =
|
||||||
|
addr.u8[0] << 24 |
|
||||||
|
addr.u8[1] << 16 |
|
||||||
|
addr.u8[2] << 8 |
|
||||||
|
addr.u8[3];
|
||||||
|
*MACA_MAC64LO =
|
||||||
|
addr.u8[4] << 24 |
|
||||||
|
addr.u8[5] << 16 |
|
||||||
|
addr.u8[6] << 8 |
|
||||||
|
addr.u8[7];
|
||||||
|
PRINTF("setting panid 0x%04x\n\r", *MACA_MACPANID);
|
||||||
|
PRINTF("setting short mac 0x%04x\n\r", *MACA_MAC16ADDR);
|
||||||
|
PRINTF("setting long mac 0x%08x_%08x\n\r", *MACA_MAC64HI, *MACA_MAC64LO);
|
||||||
|
|
||||||
|
#if NULLRDC_CONF_802154_AUTOACK_HW
|
||||||
|
set_prm_mode(AUTOACK);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if PROFILE_CONF_ON
|
#if PROFILE_CONF_ON
|
||||||
profile_init();
|
profile_init();
|
||||||
#endif /* PROFILE_CONF_ON */
|
#endif /* PROFILE_CONF_ON */
|
||||||
|
|
|
@ -31,22 +31,79 @@
|
||||||
|
|
||||||
package se.sics.mrm;
|
package se.sics.mrm;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.BasicStroke;
|
||||||
import java.awt.event.*;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.geom.*;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
|
import java.awt.Cursor;
|
||||||
|
import java.awt.Dialog;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Frame;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.GraphicsEnvironment;
|
||||||
|
import java.awt.GridLayout;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.MediaTracker;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.Window;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.event.MouseListener;
|
||||||
|
import java.awt.event.MouseMotionListener;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
import javax.swing.*;
|
import java.util.Enumeration;
|
||||||
|
import java.util.Observable;
|
||||||
|
import java.util.Observer;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import javax.swing.AbstractButton;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.Box;
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.ButtonGroup;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JCheckBox;
|
||||||
|
import javax.swing.JDialog;
|
||||||
|
import javax.swing.JFileChooser;
|
||||||
|
import javax.swing.JFormattedTextField;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JRadioButton;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.JSeparator;
|
||||||
|
import javax.swing.JSlider;
|
||||||
|
import javax.swing.JToolTip;
|
||||||
|
import javax.swing.Popup;
|
||||||
|
import javax.swing.PopupFactory;
|
||||||
|
import javax.swing.ProgressMonitor;
|
||||||
import javax.swing.filechooser.FileFilter;
|
import javax.swing.filechooser.FileFilter;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
import se.sics.cooja.*;
|
import se.sics.cooja.ClassDescription;
|
||||||
import se.sics.cooja.interfaces.*;
|
import se.sics.cooja.GUI;
|
||||||
|
import se.sics.cooja.PluginType;
|
||||||
|
import se.sics.cooja.RadioConnection;
|
||||||
|
import se.sics.cooja.Simulation;
|
||||||
|
import se.sics.cooja.VisPlugin;
|
||||||
|
import se.sics.cooja.interfaces.Position;
|
||||||
|
import se.sics.cooja.interfaces.Radio;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class AreaViewer belongs to the MRM package.
|
* The class AreaViewer belongs to the MRM package.
|
||||||
|
@ -128,7 +185,7 @@ public class AreaViewer extends VisPlugin {
|
||||||
private boolean inSelectMode = true;
|
private boolean inSelectMode = true;
|
||||||
private boolean inTrackMode = false;
|
private boolean inTrackMode = false;
|
||||||
|
|
||||||
private Vector<Line2D> trackedComponents = null;
|
private ChannelModel.TrackedSignalComponents trackedComponents = null;
|
||||||
|
|
||||||
// Coloring variables
|
// Coloring variables
|
||||||
private JPanel coloringIntervalPanel = null;
|
private JPanel coloringIntervalPanel = null;
|
||||||
|
@ -148,6 +205,8 @@ public class AreaViewer extends VisPlugin {
|
||||||
|
|
||||||
private JRadioButton noneButton = null;
|
private JRadioButton noneButton = null;
|
||||||
|
|
||||||
|
private JRadioButton trackModeButton;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes an AreaViewer.
|
* Initializes an AreaViewer.
|
||||||
*
|
*
|
||||||
|
@ -196,11 +255,12 @@ public class AreaViewer extends VisPlugin {
|
||||||
zoomModeButton.setActionCommand("set zoom mode");
|
zoomModeButton.setActionCommand("set zoom mode");
|
||||||
zoomModeButton.addActionListener(canvasModeHandler);
|
zoomModeButton.addActionListener(canvasModeHandler);
|
||||||
|
|
||||||
JRadioButton trackModeButton = new JRadioButton ("track rays");
|
trackModeButton = new JRadioButton ("track rays");
|
||||||
trackModeButton.setAlignmentY(Component.BOTTOM_ALIGNMENT);
|
trackModeButton.setAlignmentY(Component.BOTTOM_ALIGNMENT);
|
||||||
trackModeButton.setContentAreaFilled(false);
|
trackModeButton.setContentAreaFilled(false);
|
||||||
trackModeButton.setActionCommand("set track rays mode");
|
trackModeButton.setActionCommand("set track rays mode");
|
||||||
trackModeButton.addActionListener(canvasModeHandler);
|
trackModeButton.addActionListener(canvasModeHandler);
|
||||||
|
trackModeButton.setEnabled(false);
|
||||||
|
|
||||||
ButtonGroup group = new ButtonGroup();
|
ButtonGroup group = new ButtonGroup();
|
||||||
group.add(selectModeButton);
|
group.add(selectModeButton);
|
||||||
|
@ -565,19 +625,36 @@ public class AreaViewer extends VisPlugin {
|
||||||
/**
|
/**
|
||||||
* Listens to mouse event on canvas
|
* Listens to mouse event on canvas
|
||||||
*/
|
*/
|
||||||
private MouseListener canvasMouseHandler = new MouseListener() {
|
private MouseAdapter canvasMouseHandler = new MouseAdapter() {
|
||||||
|
private Popup popUpToolTip = null;
|
||||||
|
|
||||||
public void mouseReleased(MouseEvent e) {
|
public void mouseReleased(MouseEvent e) {
|
||||||
|
if (popUpToolTip != null) {
|
||||||
|
popUpToolTip.hide();
|
||||||
|
popUpToolTip = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public void mouseExited(MouseEvent e) {
|
|
||||||
}
|
public void mousePressed(MouseEvent e) {
|
||||||
public void mouseClicked(MouseEvent e) {
|
if (popUpToolTip != null) {
|
||||||
|
popUpToolTip.hide();
|
||||||
|
popUpToolTip = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zoom & Pan */
|
||||||
|
lastHandledPosition = new Point(e.getX(), e.getY());
|
||||||
|
zoomCenterX = e.getX() / currentZoomX - currentPanX;
|
||||||
|
zoomCenterY = e.getY() / currentZoomY - currentPanY;
|
||||||
|
zoomCenterPoint = e.getPoint();
|
||||||
|
|
||||||
|
/* Select */
|
||||||
if (inSelectMode) {
|
if (inSelectMode) {
|
||||||
Vector<Radio> hitRadios = trackClickedRadio(e.getPoint());
|
Vector<Radio> hitRadios = trackClickedRadio(e.getPoint());
|
||||||
|
|
||||||
if (hitRadios == null || hitRadios.size() == 0) {
|
if (hitRadios == null || hitRadios.size() == 0) {
|
||||||
if (e.getButton() != MouseEvent.BUTTON1) {
|
if (e.getButton() != MouseEvent.BUTTON1) {
|
||||||
selectedRadio = null;
|
selectedRadio = null;
|
||||||
channelImage = null;
|
channelImage = null;
|
||||||
|
trackModeButton.setEnabled(false);
|
||||||
canvas.repaint();
|
canvas.repaint();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -589,39 +666,47 @@ public class AreaViewer extends VisPlugin {
|
||||||
|
|
||||||
if (selectedRadio == null || !hitRadios.contains(selectedRadio)) {
|
if (selectedRadio == null || !hitRadios.contains(selectedRadio)) {
|
||||||
selectedRadio = hitRadios.firstElement();
|
selectedRadio = hitRadios.firstElement();
|
||||||
|
trackModeButton.setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
// Select next in list
|
|
||||||
selectedRadio = hitRadios.get(
|
selectedRadio = hitRadios.get(
|
||||||
(hitRadios.indexOf(selectedRadio)+1) % hitRadios.size()
|
(hitRadios.indexOf(selectedRadio)+1) % hitRadios.size()
|
||||||
);
|
);
|
||||||
|
trackModeButton.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
channelImage = null;
|
channelImage = null;
|
||||||
canvas.repaint();
|
canvas.repaint();
|
||||||
} else if (inTrackMode && selectedRadio != null) {
|
return;
|
||||||
// Calculate real clicked position
|
}
|
||||||
|
|
||||||
|
/* Track */
|
||||||
|
if (inTrackMode && selectedRadio != null) {
|
||||||
double realClickedX = e.getX() / currentZoomX - currentPanX;
|
double realClickedX = e.getX() / currentZoomX - currentPanX;
|
||||||
double realClickedY = e.getY() / currentZoomY - currentPanY;
|
double realClickedY = e.getY() / currentZoomY - currentPanY;
|
||||||
|
|
||||||
Position radioPosition = currentRadioMedium.getRadioPosition(selectedRadio);
|
Position radioPosition = selectedRadio.getPosition();
|
||||||
final double radioX = radioPosition.getXCoordinate();
|
final double radioX = radioPosition.getXCoordinate();
|
||||||
final double radioY = radioPosition.getYCoordinate();
|
final double radioY = radioPosition.getYCoordinate();
|
||||||
|
|
||||||
trackedComponents = currentChannelModel.getRaysOfTransmission(radioX, radioY, realClickedX, realClickedY);
|
trackedComponents = currentChannelModel.getRaysOfTransmission(radioX, radioY, realClickedX, realClickedY);
|
||||||
|
|
||||||
canvas.repaint();
|
canvas.repaint();
|
||||||
|
|
||||||
|
/* Show popup */
|
||||||
|
JToolTip t = AreaViewer.this.createToolTip();
|
||||||
|
|
||||||
|
String logHtml =
|
||||||
|
"<html>" +
|
||||||
|
trackedComponents.log.replace("\n", "<br>").replace(" pi", " π") +
|
||||||
|
"</html>";
|
||||||
|
t.setTipText(logHtml);
|
||||||
|
|
||||||
|
if (t.getTipText() == null || t.getTipText().equals("")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
popUpToolTip = PopupFactory.getSharedInstance().getPopup(
|
||||||
|
AreaViewer.this, t, e.getXOnScreen(), e.getYOnScreen());
|
||||||
|
popUpToolTip.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
public void mouseEntered(MouseEvent e) {
|
|
||||||
}
|
|
||||||
public void mousePressed(MouseEvent e) {
|
|
||||||
lastHandledPosition = new Point(e.getX(), e.getY());
|
|
||||||
|
|
||||||
// Set zoom center (real world)
|
|
||||||
zoomCenterX = e.getX() / currentZoomX - currentPanX;
|
|
||||||
zoomCenterY = e.getY() / currentZoomY - currentPanY;
|
|
||||||
zoomCenterPoint = e.getPoint();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1523,6 +1608,7 @@ public class AreaViewer extends VisPlugin {
|
||||||
// Clear selected radio (if any selected) and radio medium coverage
|
// Clear selected radio (if any selected) and radio medium coverage
|
||||||
selectedRadio = null;
|
selectedRadio = null;
|
||||||
channelImage = null;
|
channelImage = null;
|
||||||
|
trackModeButton.setEnabled(false);
|
||||||
canvas.repaint();
|
canvas.repaint();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1616,7 +1702,7 @@ public class AreaViewer extends VisPlugin {
|
||||||
final double height = canvas.getHeight() / currentZoomY;
|
final double height = canvas.getHeight() / currentZoomY;
|
||||||
|
|
||||||
// Get sending radio position
|
// Get sending radio position
|
||||||
Position radioPosition = currentRadioMedium.getRadioPosition(selectedRadio);
|
Position radioPosition = selectedRadio.getPosition();
|
||||||
final double radioX = radioPosition.getXCoordinate();
|
final double radioX = radioPosition.getXCoordinate();
|
||||||
final double radioY = radioPosition.getYCoordinate();
|
final double radioY = radioPosition.getYCoordinate();
|
||||||
|
|
||||||
|
@ -1990,7 +2076,7 @@ public class AreaViewer extends VisPlugin {
|
||||||
|
|
||||||
// Translate to real world radio position
|
// Translate to real world radio position
|
||||||
Radio radio = currentRadioMedium.getRegisteredRadio(i);
|
Radio radio = currentRadioMedium.getRegisteredRadio(i);
|
||||||
Position radioPosition = currentRadioMedium.getRadioPosition(radio);
|
Position radioPosition = radio.getPosition();
|
||||||
g2d.translate(
|
g2d.translate(
|
||||||
radioPosition.getXCoordinate(),
|
radioPosition.getXCoordinate(),
|
||||||
radioPosition.getYCoordinate()
|
radioPosition.getYCoordinate()
|
||||||
|
@ -2129,16 +2215,14 @@ public class AreaViewer extends VisPlugin {
|
||||||
g2d.setStroke(new BasicStroke((float) 0.0));
|
g2d.setStroke(new BasicStroke((float) 0.0));
|
||||||
|
|
||||||
Random random = new Random(); /* Do not use main random generator */
|
Random random = new Random(); /* Do not use main random generator */
|
||||||
for (int i=0; i < trackedComponents.size(); i++) {
|
for (Line2D l: trackedComponents.components) {
|
||||||
g2d.setColor(new Color(255, random.nextInt(255), random.nextInt(255), 255));
|
g2d.setColor(new Color(255, random.nextInt(255), random.nextInt(255), 255));
|
||||||
Line2D originalLine = trackedComponents.get(i);
|
|
||||||
Line2D newLine = new Line2D.Double(
|
Line2D newLine = new Line2D.Double(
|
||||||
originalLine.getX1()*100.0,
|
l.getX1()*100.0,
|
||||||
originalLine.getY1()*100.0,
|
l.getY1()*100.0,
|
||||||
originalLine.getX2()*100.0,
|
l.getX2()*100.0,
|
||||||
originalLine.getY2()*100.0
|
l.getY2()*100.0
|
||||||
);
|
);
|
||||||
|
|
||||||
g2d.draw(newLine);
|
g2d.draw(newLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2167,7 +2251,7 @@ public class AreaViewer extends VisPlugin {
|
||||||
|
|
||||||
for (int i=0; i < currentRadioMedium.getRegisteredRadioCount(); i++) {
|
for (int i=0; i < currentRadioMedium.getRegisteredRadioCount(); i++) {
|
||||||
Radio testRadio = currentRadioMedium.getRegisteredRadio(i);
|
Radio testRadio = currentRadioMedium.getRegisteredRadio(i);
|
||||||
Position testPosition = currentRadioMedium.getRadioPosition(testRadio);
|
Position testPosition = testRadio.getPosition();
|
||||||
|
|
||||||
if (realClickedX > testPosition.getXCoordinate() - realIconHalfWidth &&
|
if (realClickedX > testPosition.getXCoordinate() - realIconHalfWidth &&
|
||||||
realClickedX < testPosition.getXCoordinate() + realIconHalfWidth &&
|
realClickedX < testPosition.getXCoordinate() + realIconHalfWidth &&
|
||||||
|
|
|
@ -33,6 +33,7 @@ package se.sics.mrm;
|
||||||
|
|
||||||
import java.awt.geom.*;
|
import java.awt.geom.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import javax.swing.tree.DefaultMutableTreeNode;
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
@ -65,9 +66,13 @@ public class ChannelModel {
|
||||||
|
|
||||||
private ObstacleWorld myObstacleWorld = new ObstacleWorld();
|
private ObstacleWorld myObstacleWorld = new ObstacleWorld();
|
||||||
|
|
||||||
|
/* Log mode: visualize signal components */
|
||||||
|
private boolean logMode = false;
|
||||||
|
private StringBuilder logInfo = null;
|
||||||
|
private ArrayList<Line2D> loggedRays = null;
|
||||||
|
|
||||||
|
|
||||||
// Ray tracing components temporary vector
|
// Ray tracing components temporary vector
|
||||||
private boolean inLoggingMode = false;
|
|
||||||
private Vector<Line2D> savedRays = null;
|
|
||||||
private Vector<Vector<Line2D>> calculatedVisibleSides = new Vector<Vector<Line2D>>();
|
private Vector<Vector<Line2D>> calculatedVisibleSides = new Vector<Vector<Line2D>>();
|
||||||
private Vector<Point2D> calculatedVisibleSidesSources = new Vector<Point2D>();
|
private Vector<Point2D> calculatedVisibleSidesSources = new Vector<Point2D>();
|
||||||
private Vector<Line2D> calculatedVisibleSidesLines = new Vector<Line2D>();
|
private Vector<Line2D> calculatedVisibleSidesLines = new Vector<Line2D>();
|
||||||
|
@ -1322,11 +1327,14 @@ public class ChannelModel {
|
||||||
* the random variable mean, and the second is the variance.
|
* the random variable mean, and the second is the variance.
|
||||||
*/
|
*/
|
||||||
public double[] getReceivedSignalStrength(double sourceX, double sourceY, double destX, double destY) {
|
public double[] getReceivedSignalStrength(double sourceX, double sourceY, double destX, double destY) {
|
||||||
return getTransmissionData(sourceX, sourceY, destX, destY, TransmissionData.SIGNAL_STRENGTH);
|
return getTransmissionData(sourceX, sourceY, destX, destY, TransmissionData.SIGNAL_STRENGTH, null);
|
||||||
|
}
|
||||||
|
public double[] getReceivedSignalStrength(double sourceX, double sourceY, double destX, double destY, Double txPower) {
|
||||||
|
return getTransmissionData(sourceX, sourceY, destX, destY, TransmissionData.SIGNAL_STRENGTH, txPower);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Fix better data type support
|
// TODO Fix better data type support
|
||||||
private double[] getTransmissionData(double sourceX, double sourceY, double destX, double destY, TransmissionData dataType) {
|
private double[] getTransmissionData(double sourceX, double sourceY, double destX, double destY, TransmissionData dataType, Double txPower) {
|
||||||
Point2D source = new Point2D.Double(sourceX, sourceY);
|
Point2D source = new Point2D.Double(sourceX, sourceY);
|
||||||
Point2D dest = new Point2D.Double(destX, destY);
|
Point2D dest = new Point2D.Double(destX, destY);
|
||||||
double accumulatedVariance = 0;
|
double accumulatedVariance = 0;
|
||||||
|
@ -1352,14 +1360,14 @@ public class ChannelModel {
|
||||||
// Calculate all paths from source to destination, using above calculated tree
|
// Calculate all paths from source to destination, using above calculated tree
|
||||||
Vector<RayPath> allPaths = getConnectingPaths(source, dest, visibleLinesTree);
|
Vector<RayPath> allPaths = getConnectingPaths(source, dest, visibleLinesTree);
|
||||||
|
|
||||||
if (inLoggingMode) {
|
if (logMode) {
|
||||||
logger.info("Saved rays:");
|
logInfo.append("Signal components:\n");
|
||||||
Enumeration<RayPath> pathsEnum = allPaths.elements();
|
Enumeration<RayPath> pathsEnum = allPaths.elements();
|
||||||
while (pathsEnum.hasMoreElements()) {
|
while (pathsEnum.hasMoreElements()) {
|
||||||
RayPath currentPath = pathsEnum.nextElement();
|
RayPath currentPath = pathsEnum.nextElement();
|
||||||
logger.info("* " + currentPath);
|
logInfo.append("* " + currentPath + "\n");
|
||||||
for (int i=0; i < currentPath.getSubPathCount(); i++) {
|
for (int i=0; i < currentPath.getSubPathCount(); i++) {
|
||||||
savedRays.add(currentPath.getSubPath(i));
|
loggedRays.add(currentPath.getSubPath(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1481,12 +1489,13 @@ public class ChannelModel {
|
||||||
|
|
||||||
// Using Rician fading approach, TODO Only one best signal considered - combine these? (need two limits)
|
// Using Rician fading approach, TODO Only one best signal considered - combine these? (need two limits)
|
||||||
totalPathGain += Math.pow(10, pathGain[i]/10.0)*Math.cos(2*Math.PI * pathModdedLengths[i]/wavelength);
|
totalPathGain += Math.pow(10, pathGain[i]/10.0)*Math.cos(2*Math.PI * pathModdedLengths[i]/wavelength);
|
||||||
if (inLoggingMode) {
|
if (logMode) {
|
||||||
logger.info("Adding ray path with gain " + pathGain[i] + " and phase " + (2*Math.PI * pathModdedLengths[i]/wavelength));
|
logInfo.append("Signal component: " + String.format("%2.3f", pathGain[i]) + " dB, phase " + String.format("%2.3f", (2*/*Math.PI* */ pathModdedLengths[i]/wavelength)) + " pi\n");
|
||||||
}
|
}
|
||||||
} else if (inLoggingMode) {
|
} else if (logMode) {
|
||||||
|
/* TODO Log mode affects result? */
|
||||||
pathModdedLengths[i] = (pathLengths[i] - pathLengths[bestSignalNr]) % wavelength;
|
pathModdedLengths[i] = (pathLengths[i] - pathLengths[bestSignalNr]) % wavelength;
|
||||||
logger.info("Not adding ray path with gain " + pathGain[i] + " and phase " + (2*Math.PI * pathModdedLengths[i]/wavelength));
|
logInfo.append("(IGNORED) Signal component: " + String.format("%2.3f", pathGain[i]) + " dB, phase " + String.format("%2.3f", (2*/*Math.PI* */ pathModdedLengths[i]/wavelength)) + " pi\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1499,17 +1508,22 @@ public class ChannelModel {
|
||||||
// Convert back to dB
|
// Convert back to dB
|
||||||
totalPathGain = 10*Math.log10(Math.abs(totalPathGain));
|
totalPathGain = 10*Math.log10(Math.abs(totalPathGain));
|
||||||
|
|
||||||
if (inLoggingMode) {
|
if (logMode) {
|
||||||
logger.info("Total path gain:\t" + totalPathGain);
|
logInfo.append("\nTotal path gain: " + String.format("%2.3f", totalPathGain) + " dB\n");
|
||||||
logger.info("Delay spread:\t" + delaySpread);
|
logInfo.append("Delay spread: " + String.format("%2.3f", delaySpread) + "\n");
|
||||||
logger.info("RMS Delay spread:\t" + delaySpreadRMS);
|
logInfo.append("RMS delay spread: " + String.format("%2.3f", delaySpreadRMS) + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// - Calculate received power -
|
// - Calculate received power -
|
||||||
// Using formula (dB)
|
// Using formula (dB)
|
||||||
// Received power = Output power + System gain + Transmitter gain + Path Loss + Receiver gain
|
// Received power = Output power + System gain + Transmitter gain + Path Loss + Receiver gain
|
||||||
// TODO Update formulas
|
// TODO Update formulas
|
||||||
double outputPower = getParameterDoubleValue("tx_power");
|
double outputPower;
|
||||||
|
if (txPower == null) {
|
||||||
|
outputPower = getParameterDoubleValue("tx_power");
|
||||||
|
} else {
|
||||||
|
outputPower = txPower;
|
||||||
|
}
|
||||||
double systemGain = getParameterDoubleValue("system_gain_mean");
|
double systemGain = getParameterDoubleValue("system_gain_mean");
|
||||||
if (getParameterBooleanValue("apply_random")) {
|
if (getParameterBooleanValue("apply_random")) {
|
||||||
Random random = new Random(); /* TODO Use main random generator? */
|
Random random = new Random(); /* TODO Use main random generator? */
|
||||||
|
@ -1520,8 +1534,8 @@ public class ChannelModel {
|
||||||
double transmitterGain = getParameterDoubleValue("tx_antenna_gain"); // TODO Should depend on angle
|
double transmitterGain = getParameterDoubleValue("tx_antenna_gain"); // TODO Should depend on angle
|
||||||
|
|
||||||
double receivedPower = outputPower + systemGain + transmitterGain + totalPathGain;
|
double receivedPower = outputPower + systemGain + transmitterGain + totalPathGain;
|
||||||
if (inLoggingMode) {
|
if (logMode) {
|
||||||
logger.info("Resulting received signal strength:\t" + receivedPower + " (" + accumulatedVariance + ")");
|
logInfo.append("\nReceived signal strength: " + String.format("%2.3f", receivedPower) + " dB (variance " + accumulatedVariance + ")\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataType == TransmissionData.DELAY_SPREAD || dataType == TransmissionData.DELAY_SPREAD_RMS) {
|
if (dataType == TransmissionData.DELAY_SPREAD || dataType == TransmissionData.DELAY_SPREAD_RMS) {
|
||||||
|
@ -1531,6 +1545,11 @@ public class ChannelModel {
|
||||||
return new double[] {receivedPower, accumulatedVariance};
|
return new double[] {receivedPower, accumulatedVariance};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class TrackedSignalComponents {
|
||||||
|
ArrayList<Line2D> components;
|
||||||
|
String log;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all rays from given source to given destination if a transmission
|
* Returns all rays from given source to given destination if a transmission
|
||||||
* were to be made. The resulting rays depend on the current settings and may
|
* were to be made. The resulting rays depend on the current settings and may
|
||||||
|
@ -1540,20 +1559,26 @@ public class ChannelModel {
|
||||||
* @param sourceY Source position Y
|
* @param sourceY Source position Y
|
||||||
* @param destX Destination position X
|
* @param destX Destination position X
|
||||||
* @param destY Destination position Y
|
* @param destY Destination position Y
|
||||||
* @return All resulting rays of a simulated transmission from source to destination
|
* @return Signal components and printable description
|
||||||
*/
|
*/
|
||||||
public Vector<Line2D> getRaysOfTransmission(double sourceX, double sourceY, double destX, double destY) {
|
public TrackedSignalComponents getRaysOfTransmission(double sourceX, double sourceY, double destX, double destY) {
|
||||||
|
TrackedSignalComponents tsc = new TrackedSignalComponents();
|
||||||
|
|
||||||
// Reset current rays vector
|
logInfo = new StringBuilder();
|
||||||
inLoggingMode = true;
|
loggedRays = new ArrayList<Line2D>();
|
||||||
savedRays = new Vector<Line2D>();
|
|
||||||
|
|
||||||
// Calculate rays, ignore power
|
/* TODO Include background noise? */
|
||||||
|
logMode = true;
|
||||||
getProbability(sourceX, sourceY, destX, destY, -Double.MAX_VALUE);
|
getProbability(sourceX, sourceY, destX, destY, -Double.MAX_VALUE);
|
||||||
|
logMode = false;
|
||||||
|
|
||||||
inLoggingMode = false;
|
tsc.log = logInfo.toString();
|
||||||
|
tsc.components = loggedRays;
|
||||||
|
|
||||||
return savedRays;
|
logInfo = null;
|
||||||
|
loggedRays = null;
|
||||||
|
|
||||||
|
return tsc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1562,18 +1587,18 @@ public class ChannelModel {
|
||||||
* variable. This method uses current parameters such as transmitted power,
|
* variable. This method uses current parameters such as transmitted power,
|
||||||
* obstacles, overall system loss etc.
|
* obstacles, overall system loss etc.
|
||||||
*
|
*
|
||||||
* @param sourceX
|
* @param sourceX Source position X
|
||||||
* Source position X
|
* @param sourceY Source position Y
|
||||||
* @param sourceY
|
* @param destX Destination position X
|
||||||
* Source position Y
|
* @param destY Destination position Y
|
||||||
* @param destX
|
* @return Received SNR (dB) random variable:
|
||||||
* Destination position X
|
* The first value in the array is the random variable mean.
|
||||||
* @param destY
|
* The second is the variance.
|
||||||
* Destination position Y
|
* The third value is the received signal strength which may be used in comparison with interference etc.
|
||||||
* @return Received SNR (dB) random variable. The first value is the random
|
|
||||||
* variable mean, and the second is the variance. The third value is the received signal strength which may be used in comparison with interference etc.
|
|
||||||
*/
|
*/
|
||||||
public double[] getSINR(double sourceX, double sourceY, double destX, double destY, double interference) {
|
public double[] getSINR(double sourceX, double sourceY, double destX, double destY, double interference) {
|
||||||
|
/* TODO Cache values: called repeatedly with noise sources. */
|
||||||
|
|
||||||
|
|
||||||
// Calculate received signal strength
|
// Calculate received signal strength
|
||||||
double[] signalStrength = getReceivedSignalStrength(sourceX, sourceY, destX, destY);
|
double[] signalStrength = getReceivedSignalStrength(sourceX, sourceY, destX, destY);
|
||||||
|
@ -1601,28 +1626,27 @@ public class ChannelModel {
|
||||||
snrData[0] -= noiseMean;
|
snrData[0] -= noiseMean;
|
||||||
snrData[1] += noiseVariance;
|
snrData[1] += noiseVariance;
|
||||||
|
|
||||||
if (inLoggingMode) {
|
if (logMode) {
|
||||||
logger.info("SNR at receiver:\t" + snrData[0] + " (" + snrData[1] + ")");
|
logInfo.append("\nReceived SNR: " + String.format("%2.3f", snrData[0]) + " dB (variance " + snrData[1] + ")\n");
|
||||||
}
|
}
|
||||||
return snrData;
|
return snrData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates and returns probability that a receiver at given destination receives a packet from a transmitter at given source.
|
* Calculates probability that a receiver at given destination receives
|
||||||
|
* a packet from a transmitter at given source.
|
||||||
* This method uses current parameters such as transmitted power,
|
* This method uses current parameters such as transmitted power,
|
||||||
* obstacles, overall system loss, packet size etc. TODO Packet size?! TODO Interfering signal strength
|
* obstacles, overall system loss, packet size etc.
|
||||||
*
|
*
|
||||||
* @param sourceX
|
* TODO Packet size
|
||||||
* Source position X
|
* TODO External interference/Background noise
|
||||||
* @param sourceY
|
*
|
||||||
* Source position Y
|
* @param sourceX Source position X
|
||||||
* @param destX
|
* @param sourceY Source position Y
|
||||||
* Destination position X
|
* @param destX Destination position X
|
||||||
* @param destY
|
* @param destY Destination position Y
|
||||||
* Destination position Y
|
* @param interference Current interference at destination (dBm)
|
||||||
* @param interference
|
|
||||||
* Current interference at destination (dBm)
|
|
||||||
* @return [Probability of reception, signal strength at destination]
|
* @return [Probability of reception, signal strength at destination]
|
||||||
*/
|
*/
|
||||||
public double[] getProbability(double sourceX, double sourceY, double destX, double destY, double interference) {
|
public double[] getProbability(double sourceX, double sourceY, double destX, double destY, double interference) {
|
||||||
|
@ -1634,9 +1658,10 @@ public class ChannelModel {
|
||||||
double rxSensitivity = getParameterDoubleValue("rx_sensitivity");
|
double rxSensitivity = getParameterDoubleValue("rx_sensitivity");
|
||||||
|
|
||||||
// Check signal strength against receiver sensitivity and interference
|
// Check signal strength against receiver sensitivity and interference
|
||||||
if (rxSensitivity > signalStrength - snrMean && threshold < rxSensitivity + snrMean - signalStrength) {
|
if (rxSensitivity > signalStrength - snrMean &&
|
||||||
if (inLoggingMode) {
|
threshold < rxSensitivity + snrMean - signalStrength) {
|
||||||
logger.info("Signal to low for receiver sensitivity, increasing threshold");
|
if (logMode) {
|
||||||
|
logInfo.append("Weak signal: increasing threshold\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keeping snr variance but increasing theshold to sensitivity
|
// Keeping snr variance but increasing theshold to sensitivity
|
||||||
|
@ -1657,11 +1682,10 @@ public class ChannelModel {
|
||||||
// current threshold.
|
// current threshold.
|
||||||
|
|
||||||
// (Using error algorithm method, much faster than taylor approximation!)
|
// (Using error algorithm method, much faster than taylor approximation!)
|
||||||
double probReception = 1 - GaussianWrapper.cdfErrorAlgo(
|
double probReception = 1 - GaussianWrapper.cdfErrorAlgo(threshold, snrMean, snrStdDev);
|
||||||
threshold, snrMean, snrStdDev);
|
|
||||||
|
|
||||||
if (inLoggingMode) {
|
if (logMode) {
|
||||||
logger.info("Probability of reception: " + probReception);
|
logInfo.append("Reception probability: " + String.format("%1.1f%%", 100*probReception) + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns probabilities
|
// Returns probabilities
|
||||||
|
@ -1684,7 +1708,7 @@ public class ChannelModel {
|
||||||
* @return RMS delay spread
|
* @return RMS delay spread
|
||||||
*/
|
*/
|
||||||
public double getRMSDelaySpread(double sourceX, double sourceY, double destX, double destY) {
|
public double getRMSDelaySpread(double sourceX, double sourceY, double destX, double destY) {
|
||||||
return getTransmissionData(sourceX, sourceY, destX, destY, TransmissionData.DELAY_SPREAD)[1];
|
return getTransmissionData(sourceX, sourceY, destX, destY, TransmissionData.DELAY_SPREAD, null)[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -43,13 +43,14 @@ import org.jdom.Element;
|
||||||
import se.sics.cooja.ClassDescription;
|
import se.sics.cooja.ClassDescription;
|
||||||
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.NoiseSourceRadio;
|
||||||
|
import se.sics.cooja.interfaces.NoiseSourceRadio.NoiseLevelListener;
|
||||||
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.radiomediums.AbstractRadioMedium;
|
import se.sics.cooja.radiomediums.AbstractRadioMedium;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the main class of the COOJA Multi-path Ray-tracing Medium (MRM)
|
* Multi-path Ray-tracing radio medium (MRM).
|
||||||
* package.
|
|
||||||
*
|
*
|
||||||
* MRM is an alternative to the simpler radio mediums available in
|
* MRM is an alternative to the simpler radio mediums available in
|
||||||
* COOJA. It is packet based and uses a 2D ray-tracing approach to approximate
|
* COOJA. It is packet based and uses a 2D ray-tracing approach to approximate
|
||||||
|
@ -57,22 +58,27 @@ import se.sics.cooja.radiomediums.AbstractRadioMedium;
|
||||||
* ray-tracing only supports reflections and refractions through homogeneous
|
* ray-tracing only supports reflections and refractions through homogeneous
|
||||||
* obstacles.
|
* obstacles.
|
||||||
*
|
*
|
||||||
* MRM registers two plugins: a plugin for visualizing the radio
|
* MRM provides two plugins: one for visualizing the radio environment,
|
||||||
* environments, and a plugin for configuring the radio medium parameters.
|
* and one for configuring the radio medium parameters.
|
||||||
*
|
*
|
||||||
* Future work includes adding support for diffraction and scattering.
|
* Future work includes adding support for diffraction and scattering.
|
||||||
*
|
*
|
||||||
|
* MRM supports noise source radios.
|
||||||
|
*
|
||||||
|
* @see NoiseSourceRadio
|
||||||
* @author Fredrik Osterlind
|
* @author Fredrik Osterlind
|
||||||
*/
|
*/
|
||||||
@ClassDescription("Multi-path Ray-tracer Medium (MRM)")
|
@ClassDescription("Multi-path Ray-tracer Medium (MRM)")
|
||||||
public class MRM extends AbstractRadioMedium {
|
public class MRM extends AbstractRadioMedium {
|
||||||
private static Logger logger = Logger.getLogger(MRM.class);
|
private static Logger logger = Logger.getLogger(MRM.class);
|
||||||
|
|
||||||
private ChannelModel currentChannelModel = null;
|
public final static boolean WITH_NOISE = true; /* NoiseSourceRadio:s */
|
||||||
|
public final static boolean WITH_CAPTURE_EFFECT = true;
|
||||||
private Random random = null;
|
|
||||||
|
|
||||||
private Simulation sim;
|
private Simulation sim;
|
||||||
|
private Random random = null;
|
||||||
|
private ChannelModel currentChannelModel = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies observers when this radio medium has changed settings.
|
* Notifies observers when this radio medium has changed settings.
|
||||||
*/
|
*/
|
||||||
|
@ -83,11 +89,9 @@ public class MRM extends AbstractRadioMedium {
|
||||||
*/
|
*/
|
||||||
public MRM(Simulation simulation) {
|
public MRM(Simulation simulation) {
|
||||||
super(simulation);
|
super(simulation);
|
||||||
|
|
||||||
sim = simulation;
|
sim = simulation;
|
||||||
|
|
||||||
random = simulation.getRandomGenerator();
|
random = simulation.getRandomGenerator();
|
||||||
|
|
||||||
// Create the channel model
|
|
||||||
currentChannelModel = new ChannelModel();
|
currentChannelModel = new ChannelModel();
|
||||||
|
|
||||||
/* Register plugins */
|
/* Register plugins */
|
||||||
|
@ -95,6 +99,26 @@ public class MRM extends AbstractRadioMedium {
|
||||||
sim.getGUI().registerPlugin(FormulaViewer.class);
|
sim.getGUI().registerPlugin(FormulaViewer.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NoiseLevelListener noiseListener = new NoiseLevelListener() {
|
||||||
|
public void noiseLevelChanged(NoiseSourceRadio radio, int signal) {
|
||||||
|
updateSignalStrengths();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
public void registerRadioInterface(Radio radio, Simulation sim) {
|
||||||
|
super.registerRadioInterface(radio, sim);
|
||||||
|
|
||||||
|
if (radio instanceof NoiseSourceRadio) {
|
||||||
|
((NoiseSourceRadio)radio).addNoiseLevelListener(noiseListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void unregisterRadioInterface(Radio radio, Simulation sim) {
|
||||||
|
super.unregisterRadioInterface(radio, sim);
|
||||||
|
|
||||||
|
if (radio instanceof NoiseSourceRadio) {
|
||||||
|
((NoiseSourceRadio)radio).removeNoiseLevelListener(noiseListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void removed() {
|
public void removed() {
|
||||||
super.removed();
|
super.removed();
|
||||||
|
|
||||||
|
@ -103,90 +127,82 @@ public class MRM extends AbstractRadioMedium {
|
||||||
sim.getGUI().unregisterPlugin(FormulaViewer.class);
|
sim.getGUI().unregisterPlugin(FormulaViewer.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MRMRadioConnection createConnections(Radio sendingRadio) {
|
public MRMRadioConnection createConnections(Radio sender) {
|
||||||
Position sendingPosition = sendingRadio.getPosition();
|
MRMRadioConnection newConnection = new MRMRadioConnection(sender);
|
||||||
MRMRadioConnection newConnection = new MRMRadioConnection(sendingRadio);
|
Position senderPos = sender.getPosition();
|
||||||
|
|
||||||
// Loop through all radios
|
/* TODO Cache potential destination in DGRM */
|
||||||
for (Radio listeningRadio: getRegisteredRadios()) {
|
/* Loop through all potential destinations */
|
||||||
// Ignore sending radio and radios on different channels
|
for (Radio recv: getRegisteredRadios()) {
|
||||||
if (sendingRadio == listeningRadio) {
|
if (sender == recv) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (sendingRadio.getChannel() >= 0 &&
|
|
||||||
listeningRadio.getChannel() >= 0 &&
|
|
||||||
sendingRadio.getChannel() != listeningRadio.getChannel()) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO Use DGRM to cache link information.
|
/* Fail if radios are on different (but configured) channels */
|
||||||
* (No need to loop over all receivers) */
|
if (sender.getChannel() >= 0 &&
|
||||||
|
recv.getChannel() >= 0 &&
|
||||||
|
sender.getChannel() != recv.getChannel()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Position recvPos = recv.getPosition();
|
||||||
|
|
||||||
double listeningPositionX = listeningRadio.getPosition().getXCoordinate();
|
/* Calculate receive probability */
|
||||||
double listeningPositionY = listeningRadio.getPosition().getYCoordinate();
|
|
||||||
|
|
||||||
// Calculate probability of reception of listening radio
|
|
||||||
double[] probData = currentChannelModel.getProbability(
|
double[] probData = currentChannelModel.getProbability(
|
||||||
sendingPosition.getXCoordinate(),
|
senderPos.getXCoordinate(),
|
||||||
sendingPosition.getYCoordinate(),
|
senderPos.getYCoordinate(),
|
||||||
listeningPositionX,
|
recvPos.getXCoordinate(),
|
||||||
listeningPositionY,
|
recvPos.getYCoordinate(),
|
||||||
-Double.MAX_VALUE
|
-Double.MAX_VALUE /* TODO Include interference */
|
||||||
);
|
);
|
||||||
|
|
||||||
//logger.info("Probability of reception is " + probData[0]);
|
double recvProb = probData[0];
|
||||||
//logger.info("Signal strength at destination is " + probData[1]);
|
double recvSignalStrength = probData[1];
|
||||||
if (random.nextFloat() < probData[0]) {
|
if (recvProb == 1.0 || random.nextDouble() < recvProb) {
|
||||||
// Check if this radio is able to receive transmission
|
/* Yes, the receiver *may* receive this packet (it's strong enough) */
|
||||||
if (listeningRadio.isInterfered()) {
|
if (!recv.isReceiverOn()) {
|
||||||
// Keep interfering radio
|
newConnection.addInterfered(recv);
|
||||||
newConnection.addInterfered(listeningRadio, probData[1]);
|
recv.interfereAnyReception();
|
||||||
|
} else if (recv.isInterfered()) {
|
||||||
|
/* Was interfered: keep interfering */
|
||||||
|
newConnection.addInterfered(recv, recvSignalStrength);
|
||||||
|
} else if (recv.isTransmitting()) {
|
||||||
|
newConnection.addInterfered(recv, recvSignalStrength);
|
||||||
|
} else if (recv.isReceiving()) {
|
||||||
|
/* Was already receiving: start interfering.
|
||||||
|
* Assuming no continuous preambles checking */
|
||||||
|
|
||||||
} else if (listeningRadio.isReceiving()) {
|
double currSignal = recv.getCurrentSignalStrength();
|
||||||
newConnection.addInterfered(listeningRadio, probData[1]);
|
/* Capture effect: recv-radio is already receiving.
|
||||||
|
* Are we strong enough to interfere? */
|
||||||
|
if (WITH_CAPTURE_EFFECT &&
|
||||||
|
recvSignalStrength < currSignal - 3 /* config */) {
|
||||||
|
/* No, we are too weak */
|
||||||
|
} else {
|
||||||
|
newConnection.addInterfered(recv, recvSignalStrength);
|
||||||
|
recv.interfereAnyReception();
|
||||||
|
|
||||||
// Start interfering radio
|
/* Interfere receiver in all other active radio connections */
|
||||||
listeningRadio.interfereAnyReception();
|
for (RadioConnection conn : getActiveConnections()) {
|
||||||
|
if (conn.isDestination(recv)) {
|
||||||
// Update connection that is transmitting to this radio
|
conn.addInterfered(recv);
|
||||||
MRMRadioConnection existingConn = null;
|
|
||||||
for (RadioConnection conn : getActiveConnections()) {
|
|
||||||
for (Radio dstRadio : ((MRMRadioConnection) conn).getDestinations()) {
|
|
||||||
if (dstRadio == listeningRadio) {
|
|
||||||
existingConn = (MRMRadioConnection) conn;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (existingConn != null) {
|
|
||||||
/* Flag radio as interfered */
|
|
||||||
existingConn.addInterfered(listeningRadio);
|
|
||||||
listeningRadio.interfereAnyReception();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Radio OK to receive
|
/* Success: radio starts receiving */
|
||||||
//logger.info("OK, creating connection and starting to transmit");
|
newConnection.addDestination(recv, recvSignalStrength);
|
||||||
newConnection.addDestination(listeningRadio, probData[1]);
|
|
||||||
}
|
}
|
||||||
} else if (probData[1] > currentChannelModel.getParameterDoubleValue("bg_noise_mean")) {
|
} else if (recvSignalStrength > currentChannelModel.getParameterDoubleValue("bg_noise_mean")) {
|
||||||
// Interfere radio
|
/* The incoming signal is strong, but strong enough to interfere? */
|
||||||
newConnection.addInterfered(listeningRadio, probData[1]);
|
|
||||||
listeningRadio.interfereAnyReception();
|
|
||||||
|
|
||||||
// TODO Radios always get interfered right now, should recalculate probability
|
|
||||||
// if (maxInterferenceSignalStrength + SOME_RELEVANT_LIMIT > transmissionSignalStrength) {
|
|
||||||
// // Recalculating probability of delivery
|
|
||||||
// double[] probData = currentChannelModel.getProbability(
|
|
||||||
// mySource.source.position.getXCoordinate(),
|
|
||||||
// mySource.source.position.getYCoordinate(),
|
|
||||||
// myDestination.position.getXCoordinate(),
|
|
||||||
// myDestination.position.getYCoordinate(),
|
|
||||||
// maxInterferenceSignalStrength);
|
|
||||||
//
|
|
||||||
// if (new Random().nextFloat() >= probData[0]) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
if (!WITH_CAPTURE_EFFECT) {
|
||||||
|
newConnection.addInterfered(recv, recvSignalStrength);
|
||||||
|
recv.interfereAnyReception();
|
||||||
|
} else {
|
||||||
|
/* TODO Implement new type: newConnection.addNoise()?
|
||||||
|
* Currently, this connection will never disturb this radio... */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -195,57 +211,92 @@ public class MRM extends AbstractRadioMedium {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSignalStrengths() {
|
public void updateSignalStrengths() {
|
||||||
// // Save old signal strengths
|
|
||||||
// double[] oldSignalStrengths = new double[registeredRadios.size()];
|
|
||||||
// for (int i = 0; i < registeredRadios.size(); i++) {
|
|
||||||
// oldSignalStrengths[i] = registeredRadios.get(i)
|
|
||||||
// .getCurrentSignalStrength();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Reset signal strength on all radios
|
/* Reset: Background noise */
|
||||||
|
double background =
|
||||||
|
currentChannelModel.getParameterDoubleValue(("bg_noise_mean"));
|
||||||
for (Radio radio : getRegisteredRadios()) {
|
for (Radio radio : getRegisteredRadios()) {
|
||||||
radio.setCurrentSignalStrength(currentChannelModel.getParameterDoubleValue(("bg_noise_mean")));
|
radio.setCurrentSignalStrength(background);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set signal strength on all OK transmissions
|
/* Active radio connections */
|
||||||
for (RadioConnection conn : getActiveConnections()) {
|
RadioConnection[] conns = getActiveConnections();
|
||||||
// ((MRMRadioConnection) conn).getSource().setCurrentSignalStrength(12345); // TODO Set signal strength on source?
|
for (RadioConnection conn : conns) {
|
||||||
for (Radio dstRadio : ((MRMRadioConnection) conn).getDestinations()) {
|
for (Radio dstRadio : ((MRMRadioConnection) conn).getDestinations()) {
|
||||||
double signalStrength = ((MRMRadioConnection) conn).getDestinationSignalStrength(dstRadio);
|
double signalStrength = ((MRMRadioConnection) conn).getDestinationSignalStrength(dstRadio);
|
||||||
if (signalStrength > dstRadio.getCurrentSignalStrength()) {
|
if (dstRadio.getCurrentSignalStrength() < signalStrength) {
|
||||||
dstRadio.setCurrentSignalStrength(signalStrength);
|
dstRadio.setCurrentSignalStrength(signalStrength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set signal strength on all interferences
|
/* Interfering/colliding radio connections */
|
||||||
for (RadioConnection conn : getActiveConnections()) {
|
for (RadioConnection conn : conns) {
|
||||||
for (Radio interferedRadio : ((MRMRadioConnection) conn).getInterfered()) {
|
for (Radio intfRadio : ((MRMRadioConnection) conn).getInterfered()) {
|
||||||
double signalStrength = ((MRMRadioConnection) conn).getInterferenceSignalStrength(interferedRadio);
|
double signalStrength = ((MRMRadioConnection) conn).getInterferenceSignalStrength(intfRadio);
|
||||||
if (signalStrength > interferedRadio.getCurrentSignalStrength()) {
|
if (intfRadio.getCurrentSignalStrength() < signalStrength) {
|
||||||
interferedRadio.setCurrentSignalStrength(signalStrength);
|
intfRadio.setCurrentSignalStrength(signalStrength);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!interferedRadio.isInterfered()) {
|
if (!intfRadio.isInterfered()) {
|
||||||
// Set to interfered again
|
/*logger.warn("Radio was not interfered: " + intfRadio);*/
|
||||||
interferedRadio.interfereAnyReception();
|
intfRadio.interfereAnyReception();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Fetch new signal strengths
|
/* Check for noise sources */
|
||||||
// double[] newSignalStrengths = new double[registeredRadios.size()];
|
if (!WITH_NOISE) return;
|
||||||
// for (int i = 0; i < registeredRadios.size(); i++) {
|
for (Radio noiseRadio: getRegisteredRadios()) {
|
||||||
// newSignalStrengths[i] = registeredRadios.get(i)
|
if (!(noiseRadio instanceof NoiseSourceRadio)) {
|
||||||
// .getCurrentSignalStrength();
|
continue;
|
||||||
// }
|
}
|
||||||
//
|
NoiseSourceRadio radio = (NoiseSourceRadio) noiseRadio;
|
||||||
// // Compare new and old signal strengths
|
int signalStrength = radio.getNoiseLevel();
|
||||||
// for (int i = 0; i < registeredRadios.size(); i++) {
|
if (signalStrength == Integer.MIN_VALUE) {
|
||||||
// if (oldSignalStrengths[i] != newSignalStrengths[i])
|
continue;
|
||||||
// logger.warn("Signal strengths changed on radio[" + i + "]: "
|
}
|
||||||
// + oldSignalStrengths[i] + " -> " + newSignalStrengths[i]);
|
|
||||||
// }
|
/* Calculate how noise source affects surrounding radios */
|
||||||
|
for (Radio affectedRadio : getRegisteredRadios()) {
|
||||||
|
if (noiseRadio == affectedRadio) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update noise levels */
|
||||||
|
double[] signalMeanVar = currentChannelModel.getReceivedSignalStrength(
|
||||||
|
noiseRadio.getPosition().getXCoordinate(),
|
||||||
|
noiseRadio.getPosition().getYCoordinate(),
|
||||||
|
affectedRadio.getPosition().getXCoordinate(),
|
||||||
|
affectedRadio.getPosition().getYCoordinate(),
|
||||||
|
(double) signalStrength); /* TODO Convert to dBm */
|
||||||
|
double signal = signalMeanVar[0];
|
||||||
|
if (signal < background) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO Additive signals strengths? */
|
||||||
|
/* TODO XXX Consider radio channels */
|
||||||
|
/* TODO XXX Potentially interfere even when signal is weaker (~3dB)...
|
||||||
|
* (we may alternatively just use the getSINR method...) */
|
||||||
|
if (affectedRadio.getCurrentSignalStrength() < signal) {
|
||||||
|
affectedRadio.setCurrentSignalStrength(signal);
|
||||||
|
|
||||||
|
/* TODO Interfere with radio connections? */
|
||||||
|
if (affectedRadio.isReceiving() && !affectedRadio.isInterfered()) {
|
||||||
|
for (RadioConnection conn : conns) {
|
||||||
|
if (conn.isDestination(affectedRadio)) {
|
||||||
|
/* Intefere with current reception, mark radio as interfered */
|
||||||
|
conn.addInterfered(affectedRadio);
|
||||||
|
if (!affectedRadio.isInterfered()) {
|
||||||
|
affectedRadio.interfereAnyReception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<Element> getConfigXML() {
|
public Collection<Element> getConfigXML() {
|
||||||
|
@ -279,20 +330,11 @@ public class MRM extends AbstractRadioMedium {
|
||||||
settingsObservable.deleteObserver(obs);
|
settingsObservable.deleteObserver(obs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns position of given radio.
|
|
||||||
*
|
|
||||||
* @param radio Registered radio
|
|
||||||
* @return Position of given radio
|
|
||||||
*/
|
|
||||||
public Position getRadioPosition(Radio radio) {
|
|
||||||
return radio.getPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Number of registered radios.
|
* @return Number of registered radios.
|
||||||
*/
|
*/
|
||||||
public int getRegisteredRadioCount() {
|
public int getRegisteredRadioCount() {
|
||||||
|
/* TODO Expensive operation */
|
||||||
return getRegisteredRadios().length;
|
return getRegisteredRadios().length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,10 +383,16 @@ public class MRM extends AbstractRadioMedium {
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getDestinationSignalStrength(Radio radio) {
|
public double getDestinationSignalStrength(Radio radio) {
|
||||||
|
if (signalStrengths.get(radio) == null) {
|
||||||
|
return Double.MIN_VALUE;
|
||||||
|
}
|
||||||
return signalStrengths.get(radio);
|
return signalStrengths.get(radio);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getInterferenceSignalStrength(Radio radio) {
|
public double getInterferenceSignalStrength(Radio radio) {
|
||||||
|
if (signalStrengths.get(radio) == null) {
|
||||||
|
return Double.MIN_VALUE;
|
||||||
|
}
|
||||||
return signalStrengths.get(radio);
|
return signalStrengths.get(radio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ public class SkyButton extends Button {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPressed() {
|
public boolean isPressed() {
|
||||||
logger.warn("Not implemented");
|
/* Not implemented */
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
88
tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/SkyByteRadio.java
Executable file → Normal file
88
tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/SkyByteRadio.java
Executable file → Normal file
|
@ -31,17 +31,7 @@
|
||||||
|
|
||||||
package se.sics.cooja.mspmote.interfaces;
|
package se.sics.cooja.mspmote.interfaces;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
|
||||||
import java.awt.GridLayout;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Observable;
|
|
||||||
import java.util.Observer;
|
|
||||||
|
|
||||||
import javax.swing.JButton;
|
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
@ -385,84 +375,6 @@ public class SkyByteRadio extends Radio implements CustomDataRadio {
|
||||||
rssiLastCounter = 8;
|
rssiLastCounter = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JPanel getInterfaceVisualizer() {
|
|
||||||
// Location
|
|
||||||
JPanel wrapperPanel = new JPanel(new BorderLayout());
|
|
||||||
JPanel panel = new JPanel(new GridLayout(5, 2));
|
|
||||||
|
|
||||||
final JLabel statusLabel = new JLabel("");
|
|
||||||
final JLabel lastEventLabel = new JLabel("");
|
|
||||||
final JLabel channelLabel = new JLabel("");
|
|
||||||
final JLabel powerLabel = new JLabel("");
|
|
||||||
final JLabel ssLabel = new JLabel("");
|
|
||||||
final JButton updateButton = new JButton("Update");
|
|
||||||
|
|
||||||
panel.add(new JLabel("STATE:"));
|
|
||||||
panel.add(statusLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("LAST EVENT:"));
|
|
||||||
panel.add(lastEventLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("CHANNEL:"));
|
|
||||||
panel.add(channelLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("OUTPUT POWER:"));
|
|
||||||
panel.add(powerLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("SIGNAL STRENGTH:"));
|
|
||||||
JPanel smallPanel = new JPanel(new GridLayout(1, 2));
|
|
||||||
smallPanel.add(ssLabel);
|
|
||||||
smallPanel.add(updateButton);
|
|
||||||
panel.add(smallPanel);
|
|
||||||
|
|
||||||
updateButton.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
channelLabel.setText(getChannel() + " (freq=" + getFrequency() + " MHz)");
|
|
||||||
powerLabel.setText(getCurrentOutputPower() + " dBm (indicator=" + getCurrentOutputPowerIndicator() + "/" + getOutputPowerIndicatorMax() + ")");
|
|
||||||
ssLabel.setText(getCurrentSignalStrength() + " dBm");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Observer observer;
|
|
||||||
this.addObserver(observer = new Observer() {
|
|
||||||
public void update(Observable obs, Object obj) {
|
|
||||||
if (isTransmitting()) {
|
|
||||||
statusLabel.setText("transmitting");
|
|
||||||
} else if (isReceiving()) {
|
|
||||||
statusLabel.setText("receiving");
|
|
||||||
} else if (isReceiverOn()) {
|
|
||||||
statusLabel.setText("listening for traffic");
|
|
||||||
} else {
|
|
||||||
statusLabel.setText("HW off");
|
|
||||||
}
|
|
||||||
|
|
||||||
lastEventLabel.setText(lastEvent + " @ time=" + lastEventTime);
|
|
||||||
|
|
||||||
channelLabel.setText(getChannel() + " (freq=" + getFrequency() + " MHz)");
|
|
||||||
powerLabel.setText(getCurrentOutputPower() + " dBm (indicator=" + getCurrentOutputPowerIndicator() + "/" + getOutputPowerIndicatorMax() + ")");
|
|
||||||
ssLabel.setText(getCurrentSignalStrength() + " dBm");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.update(null, null);
|
|
||||||
|
|
||||||
wrapperPanel.add(BorderLayout.NORTH, panel);
|
|
||||||
|
|
||||||
// Saving observer reference for releaseInterfaceVisualizer
|
|
||||||
wrapperPanel.putClientProperty("intf_obs", observer);
|
|
||||||
return wrapperPanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void releaseInterfaceVisualizer(JPanel panel) {
|
|
||||||
Observer observer = (Observer) panel.getClientProperty("intf_obs");
|
|
||||||
if (observer == null) {
|
|
||||||
logger.fatal("Error when releasing panel, observer is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.deleteObserver(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mote getMote() {
|
public Mote getMote() {
|
||||||
return mote;
|
return mote;
|
||||||
}
|
}
|
||||||
|
|
|
@ -355,86 +355,6 @@ public class TR1001Radio extends Radio implements USARTListener, CustomDataRadio
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public JPanel getInterfaceVisualizer() {
|
|
||||||
// Location
|
|
||||||
JPanel wrapperPanel = new JPanel(new BorderLayout());
|
|
||||||
JPanel panel = new JPanel(new GridLayout(5, 2));
|
|
||||||
|
|
||||||
final JLabel statusLabel = new JLabel("");
|
|
||||||
final JLabel lastEventLabel = new JLabel("");
|
|
||||||
final JLabel channelLabel = new JLabel("ALL CHANNELS (-1)");
|
|
||||||
final JLabel powerLabel = new JLabel("");
|
|
||||||
final JLabel ssLabel = new JLabel("");
|
|
||||||
final JButton updateButton = new JButton("Update");
|
|
||||||
|
|
||||||
panel.add(new JLabel("STATE:"));
|
|
||||||
panel.add(statusLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("LAST EVENT:"));
|
|
||||||
panel.add(lastEventLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("CHANNEL:"));
|
|
||||||
panel.add(channelLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("OUTPUT POWER:"));
|
|
||||||
panel.add(powerLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("SIGNAL STRENGTH:"));
|
|
||||||
JPanel smallPanel = new JPanel(new GridLayout(1, 2));
|
|
||||||
smallPanel.add(ssLabel);
|
|
||||||
smallPanel.add(updateButton);
|
|
||||||
panel.add(smallPanel);
|
|
||||||
|
|
||||||
updateButton.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
powerLabel.setText(getCurrentOutputPower() + " dBm (indicator="
|
|
||||||
+ getCurrentOutputPowerIndicator() + "/"
|
|
||||||
+ getOutputPowerIndicatorMax() + ")");
|
|
||||||
ssLabel.setText(getCurrentSignalStrength() + " dBm");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Observer observer;
|
|
||||||
this.addObserver(observer = new Observer() {
|
|
||||||
public void update(Observable obs, Object obj) {
|
|
||||||
if (isTransmitting()) {
|
|
||||||
statusLabel.setText("transmitting");
|
|
||||||
} else if (isReceiving()) {
|
|
||||||
statusLabel.setText("receiving");
|
|
||||||
} else if (radioOn) {
|
|
||||||
statusLabel.setText("listening for traffic");
|
|
||||||
} else {
|
|
||||||
statusLabel.setText("HW off");
|
|
||||||
}
|
|
||||||
|
|
||||||
lastEventLabel.setText(lastEvent + " @ time=" + lastEventTime);
|
|
||||||
|
|
||||||
powerLabel.setText(getCurrentOutputPower() + " dBm (indicator="
|
|
||||||
+ getCurrentOutputPowerIndicator() + "/"
|
|
||||||
+ getOutputPowerIndicatorMax() + ")");
|
|
||||||
ssLabel.setText(getCurrentSignalStrength() + " dBm");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.update(null, null);
|
|
||||||
|
|
||||||
// Saving observer reference for releaseInterfaceVisualizer
|
|
||||||
panel.putClientProperty("intf_obs", observer);
|
|
||||||
|
|
||||||
wrapperPanel.add(BorderLayout.NORTH, panel);
|
|
||||||
return wrapperPanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void releaseInterfaceVisualizer(JPanel panel) {
|
|
||||||
Observer observer = (Observer) panel.getClientProperty("intf_obs");
|
|
||||||
if (observer == null) {
|
|
||||||
logger.fatal("Error when releasing panel, observer is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.deleteObserver(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<Element> getConfigXML() {
|
public Collection<Element> getConfigXML() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -685,6 +685,12 @@ public class Simulation extends Observable implements Runnable {
|
||||||
|
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers(this);
|
notifyObservers(this);
|
||||||
|
|
||||||
|
/* Execute simulation thread events now, before simulation starts */
|
||||||
|
while (hasPollRequests) {
|
||||||
|
popSimulationInvokes().run();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -345,84 +345,6 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public JPanel getInterfaceVisualizer() {
|
|
||||||
// Location
|
|
||||||
JPanel wrapperPanel = new JPanel(new BorderLayout());
|
|
||||||
JPanel panel = new JPanel(new GridLayout(5, 2));
|
|
||||||
|
|
||||||
final JLabel statusLabel = new JLabel("");
|
|
||||||
final JLabel lastEventLabel = new JLabel("");
|
|
||||||
final JLabel channelLabel = new JLabel("");
|
|
||||||
final JLabel powerLabel = new JLabel("");
|
|
||||||
final JLabel ssLabel = new JLabel("");
|
|
||||||
final JButton updateButton = new JButton("Update");
|
|
||||||
|
|
||||||
panel.add(new JLabel("STATE:"));
|
|
||||||
panel.add(statusLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("LAST EVENT:"));
|
|
||||||
panel.add(lastEventLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("CHANNEL:"));
|
|
||||||
panel.add(channelLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("OUTPUT POWER:"));
|
|
||||||
panel.add(powerLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("SIGNAL STRENGTH:"));
|
|
||||||
JPanel smallPanel = new JPanel(new GridLayout(1, 2));
|
|
||||||
smallPanel.add(ssLabel);
|
|
||||||
smallPanel.add(updateButton);
|
|
||||||
panel.add(smallPanel);
|
|
||||||
|
|
||||||
updateButton.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
channelLabel.setText("" + getChannel());
|
|
||||||
powerLabel.setText(getCurrentOutputPower() + " dBm (indicator=" + getCurrentOutputPowerIndicator() + "/" + getOutputPowerIndicatorMax() + ")");
|
|
||||||
ssLabel.setText(getCurrentSignalStrength() + " dBm");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Observer observer;
|
|
||||||
this.addObserver(observer = new Observer() {
|
|
||||||
public void update(Observable obs, Object obj) {
|
|
||||||
if (isTransmitting()) {
|
|
||||||
statusLabel.setText("transmitting");
|
|
||||||
} else if (isReceiving()) {
|
|
||||||
statusLabel.setText("receiving");
|
|
||||||
} else if (radioOn) {
|
|
||||||
statusLabel.setText("listening for traffic");
|
|
||||||
} else {
|
|
||||||
statusLabel.setText("HW off");
|
|
||||||
}
|
|
||||||
|
|
||||||
lastEventLabel.setText(lastEvent + " @ time=" + lastEventTime);
|
|
||||||
|
|
||||||
channelLabel.setText("" + getChannel());
|
|
||||||
powerLabel.setText(getCurrentOutputPower() + " dBm (indicator=" + getCurrentOutputPowerIndicator() + "/" + getOutputPowerIndicatorMax() + ")");
|
|
||||||
ssLabel.setText(getCurrentSignalStrength() + " dBm");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.update(null, null);
|
|
||||||
|
|
||||||
wrapperPanel.add(BorderLayout.NORTH, panel);
|
|
||||||
|
|
||||||
// Saving observer reference for releaseInterfaceVisualizer
|
|
||||||
wrapperPanel.putClientProperty("intf_obs", observer);
|
|
||||||
return wrapperPanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void releaseInterfaceVisualizer(JPanel panel) {
|
|
||||||
Observer observer = (Observer) panel.getClientProperty("intf_obs");
|
|
||||||
if (observer == null) {
|
|
||||||
logger.fatal("Error when releasing panel, observer is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.deleteObserver(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<Element> getConfigXML() {
|
public Collection<Element> getConfigXML() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,7 +346,10 @@ public abstract class SerialUI extends Log implements SerialPort {
|
||||||
} else {
|
} else {
|
||||||
newMessage.append((char) data);
|
newMessage.append((char) data);
|
||||||
if (newMessage.length() > MAX_LENGTH) {
|
if (newMessage.length() > MAX_LENGTH) {
|
||||||
logger.warn("Dropping too large log message (>" + MAX_LENGTH + " bytes).");
|
/*logger.warn("Dropping too large log message (>" + MAX_LENGTH + " bytes).");*/
|
||||||
|
lastLogMessage = "# [1024 bytes binary data]";
|
||||||
|
this.setChanged();
|
||||||
|
this.notifyObservers(getMote());
|
||||||
newMessage.setLength(0);
|
newMessage.setLength(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,84 +250,6 @@ public abstract class Radio802154 extends Radio implements CustomDataRadio {
|
||||||
notifyObservers();
|
notifyObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public JPanel getInterfaceVisualizer() {
|
|
||||||
// Location
|
|
||||||
JPanel wrapperPanel = new JPanel(new BorderLayout());
|
|
||||||
JPanel panel = new JPanel(new GridLayout(5, 2));
|
|
||||||
|
|
||||||
final JLabel statusLabel = new JLabel("");
|
|
||||||
final JLabel lastEventLabel = new JLabel("");
|
|
||||||
final JLabel channelLabel = new JLabel("");
|
|
||||||
final JLabel powerLabel = new JLabel("");
|
|
||||||
final JLabel ssLabel = new JLabel("");
|
|
||||||
final JButton updateButton = new JButton("Update");
|
|
||||||
|
|
||||||
panel.add(new JLabel("STATE:"));
|
|
||||||
panel.add(statusLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("LAST EVENT:"));
|
|
||||||
panel.add(lastEventLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("CHANNEL:"));
|
|
||||||
panel.add(channelLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("OUTPUT POWER:"));
|
|
||||||
panel.add(powerLabel);
|
|
||||||
|
|
||||||
panel.add(new JLabel("SIGNAL STRENGTH:"));
|
|
||||||
JPanel smallPanel = new JPanel(new GridLayout(1, 2));
|
|
||||||
smallPanel.add(ssLabel);
|
|
||||||
smallPanel.add(updateButton);
|
|
||||||
panel.add(smallPanel);
|
|
||||||
|
|
||||||
updateButton.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
channelLabel.setText(getChannel() + " (freq=" + getFrequency() + " MHz)");
|
|
||||||
powerLabel.setText(getCurrentOutputPower() + " dBm (indicator=" + getCurrentOutputPowerIndicator() + "/" + getOutputPowerIndicatorMax() + ")");
|
|
||||||
ssLabel.setText(getCurrentSignalStrength() + " dBm");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Observer observer;
|
|
||||||
this.addObserver(observer = new Observer() {
|
|
||||||
public void update(Observable obs, Object obj) {
|
|
||||||
if (isTransmitting()) {
|
|
||||||
statusLabel.setText("transmitting");
|
|
||||||
} else if (isReceiving()) {
|
|
||||||
statusLabel.setText("receiving");
|
|
||||||
} else if (radioOn /* mode != CC2420.MODE_TXRX_OFF */) {
|
|
||||||
statusLabel.setText("listening for traffic");
|
|
||||||
} else {
|
|
||||||
statusLabel.setText("HW off");
|
|
||||||
}
|
|
||||||
|
|
||||||
lastEventLabel.setText(lastEvent + " @ time=" + lastEventTime);
|
|
||||||
|
|
||||||
channelLabel.setText(getChannel() + " (freq=" + getFrequency() + " MHz)");
|
|
||||||
powerLabel.setText(getCurrentOutputPower() + " dBm (indicator=" + getCurrentOutputPowerIndicator() + "/" + getOutputPowerIndicatorMax() + ")");
|
|
||||||
ssLabel.setText(getCurrentSignalStrength() + " dBm");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.update(null, null);
|
|
||||||
|
|
||||||
wrapperPanel.add(BorderLayout.NORTH, panel);
|
|
||||||
|
|
||||||
// Saving observer reference for releaseInterfaceVisualizer
|
|
||||||
wrapperPanel.putClientProperty("intf_obs", observer);
|
|
||||||
return wrapperPanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void releaseInterfaceVisualizer(JPanel panel) {
|
|
||||||
Observer observer = (Observer) panel.getClientProperty("intf_obs");
|
|
||||||
if (observer == null) {
|
|
||||||
logger.fatal("Error when releasing panel, observer is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.deleteObserver(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mote getMote() {
|
public Mote getMote() {
|
||||||
return mote;
|
return mote;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ package se.sics.cooja.interfaces;
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
|
@ -61,7 +62,7 @@ import se.sics.cooja.Simulation;
|
||||||
*
|
*
|
||||||
* @author Fredrik Osterlind
|
* @author Fredrik Osterlind
|
||||||
*/
|
*/
|
||||||
public class ApplicationRadio extends Radio {
|
public class ApplicationRadio extends Radio implements NoiseSourceRadio {
|
||||||
private static Logger logger = Logger.getLogger(ApplicationRadio.class);
|
private static Logger logger = Logger.getLogger(ApplicationRadio.class);
|
||||||
|
|
||||||
private Simulation simulation;
|
private Simulation simulation;
|
||||||
|
@ -321,7 +322,7 @@ public class ApplicationRadio extends Radio {
|
||||||
updateButton.addActionListener(new ActionListener() {
|
updateButton.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
ssLabel.setText("Signal strength (not auto-updated): "
|
ssLabel.setText("Signal strength (not auto-updated): "
|
||||||
+ getCurrentSignalStrength() + " dBm");
|
+ String.format("%1.1f", getCurrentSignalStrength()) + " dBm");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -337,7 +338,7 @@ public class ApplicationRadio extends Radio {
|
||||||
|
|
||||||
lastEventLabel.setText("Last event (time=" + lastEventTime + "): " + lastEvent);
|
lastEventLabel.setText("Last event (time=" + lastEventTime + "): " + lastEvent);
|
||||||
ssLabel.setText("Signal strength (not auto-updated): "
|
ssLabel.setText("Signal strength (not auto-updated): "
|
||||||
+ getCurrentSignalStrength() + " dBm");
|
+ String.format("%1.1f", getCurrentSignalStrength()) + " dBm");
|
||||||
if (getChannel() == -1) {
|
if (getChannel() == -1) {
|
||||||
channelLabel.setText("Current channel: ALL");
|
channelLabel.setText("Current channel: ALL");
|
||||||
} else {
|
} else {
|
||||||
|
@ -354,17 +355,8 @@ public class ApplicationRadio extends Radio {
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void releaseInterfaceVisualizer(JPanel panel) {
|
|
||||||
Observer observer = (Observer) panel.getClientProperty("intf_obs");
|
|
||||||
if (observer == null) {
|
|
||||||
logger.fatal("Error when releasing panel, observer is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.deleteObserver(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<Element> getConfigXML() {
|
public Collection<Element> getConfigXML() {
|
||||||
|
/* TODO Save channel info? */
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,4 +382,27 @@ public class ApplicationRadio extends Radio {
|
||||||
public boolean isReceiverOn() {
|
public boolean isReceiverOn() {
|
||||||
return radioOn;
|
return radioOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Noise source radio support */
|
||||||
|
public int getNoiseLevel() {
|
||||||
|
return noiseSignal;
|
||||||
|
}
|
||||||
|
public void addNoiseLevelListener(NoiseLevelListener l) {
|
||||||
|
noiseListeners.add(l);
|
||||||
|
}
|
||||||
|
public void removeNoiseLevelListener(NoiseLevelListener l) {
|
||||||
|
noiseListeners.remove(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Noise source radio support (app mote API) */
|
||||||
|
private int noiseSignal = Integer.MIN_VALUE;
|
||||||
|
private ArrayList<NoiseLevelListener> noiseListeners = new ArrayList<NoiseLevelListener>();
|
||||||
|
public void setNoiseLevel(int signal) {
|
||||||
|
this.noiseSignal = signal;
|
||||||
|
for (NoiseLevelListener l: noiseListeners) {
|
||||||
|
l.noiseLevelChanged(this, signal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.sics.cooja.interfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The noise source radio is used to simulate ambient background noise or
|
||||||
|
* point-sources of external interference (e.g. Wifi basestations).
|
||||||
|
*
|
||||||
|
* Note that interference generated from these radios are different from
|
||||||
|
* transmissions; they will not appear in the radio logger but may still
|
||||||
|
* hinder or interfere with ongoing transmissions.
|
||||||
|
*
|
||||||
|
* Noise source radios require significant processing resources in comparison
|
||||||
|
* to only transmission radios.
|
||||||
|
*
|
||||||
|
* COOJA's radio mediums may or may not choose to respect noise source radios.
|
||||||
|
*
|
||||||
|
* @see MRM
|
||||||
|
* @author Fredrik Osterlind
|
||||||
|
*/
|
||||||
|
public interface NoiseSourceRadio {
|
||||||
|
public int getNoiseLevel();
|
||||||
|
|
||||||
|
public void addNoiseLevelListener(NoiseLevelListener l);
|
||||||
|
public void removeNoiseLevelListener(NoiseLevelListener l);
|
||||||
|
|
||||||
|
public interface NoiseLevelListener {
|
||||||
|
public void noiseLevelChanged(NoiseSourceRadio radio, int signal);
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,21 +29,37 @@
|
||||||
|
|
||||||
package se.sics.cooja.interfaces;
|
package se.sics.cooja.interfaces;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.Observable;
|
||||||
|
import java.util.Observer;
|
||||||
|
|
||||||
|
import javax.swing.Box;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import se.sics.cooja.ClassDescription;
|
import se.sics.cooja.ClassDescription;
|
||||||
import se.sics.cooja.Mote;
|
import se.sics.cooja.Mote;
|
||||||
import se.sics.cooja.MoteInterface;
|
import se.sics.cooja.MoteInterface;
|
||||||
import se.sics.cooja.RadioPacket;
|
import se.sics.cooja.RadioPacket;
|
||||||
|
import se.sics.cooja.contikimote.interfaces.ContikiRadio;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Radio represents a mote radio transceiver.
|
* A mote radio transceiver.
|
||||||
*
|
*
|
||||||
* @see RadioPacket
|
* @see ContikiRadio
|
||||||
* @see CustomDataRadio
|
* @see CustomDataRadio
|
||||||
|
* @see NoiseSourceRadio
|
||||||
*
|
*
|
||||||
* @author Fredrik Osterlind
|
* @author Fredrik Osterlind
|
||||||
*/
|
*/
|
||||||
@ClassDescription("Radio")
|
@ClassDescription("Radio")
|
||||||
public abstract class Radio extends MoteInterface {
|
public abstract class Radio extends MoteInterface {
|
||||||
|
private static Logger logger = Logger.getLogger(Radio.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Events that radios should notify observers about.
|
* Events that radios should notify observers about.
|
||||||
|
@ -191,4 +207,66 @@ public abstract class Radio extends MoteInterface {
|
||||||
*/
|
*/
|
||||||
public abstract Mote getMote();
|
public abstract Mote getMote();
|
||||||
|
|
||||||
|
|
||||||
|
public JPanel getInterfaceVisualizer() {
|
||||||
|
JPanel panel = new JPanel(new BorderLayout());
|
||||||
|
Box box = Box.createVerticalBox();
|
||||||
|
|
||||||
|
final JLabel statusLabel = new JLabel("");
|
||||||
|
final JLabel lastEventLabel = new JLabel("");
|
||||||
|
final JLabel channelLabel = new JLabel("");
|
||||||
|
final JLabel ssLabel = new JLabel("");
|
||||||
|
final JButton updateButton = new JButton("Update SS");
|
||||||
|
|
||||||
|
box.add(statusLabel);
|
||||||
|
box.add(lastEventLabel);
|
||||||
|
box.add(ssLabel);
|
||||||
|
box.add(updateButton);
|
||||||
|
box.add(channelLabel);
|
||||||
|
|
||||||
|
updateButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
ssLabel.setText("Signal strength (not auto-updated): "
|
||||||
|
+ String.format("%1.1f", getCurrentSignalStrength()) + " dBm");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final Observer observer = new Observer() {
|
||||||
|
public void update(Observable obs, Object obj) {
|
||||||
|
if (isTransmitting()) {
|
||||||
|
statusLabel.setText("Transmitting");
|
||||||
|
} else if (isReceiving()) {
|
||||||
|
statusLabel.setText("Receiving");
|
||||||
|
} else {
|
||||||
|
statusLabel.setText("Listening");
|
||||||
|
}
|
||||||
|
|
||||||
|
lastEventLabel.setText("Last event: " + getLastEvent());
|
||||||
|
ssLabel.setText("Signal strength (not auto-updated): "
|
||||||
|
+ String.format("%1.1f", getCurrentSignalStrength()) + " dBm");
|
||||||
|
if (getChannel() == -1) {
|
||||||
|
channelLabel.setText("Current channel: ALL");
|
||||||
|
} else {
|
||||||
|
channelLabel.setText("Current channel: " + getChannel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.addObserver(observer);
|
||||||
|
|
||||||
|
observer.update(null, null);
|
||||||
|
|
||||||
|
panel.add(BorderLayout.NORTH, box);
|
||||||
|
panel.putClientProperty("intf_obs", observer);
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void releaseInterfaceVisualizer(JPanel panel) {
|
||||||
|
Observer observer = (Observer) panel.getClientProperty("intf_obs");
|
||||||
|
if (observer == null) {
|
||||||
|
logger.fatal("Error when releasing panel, observer is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.deleteObserver(observer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@ while(<STDIN>) {
|
||||||
if(/\<transmitting_range\>([\d.]+)\<\//) {
|
if(/\<transmitting_range\>([\d.]+)\<\//) {
|
||||||
$range = $1;
|
$range = $1;
|
||||||
}
|
}
|
||||||
|
if(/\<success_ratio_rx\>([\d.]+)\<\//) {
|
||||||
|
$success_ratio_rx = $1;
|
||||||
|
}
|
||||||
|
|
||||||
if(/\<x\>([\d.]+)\</) {
|
if(/\<x\>([\d.]+)\</) {
|
||||||
$x[$num] = $1;
|
$x[$num] = $1;
|
||||||
|
@ -18,7 +21,6 @@ while(<STDIN>) {
|
||||||
$num++;
|
$num++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print "Range $range num $num override range $override_range\n";
|
|
||||||
|
|
||||||
if($override_range) {
|
if($override_range) {
|
||||||
$range = $override_range;
|
$range = $override_range;
|
||||||
|
@ -27,15 +29,26 @@ if($override_range) {
|
||||||
$no_neighbors = 0;
|
$no_neighbors = 0;
|
||||||
$all_neighbors = 0;
|
$all_neighbors = 0;
|
||||||
$total_neighbors = 0;
|
$total_neighbors = 0;
|
||||||
# Go through all nodes, find how many are in their range.
|
|
||||||
|
# Go through all nodes, find how many are in their range and compute
|
||||||
|
# the average reception probability. Make sure we only count each neighbor once.
|
||||||
for($i = 0; $i < $num; $i++) {
|
for($i = 0; $i < $num; $i++) {
|
||||||
$neighbors = 0;
|
$neighbors = 0;
|
||||||
for($j = 0; $j < $num; $j++) {
|
for($j = 0; $j < $num; $j++) {
|
||||||
if($i != $j) {
|
if($i != $j) {
|
||||||
if(($x[$i] - $x[$j]) * ($x[$i] - $x[$j]) +
|
$distance2 = ($x[$i] - $x[$j]) * ($x[$i] - $x[$j]) +
|
||||||
($y[$i] - $y[$j]) * ($y[$i] - $y[$j]) <=
|
($y[$i] - $y[$j]) * ($y[$i] - $y[$j]);
|
||||||
$range * $range) {
|
$range2 = $range * $range;
|
||||||
|
if($distance2 <= $range2) {
|
||||||
$neighbors++;
|
$neighbors++;
|
||||||
|
|
||||||
|
$ratio = $distance2 / $range2;
|
||||||
|
if($ratio > 1) {
|
||||||
|
$reception_probability = 0;
|
||||||
|
} else {
|
||||||
|
$reception_probability = 1 - $ratio * (1 - $success_ratio_rx);
|
||||||
|
}
|
||||||
|
$reception_probability_sum += $reception_probability;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,8 +60,16 @@ for($i = 0; $i < $num; $i++) {
|
||||||
}
|
}
|
||||||
$total_neighbors += $neighbors;
|
$total_neighbors += $neighbors;
|
||||||
}
|
}
|
||||||
print "Num nodes $num, average neighbors " . ($total_neighbors / $num) .
|
|
||||||
|
print "$num $range " . ($total_neighbors / $num) .
|
||||||
|
" " . ($no_neighbors / $num) .
|
||||||
|
" " . ($all_neighbors / $num) .
|
||||||
|
" " . ($reception_probability_sum / $total_neighbors) .
|
||||||
|
"\n";
|
||||||
|
print "# Range $range number of nodes $num override range $override_range\n";
|
||||||
|
print "# Num nodes $num, average neighbors " . ($total_neighbors / $num) .
|
||||||
", $no_neighbors nodes (" . (100 * $no_neighbors / $num) .
|
", $no_neighbors nodes (" . (100 * $no_neighbors / $num) .
|
||||||
"%) have no neighbors, $all_neighbors (" . (100 * $all_neighbors / $num) .
|
"%) have no neighbors, $all_neighbors (" . (100 * $all_neighbors / $num) .
|
||||||
"%) have all nodes as neighbors\n";
|
"%) have all other nodes as neighbors\n";
|
||||||
|
print "# Average reception probability " .
|
||||||
|
($reception_probability_sum / $total_neighbors) . "\n";
|
||||||
|
|
Loading…
Reference in a new issue