new plugin:
plugin can be configured to break on certain events in simulation environment, for example whenever a led changes
This commit is contained in:
parent
18d9c94222
commit
34c020d87e
1 changed files with 292 additions and 0 deletions
292
tools/cooja/java/se/sics/cooja/plugins/EventListener.java
Normal file
292
tools/cooja/java/se/sics/cooja/plugins/EventListener.java
Normal file
|
@ -0,0 +1,292 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006, Swedish Institute of Computer Science. All rights
|
||||||
|
* reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer. 2. Redistributions in
|
||||||
|
* binary form must reproduce the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer in the documentation and/or other
|
||||||
|
* materials provided with the distribution. 3. Neither the name of the
|
||||||
|
* Institute nor the names of its contributors may be used to endorse or promote
|
||||||
|
* products derived from this software without specific prior written
|
||||||
|
* permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (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: EventListener.java,v 1.1 2007/01/09 09:50:52 fros4943 Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.sics.cooja.plugins;
|
||||||
|
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import se.sics.cooja.*;
|
||||||
|
import se.sics.cooja.contikimote.ContikiMoteType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EXPERIMENTAL:
|
||||||
|
*
|
||||||
|
* Allows a user to observe several different parts of the simulator, stopping a
|
||||||
|
* simulation whenever an object changes.
|
||||||
|
*
|
||||||
|
* @author Fredrik Osterlind
|
||||||
|
*/
|
||||||
|
@ClassDescription("Event Listener")
|
||||||
|
@PluginType(PluginType.SIM_PLUGIN)
|
||||||
|
public class EventListener extends VisPlugin {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static Logger logger = Logger.getLogger(EventListener.class);
|
||||||
|
|
||||||
|
private Simulation mySimulation;
|
||||||
|
|
||||||
|
private Vector<EventObserver> allObservers = new Vector<EventObserver>();
|
||||||
|
|
||||||
|
private EventListener myPlugin;
|
||||||
|
|
||||||
|
private JLabel messageLabel = null;
|
||||||
|
|
||||||
|
private JButton actionButton = null;
|
||||||
|
|
||||||
|
protected abstract class EventObserver implements Observer {
|
||||||
|
protected Observable myObservation = null;
|
||||||
|
|
||||||
|
protected EventListener myParent = null;
|
||||||
|
|
||||||
|
public EventObserver(EventListener parent, Observable objectToObserve) {
|
||||||
|
myParent = parent;
|
||||||
|
myObservation = objectToObserve;
|
||||||
|
objectToObserve.addObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop observing object (for cleaning up).
|
||||||
|
*/
|
||||||
|
public void detachFromObject() {
|
||||||
|
myObservation.deleteObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Object being observed.
|
||||||
|
*/
|
||||||
|
public Observable getObservable() {
|
||||||
|
return myObservation;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected class InterfaceEventObserver extends EventObserver {
|
||||||
|
private Mote myMote = null;
|
||||||
|
|
||||||
|
public InterfaceEventObserver(EventListener parent, Mote mote,
|
||||||
|
Observable objectToObserve) {
|
||||||
|
super(parent, objectToObserve);
|
||||||
|
myMote = mote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(Observable obs, Object obj) {
|
||||||
|
final MoteInterface moteInterface = (MoteInterface) obs;
|
||||||
|
int moteID = -1;
|
||||||
|
if (myMote.getInterfaces().getMoteID() != null)
|
||||||
|
moteID = myMote.getInterfaces().getMoteID().getMoteID();
|
||||||
|
|
||||||
|
myParent.actOnChange("'" + GUI.getDescriptionOf(moteInterface.getClass())
|
||||||
|
+ "'" + " of mote '" + (moteID > 0 ? Integer.toString(moteID) : "?")
|
||||||
|
+ "'" + " changed at time "
|
||||||
|
+ myParent.mySimulation.getSimulationTime(), new AbstractAction(
|
||||||
|
"View interface visualizer") {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
MoteInterfaceViewer plugin = (MoteInterfaceViewer) mySimulation
|
||||||
|
.getGUI().startPlugin(MoteInterfaceViewer.class,
|
||||||
|
mySimulation.getGUI(), mySimulation, myMote);
|
||||||
|
plugin.setSelectedInterface(GUI.getDescriptionOf(moteInterface
|
||||||
|
.getClass()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class GeneralEventObserver extends EventObserver {
|
||||||
|
public GeneralEventObserver(EventListener parent, Observable objectToObserve) {
|
||||||
|
super(parent, objectToObserve);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(Observable obs, Object obj) {
|
||||||
|
myParent.actOnChange("'" + GUI.getDescriptionOf(obs.getClass()) + "'"
|
||||||
|
+ " changed at time " + myParent.mySimulation.getSimulationTime(),
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new simulation control panel.
|
||||||
|
*
|
||||||
|
* @param simulationToControl
|
||||||
|
* Simulation to control
|
||||||
|
*/
|
||||||
|
public EventListener(Simulation simulationToControl, GUI gui) {
|
||||||
|
super("Event Breaker", gui);
|
||||||
|
|
||||||
|
mySimulation = simulationToControl;
|
||||||
|
myPlugin = this;
|
||||||
|
|
||||||
|
// Create selectable interfaces list (only supports Contiki mote types)
|
||||||
|
Vector<Class<? extends MoteInterface>> allMoteTypes = new Vector<Class<? extends MoteInterface>>();
|
||||||
|
Vector<Class<? extends MoteInterface>> allMoteTypesDups = new Vector<Class<? extends MoteInterface>>();
|
||||||
|
for (MoteType moteType : simulationToControl.getMoteTypes()) {
|
||||||
|
if (moteType instanceof ContikiMoteType) {
|
||||||
|
allMoteTypesDups.addAll(((ContikiMoteType) moteType)
|
||||||
|
.getMoteInterfaces());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Class<? extends MoteInterface> moteTypeClass : allMoteTypesDups) {
|
||||||
|
if (!allMoteTypes.contains(moteTypeClass)) {
|
||||||
|
allMoteTypes.add(moteTypeClass);
|
||||||
|
logger.debug("Available mote interface class: " + moteTypeClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JPanel interfacePanel = new JPanel();
|
||||||
|
interfacePanel.setLayout(new BoxLayout(interfacePanel, BoxLayout.Y_AXIS));
|
||||||
|
interfacePanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5));
|
||||||
|
for (Class<? extends MoteInterface> moteTypeClass : allMoteTypes) {
|
||||||
|
JCheckBox checkBox = new JCheckBox(GUI.getDescriptionOf(moteTypeClass),
|
||||||
|
false);
|
||||||
|
checkBox.putClientProperty("interface_class", moteTypeClass);
|
||||||
|
checkBox.addActionListener(interfaceCheckBoxListener);
|
||||||
|
|
||||||
|
interfacePanel.add(checkBox);
|
||||||
|
}
|
||||||
|
if (allMoteTypes.isEmpty()) {
|
||||||
|
interfacePanel.add(new JLabel("No used interface classes detected"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create general selectable list
|
||||||
|
JPanel generalPanel = new JPanel();
|
||||||
|
generalPanel.setLayout(new BoxLayout(generalPanel, BoxLayout.Y_AXIS));
|
||||||
|
generalPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5));
|
||||||
|
|
||||||
|
JCheckBox simCheckBox = new JCheckBox("Simulation event", false);
|
||||||
|
simCheckBox.putClientProperty("observable", mySimulation);
|
||||||
|
simCheckBox.addActionListener(generalCheckBoxListener);
|
||||||
|
generalPanel.add(simCheckBox);
|
||||||
|
|
||||||
|
JCheckBox radioMediumCheckBox = new JCheckBox("Radio medium event", false);
|
||||||
|
radioMediumCheckBox.putClientProperty("observable", mySimulation
|
||||||
|
.getRadioMedium().getRadioMediumObservable());
|
||||||
|
radioMediumCheckBox.addActionListener(generalCheckBoxListener);
|
||||||
|
generalPanel.add(radioMediumCheckBox);
|
||||||
|
|
||||||
|
// Add components
|
||||||
|
JPanel mainPanel = new JPanel();
|
||||||
|
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
|
||||||
|
setContentPane(mainPanel);
|
||||||
|
|
||||||
|
mainPanel.add(new JLabel("Break on general changes:"));
|
||||||
|
mainPanel.add(generalPanel);
|
||||||
|
|
||||||
|
mainPanel.add(new JLabel("Break on mote interface changes:"));
|
||||||
|
mainPanel.add(new JScrollPane(interfacePanel));
|
||||||
|
|
||||||
|
messageLabel = new JLabel("[no change detected yet]");
|
||||||
|
actionButton = new JButton("[no action available]");
|
||||||
|
actionButton.setEnabled(false);
|
||||||
|
mainPanel.add(new JLabel("Last message:"));
|
||||||
|
mainPanel.add(messageLabel);
|
||||||
|
mainPanel.add(actionButton);
|
||||||
|
|
||||||
|
pack();
|
||||||
|
|
||||||
|
try {
|
||||||
|
setSelected(true);
|
||||||
|
} catch (java.beans.PropertyVetoException e) {
|
||||||
|
// Could not select
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actOnChange(final String message, final Action action) {
|
||||||
|
if (!mySimulation.isRunning())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mySimulation.stopSimulation();
|
||||||
|
|
||||||
|
// Update plugin in separate thread
|
||||||
|
Thread t = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
messageLabel.setText(message);
|
||||||
|
actionButton.setAction(action);
|
||||||
|
actionButton.setVisible(action != null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionListener interfaceCheckBoxListener = new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
Class<? extends MoteInterface> interfaceClass = (Class<? extends MoteInterface>) ((JCheckBox) e
|
||||||
|
.getSource()).getClientProperty("interface_class");
|
||||||
|
boolean shouldObserve = ((JCheckBox) e.getSource()).isSelected();
|
||||||
|
|
||||||
|
if (!shouldObserve) {
|
||||||
|
// Remove existing observers
|
||||||
|
for (EventObserver obs : allObservers.toArray(new EventObserver[0])) {
|
||||||
|
if (obs.getObservable().getClass() == interfaceClass) {
|
||||||
|
obs.detachFromObject();
|
||||||
|
allObservers.remove(obs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Register new observers
|
||||||
|
for (int i = 0; i < mySimulation.getMotesCount(); i++) {
|
||||||
|
MoteInterface moteInterface = mySimulation.getMote(i).getInterfaces()
|
||||||
|
.getInterfaceOfType(interfaceClass);
|
||||||
|
allObservers.add(new InterfaceEventObserver(myPlugin, mySimulation
|
||||||
|
.getMote(i), moteInterface));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private ActionListener generalCheckBoxListener = new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
Observable observable = (Observable) ((JCheckBox) e.getSource())
|
||||||
|
.getClientProperty("observable");
|
||||||
|
boolean shouldObserve = ((JCheckBox) e.getSource()).isSelected();
|
||||||
|
|
||||||
|
if (!shouldObserve) {
|
||||||
|
// Remove existing observers
|
||||||
|
for (EventObserver obs : allObservers.toArray(new EventObserver[0])) {
|
||||||
|
if (obs.getObservable() == observable) {
|
||||||
|
obs.detachFromObject();
|
||||||
|
allObservers.remove(obs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Register new observers
|
||||||
|
allObservers.add(new GeneralEventObserver(myPlugin, observable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void closePlugin() {
|
||||||
|
// Remove all existing observers
|
||||||
|
for (EventObserver obs : allObservers) {
|
||||||
|
obs.detachFromObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue