added Payload Alias for easier overview of several packets with identical payloads.

added Timeline menu option for quickly viewing the selected radio packet in the Timeline plugin.
This commit is contained in:
fros4943 2009-11-25 15:32:34 +00:00
parent d4f674c053
commit d27a2dfb5b
1 changed files with 139 additions and 22 deletions

View File

@ -26,28 +26,33 @@
* 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: RadioLogger.java,v 1.24 2009/09/24 08:56:17 nifi Exp $ * $Id: RadioLogger.java,v 1.25 2009/11/25 15:32:34 fros4943 Exp $
*/ */
package se.sics.cooja.plugins; package se.sics.cooja.plugins;
import java.awt.Color;
import java.awt.Font; import java.awt.Font;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Observable; import java.util.Observable;
import java.util.Observer; import java.util.Observer;
import java.util.Properties;
import java.util.Vector;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JFileChooser; import javax.swing.JFileChooser;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
@ -58,10 +63,10 @@ import javax.swing.table.AbstractTableModel;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.jdom.Element; import org.jdom.Element;
import se.sics.cooja.ClassDescription; import se.sics.cooja.ClassDescription;
import se.sics.cooja.ConvertedRadioPacket; import se.sics.cooja.ConvertedRadioPacket;
import se.sics.cooja.GUI; import se.sics.cooja.GUI;
import se.sics.cooja.Mote;
import se.sics.cooja.PluginType; import se.sics.cooja.PluginType;
import se.sics.cooja.RadioConnection; import se.sics.cooja.RadioConnection;
import se.sics.cooja.RadioMedium; import se.sics.cooja.RadioMedium;
@ -69,7 +74,6 @@ import se.sics.cooja.RadioPacket;
import se.sics.cooja.Simulation; import se.sics.cooja.Simulation;
import se.sics.cooja.VisPlugin; import se.sics.cooja.VisPlugin;
import se.sics.cooja.dialogs.TableColumnAdjuster; import se.sics.cooja.dialogs.TableColumnAdjuster;
import se.sics.cooja.interfaces.MoteID;
import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.Radio;
import se.sics.cooja.util.StringUtils; import se.sics.cooja.util.StringUtils;
@ -147,6 +151,13 @@ public class RadioLogger extends VisPlugin {
if (conn.data == null) { if (conn.data == null) {
prepareDataString(connections.get(row)); prepareDataString(connections.get(row));
} }
if (aliases != null) {
/* Check if alias exists */
String alias = (String) aliases.get(conn.data);
if (alias != null) {
return alias;
}
}
return conn.data; return conn.data;
} }
return null; return null;
@ -237,7 +248,11 @@ public class RadioLogger extends VisPlugin {
popupMenu.add(new JMenuItem(copyAllAction)); popupMenu.add(new JMenuItem(copyAllAction));
popupMenu.add(new JMenuItem(clearAction)); popupMenu.add(new JMenuItem(clearAction));
popupMenu.addSeparator(); popupMenu.addSeparator();
popupMenu.add(new JMenuItem(aliasAction));
popupMenu.addSeparator();
popupMenu.add(new JMenuItem(saveAction)); popupMenu.add(new JMenuItem(saveAction));
popupMenu.addSeparator();
popupMenu.add(new JMenuItem(timeLineAction));
dataTable.setComponentPopupMenu(popupMenu); dataTable.setComponentPopupMenu(popupMenu);
add(new JScrollPane(dataTable)); add(new JScrollPane(dataTable));
@ -248,19 +263,15 @@ public class RadioLogger extends VisPlugin {
radioMedium.addRadioMediumObserver(radioMediumObserver = new Observer() { radioMedium.addRadioMediumObserver(radioMediumObserver = new Observer() {
public void update(Observable obs, Object obj) { public void update(Observable obs, Object obj) {
RadioConnection[] conns = radioMedium.getLastTickConnections(); RadioConnection conn = radioMedium.getLastConnection();
if (conns == null || conns.length == 0) { if (conn == null) {
return; return;
} }
final RadioConnectionLog[] logged = new RadioConnectionLog[conns.length]; final RadioConnectionLog loggedConn = new RadioConnectionLog();
for (int i = 0, n = logged.length; i < n; i++) { loggedConn.startTime = conn.getStartTime();
RadioConnectionLog loggedConn = new RadioConnectionLog(); loggedConn.endTime = simulation.getSimulationTime();
loggedConn.startTime = conns[i].getStartTime(); loggedConn.connection = conn;
loggedConn.endTime = simulation.getSimulationTime(); loggedConn.packet = conn.getSource().getLastPacketTransmitted();
loggedConn.connection = conns[i];
loggedConn.packet = conns[i].getSource().getLastPacketTransmitted();
logged[i] = loggedConn;
}
java.awt.EventQueue.invokeLater(new Runnable() { java.awt.EventQueue.invokeLater(new Runnable() {
public void run() { public void run() {
int lastSize = connections.size(); int lastSize = connections.size();
@ -272,9 +283,7 @@ public class RadioLogger extends VisPlugin {
Rectangle visible = dataTable.getVisibleRect(); Rectangle visible = dataTable.getVisibleRect();
isVisible = visible.y <= lastRow.y && visible.y + visible.height >= lastRow.y + lastRow.height; isVisible = visible.y <= lastRow.y && visible.y + visible.height >= lastRow.y + lastRow.height;
} }
for(RadioConnectionLog log: logged) { connections.add(loggedConn);
connections.add(log);
}
if (connections.size() > lastSize) { if (connections.size() > lastSize) {
model.fireTableRowsInserted(lastSize, connections.size() - 1); model.fireTableRowsInserted(lastSize, connections.size() - 1);
} }
@ -295,6 +304,26 @@ public class RadioLogger extends VisPlugin {
} }
} }
/**
* Selects a logged radio packet close to the given time.
*
* @param time Start time
*/
public void trySelectTime(final long time) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
for (int i=0; i < connections.size(); i++) {
if (connections.get(i).endTime < time) {
continue;
}
dataTable.scrollRectToVisible(dataTable.getCellRect(i, 0, true));
dataTable.setRowSelectionInterval(i, i);
return;
}
}
});
}
private void prepareDataString(RadioConnectionLog conn) { private void prepareDataString(RadioConnectionLog conn) {
byte[] data; byte[] data;
if (conn.packet == null) { if (conn.packet == null) {
@ -353,14 +382,37 @@ public class RadioLogger extends VisPlugin {
} }
public Collection<Element> getConfigXML() { public Collection<Element> getConfigXML() {
return null; if (aliases == null) {
return null;
}
ArrayList<Element> config = new ArrayList<Element>();
Element element;
for (Object key: aliases.keySet()) {
element = new Element("alias");
element.setAttribute("payload", (String) key);
element.setAttribute("alias", (String) aliases.get(key));
config.add(element);
}
return config;
} }
public boolean setConfigXML(Collection<Element> configXML, public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
boolean visAvailable) { if (aliases == null) {
aliases = new Properties();
}
for (Element element : configXML) {
if (element.getName().equals("alias")) {
String payload = element.getAttributeValue("payload");
String alias = element.getAttributeValue("alias");
aliases.put(payload, alias);
}
}
return true; return true;
} }
private static class RadioConnectionLog { private static class RadioConnectionLog {
long startTime; long startTime;
long endTime; long endTime;
@ -478,5 +530,70 @@ public class RadioLogger extends VisPlugin {
} }
}; };
private Action timeLineAction = new AbstractAction("to Timeline") {
public void actionPerformed(ActionEvent e) {
TimeLine plugin = (TimeLine) simulation.getGUI().getStartedPlugin(TimeLine.class.getName());
if (plugin == null) {
logger.fatal("No Timeline plugin");
return;
}
int selectedRow = dataTable.getSelectedRow();
if (selectedRow < 0) return;
long time = connections.get(selectedRow).startTime;
/* Select simulation time */
plugin.trySelectTime(time);
}
};
private Properties aliases = null;
private Action aliasAction = new AbstractAction("Assign alias") {
public void actionPerformed(ActionEvent e) {
int selectedRow = dataTable.getSelectedRow();
if (selectedRow < 0) return;
String current = "";
if (aliases != null && aliases.get(connections.get(selectedRow).data) != null) {
current = (String) aliases.get(connections.get(selectedRow).data);
}
String alias = (String) JOptionPane.showInputDialog(
GUI.getTopParentContainer(),
"Enter alias for all packets with identical payload.\n" +
"An empty string removes the current alias.\n\n" +
connections.get(selectedRow).data + "\n",
"Create packet payload alias",
JOptionPane.QUESTION_MESSAGE,
null,
null,
current);
if (alias == null) {
/* Cancelled */
return;
}
/* Should be null if empty */
if (aliases == null) {
aliases = new Properties();
}
/* Remove current alias */
if (alias.equals("")) {
aliases.remove(connections.get(selectedRow).data);
/* Should be null if empty */
if (aliases.isEmpty()) {
aliases = null;
}
repaint();
return;
}
/* (Re)define alias */
aliases.put(connections.get(selectedRow).data, alias);
repaint();
}
};
} }