diff --git a/tools/cooja/apps/avrora/build.xml b/tools/cooja/apps/avrora/build.xml new file mode 100644 index 000000000..260fb5eb3 --- /dev/null +++ b/tools/cooja/apps/avrora/build.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/cooja/apps/avrora/cooja.config b/tools/cooja/apps/avrora/cooja.config new file mode 100644 index 000000000..64c829a28 --- /dev/null +++ b/tools/cooja/apps/avrora/cooja.config @@ -0,0 +1,2 @@ +se.sics.cooja.GUI.MOTETYPES = + se.sics.cooja.avrmote.MicaZMoteType +se.sics.cooja.GUI.JARFILES = + cooja_avrora.jar avrora.jar diff --git a/tools/cooja/apps/avrora/lib/avrora.jar b/tools/cooja/apps/avrora/lib/avrora.jar new file mode 100644 index 000000000..f926a0dfd Binary files /dev/null and b/tools/cooja/apps/avrora/lib/avrora.jar differ diff --git a/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/MicaZMote.java b/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/MicaZMote.java new file mode 100755 index 000000000..57d4bb593 --- /dev/null +++ b/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/MicaZMote.java @@ -0,0 +1,312 @@ +/* + * 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: MicaZMote.java,v 1.1 2009/02/22 16:45:01 joxe Exp $ + */ + +package se.sics.cooja.avrmote; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.net.URL; +import java.util.Collection; +import java.util.Observable; +import java.util.Observer; +import java.util.Random; +import java.util.Vector; +import org.apache.log4j.Logger; +import org.jdom.Element; +import se.sics.cooja.GUI; +import se.sics.cooja.Mote; +import se.sics.cooja.MoteInterface; +import se.sics.cooja.MoteInterfaceHandler; +import se.sics.cooja.MoteMemory; +import se.sics.cooja.MoteType; +import se.sics.cooja.Simulation; +import se.sics.cooja.avrmote.interfaces.MicaZLED; +import se.sics.cooja.interfaces.Position; +import avrora.sim.*; +import avrora.sim.platform.*; +import avrora.sim.mcu.*; +import avrora.core.*; +import avrora.sim.radio.*; +import avrora.sim.util.SimUtil; + + +/** + * @author Joakim Eriksson + */ +public class MicaZMote implements Mote { + private static Logger logger = Logger.getLogger(MicaZMote.class); + + /* 8 MHz according to Contiki config */ + public static long NR_CYCLES_PER_MSEC = 8000; + + /* Cycle counter */ + public long cycleCounter = 0; + public long cycleDrift = 0; + + private Simulation mySimulation = null; + private Microcontroller myCpu = null; + private MicaZ micaZ = null; + private LoadableProgram program = null; + private Interpreter interpreter = null; + + private MicaZMoteType myMoteType = null; + + /* Stack monitoring variables */ + private boolean stopNextInstruction = false; + + private MoteInterfaceHandler myMoteInterfaceHandler; + + /** + * Abort current tick immediately. + * May for example be called by a breakpoint handler. + */ + public void stopNextInstruction() { + stopNextInstruction = true; + } + + public MicaZMote() { + mySimulation = null; + myCpu = null; + myMoteInterfaceHandler = null; + } + + public MicaZMote(Simulation simulation, MicaZMoteType type) { + mySimulation = simulation; + myMoteType = type; + } + + protected void initMote() { + if (myMoteType != null) { + initEmulator(myMoteType.getELFFile()); + myMoteInterfaceHandler = createMoteInterfaceHandler(); + } + } + + protected boolean initEmulator(String fileELF) { + try { + prepareMote(fileELF); + } catch (Exception e) { + logger.fatal("Error when creating MicaZ mote:", e); + return false; + } + return true; + } + + + public Simulation getSimulation() { + return mySimulation; + } + + public void setSimulation(Simulation simulation) { + mySimulation = simulation; + } + + /** + * Prepares CPU, memory and ELF module. + * + * @param fileELF ELF file + * @param cpu MSP430 cpu + * @throws Exception + */ + protected void prepareMote(String file) throws Exception { + program = new LoadableProgram(file); + program.load(); + PlatformFactory factory = new MicaZ.Factory(); + micaZ = (MicaZ) factory.newPlatform(1, program.getProgram()); + myCpu = micaZ.getMicrocontroller(); + Simulator sim = myCpu.getSimulator(); + interpreter = sim.getInterpreter(); +// State state = interpreter.getState(); + } + + public void setState(State newState) { + logger.warn("MicaZ motes can't change state"); + } + + public State getState() { + return Mote.State.ACTIVE; + } + + /* called when moteID is updated */ + public void idUpdated(int newID) { + } + + 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; + } + + /* return false when done - e.g. true means more work to do before finished with this tick */ + + private boolean firstTick = true; + private long cyclesExecuted = 0; + public boolean tick(long simTime) { + if (stopNextInstruction) { + stopNextInstruction = false; + throw new RuntimeException("MSPSim requested simulation stop"); + } + + /* Nodes may be added in an ongoing simulation: + * Update cycle drift to current simulation time */ + if (firstTick) { + firstTick = false; + cycleDrift += (-NR_CYCLES_PER_MSEC*simTime); + } + + long maxSimTimeCycles = NR_CYCLES_PER_MSEC * (simTime + 1) + cycleDrift; + + if (maxSimTimeCycles <= cycleCounter) { + return false; + } + + // Leave control to emulated CPU + cycleCounter += 1; + + if (cyclesExecuted > cycleCounter) { + /* CPU already ticked too far - just wait it out */ + return true; + } + // myMoteInterfaceHandler.doActiveActionsBeforeTick(); + + cyclesExecuted += interpreter.step(); + + //cpu.step(cycleCounter); + + /* Check if radio has pending incoming bytes */ +// if (myRadio != null && myRadio.hasPendingBytes()) { +// myRadio.tryDeliverNextByte(cpu.cycles); +// } + + return true; + } + + public boolean setConfigXML(Simulation simulation, Collection configXML, boolean visAvailable) { + for (Element element: configXML) { + String name = element.getName(); + + if (name.equals("motetype_identifier")) { + + setSimulation(simulation); + myMoteType = (MicaZMoteType) simulation.getMoteType(element.getText()); + getType().setIdentifier(element.getText()); + + try { + prepareMote(myMoteType.getELFFile()); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + myMoteInterfaceHandler = createMoteInterfaceHandler(); + + } else if (name.equals("interface_config")) { + Class 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; + } + + private MoteInterfaceHandler createMoteInterfaceHandler() { + System.out.println("Creating mote interface handler...."); + MoteInterfaceHandler moteInterfaceHandler = new MoteInterfaceHandler(); + + // Add position interface + Position motePosition = new Position(this); + Random random = new Random(); /* Do not use main random generator for positioning */ + motePosition.setCoordinates(random.nextDouble()*100, random.nextDouble()*100, random.nextDouble()*100); + moteInterfaceHandler.addInterface(motePosition); + + // Add LED interface + MicaZLED moteLED = new MicaZLED(micaZ); + moteInterfaceHandler.addInterface(moteLED); + + return moteInterfaceHandler; + } + + public Collection getConfigXML() { + Vector config = new Vector(); + + Element element; + + // Mote type identifier + element = new Element("motetype_identifier"); + element.setText(getType().getIdentifier()); + config.add(element); + + // Mote interfaces + for (MoteInterface moteInterface: getInterfaces().getInterfaces()) { + 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; + } + + public MoteMemory getMemory() { + return null; + } + + public void setMemory(MoteMemory memory) { + } + +} diff --git a/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/MicaZMoteType.java b/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/MicaZMoteType.java new file mode 100644 index 000000000..37f98ab2b --- /dev/null +++ b/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/MicaZMoteType.java @@ -0,0 +1,1135 @@ +/* + * 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: MicaZMoteType.java,v 1.1 2009/02/22 16:45:01 joxe Exp $ + */ + +package se.sics.cooja.avrmote; + +import java.awt.*; +import java.awt.Dialog.ModalityType; +import java.awt.event.*; +import java.io.*; +import java.util.Collection; +import java.util.Vector; +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; +import se.sics.cooja.dialogs.MessageList.MessageContainer; + +@ClassDescription("MicaZ Mote Type") +public class MicaZMoteType implements MoteType { + private static Logger logger = Logger.getLogger(MicaZMoteType.class); + + public static final String target = "micaz"; + public static final String targetNice = "MicaZ"; + + protected static String getTargetFileExtension(String target) { + return "." + target; + } + + /* 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 String fileFirmware = 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.fileFirmware = file.getAbsolutePath(); + } + + /** + * Set compile command. + * + * @param command + * Compile command + */ + public void setCompileCommand(String command) { + this.compileCommand = command; + } + + /** + * @return ELF file + */ + public String getELFFile() { + return fileFirmware; + } + + /** + * @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; + } + + public final Mote generateMote(Simulation simulation) { + MicaZMote mote = new MicaZMote(simulation, this); + mote.initMote(); + return mote; + } + + /** + * Configures and initialized MicaZ mote types. + * TODO: share this code with mspmote using an abstract emulated mote class... + * + * @param parentContainer Graphical parent container + * @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 configureAndInitMicaZType(Container parentContainer, Simulation simulation, + boolean visAvailable, final String target, final 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 = { "Compile", "Existing" }; + + String question = targetNice + " mote type loads a firmware (ELF).\n\n" + + "To compile a Contiki application from source: 'Compile'\n" + + "To use a pre-compiled existing firmware: 'Existing'.\n"; + String title = "Compile or load existing " + targetNice + " firmware"; + + if (GUI.isVisualizedInApplet()) { + compileFromSource = false; + } else { + int answer = JOptionPane.showOptionDialog(GUI.getTopParentContainer(), + 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) { + MicaELFCompiler compiler = new MicaELFCompiler(target); + compiler.setCompileCommand(compileCommand); + + if (visAvailable) { + boolean success = compiler.showDialog(GUI.getTopParentContainer(), 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); + + /* Print last 5 compilation errors */ + MessageContainer[] messages = compilationOutput.getMessages(); + for (int i=messages.length-5; i < messages.length; i++) { + if (i < 0) { + continue; + } + logger.fatal(">> " + messages[i]); + } + + logger.fatal("Compilation error: " + e.getMessage()); + throw newException; + } + + setSourceFile(compiler.getSourceFile()); + setELFFile(compiler.getOutputFile()); + setCompileCommand(compiler.getLastCompileCommand()); + + return true; + } + } + + if (GUI.isVisualizedInApplet()) { + return true; + } + + // Check dependency files + File elfFile = null; + if (getELFFile() != null) { + elfFile = new File(getELFFile()); + } + if (elfFile == null || !elfFile.exists()) { + if (!visAvailable) { + throw new MoteTypeCreationException("ELF file does not exist: " + getELFFile()); + } + + 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) { + String filename = f.getName(); + if (f.isDirectory()) { + return true; + } + + if (filename != null) { + if (filename.endsWith(getTargetFileExtension(target)) || filename.endsWith(".firmware") + || filename.endsWith(".elf")) { + return true; + } + } + return false; + } + + public String getDescription() { + return "Firmware files"; + } + }); + fc.addChoosableFileFilter(new FileFilter() { + public boolean accept(File f) { + String filename = f.getName(); + if (f.isDirectory()) { + return true; + } + + if (filename != null) { + if (filename.endsWith(getTargetFileExtension(target))) { + return true; + } + } + return false; + } + + public String getDescription() { + return targetNice + " firmware files"; + } + }); + fc.setDialogTitle("Select firmware file"); + + if (fc.showOpenDialog(parentContainer) == JFileChooser.APPROVE_OPTION) { + File selectedFile = fc.getSelectedFile(); + + if (!selectedFile.exists()) { + logger.fatal("Selected file \"" + selectedFile + "\" does not exist"); + return false; + } + + setELFFile(fc.getSelectedFile()); + } else { + return false; + } + } + return true; + } + + protected static class MicaELFCompiler { + private static int LABEL_WIDTH = 170; + + private static int LABEL_HEIGHT = 15; + + private JButton cancelButton = new JButton("Cancel"); + + private JButton cleanButton = new JButton("Clean"); + + 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; + + private Process compileProcess; + + static enum DialogState { + NO_SOURCE, SELECTED_SOURCE, IS_COMPILING, COMPILED_SOURCE + } + + public MicaELFCompiler(String target) { + this.target = target; + } + + private String getCompileCommand(String filename) { + if (customizedCompileCommand != null) { + return customizedCompileCommand; + } + return GUI.getExternalToolsSetting("PATH_MAKE") + " " + filename + getTargetFileExtension(target) + " 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, + final MessageList compilationOutput, boolean synchronous) throws Exception { + final File parentDirectory = sourceFile.getParentFile(); + + if (!sourceFile.getName().endsWith(".c")) { + logger.fatal("Source file does not end with '.c'"); + return; + } + + final String filenameNoExtension = sourceFile.getName().substring(0, + sourceFile.getName().length() - 2); + + final String command = getCompileCommand(filenameNoExtension); + logger.info("-- Compiling AVR/MicaZ Firmware --"); + + compileFirmware(command, sourceFile, filenameNoExtension + getTargetFileExtension(target), + parentDirectory, + successAction, failAction, + compilationOutput, synchronous); + } + + protected void compileFirmware( + final String command, final File sourceFile, + final String firmware, final File parentDirectory, + final Action successAction, final Action failAction, + final MessageList compilationOutput, boolean synchronous) throws Exception { + + if (compilationOutput != null) { + compilationOutput.clearMessages(); + } + + try { + logger.info("Compilation command: " + command); + compileProcess = Runtime.getRuntime().exec( + new String[] {"bash", "-c", command}, + null, + parentDirectory + ); + + final BufferedReader processNormal = new BufferedReader( + new InputStreamReader(compileProcess.getInputStream())); + final BufferedReader processError = new BufferedReader( + new InputStreamReader(compileProcess.getErrorStream())); + + final File ELFFile = new File(parentDirectory, firmware); + if (firmware != null) { + if (ELFFile.exists()) { + ELFFile.delete(); + if (ELFFile.exists()) { + if (compilationOutput != null) { + compilationOutput.addMessage("Error when deleting old " + ELFFile.getName(), MessageList.ERROR); + } + if (failAction != null) { + failAction.actionPerformed(null); + } + throw new MoteTypeCreationException("Error when deleting old " + + ELFFile.getName()); + } + } + } + + Thread readInput = new Thread(new Runnable() { + public void run() { + try { + String readLine; + while ((readLine = processNormal.readLine()) != null) { + if (compilationOutput != null) { + compilationOutput.addMessage(readLine, MessageList.NORMAL); + } + } + } catch (IOException e) { + logger.warn("Error while reading from process"); + } + } + }, "read input stream thread"); + + Thread readError = new Thread(new Runnable() { + public void run() { + try { + String readLine; + while ((readLine = processError.readLine()) != null) { + if (compilationOutput != null) { + compilationOutput.addMessage(readLine, MessageList.ERROR); + } + } + } 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) { + if (compilationOutput != null) { + compilationOutput.addMessage(e.getMessage(), MessageList.ERROR); + } + syncException.setCompilationOutput(new MessageList()); + syncException.fillInStackTrace(); + return; + } + + /* Check return value */ + if (compileProcess.exitValue() != 0) { + if (compilationOutput != null) { + compilationOutput.addMessage("Process returned error code " + compileProcess.exitValue(), MessageList.ERROR); + } + if (failAction != null) { + failAction.actionPerformed(null); + } + syncException.setCompilationOutput(new MessageList()); + syncException.fillInStackTrace(); + return; + } + + if (firmware == null) { + return; + } + + if (!ELFFile.exists()) { + if (compilationOutput != null) { + compilationOutput.addMessage("Can't locate output file " + ELFFile, MessageList.ERROR); + } + if (failAction != null) { + failAction.actionPerformed(null); + } + syncException.setCompilationOutput(new MessageList()); + syncException.fillInStackTrace(); + return; + } + + if (compilationOutput != null) { + compilationOutput.addMessage("", MessageList.NORMAL); + compilationOutput.addMessage("Compilation succeded", MessageList.NORMAL); + } + MicaELFCompiler.this.lastCompileCommand = command; + MicaELFCompiler.this.sourceFile = sourceFile; + MicaELFCompiler.this.ELFFile = ELFFile; + if (successAction != null) { + successAction.actionPerformed(null); + } + } + }, "handle compilation results"); + + readInput.start(); + readError.start(); + handleCompilationResultThread.start(); + + if (synchronous) { + try { + handleCompilationResultThread.join(); + } catch (Exception e) { + throw (MoteTypeCreationException) new MoteTypeCreationException( + "Compilation error: " + e.getMessage()).initCause(e); + } + + /* Detect error manually */ + if (syncException.hasCompilationOutput()) { + throw (MoteTypeCreationException) new MoteTypeCreationException( + "Bad return value").initCause(syncException); + } + } + + else { + } + } catch (IOException ex) { + if (failAction != null) { + failAction.actionPerformed(null); + } + throw (MoteTypeCreationException) new MoteTypeCreationException( + "Compilation error: " + ex.getMessage()).initCause(ex); + } + } + + public boolean showDialog(Container parentContainer, final MicaZMoteType moteType) { + + if (parentContainer instanceof Window) { + myDialog = new JDialog((Window)parentContainer, "Compile firmware file", ModalityType.APPLICATION_MODAL); + } else if (parentContainer instanceof Dialog) { + myDialog = new JDialog((Dialog)parentContainer, "Compile firmware file", ModalityType.APPLICATION_MODAL); + } else if (parentContainer instanceof Frame) { + myDialog = new JDialog((Frame)parentContainer, "Compile firmware file", ModalityType.APPLICATION_MODAL); + } else { + logger.fatal("Unknown parent container type: " + parentContainer); + return false; + } + + 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; + + if (compileProcess != null) { + compileProcess.destroy(); + } + myDialog.dispose(); + } + }); + + cleanButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + new Thread(new Runnable() { + public void run() { + try { + File parentDir = new File(sourceTextField.getText()).getParentFile(); + compileFirmware( + "make clean TARGET=" + target, new File(sourceTextField.getText()), null, + parentDir, null, null, taskOutput, true); + } catch (Exception e2) { + } + } + }).start(); + } + }); + + compileButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final File selectedSourceFile = new File(sourceTextField.getText()); + + /* Strip .c file extension */ + if (!selectedSourceFile.getName().endsWith(".c")) { + logger.fatal("Source file does not end with '.c'"); + return; + } + + final String filenameNoExtension = selectedSourceFile.getName() + .substring(0, selectedSourceFile.getName().length() - 2); + + final Action successAction = new AbstractAction() { + public void actionPerformed(ActionEvent e) { + updateDialog(DialogState.COMPILED_SOURCE); + File parentFile = selectedSourceFile.getParentFile(); + + sourceFile = selectedSourceFile; + ELFFile = new File(parentFile, filenameNoExtension + getTargetFileExtension(target)); + } + }; + final Action failAction = new AbstractAction() { + public void actionPerformed(ActionEvent e) { + updateDialog(DialogState.SELECTED_SOURCE); + } + }; + + updateDialog(DialogState.IS_COMPILING); + try { + new Thread(new Runnable() { + public void run() { + try { + compileFirmware(selectedSourceFile, + successAction, failAction, + taskOutput, false); + } catch (Exception e) { + e.printStackTrace(); + } + } + }).start(); + } catch (Exception e2) { + } + } + }); + + createButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + myDialog.dispose(); + } + }); + + buttonBox.add(cancelButton); + buttonBox.add(Box.createHorizontalStrut(5)); + buttonBox.add(cleanButton); + 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(parentContainer); + 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); + File elfFile = new File(getELFFile()); + label = new JLabel(elfFile.getName()); + label.setToolTipText(elfFile.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); + + // Icon (if available) + if (!GUI.isVisualizedInApplet()) { + Icon moteTypeIcon = getMoteTypeIcon(); + if (moteTypeIcon != null) { + smallPane = new JPanel(new BorderLayout()); + label = new JLabel(moteTypeIcon); + smallPane.add(BorderLayout.CENTER, label); + panel.add(smallPane); + } + } else { + smallPane = new JPanel(new BorderLayout()); + label = new JLabel("No icon available in applet mode"); + smallPane.add(BorderLayout.CENTER, label); + panel.add(smallPane); + } + + panel.add(Box.createRigidArea(new Dimension(0, 5))); + return panel; + } + + public Icon getMoteTypeIcon() { + return null; + } + + public ProjectConfig getConfig() { + logger.warn("MicaZ mote type project config not implemented"); + return null; + } + + public Collection getConfigXML() { + Vector config = new Vector(); + + 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"); + fileSource = GUI.stripAbsoluteContikiPath(fileSource); + element.setText(fileSource.getPath().replaceAll("\\\\", "/")); + config.add(element); + element = new Element("command"); + element.setText(compileCommand); + config.add(element); + } else { + // ELF file + element = new Element("elf"); + File file = new File(fileFirmware); + file = GUI.stripAbsoluteContikiPath(file); + fileFirmware = file.getAbsolutePath(); + element.setText(file.getPath().replaceAll("\\\\", "/")); + config.add(element); + } + + return config; + } + + public boolean setConfigXML(Simulation simulation, + Collection 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")) { + fileFirmware = new File(element.getText()).getAbsolutePath(); + } else { + logger.fatal("Unrecognized entry in loaded configuration: " + name); + throw new MoteTypeCreationException( + "Unrecognized entry in loaded configuration: " + name); + } + } + + return configureAndInit(GUI.getTopParentContainer(), simulation, visAvailable); + } + + @Override + public boolean configureAndInit(Container parentContainer, + Simulation simulation, boolean visAvailable) + throws MoteTypeCreationException { + if (GUI.isVisualizedInApplet()) { + String firmware = GUI.getExternalToolsSetting("MICAZ_FIRMWARE", ""); + if (!firmware.equals("")) { + setELFFile(new File(firmware)); + JOptionPane.showMessageDialog(GUI.getTopParentContainer(), + "Creating mote type from precompiled firmware: " + firmware, + "Compiled firmware file available", JOptionPane.INFORMATION_MESSAGE); + } else { + JOptionPane.showMessageDialog(GUI.getTopParentContainer(), + "No precompiled firmware found", + "Compiled firmware file not available", JOptionPane.ERROR_MESSAGE); + return false; + } + } + return configureAndInitMicaZType(parentContainer, simulation, visAvailable, target, targetNice); + } + +} diff --git a/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/interfaces/MicaZLED.java b/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/interfaces/MicaZLED.java new file mode 100755 index 000000000..46b9e63a1 --- /dev/null +++ b/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/interfaces/MicaZLED.java @@ -0,0 +1,195 @@ +/* + * 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: MicaZLED.java,v 1.1 2009/02/22 16:45:01 joxe Exp $ + */ + +package se.sics.cooja.avrmote.interfaces; + +import java.awt.*; +import java.util.*; +import javax.swing.*; +import org.apache.log4j.Logger; +import org.jdom.Element; + +import avrora.sim.FiniteStateMachine; +import avrora.sim.platform.MicaZ; +import se.sics.cooja.*; +import se.sics.cooja.interfaces.LED; + +/** + * @author Joakim Eriksson + */ +@ClassDescription("MicaZ LED") +public class MicaZLED extends LED { + private static Logger logger = Logger.getLogger(MicaZLED.class); + + private boolean blueOn = false; + private boolean greenOn = false; + private boolean redOn = false; + + private static final Color DARK_BLUE = new Color(0, 0, 100); + private static final Color DARK_GREEN = new Color(0, 100, 0); + private static final Color DARK_RED = new Color(100, 0, 0); + private static final Color BLUE = new Color(0, 0, 255); + private static final Color GREEN = new Color(0, 255, 0); + private static final Color RED = new Color(255, 0, 0); + + public MicaZLED(MicaZ micaZ) { + avrora.sim.platform.LED.LEDGroup leds = + (avrora.sim.platform.LED.LEDGroup) micaZ.getDevice("leds"); + leds.leds[0].getFSM().insertProbe(new FiniteStateMachine.Probe() { + public void fireAfterTransition(int old, int newstate) { + redOn = newstate > 0; + setChanged(); + notifyObservers(); + } + public void fireBeforeTransition(int arg0, int arg1) { + } + }); + leds.leds[1].getFSM().insertProbe(new FiniteStateMachine.Probe() { + public void fireAfterTransition(int old, int newstate) { + blueOn = newstate > 0; + setChanged(); + notifyObservers(); + } + public void fireBeforeTransition(int arg0, int arg1) { + } + }); + leds.leds[2].getFSM().insertProbe(new FiniteStateMachine.Probe() { + public void fireAfterTransition(int old, int newstate) { + greenOn = newstate > 0; + setChanged(); + notifyObservers(); + } + public void fireBeforeTransition(int arg0, int arg1) { + } + }); + } + + public boolean isAnyOn() { + return blueOn || greenOn || redOn; + } + + public boolean isGreenOn() { + return greenOn; + } + + public boolean isYellowOn() { + return blueOn; /* Returning blue */ + } + + public boolean isRedOn() { + return redOn; + } + + public double energyConsumption() { + return 0; + } + + public JPanel getInterfaceVisualizer() { + final JPanel panel = new JPanel() { + public void paintComponent(Graphics g) { + super.paintComponent(g); + + int x = 20; + int y = 25; + int d = 25; + + if (isGreenOn()) { + g.setColor(GREEN); + g.fillOval(x, y, d, d); + g.setColor(Color.BLACK); + g.drawOval(x, y, d, d); + } else { + g.setColor(DARK_GREEN); + g.fillOval(x + 5, y + 5, d-10, d-10); + } + + x += 40; + + if (isRedOn()) { + g.setColor(RED); + g.fillOval(x, y, d, d); + g.setColor(Color.BLACK); + g.drawOval(x, y, d, d); + } else { + g.setColor(DARK_RED); + g.fillOval(x + 5, y + 5, d-10, d-10); + } + + x += 40; + + if (isYellowOn()) { + g.setColor(BLUE); + g.fillOval(x, y, d, d); + g.setColor(Color.BLACK); + g.drawOval(x, y, d, d); + } else { + g.setColor(DARK_BLUE); + g.fillOval(x + 5, y + 5, d-10, d-10); + } + } + }; + + Observer observer; + this.addObserver(observer = new Observer() { + public void update(Observable obs, Object obj) { + panel.repaint(); + } + }); + + // Saving observer reference for releaseInterfaceVisualizer + panel.putClientProperty("intf_obs", observer); + + panel.setMinimumSize(new Dimension(140, 60)); + panel.setPreferredSize(new Dimension(140, 60)); + + return panel; + } + + public void releaseInterfaceVisualizer(JPanel panel) { + Observer observer = (Observer) panel.getClientProperty("intf_obs"); + if (observer == null) { + logger.fatal("Error when releasing panel, observer is null"); + return; + } + + this.deleteObserver(observer); + } + + + public Collection getConfigXML() { + return null; + } + + public void setConfigXML(Collection configXML, boolean visAvailable) { + } + +} + diff --git a/tools/cooja/config/external_tools_win32.config b/tools/cooja/config/external_tools_win32.config index 3101743c4..958007bc6 100644 --- a/tools/cooja/config/external_tools_win32.config +++ b/tools/cooja/config/external_tools_win32.config @@ -22,7 +22,7 @@ CONTIKI_STANDARD_PROCESSES = sensors_process;etimer_process CONTIKI_MAIN_TEMPLATE_FILENAME = contiki_template.c CORECOMM_TEMPLATE_FILENAME = corecomm_template.java PATH_JAVAC = javac -DEFAULT_PROJECTDIRS = ../apps/mrm;../apps/mspsim +DEFAULT_PROJECTDIRS = ../apps/mrm;../apps/mspsim;../apps/avrora PARSE_WITH_COMMAND = true PARSE_COMMAND=nm -C $(LIBFILE)