Merge pull request #769 from ejoerns/pull-req/cooja-traffic-vis
[Cooja] TrafficVisualizerSkin modifications
This commit is contained in:
commit
6fec61bf7c
|
@ -33,7 +33,9 @@ import java.awt.Color;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.Polygon;
|
import java.awt.Polygon;
|
||||||
import java.util.ArrayList;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
|
|
||||||
|
@ -60,54 +62,51 @@ import org.contikios.cooja.radiomediums.AbstractRadioMedium;
|
||||||
@ClassDescription("Radio traffic")
|
@ClassDescription("Radio traffic")
|
||||||
@SupportedArguments(radioMediums = {AbstractRadioMedium.class})
|
@SupportedArguments(radioMediums = {AbstractRadioMedium.class})
|
||||||
public class TrafficVisualizerSkin implements VisualizerSkin {
|
public class TrafficVisualizerSkin implements VisualizerSkin {
|
||||||
private static Logger logger = Logger.getLogger(TrafficVisualizerSkin.class);
|
private static final Logger logger = Logger.getLogger(TrafficVisualizerSkin.class);
|
||||||
|
|
||||||
private final int MAX_HISTORY_SIZE = 200;
|
private final int MAX_HISTORY_SIZE = 200;
|
||||||
|
private final float TRANSMITTED_COLOR_RGB[] = Color.BLUE.getRGBColorComponents(null);
|
||||||
|
private final float UNTRANSMITTED_COLOR_RGB[] = Color.RED.getRGBColorComponents(null);
|
||||||
|
|
||||||
private boolean active = false;
|
private boolean active = false;
|
||||||
private Simulation simulation = null;
|
private Simulation simulation = null;
|
||||||
private Visualizer visualizer = null;
|
private Visualizer visualizer = null;
|
||||||
private AbstractRadioMedium radioMedium = null;
|
private AbstractRadioMedium radioMedium = null;
|
||||||
|
|
||||||
private ArrayList<RadioConnectionArrow> historyList = new ArrayList<RadioConnectionArrow>();
|
private final List<RadioConnectionArrow> historyList = new LinkedList<>();
|
||||||
private RadioConnectionArrow[] history = null;
|
|
||||||
|
|
||||||
private Observer radioMediumObserver = new Observer() {
|
private Observer radioMediumObserver = new Observer() {
|
||||||
|
@Override
|
||||||
public void update(Observable obs, Object obj) {
|
public void update(Observable obs, Object obj) {
|
||||||
RadioConnection last = radioMedium.getLastConnection();
|
RadioConnection last = radioMedium.getLastConnection();
|
||||||
if (last != null && historyList.size() < MAX_HISTORY_SIZE) {
|
if (last != null && historyList.size() < MAX_HISTORY_SIZE) {
|
||||||
historyList.add(new RadioConnectionArrow(last));
|
synchronized(historyList) {
|
||||||
history = historyList.toArray(new RadioConnectionArrow[0]);
|
historyList.add(new RadioConnectionArrow(last));
|
||||||
visualizer.repaint(500);
|
visualizer.repaint(500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private TimeEvent ageArrowsTimeEvent = new TimeEvent(0) {
|
|
||||||
|
private final TimeEvent ageArrowsTimeEvent = new TimeEvent(0) {
|
||||||
|
@Override
|
||||||
public void execute(long t) {
|
public void execute(long t) {
|
||||||
if (!active) {
|
if (!active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (historyList.size() > 0) {
|
if (historyList.size() > 0) {
|
||||||
boolean hasOld = false;
|
|
||||||
|
|
||||||
/* Increase age */
|
synchronized (historyList) {
|
||||||
for (RadioConnectionArrow connArrow : historyList) {
|
/* Increase age and remove too old arrows */
|
||||||
connArrow.increaseAge();
|
Iterator<RadioConnectionArrow> iter = historyList.iterator();
|
||||||
if(connArrow.getAge() >= connArrow.getMaxAge()) {
|
while (iter.hasNext()) {
|
||||||
hasOld = true;
|
RadioConnectionArrow rca = iter.next();
|
||||||
}
|
/* Try to increase age and remove if max age was reached */
|
||||||
}
|
if (!rca.increaseAge()) {
|
||||||
|
iter.remove();
|
||||||
/* Remove too old arrows */
|
|
||||||
if (hasOld) {
|
|
||||||
RadioConnectionArrow[] historyArr = historyList.toArray(new RadioConnectionArrow[0]);
|
|
||||||
for (RadioConnectionArrow connArrow : historyArr) {
|
|
||||||
if(connArrow.getAge() >= connArrow.getMaxAge()) {
|
|
||||||
historyList.remove(connArrow);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
historyArr = historyList.toArray(new RadioConnectionArrow[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visualizer.repaint(500);
|
visualizer.repaint(500);
|
||||||
|
@ -118,6 +117,7 @@ public class TrafficVisualizerSkin implements VisualizerSkin {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setActive(final Simulation simulation, Visualizer vis) {
|
public void setActive(final Simulation simulation, Visualizer vis) {
|
||||||
this.radioMedium = (AbstractRadioMedium) simulation.getRadioMedium();
|
this.radioMedium = (AbstractRadioMedium) simulation.getRadioMedium();
|
||||||
this.simulation = simulation;
|
this.simulation = simulation;
|
||||||
|
@ -125,9 +125,9 @@ public class TrafficVisualizerSkin implements VisualizerSkin {
|
||||||
this.active = true;
|
this.active = true;
|
||||||
|
|
||||||
simulation.invokeSimulationThread(new Runnable() {
|
simulation.invokeSimulationThread(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
historyList.clear();
|
historyList.clear();
|
||||||
history = null;
|
|
||||||
|
|
||||||
/* Start observing radio medium for transmissions */
|
/* Start observing radio medium for transmissions */
|
||||||
radioMedium.addRadioMediumObserver(radioMediumObserver);
|
radioMedium.addRadioMediumObserver(radioMediumObserver);
|
||||||
|
@ -138,6 +138,7 @@ public class TrafficVisualizerSkin implements VisualizerSkin {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setInactive() {
|
public void setInactive() {
|
||||||
this.active = false;
|
this.active = false;
|
||||||
if (simulation == null) {
|
if (simulation == null) {
|
||||||
|
@ -149,11 +150,12 @@ public class TrafficVisualizerSkin implements VisualizerSkin {
|
||||||
radioMedium.deleteRadioMediumObserver(radioMediumObserver);
|
radioMedium.deleteRadioMediumObserver(radioMediumObserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Color[] getColorOf(Mote mote) {
|
public Color[] getColorOf(Mote mote) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Polygon arrowPoly = new Polygon();
|
private final Polygon arrowPoly = new Polygon();
|
||||||
private void drawArrow(Graphics g, int xSource, int ySource, int xDest, int yDest, int delta) {
|
private void drawArrow(Graphics g, int xSource, int ySource, int xDest, int yDest, int delta) {
|
||||||
double dx = xSource - xDest;
|
double dx = xSource - xDest;
|
||||||
double dy = ySource - yDest;
|
double dy = ySource - yDest;
|
||||||
|
@ -183,52 +185,81 @@ public class TrafficVisualizerSkin implements VisualizerSkin {
|
||||||
return (int)(0.5 + len * Math.sin(dir));
|
return (int)(0.5 + len * Math.sin(dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void paintBeforeMotes(Graphics g) {
|
public void paintBeforeMotes(Graphics g) {
|
||||||
RadioConnectionArrow[] historyCopy = history;
|
synchronized (historyList) {
|
||||||
if (historyCopy == null) {
|
for (RadioConnectionArrow connArrow : historyList) {
|
||||||
return;
|
float colorHistoryIndex = 1.0f - connArrow.getAge();
|
||||||
}
|
Radio source = connArrow.getConnection().getSource();
|
||||||
for (RadioConnectionArrow connArrow : historyCopy) {
|
Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition());
|
||||||
float colorHistoryIndex = (float)connArrow.getAge() / (float)connArrow.getMaxAge();
|
/* If there is no destination, paint red circles to indicate untransmitted message */
|
||||||
g.setColor(new Color(colorHistoryIndex, colorHistoryIndex, 1.0f));
|
if (connArrow.getConnection().getDestinations().length == 0) {
|
||||||
Radio source = connArrow.getConnection().getSource();
|
g.setColor(new Color(UNTRANSMITTED_COLOR_RGB[0], UNTRANSMITTED_COLOR_RGB[1], UNTRANSMITTED_COLOR_RGB[2], colorHistoryIndex));
|
||||||
Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition());
|
g.drawOval(sourcePoint.x - 20, sourcePoint.y - 20, 40, 40);
|
||||||
for (Radio destRadio : connArrow.getConnection().getDestinations()) {
|
g.drawOval(sourcePoint.x - 30, sourcePoint.y - 30, 60, 60);
|
||||||
Position destPos = destRadio.getPosition();
|
continue;
|
||||||
Point destPoint = visualizer.transformPositionToPixel(destPos);
|
}
|
||||||
drawArrow(g, sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y, 8);
|
g.setColor(new Color(TRANSMITTED_COLOR_RGB[0], TRANSMITTED_COLOR_RGB[1], TRANSMITTED_COLOR_RGB[2], colorHistoryIndex));
|
||||||
|
for (Radio destRadio : connArrow.getConnection().getDestinations()) {
|
||||||
|
Position destPos = destRadio.getPosition();
|
||||||
|
Point destPoint = visualizer.transformPositionToPixel(destPos);
|
||||||
|
drawArrow(g, sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y, 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void paintAfterMotes(Graphics g) {
|
public void paintAfterMotes(Graphics g) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Visualizer getVisualizer() {
|
public Visualizer getVisualizer() {
|
||||||
return visualizer;
|
return visualizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class RadioConnectionArrow {
|
private static class RadioConnectionArrow {
|
||||||
private RadioConnection conn;
|
|
||||||
private int age;
|
|
||||||
private static final int MAX_AGE = 10;
|
private static final int MAX_AGE = 10;
|
||||||
|
private final RadioConnection conn;
|
||||||
|
private int age;
|
||||||
|
|
||||||
RadioConnectionArrow(RadioConnection conn) {
|
RadioConnectionArrow(RadioConnection conn) {
|
||||||
this.conn = conn;
|
this.conn = conn;
|
||||||
this.age = 0;
|
this.age = 0;
|
||||||
}
|
}
|
||||||
public void increaseAge() {
|
|
||||||
|
/**
|
||||||
|
* Increases age of radio connection if possible or indicates max age.
|
||||||
|
*
|
||||||
|
* @return true if max age was not reached yet, false, if max age was
|
||||||
|
* reached
|
||||||
|
*/
|
||||||
|
public boolean increaseAge() {
|
||||||
if (age < MAX_AGE) {
|
if (age < MAX_AGE) {
|
||||||
age++;
|
age++;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public int getAge() {
|
|
||||||
return age;
|
/**
|
||||||
|
* Returns relative age of radio connection
|
||||||
|
*
|
||||||
|
* @return Relative age (0.0 - 1.0)
|
||||||
|
*/
|
||||||
|
public float getAge() {
|
||||||
|
return (float) age / (float) MAX_AGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns radio connection
|
||||||
|
*
|
||||||
|
* @return radio connection
|
||||||
|
*/
|
||||||
public RadioConnection getConnection() {
|
public RadioConnection getConnection() {
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
public int getMaxAge() {
|
|
||||||
return MAX_AGE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue