esb mote extends general msp mote

This commit is contained in:
fros4943 2008-02-07 14:53:29 +00:00
parent 09345f05ae
commit c18afffd36
5 changed files with 1666 additions and 0 deletions

View file

@ -0,0 +1,115 @@
/*
* 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: ESBMote.java,v 1.1 2008/02/07 14:53:29 fros4943 Exp $
*/
package se.sics.cooja.mspmote;
import java.io.File;
import java.util.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.*;
import se.sics.cooja.mspmote.interfaces.*;
import se.sics.mspsim.platform.esb.ESBNode;
/**
* @author Fredrik Osterlind
*/
public class ESBMote extends MspMote {
private static Logger logger = Logger.getLogger(ESBMote.class);
public ESBNode esbNode = null;
public ESBMote() {
super();
}
public ESBMote(MoteType moteType, Simulation sim) {
super((ESBMoteType) moteType, sim);
}
protected boolean initEmulator(File fileELF) {
try {
createCPUAndMemory(fileELF);
esbNode = new ESBNode(getCPU());
} catch (Exception e) {
logger.fatal("Error when creating ESB mote: " + e);
return false;
}
return true;
}
protected MoteInterfaceHandler createMoteInterfaceHandler() {
MoteInterfaceHandler moteInterfaceHandler = new MoteInterfaceHandler();
// Add position interface
Position motePosition = new Position(this);
Random random = new Random();
motePosition.setCoordinates(random.nextDouble()*100, random.nextDouble()*100, random.nextDouble()*100);
moteInterfaceHandler.addActiveInterface(motePosition);
// Add log interface
Log moteLog = new ESBLog(this);
moteInterfaceHandler.addActiveInterface(moteLog);
// Add time interface
Clock moteClock = new MspClock(this);
moteInterfaceHandler.addActiveInterface(moteClock);
// Add led interface
LED moteLed = new ESBLED(this);
moteInterfaceHandler.addActiveInterface(moteLed);
// Add button interface
Button moteButton = new ESBButton(this);
moteInterfaceHandler.addActiveInterface(moteButton);
// Add ID interface
MoteID moteID = new MspMoteID(this);
moteInterfaceHandler.addActiveInterface(moteID);
// Add radio interface
myRadio = new TR1001Radio(this);
moteInterfaceHandler.addActiveInterface(myRadio);
return moteInterfaceHandler;
}
public String toString() {
if (getInterfaces().getMoteID() != null) {
return "ESB Mote, ID=" + getInterfaces().getMoteID().getMoteID();
} else {
return "ESB Mote, ID=null";
}
}
}

View file

@ -0,0 +1,63 @@
/*
* 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: ESBMoteType.java,v 1.1 2008/02/07 14:53:29 fros4943 Exp $
*/
package se.sics.cooja.mspmote;
import javax.swing.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
@ClassDescription("ESB Mote Type")
@AbstractionLevelDescription("Emulated level")
public class ESBMoteType extends MspMoteType {
private static Logger logger = Logger.getLogger(ESBMoteType.class);
public static final String target = "esb";
public static final String targetNice = "ESB";
public ESBMoteType() {
}
public ESBMoteType(String identifier) {
setIdentifier(identifier);
setDescription(targetNice + " Mote Type #" + identifier);
}
public Mote generateMote(Simulation simulation) {
return new ESBMote(this, simulation);
}
public boolean configureAndInit(JFrame parentFrame, Simulation simulation,
boolean visAvailable) throws MoteTypeCreationException {
return configureAndInitMspType(parentFrame, simulation, visAvailable, target, targetNice);
}
}

View file

