commit
150cb33b94
|
@ -381,7 +381,21 @@ public class Msp802154Radio extends Radio implements CustomDataRadio {
|
|||
}
|
||||
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() {
|
||||
return mote;
|
||||
}
|
||||
|
|
|
@ -168,6 +168,25 @@ public abstract class Radio extends MoteInterface {
|
|||
* @return Maximum output power indicator
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -91,9 +91,11 @@ public class DGRMConfigurator extends VisPlugin {
|
|||
private final static int IDX_DST = 1;
|
||||
private final static int IDX_RATIO = 2;
|
||||
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[] {
|
||||
"Source", "Destination", "RX Ratio", "RSSI", "Delay"
|
||||
"Source", "Destination", "RX Ratio", "RSSI","LQI", "Delay"
|
||||
};
|
||||
|
||||
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) {
|
||||
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) {
|
||||
for (double d=0; d <= 5; d++) {
|
||||
combo.addItem(d);
|
||||
|
@ -161,6 +167,17 @@ public class DGRMConfigurator extends VisPlugin {
|
|||
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() {
|
||||
private static final long serialVersionUID = -4669897764928372246L;
|
||||
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_SIGNAL).setCellEditor(new DefaultCellEditor(combo));
|
||||
graphTable.getColumnModel().getColumn(IDX_LQI).setCellEditor(new DefaultCellEditor(combo));
|
||||
graphTable.getColumnModel().getColumn(IDX_DELAY).setCellEditor(new DefaultCellEditor(combo));
|
||||
|
||||
graphTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
|
||||
|
@ -411,6 +429,9 @@ public class DGRMConfigurator extends VisPlugin {
|
|||
if (column == IDX_SIGNAL) {
|
||||
return ((DGRMDestinationRadio)edge.superDest).signal;
|
||||
}
|
||||
if (column == IDX_LQI) {
|
||||
return ((DGRMDestinationRadio)edge.superDest).lqi;
|
||||
}
|
||||
if (column == IDX_DELAY) {
|
||||
return ((DGRMDestinationRadio)edge.superDest).delay / Simulation.MILLISECOND;
|
||||
}
|
||||
|
@ -433,7 +454,10 @@ public class DGRMConfigurator extends VisPlugin {
|
|||
} else if (column == IDX_DELAY) {
|
||||
((DGRMDestinationRadio)edge.superDest).delay =
|
||||
((Number)value).longValue() * Simulation.MILLISECOND;
|
||||
} else {
|
||||
} else if (column == IDX_LQI) {
|
||||
((DGRMDestinationRadio)edge.superDest).lqi = ((Number)value).intValue();
|
||||
}
|
||||
else {
|
||||
super.setValueAt(value, row, column);
|
||||
}
|
||||
radioMedium.requestEdgeAnalysis();
|
||||
|
@ -461,6 +485,9 @@ public class DGRMConfigurator extends VisPlugin {
|
|||
if (column == IDX_SIGNAL) {
|
||||
return true;
|
||||
}
|
||||
if (column == IDX_LQI) {
|
||||
return true;
|
||||
}
|
||||
if (column == IDX_DELAY) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -117,6 +117,15 @@ public class DGRMVisualizerSkin implements VisualizerSkin {
|
|||
g.drawString(msg, x - msgWidth/2, y + 2*Visualizer.MOTE_RADIUS + 3);
|
||||
for (DestinationRadio r: dests) {
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
|
@ -124,7 +133,8 @@ public class DGRMVisualizerSkin implements VisualizerSkin {
|
|||
Position pos = r.radio.getPosition();
|
||||
Point pixel = visualizer.transformPositionToPixel(pos);
|
||||
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.setColor(Color.BLACK);
|
||||
g.drawString(msg, pixel.x - msgWidth/2, pixel.y + 2*Visualizer.MOTE_RADIUS + 3);
|
||||
|
|
|
@ -61,416 +61,410 @@ import se.sics.cooja.interfaces.Radio;
|
|||
* @author Fredrik Osterlind
|
||||
*/
|
||||
public abstract class AbstractRadioMedium extends RadioMedium {
|
||||
private static Logger logger = Logger.getLogger(AbstractRadioMedium.class);
|
||||
|
||||
/* Signal strengths in dBm.
|
||||
* Approx. values measured on TmoteSky */
|
||||
public static final double SS_NOTHING = -100;
|
||||
public static final double SS_STRONG = -10;
|
||||
public static final double SS_WEAK = -95;
|
||||
|
||||
private ArrayList<Radio> registeredRadios = new ArrayList<Radio>();
|
||||
|
||||
private ArrayList<RadioConnection> activeConnections = new ArrayList<RadioConnection>();
|
||||
|
||||
private RadioConnection lastConnection = null;
|
||||
|
||||
private Simulation simulation = null;
|
||||
|
||||
/* Book-keeping */
|
||||
public int COUNTER_TX = 0;
|
||||
public int COUNTER_RX = 0;
|
||||
public int COUNTER_INTERFERED = 0;
|
||||
|
||||
public class RadioMediumObservable extends Observable {
|
||||
public void setRadioMediumChanged() {
|
||||
setChanged();
|
||||
}
|
||||
public void setRadioMediumChangedAndNotify() {
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
private RadioMediumObservable radioMediumObservable = new RadioMediumObservable();
|
||||
|
||||
/**
|
||||
* This constructor should always be called from implemented radio mediums.
|
||||
*
|
||||
* @param simulation Simulation
|
||||
*/
|
||||
public AbstractRadioMedium(Simulation simulation) {
|
||||
this.simulation = simulation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return All registered radios
|
||||
*/
|
||||
public Radio[] getRegisteredRadios() {
|
||||
return registeredRadios.toArray(new Radio[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return All active connections
|
||||
*/
|
||||
public RadioConnection[] getActiveConnections() {
|
||||
/* NOTE: toArray([0]) creates array and handles synchronization */
|
||||
return activeConnections.toArray(new RadioConnection[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new connection from given radio.
|
||||
*
|
||||
* Determines which radios should receive or be interfered by the transmission.
|
||||
*
|
||||
* @param radio Source radio
|
||||
* @return New connection
|
||||
*/
|
||||
abstract public RadioConnection createConnections(Radio radio);
|
||||
|
||||
/**
|
||||
* Updates all radio interfaces' signal strengths according to
|
||||
* the current active connections.
|
||||
*/
|
||||
public void updateSignalStrengths() {
|
||||
|
||||
/* Reset signal strengths */
|
||||
for (Radio radio : getRegisteredRadios()) {
|
||||
radio.setCurrentSignalStrength(SS_NOTHING);
|
||||
}
|
||||
|
||||
/* Set signal strength to strong on destinations */
|
||||
RadioConnection[] conns = getActiveConnections();
|
||||
for (RadioConnection conn : conns) {
|
||||
if (conn.getSource().getCurrentSignalStrength() < SS_STRONG) {
|
||||
conn.getSource().setCurrentSignalStrength(SS_STRONG);
|
||||
}
|
||||
for (Radio dstRadio : conn.getDestinations()) {
|
||||
if (conn.getSource().getChannel() >= 0 &&
|
||||
dstRadio.getChannel() >= 0 &&
|
||||
conn.getSource().getChannel() != dstRadio.getChannel()) {
|
||||
continue;
|
||||
}
|
||||
if (dstRadio.getCurrentSignalStrength() < SS_STRONG) {
|
||||
dstRadio.setCurrentSignalStrength(SS_STRONG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 (conn.getSource().getChannel() >= 0 &&
|
||||
intfRadio.getChannel() >= 0 &&
|
||||
conn.getSource().getChannel() != intfRadio.getChannel()) {
|
||||
continue;
|
||||
}
|
||||
if (!intfRadio.isInterfered()) {
|
||||
/*logger.warn("Radio was not interfered");*/
|
||||
intfRadio.interfereAnyReception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove given radio from any active connections.
|
||||
* This method can be called if a radio node falls asleep or is removed.
|
||||
*
|
||||
* @param radio Radio
|
||||
*/
|
||||
private void removeFromActiveConnections(Radio radio) {
|
||||
/* This radio must not be a connection source */
|
||||
RadioConnection connection = getActiveConnectionFrom(radio);
|
||||
if (connection != null) {
|
||||
logger.fatal("Connection source turned off radio: " + radio);
|
||||
}
|
||||
|
||||
/* Set interfered if currently a connection destination */
|
||||
for (RadioConnection conn : activeConnections) {
|
||||
if (conn.isDestination(radio)) {
|
||||
conn.addInterfered(radio);
|
||||
if (!radio.isInterfered()) {
|
||||
radio.interfereAnyReception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private RadioConnection getActiveConnectionFrom(Radio source) {
|
||||
for (RadioConnection conn : activeConnections) {
|
||||
if (conn.getSource() == source) {
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This observer is responsible for detecting radio interface events, for example
|
||||
* new transmissions.
|
||||
*/
|
||||
private Observer radioEventsObserver = new Observer() {
|
||||
public void update(Observable obs, Object obj) {
|
||||
if (!(obs instanceof Radio)) {
|
||||
logger.fatal("Radio event dispatched by non-radio object");
|
||||
return;
|
||||
}
|
||||
Radio radio = (Radio) obs;
|
||||
|
||||
final Radio.RadioEvent event = radio.getLastEvent();
|
||||
if (event == Radio.RadioEvent.RECEPTION_STARTED ||
|
||||
event == Radio.RadioEvent.RECEPTION_INTERFERED ||
|
||||
event == Radio.RadioEvent.RECEPTION_FINISHED ||
|
||||
event == Radio.RadioEvent.UNKNOWN) {
|
||||
/* Ignored */
|
||||
return;
|
||||
}
|
||||
|
||||
if (event == Radio.RadioEvent.HW_ON) {
|
||||
|
||||
/* Update signal strengths */
|
||||
updateSignalStrengths();
|
||||
|
||||
} else if (event == Radio.RadioEvent.HW_OFF) {
|
||||
|
||||
/* Remove any radio connections from this radio */
|
||||
removeFromActiveConnections(radio);
|
||||
|
||||
/* Update signal strengths */
|
||||
updateSignalStrengths();
|
||||
|
||||
} else if (event == Radio.RadioEvent.TRANSMISSION_STARTED) {
|
||||
/* Create new radio connection */
|
||||
|
||||
if (radio.isReceiving()) {
|
||||
/* Radio starts transmitting when it should be receiving!
|
||||
* Ok, but it won't receive the packet */
|
||||
for (RadioConnection conn : activeConnections) {
|
||||
if (conn.isDestination(radio)) {
|
||||
conn.addInterfered(radio);
|
||||
}
|
||||
}
|
||||
radio.interfereAnyReception();
|
||||
}
|
||||
|
||||
RadioConnection newConnection = createConnections(radio);
|
||||
activeConnections.add(newConnection);
|
||||
for (Radio r: newConnection.getAllDestinations()) {
|
||||
if (newConnection.getDestinationDelay(r) == 0) {
|
||||
r.signalReceptionStart();
|
||||
} else {
|
||||
|
||||
/* EXPERIMENTAL: Simulating propagation delay */
|
||||
final Radio delayedRadio = r;
|
||||
TimeEvent delayedEvent = new TimeEvent(0) {
|
||||
public void execute(long t) {
|
||||
delayedRadio.signalReceptionStart();
|
||||
}
|
||||
};
|
||||
simulation.scheduleEvent(
|
||||
delayedEvent,
|
||||
simulation.getSimulationTime() + newConnection.getDestinationDelay(r));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Update signal strengths */
|
||||
updateSignalStrengths();
|
||||
|
||||
/* Notify observers */
|
||||
lastConnection = null;
|
||||
radioMediumObservable.setRadioMediumChangedAndNotify();
|
||||
|
||||
} else if (event == Radio.RadioEvent.TRANSMISSION_FINISHED) {
|
||||
/* Remove radio connection */
|
||||
|
||||
/* Connection */
|
||||
RadioConnection connection = getActiveConnectionFrom(radio);
|
||||
if (connection == null) {
|
||||
logger.fatal("No radio connection found");
|
||||
return;
|
||||
}
|
||||
|
||||
activeConnections.remove(connection);
|
||||
lastConnection = connection;
|
||||
COUNTER_TX++;
|
||||
for (Radio dstRadio : connection.getAllDestinations()) {
|
||||
if (connection.getDestinationDelay(dstRadio) == 0) {
|
||||
dstRadio.signalReceptionEnd();
|
||||
} else {
|
||||
|
||||
/* EXPERIMENTAL: Simulating propagation delay */
|
||||
final Radio delayedRadio = dstRadio;
|
||||
TimeEvent delayedEvent = new TimeEvent(0) {
|
||||
public void execute(long t) {
|
||||
delayedRadio.signalReceptionEnd();
|
||||
}
|
||||
};
|
||||
simulation.scheduleEvent(
|
||||
delayedEvent,
|
||||
simulation.getSimulationTime() + connection.getDestinationDelay(dstRadio));
|
||||
}
|
||||
}
|
||||
COUNTER_RX += connection.getDestinations().length;
|
||||
COUNTER_INTERFERED += connection.getInterfered().length;
|
||||
for (Radio intRadio : connection.getInterferedNonDestinations()) {
|
||||
intRadio.signalReceptionEnd();
|
||||
}
|
||||
|
||||
/* Update signal strengths */
|
||||
updateSignalStrengths();
|
||||
|
||||
/* Notify observers */
|
||||
radioMediumObservable.setRadioMediumChangedAndNotify();
|
||||
|
||||
} else if (event == Radio.RadioEvent.CUSTOM_DATA_TRANSMITTED) {
|
||||
|
||||
/* Connection */
|
||||
RadioConnection connection = getActiveConnectionFrom(radio);
|
||||
if (connection == null) {
|
||||
logger.fatal("No radio connection found");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Custom data object */
|
||||
Object data = ((CustomDataRadio) radio).getLastCustomDataTransmitted();
|
||||
if (data == null) {
|
||||
logger.fatal("No custom data object to forward");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Radio dstRadio : connection.getAllDestinations()) {
|
||||
|
||||
if (!radio.getClass().equals(dstRadio.getClass()) ||
|
||||
!(radio instanceof CustomDataRadio)) {
|
||||
/* Radios communicate via radio packets */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (connection.getDestinationDelay(dstRadio) == 0) {
|
||||
((CustomDataRadio) dstRadio).receiveCustomData(data);
|
||||
} else {
|
||||
|
||||
/* EXPERIMENTAL: Simulating propagation delay */
|
||||
final CustomDataRadio delayedRadio = (CustomDataRadio) dstRadio;
|
||||
final Object delayedData = data;
|
||||
TimeEvent delayedEvent = new TimeEvent(0) {
|
||||
public void execute(long t) {
|
||||
delayedRadio.receiveCustomData(delayedData);
|
||||
}
|
||||
};
|
||||
simulation.scheduleEvent(
|
||||
delayedEvent,
|
||||
simulation.getSimulationTime() + connection.getDestinationDelay(dstRadio));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else if (event == Radio.RadioEvent.PACKET_TRANSMITTED) {
|
||||
|
||||
/* Connection */
|
||||
RadioConnection connection = getActiveConnectionFrom(radio);
|
||||
if (connection == null) {
|
||||
logger.fatal("No radio connection found");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Radio packet */
|
||||
RadioPacket packet = radio.getLastPacketTransmitted();
|
||||
if (packet == null) {
|
||||
logger.fatal("No radio packet to forward");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Radio dstRadio : connection.getAllDestinations()) {
|
||||
|
||||
if (radio.getClass().equals(dstRadio.getClass()) &&
|
||||
radio instanceof CustomDataRadio) {
|
||||
/* Radios instead communicate via custom data objects */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Forward radio packet */
|
||||
if (connection.getDestinationDelay(dstRadio) == 0) {
|
||||
dstRadio.setReceivedPacket(packet);
|
||||
} else {
|
||||
|
||||
/* EXPERIMENTAL: Simulating propagation delay */
|
||||
final Radio delayedRadio = dstRadio;
|
||||
final RadioPacket delayedPacket = packet;
|
||||
TimeEvent delayedEvent = new TimeEvent(0) {
|
||||
public void execute(long t) {
|
||||
delayedRadio.setReceivedPacket(delayedPacket);
|
||||
}
|
||||
};
|
||||
simulation.scheduleEvent(
|
||||
delayedEvent,
|
||||
simulation.getSimulationTime() + connection.getDestinationDelay(dstRadio));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
logger.fatal("Unsupported radio event: " + event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void registerMote(Mote mote, Simulation sim) {
|
||||
registerRadioInterface(mote.getInterfaces().getRadio(), sim);
|
||||
}
|
||||
|
||||
public void unregisterMote(Mote mote, Simulation sim) {
|
||||
unregisterRadioInterface(mote.getInterfaces().getRadio(), sim);
|
||||
}
|
||||
|
||||
public void registerRadioInterface(Radio radio, Simulation sim) {
|
||||
if (radio == null) {
|
||||
logger.warn("No radio to register");
|
||||
return;
|
||||
}
|
||||
|
||||
registeredRadios.add(radio);
|
||||
radio.addObserver(radioEventsObserver);
|
||||
|
||||
/* Update signal strengths */
|
||||
updateSignalStrengths();
|
||||
}
|
||||
|
||||
public void unregisterRadioInterface(Radio radio, Simulation sim) {
|
||||
if (!registeredRadios.contains(radio)) {
|
||||
logger.warn("No radio to unregister: " + radio);
|
||||
return;
|
||||
}
|
||||
|
||||
radio.deleteObserver(radioEventsObserver);
|
||||
registeredRadios.remove(radio);
|
||||
|
||||
removeFromActiveConnections(radio);
|
||||
|
||||
/* Update signal strengths */
|
||||
updateSignalStrengths();
|
||||
}
|
||||
|
||||
public void addRadioMediumObserver(Observer observer) {
|
||||
radioMediumObservable.addObserver(observer);
|
||||
}
|
||||
|
||||
public Observable getRadioMediumObservable() {
|
||||
return radioMediumObservable;
|
||||
}
|
||||
|
||||
public void deleteRadioMediumObserver(Observer observer) {
|
||||
radioMediumObservable.deleteObserver(observer);
|
||||
}
|
||||
|
||||
public RadioConnection getLastConnection() {
|
||||
return lastConnection;
|
||||
}
|
||||
private static Logger logger = Logger.getLogger(AbstractRadioMedium.class);
|
||||
|
||||
/* Signal strengths in dBm.
|
||||
* Approx. values measured on TmoteSky */
|
||||
public static final double SS_NOTHING = -100;
|
||||
public static final double SS_STRONG = -10;
|
||||
public static final double SS_WEAK = -95;
|
||||
|
||||
private ArrayList<Radio> registeredRadios = new ArrayList<Radio>();
|
||||
|
||||
private ArrayList<RadioConnection> activeConnections = new ArrayList<RadioConnection>();
|
||||
|
||||
private RadioConnection lastConnection = null;
|
||||
|
||||
private Simulation simulation = null;
|
||||
|
||||
/* Book-keeping */
|
||||
public int COUNTER_TX = 0;
|
||||
public int COUNTER_RX = 0;
|
||||
public int COUNTER_INTERFERED = 0;
|
||||
|
||||
public class RadioMediumObservable extends Observable {
|
||||
public void setRadioMediumChanged() {
|
||||
setChanged();
|
||||
}
|
||||
public void setRadioMediumChangedAndNotify() {
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
private RadioMediumObservable radioMediumObservable = new RadioMediumObservable();
|
||||
|
||||
/**
|
||||
* This constructor should always be called from implemented radio mediums.
|
||||
*
|
||||
* @param simulation Simulation
|
||||
*/
|
||||
public AbstractRadioMedium(Simulation simulation) {
|
||||
this.simulation = simulation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return All registered radios
|
||||
*/
|
||||
public Radio[] getRegisteredRadios() {
|
||||
return registeredRadios.toArray(new Radio[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return All active connections
|
||||
*/
|
||||
public RadioConnection[] getActiveConnections() {
|
||||
/* NOTE: toArray([0]) creates array and handles synchronization */
|
||||
return activeConnections.toArray(new RadioConnection[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new connection from given radio.
|
||||
*
|
||||
* Determines which radios should receive or be interfered by the transmission.
|
||||
*
|
||||
* @param radio Source radio
|
||||
* @return New connection
|
||||
*/
|
||||
abstract public RadioConnection createConnections(Radio radio);
|
||||
|
||||
/**
|
||||
* Updates all radio interfaces' signal strengths according to
|
||||
* the current active connections.
|
||||
*/
|
||||
public void updateSignalStrengths() {
|
||||
|
||||
/* Reset signal strengths */
|
||||
for (Radio radio : getRegisteredRadios()) {
|
||||
radio.setCurrentSignalStrength(SS_NOTHING);
|
||||
}
|
||||
|
||||
/* Set signal strength to strong on destinations */
|
||||
RadioConnection[] conns = getActiveConnections();
|
||||
for (RadioConnection conn : conns) {
|
||||
if (conn.getSource().getCurrentSignalStrength() < SS_STRONG) {
|
||||
conn.getSource().setCurrentSignalStrength(SS_STRONG);
|
||||
}
|
||||
for (Radio dstRadio : conn.getDestinations()) {
|
||||
if (conn.getSource().getChannel() >= 0 &&
|
||||
dstRadio.getChannel() >= 0 &&
|
||||
conn.getSource().getChannel() != dstRadio.getChannel()) {
|
||||
continue;
|
||||
}
|
||||
if (dstRadio.getCurrentSignalStrength() < SS_STRONG) {
|
||||
dstRadio.setCurrentSignalStrength(SS_STRONG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 (conn.getSource().getChannel() >= 0 &&
|
||||
intfRadio.getChannel() >= 0 &&
|
||||
conn.getSource().getChannel() != intfRadio.getChannel()) {
|
||||
continue;
|
||||
}
|
||||
if (!intfRadio.isInterfered()) {
|
||||
/*logger.warn("Radio was not interfered");*/
|
||||
intfRadio.interfereAnyReception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove given radio from any active connections.
|
||||
* This method can be called if a radio node falls asleep or is removed.
|
||||
*
|
||||
* @param radio Radio
|
||||
*/
|
||||
private void removeFromActiveConnections(Radio radio) {
|
||||
/* This radio must not be a connection source */
|
||||
RadioConnection connection = getActiveConnectionFrom(radio);
|
||||
if (connection != null) {
|
||||
logger.fatal("Connection source turned off radio: " + radio);
|
||||
}
|
||||
|
||||
/* Set interfered if currently a connection destination */
|
||||
for (RadioConnection conn : activeConnections) {
|
||||
if (conn.isDestination(radio)) {
|
||||
conn.addInterfered(radio);
|
||||
if (!radio.isInterfered()) {
|
||||
radio.interfereAnyReception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private RadioConnection getActiveConnectionFrom(Radio source) {
|
||||
for (RadioConnection conn : activeConnections) {
|
||||
if (conn.getSource() == source) {
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This observer is responsible for detecting radio interface events, for example
|
||||
* new transmissions.
|
||||
*/
|
||||
private Observer radioEventsObserver = new Observer() {
|
||||
public void update(Observable obs, Object obj) {
|
||||
if (!(obs instanceof Radio)) {
|
||||
logger.fatal("Radio event dispatched by non-radio object");
|
||||
return;
|
||||
}
|
||||
Radio radio = (Radio) obs;
|
||||
|
||||
final Radio.RadioEvent event = radio.getLastEvent();
|
||||
|
||||
switch (event) {
|
||||
case RECEPTION_STARTED:
|
||||
case RECEPTION_INTERFERED:
|
||||
case RECEPTION_FINISHED:
|
||||
case UNKNOWN:
|
||||
return;
|
||||
case HW_ON: {
|
||||
/* Update signal strengths */
|
||||
updateSignalStrengths();
|
||||
}
|
||||
break;
|
||||
case HW_OFF: {
|
||||
/* Remove any radio connections from this radio */
|
||||
removeFromActiveConnections(radio);
|
||||
/* Update signal strengths */
|
||||
updateSignalStrengths();
|
||||
}
|
||||
break;
|
||||
case TRANSMISSION_STARTED: {
|
||||
/* Create new radio connection */
|
||||
if (radio.isReceiving()) {
|
||||
/*
|
||||
* Radio starts transmitting when it should be
|
||||
* receiving! Ok, but it won't receive the packet
|
||||
*/
|
||||
radio.interfereAnyReception();
|
||||
for (RadioConnection conn : activeConnections) {
|
||||
if (conn.isDestination(radio)) {
|
||||
conn.addInterfered(radio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RadioConnection newConnection = createConnections(radio);
|
||||
activeConnections.add(newConnection);
|
||||
|
||||
for (Radio r : newConnection.getAllDestinations()) {
|
||||
if (newConnection.getDestinationDelay(r) == 0) {
|
||||
r.signalReceptionStart();
|
||||
} else {
|
||||
/* EXPERIMENTAL: Simulating propagation delay */
|
||||
final Radio delayedRadio = r;
|
||||
TimeEvent delayedEvent = new TimeEvent(0) {
|
||||
public void execute(long t) {
|
||||
delayedRadio.signalReceptionStart();
|
||||
}
|
||||
};
|
||||
simulation.scheduleEvent(delayedEvent, simulation.getSimulationTime() + newConnection.getDestinationDelay(r));
|
||||
|
||||
}
|
||||
} /* Update signal strengths */
|
||||
updateSignalStrengths();
|
||||
|
||||
/* Notify observers */
|
||||
lastConnection = null;
|
||||
radioMediumObservable.setRadioMediumChangedAndNotify();
|
||||
}
|
||||
break;
|
||||
case TRANSMISSION_FINISHED: {
|
||||
/* Remove radio connection */
|
||||
|
||||
/* Connection */
|
||||
RadioConnection connection = getActiveConnectionFrom(radio);
|
||||
if (connection == null) {
|
||||
logger.fatal("No radio connection found");
|
||||
return;
|
||||
}
|
||||
|
||||
activeConnections.remove(connection);
|
||||
lastConnection = connection;
|
||||
COUNTER_TX++;
|
||||
for (Radio dstRadio : connection.getAllDestinations()) {
|
||||
if (connection.getDestinationDelay(dstRadio) == 0) {
|
||||
dstRadio.signalReceptionEnd();
|
||||
} else {
|
||||
|
||||
/* EXPERIMENTAL: Simulating propagation delay */
|
||||
final Radio delayedRadio = dstRadio;
|
||||
TimeEvent delayedEvent = new TimeEvent(0) {
|
||||
public void execute(long t) {
|
||||
delayedRadio.signalReceptionEnd();
|
||||
}
|
||||
};
|
||||
simulation.scheduleEvent(delayedEvent,
|
||||
simulation.getSimulationTime() + connection.getDestinationDelay(dstRadio));
|
||||
}
|
||||
}
|
||||
COUNTER_RX += connection.getDestinations().length;
|
||||
COUNTER_INTERFERED += connection.getInterfered().length;
|
||||
for (Radio intRadio : connection.getInterferedNonDestinations()) {
|
||||
intRadio.signalReceptionEnd();
|
||||
}
|
||||
|
||||
/* Update signal strengths */
|
||||
updateSignalStrengths();
|
||||
|
||||
/* Notify observers */
|
||||
radioMediumObservable.setRadioMediumChangedAndNotify();
|
||||
}
|
||||
break;
|
||||
case CUSTOM_DATA_TRANSMITTED: {
|
||||
|
||||
/* Connection */
|
||||
RadioConnection connection = getActiveConnectionFrom(radio);
|
||||
if (connection == null) {
|
||||
logger.fatal("No radio connection found");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Custom data object */
|
||||
Object data = ((CustomDataRadio) radio).getLastCustomDataTransmitted();
|
||||
if (data == null) {
|
||||
logger.fatal("No custom data object to forward");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Radio dstRadio : connection.getAllDestinations()) {
|
||||
|
||||
if (!radio.getClass().equals(dstRadio.getClass()) || !(radio instanceof CustomDataRadio)) {
|
||||
/* Radios communicate via radio packets */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (connection.getDestinationDelay(dstRadio) == 0) {
|
||||
((CustomDataRadio) dstRadio).receiveCustomData(data);
|
||||
} else {
|
||||
|
||||
/* EXPERIMENTAL: Simulating propagation delay */
|
||||
final CustomDataRadio delayedRadio = (CustomDataRadio) dstRadio;
|
||||
final Object delayedData = data;
|
||||
TimeEvent delayedEvent = new TimeEvent(0) {
|
||||
public void execute(long t) {
|
||||
delayedRadio.receiveCustomData(delayedData);
|
||||
}
|
||||
};
|
||||
simulation.scheduleEvent(delayedEvent,
|
||||
simulation.getSimulationTime() + connection.getDestinationDelay(dstRadio));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case PACKET_TRANSMITTED: {
|
||||
/* Connection */
|
||||
RadioConnection connection = getActiveConnectionFrom(radio);
|
||||
if (connection == null) {
|
||||
logger.fatal("No radio connection found");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Radio packet */
|
||||
RadioPacket packet = radio.getLastPacketTransmitted();
|
||||
if (packet == null) {
|
||||
logger.fatal("No radio packet to forward");
|
||||
return;
|
||||
}
|
||||
|
||||
for (Radio dstRadio : connection.getAllDestinations()) {
|
||||
|
||||
if (radio.getClass().equals(dstRadio.getClass()) && radio instanceof CustomDataRadio) {
|
||||
/* Radios instead communicate via custom data objects */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Forward radio packet */
|
||||
if (connection.getDestinationDelay(dstRadio) == 0) {
|
||||
dstRadio.setReceivedPacket(packet);
|
||||
} else {
|
||||
|
||||
/* EXPERIMENTAL: Simulating propagation delay */
|
||||
final Radio delayedRadio = dstRadio;
|
||||
final RadioPacket delayedPacket = packet;
|
||||
TimeEvent delayedEvent = new TimeEvent(0) {
|
||||
public void execute(long t) {
|
||||
delayedRadio.setReceivedPacket(delayedPacket);
|
||||
}
|
||||
};
|
||||
simulation.scheduleEvent(delayedEvent,
|
||||
simulation.getSimulationTime() + connection.getDestinationDelay(dstRadio));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logger.fatal("Unsupported radio event: " + event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void registerMote(Mote mote, Simulation sim) {
|
||||
registerRadioInterface(mote.getInterfaces().getRadio(), sim);
|
||||
}
|
||||
|
||||
public void unregisterMote(Mote mote, Simulation sim) {
|
||||
unregisterRadioInterface(mote.getInterfaces().getRadio(), sim);
|
||||
}
|
||||
|
||||
public void registerRadioInterface(Radio radio, Simulation sim) {
|
||||
if (radio == null) {
|
||||
logger.warn("No radio to register");
|
||||
return;
|
||||
}
|
||||
|
||||
registeredRadios.add(radio);
|
||||
radio.addObserver(radioEventsObserver);
|
||||
|
||||
/* Update signal strengths */
|
||||
updateSignalStrengths();
|
||||
}
|
||||
|
||||
public void unregisterRadioInterface(Radio radio, Simulation sim) {
|
||||
if (!registeredRadios.contains(radio)) {
|
||||
logger.warn("No radio to unregister: " + radio);
|
||||
return;
|
||||
}
|
||||
|
||||
radio.deleteObserver(radioEventsObserver);
|
||||
registeredRadios.remove(radio);
|
||||
|
||||
removeFromActiveConnections(radio);
|
||||
|
||||
/* Update signal strengths */
|
||||
updateSignalStrengths();
|
||||
}
|
||||
|
||||
public void addRadioMediumObserver(Observer observer) {
|
||||
radioMediumObservable.addObserver(observer);
|
||||
}
|
||||
|
||||
public Observable getRadioMediumObservable() {
|
||||
return radioMediumObservable;
|
||||
}
|
||||
|
||||
public void deleteRadioMediumObserver(Observer observer) {
|
||||
radioMediumObservable.deleteObserver(observer);
|
||||
}
|
||||
|
||||
public RadioConnection getLastConnection() {
|
||||
return lastConnection;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ public class DGRMDestinationRadio extends DestinationRadio {
|
|||
public double ratio = 1.0; /* Link success ratio (per packet). */
|
||||
public double signal = AbstractRadioMedium.SS_STRONG; /* RSSI */
|
||||
public long delay = 0; /* EXPERIMENTAL: Propagation delay (us). */
|
||||
public int lqi = 105;
|
||||
|
||||
public DGRMDestinationRadio() {
|
||||
super();
|
||||
|
@ -54,6 +55,7 @@ public class DGRMDestinationRadio extends DestinationRadio {
|
|||
clone.ratio = this.ratio;
|
||||
clone.delay = this.delay;
|
||||
clone.signal = this.signal;
|
||||
clone.lqi = this.lqi;
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
@ -69,6 +71,11 @@ public class DGRMDestinationRadio extends DestinationRadio {
|
|||
element.setText("" + signal);
|
||||
config.add(element);
|
||||
|
||||
element = new Element("lqi");
|
||||
element.setText("" + lqi);
|
||||
config.add(element);
|
||||
|
||||
|
||||
element = new Element("delay");
|
||||
element.setText("" + delay);
|
||||
config.add(element);
|
||||
|
@ -85,6 +92,8 @@ public class DGRMDestinationRadio extends DestinationRadio {
|
|||
ratio = Double.parseDouble(element.getText());
|
||||
} else if (element.getName().equals("signal")) {
|
||||
signal = Double.parseDouble(element.getText());
|
||||
} else if (element.getName().equals("lqi")) {
|
||||
lqi = Integer.parseInt(element.getText());
|
||||
} else if (element.getName().equals("delay")) {
|
||||
delay = Long.parseLong(element.getText());
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
@ -71,7 +72,7 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
private boolean edgesDirty = true;
|
||||
|
||||
/* 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() {
|
||||
/* Do not initialize radio medium: use only for hash table */
|
||||
|
@ -164,45 +165,42 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
/* Set signal strengths */
|
||||
RadioConnection[] conns = getActiveConnections();
|
||||
for (RadioConnection conn : conns) {
|
||||
/* When sending RSSI is Strong!
|
||||
* TODO: is this reasonable
|
||||
*/
|
||||
if (conn.getSource().getCurrentSignalStrength() < SS_STRONG) {
|
||||
conn.getSource().setCurrentSignalStrength(SS_STRONG);
|
||||
}
|
||||
for (Radio dstRadio : conn.getDestinations()) {
|
||||
if (dstRadio.getCurrentSignalStrength() < SS_STRONG) {
|
||||
dstRadio.setCurrentSignalStrength(SS_STRONG);
|
||||
//Maximum reception signal of all possible radios received
|
||||
DGRMDestinationRadio dstRadios[] = getPotentialDestinations(conn.getSource());
|
||||
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.
|
||||
*/
|
||||
protected void analyzeEdges() {
|
||||
Hashtable<Radio,ArrayList<DestinationRadio>> listTable =
|
||||
new Hashtable<Radio,ArrayList<DestinationRadio>>();
|
||||
Hashtable<Radio,ArrayList<DGRMDestinationRadio>> listTable =
|
||||
new Hashtable<Radio,ArrayList<DGRMDestinationRadio>>();
|
||||
|
||||
/* Fill edge hash table with all edges */
|
||||
for (Edge edge: getEdges()) {
|
||||
ArrayList<DestinationRadio> destRadios;
|
||||
ArrayList<DGRMDestinationRadio> destRadios;
|
||||
if (!listTable.containsKey(edge.source)) {
|
||||
destRadios = new ArrayList<DestinationRadio>();
|
||||
destRadios = new ArrayList<DGRMDestinationRadio>();
|
||||
} else {
|
||||
destRadios = listTable.get(edge.source);
|
||||
}
|
||||
|
@ -212,11 +210,11 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
}
|
||||
|
||||
/* Convert to arrays */
|
||||
Hashtable<Radio,DestinationRadio[]> arrTable = new Hashtable<Radio,DestinationRadio[]>();
|
||||
Hashtable<Radio,DGRMDestinationRadio[]> arrTable = new Hashtable<Radio,DGRMDestinationRadio[]>();
|
||||
Enumeration<Radio> sources = listTable.keys();
|
||||
while (sources.hasMoreElements()) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -231,7 +229,7 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
* @param source Source radio
|
||||
* @return All potential destination radios
|
||||
*/
|
||||
public DestinationRadio[] getPotentialDestinations(Radio source) {
|
||||
public DGRMDestinationRadio[] getPotentialDestinations(Radio source) {
|
||||
if (edgesDirty) {
|
||||
analyzeEdges();
|
||||
}
|
||||
|
@ -249,7 +247,7 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
|
||||
/* Create new radio connection using edge hash table */
|
||||
RadioConnection newConn = new RadioConnection(source);
|
||||
DestinationRadio[] destinations = getPotentialDestinations(source);
|
||||
DGRMDestinationRadio[] destinations = getPotentialDestinations(source);
|
||||
if (destinations == null || destinations.length == 0) {
|
||||
/* No destinations */
|
||||
/*logger.info(sendingRadio + ": No dest");*/
|
||||
|
@ -257,20 +255,14 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
}
|
||||
|
||||
/*logger.info(source + ": " + destinations.length + " potential destinations");*/
|
||||
for (DestinationRadio d: destinations) {
|
||||
DGRMDestinationRadio dest = (DGRMDestinationRadio) d;
|
||||
for (DGRMDestinationRadio dest: destinations) {
|
||||
|
||||
if (dest.radio == source) {
|
||||
/* Fail: cannot receive our own transmission */
|
||||
/*logger.info(source + ": Fail, receiver is sender");*/
|
||||
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()) {
|
||||
/* Fail: radio is off */
|
||||
|
@ -278,50 +270,7 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
newConn.addInterfered(dest.radio);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dest.ratio < 1.0 && random.nextDouble() > dest.ratio) {
|
||||
/*logger.info(source + ": Fail, randomly");*/
|
||||
/* TODO Interfere now? */
|
||||
newConn.addInterfered(dest.radio);
|
||||
|
||||
dest.radio.interfereAnyReception();
|
||||
RadioConnection otherConnection = null;
|
||||
for (RadioConnection conn : getActiveConnections()) {
|
||||
for (Radio dstRadio : conn.getDestinations()) {
|
||||
if (dstRadio == dest.radio) {
|
||||
otherConnection = conn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (otherConnection != null) {
|
||||
otherConnection.addInterfered(dest.radio);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dest.radio.isReceiving()) {
|
||||
/* Fail: radio is already actively receiving */
|
||||
/*logger.info(source + ": Fail, receiving");*/
|
||||
newConn.addInterfered(dest.radio);
|
||||
|
||||
/* We will also interfere with the other connection */
|
||||
dest.radio.interfereAnyReception();
|
||||
RadioConnection otherConnection = null;
|
||||
for (RadioConnection conn : getActiveConnections()) {
|
||||
for (Radio dstRadio : conn.getDestinations()) {
|
||||
if (dstRadio == dest.radio) {
|
||||
otherConnection = conn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (otherConnection != null) {
|
||||
otherConnection.addInterfered(dest.radio);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (dest.radio.isInterfered()) {
|
||||
/* Fail: radio is interfered in another connection */
|
||||
/*logger.info(source + ": Fail, interfered");*/
|
||||
|
@ -329,6 +278,41 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
continue;
|
||||
}
|
||||
|
||||
int srcc = source.getChannel();
|
||||
int dstc = dest.radio.getChannel();
|
||||
if ( srcc >= 0 && dstc >= 0 && srcc != dstc) {
|
||||
/* Fail: radios are on different (but configured) channels */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dest.radio.isReceiving()) {
|
||||
/* Fail: radio is already actively receiving */
|
||||
/*logger.info(source + ": Fail, receiving");*/
|
||||
newConn.addInterfered(dest.radio);
|
||||
|
||||
/* We will also interfere with the other connection */
|
||||
dest.radio.interfereAnyReception();
|
||||
|
||||
// Find connection, that is sending to that radio
|
||||
// and mark the destination as interfered
|
||||
for (RadioConnection conn : getActiveConnections()) {
|
||||
for (Radio dstRadio : conn.getDestinations()) {
|
||||
if (dstRadio == dest.radio) {
|
||||
conn.addInterfered(dest.radio);;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dest.ratio < 1.0 && random.nextDouble() > dest.ratio) {
|
||||
/* Fail: Reception ratio */
|
||||
/*logger.info(source + ": Fail, randomly");*/
|
||||
newConn.addInterfered(dest.radio);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Success: radio starts receiving */
|
||||
/*logger.info(source + ": OK: " + dest.radio);*/
|
||||
newConn.addDestination(dest.radio, dest.delay);
|
||||
|
@ -358,7 +342,8 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
delayedConfiguration = configXML;
|
||||
return true;
|
||||
}
|
||||
public void simulationFinishedLoading() {
|
||||
|
||||
public void simulationFinishedLoading() {
|
||||
if (delayedConfiguration == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -366,9 +351,10 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
boolean oldConfig = false;
|
||||
for (Element element : delayedConfiguration) {
|
||||
if (element.getName().equals("edge")) {
|
||||
Collection<Element> edgeConfig = element.getChildren();
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Element> edgeConfig = element.getChildren();
|
||||
Radio source = null;
|
||||
DestinationRadio dest = null;
|
||||
DGRMDestinationRadio dest = null;
|
||||
for (Element edgeElement : edgeConfig) {
|
||||
if (edgeElement.getName().equals("src")) {
|
||||
oldConfig = true;
|
||||
|
@ -387,7 +373,7 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
} else if (oldConfig && edgeElement.getName().equals("ratio")) {
|
||||
/* Old config: parse link ratio */
|
||||
double ratio = Double.parseDouble(edgeElement.getText());
|
||||
((DGRMDestinationRadio)dest).ratio = ratio;
|
||||
dest.ratio = ratio;
|
||||
} else if (edgeElement.getName().equals("dest")) {
|
||||
if (oldConfig) {
|
||||
/* Old config: create simple destination link */
|
||||
|
@ -405,14 +391,16 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
if (destClassName == null || destClassName.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
Class<? extends DestinationRadio> destClass =
|
||||
simulation.getGUI().tryLoadClass(this, DestinationRadio.class, destClassName);
|
||||
Class<? extends DGRMDestinationRadio> destClass =
|
||||
simulation.getGUI().tryLoadClass(this, DGRMDestinationRadio.class, destClassName);
|
||||
if (destClass == null) {
|
||||
throw new RuntimeException("Could not load class: " + destClassName);
|
||||
}
|
||||
try {
|
||||
dest = destClass.newInstance();
|
||||
dest.setConfigXML(edgeElement.getChildren(), simulation);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Element> children = edgeElement.getChildren();
|
||||
dest.setConfigXML(children, simulation);
|
||||
} catch (Exception e) {
|
||||
throw (RuntimeException)
|
||||
new RuntimeException("Unknown class: " + destClassName).initCause(e);
|
||||
|
@ -434,9 +422,9 @@ public class DirectedGraphMedium extends AbstractRadioMedium {
|
|||
|
||||
public static class Edge {
|
||||
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.superDest = dest;
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ public class UDGM extends AbstractRadioMedium {
|
|||
/* Add potential destination */
|
||||
addEdge(
|
||||
new DirectedGraphMedium.Edge(source,
|
||||
new DestinationRadio(dest)));
|
||||
new DGRMDestinationRadio(dest)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue