radio-related changes:

radios can belong to different abstraction levels for example byte of packet radios.

=> lots of changes in surrounding files
This commit is contained in:
fros4943 2007-02-28 09:47:45 +00:00
parent 215df016b9
commit 54002df73b
13 changed files with 836 additions and 537 deletions

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: DummyRadioMedium.java,v 1.2 2007/01/09 10:10:18 fros4943 Exp $ * $Id: DummyRadioMedium.java,v 1.3 2007/02/28 09:51:11 fros4943 Exp $
*/ */
import java.util.Collection; import java.util.Collection;
@ -57,7 +57,7 @@ public class DummyRadioMedium extends RadioMedium {
// Do nothing // Do nothing
} }
public void registerRadioInterface(Radio radio, Position position, Simulation sim) { public void registerRadioInterface(Radio radio, Simulation sim) {
// Do nothing // Do nothing
logger.debug("I'm a dummy. Nothing will be registered by me."); logger.debug("I'm a dummy. Nothing will be registered by me.");
} }

View File

@ -26,14 +26,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: VisUAODV.java,v 1.2 2007/01/09 10:09:59 fros4943 Exp $ * $Id: VisUAODV.java,v 1.3 2007/02/28 09:50:51 fros4943 Exp $
*/ */
import java.awt.*; import java.awt.*;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import se.sics.cooja.*; import se.sics.cooja.*;
import se.sics.cooja.interfaces.Position; import se.sics.cooja.interfaces.*;
import se.sics.cooja.plugins.*; import se.sics.cooja.plugins.*;
/** /**
@ -62,28 +62,32 @@ public class VisUAODV extends VisTraffic {
} }
protected void paintConnection(RadioConnection connection, Graphics g2d) { protected void paintConnection(RadioConnection connection, Graphics g2d) {
Point sourcePixelPosition = transformPositionToPixel(connection.getSourcePosition()); Point sourcePixelPosition = transformPositionToPixel(connection.getSource().getPosition());
for (Position destPosition: connection.getDestinationPositons()) { for (Radio destRadio: connection.getDestinations()) {
Position destPosition = destRadio.getPosition();
Point destPixelPosition = transformPositionToPixel(destPosition); Point destPixelPosition = transformPositionToPixel(destPosition);
g2d.setColor(getColorOf(connection)); g2d.setColor(getColorOf(connection));
if (isRouteReply(connection.getSourceData())) { byte[] packet = ((PacketRadio)destRadio).getLastPacketReceived();
if (isRouteReply(packet)) {
((Graphics2D) g2d).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f)); ((Graphics2D) g2d).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
} }
g2d.drawLine(sourcePixelPosition.x, sourcePixelPosition.y, g2d.drawLine(sourcePixelPosition.x, sourcePixelPosition.y,
destPixelPosition.x, destPixelPosition.y); destPixelPosition.x, destPixelPosition.y);
int hopCount = getHopCount(connection.getSourceData()); int hopCount = getHopCount(packet);
if (hopCount >= 0) if (hopCount >= 0)
g2d.drawString("" + hopCount, sourcePixelPosition.x, sourcePixelPosition.y); g2d.drawString("" + hopCount, sourcePixelPosition.x, sourcePixelPosition.y);
} }
} }
protected Color getColorOf(RadioConnection conn) { protected Color getColorOf(RadioConnection conn) {
if (isRouteRequest(conn.getSourceData())) byte[] packet = ((PacketRadio)conn.getSource()).getLastPacketReceived();
if (isRouteRequest(packet))
return Color.RED; return Color.RED;
else if (isRouteReply(conn.getSourceData())) else if (isRouteReply(packet))
return Color.GREEN; return Color.GREEN;
else else
return Color.BLACK; return Color.BLACK;

View File

@ -24,7 +24,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* $Id: ConnectionLogger.java,v 1.4 2007/01/10 14:57:42 fros4943 Exp $ * $Id: ConnectionLogger.java,v 1.5 2007/02/28 09:47:55 fros4943 Exp $
*/ */
package se.sics.cooja; package se.sics.cooja;
@ -33,12 +33,14 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import se.sics.cooja.interfaces.PacketRadio;
import se.sics.cooja.interfaces.Position; import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio;
/** /**
* ConnectionLogger is a simple connection information outputter. All * A connection logger is a simple connection information outputter. All
* connections given via the method logConnection will be written to either * connections given to it will be written to either the currently configured
* default Log4J info stream, a log file or both. * Log4J info stream, a log file or both.
* *
* Log files have the following structure (seprated by tabs): SRC_POS [src_x] * Log files have the following structure (seprated by tabs): SRC_POS [src_x]
* [src_y] [src_z] SRC_DATA [sent data bytes] DEST_POS [dest_x] [dest_y] * [src_y] [src_z] SRC_DATA [sent data bytes] DEST_POS [dest_x] [dest_y]
@ -90,29 +92,29 @@ public class ConnectionLogger {
* Connection to output * Connection to output
*/ */
public void logConnection(RadioConnection conn) { public void logConnection(RadioConnection conn) {
if (myType == LOG_TO_LOG4J || myType == LOG_TO_FILE_AND_LOG4J) { if (myType == LOG_TO_LOG4J || myType == LOG_TO_FILE_AND_LOG4J) {
if (conn.getDestinationPositons() != null Radio[] destinations = conn.getDestinations();
&& conn.getDestinationPositons().length > 0) if (destinations != null && destinations.length > 0) {
for (Position destPos : conn.getDestinationPositons()) { for (Radio destRadio : destinations) {
logger.info("RADIODATA from " + conn.getSourcePosition() + " to " logger.info("RADIODATA from " + conn.getSource().getPosition()
+ destPos + "\tsize:" + conn.getSourceData().length); + " to " + destRadio.getPosition());
} }
else } else {
logger.info("RADIODATA from " + conn.getSourcePosition() + " to " logger.info("RADIODATA from " + conn.getSource().getPosition()
+ "[NOWHERE]" + "\tsize:" + conn.getSourceData().length); + " to [NOWHERE]");
}
} }
if (myType == LOG_TO_FILE || myType == LOG_TO_FILE_AND_LOG4J) {
if (myType == LOG_TO_FILE || myType == LOG_TO_FILE_AND_LOG4J) {
try { try {
FileOutputStream out = new FileOutputStream(myFile, true); FileOutputStream out = new FileOutputStream(myFile, true);
if (conn.getDestinationPositons() != null Radio[] destinations = conn.getDestinations();
&& conn.getDestinationPositons().length > 0) { if (destinations != null && destinations.length > 0) {
for (int i = 0; i < conn.getDestinationPositons().length; i++) { for (int i = 0; i < destinations.length; i++) {
// Source pos // Source pos
out.write("SRC_POS\t".getBytes()); out.write("SRC_POS\t".getBytes());
Position pos = conn.getSourcePosition(); Position pos = conn.getSource().getPosition();
out.write(Double.toString(pos.getXCoordinate()).getBytes()); out.write(Double.toString(pos.getXCoordinate()).getBytes());
out.write("\t".getBytes()); out.write("\t".getBytes());
out.write(Double.toString(pos.getYCoordinate()).getBytes()); out.write(Double.toString(pos.getYCoordinate()).getBytes());
@ -122,7 +124,9 @@ public class ConnectionLogger {
// Source data // Source data
out.write("SRC_DATA\t".getBytes()); out.write("SRC_DATA\t".getBytes());
for (byte b : conn.getSourceData()) { // TODO We need to log destination data again...
for (byte b : ((PacketRadio) conn.getSource())
.getLastPacketTransmitted()) {
String hexString = Integer.toHexString((int) b); String hexString = Integer.toHexString((int) b);
if (hexString.length() == 1) if (hexString.length() == 1)
hexString = "0" + hexString; hexString = "0" + hexString;
@ -132,7 +136,7 @@ public class ConnectionLogger {
// Destination pos // Destination pos
out.write("DEST_POS\t".getBytes()); out.write("DEST_POS\t".getBytes());
pos = conn.getDestinationPositons()[i]; pos = destinations[i].getPosition();
out.write(Double.toString(pos.getXCoordinate()).getBytes()); out.write(Double.toString(pos.getXCoordinate()).getBytes());
out.write("\t".getBytes()); out.write("\t".getBytes());
out.write(Double.toString(pos.getYCoordinate()).getBytes()); out.write(Double.toString(pos.getYCoordinate()).getBytes());
@ -142,7 +146,9 @@ public class ConnectionLogger {
// Source data // Source data
out.write("DEST_DATA\t".getBytes()); out.write("DEST_DATA\t".getBytes());
for (byte b : conn.getDestinationData()[i]) { // TODO We need to log destination data again...
for (byte b : ((PacketRadio) destinations[i])
.getLastPacketReceived()) {
String hexString = Integer.toHexString((int) b); String hexString = Integer.toHexString((int) b);
if (hexString.length() == 1) if (hexString.length() == 1)
hexString = "0" + hexString; hexString = "0" + hexString;
@ -156,7 +162,7 @@ public class ConnectionLogger {
} else { } else {
// Source pos // Source pos
out.write("SRC_POS\t".getBytes()); out.write("SRC_POS\t".getBytes());
Position pos = conn.getSourcePosition(); Position pos = conn.getSource().getPosition();
out.write(Double.toString(pos.getXCoordinate()).getBytes()); out.write(Double.toString(pos.getXCoordinate()).getBytes());
out.write("\t".getBytes()); out.write("\t".getBytes());
out.write(Double.toString(pos.getYCoordinate()).getBytes()); out.write(Double.toString(pos.getYCoordinate()).getBytes());
@ -166,12 +172,16 @@ public class ConnectionLogger {
// Source data // Source data
out.write("SRC_DATA\t".getBytes()); out.write("SRC_DATA\t".getBytes());
for (byte b : conn.getSourceData()) { // TODO We need to log destination data again...
for (byte b : ((PacketRadio) conn.getSource())
.getLastPacketTransmitted()) {
String hexString = Integer.toHexString((int) b); String hexString = Integer.toHexString((int) b);
if (hexString.length() == 1) if (hexString.length() == 1)
hexString = "0" + hexString; hexString = "0" + hexString;
out.write(hexString.getBytes()); out.write(hexString.getBytes());
} }
out.write("\t".getBytes());
out.write("[NOWHERE]".getBytes());
out.write("\n".getBytes()); out.write("\n".getBytes());
} }
out.close(); out.close();

View File

@ -26,139 +26,121 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: RadioConnection.java,v 1.3 2006/10/09 13:38:38 fros4943 Exp $ * $Id: RadioConnection.java,v 1.4 2007/02/28 09:47:55 fros4943 Exp $
*/ */
package se.sics.cooja; package se.sics.cooja;
import java.util.Vector; import java.util.Vector;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.Radio;
/** /**
* RadioConnection represents a radio connection between a sending radio * A radio connection represents a connection between a source radio and zero or
* and zero or more receiving radios. * more destination and interfered radios. Typically the destinations are able
* By registering as an observer to the current radio medium, all * to receive data sent by the source radio, and the interfered radios are not.
* radio connections and data sent in that medium can be accessed. *
*
* Each radio is associated with a position and some radio data.
* Often the destinations' and source's data will refer to the same object,
* but some radio mediums may want to distort the transferred data, hence
* resulting in different data sent and received.
*
* @see RadioMedium * @see RadioMedium
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
public class RadioConnection { public class RadioConnection {
private Radio sourceRadio; private Radio source;
private Position sourcePosition;
private byte[] sourceData;
private Vector<Radio> destinationRadios = new Vector<Radio>(); private Vector<Radio> destinations = new Vector<Radio>();
private Vector<Position> destinationPositions = new Vector<Position>();
private Vector<byte[]> destinationData = new Vector<byte[]>(); private Vector<Radio> interfered = new Vector<Radio>();
/**
* Creates a new radio connection with given source and no destinations.
*
* @param sourceRadio
* Source radio
*/
public RadioConnection(Radio sourceRadio) {
this.source = sourceRadio;
}
/** /**
* Set source of this connection. * Set source of this connection.
* *
* @param radio Source radio * @param radio
* @param position Source position * Source radio
* @param data Source data
*/ */
public void setSource(Radio radio, Position position, byte[] data) { public void setSource(Radio radio) {
sourceRadio = radio; source = radio;
sourcePosition = position;
sourceData = data;
} }
/** /**
* Add a connection destination. * Adds destination radio.
* *
* @param radio Source radio * @param radio
* @param position Source position * Radio
* @param data Source data
*/ */
public void addDestination(Radio radio, Position position, byte[] data) { public void addDestination(Radio radio) {
destinationRadios.add(radio); destinations.add(radio);
destinationPositions.add(position);
destinationData.add(data);
} }
/** /**
* Remove a connection destination. * Adds interfered radio.
* *
* @param radio Destination to remove * @param radio
* Radio
*/
public void addInterfered(Radio radio) {
interfered.add(radio);
}
/**
* Removes destination radio.
*
* @param radio
* Radio
*/ */
public void removeDestination(Radio radio) { public void removeDestination(Radio radio) {
int pos = destinationRadios.indexOf(radio); destinations.remove(radio);
if (pos >= 0) { }
destinationRadios.remove(pos);
destinationPositions.remove(pos); /**
destinationData.remove(pos); * Removes interfered radio.
} *
* @param radio
* Radio
*/
public void removeInterfered(Radio radio) {
interfered.remove(radio);
} }
/** /**
* @return Source radio * @return Source radio
*/ */
public Radio getSourceRadio() { public Radio getSource() {
return sourceRadio; return source;
} }
/** /**
* @return Source position * @return All destinations of this connection
*/ */
public Position getSourcePosition() { public Radio[] getDestinations() {
return sourcePosition;
}
/**
* Returns the data actually sent by source radio.
* @return Source data
*/
public byte[] getSourceData() {
return sourceData;
}
/**
* @return Array of destination radios
*/
public Radio[] getDestinationRadios() {
Radio[] radioArrayType; Radio[] radioArrayType;
Radio[] radioArray; Radio[] radioArray;
radioArrayType = new Radio[destinationRadios.size()]; radioArrayType = new Radio[destinations.size()];
radioArray = (Radio[]) destinationRadios.toArray(radioArrayType); radioArray = (Radio[]) destinations.toArray(radioArrayType);
return radioArray; return radioArray;
} }
/** /**
* @return Array of destination positions * @return All radios interfered by this connection
*/ */
public Position[] getDestinationPositons() { public Radio[] getInterfered() {
Position[] positionArrayType; Radio[] radioArrayType;
Position[] positionArray; Radio[] radioArray;
positionArrayType = new Position[destinationPositions.size()]; radioArrayType = new Radio[interfered.size()];
positionArray = (Position[]) destinationPositions.toArray(positionArrayType); radioArray = (Radio[]) interfered.toArray(radioArrayType);
return positionArray; return radioArray;
}
/**
* Returns an array of data actually received by each radio.
* @return Array of destination data
*/
public byte[][] getDestinationData() {
byte[][] dataArrayType;
byte[][] dataArray;
dataArrayType = new byte[destinationData.size()][];
dataArray = (byte[][]) destinationData.toArray(dataArrayType);
return dataArray;
} }
} }

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: RadioMedium.java,v 1.4 2007/01/10 14:57:42 fros4943 Exp $ * $Id: RadioMedium.java,v 1.5 2007/02/28 09:47:45 fros4943 Exp $
*/ */
package se.sics.cooja; package se.sics.cooja;
@ -36,7 +36,6 @@ import java.lang.reflect.InvocationTargetException;
import java.util.*; import java.util.*;
import org.jdom.Element; import org.jdom.Element;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.Radio;
/** /**
@ -79,7 +78,7 @@ public abstract class RadioMedium {
public abstract void unregisterMote(Mote mote, Simulation sim); public abstract void unregisterMote(Mote mote, Simulation sim);
/** /**
* Register a radio to this medium at a given position. * Register a radio to this radio medium.
* *
* Concerning radio data, this radio will be treated the same way as a mote's * Concerning radio data, this radio will be treated the same way as a mote's
* radio. This method can be used to add non-mote radio devices, such as a * radio. This method can be used to add non-mote radio devices, such as a
@ -87,16 +86,13 @@ public abstract class RadioMedium {
* *
* @param radio * @param radio
* Radio * Radio
* @param position
* Position
* @param sim * @param sim
* Simulation holding radio * Simulation holding radio
*/ */
public abstract void registerRadioInterface(Radio radio, Position position, public abstract void registerRadioInterface(Radio radio, Simulation sim);
Simulation sim);
/** /**
* Unregisters a radio interface from this medium. * Unregister given radio interface from this medium.
* *
* @param radio * @param radio
* Radio interface to unregister * Radio interface to unregister

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: ContikiRadio.java,v 1.10 2007/01/09 10:05:19 fros4943 Exp $ * $Id: ContikiRadio.java,v 1.11 2007/02/28 09:48:48 fros4943 Exp $
*/ */
package se.sics.cooja.contikimote.interfaces; package se.sics.cooja.contikimote.interfaces;
@ -39,6 +39,8 @@ import org.jdom.Element;
import se.sics.cooja.*; import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface; import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.PacketRadio;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.Radio;
/** /**
@ -46,9 +48,9 @@ import se.sics.cooja.interfaces.Radio;
* transmission rates, the underlying Contiki system can be locked in either * transmission rates, the underlying Contiki system can be locked in either
* transmission or reception states (using multi-threading). When a transmission * transmission or reception states (using multi-threading). When a transmission
* is initiated, it will automatically lock the Contiki system. When a packet is * is initiated, it will automatically lock the Contiki system. When a packet is
* received by this radio the Contiki system, the entitiy transfering the packet may explicitly * received by this radio the Contiki system, the entitiy transferring the
* lock the radio in receiving mode. After some time it should then deliver the * packet may explicitly lock the radio in receiving mode. After some time it
* packet. * should then deliver the packet.
* *
* It needs read/write access to the following core variables: * It needs read/write access to the following core variables:
* <ul> * <ul>
@ -64,7 +66,7 @@ import se.sics.cooja.interfaces.Radio;
* <li>char simRadioHWOn (radio hardware status (on/off)) * <li>char simRadioHWOn (radio hardware status (on/off))
* <li>int simSignalStrength (heard radio signal strength) * <li>int simSignalStrength (heard radio signal strength)
* <li>char simPower (number indicating power output) * <li>char simPower (number indicating power output)
* <li>int simRadioChannel * <li>int simRadioChannel (number indicating current channel)
* </ul> * </ul>
* <p> * <p>
* Dependency core interfaces are: * Dependency core interfaces are:
@ -75,9 +77,12 @@ import se.sics.cooja.interfaces.Radio;
* *
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
public class ContikiRadio extends Radio implements ContikiMoteInterface { public class ContikiRadio extends Radio implements ContikiMoteInterface,
PacketRadio {
private Mote myMote; private Mote myMote;
private SectionMoteMemory myMoteMemory; private SectionMoteMemory myMoteMemory;
private static Logger logger = Logger.getLogger(ContikiRadio.class); private static Logger logger = Logger.getLogger(ContikiRadio.class);
/** /**
@ -98,17 +103,18 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
private double myEnergyConsumption = 0.0; private double myEnergyConsumption = 0.0;
private boolean transmitting = false; private boolean isTransmitting = false;
private boolean isInterfered = false;
private int transmissionEndTime = -1; private int transmissionEndTime = -1;
private int interferenceEndTime = -1;
private int receptionEndTime = -1;
private RadioEvent lastEvent = RadioEvent.UNKNOWN; private RadioEvent lastEvent = RadioEvent.UNKNOWN;
private int lastEventTime = 0; private int lastEventTime = 0;
private int oldOutputPowerIndicator = -1; private int oldOutputPowerIndicator = -1;
/** /**
* Creates an interface to the radio at mote. * Creates an interface to the radio at mote.
* *
@ -135,10 +141,12 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
radioOn = myMoteMemory.getByteValueOf("simRadioHWOn") == 1; radioOn = myMoteMemory.getByteValueOf("simRadioHWOn") == 1;
} }
/* Contiki mote interface support */
public static String[] getCoreInterfaceDependencies() { public static String[] getCoreInterfaceDependencies() {
return new String[] { "radio_interface" }; return new String[] { "radio_interface" };
} }
/* Packet radio support */
public byte[] getLastPacketTransmitted() { public byte[] getLastPacketTransmitted() {
return packetFromMote; return packetFromMote;
} }
@ -146,30 +154,110 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
public byte[] getLastPacketReceived() { public byte[] getLastPacketReceived() {
return packetToMote; return packetToMote;
} }
public boolean isTransmitting() { public void setReceivedPacket(byte[] data) {
return transmitting; packetToMote = data;
} }
public int getTransmissionEndTime() { /* General radio support */
return transmissionEndTime; public boolean isTransmitting() {
return isTransmitting;
} }
public boolean isReceiving() { public boolean isReceiving() {
if (isLockedAtReceiving()) if (isLockedAtReceiving())
return true; return true;
return myMoteMemory.getIntValueOf("simInSize") != 0; return myMoteMemory.getIntValueOf("simInSize") != 0;
} }
public boolean isInterfered() {
return isInterfered;
}
public int getChannel() { public int getChannel() {
return myMoteMemory.getIntValueOf("simRadioChannel"); return myMoteMemory.getIntValueOf("simRadioChannel");
} }
public void signalReceptionStart() {
packetToMote = null;
if (isInterfered() || isReceiving() || isTransmitting()) {
interfereAnyReception();
return;
}
lockInReceivingMode();
lastEventTime = myMote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.RECEPTION_STARTED;
this.setChanged();
this.notifyObservers();
}
public void signalReceptionEnd() {
if (isInterfered() || packetToMote == null) {
// Reset interfered flag
isInterfered = false;
// Reset data
packetToMote = null;
myMoteMemory.setIntValueOf("simInSize", 0);
// Unlock (if locked)
myMoteMemory.setByteValueOf("simReceiving", (byte) 0);
return;
}
// Unlock (if locked)
myMoteMemory.setByteValueOf("simReceiving", (byte) 0);
// Set data
myMoteMemory.setIntValueOf("simInSize", packetToMote.length);
myMoteMemory.setByteArray("simInDataBuffer", packetToMote);
lastEventTime = myMote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.RECEPTION_FINISHED;
this.setChanged();
this.notifyObservers();
}
public RadioEvent getLastEvent() { public RadioEvent getLastEvent() {
return lastEvent; return lastEvent;
} }
public void interfereAnyReception() {
if (!isInterfered()) {
isInterfered = true;
lastEvent = RadioEvent.RECEPTION_INTERFERED;
lastEventTime = myMote.getSimulation().getSimulationTime();
this.setChanged();
this.notifyObservers();
}
}
public double getCurrentOutputPower() {
// TODO Implement method
logger.warn("Not implemeted, always returning 1.5 dBm");
return 1.5;
}
public int getCurrentOutputPowerIndicator() {
return (int) myMoteMemory.getByteValueOf("simPower");
}
public double getCurrentSignalStrength() {
return myMoteMemory.getIntValueOf("simSignalStrength");
}
public void setCurrentSignalStrength(double signalStrength) {
myMoteMemory.setIntValueOf("simSignalStrength", (int) signalStrength);
}
public Position getPosition() {
return myMote.getInterfaces().getPosition();
}
/** /**
* @return True if locked at transmitting * @return True if locked at transmitting
*/ */
@ -201,98 +289,9 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
// Lock core radio in receiving loop // Lock core radio in receiving loop
myMoteMemory.setByteValueOf("simReceiving", (byte) 1); myMoteMemory.setByteValueOf("simReceiving", (byte) 1);
lastEventTime = myMote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.RECEPTION_STARTED;
this.setChanged();
this.notifyObservers();
} }
public void receivePacket(byte[] data, int endTime) {
if (isInterfered() || isReceiving() || isTransmitting()) {
interferReception(endTime);
return;
}
lockInReceivingMode();
receptionEndTime = endTime;
packetToMote = data;
}
private void deliverPacket() {
// If mote is inactive, try to wake it up
if (myMote.getState() != Mote.State.ACTIVE) {
if (RAISES_EXTERNAL_INTERRUPT)
myMote.setState(Mote.State.ACTIVE);
if (myMote.getState() != Mote.State.ACTIVE) {
logger.fatal("Mote fell asleep during reception of packet, skipping packet!");
myMoteMemory.setByteValueOf("simReceiving", (byte) 0);
myMoteMemory.setIntValueOf("simInSize", 0);
this.setChanged();
this.notifyObservers();
return;
}
}
// Unlock (if locked)
myMoteMemory.setByteValueOf("simReceiving", (byte) 0);
// Set data
myMoteMemory.setIntValueOf("simInSize", packetToMote.length);
myMoteMemory.setByteArray("simInDataBuffer", packetToMote);
lastEventTime = myMote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.RECEPTION_FINISHED;
this.setChanged();
this.notifyObservers();
}
public void interferReception(int endTime) {
// Unlock (if locked)
myMoteMemory.setByteValueOf("simReceiving", (byte) 0);
// Reset data
myMoteMemory.setIntValueOf("simInSize", 0);
// Save interference end time (if updated)
interferenceEndTime = Math.max(interferenceEndTime, endTime);
if (lastEvent != RadioEvent.RECEPTION_INTERFERED) {
lastEvent = RadioEvent.RECEPTION_INTERFERED;
lastEventTime = myMote.getSimulation().getSimulationTime();
this.setChanged();
this.notifyObservers();
}
}
public boolean isInterfered() {
return interferenceEndTime >= myMote.getSimulation().getSimulationTime();
}
public double getCurrentOutputPower() {
// TODO Implement method
logger.warn("Not implemeted, always returning 1.5 dBm");
return 1.5;
}
public int getCurrentOutputPowerIndicator() {
return (int) myMoteMemory.getByteValueOf("simPower");
}
public double getCurrentSignalStrength() {
return myMoteMemory.getIntValueOf("simSignalStrength");
}
public void setCurrentSignalStrength(double signalStrength) {
myMoteMemory.setIntValueOf("simSignalStrength", (int) signalStrength);
}
public void doActionsBeforeTick() { public void doActionsBeforeTick() {
// Check if we need to release Contiki lock and deliver packet data
if (isLockedAtReceiving() && myMote.getSimulation().getSimulationTime() >= receptionEndTime) {
deliverPacket();
}
} }
public void doActionsAfterTick() { public void doActionsAfterTick() {
@ -300,18 +299,18 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
if (radioOn != (myMoteMemory.getByteValueOf("simRadioHWOn") == 1)) { if (radioOn != (myMoteMemory.getByteValueOf("simRadioHWOn") == 1)) {
// Radio changed // Radio changed
radioOn = !radioOn; radioOn = !radioOn;
if (!radioOn) { if (!radioOn) {
// Reset status // Reset status
myMoteMemory.setByteValueOf("simReceiving", (byte) 0); myMoteMemory.setByteValueOf("simReceiving", (byte) 0);
myMoteMemory.setIntValueOf("simInSize", 0); myMoteMemory.setIntValueOf("simInSize", 0);
myMoteMemory.setByteValueOf("simTransmitting", (byte) 0); myMoteMemory.setByteValueOf("simTransmitting", (byte) 0);
myMoteMemory.setIntValueOf("simOutSize", 0); myMoteMemory.setIntValueOf("simOutSize", 0);
transmitting = false; isTransmitting = false;
lastEvent = RadioEvent.HW_OFF; lastEvent = RadioEvent.HW_OFF;
} else } else
lastEvent = RadioEvent.HW_ON; lastEvent = RadioEvent.HW_ON;
lastEventTime = myMote.getSimulation().getSimulationTime(); lastEventTime = myMote.getSimulation().getSimulationTime();
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
@ -325,26 +324,28 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
// Check if radio output power changed // Check if radio output power changed
if (myMoteMemory.getByteValueOf("simPower") != oldOutputPowerIndicator) { if (myMoteMemory.getByteValueOf("simPower") != oldOutputPowerIndicator) {
oldOutputPowerIndicator = myMoteMemory.getByteValueOf("simPower"); oldOutputPowerIndicator = myMoteMemory.getByteValueOf("simPower");
lastEvent = RadioEvent.UNKNOWN;
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
} }
// Are we transmitting but should stop? // Are we transmitting but should stop?
if (transmitting && myMote.getSimulation().getSimulationTime() >= transmissionEndTime) { if (isTransmitting
&& myMote.getSimulation().getSimulationTime() >= transmissionEndTime) {
myMoteMemory.setByteValueOf("simTransmitting", (byte) 0); myMoteMemory.setByteValueOf("simTransmitting", (byte) 0);
myMoteMemory.setIntValueOf("simOutSize", 0); myMoteMemory.setIntValueOf("simOutSize", 0);
transmitting = false; isTransmitting = false;
lastEventTime = myMote.getSimulation().getSimulationTime(); lastEventTime = myMote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.TRANSMISSION_FINISHED; lastEvent = RadioEvent.TRANSMISSION_FINISHED;
// TODO Energy consumption of transmitted packet? // TODO Energy consumption of transmitted packet?
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
} }
// Check if a new transmission should be started // Check if a new transmission should be started
if (!transmitting && myMoteMemory.getByteValueOf("simTransmitting") == 1) { if (!isTransmitting && myMoteMemory.getByteValueOf("simTransmitting") == 1) {
transmitting = true; isTransmitting = true;
int size = myMoteMemory.getIntValueOf("simOutSize"); int size = myMoteMemory.getIntValueOf("simOutSize");
packetFromMote = myMoteMemory.getByteArray("simOutDataBuffer", size); packetFromMote = myMoteMemory.getByteArray("simOutDataBuffer", size);
@ -353,11 +354,17 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
int duration = (int) ((2 * size * 9) / 19.2); // ms int duration = (int) ((2 * size * 9) / 19.2); // ms
transmissionEndTime = myMote.getSimulation().getSimulationTime() transmissionEndTime = myMote.getSimulation().getSimulationTime()
+ Math.max(1, duration); + Math.max(1, duration);
lastEventTime = myMote.getSimulation().getSimulationTime(); lastEventTime = myMote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.TRANSMISSION_STARTED; lastEvent = RadioEvent.TRANSMISSION_STARTED;
this.setChanged(); this.setChanged();
this.notifyObservers(); this.notifyObservers();
// Deliver packet right away
lastEvent = RadioEvent.PACKET_TRANSMITTED;
this.setChanged();
this.notifyObservers();
} }
} }
@ -365,23 +372,24 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
// Location // Location
JPanel panel = new JPanel(); JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
final JLabel statusLabel = new JLabel(""); final JLabel statusLabel = new JLabel("");
final JLabel lastEventLabel = new JLabel(""); final JLabel lastEventLabel = new JLabel("");
final JLabel ssLabel = new JLabel(""); final JLabel ssLabel = new JLabel("");
final JButton updateButton = new JButton("Update SS"); final JButton updateButton = new JButton("Update SS");
panel.add(statusLabel); panel.add(statusLabel);
panel.add(lastEventLabel); panel.add(lastEventLabel);
panel.add(ssLabel); panel.add(ssLabel);
panel.add(updateButton); panel.add(updateButton);
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): " + getCurrentSignalStrength() + " dBm"); ssLabel.setText("Signal strength (not auto-updated): "
+ getCurrentSignalStrength() + " dBm");
} }
}); });
Observer observer; Observer observer;
this.addObserver(observer = new Observer() { this.addObserver(observer = new Observer() {
public void update(Observable obs, Object obj) { public void update(Observable obs, Object obj) {
@ -394,19 +402,21 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
else else
statusLabel.setText("HW turned off"); statusLabel.setText("HW turned off");
lastEventLabel.setText("Last event (time=" + lastEventTime + "): " + lastEvent); lastEventLabel.setText("Last event (time=" + lastEventTime + "): "
ssLabel.setText("Signal strength (not auto-updated): " + getCurrentSignalStrength() + " dBm"); + lastEvent);
ssLabel.setText("Signal strength (not auto-updated): "
+ getCurrentSignalStrength() + " dBm");
} }
}); });
observer.update(null, null); observer.update(null, null);
// Saving observer reference for releaseInterfaceVisualizer // Saving observer reference for releaseInterfaceVisualizer
panel.putClientProperty("intf_obs", observer); panel.putClientProperty("intf_obs", observer);
return panel; return panel;
} }
public void releaseInterfaceVisualizer(JPanel panel) { public void releaseInterfaceVisualizer(JPanel panel) {
Observer observer = (Observer) panel.getClientProperty("intf_obs"); Observer observer = (Observer) panel.getClientProperty("intf_obs");
if (observer == null) { if (observer == null) {
@ -416,7 +426,7 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
this.deleteObserver(observer); this.deleteObserver(observer);
} }
public double energyConsumptionPerTick() { public double energyConsumptionPerTick() {
return myEnergyConsumption; return myEnergyConsumption;
} }
@ -424,7 +434,7 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
public Collection<Element> getConfigXML() { public Collection<Element> getConfigXML() {
return null; return null;
} }
public void setConfigXML(Collection<Element> configXML, boolean visAvailable) { public void setConfigXML(Collection<Element> configXML, boolean visAvailable) {
} }

View File

@ -0,0 +1,41 @@
package se.sics.cooja.interfaces;
/**
* A byte radio is able to transmit and receive radio data on a byte level.
*
* The byte radio is a lower abstraction level than the packet radio and should,
* according to the bottom-up abstraction policy, implement the packet
* abstraction level.
*
* @author Fredrik Osterlind
*/
public interface ByteRadio extends PacketRadio {
/**
* Radio receives given byte.
*
* @param b
* Byte
* @param timestamp
* Timestamp information
*/
public void receiveByte(byte b, long timestamp);
/**
* @return Last byte transmitted by radio
*/
public byte getLastByteTransmitted();
/**
* Returns timestamp information of byte transmitted. This may for example be
* the number of cycles since transmission started.
*
* @return Timestamp info
*/
public long getLastByteTransmittedTimestamp();
/**
* @return Last byte received by radio
*/
public byte getLastByteReceived();
}

View File

@ -0,0 +1,33 @@
package se.sics.cooja.interfaces;
/**
* A packet radio is able to transmit and receive radio data on a packet level.
*
* The packet radio is the highest abstraction level of radios, and must
* therefore be implemented by all lower abstraction levels.
*
* @author Fredrik Osterlind
*/
public interface PacketRadio {
/**
* Sets the packet data that is being received during a connection. Different
* radio may handle the data differently, but as a general rule this data
* should be supplied as soon as possible.
*
* @param p
* Packet dat
*/
public void setReceivedPacket(byte[] p);
/**
* @return Last packet transmitted by radio
*/
public byte[] getLastPacketTransmitted();
/**
* @return Last packet received by radio
*/
public byte[] getLastPacketReceived();
}

View File

@ -24,7 +24,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* $Id: Radio.java,v 1.5 2006/10/11 15:13:57 fros4943 Exp $ * $Id: Radio.java,v 1.6 2007/02/28 09:49:20 fros4943 Exp $
*/ */
package se.sics.cooja.interfaces; package se.sics.cooja.interfaces;
@ -32,8 +32,15 @@ package se.sics.cooja.interfaces;
import se.sics.cooja.*; import se.sics.cooja.*;
/** /**
* A Radio represents a mote radio transceiver. An implementation should notify * A Radio represents a mote radio transceiver.
* all observers both when packets are received and transmitted. *
* A radio can support different abstraction levels such as transmitting and
* receiving on a byte or packet-basis. In order to support communication
* between different levels the general rule in COOJA is that all radios at a
* lower abstraction level must also implement all higher levels.
*
* @see PacketRadio
* @see ByteRadio
* *
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
@ -44,84 +51,65 @@ public abstract class Radio extends MoteInterface {
* Events that radios should notify observers about. * Events that radios should notify observers about.
*/ */
public enum RadioEvent { public enum RadioEvent {
UNKNOWN, UNKNOWN, HW_OFF, HW_ON, RECEPTION_STARTED, RECEPTION_FINISHED, RECEPTION_INTERFERED, TRANSMISSION_STARTED, TRANSMISSION_FINISHED, PACKET_TRANSMITTED, BYTE_TRANSMITTED
HW_OFF, HW_ON,
RECEPTION_STARTED, RECEPTION_INTERFERED, RECEPTION_FINISHED,
TRANSMISSION_STARTED, TRANSMISSION_FINISHED
} }
/** /**
* Returns last significant event at this radio. Method may for example be * Signal that a new reception just begun. This method should normally be
* used to learn the reason when a radio notifies a change to observers. * called from the radio medium.
*
* @see #signalReceptionEnd()
*/
public abstract void signalReceptionStart();
/**
* Signal that the current reception was ended. This method should normally be
* called from the radio medium.
*
* @see #signalReceptionStart()
*/
public abstract void signalReceptionEnd();
/**
* Returns last event at this radio. This method should be used to learn the
* reason when a radio notifies a change to observers.
* *
* @return Last radio event * @return Last radio event
*/ */
public abstract RadioEvent getLastEvent(); public abstract RadioEvent getLastEvent();
/**
* @return Last packet data transmitted, or currently being transmitted, from
* this radio.
*/
public abstract byte[] getLastPacketTransmitted();
/**
* @return Last packet data received, or currently being received, by this
* radio.
*/
public abstract byte[] getLastPacketReceived();
/**
* Receive given packet. If reception is not interfered during
* this time, the packet will be delivered ok.
*
* @param data
* Packet data
* @param endTime
* Time (ms) when reception is finished
*/
public abstract void receivePacket(byte[] data, int endTime);
/** /**
* Returns true if this radio is transmitting, or just finished transmitting, * Returns true if this radio is transmitting, or just finished transmitting,
* data. * data.
* *
* @see #getLastPacketTransmitted() * @see #isReceiving()
* @return True if radio is transmitting data * @return True if radio is transmitting data
*/ */
public abstract boolean isTransmitting(); public abstract boolean isTransmitting();
/**
* @return Transmission end time if any transmission active
*/
public abstract int getTransmissionEndTime();
/** /**
* Returns true if this radio is receiving data. * Returns true if this radio is receiving data.
* *
* @see #getLastPacketReceived() * @see #isTransmitting()
* @return True if radio is receiving data * @return True if radio is receiving data
*/ */
public abstract boolean isReceiving(); public abstract boolean isReceiving();
/** /**
* If a packet is being received, it will be interfered and dropped. The * Returns true if this radio had a connection that was dropped due to
* interference will continue until the given time, during which no other * interference.
* radio traffic may be received. This method can be used to simulate
* significant interference during transmissions.
*
* @param endTime
* Time when interference stops
*/
public abstract void interferReception(int endTime);
/**
* Returns true is this radio is currently hearing noise from another
* transmission.
* *
* @return True if this radio is interfered * @return True if this radio is interfered
*/ */
public abstract boolean isInterfered(); public abstract boolean isInterfered();
/**
* Interferes with any current reception. If this method is called, the packet
* will be dropped. This method can be used to simulate radio interference
* such as high background noise.
*/
public abstract void interfereAnyReception();
/** /**
* @return Current output power (dBm) * @return Current output power (dBm)
*/ */
@ -138,7 +126,8 @@ public abstract class Radio extends MoteInterface {
public abstract double getCurrentSignalStrength(); public abstract double getCurrentSignalStrength();
/** /**
* Sets surrounding signal strength. * Sets surrounding signal strength. This method should normally be called by
* the radio medium.
* *
* @param signalStrength * @param signalStrength
* Current surrounding signal strength * Current surrounding signal strength
@ -151,5 +140,13 @@ public abstract class Radio extends MoteInterface {
* @return Current channel number * @return Current channel number
*/ */
public abstract int getChannel(); public abstract int getChannel();
/**
* Returns the radio position.
* This is typically the position of the mote.
*
* @return Radio position
*/
public abstract Position getPosition();
} }

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: DisturberRadio.java,v 1.2 2007/01/09 10:01:14 fros4943 Exp $ * $Id: DisturberRadio.java,v 1.3 2007/02/28 09:49:48 fros4943 Exp $
*/ */
package se.sics.cooja.motes; package se.sics.cooja.motes;
@ -40,14 +40,14 @@ import org.apache.log4j.Logger;
import org.jdom.Element; import org.jdom.Element;
import se.sics.cooja.*; import se.sics.cooja.*;
import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.*;
/** /**
* This radio periodically transmits data on a configurable channel. * This radio periodically transmits data on a configurable channel.
* *
* @author Fredrik Osterlind, Thiemo Voigt * @author Fredrik Osterlind, Thiemo Voigt
*/ */
public class DisturberRadio extends Radio { public class DisturberRadio extends Radio implements PacketRadio {
private Mote myMote; private Mote myMote;
private static Logger logger = Logger.getLogger(DisturberRadio.class); private static Logger logger = Logger.getLogger(DisturberRadio.class);
@ -78,7 +78,8 @@ public class DisturberRadio extends Radio {
public DisturberRadio(Mote mote) { public DisturberRadio(Mote mote) {
this.myMote = mote; this.myMote = mote;
} }
/* Packet radio support */
public byte[] getLastPacketTransmitted() { public byte[] getLastPacketTransmitted() {
return packetFromMote; return packetFromMote;
} }
@ -87,6 +88,17 @@ public class DisturberRadio extends Radio {
return null; return null;
} }
public void setReceivedPacket(byte[] data) {
}
/* General radio support */
public void signalReceptionStart() {
}
public void signalReceptionEnd() {
}
public boolean isTransmitting() { public boolean isTransmitting() {
return transmitting; return transmitting;
} }
@ -96,8 +108,6 @@ public class DisturberRadio extends Radio {
} }
public boolean isReceiving() { public boolean isReceiving() {
if (isLockedAtReceiving())
return true;
return false; return false;
} }
@ -105,21 +115,15 @@ public class DisturberRadio extends Radio {
return distChannel; return distChannel;
} }
public Position getPosition() {
return myMote.getInterfaces().getPosition();
}
public RadioEvent getLastEvent() { public RadioEvent getLastEvent() {
return lastEvent; return lastEvent;
} }
/** public void interfereAnyReception() {
* @return True if locked at receiving
*/
private boolean isLockedAtReceiving() {
return false;
}
public void receivePacket(byte[] data, int endTime) {
}
public void interferReception(int endTime) {
} }
public boolean isInterfered() { public boolean isInterfered() {

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: VisTraffic.java,v 1.5 2007/01/09 09:49:24 fros4943 Exp $ * $Id: VisTraffic.java,v 1.6 2007/02/28 09:50:00 fros4943 Exp $
*/ */
package se.sics.cooja.plugins; package se.sics.cooja.plugins;
@ -38,6 +38,7 @@ import org.apache.log4j.Logger;
import se.sics.cooja.*; import se.sics.cooja.*;
import se.sics.cooja.interfaces.Position; import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio;
/** /**
* A Traffic Visualizer visualizes radio traffic by painting lines between * A Traffic Visualizer visualizes radio traffic by painting lines between
@ -124,11 +125,10 @@ public class VisTraffic extends Visualizer2D {
* Graphics to paint on * Graphics to paint on
*/ */
protected void paintConnection(PaintedConnection connection, Graphics g2d) { protected void paintConnection(PaintedConnection connection, Graphics g2d) {
Point sourcePixelPosition = transformPositionToPixel(connection.radioConnection Point sourcePixelPosition = transformPositionToPixel(connection.radioConnection.getSource().getPosition());
.getSourcePosition());
g2d.setColor(connection.getColor(simulation.isRunning())); g2d.setColor(connection.getColor(simulation.isRunning()));
for (Position destPosition : connection.radioConnection for (Radio destRadio : connection.radioConnection.getDestinations()) {
.getDestinationPositons()) { Position destPosition = destRadio.getPosition();
Point destPixelPosition = transformPositionToPixel(destPosition); Point destPixelPosition = transformPositionToPixel(destPosition);
g2d.drawLine(sourcePixelPosition.x, sourcePixelPosition.y, g2d.drawLine(sourcePixelPosition.x, sourcePixelPosition.y,
destPixelPosition.x, destPixelPosition.y); destPixelPosition.x, destPixelPosition.y);

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: SilentRadioMedium.java,v 1.2 2007/01/09 09:47:10 fros4943 Exp $ * $Id: SilentRadioMedium.java,v 1.3 2007/02/28 09:50:00 fros4943 Exp $
*/ */
package se.sics.cooja.radiomediums; package se.sics.cooja.radiomediums;
@ -57,7 +57,7 @@ public class SilentRadioMedium extends RadioMedium {
// Do nothing // Do nothing
} }
public void registerRadioInterface(Radio radio, Position position, Simulation sim) { public void registerRadioInterface(Radio radio, Simulation sim) {
// Do nothing // Do nothing
} }

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: UDGM.java,v 1.1 2007/01/09 09:47:36 fros4943 Exp $ * $Id: UDGM.java,v 1.2 2007/02/28 09:50:00 fros4943 Exp $
*/ */
package se.sics.cooja.radiomediums; package se.sics.cooja.radiomediums;
@ -47,35 +47,41 @@ import se.sics.cooja.plugins.Visualizer2D;
* The Unit Disk Graph medium has two different range parameters; one for * The Unit Disk Graph medium has two different range parameters; one for
* transmitting and one for interfering other transmissions. * transmitting and one for interfering other transmissions.
* *
* Radio data are analysed when all registered motes have ticked once (this * The radio medium supports both byte and packet radios. Any transmitted bytes
* medium is registered as a tick observer). For every mote in transmission * are forwarded TODO immediately with a timestamp (more fine-grained than
* range of a sending mote, current listen status is changed from hearing * ticks).
* nothing to hearing packet, or hearing packet to hearing noise. This way, if a
* mote hears two packets during one tick loop, it will receive none (noise). If
* a mote is in the interference range, the current listen status will be set to
* hears noise immediately.
* *
* This radio medium registers a temporary visual plugin class. * The radio medium registers a visualizer plugin. Via this plugin the current
* Via this plugin ranges can be viewed and changed. Active connection may also * radio states and range parameters can be viewed and changed.
* be viewed.
* *
* The registered radios' signal strengths are updated whenever the radio medium
* changes. There are three fixed levels: no surrounding traffic heard, noise
* heard and data heard.
*
* The radio output power indicator (0-100) is used in a very simple way; the
* total transmission (and interfering) range is multiplied with [power_ind]%.
*
* @see #SS_OK
* @see #SS_NOISE
* @see #SS_NOTHING
*
* @see VisUDGM
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
@ClassDescription("Unit Disk Graph Medium (UDGM)") @ClassDescription("Unit Disk Graph Medium (UDGM)")
public class UDGM extends RadioMedium { public class UDGM extends RadioMedium {
private static Logger logger = Logger.getLogger(UDGM.class); private static Logger logger = Logger.getLogger(UDGM.class);
private Vector<Position> registeredPositions = new Vector<Position>();
private Vector<Radio> registeredRadios = new Vector<Radio>(); private Vector<Radio> registeredRadios = new Vector<Radio>();
private Vector<Radio> transmissionEndedRadios = new Vector<Radio>(); // private Vector<Radio> transmissionEndedRadios = new Vector<Radio>();
private Vector<RadioConnection> finishedConnections = new Vector<RadioConnection>();
private static RadioMedium myRadioMedium; private static RadioMedium myRadioMedium;
public static final double SS_NOTHING = -200; public static final double SS_NOTHING = -200;
public static final double SS_BAD = -60; public static final double SS_NOISE = -60;
public static final double SS_OK = 0; public static final double SS_OK = 0;
@ -89,7 +95,7 @@ public class UDGM extends RadioMedium {
* *
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
@ClassDescription("Radio Medium Visualizer") @ClassDescription("UDGM Visualizer")
@PluginType(PluginType.SIM_PLUGIN) @PluginType(PluginType.SIM_PLUGIN)
public static class VisUDGM extends Visualizer2D { public static class VisUDGM extends Visualizer2D {
private Mote selectedMote = null; private Mote selectedMote = null;
@ -118,7 +124,7 @@ public class UDGM extends RadioMedium {
public VisUDGM(Simulation sim, GUI gui) { public VisUDGM(Simulation sim, GUI gui) {
super(sim, gui); super(sim, gui);
setTitle("Radio Medium Visualizer"); setTitle("UDGM Visualizer");
// Create spinners for changing ranges // Create spinners for changing ranges
SpinnerNumberModel transmissionModel = new SpinnerNumberModel(); SpinnerNumberModel transmissionModel = new SpinnerNumberModel();
@ -253,54 +259,57 @@ public class UDGM extends RadioMedium {
int y = pixelCoord.y; int y = pixelCoord.y;
// Fetch current output power indicator (scale with as percent) // Fetch current output power indicator (scale with as percent)
// TODO Probably not the best way to use indicator if (selectedMote.getInterfaces().getRadio() != null) {
double moteInterferenceRange = INTERFERENCE_RANGE double moteInterferenceRange = INTERFERENCE_RANGE
* (0.01 * (double) selectedMote.getInterfaces().getRadio() * (0.01 * (double) selectedMote.getInterfaces().getRadio()
.getCurrentOutputPowerIndicator()); .getCurrentOutputPowerIndicator());
double moteTransmissionRange = TRANSMITTING_RANGE double moteTransmissionRange = TRANSMITTING_RANGE
* (0.01 * (double) selectedMote.getInterfaces().getRadio() * (0.01 * (double) selectedMote.getInterfaces().getRadio()
.getCurrentOutputPowerIndicator()); .getCurrentOutputPowerIndicator());
Point translatedZero = transformPositionToPixel(0.0, 0.0, 0.0); Point translatedZero = transformPositionToPixel(0.0, 0.0, 0.0);
Point translatedInterference = transformPositionToPixel( Point translatedInterference = transformPositionToPixel(
moteInterferenceRange, moteInterferenceRange, 0.0); moteInterferenceRange, moteInterferenceRange, 0.0);
Point translatedTransmission = transformPositionToPixel( Point translatedTransmission = transformPositionToPixel(
moteTransmissionRange, moteTransmissionRange, 0.0); moteTransmissionRange, moteTransmissionRange, 0.0);
translatedInterference.x = Math.abs(translatedInterference.x translatedInterference.x = Math.abs(translatedInterference.x
- translatedZero.x); - translatedZero.x);
translatedInterference.y = Math.abs(translatedInterference.y translatedInterference.y = Math.abs(translatedInterference.y
- translatedZero.y); - translatedZero.y);
translatedTransmission.x = Math.abs(translatedTransmission.x translatedTransmission.x = Math.abs(translatedTransmission.x
- translatedZero.x); - translatedZero.x);
translatedTransmission.y = Math.abs(translatedTransmission.y translatedTransmission.y = Math.abs(translatedTransmission.y
- translatedZero.y); - translatedZero.y);
// Interference // Interference
g.setColor(Color.DARK_GRAY); g.setColor(Color.DARK_GRAY);
g.fillOval(x - translatedInterference.x, y - translatedInterference.y, g.fillOval(x - translatedInterference.x,
2 * translatedInterference.x, 2 * translatedInterference.y); y - translatedInterference.y, 2 * translatedInterference.x,
2 * translatedInterference.y);
// Transmission
g.setColor(Color.GREEN);
g.fillOval(x - translatedTransmission.x, y - translatedTransmission.y,
2 * translatedTransmission.x, 2 * translatedTransmission.y);
// Transmission
g.setColor(Color.GREEN);
g.fillOval(x - translatedTransmission.x,
y - translatedTransmission.y, 2 * translatedTransmission.x,
2 * translatedTransmission.y);
}
} }
// Let parent paint motes // Let parent paint motes
super.visualizeSimulation(g); super.visualizeSimulation(g);
// Paint last tick connections // Paint just finished connections
if (myRadioMedium != null if (myRadioMedium != null
&& myRadioMedium.getLastTickConnections() != null) { && myRadioMedium.getLastTickConnections() != null) {
for (RadioConnection conn : myRadioMedium.getLastTickConnections()) { for (RadioConnection conn : myRadioMedium.getLastTickConnections()) {
if (conn != null) { if (conn != null) {
Point sourcePoint = transformPositionToPixel(conn Point sourcePoint = transformPositionToPixel(conn.getSource()
.getSourcePosition()); .getPosition());
// Paint destinations // Paint destinations
for (Position destPos : conn.getDestinationPositons()) { for (Radio destRadio : conn.getDestinations()) {
Position destPos = destRadio.getPosition();
Point destPoint = transformPositionToPixel(destPos); Point destPoint = transformPositionToPixel(destPos);
g.setColor(Color.BLACK); g.setColor(Color.BLACK);
@ -338,205 +347,417 @@ public class UDGM extends RadioMedium {
private RadioConnection[] lastTickConnections = null; private RadioConnection[] lastTickConnections = null;
private Vector<RadioConnection> pendingConnections = new Vector<RadioConnection>(); private Vector<RadioConnection> activeConnections = new Vector<RadioConnection>();
private ConnectionLogger myLogger = null; private ConnectionLogger myLogger = null;
private Observer radioDataObserver = new Observer() { /**
public void update(Observable radio, Object obj) { * Creates and registers a new connection from given radio.
// This radio changed, let tick loop notify observers *
radioMediumObservable.setRadioMediumChanged(); * @param radio
* Transmitting radio
* @return New registered connection
*/
private RadioConnection createConnections(Radio radio) {
Radio sendingRadio = radio;
Position sendingPosition = sendingRadio.getPosition();
// Register any new transmission RadioConnection newConnection = new RadioConnection(sendingRadio);
if (((Radio) radio).getLastEvent() == Radio.RadioEvent.TRANSMISSION_STARTED) {
Radio sendingRadio = (Radio) radio;
// If obj is the position, use it directly (speeds up things) // Fetch current output power indicator (scale with as percent)
// Otherwise we must search for the position ourselves double moteTransmissionRange = TRANSMITTING_RANGE
Position sendingPosition = (Position) obj; * (0.01 * (double) sendingRadio.getCurrentOutputPowerIndicator());
if (sendingPosition == null) { double moteInterferenceRange = INTERFERENCE_RANGE
if (!registeredRadios.contains(radio)) { * (0.01 * (double) sendingRadio.getCurrentOutputPowerIndicator());
logger.fatal("Sending radio not registered, skipping packet");
return;
}
sendingPosition = registeredPositions.get(registeredRadios // Loop through all radios
.indexOf(radio)); for (int listenNr = 0; listenNr < registeredRadios.size(); listenNr++) {
if (sendingPosition == null) { Radio listeningRadio = registeredRadios.get(listenNr);
logger.fatal("Sending radio not registered, skipping packet"); Position listeningRadioPosition = listeningRadio.getPosition();
return;
}
}
byte[] dataToSend = sendingRadio.getLastPacketTransmitted(); // Ignore sending radio and radios on different channels
if (sendingRadio == listeningRadio)
RadioConnection newConnection = new RadioConnection(); continue;
pendingConnections.add(newConnection); if (sendingRadio.getChannel() != listeningRadio.getChannel())
newConnection.setSource(sendingRadio, sendingPosition, dataToSend); continue;
// Fetch current output power indicator (scale with as percent) double distance = sendingPosition.getDistanceTo(listeningRadioPosition);
// TODO Probably not the best way to use indicator
double moteInterferenceRange = INTERFERENCE_RANGE
* (0.01 * (double) sendingRadio.getCurrentOutputPowerIndicator());
double moteTransmissionRange = TRANSMITTING_RANGE
* (0.01 * (double) sendingRadio.getCurrentOutputPowerIndicator());
// Loop through all radios that are listening if (distance <= moteTransmissionRange) {
for (int listenNr = 0; listenNr < registeredPositions.size(); listenNr++) { // Check if this radio is able to receive transmission
Radio listeningRadio = registeredRadios.get(listenNr); if (listeningRadio.isInterfered()) {
// Keep interfering radio
newConnection.addInterfered(listeningRadio);
if (sendingRadio == listeningRadio) } else if (listeningRadio.isReceiving()) {
continue; newConnection.addInterfered(listeningRadio);
if (sendingRadio.getChannel() != listeningRadio.getChannel())
continue; // Start interfering radio
listeningRadio.interfereAnyReception();
// If not the sending radio.. // Update connection that is transmitting to this radio
double distance = sendingPosition.getDistanceTo(registeredPositions RadioConnection existingConn = null;
.get(listenNr)); for (RadioConnection conn : activeConnections) {
for (Radio dstRadio : conn.getDestinations()) {
if (distance <= moteTransmissionRange) { if (dstRadio == listeningRadio) {
newConnection.addDestination(registeredRadios.get(listenNr), existingConn = conn;
registeredPositions.get(listenNr), dataToSend); break;
}
// If close enough to transmit ok..
if (listeningRadio.isReceiving() || listeningRadio.isInterfered()) {
// .. but listening radio already received a packet
listeningRadio.interferReception(sendingRadio
.getTransmissionEndTime());
listeningRadio.setCurrentSignalStrength(SS_BAD);
} else {
// .. send packet
listeningRadio.receivePacket(dataToSend, sendingRadio
.getTransmissionEndTime());
listeningRadio.setCurrentSignalStrength(SS_OK);
} }
} else if (distance <= moteInterferenceRange) {
// If close enough to sabotage other transmissions..
listeningRadio.interferReception(sendingRadio
.getTransmissionEndTime());
listeningRadio.setCurrentSignalStrength(SS_BAD);
} }
// else too far away if (existingConn != null) {
// Change radio from receiving to interfered
existingConn.removeDestination(listeningRadio);
existingConn.addInterfered(listeningRadio);
}
} else {
// Radio OK to receive
newConnection.addDestination(listeningRadio);
listeningRadio.signalReceptionStart();
}
} else if (distance <= moteInterferenceRange) {
// Interfere radio
newConnection.addInterfered(listeningRadio);
listeningRadio.interfereAnyReception();
}
}
// Register new connection
activeConnections.add(newConnection);
return newConnection;
}
/**
* Forward given packet from source to all destinations in given connection.
*
* @param connection
* Radio connection
* @param packetData
* Packet data
*/
private void forwardPacket(RadioConnection connection, byte[] packetData) {
Radio sourceRadio = connection.getSource();
if (sourceRadio instanceof ByteRadio) {
// Byte radios only forwards packets to packet radios
for (Radio receivingRadio : connection.getDestinations()) {
if (receivingRadio instanceof ByteRadio) {
// Do nothing (data will be forwarded on byte-per-byte basis)
} else if (receivingRadio instanceof PacketRadio) {
// Forward packet data
((PacketRadio) receivingRadio).setReceivedPacket(packetData);
} else {
logger.warn("Packet was not forwarded correctly");
} }
} }
} else if (sourceRadio instanceof PacketRadio) {
if (((Radio) radio).getLastEvent() == Radio.RadioEvent.TRANSMISSION_FINISHED) { // Packet radios forwards packets to all packet radios
transmissionEndedRadios.add((Radio) radio); for (Radio receivingRadio : connection.getDestinations()) {
if (receivingRadio instanceof PacketRadio) {
// Forward packet data
((PacketRadio) receivingRadio).setReceivedPacket(packetData);
} else {
logger.warn("Packet was not forwarded correctly");
}
}
}
}
private void removeFromActiveConnections(Radio radio) {
// Abort any reception
if (radio.isReceiving()) {
radio.interfereAnyReception();
radio.signalReceptionEnd();
}
// Remove radio from all active connections
RadioConnection connToRemove = null;
for (RadioConnection conn : activeConnections) {
conn.removeDestination(radio);
conn.removeInterfered(radio);
if (conn.getSource() == radio) {
// Radio is currently transmitting
connToRemove = conn;
for (Radio dstRadio : conn.getDestinations()) {
dstRadio.interfereAnyReception();
dstRadio.signalReceptionEnd();
}
for (Radio dstRadio : conn.getInterfered()) {
dstRadio.signalReceptionEnd();
}
}
}
if (connToRemove != null)
activeConnections.remove(connToRemove);
}
/**
* Updates all radio signal strengths according to current transmissions. This
* method also updates earlier interfered radios.
*/
private 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
for (Radio radio : registeredRadios) {
radio.setCurrentSignalStrength(SS_NOTHING);
}
// Set signal strength on all OK transmissions
for (RadioConnection conn : activeConnections) {
conn.getSource().setCurrentSignalStrength(SS_OK);
for (Radio dstRadio : conn.getDestinations()) {
dstRadio.setCurrentSignalStrength(SS_OK);
}
}
// Set signal strength on all interferences
for (RadioConnection conn : activeConnections) {
for (Radio dstRadio : conn.getInterfered()) {
dstRadio.setCurrentSignalStrength(SS_NOISE);
if (!dstRadio.isInterfered()) {
// Set to interfered again
dstRadio.interfereAnyReception();
}
}
}
// // Fetch new signal strengths
// double[] newSignalStrengths = new double[registeredRadios.size()];
// for (int i = 0; i < registeredRadios.size(); i++) {
// newSignalStrengths[i] = registeredRadios.get(i)
// .getCurrentSignalStrength();
// }
//
// // Compare new and old signal strengths
// for (int i = 0; i < registeredRadios.size(); i++) {
// if (oldSignalStrengths[i] != newSignalStrengths[i])
// logger.warn("Signal strengths changed on radio[" + i + "]: "
// + oldSignalStrengths[i] + " -> " + newSignalStrengths[i]);
// }
}
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;
// Handle radio event
final Radio.RadioEvent event = radio.getLastEvent();
// Ignore reception events
if (event == Radio.RadioEvent.RECEPTION_STARTED
|| event == Radio.RadioEvent.RECEPTION_INTERFERED
|| event == Radio.RadioEvent.RECEPTION_FINISHED) {
return;
}
if (event == Radio.RadioEvent.HW_OFF) {
// Destroy any(?) transfers
removeFromActiveConnections(radio);
// Recalculate signal strengths on all radios
updateSignalStrengths();
// Wake up tick observer
radioMediumObservable.setRadioMediumChanged();
} else if (event == Radio.RadioEvent.HW_ON) {
// No action
// TODO Maybe set signal strength levels now?
// Recalculate signal strengths on all radios
updateSignalStrengths();
// Wake up tick observer
radioMediumObservable.setRadioMediumChanged();
} else if (event == Radio.RadioEvent.TRANSMISSION_STARTED) {
/* Create radio connections */
createConnections((Radio) radio);
// Recalculate signal strengths on all radios
updateSignalStrengths();
// Wake up tick observer
radioMediumObservable.setRadioMediumChanged();
} else if (event == Radio.RadioEvent.TRANSMISSION_FINISHED) {
/* Remove active connection */
// Find corresponding connection of radio
RadioConnection connection = null;
for (RadioConnection conn : activeConnections) {
if (conn.getSource() == radio) {
connection = conn;
break;
}
}
if (connection == null) {
logger.fatal("Can't find active connection to remove");
} else {
activeConnections.remove(connection);
finishedConnections.add(connection);
for (Radio dstRadio : connection.getDestinations()) {
dstRadio.signalReceptionEnd();
}
for (Radio dstRadio : connection.getInterfered()) {
dstRadio.signalReceptionEnd();
}
}
// Recalculate signal strengths on all radios
updateSignalStrengths();
// Wake up tick observer
radioMediumObservable.setRadioMediumChanged();
} else if (event == Radio.RadioEvent.BYTE_TRANSMITTED) {
/* Forward byte */
// Find corresponding connection of radio
RadioConnection connection = null;
for (RadioConnection conn : activeConnections) {
if (conn.getSource() == radio) {
connection = conn;
break;
}
}
if (connection == null) {
logger.fatal("Can't find active connection to forward byte in");
} else {
byte b = ((ByteRadio) radio).getLastByteTransmitted();
long timestamp = ((ByteRadio) radio).getLastByteTransmittedTimestamp();
for (Radio dstRadio : connection.getDestinations()) {
if (dstRadio instanceof ByteRadio) {
((ByteRadio) dstRadio).receiveByte(b, timestamp);
}
}
}
} else if (event == Radio.RadioEvent.PACKET_TRANSMITTED) {
/* Forward packet */
// Find corresponding connection of radio
RadioConnection connection = null;
for (RadioConnection conn : activeConnections) {
if (conn.getSource() == radio) {
connection = conn;
break;
}
}
if (connection == null) {
logger.fatal("Can't find active connection to forward byte in");
} else {
byte[] packetData = ((PacketRadio) radio).getLastPacketTransmitted();
forwardPacket(connection, packetData);
}
} else if (event == Radio.RadioEvent.UNKNOWN) {
// Do nothing
} else {
logger.fatal("Unsupported radio event: " + event);
} }
} }
}; };
/**
* This observer is resposible for making last tick connections available to
* external observers, as well as forwarding finished connections to any
* registered connection logger.
*
* @see #getLastTickConnections()
* @see #setConnectionLogger(ConnectionLogger)
*/
private Observer tickObserver = new Observer() { private Observer tickObserver = new Observer() {
public void update(Observable obs, Object obj) { public void update(Observable obs, Object obj) {
if (lastTickConnections != null) // Reset any last tick connections
if (lastTickConnections != null) {
radioMediumObservable.setRadioMediumChanged(); radioMediumObservable.setRadioMediumChanged();
lastTickConnections = null;
}
// Reset last tick connections // Do nothing if radio medium unchanged
lastTickConnections = null; if (!radioMediumObservable.hasChanged())
return;
// Log finished connections if any // Log any new finished connections
Vector<RadioConnection> updatedPendingConnections = new Vector<RadioConnection>(); if (finishedConnections.size() > 0) {
if (transmissionEndedRadios.size() > 0) { lastTickConnections = new RadioConnection[finishedConnections.size()];
final int numberFinished = transmissionEndedRadios.size(); for (int i = 0; i < finishedConnections.size(); i++)
Vector<RadioConnection> newTickConnections = new Vector<RadioConnection>(); lastTickConnections[i] = finishedConnections.get(i);
finishedConnections.clear();
// Loop through all radios that finished transmitting data
for (int recvNr = 0; recvNr < numberFinished; recvNr++) {
Radio transmittingRadio = transmissionEndedRadios.get(recvNr);
for (RadioConnection pendingConnection : pendingConnections) {
// Log finished connection
if (pendingConnection.getSourceRadio() == transmittingRadio) {
for (Radio destRadio : pendingConnection.getDestinationRadios()) {
if (destRadio.getLastEvent() != Radio.RadioEvent.RECEPTION_FINISHED) {
// Radio was interfered
pendingConnection.removeDestination(destRadio);
}
}
newTickConnections.add(pendingConnection);
}
// Remove connection if old (don't keep)
if (pendingConnection.getSourceRadio().isTransmitting()) {
updatedPendingConnections.add(pendingConnection);
}
}
}
lastTickConnections = new RadioConnection[newTickConnections.size()];
for (int i = 0; i < lastTickConnections.length; i++)
lastTickConnections[i] = newTickConnections.get(i);
transmissionEndedRadios.clear();
pendingConnections = updatedPendingConnections;
// Notify radio medium logger of the finished transmissions
if (myLogger != null) { if (myLogger != null) {
for (RadioConnection conn : lastTickConnections) for (RadioConnection conn : lastTickConnections)
myLogger.logConnection(conn); myLogger.logConnection(conn);
} }
// Radio medium has changed, notifing below
radioMediumObservable.setRadioMediumChanged();
} }
// Set signal strengths on all radios // Notify all other radio medium observers
for (Radio radio : registeredRadios) {
if (radio.isTransmitting())
radio.setCurrentSignalStrength(SS_OK);
else if (radio.isReceiving())
radio.setCurrentSignalStrength(SS_OK);
else if (radio.isInterfered())
radio.setCurrentSignalStrength(SS_BAD);
else
radio.setCurrentSignalStrength(SS_NOTHING);
}
// Notify observers (if anything has changed)
radioMediumObservable.notifyObservers(); radioMediumObservable.notifyObservers();
} }
}; };
public void registerMote(Mote mote, Simulation sim) { public void registerMote(Mote mote, Simulation sim) {
registerRadioInterface(mote.getInterfaces().getRadio(), mote registerRadioInterface(mote.getInterfaces().getRadio(), sim);
.getInterfaces().getPosition(), sim);
} }
public void unregisterMote(Mote mote, Simulation sim) { public void unregisterMote(Mote mote, Simulation sim) {
unregisterRadioInterface(mote.getInterfaces().getRadio(), sim); unregisterRadioInterface(mote.getInterfaces().getRadio(), sim);
} }
public void registerRadioInterface(Radio radio, Position position, public void registerRadioInterface(Radio radio, Simulation sim) {
Simulation sim) { if (radio != null) {
if (radio != null && position != null) {
if (!isTickObserver) { if (!isTickObserver) {
sim.addTickObserver(tickObserver); sim.addTickObserver(tickObserver);
isTickObserver = true; isTickObserver = true;
} }
registeredPositions.add(position); // Warn if radio medium does not support radio
if (!(radio instanceof PacketRadio)) {
logger
.warn("Radio medium does not support radio (no transmission supported)");
}
// Register and start observing radio
registeredRadios.add(radio); registeredRadios.add(radio);
radio.addObserver(radioDataObserver); radio.addObserver(radioEventsObserver);
// Set initial signal strenth // Set initial signal strenth
radio.setCurrentSignalStrength(SS_NOTHING); radio.setCurrentSignalStrength(SS_NOTHING);
}
} // else logger.warn("Radio Medium not registering mote");
} }
public void unregisterRadioInterface(Radio radio, Simulation sim) { public void unregisterRadioInterface(Radio radio, Simulation sim) {
for (int i = 0; i < registeredRadios.size(); i++) { if (!registeredRadios.contains(radio)) {
if (registeredRadios.get(i).equals(radio)) { logger.warn("Could not find radio: " + radio + " to unregister");
registeredRadios.remove(i); return;
registeredPositions.remove(i);
radio.deleteObserver(radioDataObserver);
return;
}
} }
logger.warn("Could not find radio: " + radio + " to unregister");
radio.deleteObserver(radioEventsObserver);
registeredRadios.remove(radio);
removeFromActiveConnections(radio);
} }
public void addRadioMediumObserver(Observer observer) { public void addRadioMediumObserver(Observer observer) {
@ -576,7 +797,8 @@ public class UDGM extends RadioMedium {
return config; return config;
} }
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) { public boolean setConfigXML(Collection<Element> configXML,
boolean visAvailable) {
for (Element element : configXML) { for (Element element : configXML) {
if (element.getName().equals("transmitting_range")) { if (element.getName().equals("transmitting_range")) {
TRANSMITTING_RANGE = Double.parseDouble(element.getText()); TRANSMITTING_RANGE = Double.parseDouble(element.getText());