[cooja] plugins/VariableWatcher: Allow to access memory by address/size

By selecting the checbox next to the address field, VariableWatcher
switches from variable mode to address mode.
Now any address and size might be entered to show data from memory.

Additionally for variables where now size information is available the
interface allows the user to select one.
This commit is contained in:
Enrico Joerns 2014-08-28 13:37:30 +02:00
parent 9d8516e9ef
commit f70e1ef99f

View file

@ -37,6 +37,8 @@ import java.awt.Dimension;
import java.awt.FlowLayout; import java.awt.FlowLayout;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent; import java.awt.event.ItemEvent;
import java.awt.event.ItemListener; import java.awt.event.ItemListener;
import java.text.NumberFormat; import java.text.NumberFormat;
@ -50,13 +52,13 @@ import javax.swing.BorderFactory;
import javax.swing.Box; import javax.swing.Box;
import javax.swing.BoxLayout; import javax.swing.BoxLayout;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox; import javax.swing.JComboBox;
import javax.swing.JFormattedTextField; import javax.swing.JFormattedTextField;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JTextField; import javax.swing.JTextField;
import javax.swing.JToggleButton; import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener; import javax.swing.event.PopupMenuListener;
import javax.swing.text.AttributeSet; import javax.swing.text.AttributeSet;
@ -96,19 +98,17 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
private final static int LABEL_WIDTH = 170; private final static int LABEL_WIDTH = 170;
private final static int LABEL_HEIGHT = 15; private final static int LABEL_HEIGHT = 15;
private JPanel lengthPane;
private JComboBox varNameCombo; private JComboBox varNameCombo;
private JComboBox varTypeCombo; private JComboBox varTypeCombo;
private JComboBox varFormatCombo; private JComboBox varFormatCombo;
private JPanel infoPane; private JPanel infoPane;
private JTextField varAddressField; private JFormattedTextField varAddressField;
private JTextField varSizeField; private JTextField varSizeField;
private JPanel valuePane; private JPanel valuePane;
private JFormattedTextField[] varValues; private JFormattedTextField[] varValues;
private byte[] bufferedBytes; private byte[] bufferedBytes;
private JButton readButton; private JButton readButton;
private AbstractButton monitorButton; private AbstractButton monitorButton;
private JFormattedTextField varLength;
private JButton writeButton; private JButton writeButton;
private JLabel debuglbl; private JLabel debuglbl;
private VarMemory moteMemory; private VarMemory moteMemory;
@ -251,43 +251,21 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
@Override @Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
String currentItem = (String)varNameCombo.getSelectedItem(); String currentItem = (String)varNameCombo.getSelectedItem();
/* If item did not changed, skip! */ /* If item did not changed, skip! */
if (currentItem == null || currentItem.equals(lastItem)) { if (currentItem == null || currentItem.equals(lastItem)) {
return; return;
} }
lastItem = currentItem; lastItem = currentItem;
try { updateBySelectedVarname();
/* invalidate byte field */
bufferedBytes = null;
/* calculate number of elements required to show the value in the given size */
updateNumberOfValues();
varAddressField.setText(String.format("0x%04x", moteMemory.getVariableAddress(currentItem)));
long size = moteMemory.getVariableSize(currentItem);
/* Disable buttons if variable reported size < 1, activate otherwise */
if (size < 1) {
varSizeField.setText("N/A");
readButton.setEnabled(false);
monitorButton.setEnabled(false);
writeButton.setEnabled(false);
} else {
varSizeField.setText(String.valueOf(size));
readButton.setEnabled(true);
monitorButton.setEnabled(true);
writeButton.setEnabled(true);
}
}
catch (UnknownVariableException ex) {
((JTextField) varNameCombo.getEditor().getEditorComponent()).setForeground(Color.RED);
writeButton.setEnabled(false);
}
} }
@Override @Override
public void popupMenuCanceled(PopupMenuEvent e) { public void popupMenuCanceled(PopupMenuEvent e) {
} }
}); });
smallPane.add(BorderLayout.EAST, varNameCombo); smallPane.add(BorderLayout.EAST, varNameCombo);
mainPane.add(smallPane); mainPane.add(smallPane);
@ -340,26 +318,94 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
infoPane = new JPanel(); infoPane = new JPanel();
infoPane.setLayout(new BoxLayout(infoPane, BoxLayout.Y_AXIS)); infoPane.setLayout(new BoxLayout(infoPane, BoxLayout.Y_AXIS));
JPanel addrInfoPane = new JPanel(new BorderLayout()); JPanel addrInfoPane = new JPanel();
JPanel sizeInfoPane = new JPanel(new BorderLayout()); addrInfoPane.setLayout(new BoxLayout(addrInfoPane, BoxLayout.LINE_AXIS));
JPanel sizeInfoPane = new JPanel();
sizeInfoPane.setLayout(new BoxLayout(sizeInfoPane, BoxLayout.LINE_AXIS));
label = new JLabel("Address"); label = new JLabel("Address");
addrInfoPane.add(BorderLayout.CENTER, label); addrInfoPane.add(label);
varAddressField = new JTextField("?"); addrInfoPane.add(Box.createHorizontalGlue());
final JCheckBox varAddrCheckBox = new JCheckBox();
varAddrCheckBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (varAddrCheckBox.isSelected()) {
varNameCombo.setEnabled(false);
varNameCombo.setEditable(false);
varAddressField.setEnabled(true);
varAddressField.setEditable(true);
varSizeField.setEnabled(true);
varSizeField.setEditable(true);
} else {
varNameCombo.setEnabled(true);
varNameCombo.setEditable(true);
// switch back to var name control
updateBySelectedVarname();
varAddressField.setEditable(false);
varSizeField.setEditable(false);
}
}
});
addrInfoPane.add(varAddrCheckBox);
DefaultFormatterFactory defac = new DefaultFormatterFactory(new ValueFormatter(VarTypes.LONG, VarFormats.HEX));
varAddressField = new JFormattedTextField(defac);
varAddressField.setValue(null);
varAddressField.setEditable(false); varAddressField.setEditable(false);
varAddressField.setEnabled(false); varAddressField.setColumns(8);
varAddressField.setColumns(6); varAddressField.setMaximumSize(varAddressField.getPreferredSize());
addrInfoPane.add(BorderLayout.EAST, varAddressField); /* Select all text when clicking in text field */
varAddressField.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
varAddressField.selectAll();
}
@Override
public void focusLost(FocusEvent e) {
}
});
/* Update when content might have changed */
varAddressField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateNumberOfValues();
}
});
addrInfoPane.add(varAddressField);
infoPane.add(addrInfoPane); infoPane.add(addrInfoPane);
label = new JLabel("Size"); label = new JLabel("Size");
sizeInfoPane.add(BorderLayout.WEST, label); sizeInfoPane.add(label);
varSizeField = new JTextField("?"); sizeInfoPane.add(Box.createHorizontalGlue());
varSizeField = new JTextField("N/A");
varSizeField.setEditable(false); varSizeField.setEditable(false);
varSizeField.setEnabled(false); varSizeField.setColumns(8);
varSizeField.setColumns(6); varSizeField.setMaximumSize(varSizeField.getPreferredSize());
sizeInfoPane.add(BorderLayout.EAST, varSizeField); /* Select all text when clicking in text field */
varSizeField.addFocusListener(new FocusListener() {
@Override
public void focusGained(final FocusEvent pE) {
varSizeField.selectAll();
}
@Override
public void focusLost(final FocusEvent pE) {
}
});
/* Update size information when text box action fired */
varSizeField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateNumberOfValues();
}
});
sizeInfoPane.add(varSizeField);
infoPane.add(sizeInfoPane); infoPane.add(sizeInfoPane);
mainPane.add(infoPane); mainPane.add(infoPane);
@ -380,9 +426,8 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
varValues = new JFormattedTextField[1]; varValues = new JFormattedTextField[1];
varValues[0] = new JFormattedTextField(integerFormat); varValues[0] = new JFormattedTextField(integerFormat);
varValues[0].setValue(new Integer(0)); varValues[0].setValue(null);
varValues[0].setColumns(3); varValues[0].setColumns(3);
varValues[0].setText("?");
mainPane.add(valuePane); mainPane.add(valuePane);
mainPane.add(Box.createRigidArea(new Dimension(0,5))); mainPane.add(Box.createRigidArea(new Dimension(0,5)));
@ -408,8 +453,8 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
writeButton.setEnabled(true); writeButton.setEnabled(true);
bufferedBytes = moteMemory.getByteArray( bufferedBytes = moteMemory.getByteArray(
(String) varNameCombo.getSelectedItem(), (long) varAddressField.getValue(),
moteMemory.getVariableSize((String) varNameCombo.getSelectedItem())); Integer.decode(varSizeField.getText()));
refreshValues(); refreshValues();
} }
}); });
@ -425,31 +470,24 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
String varname = (String) varNameCombo.getSelectedItem();
// deselect // deselect
if (!((JToggleButton) e.getSource()).isSelected()) { if (!((JToggleButton) e.getSource()).isSelected()) {
//System.out.println("Removing monitor " + memMonitor + " for addr " + monitorAddr + ", size " + monitorSize + ""); //System.out.println("Removing monitor " + memMonitor + " for addr " + monitorAddr + ", size " + monitorSize + "");
moteMemory.removeVarMonitor(varname, memMonitor); mote.getMemory().removeSegmentMonitor(
(long) varAddressField.getValue(),
Integer.decode(varSizeField.getText()),
memMonitor);
varAddrCheckBox.setEnabled(true);
readButton.setEnabled(true); readButton.setEnabled(true);
varNameCombo.setEnabled(true); varNameCombo.setEnabled(true);
writeButton.setEnabled(true); writeButton.setEnabled(true);
return; return;
} }
// handle unknown variable
if (!moteMemory.variableExists(varname)) {
((JTextField) varNameCombo.getEditor().getEditorComponent()).setForeground(Color.RED);
writeButton.setEnabled(false);
((JToggleButton) e.getSource()).setSelected(false);
return;
}
/* initial readout so we have a value to display */ /* initial readout so we have a value to display */
bufferedBytes = moteMemory.getByteArray( bufferedBytes = moteMemory.getByteArray(
(String) varNameCombo.getSelectedItem(), (long) varAddressField.getValue(),
moteMemory.getVariableSize((String) varNameCombo.getSelectedItem())); Integer.decode(varSizeField.getText()));
refreshValues(); refreshValues();
// monitorAddr = moteMemory.getVariableAddress(varname); // monitorAddr = moteMemory.getVariableAddress(varname);
@ -460,19 +498,21 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
// public void memoryChanged(MoteMemory memory, MoteMemory.MemoryEventType type, int address) { // public void memoryChanged(MoteMemory memory, MoteMemory.MemoryEventType type, int address) {
public void memoryChanged(MemoryInterface memory, EventType type, long address) { public void memoryChanged(MemoryInterface memory, EventType type, long address) {
bufferedBytes = moteMemory.getByteArray( bufferedBytes = moteMemory.getByteArray(
(String) varNameCombo.getSelectedItem(), (long) varAddressField.getValue(),
moteMemory.getVariableSize((String) varNameCombo.getSelectedItem())); Integer.decode(varSizeField.getText()));
refreshValues(); refreshValues();
} }
}; };
//System.out.println("Adding monitor " + memMonitor + " for addr " + monitorAddr + ", size " + monitorSize + ""); //System.out.println("Adding monitor " + memMonitor + " for addr " + monitorAddr + ", size " + monitorSize + "");
moteMemory.addVarMonitor( mote.getMemory().addSegmentMonitor(
MemoryInterface.SegmentMonitor.EventType.WRITE, MemoryInterface.SegmentMonitor.EventType.WRITE,
varname, (long) varAddressField.getValue(),
Integer.decode(varSizeField.getText()),
memMonitor); memMonitor);
/* During monitoring we neither allow writes nor to change variable */ /* During monitoring we neither allow writes nor to change variable */
varAddrCheckBox.setEnabled(false);
readButton.setEnabled(false); readButton.setEnabled(false);
writeButton.setEnabled(false); writeButton.setEnabled(false);
varNameCombo.setEnabled(false); varNameCombo.setEnabled(false);
@ -501,7 +541,7 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
} }
} }
/* Write to memory */ /* Write to memory */
moteMemory.setByteArray((String) varNameCombo.getSelectedItem(), bufferedBytes); moteMemory.setByteArray((long) varAddressField.getValue(), bufferedBytes);
} }
}); });
@ -512,6 +552,29 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
pack(); pack();
} }
private void updateBySelectedVarname() {
try {
String currentItem = (String) varNameCombo.getSelectedItem();
/* invalidate byte field */
bufferedBytes = null;
/* calculate number of elements required to show the value in the given size */
varAddressField.setValue(moteMemory.getVariableAddress(currentItem));
int size = moteMemory.getVariableSize(currentItem);
/* Disable buttons if variable reported size < 1, activate otherwise */
if (size < 1) {
varSizeField.setText("N/A");
varSizeField.setEditable(true);
} else {
varSizeField.setText(String.valueOf(size));
varSizeField.setEditable(false);
}
updateNumberOfValues();
} catch (UnknownVariableException ex) {
((JTextField) varNameCombo.getEditor().getEditorComponent()).setForeground(Color.RED);
writeButton.setEnabled(false);
}
}
/** /**
* String to Value to String conversion for JFormattedTextField * String to Value to String conversion for JFormattedTextField
* based on selected VarTypes and VarFormats. * based on selected VarTypes and VarFormats.
@ -552,7 +615,20 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
case DEC: case DEC:
case HEX: case HEX:
try { try {
ret = Integer.decode(text); switch (mType) {
case BYTE:
ret = Byte.decode(text);
break;
case INT:
ret = Integer.decode(text);
break;
case LONG:
case ADDR:
ret = Long.decode(text);
break;
default:
ret = null;
}
} }
catch (NumberFormatException ex) { catch (NumberFormatException ex) {
ret = 0; ret = 0;
@ -567,7 +643,7 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
@Override @Override
public String valueToString(Object value) throws ParseException { public String valueToString(Object value) throws ParseException {
if (value == null) { if (value == null) {
return "?"; return "N/A";
} }
switch (mFormat) { switch (mFormat) {
@ -626,13 +702,8 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
* @note Does not read memory. Leaves number of fields unchanged. * @note Does not read memory. Leaves number of fields unchanged.
*/ */
private void refreshValues() { private void refreshValues() {
String varname = (String) varNameCombo.getSelectedItem();
if (!moteMemory.variableExists(varname)) { int bytes = Integer.decode(varSizeField.getText());
return;
}
int bytes = moteMemory.getVariableSize(varname);
int typeSize = ((VarTypes) varTypeCombo.getSelectedItem()).getBytes(); int typeSize = ((VarTypes) varTypeCombo.getSelectedItem()).getBytes();
int elements = (int) Math.ceil((double) bytes / typeSize); int elements = (int) Math.ceil((double) bytes / typeSize);
@ -667,19 +738,21 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
* Updates the number of value fields. * Updates the number of value fields.
*/ */
private void updateNumberOfValues() { private void updateNumberOfValues() {
String varname = (String) varNameCombo.getSelectedItem();
if (!moteMemory.variableExists(varname)) {
return;
}
valuePane.removeAll(); valuePane.removeAll();
JPanel linePane = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); JPanel linePane = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
DefaultFormatterFactory defac = new DefaultFormatterFactory(hf); DefaultFormatterFactory defac = new DefaultFormatterFactory(hf);
long address = moteMemory.getVariableAddress((String) varNameCombo.getSelectedItem()); long address = (varAddressField.getValue() == null) ? 0 : (long) varAddressField.getValue();
int bytes = moteMemory.getVariableSize((String) varNameCombo.getSelectedItem()); int bytes;
try {
//address = Integer.parseInt(varAddressField.getText());
bytes = Integer.parseInt(varSizeField.getText());
} catch (NumberFormatException ex) {
bytes = 0;
}
int typeSize = ((VarTypes) varTypeCombo.getSelectedItem()).getBytes(); int typeSize = ((VarTypes) varTypeCombo.getSelectedItem()).getBytes();
int elements = (int) Math.ceil((double) bytes / typeSize); int elements = (int) Math.ceil((double) bytes / typeSize);
@ -697,6 +770,14 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
} }
} }
valuePane.add(linePane); valuePane.add(linePane);
readButton.setEnabled(true);
monitorButton.setEnabled(true);
writeButton.setEnabled(true);
} else {
readButton.setEnabled(false);
monitorButton.setEnabled(false);
writeButton.setEnabled(false);
} }
refreshValues(); refreshValues();