@ -0,0 +1,354 @@
/*
* 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: MspMote.java,v 1.1 2008/02/07 14:53:29 fros4943 Exp $
*/
package se.sics.cooja.mspmote;
import java.io.*;
import java.util.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.mspmote.interfaces.TR1001Radio;
import se.sics.mspsim.core.MSP430;
import se.sics.mspsim.core.MapTable;
import se.sics.mspsim.util.ELF;
/**
* @author Fredrik Osterlind
*/
public abstract class MspMote implements Mote {
private static Logger logger = Logger.getLogger(MspMote.class);
/* 2.4 MHz */
public static int NR_CYCLES_PER_MSEC = 2365;
/* Cycle counter */
public long cycleCounter = 0;
private Simulation mySimulation = null;
private MSP430 myCpu = null;
private MspMoteType myMoteType = null;
private MspMoteMemory myMemory = null;
private MoteInterfaceHandler myMoteInterfaceHandler = null;
private ELF myELFModule = null;
protected TR1001Radio myRadio = null; /* TODO Only used by ESB (TR1001) */
/* Stack monitoring variables */
private boolean stopNextInstruction = false;
private boolean monitorStackUsage = false;
private int stackPointerLow = Integer.MAX_VALUE;
private int heapStartAddress;
private StackOverflowObservable stackOverflowObservable = new StackOverflowObservable();
/**
* Abort current tick immediately.
* May for example be called by a breakpoint handler.
*/
public void stopNextInstruction() {
stopNextInstruction = true;
}
public MspMote() {
myMoteType = null;
mySimulation = null;
myCpu = null;
myMemory = null;
myMoteInterfaceHandler = null;
}
public MspMote(MspMoteType moteType, Simulation simulation) {
myMoteType = moteType;
mySimulation = simulation;
initEmulator(myMoteType.getELFFile());
myMoteInterfaceHandler = createMoteInterfaceHandler();
}
/**
* @return MSP430 CPU
*/
public MSP430 getCPU() {
return myCpu;
}
public MoteMemory getMemory() {
return myMemory;
}
public void setMemory(MoteMemory memory) {
myMemory = (MspMoteMemory) memory;
}
public Simulation getSimulation() {
return mySimulation;
}
public void setSimulation(Simulation simulation) {
mySimulation = simulation;
}
/* Stack monitoring variables */
public class StackOverflowObservable extends Observable {
public void signalStackOverflow() {
setChanged();
notifyObservers();
}
}
/**
* Enable/disable stack monitoring
*
* @param monitoring Monitoring enabled
*/
public void monitorStack(boolean monitoring) {
this.monitorStackUsage = monitoring;
resetLowestStackPointer();
}
/**
* @return Lowest SP since stack monitoring was enabled
*/
public int getLowestStackPointer() {
return stackPointerLow;
}
/**
* Resets lowest stack pointer variable
*/
public void resetLowestStackPointer() {
stackPointerLow = Integer.MAX_VALUE;
}
/**
* @return Stack overflow observable
*/
public StackOverflowObservable getStackOverflowObservable() {
return stackOverflowObservable;
}
/**
* Creates MSP430 CPU object and address memory for current object.
* This method should normally not be called from outside constructor.
*
* @param fileELF ELF file
* @throws IOException File loading failed
*/
protected void createCPUAndMemory(File fileELF) throws IOException {
myCpu = new MSP430(0);
myCpu.setMonitorExec(true);
int[] memory = myCpu.getMemory();
myELFModule = ELF.readELF(fileELF.getPath());
myELFModule.loadPrograms(memory);
MapTable map = myELFModule.getMap();
myCpu.getDisAsm().setMap(map);
myCpu.setMap(map);
/* TODO Need new memory type including size and type as well */
/* Create mote address memory */
Properties varAddresses = new Properties();
for (int i=0; i < map.functionNames.length; i++) {
if (map.functionNames[i] != null) {
varAddresses.put(map.functionNames[i], new Integer(i));
}
}
myMemory = new MspMoteMemory(varAddresses, myCpu);
myCpu.reset();
}
public void setState(State newState) {
logger.warn("Msp motes can't change state");
}
public State getState() {
return Mote.State.ACTIVE;
}
public MoteType getType() {
return myMoteType;
}
public void setType(MoteType type) {
myMoteType = (MspMoteType) type;
}
public void addStateObserver(Observer newObserver) {
}
public void deleteStateObserver(Observer newObserver) {
}
public MoteInterfaceHandler getInterfaces() {
return myMoteInterfaceHandler;
}
public void setInterfaces(MoteInterfaceHandler moteInterfaceHandler) {
myMoteInterfaceHandler = moteInterfaceHandler;
}
/**
* Creates an interface handler object and registers interfaces to it.
*
* @return Interface handler
*/
protected abstract MoteInterfaceHandler createMoteInterfaceHandler();
/**
* Initializes emulator by creating CPU, memory and node object.
*
* @param ELFFile ELF file
* @return True if successful
*/
protected abstract boolean initEmulator(File ELFFile);
public void tick(int simTime) {
// Let all interfaces act
myMoteInterfaceHandler.doPassiveActionsBeforeTick();
myMoteInterfaceHandler.doActiveActionsBeforeTick();
stopNextInstruction = false;
// Leave control to emulated CPU
MSP430 cpu = getCPU();
cycleCounter += NR_CYCLES_PER_MSEC;
if (monitorStackUsage) {
// CPU loop with stack observer
int newStack;
while (!stopNextInstruction && cpu.step() < cycleCounter) {
/* Check if radio has pending incoming bytes */
if (myRadio != null && myRadio.hasPendingBytes()) {
myRadio.tryDeliverNextByte(cpu.cycles);
}
newStack = cpu.reg[MSP430.SP];
if (newStack < stackPointerLow && newStack > 0) {
stackPointerLow = cpu.reg[MSP430.SP];
// Check if stack is writing in memory
if (stackPointerLow < heapStartAddress) {
stackOverflowObservable.signalStackOverflow();
stopNextInstruction = true;
}
}
}
} else { /* Fast CPU loop */
do {
/* Check if radio has pending incoming bytes */
if (myRadio != null && myRadio.hasPendingBytes()) {
myRadio.tryDeliverNextByte(cpu.cycles);
}
} while (!stopNextInstruction && (cpu.step() < cycleCounter) );
}
// Reset abort flag
stopNextInstruction = false;
// Let all interfaces act after tick
myMoteInterfaceHandler.doActiveActionsAfterTick();
myMoteInterfaceHandler.doPassiveActionsAfterTick();
}
public boolean setConfigXML(Simulation simulation, Collection<Element> configXML, boolean visAvailable) {
for (Element element: configXML) {
String name = element.getName();
if (name.equals("motetype_identifier")) {
setSimulation(simulation);
myMoteType = (MspMoteType) simulation.getMoteType(element.getText());
getType().setIdentifier(element.getText());
initEmulator(myMoteType.getELFFile());
myMoteInterfaceHandler = createMoteInterfaceHandler();
} else if (name.equals("interface_config")) {
Class<? extends MoteInterface> moteInterfaceClass = simulation.getGUI().tryLoadClass(
this, MoteInterface.class, element.getText().trim());
if (moteInterfaceClass == null) {
logger.fatal("Could not load mote interface class: " + element.getText().trim());
return false;
}
MoteInterface moteInterface = getInterfaces().getInterfaceOfType(moteInterfaceClass);
moteInterface.setConfigXML(element.getChildren(), visAvailable);
}
}
return true;
}
public Collection<Element> getConfigXML() {
Vector<Element> config = new Vector<Element>();
Element element;
// Mote type identifier
element = new Element("motetype_identifier");
element.setText(getType().getIdentifier());
config.add(element);
// Active interface configs (if any)
for (MoteInterface moteInterface: getInterfaces().getAllActiveInterfaces()) {
element = new Element("interface_config");
element.setText(moteInterface.getClass().getName());
Collection interfaceXML = moteInterface.getConfigXML();
if (interfaceXML != null) {
element.addContent(interfaceXML);
config.add(element);
}
}
// Passive interface configs (if any)
for (MoteInterface moteInterface: getInterfaces().getAllPassiveInterfaces()) {
element = new Element("interface_config");
element.setText(moteInterface.getClass().getName());
Collection interfaceXML = moteInterface.getConfigXML();
if (interfaceXML != null) {
element.addContent(interfaceXML);
config.add(element);
}
}
return config;
}
}

