visualizers = new Visualizer[] {
nodeControl,
mapPanel,
new MapPanel(this, "Network Graph", MAIN, false),
new BarChartPanel(this, SENSORS, "Average Temperature", "Temperature", "Nodes", "Celsius",
new String[] { "Celsius" }) {
{
chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
protected void addSensorData(SensorData data) {
Node node = data.getNode();
String nodeName = node.getName();
SensorDataAggregator aggregator = node.getSensorDataAggregator();
dataset.addValue(aggregator.getAverageTemperature(), categories[0], nodeName);
}
},
new TimeChartPanel(this, SENSORS, "Temperature", "Temperature", "Time", "Celsius") {
{
chart.getXYPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits());
setRangeTick(5);
setRangeMinimumSize(10.0);
setGlobalRange(true);
}
protected double getSensorDataValue(SensorData data) {
return data.getTemperature();
}
},
new TimeChartPanel(this, SENSORS, "Battery Voltage", "Battery Voltage",
"Time", "Volt") {
{
setRangeTick(1);
setRangeMinimumSize(4.0);
setGlobalRange(true);
}
protected double getSensorDataValue(SensorData data) {
return data.getBatteryVoltage();
}
},
new TimeChartPanel(this, SENSORS, "Battery Indicator", "Battery Indicator",
"Time", "Indicator") {
{
chart.getXYPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits());
setRangeTick(5);
setRangeMinimumSize(10.0);
setGlobalRange(true);
}
protected double getSensorDataValue(SensorData data) {
return data.getBatteryIndicator();
}
},
new TimeChartPanel(this, SENSORS, "Relative Humidity", "Humidity", "Time", "%") {
{
chart.getXYPlot().getRangeAxis().setRange(0.0, 100.0);
}
protected double getSensorDataValue(SensorData data) {
return data.getHumidity();
}
},
new TimeChartPanel(this, SENSORS, "Light 1", "Light 1", "Time", "-") {
protected double getSensorDataValue(SensorData data) {
return data.getLight1();
}
},
new TimeChartPanel(this, SENSORS, "Light 2", "Light 2", "Time", "-") {
protected double getSensorDataValue(SensorData data) {
return data.getLight2();
}
},
new TimeChartPanel(this, NETWORK, "Neighbors", "Neighbor Count", "Time", "Neighbors") {
{
ValueAxis axis = chart.getXYPlot().getRangeAxis();
((NumberAxis)axis).setAutoRangeIncludesZero(true);
axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
protected double getSensorDataValue(SensorData data) {
return data.getValue(SensorData.NUM_NEIGHBORS);
}
},
new TimeChartPanel(this, NETWORK, "Beacon Interval", "Beacon interval", "Time", "Interval (s)") {
{
ValueAxis axis = chart.getXYPlot().getRangeAxis();
((NumberAxis)axis).setAutoRangeIncludesZero(true);
axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
protected double getSensorDataValue(SensorData data) {
return data.getValue(SensorData.BEACON_INTERVAL);
}
},
new TimeChartPanel(this, NETWORK, "Network Hops (Over Time)", "Network Hops", "Time", "Hops") {
{
ValueAxis axis = chart.getXYPlot().getRangeAxis();
((NumberAxis)axis).setAutoRangeIncludesZero(true);
axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
protected double getSensorDataValue(SensorData data) {
return data.getValue(SensorData.HOPS);
}
},
new BarChartPanel(this, NETWORK, "Network Hops (Per Node)", "Network Hops", "Nodes", "Hops",
new String[] { "Last Hop", "Average Hops" }, false) {
{
chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
protected void addSensorData(SensorData data) {
dataset.addValue(data.getValue(SensorData.HOPS), categories[0], data.getNode().getName());
dataset.addValue(data.getNode().getSensorDataAggregator().getAverageValue(SensorData.HOPS), categories[1], data.getNode().getName());
}
},
new TimeChartPanel(this, NETWORK, "Routing Metric (Over Time)", "Routing Metric", "Time", "Routing Metric") {
{
ValueAxis axis = chart.getXYPlot().getRangeAxis();
((NumberAxis)axis).setAutoRangeIncludesZero(true);
axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
protected double getSensorDataValue(SensorData data) {
return data.getValue(SensorData.RTMETRIC);
}
},
new AggregatedTimeChartPanel<boolean[]>(this, NETWORK, "Avg Routing Metric (Over Time)", "Time",
"Average Routing Metric") {
private int nodeCount;
{
ValueAxis axis = chart.getXYPlot().getRangeAxis();
((NumberAxis)axis).setAutoRangeIncludesZero(true);
axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
@Override
protected boolean[] createState(Node node) {
return new boolean[1];
}
@Override
protected void clearState(Map<Node,boolean[]> map) {
nodeCount = 0;
for(boolean[] value : map.values()) {
value[0] = false;
}
}
@Override
protected String getTitle(int selectedCount, int dataCount, int duplicateCount) {
return "Average Routing Metric (" + dataCount + " packets from " + nodeCount + " node"
+ (nodeCount > 1 ? "s" : "") + ')';
}
@Override
protected int getTotalDataValue(int value) {
// Return average value
return nodeCount > 0 ? (value / nodeCount) : value;
}
@Override
protected int getSensorDataValue(SensorData data, boolean[] nodeState) {
if (!nodeState[0]) {
nodeCount++;
nodeState[0] = true;
}
return data.getValue(SensorData.RTMETRIC);
}
},
new TimeChartPanel(this, NETWORK, "ETX (Over Time)", "ETX to Next Hop", "Time", "ETX") {
{
ValueAxis axis = chart.getXYPlot().getRangeAxis();
((NumberAxis)axis).setAutoRangeIncludesZero(true);
axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
protected double getSensorDataValue(SensorData data) {
return data.getBestNeighborETX();
}
},
new AggregatedTimeChartPanel<int[]>(this, NETWORK,
"Next Hop (Over Time)", "Time", "Next Hop Changes") {
{
ValueAxis axis = chart.getXYPlot().getRangeAxis();
((NumberAxis)axis).setAutoRangeIncludesZero(true);
axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
@Override
protected int[] createState(Node node) {
return new int[1];
}
@Override
protected void clearState(Map<Node,int[]> map) {
for(int[] value : map.values()) {
value[0] = 0;
}
}
@Override
protected int getSensorDataValue(SensorData sd, int[] nodeState) {
boolean hasBest = nodeState[0] != 0;
int bestNeighbor = sd.getValue(SensorData.BEST_NEIGHBOR);
if (bestNeighbor != 0 && bestNeighbor != nodeState[0]) {
nodeState[0] = bestNeighbor;
return hasBest ? 1 : 0;
}
return 0;
}
},
new TimeChartPanel(this, NETWORK, "Latency", "Latency", "Time", "Seconds") {
protected double getSensorDataValue(SensorData data) {
return data.getLatency();
}
},
new AggregatedTimeChartPanel<Node>(this, NETWORK,
"Received (Over Time)", "Time", "Received Packets") {
{
ValueAxis axis = chart.getXYPlot().getRangeAxis();
((NumberAxis)axis).setAutoRangeIncludesZero(true);
axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
@Override
protected String getTitle(int nodeCount, int dataCount, int duplicateCount) {
return "Received " + dataCount + " packets from " + nodeCount + " node"
+ (nodeCount > 1 ? "s" : "")
+ (duplicateCount > 0 ? (" (" + duplicateCount + " duplicates)") : "");
}
@Override
protected Node createState(Node node) {
return node;
}
@Override
protected int getSensorDataValue(SensorData sd, Node node) {
return 1;
}
},
new AggregatedTimeChartPanel<int[]>(this, NETWORK,
"Lost (Over Time)", "Time", "Estimated Lost Packets") {
private int totalLost;
{
ValueAxis axis = chart.getXYPlot().getRangeAxis();
((NumberAxis)axis).setAutoRangeIncludesZero(true);
axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
@Override
protected String getTitle(int nodeCount, int dataCount, int duplicateCount) {
return "Received " + dataCount + " packets from " + nodeCount
+ " node" + (nodeCount > 1 ? "s" : "") + ". Estimated "
+ totalLost + " lost packet" + (totalLost == 1 ? "" : "s")
+ '.';
}
@Override
protected int[] createState(Node node) {
return new int[1];
}
@Override
protected void clearState(Map<Node,int[]> map) {
totalLost = 0;
for(int[] v : map.values()) {
v[0] = 0;
}
}
@Override
protected int getSensorDataValue(SensorData sd, int[] nodeState) {
int lastSeqno = nodeState[0];
int seqno = sd.getSeqno();
nodeState[0] = seqno;
if (seqno > lastSeqno + 1 && lastSeqno != 0) {
int estimatedLost = seqno - lastSeqno - 1;
totalLost += estimatedLost;
return estimatedLost;
}
return 0;
}
},
new BarChartPanel(this, NETWORK, "Received (Per Node)", "Received Packets Per Node", "Nodes", "Packets",
new String[] { "Packets", "Duplicates" }) {
{
chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
protected void addSensorData(SensorData data) {
Node node = data.getNode();
SensorDataAggregator sda = node.getSensorDataAggregator();
dataset.addValue(sda.getDataCount(), categories[0], node.getName());
dataset.addValue(sda.getDuplicateCount(), categories[1], node.getName());
}
},
new BarChartPanel(this, NETWORK, "Received (5 min)", "Received Packets (last 5 min)", "Nodes", "Packets",
new String[] { "Packets", "Duplicates" }) {
{
chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits());
}
protected void addSensorData(SensorData data) {
Node node = data.getNode();
int packetCount = 0;
int duplicateCount = 0;
long earliestData = System.currentTimeMillis() - (5 * 60 * 1000);
for(int index = node.getSensorDataCount() - 1; index >= 0; index--) {
SensorData sd = node.getSensorData(index);
if (sd.getNodeTime() < earliestData) {
break;
}
if (sd.isDuplicate()) {
duplicateCount++;
} else {
packetCount++;
}
}
dataset.addValue(packetCount, categories[0], node.getName());
dataset.addValue(duplicateCount, categories[1], node.getName());
}
},
new BarChartPanel(this, POWER, "Average Power", "Average Power Consumption",
"Nodes", "Power (mW)",
new String[] { "LPM", "CPU", "Radio listen", "Radio transmit" }) {
{
ValueAxis axis = chart.getCategoryPlot().getRangeAxis();
((NumberAxis)axis).setAutoRangeIncludesZero(true);
}
protected void addSensorData(SensorData data) {
Node node = data.getNode();
String nodeName = node.getName();
SensorDataAggregator aggregator = node.getSensorDataAggregator();
dataset.addValue(aggregator.getLPMPower(), categories[0], nodeName);
dataset.addValue(aggregator.getCPUPower(), categories[1], nodeName);
dataset.addValue(aggregator.getListenPower(), categories[2], nodeName);
dataset.addValue(aggregator.getTransmitPower(), categories[3], nodeName);
}
},
new BarChartPanel(this, POWER, "Radio Duty Cycle", "Average Radio Duty Cycle",
"Nodes", "Duty Cycle (%)",
new String[] { "Radio listen", "Radio transmit" }) {
{
ValueAxis axis = chart.getCategoryPlot().getRangeAxis();
((NumberAxis)axis).setAutoRangeIncludesZero(true);
}
protected void addSensorData(SensorData data) {
Node node = data.getNode();
String nodeName = node.getName();
SensorDataAggregator aggregator = node.getSensorDataAggregator();
dataset.addValue(100 * aggregator.getAverageDutyCycle(SensorInfo.TIME_LISTEN),
categories[0], nodeName);
dataset.addValue(100 * aggregator.getAverageDutyCycle(SensorInfo.TIME_TRANSMIT),
categories[1], nodeName);
}
},
new BarChartPanel(this, POWER, "Instantaneous Power",
"Instantaneous Power Consumption", "Nodes", "Power (mW)",
new String[] { "LPM", "CPU", "Radio listen", "Radio transmit" }) {
{
ValueAxis axis = chart.getCategoryPlot().getRangeAxis();
((NumberAxis)axis).setAutoRangeIncludesZero(true);