1159 lines
40 KiB
Java
1159 lines
40 KiB
Java
/*
|
|
* Copyright (c) 2007, 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: XMLCommandHandler.java,v 1.1 2007/08/21 14:39:58 fros4943 Exp $
|
|
*/
|
|
|
|
package se.sics.chakana;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.StringReader;
|
|
import java.lang.reflect.Constructor;
|
|
import java.lang.reflect.Method;
|
|
import java.util.Collection;
|
|
import javax.swing.JFrame;
|
|
import javax.swing.JInternalFrame;
|
|
|
|
import org.apache.log4j.Logger;
|
|
import org.jdom.Document;
|
|
import org.jdom.Element;
|
|
import org.jdom.JDOMException;
|
|
import org.jdom.input.SAXBuilder;
|
|
|
|
import se.sics.chakana.EventpointEvaluator.EventpointException;
|
|
import se.sics.chakana.eventpoints.*;
|
|
import se.sics.cooja.AddressMemory;
|
|
import se.sics.cooja.CoreComm;
|
|
import se.sics.cooja.GUI;
|
|
import se.sics.cooja.Mote;
|
|
import se.sics.cooja.MoteMemory;
|
|
import se.sics.cooja.RadioMedium;
|
|
import se.sics.cooja.Simulation;
|
|
import se.sics.cooja.Mote.State;
|
|
import se.sics.cooja.MoteType.MoteTypeCreationException;
|
|
import se.sics.cooja.dialogs.MessageList;
|
|
import se.sics.cooja.plugins.VisState;
|
|
import se.sics.cooja.plugins.Visualizer2D;
|
|
import se.sics.cooja.radiomediums.UDGM;
|
|
|
|
/**
|
|
* Handles incoming XML commands.
|
|
* Each command handling call blocks during handling and returns a reply to the client.
|
|
*
|
|
* A command must always be of the form:
|
|
* <command>...</command>
|
|
*
|
|
* @author Fredrik Osterlind
|
|
*/
|
|
public class XMLCommandHandler {
|
|
public static final boolean DEBUG_OUTPUT = true;
|
|
|
|
private static Logger logger = Logger.getLogger(XMLCommandHandler.class);
|
|
|
|
public static final String XML_OK = "<ok/>";
|
|
public static final String XML_OK_START = "<ok>";
|
|
public static final String XML_OK_END = "</ok>";
|
|
|
|
public static final String XML_INFO_START = "<info>";
|
|
public static final String XML_INFO_END = "</info>";
|
|
public static final String XML_ERROR_START = "<error>";
|
|
public static final String XML_ERROR_END = "</error>";
|
|
|
|
public static final String XML_COMMAND_NAME = "command";
|
|
public static final String XML_COMMAND_END = "</command>";
|
|
|
|
public static final String XML_EVENTPOINT_START = "<eventpoint>";
|
|
public static final String XML_EVENTPOINT_END = "</eventpoint>";
|
|
|
|
public static final String XML_ID_NAME = "id";
|
|
public static final String XML_TYPE_NAME = "type";
|
|
public static final String XML_MOTE_NAME = "mote";
|
|
public static final String XML_VARIABLE_NAME = "variable";
|
|
public static final String XML_MOTECOUNT_NAME = "motecount";
|
|
public static final String XML_VALUE_NAME = "value";
|
|
public static final String XML_TIME_NAME = "time";
|
|
public static final String XML_SIZE_NAME = "size";
|
|
public static final String XML_ADDRESS_NAME = "address";
|
|
public static final String XML_VISIBLE_NAME = "visible";
|
|
public static final String XML_TRIGGERON_NAME = "triggeron";
|
|
public static final String XML_WATCHPOINT_INT = "int";
|
|
public static final String XML_WATCHPOINT_VARIABLE = "variable";
|
|
public static final String XML_WATCHPOINT_ADDRESS = "address";
|
|
public static final String XML_TIMEPOINT_SIMULATION = "time";
|
|
public static final String XML_TIMEPOINT_REAL = "realtime";
|
|
public static final String XML_EVENTPOINT_RADIOMEDIUM = "radiomedium";
|
|
|
|
private GUI myGUI;
|
|
private EventpointEvaluator myEvaluator;
|
|
private ChakanaPlugin myParent;
|
|
|
|
public enum Command {
|
|
CREATE_SIM,
|
|
CONF_SIM,
|
|
CONF_PLUGINS,
|
|
CONTROL_SIM,
|
|
SET_GUI,
|
|
ADD_EVENTPOINT,
|
|
READ_MEMORY,
|
|
WRITE_MEMORY,
|
|
CLEAR_EVENTPOINTS,
|
|
DELETE_EVENTPOINT,
|
|
KILL_NODES,
|
|
GET_INFO,
|
|
CUSTOM_COMMAND,
|
|
EXIT_COOJA;
|
|
}
|
|
|
|
public enum ControlSimulationCommand {
|
|
RESUME;
|
|
}
|
|
|
|
/**
|
|
* TODO Document
|
|
*
|
|
* @param gui
|
|
* @param parent
|
|
* @param evaluator
|
|
*/
|
|
public XMLCommandHandler(GUI gui, ChakanaPlugin parent, EventpointEvaluator evaluator) {
|
|
myGUI = gui;
|
|
myEvaluator = evaluator;
|
|
myParent = parent;
|
|
}
|
|
|
|
/**
|
|
* @param command
|
|
* @return
|
|
*/
|
|
public boolean containsEntireCommand(String command) {
|
|
return command.contains(XMLCommandHandler.XML_COMMAND_END); // TODO Ugly trick
|
|
}
|
|
|
|
/**
|
|
* Handle given command (XML format).
|
|
* Method blocks until given command has been handled.
|
|
*
|
|
* @param command
|
|
* Command to handle
|
|
* @return Reply to client in XML format
|
|
*/
|
|
public String handleCommand(String command) {
|
|
try {
|
|
SAXBuilder builder = new SAXBuilder();
|
|
Document doc = builder.build(new StringReader(command));
|
|
Element root = doc.getRootElement();
|
|
|
|
if (!root.getName().equals(XML_COMMAND_NAME)) {
|
|
return createErrorMessage("Malformed command: " + root.getName());
|
|
}
|
|
|
|
String cmdTypeString = root.getAttributeValue("value");
|
|
Command cmdType;
|
|
try {
|
|
cmdType = Command.valueOf(cmdTypeString);
|
|
} catch (IllegalArgumentException e) {
|
|
return createErrorMessage("Unknown command: " + cmdTypeString);
|
|
}
|
|
|
|
Collection<Element> cmdInfo = root.getChildren();
|
|
|
|
logger.debug("Command type: " + cmdType);
|
|
switch (cmdType) {
|
|
case CREATE_SIM:
|
|
return createSimulation(cmdInfo);
|
|
case CONF_SIM:
|
|
return configureSimulation(cmdInfo);
|
|
case CONF_PLUGINS:
|
|
return configurePlugins(cmdInfo);
|
|
case CONTROL_SIM:
|
|
return controlSimulation(cmdInfo);
|
|
case ADD_EVENTPOINT:
|
|
return addEventpoint(cmdInfo);
|
|
case SET_GUI:
|
|
return configureGUI(cmdInfo);
|
|
case READ_MEMORY:
|
|
return readMemory(cmdInfo);
|
|
case WRITE_MEMORY:
|
|
return writeMemory(cmdInfo);
|
|
case CLEAR_EVENTPOINTS:
|
|
return clearEventpoints();
|
|
case DELETE_EVENTPOINT:
|
|
return deleteEventpoint(cmdInfo);
|
|
case KILL_NODES:
|
|
return killNodes(cmdInfo);
|
|
case GET_INFO:
|
|
return getInfo(cmdInfo);
|
|
case CUSTOM_COMMAND:
|
|
return handleCustomCommand(cmdInfo);
|
|
case EXIT_COOJA:
|
|
return shutdownCOOJA(cmdInfo);
|
|
default:
|
|
return createErrorMessage("Unknown command: " + cmdType);
|
|
}
|
|
} catch (JDOMException e) {
|
|
logger.fatal("Command parsing exception: " + e);
|
|
return createErrorMessage("Invalid command syntax: " + e.getMessage());
|
|
} catch (IOException e) {
|
|
logger.fatal("Command parsing exception: " + e);
|
|
return createErrorMessage("Invalid command syntax: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle create new simulation command.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String createSimulation(Collection<Element> arguments) {
|
|
Simulation simulation = new Simulation(myGUI);
|
|
simulation.setTitle("[chakana - no title]");
|
|
simulation.setDelayTime(0);
|
|
simulation.setSimulationTime(0);
|
|
simulation.setTickTime(1);
|
|
|
|
try {
|
|
RadioMedium radioMedium = RadioMedium.generateRadioMedium(UDGM.class,
|
|
simulation);
|
|
simulation.setRadioMedium(radioMedium);
|
|
} catch (Exception e) {
|
|
return createErrorMessage("Create simulation: Could not create radio medium: " + e.getMessage());
|
|
}
|
|
|
|
// Let simulation parse command arguments
|
|
myGUI.setSimulation(simulation);
|
|
try {
|
|
boolean success = simulation.setConfigXML(arguments, false);
|
|
} catch (Exception e) {
|
|
logger.fatal("Error when configuring simulation: " + e);
|
|
if (DEBUG_OUTPUT) {
|
|
if (e instanceof MoteTypeCreationException) {
|
|
MessageList compilationOutput = ((MoteTypeCreationException) e).getCompilationOutput();
|
|
if (compilationOutput != null) {
|
|
logger.info("Compilation output:");
|
|
for(int i = 0; i < compilationOutput.getModel().getSize(); i++) {
|
|
logger.info(compilationOutput.getModel().getElementAt(i));
|
|
}
|
|
}
|
|
StackTraceElement[] stackTrace = e.getStackTrace();
|
|
if (stackTrace != null) {
|
|
logger.info("Stack trace:");
|
|
for(StackTraceElement element: stackTrace) {
|
|
logger.info(element);
|
|
}
|
|
}
|
|
GUI.showErrorDialog(new JFrame(""), "Set DEBUG_OUTPUT to false to disable this frame", e, false); // XXX Graphical component
|
|
}
|
|
}
|
|
return createErrorMessage("Create simulation: Could not configure simulation: " + e.getMessage());
|
|
}
|
|
|
|
return XML_OK;
|
|
}
|
|
|
|
/**
|
|
* Handle configure simulation command.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String configureSimulation(Collection<Element> arguments) {
|
|
Simulation simulation = myGUI.getSimulation();
|
|
|
|
// Let simulation parse command arguments
|
|
try {
|
|
simulation.setConfigXML(arguments, false);
|
|
} catch (Exception e) {
|
|
logger.fatal("Error when configuring simulation: " + e);
|
|
e.printStackTrace();
|
|
return createErrorMessage("Could not configure simulation: " + e.getMessage());
|
|
}
|
|
return XML_OK;
|
|
}
|
|
|
|
/**
|
|
* Handle configure plugins command.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String configurePlugins(Collection<Element> arguments) {
|
|
Simulation simulation = myGUI.getSimulation();
|
|
|
|
// Let GUI parse command arguments
|
|
try {
|
|
myGUI.setPluginsConfigXML(arguments, simulation, false);
|
|
} catch (Exception e) {
|
|
logger.fatal("Error when configuring plugins: " + e);
|
|
return createErrorMessage("Could not configure plugins: " + e.getMessage());
|
|
}
|
|
|
|
return XML_OK;
|
|
}
|
|
|
|
/**
|
|
* Handle control simulation command.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String controlSimulation(Collection<Element> arguments) {
|
|
String reply = "";
|
|
|
|
for (Element element : arguments) {
|
|
ControlSimulationCommand cmdType;
|
|
try {
|
|
cmdType = ControlSimulationCommand.valueOf(element.getName());
|
|
} catch (IllegalArgumentException e) {
|
|
return createErrorMessage("Unknown simulation control command: " + element.getName());
|
|
}
|
|
|
|
switch (cmdType) {
|
|
case RESUME:
|
|
// TODO Check performance degradation using try-blocks
|
|
try {
|
|
myEvaluator.resumeSimulation();
|
|
reply += createEventpointMessage(myEvaluator);
|
|
} catch (EventpointException e) {
|
|
return createErrorMessage("Exception during simulation: " + e);
|
|
}
|
|
break;
|
|
default:
|
|
return createErrorMessage("Unknown simulation control command");
|
|
}
|
|
}
|
|
return reply;
|
|
}
|
|
|
|
/**
|
|
* Handle exit COOJA command.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String shutdownCOOJA(Collection<Element> arguments) {
|
|
myParent.performCOOJAShutdown();
|
|
logger.info("Shutdown requested");
|
|
return XML_OK;
|
|
}
|
|
|
|
/**
|
|
* Fetch mote variable value as specified by arguments.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String readMemory(Collection<Element> arguments) {
|
|
Simulation simulation = myGUI.getSimulation();
|
|
|
|
String type = null;
|
|
String mote = null;
|
|
String variable = null;
|
|
String size = null;
|
|
String address = null;
|
|
|
|
for (Element element : arguments) {
|
|
if (element.getName().equals(XML_TYPE_NAME)) {
|
|
type = element.getText();
|
|
} else if (element.getName().equals(XML_MOTE_NAME)) {
|
|
mote = element.getText();
|
|
} else if (element.getName().equals(XML_VARIABLE_NAME)) {
|
|
variable = element.getText();
|
|
} else if (element.getName().equals(XML_SIZE_NAME)) {
|
|
size = element.getText();
|
|
} else if (element.getName().equals(XML_ADDRESS_NAME)) {
|
|
address = element.getText();
|
|
} else {
|
|
return createErrorMessage("Unknown read memory parameter: " + element.getName());
|
|
}
|
|
}
|
|
|
|
if (type == null)
|
|
return createErrorMessage("No read memory type specified");
|
|
if (mote == null)
|
|
return createErrorMessage("No mote specified");
|
|
|
|
if (mote == null)
|
|
return createErrorMessage("No mote ID specified");
|
|
int moteNr = Integer.parseInt(mote);
|
|
if (moteNr < 0 || simulation.getMotesCount() <= moteNr) {
|
|
return createErrorMessage("Bad mote ID specified: " + moteNr);
|
|
}
|
|
MoteMemory memory = simulation.getMote(moteNr).getMemory();
|
|
|
|
// Read integer variable
|
|
if (type.equals("int")) {
|
|
if (variable == null)
|
|
return createErrorMessage("No variable name specified");
|
|
if (variable.contains(" "))
|
|
return createErrorMessage("Variable name must not contain spaces: " + variable);
|
|
|
|
if (!(memory instanceof AddressMemory))
|
|
return createErrorMessage("Can't read mote memory variables (not address memory)");
|
|
|
|
if (!((AddressMemory) memory).variableExists(variable)) {
|
|
return createErrorMessage("Variable does not exist: " + variable);
|
|
}
|
|
|
|
int val = ((AddressMemory) memory).getIntValueOf(variable);
|
|
return XML_OK_START + val + XML_OK_END;
|
|
} else if (type.equals("variable")) {
|
|
if (variable == null)
|
|
return createErrorMessage("No variable name specified");
|
|
if (variable.contains(" "))
|
|
return createErrorMessage("Variable name must not contain spaces: " + variable);
|
|
|
|
if (!(memory instanceof AddressMemory))
|
|
return createErrorMessage("Can't read mote memory variables (not address memory)");
|
|
|
|
if (!((AddressMemory) memory).variableExists(variable)) {
|
|
return createErrorMessage("Variable does not exist: " + variable);
|
|
}
|
|
|
|
if (size == null)
|
|
return createErrorMessage("No size specified");
|
|
int sizeParsed = Integer.parseInt(size);
|
|
if (sizeParsed < 0) {
|
|
return createErrorMessage("Bad size specified: " + sizeParsed);
|
|
}
|
|
|
|
byte[] val = ((AddressMemory) memory).getByteArray(variable, sizeParsed);
|
|
String ret = "";
|
|
for (byte b: val)
|
|
ret += (int) (0xff&b) + " ";
|
|
ret = ret.trim();
|
|
return XML_OK_START + ret + XML_OK_END;
|
|
} else if (type.equals("address")) {
|
|
|
|
if (size == null)
|
|
return createErrorMessage("No size specified");
|
|
int sizeParsed = Integer.parseInt(size);
|
|
if (sizeParsed < 0) {
|
|
return createErrorMessage("Bad size specified: " + sizeParsed);
|
|
}
|
|
|
|
int addressParsed = Integer.parseInt(address);
|
|
if (addressParsed < 0) {
|
|
return createErrorMessage("Bad start address specified: " + addressParsed);
|
|
}
|
|
|
|
byte[] val = memory.getMemorySegment(addressParsed, sizeParsed);
|
|
String ret = "";
|
|
for (byte b: val)
|
|
ret += (int) (0xff&b) + " ";
|
|
ret = ret.trim();
|
|
return XML_OK_START + ret + XML_OK_END;
|
|
}
|
|
|
|
return createErrorMessage("Bad read memory type specified: " + type);
|
|
}
|
|
|
|
/**
|
|
* Write mote variable value as specified by arguments.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String writeMemory(Collection<Element> arguments) {
|
|
Simulation simulation = myGUI.getSimulation();
|
|
|
|
String type = null;
|
|
String mote = null;
|
|
String variable = null;
|
|
String size = null;
|
|
String address = null;
|
|
String value = null;
|
|
|
|
for (Element element : arguments) {
|
|
if (element.getName().equals(XML_TYPE_NAME)) {
|
|
type = element.getText();
|
|
} else if (element.getName().equals(XML_MOTE_NAME)) {
|
|
mote = element.getText();
|
|
} else if (element.getName().equals(XML_VARIABLE_NAME)) {
|
|
variable = element.getText();
|
|
} else if (element.getName().equals(XML_SIZE_NAME)) {
|
|
size = element.getText();
|
|
} else if (element.getName().equals(XML_ADDRESS_NAME)) {
|
|
address = element.getText();
|
|
} else if (element.getName().equals(XML_VALUE_NAME)) {
|
|
value = element.getText();
|
|
} else {
|
|
return createErrorMessage("Unknown write memory parameter: " + element.getName());
|
|
}
|
|
}
|
|
|
|
if (type == null)
|
|
return createErrorMessage("No write memory type specified");
|
|
if (mote == null)
|
|
return createErrorMessage("No mote specified");
|
|
|
|
if (mote == null)
|
|
return createErrorMessage("No mote ID specified");
|
|
int moteNr = Integer.parseInt(mote);
|
|
if (moteNr < 0 || simulation.getMotesCount() <= moteNr) {
|
|
return createErrorMessage("Bad mote ID specified: " + moteNr);
|
|
}
|
|
MoteMemory memory = simulation.getMote(moteNr).getMemory();
|
|
|
|
// Write integer variable
|
|
if (type.equals("int")) {
|
|
if (variable == null)
|
|
return createErrorMessage("No variable name specified");
|
|
if (variable.contains(" "))
|
|
return createErrorMessage("Variable name must not contain spaces: " + variable);
|
|
|
|
if (!(memory instanceof AddressMemory))
|
|
return createErrorMessage("Can't read mote memory variables (not address memory)");
|
|
|
|
if (!((AddressMemory) memory).variableExists(variable)) {
|
|
return createErrorMessage("Variable does not exist: " + variable);
|
|
}
|
|
|
|
if (value == null)
|
|
return createErrorMessage("No value specified");
|
|
if (value.contains(" "))
|
|
return createErrorMessage("Integer value must not contain spaces: " + value);
|
|
|
|
int val;
|
|
try {
|
|
val = Integer.parseInt(value);
|
|
} catch (NumberFormatException e) {
|
|
return createErrorMessage("Bad integer value specified: " + e);
|
|
}
|
|
|
|
((AddressMemory) memory).setIntValueOf(variable, val);
|
|
return XML_OK;
|
|
} else if (type.equals("variable")) {
|
|
if (variable == null)
|
|
return createErrorMessage("No variable name specified");
|
|
if (variable.contains(" "))
|
|
return createErrorMessage("Variable name must not contain spaces: " + variable);
|
|
|
|
if (!(memory instanceof AddressMemory))
|
|
return createErrorMessage("Can't read mote memory variables (not address memory)");
|
|
|
|
if (!((AddressMemory) memory).variableExists(variable)) {
|
|
return createErrorMessage("Variable does not exist: " + variable);
|
|
}
|
|
|
|
if (size == null)
|
|
return createErrorMessage("No size specified");
|
|
int sizeParsed = Integer.parseInt(size);
|
|
if (sizeParsed < 0) {
|
|
return createErrorMessage("Bad size specified: " + sizeParsed);
|
|
}
|
|
|
|
if (value == null)
|
|
return createErrorMessage("No value specified");
|
|
String[] bytesParsed = value.split(" ");
|
|
if (bytesParsed.length != sizeParsed)
|
|
return createErrorMessage("Number of bytes and specified size does not match: " + bytesParsed.length + "!=" + sizeParsed);
|
|
|
|
byte[] val = new byte[bytesParsed.length];
|
|
for (int i=0; i < sizeParsed; i++) {
|
|
val[i] = Byte.parseByte(bytesParsed[i]);
|
|
}
|
|
|
|
((AddressMemory) memory).setByteArray(variable, val);
|
|
return XML_OK;
|
|
} else if (type.equals("address")) {
|
|
|
|
if (size == null)
|
|
return createErrorMessage("No size specified");
|
|
int sizeParsed = Integer.parseInt(size);
|
|
if (sizeParsed < 0) {
|
|
return createErrorMessage("Bad size specified: " + sizeParsed);
|
|
}
|
|
|
|
int addressParsed = Integer.parseInt(address);
|
|
if (addressParsed < 0) {
|
|
return createErrorMessage("Bad start address specified: " + addressParsed);
|
|
}
|
|
|
|
if (value == null)
|
|
return createErrorMessage("No value specified");
|
|
String[] bytesParsed = value.split(" ");
|
|
if (bytesParsed.length != sizeParsed)
|
|
return createErrorMessage("Number of bytes and specified size does not match: " + bytesParsed.length + "!=" + sizeParsed);
|
|
|
|
byte[] val = new byte[bytesParsed.length];
|
|
for (int i=0; i < sizeParsed; i++) {
|
|
val[i] = Byte.parseByte(bytesParsed[i]);
|
|
}
|
|
|
|
memory.setMemorySegment(addressParsed, val);
|
|
return XML_OK;
|
|
}
|
|
|
|
return createErrorMessage("Bad write memory type specified: " + type);
|
|
}
|
|
|
|
/**
|
|
* Handle add new eventpoint command.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String addEventpoint(Collection<Element> arguments) {
|
|
Simulation simulation = myGUI.getSimulation();
|
|
|
|
String type = null;
|
|
String mote = null;
|
|
String variable = null;
|
|
String time = null;
|
|
String size = null;
|
|
String triggeron = null;
|
|
String address = null;
|
|
String count = null;
|
|
|
|
for (Element element : arguments) {
|
|
if (element.getName().equals(XML_TYPE_NAME)) {
|
|
type = element.getText();
|
|
} else if (element.getName().equals(XML_MOTE_NAME)) {
|
|
mote = element.getText();
|
|
} else if (element.getName().equals(XML_VARIABLE_NAME)) {
|
|
variable = element.getText();
|
|
} else if (element.getName().equals(XML_TIME_NAME)) {
|
|
time = element.getText();
|
|
} else if (element.getName().equals(XML_SIZE_NAME)) {
|
|
size = element.getText();
|
|
} else if (element.getName().equals(XML_ADDRESS_NAME)) {
|
|
address = element.getText();
|
|
} else if (element.getName().equals(XML_TRIGGERON_NAME)) {
|
|
triggeron = element.getText();
|
|
} else if (element.getName().equals("count")) {
|
|
count = element.getText();
|
|
} else {
|
|
return createErrorMessage("Unknown eventpoint parameter: " + element.getName());
|
|
}
|
|
}
|
|
|
|
logger.debug("Eventpoint type: " + type);
|
|
if (type == null)
|
|
return createErrorMessage("No eventpoint type specified");
|
|
|
|
// Integer variable watchpoint
|
|
if (type.equals(XML_WATCHPOINT_INT)) {
|
|
if (variable == null)
|
|
return createErrorMessage("No variable name specified");
|
|
if (variable.contains(" "))
|
|
return createErrorMessage("Variable name must not contain spaces: " + variable);
|
|
if (mote == null)
|
|
return createErrorMessage("No mote ID specified");
|
|
int moteNr = Integer.parseInt(mote);
|
|
if (moteNr < 0 || simulation.getMotesCount() <= moteNr) {
|
|
return createErrorMessage("Bad mote ID specified: " + moteNr);
|
|
}
|
|
Mote moteObject = simulation.getMote(moteNr);
|
|
|
|
MoteMemory memory = simulation.getMote(moteNr).getMemory();
|
|
|
|
if (!(memory instanceof AddressMemory))
|
|
return createErrorMessage("Can't write mote memory variables (not address memory)");
|
|
|
|
if (!((AddressMemory) memory).variableExists(variable)) {
|
|
return createErrorMessage("Variable does not exist: " + variable);
|
|
}
|
|
|
|
Eventpoint newEventpoint = new IntegerWatchpoint(moteObject, variable);
|
|
myEvaluator.addEventpoint(newEventpoint);
|
|
return createOkMessage(newEventpoint, simulation.getSimulationTime());
|
|
}
|
|
|
|
// Variable watchpoint
|
|
if (type.equals(XML_WATCHPOINT_VARIABLE)) {
|
|
if (variable == null)
|
|
return createErrorMessage("No variable name specified");
|
|
if (variable.contains(" "))
|
|
return createErrorMessage("Variable name must not contain spaces: " + variable);
|
|
if (mote == null)
|
|
return createErrorMessage("No mote ID specified");
|
|
if (size == null)
|
|
return createErrorMessage("No size specified");
|
|
int sizeParsed = Integer.parseInt(size);
|
|
if (sizeParsed < 0) {
|
|
return createErrorMessage("Bad size specified: " + sizeParsed);
|
|
}
|
|
int moteNr = Integer.parseInt(mote);
|
|
if (moteNr < 0 || simulation.getMotesCount() <= moteNr) {
|
|
return createErrorMessage("Bad mote ID specified: " + moteNr);
|
|
}
|
|
Mote moteObject = simulation.getMote(moteNr);
|
|
|
|
MoteMemory memory = simulation.getMote(moteNr).getMemory();
|
|
|
|
if (!(memory instanceof AddressMemory))
|
|
return createErrorMessage("Can't write mote memory variables (not address memory)");
|
|
|
|
if (!((AddressMemory) memory).variableExists(variable)) {
|
|
return createErrorMessage("Variable does not exist: " + variable);
|
|
}
|
|
|
|
Eventpoint newEventpoint = new VariableWatchpoint(moteObject, variable, sizeParsed);
|
|
myEvaluator.addEventpoint(newEventpoint);
|
|
return createOkMessage(newEventpoint, simulation.getSimulationTime());
|
|
}
|
|
|
|
|
|
// Memory area watchpoint
|
|
if (type.equals(XML_WATCHPOINT_ADDRESS)) {
|
|
if (mote == null)
|
|
return createErrorMessage("No mote ID specified");
|
|
if (size == null)
|
|
return createErrorMessage("No size specified");
|
|
int sizeParsed = Integer.parseInt(size);
|
|
if (sizeParsed < 0) {
|
|
return createErrorMessage("Bad size specified: " + sizeParsed);
|
|
}
|
|
int addressParsed = Integer.parseInt(address);
|
|
if (addressParsed < 0) {
|
|
return createErrorMessage("Bad start address specified: " + addressParsed);
|
|
}
|
|
int moteNr = Integer.parseInt(mote);
|
|
if (moteNr < 0 || simulation.getMotesCount() <= moteNr) {
|
|
return createErrorMessage("Bad mote ID specified: " + moteNr);
|
|
}
|
|
Mote moteObject = simulation.getMote(moteNr);
|
|
MoteMemory memory = simulation.getMote(moteNr).getMemory();
|
|
|
|
Eventpoint newEventpoint = new Watchpoint(moteObject, addressParsed, sizeParsed);
|
|
myEvaluator.addEventpoint(newEventpoint);
|
|
return createOkMessage(newEventpoint, simulation.getSimulationTime());
|
|
}
|
|
|
|
// Simulation timepoint
|
|
if (type.equals(XML_TIMEPOINT_SIMULATION)) {
|
|
if (time == null)
|
|
return createErrorMessage("No time specified");
|
|
int timeParsed = Integer.parseInt(time);
|
|
if (timeParsed < 0) {
|
|
return createErrorMessage("Bad time specified: " + timeParsed);
|
|
}
|
|
|
|
Eventpoint newEventpoint = new SimulationTimepoint(simulation, timeParsed);
|
|
myEvaluator.addEventpoint(newEventpoint);
|
|
return createOkMessage(newEventpoint, simulation.getSimulationTime());
|
|
}
|
|
|
|
// Real timepoint
|
|
if (type.equals(XML_TIMEPOINT_REAL)) {
|
|
if (time == null)
|
|
return createErrorMessage("No time specified");
|
|
long timeParsed = Long.parseLong(time);
|
|
if (timeParsed < 0) {
|
|
return createErrorMessage("Bad time specified: " + timeParsed);
|
|
}
|
|
|
|
Eventpoint newEventpoint = new RealTimepoint(timeParsed);
|
|
myEvaluator.addEventpoint(newEventpoint);
|
|
return createOkMessage(newEventpoint, simulation.getSimulationTime());
|
|
}
|
|
|
|
// Radio medium event point
|
|
if (type.equals(XML_EVENTPOINT_RADIOMEDIUM)) {
|
|
int countInt;
|
|
try {
|
|
countInt = Integer.parseInt(count);
|
|
} catch (NumberFormatException e) {
|
|
return createErrorMessage("Bad count specified: " + e);
|
|
}
|
|
|
|
if (triggeron == null || triggeron.equals("all")) {
|
|
Eventpoint newEventpoint = new RadioMediumEventpoint(simulation.getRadioMedium(), countInt);
|
|
myEvaluator.addEventpoint(newEventpoint);
|
|
return createOkMessage(newEventpoint, simulation.getSimulationTime());
|
|
} else if (triggeron.equals("completed")) {
|
|
Eventpoint newEventpoint = new TransmissionRadioMediumEventpoint(simulation.getRadioMedium(), countInt);
|
|
myEvaluator.addEventpoint(newEventpoint);
|
|
return createOkMessage(newEventpoint, simulation.getSimulationTime());
|
|
} else {
|
|
return createErrorMessage("Bad trigger on parameter: " + triggeron);
|
|
}
|
|
}
|
|
|
|
return createErrorMessage("Bad eventpoint type specified: " + type);
|
|
}
|
|
|
|
/**
|
|
* Handle configure GUI command.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String configureGUI(Collection<Element> arguments) {
|
|
String visible = null;
|
|
|
|
for (Element element : arguments) {
|
|
if (element.getName().equals(XML_VISIBLE_NAME)) {
|
|
visible = element.getText();
|
|
} else {
|
|
return createErrorMessage("Unknown GUI configure parameter: " + element.getName());
|
|
}
|
|
}
|
|
|
|
boolean shouldBeVisible = Boolean.parseBoolean(visible);
|
|
if (myGUI.isVisualized() != shouldBeVisible) {
|
|
myGUI.setVisualized(shouldBeVisible);
|
|
}
|
|
return XML_OK;
|
|
}
|
|
|
|
/**
|
|
* Handle delete eventpoint command.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String deleteEventpoint(Collection<Element> arguments) {
|
|
String id = null;
|
|
|
|
for (Element element : arguments) {
|
|
if (element.getName().equals(XML_ID_NAME)) {
|
|
id = element.getText();
|
|
} else {
|
|
return createErrorMessage("Unknown eventpoint parameter: " + element.getName());
|
|
}
|
|
}
|
|
|
|
int idInt;
|
|
try {
|
|
idInt = Integer.parseInt(id);
|
|
} catch (NumberFormatException e) {
|
|
return createErrorMessage("Bad eventpoint ID specified: " + e);
|
|
}
|
|
|
|
Eventpoint eventpoint = myEvaluator.getEventpoint(idInt);
|
|
if (eventpoint == null)
|
|
return createErrorMessage("No eventpoint with ID " + idInt + " exists");
|
|
|
|
myEvaluator.deleteEventpoint(idInt);
|
|
return XML_OK;
|
|
}
|
|
|
|
/**
|
|
* Handle kill nodes command.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String killNodes(Collection<Element> arguments) {
|
|
String lowId = null;
|
|
String highId = null;
|
|
|
|
for (Element element : arguments) {
|
|
if (element.getName().equals("lowmote")) {
|
|
lowId = element.getText();
|
|
} else if (element.getName().equals("highmote")) {
|
|
highId = element.getText();
|
|
} else {
|
|
return createErrorMessage("Unknown eventpoint parameter: " + element.getName());
|
|
}
|
|
}
|
|
|
|
int lowIdInt;
|
|
int highIdInt;
|
|
try {
|
|
lowIdInt = Integer.parseInt(lowId);
|
|
highIdInt = Integer.parseInt(highId);
|
|
} catch (NumberFormatException e) {
|
|
return createErrorMessage("Bad mote interval specified: " + e);
|
|
}
|
|
|
|
if (lowIdInt > highIdInt)
|
|
return createErrorMessage("Bad mote interval specified: Low ID must be <= than high ID");
|
|
|
|
if (lowIdInt < 0)
|
|
return createErrorMessage("Bad mote interval specified: Low ID >= 0");
|
|
|
|
if (myGUI.getSimulation() == null)
|
|
return createErrorMessage("No simulation exists");
|
|
|
|
if (myGUI.getSimulation().getMotesCount() < highIdInt)
|
|
return createErrorMessage("Bad mote interval specified: Only " + myGUI.getSimulation().getMotesCount() + " motes exist");
|
|
|
|
for (int pos=lowIdInt; pos <= highIdInt; pos++) {
|
|
Mote mote = myGUI.getSimulation().getMote(pos);
|
|
mote.setState(State.DEAD);
|
|
}
|
|
return XML_OK;
|
|
}
|
|
|
|
/**
|
|
* Handle get info command.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String getInfo(Collection<Element> arguments) {
|
|
Simulation simulation = myGUI.getSimulation();
|
|
String type = null;
|
|
String mote = null;
|
|
String variable = null;
|
|
|
|
for (Element element : arguments) {
|
|
if (element.getName().equals(XML_TYPE_NAME)) {
|
|
type = element.getText();
|
|
} else if (element.getName().equals(XML_MOTE_NAME)) {
|
|
mote = element.getText();
|
|
} else if (element.getName().equals(XML_VARIABLE_NAME)) {
|
|
variable = element.getText();
|
|
} else {
|
|
return createErrorMessage("Unknown info parameter: " + element.getName());
|
|
}
|
|
}
|
|
|
|
if (type.equals("motestate")) {
|
|
if (mote == null)
|
|
return createErrorMessage("No mote ID specified");
|
|
int moteNr = Integer.parseInt(mote);
|
|
if (moteNr < 0 || simulation.getMotesCount() <= moteNr) {
|
|
return createErrorMessage("Bad mote ID specified: " + moteNr);
|
|
}
|
|
|
|
State state = simulation.getMote(moteNr).getState();
|
|
if (state == State.DEAD)
|
|
return XML_OK_START + 0 + XML_OK_END;
|
|
return XML_OK_START + 1 + XML_OK_END;
|
|
|
|
} else if (type.equals("time")) {
|
|
return XML_OK_START + myGUI.getSimulation().getSimulationTime() + XML_OK_END;
|
|
} else if (type.equals(XML_MOTECOUNT_NAME)) {
|
|
return XML_OK_START + myGUI.getSimulation().getMotesCount() + XML_OK_END;
|
|
} else if (type.equals("var_address")) {
|
|
if (variable == null)
|
|
return createErrorMessage("No variable name specified");
|
|
if (variable.contains(" "))
|
|
return createErrorMessage("Variable name must not contain spaces: " + variable);
|
|
if (mote == null)
|
|
return createErrorMessage("No mote ID specified");
|
|
int moteNr = Integer.parseInt(mote);
|
|
if (moteNr < 0 || simulation.getMotesCount() <= moteNr) {
|
|
return createErrorMessage("Bad mote ID specified: " + moteNr);
|
|
}
|
|
Mote moteObject = simulation.getMote(moteNr);
|
|
MoteMemory memory = simulation.getMote(moteNr).getMemory();
|
|
|
|
if (!(memory instanceof AddressMemory))
|
|
return createErrorMessage("Can't read mote memory variable address (not address memory)");
|
|
|
|
if (!((AddressMemory) memory).variableExists(variable)) {
|
|
return createErrorMessage("Variable does not exist: " + variable);
|
|
}
|
|
|
|
int address = ((AddressMemory) memory).getVariableAddress(variable);
|
|
return XML_OK_START + address + XML_OK_END;
|
|
}
|
|
|
|
return createErrorMessage("Unknown type: " + type);
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle custom command.
|
|
*
|
|
* @param arguments Command arguments
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String handleCustomCommand(Collection<Element> arguments) {
|
|
Simulation simulation = myGUI.getSimulation();
|
|
String action = null;
|
|
int id = -1;
|
|
int visible = -1;
|
|
int hide = -1;
|
|
|
|
for (Element element : arguments) {
|
|
if (element.getName().equals("action")) {
|
|
action = element.getText();
|
|
} else if (element.getName().equals("id")) {
|
|
String idString = element.getText();
|
|
id = Integer.parseInt(idString);
|
|
} else if (element.getName().equals("hide")) {
|
|
String hideString = element.getText();
|
|
hide = Integer.parseInt(hideString);
|
|
} else if (element.getName().equals("visible")) {
|
|
String visibleString = element.getText();
|
|
visible = Integer.parseInt(visibleString);
|
|
} else {
|
|
return createErrorMessage("Unknown info parameter: " + element.getName());
|
|
}
|
|
}
|
|
|
|
if (action.equals("CLICK_SINK")) {
|
|
simulation.getMote(0).getInterfaces().getButton().clickButton();
|
|
return XML_OK;
|
|
}
|
|
|
|
if (action.equals("SHOW_FIRE")) {
|
|
if (!simulation.getGUI().isVisualized())
|
|
return XML_OK;
|
|
|
|
JInternalFrame[] allPlugins = simulation.getGUI().getDesktopPane().getAllFrames();
|
|
|
|
try {
|
|
Class<Visualizer2D> pluginClass = (Class<Visualizer2D>) simulation.getGUI().tryLoadClass(this, Visualizer2D.class, "se.sics.runes.RunesVis");
|
|
Class[] parameterTypes = new Class[1];
|
|
parameterTypes[0] = Boolean.TYPE;
|
|
Method method = pluginClass.getMethod("showFire", parameterTypes);
|
|
Object[] parameterArguments = new Object[1];
|
|
parameterArguments[0] = new Boolean(visible==1?true:false);
|
|
|
|
for (JInternalFrame plugin: allPlugins) {
|
|
if (plugin.getClass() == pluginClass) {
|
|
method.invoke(plugin, parameterArguments);
|
|
}
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
return createErrorMessage("Exception: " + e.getMessage());
|
|
}
|
|
return XML_OK;
|
|
}
|
|
|
|
if (action.equals("RESET_COLORS")) {
|
|
if (!simulation.getGUI().isVisualized())
|
|
return XML_OK;
|
|
|
|
JInternalFrame[] allPlugins = simulation.getGUI().getDesktopPane().getAllFrames();
|
|
|
|
try {
|
|
Class<Visualizer2D> pluginClass = (Class<Visualizer2D>) simulation.getGUI().tryLoadClass(this, Visualizer2D.class, "se.sics.runes.RunesVis");
|
|
Class[] parameterTypes = new Class[0];
|
|
Method method = pluginClass.getMethod("resetColors", parameterTypes);
|
|
Object[] parameterArguments = new Object[0];
|
|
|
|
for (JInternalFrame plugin: allPlugins) {
|
|
if (plugin.getClass() == pluginClass) {
|
|
method.invoke(plugin, parameterArguments);
|
|
}
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
return createErrorMessage("Exception: " + e.getMessage());
|
|
}
|
|
return XML_OK;
|
|
}
|
|
|
|
if (action.equals("SHOW_TRUCK")) {
|
|
if (!simulation.getGUI().isVisualized())
|
|
return XML_OK;
|
|
|
|
JInternalFrame[] allPlugins = simulation.getGUI().getDesktopPane().getAllFrames();
|
|
|
|
try {
|
|
Class<Visualizer2D> pluginClass = (Class<Visualizer2D>) simulation.getGUI().tryLoadClass(this, Visualizer2D.class, "se.sics.runes.RunesVis");
|
|
|
|
if (hide == 0) {
|
|
Class[] parameterTypes = new Class[0];
|
|
Method method = pluginClass.getMethod("showTruck", parameterTypes);
|
|
Object[] parameterArguments = new Object[0];
|
|
|
|
for (JInternalFrame plugin: allPlugins) {
|
|
if (plugin.getClass() == pluginClass) {
|
|
method.invoke(plugin, parameterArguments);
|
|
}
|
|
}
|
|
} else {
|
|
Class[] parameterTypes = new Class[0];
|
|
Method method = pluginClass.getMethod("hideTruck", parameterTypes);
|
|
Object[] parameterArguments = new Object[0];
|
|
|
|
for (JInternalFrame plugin: allPlugins) {
|
|
if (plugin.getClass() == pluginClass) {
|
|
method.invoke(plugin, parameterArguments);
|
|
}
|
|
}
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
return createErrorMessage("Exception: " + e.getMessage());
|
|
}
|
|
return XML_OK;
|
|
}
|
|
|
|
if (action.equals("INDICATE_MOTE")) {
|
|
if (!simulation.getGUI().isVisualized())
|
|
return XML_OK;
|
|
|
|
JInternalFrame[] allPlugins = simulation.getGUI().getDesktopPane().getAllFrames();
|
|
|
|
try {
|
|
Class<Visualizer2D> pluginClass = (Class<Visualizer2D>) simulation.getGUI().tryLoadClass(this, Visualizer2D.class, "se.sics.runes.RunesVis");
|
|
Class[] parameterTypes = new Class[1];
|
|
parameterTypes[0] = Integer.TYPE;
|
|
Method method = pluginClass.getMethod("indicateMote", parameterTypes);
|
|
Object[] parameterArguments = new Object[1];
|
|
parameterArguments[0] = new Integer(id);
|
|
|
|
for (JInternalFrame plugin: allPlugins) {
|
|
if (plugin.getClass() == pluginClass) {
|
|
method.invoke(plugin, parameterArguments);
|
|
}
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
return createErrorMessage("Exception: " + e.getMessage());
|
|
}
|
|
return XML_OK;
|
|
}
|
|
|
|
|
|
return createErrorMessage("Unknown action: " + action);
|
|
}
|
|
|
|
/**
|
|
* Handle clear eventpoints command.
|
|
*
|
|
* @return Reply to client (XML format)
|
|
*/
|
|
private String clearEventpoints() {
|
|
myEvaluator.clearAllEventpoints();
|
|
return XML_OK;
|
|
}
|
|
|
|
public static String createErrorMessage(String message) {
|
|
return XML_ERROR_START + message + XML_ERROR_END;
|
|
}
|
|
|
|
public static String createInfoMessage(String message) {
|
|
return XML_INFO_START + message + XML_INFO_END;
|
|
}
|
|
|
|
public static String createOkMessage(Eventpoint eventpoint, int time) {
|
|
return XML_OK_START + eventpoint.getID() + XML_OK_END;
|
|
}
|
|
|
|
public static String createEventpointMessage(EventpointEvaluator evaluator) {
|
|
return XML_EVENTPOINT_START +
|
|
evaluator.getLastTriggeredEventpointID() +
|
|
XML_INFO_START +
|
|
evaluator.getTriggeredEventpoint().getMessage() +
|
|
XML_INFO_END +
|
|
XML_EVENTPOINT_END;
|
|
}
|
|
}
|