View file

@ -0,0 +1,192 @@
/*
* 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: MspMoteMemory.java,v 1.1 2008/02/07 14:53:29 fros4943 Exp $
*/
package se.sics.cooja.mspmote;
import java.util.*;
import org.apache.log4j.Logger;
import se.sics.cooja.AddressMemory;
import se.sics.cooja.MoteMemory;
import se.sics.mspsim.core.MSP430;
public class MspMoteMemory implements MoteMemory, AddressMemory {
private static Logger logger = Logger.getLogger(MspMoteMemory.class);
private final Properties variableAddresses;
private int TEMP_MEM_START;
private MSP430 cpu;
public MspMoteMemory(Properties variableAddresses, MSP430 cpu) {
this.variableAddresses = variableAddresses;
this.cpu = cpu;
TEMP_MEM_START = 0;
}
public String[] getVariableNames() {
String[] names = new String[variableAddresses.size()];
Enumeration nameEnum = variableAddresses.keys();
for (int i = 0; i < variableAddresses.size(); i++) {
names[i] = (String) nameEnum.nextElement();
}
return names;
}
public int getVariableAddress(String varName) {
if (!variableAddresses.containsKey(varName)) {
return -1;
}
return ((Integer) variableAddresses.get(varName)).intValue();
}
public void clearMemory() {
logger.fatal("clearMemory() not implemented");
}
public byte[] getMemorySegment(int address, int size) {
int[] ret = new int[size];
System.arraycopy(cpu.memory, address - TEMP_MEM_START, ret, 0, size);
// TODO XXX Slow method
byte[] ret2 = new byte[size];
for (int i=0; i < size; i++) {
ret2[i] = (byte) ret[i];
}
return ret2;
}
public void setMemorySegment(int address, byte[] data) {
// TODO XXX Slow method
int[] intArr = new int[data.length];
for (int i=0; i < data.length; i++) {
intArr[i] = data[i];
}
System.arraycopy(intArr, 0, cpu.memory, address - TEMP_MEM_START, data.length);
}
public int getTotalSize() {
return cpu.memory.length;
}
public boolean variableExists(String varName) {
return variableAddresses.containsKey(varName);
}
public int getIntValueOf(String varName) {
// Get start address of variable
if (!variableAddresses.containsKey(varName)) {
return -1;
}
int varAddr = ((Integer) variableAddresses.get(varName)).intValue();
byte[] varData = getMemorySegment(varAddr, 2);
int retVal = 0;
int pos = 0;
retVal += ((varData[pos++] & 0xFF)) << 8;
retVal += ((varData[pos++] & 0xFF)) << 0;
return Integer.reverseBytes(retVal) >> 16; // Crop two bytes
}
public void setIntValueOf(String varName, int newVal) {
// Get start address of variable
if (!variableAddresses.containsKey(varName)) {
return;
}
int varAddr = ((Integer) variableAddresses.get(varName)).intValue();
// TODO Check if small/big-endian when coming from JNI?
int newValToSet = Integer.reverseBytes(newVal);
// Create byte array
int pos = 0;
byte[] varData = new byte[4];
varData[pos++] = (byte) ((newValToSet & 0xFF000000) >> 24);
varData[pos++] = (byte) ((newValToSet & 0xFF0000) >> 16);
varData[pos++] = (byte) ((newValToSet & 0xFF00) >> 8);
varData[pos++] = (byte) ((newValToSet & 0xFF) >> 0);
setMemorySegment(varAddr, varData);
}
public byte getByteValueOf(String varName) {
// Get start address of variable
if (!variableAddresses.containsKey(varName)) {
return -1;
}
int varAddr = ((Integer) variableAddresses.get(varName)).intValue();
byte[] varData = getMemorySegment(varAddr, 1);
return varData[0];
}
public void setByteValueOf(String varName, byte newVal) {
// Get start address of variable
if (!variableAddresses.containsKey(varName)) {
return;
}
int varAddr = ((Integer) variableAddresses.get(varName)).intValue();
byte[] varData = new byte[1];
varData[0] = newVal;
setMemorySegment(varAddr, varData);
}
public byte[] getByteArray(String varName, int length) {
// Get start address of variable
if (!variableAddresses.containsKey(varName)) {
return null;
}
int varAddr = ((Integer) variableAddresses.get(varName)).intValue();
// TODO Check if small/big-endian when coming from JNI?
return getMemorySegment(varAddr, length);
}
public void setByteArray(String varName, byte[] data) {
// Get start address of variable
if (!variableAddresses.containsKey(varName)) {
return;
}
int varAddr = ((Integer) variableAddresses.get(varName)).intValue();
// TODO Check if small/big-endian when coming from JNI?
setMemorySegment(varAddr, data);
}
}

