Merge pull request #16 from cmorty/COOJA_DGRM

DGRM-Related Patches
This commit is contained in:
Fredrik Österlind 2012-11-21 02:44:13 -08:00
commit 150cb33b94
8 changed files with 566 additions and 505 deletions

View file

@ -382,6 +382,20 @@ public class Msp802154Radio extends Radio implements CustomDataRadio {
rssiLastCounter = 8; rssiLastCounter = 8;
} }
/* This will set the CORR-value of the CC2420
*
* @see se.sics.cooja.interfaces.Radio#setLQI(int)
*/
public void setLQI(int lqi){
radio.setLQI(lqi);
}
public int getLQI(){
return radio.getLQI();
}
public Mote getMote() { public Mote getMote() {
return mote; return mote;
} }

View file

@ -169,6 +169,25 @@ public abstract class Radio extends MoteInterface {
*/ */
public abstract int getOutputPowerIndicatorMax(); public abstract int getOutputPowerIndicatorMax();
/**
* Returns the current LQI-value. This might differ from platform to platform
* @return Current LQI value.
*
*
*/
public int getLQI() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* Sets the LQI. This in not supported by all platforms. Also results may differ
* from platform to platform.
*
* @param lqi The current LQI
*/
public void setLQI(int lqi){
}
/** /**
* @return Current surrounding signal strength * @return Current surrounding signal strength
*/ */

View file

@ -91,9 +91,11 @@ public class DGRMConfigurator extends VisPlugin {
private final static int IDX_DST = 1; private final static int IDX_DST = 1;
private final static int IDX_RATIO = 2; private final static int IDX_RATIO = 2;
private final static int IDX_SIGNAL = 3; private final static int IDX_SIGNAL = 3;
private final static int IDX_DELAY = 4; private final static int IDX_LQI = 4;
private final static int IDX_DELAY = 5;
private final static String[] COLUMN_NAMES = new String[] { private final static String[] COLUMN_NAMES = new String[] {
"Source", "Destination", "RX Ratio", "RSSI", "Delay" "Source", "Destination", "RX Ratio", "RSSI","LQI", "Delay"
}; };
private GUI gui = null; private GUI gui = null;
@ -128,6 +130,10 @@ public class DGRMConfigurator extends VisPlugin {
for (double d=AbstractRadioMedium.SS_STRONG; d >= AbstractRadioMedium.SS_WEAK; d -= 1) { for (double d=AbstractRadioMedium.SS_STRONG; d >= AbstractRadioMedium.SS_WEAK; d -= 1) {
combo.addItem((int) d); combo.addItem((int) d);
} }
} else if (column == IDX_LQI) {
for (int d = 110; d > 50; d -= 5) {
combo.addItem((int) d);
}
} else if (column == IDX_DELAY) { } else if (column == IDX_DELAY) {
for (double d=0; d <= 5; d++) { for (double d=0; d <= 5; d++) {
combo.addItem(d); combo.addItem(d);
@ -161,6 +167,17 @@ public class DGRMConfigurator extends VisPlugin {
setText(String.format("%1.1f dBm", v)); setText(String.format("%1.1f dBm", v));
} }
}); });
graphTable.getColumnModel().getColumn(IDX_LQI).setCellRenderer(new DefaultTableCellRenderer() {
private static final long serialVersionUID = -4669897764928372246L;
public void setValue(Object value) {
if (!(value instanceof Long)) {
setText(value.toString());
return;
}
long v = ((Long) value).longValue();
setText(String.valueOf(v));
}
});
graphTable.getColumnModel().getColumn(IDX_DELAY).setCellRenderer(new DefaultTableCellRenderer() { graphTable.getColumnModel().getColumn(IDX_DELAY).setCellRenderer(new DefaultTableCellRenderer() {
private static final long serialVersionUID = -4669897764928372246L; private static final long serialVersionUID = -4669897764928372246L;
public void setValue(Object value) { public void setValue(Object value) {
@ -174,6 +191,7 @@ public class DGRMConfigurator extends VisPlugin {
}); });
graphTable.getColumnModel().getColumn(IDX_RATIO).setCellEditor(new DefaultCellEditor(combo)); graphTable.getColumnModel().getColumn(IDX_RATIO).setCellEditor(new DefaultCellEditor(combo));
graphTable.getColumnModel().getColumn(IDX_SIGNAL).setCellEditor(new DefaultCellEditor(combo)); graphTable.getColumnModel().getColumn(IDX_SIGNAL).setCellEditor(new DefaultCellEditor(combo));
graphTable.getColumnModel().getColumn(IDX_LQI).setCellEditor(new DefaultCellEditor(combo));
graphTable.getColumnModel().getColumn(IDX_DELAY).setCellEditor(new DefaultCellEditor(combo)); graphTable.getColumnModel().getColumn(IDX_DELAY).setCellEditor(new DefaultCellEditor(combo));
graphTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); graphTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
@ -411,6 +429,9 @@ public class DGRMConfigurator extends VisPlugin {
if (column == IDX_SIGNAL) { if (column == IDX_SIGNAL) {
return ((DGRMDestinationRadio)edge.superDest).signal; return ((DGRMDestinationRadio)edge.superDest).signal;
} }
if (column == IDX_LQI) {
return ((DGRMDestinationRadio)edge.superDest).lqi;
}
if (column == IDX_DELAY) { if (column == IDX_DELAY) {
return ((DGRMDestinationRadio)edge.superDest).delay / Simulation.MILLISECOND; return ((DGRMDestinationRadio)edge.superDest).delay / Simulation.MILLISECOND;
} }
@ -433,7 +454,10 @@ public class DGRMConfigurator extends VisPlugin {
} else if (column == IDX_DELAY) { } else if (column == IDX_DELAY) {
((DGRMDestinationRadio)edge.superDest).delay = ((DGRMDestinationRadio)edge.superDest).delay =
((Number)value).longValue() * Simulation.MILLISECOND; ((Number)value).longValue() * Simulation.MILLISECOND;
} else { } else if (column == IDX_LQI) {
((DGRMDestinationRadio)edge.superDest).lqi = ((Number)value).intValue();
}
else {
super.setValueAt(value, row, column); super.setValueAt(value, row, column);
} }
radioMedium.requestEdgeAnalysis(); radioMedium.requestEdgeAnalysis();
@ -461,6 +485,9 @@ public class DGRMConfigurator extends VisPlugin {
if (column == IDX_SIGNAL) { if (column == IDX_SIGNAL) {
return true; return true;
} }
if (column == IDX_LQI) {
return true;
}
if (column == IDX_DELAY) { if (column == IDX_DELAY) {
return true; return true;
} }

View file

@ -117,6 +117,15 @@ public class DGRMVisualizerSkin implements VisualizerSkin {
g.drawString(msg, x - msgWidth/2, y + 2*Visualizer.MOTE_RADIUS + 3); g.drawString(msg, x - msgWidth/2, y + 2*Visualizer.MOTE_RADIUS + 3);
for (DestinationRadio r: dests) { for (DestinationRadio r: dests) {
double prob = ((DGRMDestinationRadio)r).ratio; double prob = ((DGRMDestinationRadio)r).ratio;
double rssi = ((DGRMDestinationRadio)r).signal;
double pos_rssi = rssi + 100;
int lqi = ((DGRMDestinationRadio)r).lqi;
float red = (float)(1 - prob*pos_rssi/90*lqi/100);
if(red > 1) red = 1;
if(red < 0) red = 0;
float green = (float)(prob*pos_rssi/90*lqi/100);
if(green > 1) green = 1;
if(green < 0) green = 0;
if (prob == 0.0d) { if (prob == 0.0d) {
continue; continue;
} }
@ -124,7 +133,8 @@ public class DGRMVisualizerSkin implements VisualizerSkin {
Position pos = r.radio.getPosition(); Position pos = r.radio.getPosition();
Point pixel = visualizer.transformPositionToPixel(pos); Point pixel = visualizer.transformPositionToPixel(pos);
msgWidth = fm.stringWidth(msg); msgWidth = fm.stringWidth(msg);
g.setColor(new Color(1-(float)prob, (float)prob, 0.0f)); g.setColor(new Color(red, green, 0.0f));
g.drawString("LQI: " + lqi + " RSSI: " + rssi,(x + pixel.x)/2,(y + pixel.y)/2);
g.drawLine(x, y, pixel.x, pixel.y); g.drawLine(x, y, pixel.x, pixel.y);
g.setColor(Color.BLACK); g.setColor(Color.BLACK);
g.drawString(msg, pixel.x - msgWidth/2, pixel.y + 2*Visualizer.MOTE_RADIUS + 3); g.drawString(msg, pixel.x - msgWidth/2, pixel.y + 2*Visualizer.MOTE_RADIUS + 3);

View file

@ -61,416 +61,410 @@ import se.sics.cooja.interfaces.Radio;
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
public abstract class AbstractRadioMedium extends RadioMedium { public abstract class AbstractRadioMedium extends RadioMedium {
private static Logger logger = Logger.getLogger(AbstractRadioMedium.class); private static Logger logger = Logger.getLogger(AbstractRadioMedium.class);
/* Signal strengths in dBm. /* Signal strengths in dBm.
* Approx. values measured on TmoteSky */ * Approx. values measured on TmoteSky */
public static final double SS_NOTHING = -100; public static final double SS_NOTHING = -100;
public static final double SS_STRONG = -10; public static final double SS_STRONG = -10;
public static final double SS_WEAK = -95; public static final double SS_WEAK = -95;
private ArrayList<Radio> registeredRadios = new ArrayList<Radio>(); private ArrayList<Radio> registeredRadios = new ArrayList<Radio>();
private ArrayList<RadioConnection> activeConnections = new ArrayList<RadioConnection>(); private ArrayList<RadioConnection> activeConnections = new ArrayList<RadioConnection>();
private RadioConnection lastConnection = null; private RadioConnection lastConnection = null;
private Simulation simulation = null; private Simulation simulation = null;
/* Book-keeping */ /* Book-keeping */
public int COUNTER_TX = 0; public int COUNTER_TX = 0;
public int COUNTER_RX = 0; public int COUNTER_RX = 0;
public int COUNTER_INTERFERED = 0; public int COUNTER_INTERFERED = 0;
public class RadioMediumObservable extends Observable { public class RadioMediumObservable extends Observable {
public void setRadioMediumChanged() { public void setRadioMediumChanged() {
setChanged(); setChanged();
} }
public void setRadioMediumChangedAndNotify() { public void setRadioMediumChangedAndNotify() {
setChanged(); setChanged();
notifyObservers(); notifyObservers();
} }
} }
private RadioMediumObservable radioMediumObservable = new RadioMediumObservable(); private RadioMediumObservable radioMediumObservable = new RadioMediumObservable();
/** /**
* This constructor should always be called from implemented radio mediums. * This constructor should always be called from implemented radio mediums.
* *
* @param simulation Simulation * @param simulation Simulation
*/ */
public AbstractRadioMedium(Simulation simulation) { public AbstractRadioMedium(Simulation simulation) {
this.simulation = simulation; this.simulation = simulation;
} }
/** /**
* @return All registered radios * @return All registered radios
*/ */
public Radio[] getRegisteredRadios() { public Radio[] getRegisteredRadios() {
return registeredRadios.toArray(new Radio[0]); return registeredRadios.toArray(new Radio[0]);
} }
/** /**
* @return All active connections * @return All active connections
*/ */
public RadioConnection[] getActiveConnections() { public RadioConnection[] getActiveConnections() {
/* NOTE: toArray([0]) creates array and handles synchronization */ /* NOTE: toArray([0]) creates array and handles synchronization */
return activeConnections.toArray(new RadioConnection[0]); return activeConnections.toArray(new RadioConnection[0]);
} }
/** /**
* Creates a new connection from given radio. * Creates a new connection from given radio.
* *
* Determines which radios should receive or be interfered by the transmission. * Determines which radios should receive or be interfered by the transmission.
* *
* @param radio Source radio * @param radio Source radio
* @return New connection * @return New connection
*/ */
abstract public RadioConnection createConnections(Radio radio); abstract public RadioConnection createConnections(Radio radio);
/** /**
* Updates all radio interfaces' signal strengths according to * Updates all radio interfaces' signal strengths according to
* the current active connections. * the current active connections.
*/ */
public void updateSignalStrengths() { public void updateSignalStrengths() {
/* Reset signal strengths */ /* Reset signal strengths */
for (Radio radio : getRegisteredRadios()) { for (Radio radio : getRegisteredRadios()) {
radio.setCurrentSignalStrength(SS_NOTHING); radio.setCurrentSignalStrength(SS_NOTHING);
} }
/* Set signal strength to strong on destinations */ /* Set signal strength to strong on destinations */
RadioConnection[] conns = getActiveConnections(); RadioConnection[] conns = getActiveConnections();
for (RadioConnection conn : conns) { for (RadioConnection conn : conns) {
if (conn.getSource().getCurrentSignalStrength() < SS_STRONG) { if (conn.getSource().getCurrentSignalStrength() < SS_STRONG) {
conn.getSource().setCurrentSignalStrength(SS_STRONG); conn.getSource().setCurrentSignalStrength(SS_STRONG);
} }
for (Radio dstRadio : conn.getDestinations()) { for (Radio dstRadio : conn.getDestinations()) {
if (conn.getSource().getChannel() >= 0 && if (conn.getSource().getChannel() >= 0 &&
dstRadio.getChannel() >= 0 && dstRadio.getChannel() >= 0 &&
conn.getSource().getChannel() != dstRadio.getChannel()) { conn.getSource().getChannel() != dstRadio.getChannel()) {
continue; continue;
} }
if (dstRadio.getCurrentSignalStrength() < SS_STRONG) { if (dstRadio.getCurrentSignalStrength() < SS_STRONG) {
dstRadio.setCurrentSignalStrength(SS_STRONG); dstRadio.setCurrentSignalStrength(SS_STRONG);
} }
} }
} }
/* Set signal strength to weak on interfered */ /* Set signal strength to weak on interfered */
for (RadioConnection conn : conns) { for (RadioConnection conn : conns) {
for (Radio intfRadio : conn.getInterfered()) { for (Radio intfRadio : conn.getInterfered()) {
if (intfRadio.getCurrentSignalStrength() < SS_STRONG) { if (intfRadio.getCurrentSignalStrength() < SS_STRONG) {
intfRadio.setCurrentSignalStrength(SS_STRONG); intfRadio.setCurrentSignalStrength(SS_STRONG);
} }
if (conn.getSource().getChannel() >= 0 && if (conn.getSource().getChannel() >= 0 &&
intfRadio.getChannel() >= 0 && intfRadio.getChannel() >= 0 &&
conn.getSource().getChannel() != intfRadio.getChannel()) { conn.getSource().getChannel() != intfRadio.getChannel()) {
continue; continue;
} }
if (!intfRadio.isInterfered()) { if (!intfRadio.isInterfered()) {
/*logger.warn("Radio was not interfered");*/ /*logger.warn("Radio was not interfered");*/
intfRadio.interfereAnyReception(); intfRadio.interfereAnyReception();
} }
} }
} }
} }
/** /**
* Remove given radio from any active connections. * Remove given radio from any active connections.
* This method can be called if a radio node falls asleep or is removed. * This method can be called if a radio node falls asleep or is removed.
* *
* @param radio Radio * @param radio Radio
*/ */
private void removeFromActiveConnections(Radio radio) { private void removeFromActiveConnections(Radio radio) {
/* This radio must not be a connection source */ /* This radio must not be a connection source */
RadioConnection connection = getActiveConnectionFrom(radio); RadioConnection connection = getActiveConnectionFrom(radio);
if (connection != null) { if (connection != null) {
logger.fatal("Connection source turned off radio: " + radio); logger.fatal("Connection source turned off radio: " + radio);
} }
/* Set interfered if currently a connection destination */ /* Set interfered if currently a connection destination */
for (RadioConnection conn : activeConnections) { for (RadioConnection conn : activeConnections) {
if (conn.isDestination(radio)) { if (conn.isDestination(radio)) {
conn.addInterfered(radio); conn.addInterfered(radio);
if (!radio.isInterfered()) { if (!radio.isInterfered()) {
radio.interfereAnyReception(); radio.interfereAnyReception();
} }
} }
} }
} }
private RadioConnection getActiveConnectionFrom(Radio source) { private RadioConnection getActiveConnectionFrom(Radio source) {
for (RadioConnection conn : activeConnections) { for (RadioConnection conn : activeConnections) {
if (conn.getSource() == source) { if (conn.getSource() == source) {
return conn; return conn;
} }
} }
return null; return null;
} }
/** /**
* This observer is responsible for detecting radio interface events, for example * This observer is responsible for detecting radio interface events, for example
* new transmissions. * new transmissions.
*/ */
private Observer radioEventsObserver = new Observer() { private Observer radioEventsObserver = new Observer() {
public void update(Observable obs, Object obj) { public void update(Observable obs, Object obj) {
if (!(obs instanceof Radio)) { if (!(obs instanceof Radio)) {
logger.fatal("Radio event dispatched by non-radio object"); logger.fatal("Radio event dispatched by non-radio object");
return; return;
} }
Radio radio = (Radio) obs; Radio radio = (Radio) obs;
final Radio.RadioEvent event = radio.getLastEvent(); final Radio.RadioEvent event = radio.getLastEvent();
if (event == Radio.RadioEvent.RECEPTION_STARTED ||
event == Radio.RadioEvent.RECEPTION_INTERFERED || switch (event) {
event == Radio.RadioEvent.RECEPTION_FINISHED || case RECEPTION_STARTED:
event == Radio.RadioEvent.UNKNOWN) { case RECEPTION_INTERFERED:
/* Ignored */ case RECEPTION_FINISHED:
return; case UNKNOWN:
} return;
case HW_ON: {
if (event == Radio.RadioEvent.HW_ON) { /* Update signal strengths */
updateSignalStrengths();
/* Update signal strengths */ }
updateSignalStrengths(); break;
case HW_OFF: {
} else if (event == Radio.RadioEvent.HW_OFF) { /* Remove any radio connections from this radio */
removeFromActiveConnections(radio);
/* Remove any radio connections from this radio */ /* Update signal strengths */
removeFromActiveConnections(radio); updateSignalStrengths();
}
/* Update signal strengths */ break;
updateSignalStrengths(); case TRANSMISSION_STARTED: {
/* Create new radio connection */
} else if (event == Radio.RadioEvent.TRANSMISSION_STARTED) { if (radio.isReceiving()) {
/* Create new radio connection */ /*
* Radio starts transmitting when it should be
if (radio.isReceiving()) { * receiving! Ok, but it won't receive the packet
/* Radio starts transmitting when it should be receiving! */
* Ok, but it won't receive the packet */ radio.interfereAnyReception();
for (RadioConnection conn : activeConnections) { for (RadioConnection conn : activeConnections) {
if (conn.isDestination(radio)) { if (conn.isDestination(radio)) {
conn.addInterfered(radio); conn.addInterfered(radio);
} }
} }
radio.interfereAnyReception(); }
}
RadioConnection newConnection = createConnections(radio);
RadioConnection newConnection = createConnections(radio); activeConnections.add(newConnection);
activeConnections.add(newConnection);
for (Radio r: newConnection.getAllDestinations()) { for (Radio r : newConnection.getAllDestinations()) {
if (newConnection.getDestinationDelay(r) == 0) { if (newConnection.getDestinationDelay(r) == 0) {
r.signalReceptionStart(); r.signalReceptionStart();
} else { } else {
/* EXPERIMENTAL: Simulating propagation delay */
/* EXPERIMENTAL: Simulating propagation delay */ final Radio delayedRadio = r;
final Radio delayedRadio = r; TimeEvent delayedEvent = new TimeEvent(0) {
TimeEvent delayedEvent = new TimeEvent(0) { public void execute(long t) {
public void execute(long t) { delayedRadio.signalReceptionStart();
delayedRadio.signalReceptionStart(); }
} };
}; simulation.scheduleEvent(delayedEvent, simulation.getSimulationTime() + newConnection.getDestinationDelay(r));
simulation.scheduleEvent(
delayedEvent, }
simulation.getSimulationTime() + newConnection.getDestinationDelay(r)); } /* Update signal strengths */
updateSignalStrengths();
}
} /* Notify observers */
lastConnection = null;
/* Update signal strengths */ radioMediumObservable.setRadioMediumChangedAndNotify();
updateSignalStrengths(); }
break;
/* Notify observers */ case TRANSMISSION_FINISHED: {
lastConnection = null; /* Remove radio connection */
radioMediumObservable.setRadioMediumChangedAndNotify();
/* Connection */
} else if (event == Radio.RadioEvent.TRANSMISSION_FINISHED) { RadioConnection connection = getActiveConnectionFrom(radio);
/* Remove radio connection */ if (connection == null) {
logger.fatal("No radio connection found");
/* Connection */ return;
RadioConnection connection = getActiveConnectionFrom(radio); }
if (connection == null) {
logger.fatal("No radio connection found"); activeConnections.remove(connection);
return; lastConnection = connection;
} COUNTER_TX++;
for (Radio dstRadio : connection.getAllDestinations()) {
activeConnections.remove(connection); if (connection.getDestinationDelay(dstRadio) == 0) {
lastConnection = connection; dstRadio.signalReceptionEnd();
COUNTER_TX++; } else {
for (Radio dstRadio : connection.getAllDestinations()) {
if (connection.getDestinationDelay(dstRadio) == 0) { /* EXPERIMENTAL: Simulating propagation delay */
dstRadio.signalReceptionEnd(); final Radio delayedRadio = dstRadio;
} else { TimeEvent delayedEvent = new TimeEvent(0) {
public void execute(long t) {
/* EXPERIMENTAL: Simulating propagation delay */ delayedRadio.signalReceptionEnd();
final Radio delayedRadio = dstRadio; }
TimeEvent delayedEvent = new TimeEvent(0) { };
public void execute(long t) { simulation.scheduleEvent(delayedEvent,
delayedRadio.signalReceptionEnd(); simulation.getSimulationTime() + connection.getDestinationDelay(dstRadio));
} }
}; }
simulation.scheduleEvent( COUNTER_RX += connection.getDestinations().length;
delayedEvent, COUNTER_INTERFERED += connection.getInterfered().length;
simulation.getSimulationTime() + connection.getDestinationDelay(dstRadio)); for (Radio intRadio : connection.getInterferedNonDestinations()) {
} intRadio.signalReceptionEnd();
} }
COUNTER_RX += connection.getDestinations().length;
COUNTER_INTERFERED += connection.getInterfered().length; /* Update signal strengths */
for (Radio intRadio : connection.getInterferedNonDestinations()) { updateSignalStrengths();
intRadio.signalReceptionEnd();
} /* Notify observers */
radioMediumObservable.setRadioMediumChangedAndNotify();
/* Update signal strengths */ }
updateSignalStrengths(); break;
case CUSTOM_DATA_TRANSMITTED: {
/* Notify observers */
radioMediumObservable.setRadioMediumChangedAndNotify(); /* Connection */
RadioConnection connection = getActiveConnectionFrom(radio);
} else if (event == Radio.RadioEvent.CUSTOM_DATA_TRANSMITTED) { if (connection == null) {
logger.fatal("No radio connection found");
/* Connection */ return;
RadioConnection connection = getActiveConnectionFrom(radio); }
if (connection == null) {
logger.fatal("No radio connection found"); /* Custom data object */
return; Object data = ((CustomDataRadio) radio).getLastCustomDataTransmitted();
} if (data == null) {
logger.fatal("No custom data object to forward");
/* Custom data object */ return;
Object data = ((CustomDataRadio) radio).getLastCustomDataTransmitted(); }
if (data == null) {
logger.fatal("No custom data object to forward"); for (Radio dstRadio : connection.getAllDestinations()) {
return;
} if (!radio.getClass().equals(dstRadio.getClass()) || !(radio instanceof CustomDataRadio)) {
/* Radios communicate via radio packets */
for (Radio dstRadio : connection.getAllDestinations()) { continue;
}
if (!radio.getClass().equals(dstRadio.getClass()) ||
!(radio instanceof CustomDataRadio)) { if (connection.getDestinationDelay(dstRadio) == 0) {
/* Radios communicate via radio packets */ ((CustomDataRadio) dstRadio).receiveCustomData(data);
continue; } else {
}
/* EXPERIMENTAL: Simulating propagation delay */
if (connection.getDestinationDelay(dstRadio) == 0) { final CustomDataRadio delayedRadio = (CustomDataRadio) dstRadio;
((CustomDataRadio) dstRadio).receiveCustomData(data); final Object delayedData = data;
} else { TimeEvent delayedEvent = new TimeEvent(0) {
public void execute(long t) {
/* EXPERIMENTAL: Simulating propagation delay */ delayedRadio.receiveCustomData(delayedData);
final CustomDataRadio delayedRadio = (CustomDataRadio) dstRadio; }
final Object delayedData = data; };
TimeEvent delayedEvent = new TimeEvent(0) { simulation.scheduleEvent(delayedEvent,
public void execute(long t) { simulation.getSimulationTime() + connection.getDestinationDelay(dstRadio));
delayedRadio.receiveCustomData(delayedData);
} }
}; }
simulation.scheduleEvent(
delayedEvent, }
simulation.getSimulationTime() + connection.getDestinationDelay(dstRadio)); break;
case PACKET_TRANSMITTED: {
} /* Connection */
} RadioConnection connection = getActiveConnectionFrom(radio);
if (connection == null) {
} else if (event == Radio.RadioEvent.PACKET_TRANSMITTED) { logger.fatal("No radio connection found");
return;
/* Connection */ }
RadioConnection connection = getActiveConnectionFrom(radio);
if (connection == null) { /* Radio packet */
logger.fatal("No radio connection found"); RadioPacket packet = radio.getLastPacketTransmitted();
return; if (packet == null) {
} logger.fatal("No radio packet to forward");
return;
/* Radio packet */ }
RadioPacket packet = radio.getLastPacketTransmitted();
if (packet == null) { for (Radio dstRadio : connection.getAllDestinations()) {
logger.fatal("No radio packet to forward");
return; if (radio.getClass().equals(dstRadio.getClass()) && radio instanceof CustomDataRadio) {
} /* Radios instead communicate via custom data objects */
continue;
for (Radio dstRadio : connection.getAllDestinations()) { }
if (radio.getClass().equals(dstRadio.getClass()) && /* Forward radio packet */
radio instanceof CustomDataRadio) { if (connection.getDestinationDelay(dstRadio) == 0) {
/* Radios instead communicate via custom data objects */ dstRadio.setReceivedPacket(packet);
continue; } else {
}
/* EXPERIMENTAL: Simulating propagation delay */
/* Forward radio packet */ final Radio delayedRadio = dstRadio;
if (connection.getDestinationDelay(dstRadio) == 0) { final RadioPacket delayedPacket = packet;
dstRadio.setReceivedPacket(packet); TimeEvent delayedEvent = new TimeEvent(0) {
} else { public void execute(long t) {
delayedRadio.setReceivedPacket(delayedPacket);
/* EXPERIMENTAL: Simulating propagation delay */ }
final Radio delayedRadio = dstRadio; };
final RadioPacket delayedPacket = packet; simulation.scheduleEvent(delayedEvent,
TimeEvent delayedEvent = new TimeEvent(0) { simulation.getSimulationTime() + connection.getDestinationDelay(dstRadio));
public void execute(long t) { }
delayedRadio.setReceivedPacket(delayedPacket);
} }
}; }
simulation.scheduleEvent( break;
delayedEvent, default:
simulation.getSimulationTime() + connection.getDestinationDelay(dstRadio)); logger.fatal("Unsupported radio event: " + event);
} }
}
} };
} else { public void registerMote(Mote mote, Simulation sim) {
logger.fatal("Unsupported radio event: " + event); registerRadioInterface(mote.getInterfaces().getRadio(), sim);
} }
}
}; public void unregisterMote(Mote mote, Simulation sim) {
unregisterRadioInterface(mote.getInterfaces().getRadio(), sim);
public void registerMote(Mote mote, Simulation sim) { }
registerRadioInterface(mote.getInterfaces().getRadio(), sim);
} public void registerRadioInterface(Radio radio, Simulation sim) {
if (radio == null) {
public void unregisterMote(Mote mote, Simulation sim) { logger.warn("No radio to register");
unregisterRadioInterface(mote.getInterfaces().getRadio(), sim); return;
} }
public void registerRadioInterface(Radio radio, Simulation sim) { registeredRadios.add(radio);
if (radio == null) { radio.addObserver(radioEventsObserver);
logger.warn("No radio to register");
return; /* Update signal strengths */
} updateSignalStrengths();
}
registeredRadios.add(radio);
radio.addObserver(radioEventsObserver); public void unregisterRadioInterface(Radio radio, Simulation sim) {
if (!registeredRadios.contains(radio)) {
/* Update signal strengths */ logger.warn("No radio to unregister: " + radio);
updateSignalStrengths(); return;
} }
public void unregisterRadioInterface(Radio radio, Simulation sim) { radio.deleteObserver(radioEventsObserver);
if (!registeredRadios.contains(radio)) { registeredRadios.remove(radio);
logger.warn("No radio to unregister: " + radio);
return; removeFromActiveConnections(radio);
}
/* Update signal strengths */
radio.deleteObserver(radioEventsObserver); updateSignalStrengths();
registeredRadios.remove(radio); }
removeFromActiveConnections(radio); public void addRadioMediumObserver(Observer observer) {
radioMediumObservable.addObserver(observer);
/* Update signal strengths */ }
updateSignalStrengths();
} public Observable getRadioMediumObservable() {
return radioMediumObservable;
public void addRadioMediumObserver(Observer observer) { }
radioMediumObservable.addObserver(observer);
} public void deleteRadioMediumObserver(Observer observer) {
radioMediumObservable.deleteObserver(observer);
public Observable getRadioMediumObservable() { }
return radioMediumObservable;
} public RadioConnection getLastConnection() {
return lastConnection;
public void deleteRadioMediumObserver(Observer observer) { }
radioMediumObservable.deleteObserver(observer);
}
public RadioConnection getLastConnection() {
return lastConnection;
}
} }

View file

@ -41,6 +41,7 @@ public class DGRMDestinationRadio extends DestinationRadio {
public double ratio = 1.0; /* Link success ratio (per packet). */ public double ratio = 1.0; /* Link success ratio (per packet). */
public double signal = AbstractRadioMedium.SS_STRONG; /* RSSI */ public double signal = AbstractRadioMedium.SS_STRONG; /* RSSI */
public long delay = 0; /* EXPERIMENTAL: Propagation delay (us). */ public long delay = 0; /* EXPERIMENTAL: Propagation delay (us). */
public int lqi = 105;
public DGRMDestinationRadio() { public DGRMDestinationRadio() {
super(); super();
@ -54,6 +55,7 @@ public class DGRMDestinationRadio extends DestinationRadio {
clone.ratio = this.ratio; clone.ratio = this.ratio;
clone.delay = this.delay; clone.delay = this.delay;
clone.signal = this.signal; clone.signal = this.signal;
clone.lqi = this.lqi;
return clone; return clone;
} }
@ -69,6 +71,11 @@ public class DGRMDestinationRadio extends DestinationRadio {
element.setText("" + signal); element.setText("" + signal);
config.add(element); config.add(element);
element = new Element("lqi");
element.setText("" + lqi);
config.add(element);
element = new Element("delay"); element = new Element("delay");
element.setText("" + delay); element.setText("" + delay);
config.add(element); config.add(element);
@ -85,6 +92,8 @@ public class DGRMDestinationRadio extends DestinationRadio {
ratio = Double.parseDouble(element.getText()); ratio = Double.parseDouble(element.getText());
} else if (element.getName().equals("signal")) { } else if (element.getName().equals("signal")) {
signal = Double.parseDouble(element.getText()); signal = Double.parseDouble(element.getText());
} else if (element.getName().equals("lqi")) {
lqi = Integer.parseInt(element.getText());
} else if (element.getName().equals("delay")) { } else if (element.getName().equals("delay")) {
delay = Long.parseLong(element.getText()); delay = Long.parseLong(element.getText());
} }

View file

@ -34,6 +34,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.List;
import java.util.Random; import java.util.Random;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -71,7 +72,7 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
private boolean edgesDirty = true; private boolean edgesDirty = true;
/* Used for optimizing lookup time */ /* Used for optimizing lookup time */
private Hashtable<Radio,DestinationRadio[]> edgesTable = new Hashtable<Radio,DestinationRadio[]>(); private Hashtable<Radio,DGRMDestinationRadio[]> edgesTable = new Hashtable<Radio,DGRMDestinationRadio[]>();
public DirectedGraphMedium() { public DirectedGraphMedium() {
/* Do not initialize radio medium: use only for hash table */ /* Do not initialize radio medium: use only for hash table */
@ -164,45 +165,42 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
/* Set signal strengths */ /* Set signal strengths */
RadioConnection[] conns = getActiveConnections(); RadioConnection[] conns = getActiveConnections();
for (RadioConnection conn : conns) { for (RadioConnection conn : conns) {
/* When sending RSSI is Strong!
* TODO: is this reasonable
*/
if (conn.getSource().getCurrentSignalStrength() < SS_STRONG) { if (conn.getSource().getCurrentSignalStrength() < SS_STRONG) {
conn.getSource().setCurrentSignalStrength(SS_STRONG); conn.getSource().setCurrentSignalStrength(SS_STRONG);
} }
for (Radio dstRadio : conn.getDestinations()) { //Maximum reception signal of all possible radios received
if (dstRadio.getCurrentSignalStrength() < SS_STRONG) { DGRMDestinationRadio dstRadios[] = getPotentialDestinations(conn.getSource());
dstRadio.setCurrentSignalStrength(SS_STRONG); if (dstRadios == null) continue;
for (DGRMDestinationRadio dstRadio : dstRadios) {
if (dstRadio.radio.getCurrentSignalStrength() < dstRadio.signal) {
dstRadio.radio.setCurrentSignalStrength(dstRadio.signal);
} }
/* We can set this without further checks, as it will only be read
* if a packet is actually received. In that case it is set to the
* correct value */
dstRadio.radio.setLQI(dstRadio.lqi);
} }
}
/* Set signal strength to weak on interfered */
for (RadioConnection conn : conns) {
for (Radio intfRadio : conn.getInterfered()) {
if (intfRadio.getCurrentSignalStrength() < SS_STRONG) {
intfRadio.setCurrentSignalStrength(SS_STRONG);
}
if (!intfRadio.isInterfered()) {
/*logger.warn("Radio was not interfered");*/
intfRadio.interfereAnyReception();
}
}
} }
} }
/** /**
* Generates hash table using current edges for efficient lookup. * Generates hash table using current edges for efficient lookup.
*/ */
protected void analyzeEdges() { protected void analyzeEdges() {
Hashtable<Radio,ArrayList<DestinationRadio>> listTable = Hashtable<Radio,ArrayList<DGRMDestinationRadio>> listTable =
new Hashtable<Radio,ArrayList<DestinationRadio>>(); new Hashtable<Radio,ArrayList<DGRMDestinationRadio>>();
/* Fill edge hash table with all edges */ /* Fill edge hash table with all edges */
for (Edge edge: getEdges()) { for (Edge edge: getEdges()) {
ArrayList<DestinationRadio> destRadios; ArrayList<DGRMDestinationRadio> destRadios;
if (!listTable.containsKey(edge.source)) { if (!listTable.containsKey(edge.source)) {
destRadios = new ArrayList<DestinationRadio>(); destRadios = new ArrayList<DGRMDestinationRadio>();
} else { } else {
destRadios = listTable.get(edge.source); destRadios = listTable.get(edge.source);
} }
@ -212,11 +210,11 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
} }
/* Convert to arrays */ /* Convert to arrays */
Hashtable<Radio,DestinationRadio[]> arrTable = new Hashtable<Radio,DestinationRadio[]>(); Hashtable<Radio,DGRMDestinationRadio[]> arrTable = new Hashtable<Radio,DGRMDestinationRadio[]>();
Enumeration<Radio> sources = listTable.keys(); Enumeration<Radio> sources = listTable.keys();
while (sources.hasMoreElements()) { while (sources.hasMoreElements()) {
Radio source = sources.nextElement(); Radio source = sources.nextElement();
DestinationRadio[] arr = listTable.get(source).toArray(new DestinationRadio[0]); DGRMDestinationRadio[] arr = listTable.get(source).toArray(new DGRMDestinationRadio[0]);
arrTable.put(source, arr); arrTable.put(source, arr);
} }
@ -231,7 +229,7 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
* @param source Source radio * @param source Source radio
* @return All potential destination radios * @return All potential destination radios
*/ */
public DestinationRadio[] getPotentialDestinations(Radio source) { public DGRMDestinationRadio[] getPotentialDestinations(Radio source) {
if (edgesDirty) { if (edgesDirty) {
analyzeEdges(); analyzeEdges();
} }
@ -249,7 +247,7 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
/* Create new radio connection using edge hash table */ /* Create new radio connection using edge hash table */
RadioConnection newConn = new RadioConnection(source); RadioConnection newConn = new RadioConnection(source);
DestinationRadio[] destinations = getPotentialDestinations(source); DGRMDestinationRadio[] destinations = getPotentialDestinations(source);
if (destinations == null || destinations.length == 0) { if (destinations == null || destinations.length == 0) {
/* No destinations */ /* No destinations */
/*logger.info(sendingRadio + ": No dest");*/ /*logger.info(sendingRadio + ": No dest");*/
@ -257,20 +255,14 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
} }
/*logger.info(source + ": " + destinations.length + " potential destinations");*/ /*logger.info(source + ": " + destinations.length + " potential destinations");*/
for (DestinationRadio d: destinations) { for (DGRMDestinationRadio dest: destinations) {
DGRMDestinationRadio dest = (DGRMDestinationRadio) d;
if (dest.radio == source) { if (dest.radio == source) {
/* Fail: cannot receive our own transmission */ /* Fail: cannot receive our own transmission */
/*logger.info(source + ": Fail, receiver is sender");*/ /*logger.info(source + ": Fail, receiver is sender");*/
continue; continue;
} }
/* Fail if radios are on different (but configured) channels */
if (source.getChannel() >= 0 &&
dest.radio.getChannel() >= 0 &&
source.getChannel() != dest.radio.getChannel()) {
continue;
}
if (!dest.radio.isRadioOn()) { if (!dest.radio.isRadioOn()) {
/* Fail: radio is off */ /* Fail: radio is off */
@ -279,52 +271,44 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
continue; continue;
} }
if (dest.ratio < 1.0 && random.nextDouble() > dest.ratio) { if (dest.radio.isInterfered()) {
/*logger.info(source + ": Fail, randomly");*/ /* Fail: radio is interfered in another connection */
/* TODO Interfere now? */ /*logger.info(source + ": Fail, interfered");*/
newConn.addInterfered(dest.radio); newConn.addInterfered(dest.radio);
continue;
}
dest.radio.interfereAnyReception(); int srcc = source.getChannel();
RadioConnection otherConnection = null; int dstc = dest.radio.getChannel();
for (RadioConnection conn : getActiveConnections()) { if ( srcc >= 0 && dstc >= 0 && srcc != dstc) {
for (Radio dstRadio : conn.getDestinations()) { /* Fail: radios are on different (but configured) channels */
if (dstRadio == dest.radio) {
otherConnection = conn;
break;
}
}
}
if (otherConnection != null) {
otherConnection.addInterfered(dest.radio);
}
continue; continue;
} }
if (dest.radio.isReceiving()) { if (dest.radio.isReceiving()) {
/* Fail: radio is already actively receiving */ /* Fail: radio is already actively receiving */
/*logger.info(source + ": Fail, receiving");*/ /*logger.info(source + ": Fail, receiving");*/
newConn.addInterfered(dest.radio); newConn.addInterfered(dest.radio);
/* We will also interfere with the other connection */ /* We will also interfere with the other connection */
dest.radio.interfereAnyReception(); dest.radio.interfereAnyReception();
RadioConnection otherConnection = null;
for (RadioConnection conn : getActiveConnections()) { // Find connection, that is sending to that radio
for (Radio dstRadio : conn.getDestinations()) { // and mark the destination as interfered
if (dstRadio == dest.radio) { for (RadioConnection conn : getActiveConnections()) {
otherConnection = conn; for (Radio dstRadio : conn.getDestinations()) {
break; if (dstRadio == dest.radio) {
} conn.addInterfered(dest.radio);;
} break;
} }
if (otherConnection != null) { }
otherConnection.addInterfered(dest.radio); }
} continue;
continue;
} }
if (dest.radio.isInterfered()) { if (dest.ratio < 1.0 && random.nextDouble() > dest.ratio) {
/* Fail: radio is interfered in another connection */ /* Fail: Reception ratio */
/*logger.info(source + ": Fail, interfered");*/ /*logger.info(source + ": Fail, randomly");*/
newConn.addInterfered(dest.radio); newConn.addInterfered(dest.radio);
continue; continue;
} }
@ -358,7 +342,8 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
delayedConfiguration = configXML; delayedConfiguration = configXML;
return true; return true;
} }
public void simulationFinishedLoading() {
public void simulationFinishedLoading() {
if (delayedConfiguration == null) { if (delayedConfiguration == null) {
return; return;
} }
@ -366,9 +351,10 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
boolean oldConfig = false; boolean oldConfig = false;
for (Element element : delayedConfiguration) { for (Element element : delayedConfiguration) {
if (element.getName().equals("edge")) { if (element.getName().equals("edge")) {
Collection<Element> edgeConfig = element.getChildren(); @SuppressWarnings("unchecked")
Collection<Element> edgeConfig = element.getChildren();
Radio source = null; Radio source = null;
DestinationRadio dest = null; DGRMDestinationRadio dest = null;
for (Element edgeElement : edgeConfig) { for (Element edgeElement : edgeConfig) {
if (edgeElement.getName().equals("src")) { if (edgeElement.getName().equals("src")) {
oldConfig = true; oldConfig = true;
@ -387,7 +373,7 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
} else if (oldConfig && edgeElement.getName().equals("ratio")) { } else if (oldConfig && edgeElement.getName().equals("ratio")) {
/* Old config: parse link ratio */ /* Old config: parse link ratio */
double ratio = Double.parseDouble(edgeElement.getText()); double ratio = Double.parseDouble(edgeElement.getText());
((DGRMDestinationRadio)dest).ratio = ratio; dest.ratio = ratio;
} else if (edgeElement.getName().equals("dest")) { } else if (edgeElement.getName().equals("dest")) {
if (oldConfig) { if (oldConfig) {
/* Old config: create simple destination link */ /* Old config: create simple destination link */
@ -405,14 +391,16 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
if (destClassName == null || destClassName.isEmpty()) { if (destClassName == null || destClassName.isEmpty()) {
continue; continue;
} }
Class<? extends DestinationRadio> destClass = Class<? extends DGRMDestinationRadio> destClass =
simulation.getGUI().tryLoadClass(this, DestinationRadio.class, destClassName); simulation.getGUI().tryLoadClass(this, DGRMDestinationRadio.class, destClassName);
if (destClass == null) { if (destClass == null) {
throw new RuntimeException("Could not load class: " + destClassName); throw new RuntimeException("Could not load class: " + destClassName);
} }
try { try {
dest = destClass.newInstance(); dest = destClass.newInstance();
dest.setConfigXML(edgeElement.getChildren(), simulation); @SuppressWarnings("unchecked")
List<Element> children = edgeElement.getChildren();
dest.setConfigXML(children, simulation);
} catch (Exception e) { } catch (Exception e) {
throw (RuntimeException) throw (RuntimeException)
new RuntimeException("Unknown class: " + destClassName).initCause(e); new RuntimeException("Unknown class: " + destClassName).initCause(e);
@ -434,9 +422,9 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
public static class Edge { public static class Edge {
public Radio source = null; public Radio source = null;
public DestinationRadio superDest = null; public DGRMDestinationRadio superDest = null;
public Edge(Radio source, DestinationRadio dest) { public Edge(Radio source, DGRMDestinationRadio dest) {
this.source = source; this.source = source;
this.superDest = dest; this.superDest = dest;
} }

View file

@ -112,7 +112,7 @@ public class UDGM extends AbstractRadioMedium {
/* Add potential destination */ /* Add potential destination */
addEdge( addEdge(
new DirectedGraphMedium.Edge(source, new DirectedGraphMedium.Edge(source,
new DestinationRadio(dest))); new DGRMDestinationRadio(dest)));
} }
} }
} }