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
* 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;
@ -57,7 +57,7 @@ public class DummyRadioMedium extends RadioMedium {
// Do nothing
}
public void registerRadioInterface(Radio radio, Position position, Simulation sim) {
public void registerRadioInterface(Radio radio, Simulation sim) {
// Do nothing
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
* 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 org.apache.log4j.Logger;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.*;
import se.sics.cooja.plugins.*;
/**
@ -62,28 +62,32 @@ public class VisUAODV extends VisTraffic {
}
protected void paintConnection(RadioConnection connection, Graphics g2d) {
Point sourcePixelPosition = transformPositionToPixel(connection.getSourcePosition());
for (Position destPosition: connection.getDestinationPositons()) {
Point sourcePixelPosition = transformPositionToPixel(connection.getSource().getPosition());
for (Radio destRadio: connection.getDestinations()) {
Position destPosition = destRadio.getPosition();
Point destPixelPosition = transformPositionToPixel(destPosition);
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));
}
g2d.drawLine(sourcePixelPosition.x, sourcePixelPosition.y,
destPixelPosition.x, destPixelPosition.y);
int hopCount = getHopCount(connection.getSourceData());
int hopCount = getHopCount(packet);
if (hopCount >= 0)
g2d.drawString("" + hopCount, sourcePixelPosition.x, sourcePixelPosition.y);
}
}
protected Color getColorOf(RadioConnection conn) {
if (isRouteRequest(conn.getSourceData()))
byte[] packet = ((PacketRadio)conn.getSource()).getLastPacketReceived();
if (isRouteRequest(packet))
return Color.RED;
else if (isRouteReply(conn.getSourceData()))
else if (isRouteReply(packet))
return Color.GREEN;
else
return Color.BLACK;

View File

@ -24,7 +24,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: 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;
@ -33,12 +33,14 @@ import java.io.File;
import java.io.FileOutputStream;
import org.apache.log4j.Logger;
import se.sics.cooja.interfaces.PacketRadio;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio;
/**
* ConnectionLogger is a simple connection information outputter. All
* connections given via the method logConnection will be written to either
* default Log4J info stream, a log file or both.
* A connection logger is a simple connection information outputter. All
* connections given to it will be written to either the currently configured
* Log4J info stream, a log file or both.
*
* 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]
@ -90,29 +92,29 @@ public class ConnectionLogger {
* Connection to output
*/
public void logConnection(RadioConnection conn) {
if (myType == LOG_TO_LOG4J || myType == LOG_TO_FILE_AND_LOG4J) {
if (conn.getDestinationPositons() != null
&& conn.getDestinationPositons().length > 0)
for (Position destPos : conn.getDestinationPositons()) {
logger.info("RADIODATA from " + conn.getSourcePosition() + " to "
+ destPos + "\tsize:" + conn.getSourceData().length);
Radio[] destinations = conn.getDestinations();
if (destinations != null && destinations.length > 0) {
for (Radio destRadio : destinations) {
logger.info("RADIODATA from " + conn.getSource().getPosition()
+ " to " + destRadio.getPosition());
}
else
logger.info("RADIODATA from " + conn.getSourcePosition() + " to "
+ "[NOWHERE]" + "\tsize:" + conn.getSourceData().length);
} else {
logger.info("RADIODATA from " + conn.getSource().getPosition()
+ " 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 {
FileOutputStream out = new FileOutputStream(myFile, true);
if (conn.getDestinationPositons() != null
&& conn.getDestinationPositons().length > 0) {
for (int i = 0; i < conn.getDestinationPositons().length; i++) {
Radio[] destinations = conn.getDestinations();
if (destinations != null && destinations.length > 0) {
for (int i = 0; i < destinations.length; i++) {
// Source pos
out.write("SRC_POS\t".getBytes());
Position pos = conn.getSourcePosition();
Position pos = conn.getSource().getPosition();
out.write(Double.toString(pos.getXCoordinate()).getBytes());
out.write("\t".getBytes());
out.write(Double.toString(pos.getYCoordinate()).getBytes());
@ -122,7 +124,9 @@ public class ConnectionLogger {
// Source data
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);
if (hexString.length() == 1)
hexString = "0" + hexString;
@ -132,7 +136,7 @@ public class ConnectionLogger {
// Destination pos
out.write("DEST_POS\t".getBytes());
pos = conn.getDestinationPositons()[i];
pos = destinations[i].getPosition();
out.write(Double.toString(pos.getXCoordinate()).getBytes());
out.write("\t".getBytes());
out.write(Double.toString(pos.getYCoordinate()).getBytes());
@ -142,7 +146,9 @@ public class ConnectionLogger {
// Source data
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);
if (hexString.length() == 1)
hexString = "0" + hexString;
@ -156,7 +162,7 @@ public class ConnectionLogger {
} else {
// Source pos
out.write("SRC_POS\t".getBytes());
Position pos = conn.getSourcePosition();
Position pos = conn.getSource().getPosition();
out.write(Double.toString(pos.getXCoordinate()).getBytes());
out.write("\t".getBytes());
out.write(Double.toString(pos.getYCoordinate()).getBytes());
@ -166,12 +172,16 @@ public class ConnectionLogger {
// Source data
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);
if (hexString.length() == 1)
hexString = "0" + hexString;
out.write(hexString.getBytes());
}
out.write("\t".getBytes());
out.write("[NOWHERE]".getBytes());
out.write("\n".getBytes());
}
out.close();

View File

@ -26,139 +26,121 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* 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;
import java.util.Vector;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio;
/**
* RadioConnection represents a radio connection between a sending radio
* and zero or more receiving radios.
* By registering as an observer to the current radio medium, all
* 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.
* A radio connection represents a connection between a source radio and zero or
* more destination and interfered radios. Typically the destinations are able
* to receive data sent by the source radio, and the interfered radios are not.
*
* @see RadioMedium
* @author Fredrik Osterlind
*/
public class RadioConnection {
private Radio sourceRadio;
private Position sourcePosition;
private byte[] sourceData;
private Radio source;
private Vector<Radio> destinationRadios = new Vector<Radio>();
private Vector<Position> destinationPositions = new Vector<Position>();
private Vector<byte[]> destinationData = new Vector<byte[]>();
private Vector<Radio> destinations = new Vector<Radio>();
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.
*
* @param radio Source radio
* @param position Source position
* @param data Source data
* @param radio
* Source radio
*/
public void setSource(Radio radio, Position position, byte[] data) {
sourceRadio = radio;
sourcePosition = position;
sourceData = data;
public void setSource(Radio radio) {
source = radio;
}
/**
* Add a connection destination.
* Adds destination radio.
*
* @param radio Source radio
* @param position Source position
* @param data Source data
* @param radio
* Radio
*/
public void addDestination(Radio radio, Position position, byte[] data) {
destinationRadios.add(radio);
destinationPositions.add(position);
destinationData.add(data);
public void addDestination(Radio radio) {
destinations.add(radio);
}
/**
* 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) {
int pos = destinationRadios.indexOf(radio);
if (pos >= 0) {
destinationRadios.remove(pos);
destinationPositions.remove(pos);
destinationData.remove(pos);
}
destinations.remove(radio);
}
/**
* Removes interfered radio.
*
* @param radio
* Radio
*/
public void removeInterfered(Radio radio) {
interfered.remove(radio);
}
/**
* @return Source radio
*/
public Radio getSourceRadio() {
return sourceRadio;
public Radio getSource() {
return source;
}
/**
* @return Source position
* @return All destinations of this connection
*/
public Position getSourcePosition() {
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() {
public Radio[] getDestinations() {
Radio[] radioArrayType;
Radio[] radioArray;
radioArrayType = new Radio[destinationRadios.size()];
radioArray = (Radio[]) destinationRadios.toArray(radioArrayType);
radioArrayType = new Radio[destinations.size()];
radioArray = (Radio[]) destinations.toArray(radioArrayType);
return radioArray;
}
/**
* @return Array of destination positions
* @return All radios interfered by this connection
*/
public Position[] getDestinationPositons() {
Position[] positionArrayType;
Position[] positionArray;
public Radio[] getInterfered() {
Radio[] radioArrayType;
Radio[] radioArray;
positionArrayType = new Position[destinationPositions.size()];
positionArray = (Position[]) destinationPositions.toArray(positionArrayType);
radioArrayType = new Radio[interfered.size()];
radioArray = (Radio[]) interfered.toArray(radioArrayType);
return positionArray;
}
/**
* 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;
return radioArray;
}
}

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* 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;
@ -36,7 +36,6 @@ import java.lang.reflect.InvocationTargetException;
import java.util.*;
import org.jdom.Element;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio;
/**
@ -79,7 +78,7 @@ public abstract class RadioMedium {
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
* 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
* Radio
* @param position
* Position
* @param sim
* Simulation holding radio
*/
public abstract void registerRadioInterface(Radio radio, Position position,
Simulation sim);
public abstract void registerRadioInterface(Radio radio, Simulation sim);
/**
* Unregisters a radio interface from this medium.
* Unregister given radio interface from this medium.
*
* @param radio
* Radio interface to unregister

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* 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;
@ -39,6 +39,8 @@ import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.PacketRadio;
import se.sics.cooja.interfaces.Position;
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 or reception states (using multi-threading). When a transmission
* 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
* lock the radio in receiving mode. After some time it should then deliver the
* packet.
* received by this radio the Contiki system, the entitiy transferring the
* packet may explicitly lock the radio in receiving mode. After some time it
* should then deliver the packet.
*
* It needs read/write access to the following core variables:
* <ul>
@ -64,7 +66,7 @@ import se.sics.cooja.interfaces.Radio;
* <li>char simRadioHWOn (radio hardware status (on/off))
* <li>int simSignalStrength (heard radio signal strength)
* <li>char simPower (number indicating power output)
* <li>int simRadioChannel
* <li>int simRadioChannel (number indicating current channel)
* </ul>
* <p>
* Dependency core interfaces are:
@ -75,9 +77,12 @@ import se.sics.cooja.interfaces.Radio;
*
* @author Fredrik Osterlind
*/
public class ContikiRadio extends Radio implements ContikiMoteInterface {
public class ContikiRadio extends Radio implements ContikiMoteInterface,
PacketRadio {
private Mote myMote;
private SectionMoteMemory myMoteMemory;
private static Logger logger = Logger.getLogger(ContikiRadio.class);
/**
@ -98,13 +103,14 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
private double myEnergyConsumption = 0.0;
private boolean transmitting = false;
private boolean isTransmitting = false;
private boolean isInterfered = false;
private int transmissionEndTime = -1;
private int interferenceEndTime = -1;
private int receptionEndTime = -1;
private RadioEvent lastEvent = RadioEvent.UNKNOWN;
private int lastEventTime = 0;
private int oldOutputPowerIndicator = -1;
@ -135,10 +141,12 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
radioOn = myMoteMemory.getByteValueOf("simRadioHWOn") == 1;
}
/* Contiki mote interface support */
public static String[] getCoreInterfaceDependencies() {
return new String[] { "radio_interface" };
}
/* Packet radio support */
public byte[] getLastPacketTransmitted() {
return packetFromMote;
}
@ -147,12 +155,13 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
return packetToMote;
}
public boolean isTransmitting() {
return transmitting;
public void setReceivedPacket(byte[] data) {
packetToMote = data;
}
public int getTransmissionEndTime() {
return transmissionEndTime;
/* General radio support */
public boolean isTransmitting() {
return isTransmitting;
}
public boolean isReceiving() {
@ -162,14 +171,93 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
return myMoteMemory.getIntValueOf("simInSize") != 0;
}
public boolean isInterfered() {
return isInterfered;
}
public int getChannel() {
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() {
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
*/
@ -201,98 +289,9 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
// Lock core radio in receiving loop
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() {
// Check if we need to release Contiki lock and deliver packet data
if (isLockedAtReceiving() && myMote.getSimulation().getSimulationTime() >= receptionEndTime) {
deliverPacket();
}
}
public void doActionsAfterTick() {
@ -304,10 +303,10 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
if (!radioOn) {
// Reset status
myMoteMemory.setByteValueOf("simReceiving", (byte) 0);
myMoteMemory.setIntValueOf("simInSize", 0);
myMoteMemory.setIntValueOf("simInSize", 0);
myMoteMemory.setByteValueOf("simTransmitting", (byte) 0);
myMoteMemory.setIntValueOf("simOutSize", 0);
transmitting = false;
myMoteMemory.setIntValueOf("simOutSize", 0);
isTransmitting = false;
lastEvent = RadioEvent.HW_OFF;
} else
lastEvent = RadioEvent.HW_ON;
@ -325,15 +324,17 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
// Check if radio output power changed
if (myMoteMemory.getByteValueOf("simPower") != oldOutputPowerIndicator) {
oldOutputPowerIndicator = myMoteMemory.getByteValueOf("simPower");
lastEvent = RadioEvent.UNKNOWN;
this.setChanged();
this.notifyObservers();
}
// Are we transmitting but should stop?
if (transmitting && myMote.getSimulation().getSimulationTime() >= transmissionEndTime) {
if (isTransmitting
&& myMote.getSimulation().getSimulationTime() >= transmissionEndTime) {
myMoteMemory.setByteValueOf("simTransmitting", (byte) 0);
myMoteMemory.setIntValueOf("simOutSize", 0);
transmitting = false;
isTransmitting = false;
lastEventTime = myMote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.TRANSMISSION_FINISHED;
@ -343,8 +344,8 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
}
// Check if a new transmission should be started
if (!transmitting && myMoteMemory.getByteValueOf("simTransmitting") == 1) {
transmitting = true;
if (!isTransmitting && myMoteMemory.getByteValueOf("simTransmitting") == 1) {
isTransmitting = true;
int size = myMoteMemory.getIntValueOf("simOutSize");
packetFromMote = myMoteMemory.getByteArray("simOutDataBuffer", size);
@ -355,9 +356,15 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
+ Math.max(1, duration);
lastEventTime = myMote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.TRANSMISSION_STARTED;
this.setChanged();
this.notifyObservers();
// Deliver packet right away
lastEvent = RadioEvent.PACKET_TRANSMITTED;
this.setChanged();
this.notifyObservers();
}
}
@ -378,7 +385,8 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
updateButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ssLabel.setText("Signal strength (not auto-updated): " + getCurrentSignalStrength() + " dBm");
ssLabel.setText("Signal strength (not auto-updated): "
+ getCurrentSignalStrength() + " dBm");
}
});
@ -394,8 +402,10 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
else
statusLabel.setText("HW turned off");
lastEventLabel.setText("Last event (time=" + lastEventTime + "): " + lastEvent);
ssLabel.setText("Signal strength (not auto-updated): " + getCurrentSignalStrength() + " dBm");
lastEventLabel.setText("Last event (time=" + lastEventTime + "): "
+ lastEvent);
ssLabel.setText("Signal strength (not auto-updated): "
+ getCurrentSignalStrength() + " dBm");
}
});

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
* 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;
@ -32,8 +32,15 @@ package se.sics.cooja.interfaces;
import se.sics.cooja.*;
/**
* A Radio represents a mote radio transceiver. An implementation should notify
* all observers both when packets are received and transmitted.
* A Radio represents a mote radio transceiver.
*
* 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
*/
@ -44,84 +51,65 @@ public abstract class Radio extends MoteInterface {
* Events that radios should notify observers about.
*/
public enum RadioEvent {
UNKNOWN,
HW_OFF, HW_ON,
RECEPTION_STARTED, RECEPTION_INTERFERED, RECEPTION_FINISHED,
TRANSMISSION_STARTED, TRANSMISSION_FINISHED
UNKNOWN, HW_OFF, HW_ON, RECEPTION_STARTED, RECEPTION_FINISHED, RECEPTION_INTERFERED, TRANSMISSION_STARTED, TRANSMISSION_FINISHED, PACKET_TRANSMITTED, BYTE_TRANSMITTED
}
/**
* Returns last significant event at this radio. Method may for example be
* used to learn the reason when a radio notifies a change to observers.
* Signal that a new reception just begun. This method should normally be
* 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
*/
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,
* data.
*
* @see #getLastPacketTransmitted()
* @see #isReceiving()
* @return True if radio is transmitting data
*/
public abstract boolean isTransmitting();
/**
* @return Transmission end time if any transmission active
*/
public abstract int getTransmissionEndTime();
/**
* Returns true if this radio is receiving data.
*
* @see #getLastPacketReceived()
* @see #isTransmitting()
* @return True if radio is receiving data
*/
public abstract boolean isReceiving();
/**
* If a packet is being received, it will be interfered and dropped. The
* interference will continue until the given time, during which no other
* 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.
* Returns true if this radio had a connection that was dropped due to
* interference.
*
* @return True if this radio is interfered
*/
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)
*/
@ -138,7 +126,8 @@ public abstract class Radio extends MoteInterface {
public abstract double getCurrentSignalStrength();
/**
* Sets surrounding signal strength.
* Sets surrounding signal strength. This method should normally be called by
* the radio medium.
*
* @param signalStrength
* Current surrounding signal strength
@ -152,4 +141,12 @@ public abstract class Radio extends MoteInterface {
*/
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
* 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;
@ -40,14 +40,14 @@ import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.Radio;
import se.sics.cooja.interfaces.*;
/**
* This radio periodically transmits data on a configurable channel.
*
* @author Fredrik Osterlind, Thiemo Voigt
*/
public class DisturberRadio extends Radio {
public class DisturberRadio extends Radio implements PacketRadio {
private Mote myMote;
private static Logger logger = Logger.getLogger(DisturberRadio.class);
@ -79,6 +79,7 @@ public class DisturberRadio extends Radio {
this.myMote = mote;
}
/* Packet radio support */
public byte[] getLastPacketTransmitted() {
return packetFromMote;
}
@ -87,6 +88,17 @@ public class DisturberRadio extends Radio {
return null;
}
public void setReceivedPacket(byte[] data) {
}
/* General radio support */
public void signalReceptionStart() {
}
public void signalReceptionEnd() {
}
public boolean isTransmitting() {
return transmitting;
}
@ -96,8 +108,6 @@ public class DisturberRadio extends Radio {
}
public boolean isReceiving() {
if (isLockedAtReceiving())
return true;
return false;
}
@ -105,21 +115,15 @@ public class DisturberRadio extends Radio {
return distChannel;
}
public Position getPosition() {
return myMote.getInterfaces().getPosition();
}
public RadioEvent getLastEvent() {
return lastEvent;
}
/**
* @return True if locked at receiving
*/
private boolean isLockedAtReceiving() {
return false;
}
public void receivePacket(byte[] data, int endTime) {
}
public void interferReception(int endTime) {
public void interfereAnyReception() {
}
public boolean isInterfered() {

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* 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;
@ -38,6 +38,7 @@ import org.apache.log4j.Logger;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio;
/**
* A Traffic Visualizer visualizes radio traffic by painting lines between
@ -124,11 +125,10 @@ public class VisTraffic extends Visualizer2D {
* Graphics to paint on
*/
protected void paintConnection(PaintedConnection connection, Graphics g2d) {
Point sourcePixelPosition = transformPositionToPixel(connection.radioConnection
.getSourcePosition());
Point sourcePixelPosition = transformPositionToPixel(connection.radioConnection.getSource().getPosition());
g2d.setColor(connection.getColor(simulation.isRunning()));
for (Position destPosition : connection.radioConnection
.getDestinationPositons()) {
for (Radio destRadio : connection.radioConnection.getDestinations()) {
Position destPosition = destRadio.getPosition();
Point destPixelPosition = transformPositionToPixel(destPosition);
g2d.drawLine(sourcePixelPosition.x, sourcePixelPosition.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
* 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;
@ -57,7 +57,7 @@ public class SilentRadioMedium extends RadioMedium {
// Do nothing
}
public void registerRadioInterface(Radio radio, Position position, Simulation sim) {
public void registerRadioInterface(Radio radio, Simulation sim) {
// Do nothing
}

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* 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;
@ -47,35 +47,41 @@ import se.sics.cooja.plugins.Visualizer2D;
* The Unit Disk Graph medium has two different range parameters; one for
* transmitting and one for interfering other transmissions.
*
* Radio data are analysed when all registered motes have ticked once (this
* medium is registered as a tick observer). For every mote in transmission
* range of a sending mote, current listen status is changed from hearing
* 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.
* The radio medium supports both byte and packet radios. Any transmitted bytes
* are forwarded TODO immediately with a timestamp (more fine-grained than
* ticks).
*
* This radio medium registers a temporary visual plugin class.
* Via this plugin ranges can be viewed and changed. Active connection may also
* be viewed.
* The radio medium registers a visualizer plugin. Via this plugin the current
* radio states and range parameters can be viewed and changed.
*
* 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
*/
@ClassDescription("Unit Disk Graph Medium (UDGM)")
public class UDGM extends RadioMedium {
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> transmissionEndedRadios = new Vector<Radio>();
// private Vector<Radio> transmissionEndedRadios = new Vector<Radio>();
private Vector<RadioConnection> finishedConnections = new Vector<RadioConnection>();
private static RadioMedium myRadioMedium;
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;
@ -89,7 +95,7 @@ public class UDGM extends RadioMedium {
*
* @author Fredrik Osterlind
*/
@ClassDescription("Radio Medium Visualizer")
@ClassDescription("UDGM Visualizer")
@PluginType(PluginType.SIM_PLUGIN)
public static class VisUDGM extends Visualizer2D {
private Mote selectedMote = null;
@ -118,7 +124,7 @@ public class UDGM extends RadioMedium {
public VisUDGM(Simulation sim, GUI gui) {
super(sim, gui);
setTitle("Radio Medium Visualizer");
setTitle("UDGM Visualizer");
// Create spinners for changing ranges
SpinnerNumberModel transmissionModel = new SpinnerNumberModel();
@ -253,54 +259,57 @@ public class UDGM extends RadioMedium {
int y = pixelCoord.y;
// Fetch current output power indicator (scale with as percent)
// TODO Probably not the best way to use indicator
double moteInterferenceRange = INTERFERENCE_RANGE
* (0.01 * (double) selectedMote.getInterfaces().getRadio()
.getCurrentOutputPowerIndicator());
double moteTransmissionRange = TRANSMITTING_RANGE
* (0.01 * (double) selectedMote.getInterfaces().getRadio()
.getCurrentOutputPowerIndicator());
if (selectedMote.getInterfaces().getRadio() != null) {
double moteInterferenceRange = INTERFERENCE_RANGE
* (0.01 * (double) selectedMote.getInterfaces().getRadio()
.getCurrentOutputPowerIndicator());
double moteTransmissionRange = TRANSMITTING_RANGE
* (0.01 * (double) selectedMote.getInterfaces().getRadio()
.getCurrentOutputPowerIndicator());
Point translatedZero = transformPositionToPixel(0.0, 0.0, 0.0);
Point translatedInterference = transformPositionToPixel(
moteInterferenceRange, moteInterferenceRange, 0.0);
Point translatedTransmission = transformPositionToPixel(
moteTransmissionRange, moteTransmissionRange, 0.0);
Point translatedZero = transformPositionToPixel(0.0, 0.0, 0.0);
Point translatedInterference = transformPositionToPixel(
moteInterferenceRange, moteInterferenceRange, 0.0);
Point translatedTransmission = transformPositionToPixel(
moteTransmissionRange, moteTransmissionRange, 0.0);
translatedInterference.x = Math.abs(translatedInterference.x
- translatedZero.x);
translatedInterference.y = Math.abs(translatedInterference.y
- translatedZero.y);
translatedTransmission.x = Math.abs(translatedTransmission.x
- translatedZero.x);
translatedTransmission.y = Math.abs(translatedTransmission.y
- translatedZero.y);
translatedInterference.x = Math.abs(translatedInterference.x
- translatedZero.x);
translatedInterference.y = Math.abs(translatedInterference.y
- translatedZero.y);
translatedTransmission.x = Math.abs(translatedTransmission.x
- translatedZero.x);
translatedTransmission.y = Math.abs(translatedTransmission.y
- translatedZero.y);
// Interference
g.setColor(Color.DARK_GRAY);
g.fillOval(x - translatedInterference.x, 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);
// Interference
g.setColor(Color.DARK_GRAY);
g.fillOval(x - translatedInterference.x,
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);
}
}
// Let parent paint motes
super.visualizeSimulation(g);
// Paint last tick connections
// Paint just finished connections
if (myRadioMedium != null
&& myRadioMedium.getLastTickConnections() != null) {
for (RadioConnection conn : myRadioMedium.getLastTickConnections()) {
if (conn != null) {
Point sourcePoint = transformPositionToPixel(conn
.getSourcePosition());
Point sourcePoint = transformPositionToPixel(conn.getSource()
.getPosition());
// Paint destinations
for (Position destPos : conn.getDestinationPositons()) {
for (Radio destRadio : conn.getDestinations()) {
Position destPos = destRadio.getPosition();
Point destPoint = transformPositionToPixel(destPos);
g.setColor(Color.BLACK);
@ -338,205 +347,417 @@ public class UDGM extends RadioMedium {
private RadioConnection[] lastTickConnections = null;
private Vector<RadioConnection> pendingConnections = new Vector<RadioConnection>();
private Vector<RadioConnection> activeConnections = new Vector<RadioConnection>();
private ConnectionLogger myLogger = null;
private Observer radioDataObserver = new Observer() {
public void update(Observable radio, Object obj) {
// This radio changed, let tick loop notify observers
radioMediumObservable.setRadioMediumChanged();
/**
* Creates and registers a new connection from given radio.
*
* @param radio
* Transmitting radio
* @return New registered connection
*/
private RadioConnection createConnections(Radio radio) {
Radio sendingRadio = radio;
Position sendingPosition = sendingRadio.getPosition();
// Register any new transmission
if (((Radio) radio).getLastEvent() == Radio.RadioEvent.TRANSMISSION_STARTED) {
Radio sendingRadio = (Radio) radio;
RadioConnection newConnection = new RadioConnection(sendingRadio);
// If obj is the position, use it directly (speeds up things)
// Otherwise we must search for the position ourselves
Position sendingPosition = (Position) obj;
if (sendingPosition == null) {
if (!registeredRadios.contains(radio)) {
logger.fatal("Sending radio not registered, skipping packet");
return;
}
// Fetch current output power indicator (scale with as percent)
double moteTransmissionRange = TRANSMITTING_RANGE
* (0.01 * (double) sendingRadio.getCurrentOutputPowerIndicator());
double moteInterferenceRange = INTERFERENCE_RANGE
* (0.01 * (double) sendingRadio.getCurrentOutputPowerIndicator());
sendingPosition = registeredPositions.get(registeredRadios
.indexOf(radio));
if (sendingPosition == null) {
logger.fatal("Sending radio not registered, skipping packet");
return;
}
}
// Loop through all radios
for (int listenNr = 0; listenNr < registeredRadios.size(); listenNr++) {
Radio listeningRadio = registeredRadios.get(listenNr);
Position listeningRadioPosition = listeningRadio.getPosition();
byte[] dataToSend = sendingRadio.getLastPacketTransmitted();
// Ignore sending radio and radios on different channels
if (sendingRadio == listeningRadio)
continue;
if (sendingRadio.getChannel() != listeningRadio.getChannel())
continue;
RadioConnection newConnection = new RadioConnection();
pendingConnections.add(newConnection);
newConnection.setSource(sendingRadio, sendingPosition, dataToSend);
double distance = sendingPosition.getDistanceTo(listeningRadioPosition);
// Fetch current output power indicator (scale with as percent)
// 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());
if (distance <= moteTransmissionRange) {
// Check if this radio is able to receive transmission
if (listeningRadio.isInterfered()) {
// Keep interfering radio
newConnection.addInterfered(listeningRadio);
// Loop through all radios that are listening
for (int listenNr = 0; listenNr < registeredPositions.size(); listenNr++) {
Radio listeningRadio = registeredRadios.get(listenNr);
} else if (listeningRadio.isReceiving()) {
newConnection.addInterfered(listeningRadio);
if (sendingRadio == listeningRadio)
continue;
if (sendingRadio.getChannel() != listeningRadio.getChannel())
continue;
// Start interfering radio
listeningRadio.interfereAnyReception();
// If not the sending radio..
double distance = sendingPosition.getDistanceTo(registeredPositions
.get(listenNr));
if (distance <= moteTransmissionRange) {
newConnection.addDestination(registeredRadios.get(listenNr),
registeredPositions.get(listenNr), dataToSend);
// 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);
// Update connection that is transmitting to this radio
RadioConnection existingConn = null;
for (RadioConnection conn : activeConnections) {
for (Radio dstRadio : conn.getDestinations()) {
if (dstRadio == listeningRadio) {
existingConn = conn;
break;
}
}
} 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);
if (((Radio) radio).getLastEvent() == Radio.RadioEvent.TRANSMISSION_FINISHED) {
transmissionEndedRadios.add((Radio) radio);
}
} else {
// Radio OK to receive
newConnection.addDestination(listeningRadio);
listeningRadio.signalReceptionStart();
}
} else if (distance <= moteInterferenceRange) {
// Interfere radio
newConnection.addInterfered(listeningRadio);
listeningRadio.interfereAnyReception();
}
}
};
private Observer tickObserver = new Observer() {
// 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) {
// Packet radios forwards packets to all packet radios
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;
}
if (lastTickConnections != null)
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();
// Reset last tick connections
lastTickConnections = null;
} else if (event == Radio.RadioEvent.HW_ON) {
// No action
// TODO Maybe set signal strength levels now?
// Log finished connections if any
Vector<RadioConnection> updatedPendingConnections = new Vector<RadioConnection>();
if (transmissionEndedRadios.size() > 0) {
final int numberFinished = transmissionEndedRadios.size();
Vector<RadioConnection> newTickConnections = new Vector<RadioConnection>();
// Recalculate signal strengths on all radios
updateSignalStrengths();
// Loop through all radios that finished transmitting data
for (int recvNr = 0; recvNr < numberFinished; recvNr++) {
Radio transmittingRadio = transmissionEndedRadios.get(recvNr);
// Wake up tick observer
radioMediumObservable.setRadioMediumChanged();
for (RadioConnection pendingConnection : pendingConnections) {
} else if (event == Radio.RadioEvent.TRANSMISSION_STARTED) {
/* Create radio connections */
// 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);
}
createConnections((Radio) radio);
// Remove connection if old (don't keep)
if (pendingConnection.getSourceRadio().isTransmitting()) {
updatedPendingConnections.add(pendingConnection);
// 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);
}
}
}
lastTickConnections = new RadioConnection[newTickConnections.size()];
for (int i = 0; i < lastTickConnections.length; i++)
lastTickConnections[i] = newTickConnections.get(i);
transmissionEndedRadios.clear();
} else if (event == Radio.RadioEvent.PACKET_TRANSMITTED) {
/* Forward packet */
pendingConnections = updatedPendingConnections;
// 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() {
public void update(Observable obs, Object obj) {
// Reset any last tick connections
if (lastTickConnections != null) {
radioMediumObservable.setRadioMediumChanged();
lastTickConnections = null;
}
// Do nothing if radio medium unchanged
if (!radioMediumObservable.hasChanged())
return;
// Log any new finished connections
if (finishedConnections.size() > 0) {
lastTickConnections = new RadioConnection[finishedConnections.size()];
for (int i = 0; i < finishedConnections.size(); i++)
lastTickConnections[i] = finishedConnections.get(i);
finishedConnections.clear();
// Notify radio medium logger of the finished transmissions
if (myLogger != null) {
for (RadioConnection conn : lastTickConnections)
myLogger.logConnection(conn);
}
// Radio medium has changed, notifing below
radioMediumObservable.setRadioMediumChanged();
}
// Set signal strengths on all radios
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)
// Notify all other radio medium observers
radioMediumObservable.notifyObservers();
}
};
public void registerMote(Mote mote, Simulation sim) {
registerRadioInterface(mote.getInterfaces().getRadio(), mote
.getInterfaces().getPosition(), sim);
registerRadioInterface(mote.getInterfaces().getRadio(), sim);
}
public void unregisterMote(Mote mote, Simulation sim) {
unregisterRadioInterface(mote.getInterfaces().getRadio(), sim);
}
public void registerRadioInterface(Radio radio, Position position,
Simulation sim) {
if (radio != null && position != null) {
public void registerRadioInterface(Radio radio, Simulation sim) {
if (radio != null) {
if (!isTickObserver) {
sim.addTickObserver(tickObserver);
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);
radio.addObserver(radioDataObserver);
radio.addObserver(radioEventsObserver);
// Set initial signal strenth
radio.setCurrentSignalStrength(SS_NOTHING);
} // else logger.warn("Radio Medium not registering mote");
}
}
public void unregisterRadioInterface(Radio radio, Simulation sim) {
for (int i = 0; i < registeredRadios.size(); i++) {
if (registeredRadios.get(i).equals(radio)) {
registeredRadios.remove(i);
registeredPositions.remove(i);
radio.deleteObserver(radioDataObserver);
return;
}
if (!registeredRadios.contains(radio)) {
logger.warn("Could not find radio: " + radio + " to unregister");
return;
}
logger.warn("Could not find radio: " + radio + " to unregister");
radio.deleteObserver(radioEventsObserver);
registeredRadios.remove(radio);
removeFromActiveConnections(radio);
}
public void addRadioMediumObserver(Observer observer) {
@ -576,7 +797,8 @@ public class UDGM extends RadioMedium {
return config;
}
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
public boolean setConfigXML(Collection<Element> configXML,
boolean visAvailable) {
for (Element element : configXML) {
if (element.getName().equals("transmitting_range")) {
TRANSMITTING_RANGE = Double.parseDouble(element.getText());