View file

@ -0,0 +1,942 @@
/*
* 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: MspMoteType.java,v 1.1 2008/02/07 14:53:29 fros4943 Exp $
*/
package se.sics.cooja.mspmote;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileFilter;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.dialogs.MessageList;
@ClassDescription("Msp Mote Type")
public abstract class MspMoteType implements MoteType {
private static Logger logger = Logger.getLogger(MspMoteType.class);
private static final String firmwareFileExtension = ".firmware";
/* Convenience: Preselecting last used directory */
protected static File lastParentDirectory = null;
private String identifier = null;
private String description = null;
/* If source file is defined, (re)compilation is performed */
private File fileELF = null;
private File fileSource = null;
private String compileCommand = null;
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
/**
* Set ELF file.
*
* @param file
* ELF file
*/
public void setELFFile(File file) {
this.fileELF = file;
}
/**
* Set compile command.
*
* @param command
* Compile command
*/
public void setCompileCommand(String command) {
this.compileCommand = command;
}
/**
* @return ELF file
*/
public File getELFFile() {
return fileELF;
}
/**
* @return Compile command
*/
public String getCompileCommand() {
return compileCommand;
}
/**
* Set source file
*
* @param file Source file
*/
public void setSourceFile(File file) {
fileSource = file;
}
/**
* @return Source file
*/
public File getSourceFile() {
return fileSource;
}
/**
* Configures and initialized Msp mote types.
*
* @param parentFrame Graphical parent frame
* @param simulation Current simulation
* @param visAvailable Enable graphical interfaces and user input
* @param target Contiki target platform name
* @param targetNice Nicer representation of target
* @return True is successful
* @throws MoteTypeCreationException Mote type creation failed
*/
protected boolean configureAndInitMspType(JFrame parentFrame, Simulation simulation,
boolean visAvailable, String target, String targetNice)
throws MoteTypeCreationException {
boolean compileFromSource = false;
if (getIdentifier() == null && !visAvailable) {
throw new MoteTypeCreationException("No identifier");
}
/* Generate unique identifier */
if (getIdentifier() == null) {
int counter = 0;
boolean identifierOK = false;
while (!identifierOK) {
counter++;
setIdentifier(target + counter);
identifierOK = true;
// Check if identifier is already used by some other type
for (MoteType existingMoteType : simulation.getMoteTypes()) {
if (existingMoteType != this
&& existingMoteType.getIdentifier().equals(getIdentifier())) {
identifierOK = false;
break;
}
}
}
if (getDescription() == null) {
setDescription(targetNice + " Mote Type #" + counter);
}
/* Let user choose whether to compile or load existing binaries */
Object[] options = { "Select", "Compile" };
String question = targetNice + " mote type depends on an ELF file.\n"
+ "If you want to use an already existing file, click 'Select'.\n\n"
+ "To compile this file from source, click 'Compile'";
String title = "Select or compile " + targetNice + " firmware";
int answer = JOptionPane.showOptionDialog(GUI.frame,
question, title, JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
if (answer != JOptionPane.YES_OPTION && answer != JOptionPane.NO_OPTION) {
return false;
}
compileFromSource = answer != JOptionPane.YES_OPTION;
}
/* Description */
if (getDescription() == null) {
setDescription(targetNice + " Mote Type #" + getIdentifier());
}
if (getSourceFile() != null) {
compileFromSource = true;
}
if (compileFromSource) {
MspELFCompiler compiler = new MspELFCompiler(target);
compiler.setCompileCommand(compileCommand);
if (visAvailable) {
boolean success = compiler.showDialog(GUI.frame, this);
if (success) {
setSourceFile(compiler.getSourceFile());
setELFFile(compiler.getOutputFile());
setCompileCommand(compiler.getLastCompileCommand());
return true;
} else {
return false;
}
} else {
MessageList compilationOutput = new MessageList();
try {
compiler.compileFirmware(getSourceFile(), null, null, compilationOutput,
true);
} catch (Exception e) {
MoteTypeCreationException newException = new MoteTypeCreationException(
"Mote type creation failed: " + e.getMessage());
newException = (MoteTypeCreationException) newException.initCause(e);
newException.setCompilationOutput(compilationOutput);
throw newException;
}
/*File parentFile = getSourceFile().getParentFile();*/
/*final String filenameNoExtension = getSourceFile().getName().substring(0,
getSourceFile().getName().length() - 2);*/
/*setELFFile(new File(parentFile, filenameNoExtension + firmwareFileExtension));*/
setSourceFile(compiler.getSourceFile());
setELFFile(compiler.getOutputFile());
setCompileCommand(compiler.getLastCompileCommand());
return true;
}
}
// Check dependency files
if (getELFFile() == null || !getELFFile().exists()) {
if (visAvailable) {
JFileChooser fc = new JFileChooser();
// Select previous directory
if (lastParentDirectory != null) {
fc.setCurrentDirectory(lastParentDirectory);
} else {
fc.setCurrentDirectory(new java.io.File(GUI
.getExternalToolsSetting("PATH_CONTIKI")));
}
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.addChoosableFileFilter(new FileFilter() {
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
String filename = f.getName();
if (filename != null) {
if (filename.endsWith(firmwareFileExtension)) {
return true;
}
}
return false;
}
public String getDescription() {
return "ELF file";
}
});
fc.setDialogTitle("Select ELF file");
if (fc.showOpenDialog(parentFrame) == JFileChooser.APPROVE_OPTION) {
lastParentDirectory = fc.getSelectedFile().getParentFile();
setELFFile(fc.getSelectedFile());
} else {
return false;
}
} else {
throw new MoteTypeCreationException("No ELF file was created");
}
}
return true;
}
protected static class MspELFCompiler {
private static int LABEL_WIDTH = 170;
private static int LABEL_HEIGHT = 15;
private JButton cancelButton = new JButton("Cancel");
private JButton compileButton = new JButton("Compile");
private JButton createButton = new JButton("Create");
private JTextField sourceTextField = new JTextField();
private JTextField compileCommandTextField = new JTextField();
// private JFormattedTextField nodeIDTextField;
// private NumberFormat integerFormat = NumberFormat.getIntegerInstance();
private String lastCompileCommand = null;
private File sourceFile = null;
private File ELFFile = null;
private String target;
private JDialog myDialog;
private String customizedCompileCommand = null;
static enum DialogState {
NO_SOURCE, SELECTED_SOURCE, IS_COMPILING, COMPILED_SOURCE
}
public MspELFCompiler(String target) {
this.target = target;
}
private String getCompileCommand(String filename) {
if (customizedCompileCommand != null) {
return customizedCompileCommand;
}
return GUI.getExternalToolsSetting("PATH_MAKE") + " " + filename + firmwareFileExtension + " TARGET=" + target;
}
private void setCompileCommand(String command) {
if (command == null || command.isEmpty()) {
customizedCompileCommand = null;
return;
}
customizedCompileCommand = command;
}
/**
* @return Compiler output
*/
public File getOutputFile() {
return ELFFile;
}
public File getSourceFile() {
return sourceFile;
}
public String getLastCompileCommand() {
return lastCompileCommand;
}
private void updateDialog(DialogState dialogState) {
switch (dialogState) {
case NO_SOURCE:
compileButton.setEnabled(false);
createButton.setEnabled(false);
compileCommandTextField.setText("");
break;
case IS_COMPILING:
compileButton.setEnabled(false);
createButton.setEnabled(false);
break;
case SELECTED_SOURCE:
File sourceFile = new File(sourceTextField.getText());
if (!sourceFile.exists()) {
updateDialog(DialogState.NO_SOURCE);
break;
}
File parentDirectory = sourceFile.getParentFile();
if (!parentDirectory.exists()) {
updateDialog(DialogState.NO_SOURCE);
break;
}
if (!sourceFile.getName().endsWith(".c")) {
updateDialog(DialogState.NO_SOURCE);
break;
}
String name = sourceFile.getName().substring(0,
sourceFile.getName().length() - 2);
compileButton.setEnabled(true);
createButton.setEnabled(false);
compileCommandTextField.setText(getCompileCommand(name));
compileButton.requestFocusInWindow();
break;
case COMPILED_SOURCE:
compileButton.setEnabled(true);
createButton.setEnabled(true);
createButton.requestFocusInWindow();
myDialog.getRootPane().setDefaultButton(createButton);
break;
default:
break;
}
}
protected void compileFirmware(final File sourceFile,
final Action successAction, final Action failAction,
MessageList compilationOutput, boolean synchronous) throws Exception {
final File parentDirectory = sourceFile.getParentFile();
final String filenameNoExtension = sourceFile.getName().substring(0,
sourceFile.getName().length() - 2);
String command = getCompileCommand(filenameNoExtension);
logger.info("Compile command: " + command);
compilationOutput.clearMessages();
try {
String[] cmd = command.split(" ");
final Process compileProcess = Runtime.getRuntime().exec(cmd, null,
parentDirectory);
final BufferedReader processNormal = new BufferedReader(
new InputStreamReader(compileProcess.getInputStream()));
final BufferedReader processError = new BufferedReader(
new InputStreamReader(compileProcess.getErrorStream()));
final PrintStream listNormal = compilationOutput
.getInputStream(MessageList.NORMAL);
final PrintStream listError = compilationOutput
.getInputStream(MessageList.ERROR);
final File ELFFile = new File(parentDirectory, filenameNoExtension + firmwareFileExtension);
if (ELFFile.exists()) {
ELFFile.delete();
if (ELFFile.exists()) {
listError.println("Error when deleting old " + ELFFile.getName());
if (failAction != null) {
failAction.actionPerformed(null);
}
throw new MoteTypeCreationException("Error when deleting old "
+ ELFFile.getName());
}
}
Thread readInput = new Thread(new Runnable() {
public void run() {
String readLine;
try {
while ((readLine = processNormal.readLine()) != null) {
if (listNormal != null && readLine != null) {
listNormal.println(readLine);
}
}
} catch (IOException e) {
logger.warn("Error while reading from process");
}
}
}, "read input stream thread");
Thread readError = new Thread(new Runnable() {
public void run() {
String readLine;
try {
while ((readLine = processError.readLine()) != null) {
if (listError != null && readLine != null) {
listError.println(readLine);
}
}
} catch (IOException e) {
logger.warn("Error while reading from process");
}
}
}, "read input stream thread");
final MoteTypeCreationException syncException = new MoteTypeCreationException(
"");
Thread handleCompilationResultThread = new Thread(new Runnable() {
public void run() {
/* Wait for compilation to end */
try {
compileProcess.waitFor();
} catch (Exception e) {
syncException.setCompilationOutput(new MessageList());
syncException.fillInStackTrace();
return;
}
/* Check return value */
if (compileProcess.exitValue() != 0) {
listError.println("Process returned error code "
+ compileProcess.exitValue());
if (failAction != null) {
failAction.actionPerformed(null);
}
syncException.setCompilationOutput(new MessageList());
syncException.fillInStackTrace();
return;
}
if (!ELFFile.exists()) {
listError.println("Can't locate output file " + ELFFile);
if (failAction != null) {
failAction.actionPerformed(null);
}
syncException.setCompilationOutput(new MessageList());
syncException.fillInStackTrace();
return;
}
listNormal.println("");
listNormal.println("Compilation succeded");
if (successAction != null) {
successAction.actionPerformed(null);
}
}
}, "enable create button thread");
readInput.start();
readError.start();
handleCompilationResultThread.start();
if (synchronous) {
try {
handleCompilationResultThread.join();
} catch (Exception e) {
throw (MoteTypeCreationException) new MoteTypeCreationException(
"Compilation error: " + e.getMessage()).initCause(e);
}
if (syncException.hasCompilationOutput()) {
throw (MoteTypeCreationException) new MoteTypeCreationException(
"Compilation error").initCause(syncException);
}
}
} catch (IOException ex) {
if (failAction != null) {
failAction.actionPerformed(null);
}
throw (MoteTypeCreationException) new MoteTypeCreationException(
"Compilation error: " + ex.getMessage()).initCause(ex);
}
}
public boolean showDialog(Frame parentFrame, final MspMoteType moteType) {
myDialog = new JDialog(parentFrame, "Compile ELF file", true);
final MessageList taskOutput = new MessageList();
// BOTTOM BUTTON PART
Box buttonBox = Box.createHorizontalBox();
buttonBox.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonBox.add(Box.createHorizontalGlue());
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sourceFile = null;
ELFFile = null;
myDialog.dispose();
}
});
compileButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final File selectedSourceFile = new File(sourceTextField.getText());
/* Strip .c file extension */
final String filenameNoExtension = selectedSourceFile.getName()
.substring(0, selectedSourceFile.getName().length() - 2);
Action successAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
updateDialog(DialogState.COMPILED_SOURCE);
File parentFile = selectedSourceFile.getParentFile();
lastCompileCommand = getCompileCommand(filenameNoExtension);
sourceFile = selectedSourceFile;
ELFFile = new File(parentFile, filenameNoExtension + firmwareFileExtension);
}
};
Action failAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
updateDialog(DialogState.SELECTED_SOURCE);
}
};
updateDialog(DialogState.IS_COMPILING);
try {
compileFirmware(new File(sourceTextField.getText()), successAction,
failAction, taskOutput, false);
} catch (Exception e2) {
}
}
});
createButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
myDialog.dispose();
}
});
buttonBox.add(cancelButton);
buttonBox.add(Box.createHorizontalStrut(5));
buttonBox.add(compileButton);
buttonBox.add(Box.createHorizontalStrut(5));
buttonBox.add(createButton);
// MAIN DIALOG CONTENTS
Box horizBox;
JLabel label;
Box vertBox = Box.createVerticalBox();
// Source
horizBox = Box.createHorizontalBox();
horizBox.setMaximumSize(new Dimension(Integer.MAX_VALUE, LABEL_HEIGHT));
horizBox.setAlignmentX(Component.LEFT_ALIGNMENT);
label = new JLabel("Contiki process sourcefile");
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
sourceTextField.setText("");
if (moteType.getSourceFile() != null) {
sourceTextField.setText(moteType.getSourceFile().getAbsolutePath());
}
sourceTextField.setColumns(25);
sourceTextField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
updateDialog(DialogState.SELECTED_SOURCE);
}
public void changedUpdate(DocumentEvent e) {
updateDialog(DialogState.SELECTED_SOURCE);
}
public void removeUpdate(DocumentEvent e) {
updateDialog(DialogState.SELECTED_SOURCE);
}
});
JButton browseButton = new JButton("Browse");
browseButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
updateDialog(DialogState.NO_SOURCE);
JFileChooser fc = new JFileChooser();
if (lastParentDirectory != null) {
fc.setCurrentDirectory(lastParentDirectory);
} else {
fc.setCurrentDirectory(new java.io.File(GUI
.getExternalToolsSetting("PATH_CONTIKI")));
}
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.addChoosableFileFilter(new FileFilter() {
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
String filename = f.getName();
if (filename != null) {
if (filename.endsWith(".c")) {
return true;
}
}
return false;
}
public String getDescription() {
return "Contiki process source";
}
});
fc.setDialogTitle("Select Contiki process source");
if (fc.showOpenDialog(myDialog) == JFileChooser.APPROVE_OPTION) {
lastParentDirectory = null;
sourceTextField.setText("");
File selectedFile = fc.getSelectedFile();
if (!selectedFile.exists()) {
return;
}
if (!selectedFile.getName().endsWith(".c")) {
return;
}
lastParentDirectory = fc.getSelectedFile().getParentFile();
sourceTextField.setText(fc.getSelectedFile().getAbsolutePath());
updateDialog(DialogState.SELECTED_SOURCE);
}
}
});
horizBox.add(label);
horizBox.add(Box.createHorizontalStrut(10));
horizBox.add(sourceTextField);
horizBox.add(browseButton);
vertBox.add(horizBox);
vertBox.add(Box.createRigidArea(new Dimension(0, 5)));
// Node ID
/*
* horizBox = Box.createHorizontalBox(); horizBox.setMaximumSize(new
* Dimension(Integer.MAX_VALUE,LABEL_HEIGHT));
* horizBox.setAlignmentX(Component.LEFT_ALIGNMENT); label = new
* JLabel("Node ID (0=EEPROM)"); label.setPreferredSize(new
* Dimension(LABEL_WIDTH,LABEL_HEIGHT));
*
* nodeIDTextField = new JFormattedTextField(integerFormat);
* nodeIDTextField.setValue(new Integer(0));
* nodeIDTextField.setColumns(25);
* nodeIDTextField.addPropertyChangeListener("value", new
* PropertyChangeListener() { public void
* propertyChange(PropertyChangeEvent e) {
* updateDialog(DialogState.SELECTED_SOURCE); } });
*
* horizBox.add(label); horizBox.add(Box.createHorizontalStrut(150));
* horizBox.add(nodeIDTextField);
*
* vertBox.add(horizBox); vertBox.add(Box.createRigidArea(new
* Dimension(0,5)));
*/
// Compile command
horizBox = Box.createHorizontalBox();
horizBox.setMaximumSize(new Dimension(Integer.MAX_VALUE, LABEL_HEIGHT));
horizBox.setAlignmentX(Component.LEFT_ALIGNMENT);
label = new JLabel("Compile command");
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
compileCommandTextField.setText("");
compileCommandTextField.setColumns(25);
compileCommandTextField.setEditable(true);
compileCommandTextField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
setCompileCommand(compileCommandTextField.getText());
}
public void changedUpdate(DocumentEvent e) {
setCompileCommand(compileCommandTextField.getText());
}
public void removeUpdate(DocumentEvent e) {
setCompileCommand(compileCommandTextField.getText());
}
});
horizBox.add(label);
horizBox.add(Box.createHorizontalStrut(10));
horizBox.add(compileCommandTextField);
vertBox.add(horizBox);
vertBox.add(Box.createRigidArea(new Dimension(0, 5)));
vertBox.add(Box.createRigidArea(new Dimension(0, 5)));
vertBox.add(new JLabel("Compilation output:"));
vertBox.add(Box.createRigidArea(new Dimension(0, 5)));
vertBox.add(new JScrollPane(taskOutput));
vertBox.add(Box.createRigidArea(new Dimension(0, 5)));
vertBox.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
Container contentPane = myDialog.getContentPane();
contentPane.add(vertBox, BorderLayout.CENTER);
contentPane.add(buttonBox, BorderLayout.SOUTH);
myDialog.pack();
myDialog.setLocationRelativeTo(parentFrame);
myDialog.getRootPane().setDefaultButton(compileButton);
// Dispose on escape key
InputMap inputMap = myDialog.getRootPane().getInputMap(
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false),
"dispose");
AbstractAction cancelAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
cancelButton.doClick();
}
};
myDialog.getRootPane().getActionMap().put("dispose", cancelAction);
myDialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
myDialog.addWindowListener(new WindowListener() {
public void windowDeactivated(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowOpened(WindowEvent e) {
}
public void windowClosed(WindowEvent e) {
}
public void windowActivated(WindowEvent e) {
}
public void windowClosing(WindowEvent e) {
cancelButton.doClick();
}
});
updateDialog(DialogState.NO_SOURCE);
if (moteType.getSourceFile() != null) {
updateDialog(DialogState.SELECTED_SOURCE);
if (customizedCompileCommand != null && !customizedCompileCommand.equals("")) {
compileCommandTextField.setText(customizedCompileCommand);
}
compileButton.requestFocus();
}
myDialog.setVisible(true);
return sourceFile != null;
}
}
public JPanel getTypeVisualizer() {
JPanel panel = new JPanel();
JLabel label = new JLabel();
JPanel smallPane;
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
// Identifier
smallPane = new JPanel(new BorderLayout());
label = new JLabel("Identifier");
smallPane.add(BorderLayout.WEST, label);
label = new JLabel(getIdentifier());
smallPane.add(BorderLayout.EAST, label);
panel.add(smallPane);
// Description
smallPane = new JPanel(new BorderLayout());
label = new JLabel("Description");
smallPane.add(BorderLayout.WEST, label);
label = new JLabel(getDescription());
smallPane.add(BorderLayout.EAST, label);
panel.add(smallPane);
// ELF Hex file
smallPane = new JPanel(new BorderLayout());
label = new JLabel("ELF file");
smallPane.add(BorderLayout.WEST, label);
label = new JLabel(getELFFile().getName());
label.setToolTipText(getELFFile().getPath());
smallPane.add(BorderLayout.EAST, label);
panel.add(smallPane);
// Source file
smallPane = new JPanel(new BorderLayout());
label = new JLabel("Source file");
smallPane.add(BorderLayout.WEST, label);
if (getSourceFile() != null) {
label = new JLabel(getSourceFile().getName());
label.setToolTipText(getSourceFile().getPath());
} else {
label = new JLabel("[not specified]");
}
smallPane.add(BorderLayout.EAST, label);
panel.add(smallPane);
panel.add(Box.createRigidArea(new Dimension(0, 5)));
return panel;
}
public ProjectConfig getConfig() {
logger.warn("Msp mote type project config not implemented");
return null;
}
public Collection<Element> getConfigXML() {
Vector<Element> config = new Vector<Element>();
Element element;
// Identifier
element = new Element("identifier");
element.setText(getIdentifier());
config.add(element);
// Description
element = new Element("description");
element.setText(getDescription());
config.add(element);
// Source file
if (fileSource != null) {
element = new Element("source");
element.setText(fileSource.getPath());
config.add(element);
element = new Element("command");
element.setText(compileCommand);
config.add(element);
} else {
// ELF file
element = new Element("elf");
element.setText(fileELF.getPath());
config.add(element);
}
return config;
}
public boolean setConfigXML(Simulation simulation,
Collection<Element> configXML, boolean visAvailable)
throws MoteTypeCreationException {
for (Element element : configXML) {
String name = element.getName();
if (name.equals("identifier")) {
identifier = element.getText();
} else if (name.equals("description")) {
description = element.getText();
} else if (name.equals("source")) {
fileSource = new File(element.getText());
} else if (name.equals("command")) {
compileCommand = element.getText();
} else if (name.equals("elf")) {
fileELF = new File(element.getText());
} else {
logger.fatal("Unrecognized entry in loaded configuration: " + name);
throw new MoteTypeCreationException(
"Unrecognized entry in loaded configuration: " + name);
}
}
return configureAndInit(GUI.frame, simulation, visAvailable);
}
}