diff --git a/tools/cooja/apps/mspsim/cooja.config b/tools/cooja/apps/mspsim/cooja.config index 8ea0612c9..a0d48bbbc 100644 --- a/tools/cooja/apps/mspsim/cooja.config +++ b/tools/cooja/apps/mspsim/cooja.config @@ -1,3 +1,3 @@ se.sics.cooja.GUI.MOTETYPES = + se.sics.cooja.mspmote.ESBMoteType se.sics.cooja.mspmote.SkyMoteType se.sics.cooja.GUI.JARFILES = + cooja_mspsim.jar mspsim.jar -se.sics.cooja.GUI.PLUGINS = + se.sics.cooja.mspmote.plugins.MspCodeWatcher se.sics.cooja.mspmote.plugins.MspStackWatcher se.sics.cooja.mspmote.plugins.MspCycleWatcher +se.sics.cooja.GUI.PLUGINS = + se.sics.cooja.mspmote.plugins.MspCLI se.sics.cooja.mspmote.plugins.MspCodeWatcher se.sics.cooja.mspmote.plugins.MspStackWatcher se.sics.cooja.mspmote.plugins.MspCycleWatcher diff --git a/tools/cooja/apps/mspsim/lib/mspsim.jar b/tools/cooja/apps/mspsim/lib/mspsim.jar index d510628b4..507e36207 100644 Binary files a/tools/cooja/apps/mspsim/lib/mspsim.jar and b/tools/cooja/apps/mspsim/lib/mspsim.jar differ diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java index 79abb55fc..37e38bc2e 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ESBMote.java,v 1.3 2008/06/27 14:09:26 nifi Exp $ + * $Id: ESBMote.java,v 1.4 2008/10/13 14:50:50 nifi Exp $ */ package se.sics.cooja.mspmote; @@ -59,8 +59,7 @@ public class ESBMote extends MspMote { protected boolean initEmulator(File fileELF) { try { esbNode = new ESBNode(); - esbNode.setupNodePorts(); - prepareMote(fileELF, esbNode.getCPU()); + prepareMote(fileELF, esbNode); } catch (Exception e) { logger.fatal("Error when creating ESB mote:", e); diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java index c07b64d01..481a9ea07 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java @@ -26,21 +26,37 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: MspMote.java,v 1.13 2008/10/07 16:49:21 fros4943 Exp $ + * $Id: MspMote.java,v 1.14 2008/10/13 14:50:50 nifi Exp $ */ package se.sics.cooja.mspmote; - -import java.io.*; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; import java.net.URL; -import java.net.URLConnection; -import java.util.*; +import java.util.Collection; +import java.util.Observable; +import java.util.Observer; +import java.util.Vector; import org.apache.log4j.Logger; import org.jdom.Element; -import se.sics.cooja.*; +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.mspmote.interfaces.TR1001Radio; +import se.sics.mspsim.cli.CommandHandler; +import se.sics.mspsim.cli.LineListener; +import se.sics.mspsim.cli.LineOutputStream; import se.sics.mspsim.core.MSP430; -import se.sics.mspsim.util.*; +import se.sics.mspsim.platform.GenericNode; +import se.sics.mspsim.util.ConfigManager; +import se.sics.mspsim.util.ELF; +import se.sics.mspsim.util.MapEntry; +import se.sics.mspsim.util.MapTable; /** * @author Fredrik Osterlind @@ -56,6 +72,8 @@ public abstract class MspMote implements Mote { public int cycleDrift = 0; private Simulation mySimulation = null; + private CommandHandler commandHandler; + private LineListener commandListener; private MSP430 myCpu = null; private MspMoteType myMoteType = null; private MspMoteMemory myMemory = null; @@ -99,6 +117,20 @@ public abstract class MspMote implements Mote { } } + public void sendCLICommand(String line) { + if (commandHandler != null) { + commandHandler.lineRead(line); + } + } + + public boolean hasCLIListener() { + return this.commandListener != null; + } + + public void setCLIListener(LineListener listener) { + this.commandListener = listener; + } + /** * @return MSP430 CPU */ @@ -179,37 +211,36 @@ public abstract class MspMote implements Mote { * @param cpu MSP430 cpu * @throws IOException Preparing mote failed */ - protected void prepareMote(File fileELF, MSP430 cpu) throws IOException { - myCpu = cpu; - myCpu.setMonitorExec(true); + protected void prepareMote(File fileELF, GenericNode node) throws IOException { + LineOutputStream lout = new LineOutputStream(new LineListener() { + @Override + public void lineRead(String line) { + LineListener listener = commandListener; + if (listener != null) { + listener.lineRead(line); + } + }}); + PrintStream out = new PrintStream(lout); + this.commandHandler = new CommandHandler(out, out); + node.setCommandHandler(commandHandler); + + ConfigManager config = new ConfigManager(); + node.setup(config); + + this.myCpu = node.getCPU(); + this.myCpu.setMonitorExec(true); int[] memory = myCpu.getMemory(); - if (GUI.isVisualizedInApplet()) { - URLConnection urlConnection = new URL(GUI.getAppletCodeBase(), fileELF.getName()).openConnection(); - urlConnection.setDoInput(true); - urlConnection.setUseCaches(false); - DataInputStream inputStream = new DataInputStream(urlConnection.getInputStream()); - ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); - byte[] firmwareData = new byte[2048]; - for(int read; (read = inputStream.read(firmwareData)) != -1; byteStream.write(firmwareData, 0, read)) { } - inputStream.close(); - firmwareData = null; - firmwareData = byteStream.toByteArray(); - - myELFModule = new ELF(firmwareData); - myELFModule.readAll(); + myELFModule = node.loadFirmware(new URL(GUI.getAppletCodeBase(), fileELF.getName()), memory); } else { - myELFModule = ELF.readELF(fileELF.getPath()); + myELFModule = node.loadFirmware(fileELF.getPath(), memory); } - 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 */ + MapTable map = myELFModule.getMap(); MapEntry[] allEntries = map.getAllEntries(); myMemory = new MspMoteMemory(allEntries, myCpu); @@ -360,7 +391,7 @@ public abstract class MspMote implements Mote { element = new Element("interface_config"); element.setText(moteInterface.getClass().getName()); - Collection interfaceXML = moteInterface.getConfigXML(); + Collection interfaceXML = moteInterface.getConfigXML(); if (interfaceXML != null) { element.addContent(interfaceXML); config.add(element); @@ -372,7 +403,7 @@ public abstract class MspMote implements Mote { element = new Element("interface_config"); element.setText(moteInterface.getClass().getName()); - Collection interfaceXML = moteInterface.getConfigXML(); + Collection interfaceXML = moteInterface.getConfigXML(); if (interfaceXML != null) { element.addContent(interfaceXML); config.add(element); @@ -383,4 +414,3 @@ public abstract class MspMote implements Mote { } } - diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/SkyMote.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/SkyMote.java index d7e508fcd..5aadfdb22 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/SkyMote.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/SkyMote.java @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: SkyMote.java,v 1.6 2008/10/09 11:11:30 joxe Exp $ + * $Id: SkyMote.java,v 1.7 2008/10/13 14:50:50 nifi Exp $ */ package se.sics.cooja.mspmote; @@ -59,8 +59,7 @@ public class SkyMote extends MspMote { protected boolean initEmulator(File fileELF) { try { skyNode = new SkyNode(); - skyNode.setupNodePorts(false); - prepareMote(fileELF, skyNode.getCPU()); + prepareMote(fileELF, skyNode); } catch (Exception e) { logger.fatal("Error when creating Sky mote:", e); diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCLI.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCLI.java new file mode 100644 index 000000000..95b832119 --- /dev/null +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/MspCLI.java @@ -0,0 +1,211 @@ +/* + * 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: MspCLI.java,v 1.1 2008/10/13 14:50:50 nifi Exp $ + */ + +package se.sics.cooja.mspmote.plugins; +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import se.sics.cooja.ClassDescription; +import se.sics.cooja.GUI; +import se.sics.cooja.Mote; +import se.sics.cooja.PluginType; +import se.sics.cooja.Simulation; +import se.sics.cooja.VisPlugin; +import se.sics.cooja.mspmote.MspMote; +import se.sics.mspsim.cli.LineListener; + +@ClassDescription("Msp CLI") +@PluginType(PluginType.MOTE_PLUGIN) +public class MspCLI extends VisPlugin { + + private static final long serialVersionUID = 2833218439838209672L; + + private MspMote mspMote; + private JTextArea logArea; + private JTextField commandField; + private String[] history = new String[50]; + private int historyPos = 0; + private int historyCount = 0; + + private LineListener myListener; + + public MspCLI(Mote mote, Simulation simulationToVisualize, GUI gui) { + super("Msp CLI (" + mote.getInterfaces().getMoteID().getMoteID() + ')', gui); + this.mspMote = (MspMote) mote; + + final Container panel = getContentPane(); + + logArea = new JTextArea(4, 30); + logArea.setTabSize(4); + logArea.setEditable(false); + panel.add(new JScrollPane(logArea), BorderLayout.CENTER); + + JPopupMenu popupMenu = new JPopupMenu(); + JMenuItem clearItem = new JMenuItem("Clear"); + clearItem.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + logArea.setText(""); + } + + }); + popupMenu.add(clearItem); + logArea.setComponentPopupMenu(popupMenu); + + ActionListener action = new ActionListener() { + + public void actionPerformed(ActionEvent e) { + String command = trim(commandField.getText()); + if (command != null) { + try { + int previous = historyCount - 1; + if (previous < 0) previous += history.length; + if (!command.equals(history[previous])) { + history[historyCount] = command; + historyCount = (historyCount + 1) % history.length; + } + historyPos = historyCount; + addCLIData("> " + command); + mspMote.sendCLICommand(command); + commandField.setText(""); + } catch (Exception ex) { + System.err.println("could not send '" + command + "':"); + ex.printStackTrace(); + JOptionPane.showMessageDialog(panel, + "could not send '" + command + "':\n" + + ex, "ERROR", + JOptionPane.ERROR_MESSAGE); + } + } else { + commandField.getToolkit().beep(); + } + } + + }; + commandField = new JTextField(); + commandField.addActionListener(action); + commandField.addKeyListener(new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + switch (e.getKeyCode()) { + case KeyEvent.VK_UP: { + int nextPos = (historyPos + history.length - 1) % history.length; + if (nextPos == historyCount || history[nextPos] == null) { + commandField.getToolkit().beep(); + } else { + String cmd = trim(commandField.getText()); + if (cmd != null) { + history[historyPos] = cmd; + } + historyPos = nextPos; + commandField.setText(history[historyPos]); + } + break; + } + case KeyEvent.VK_DOWN: { + int nextPos = (historyPos + 1) % history.length; + if (nextPos == historyCount) { + historyPos = nextPos; + commandField.setText(""); + } else if (historyPos == historyCount || history[nextPos] == null) { + commandField.getToolkit().beep(); + } else { + String cmd = trim(commandField.getText()); + if (cmd != null) { + history[historyPos] = cmd; + } + historyPos = nextPos; + commandField.setText(history[historyPos]); + } + break; + } + } + } + + }); + panel.add(commandField, BorderLayout.SOUTH); + + if (mspMote.hasCLIListener()) { + logArea.setText("*** CLI already occupied by another listener ***"); + } else { + myListener = new LineListener() { + @Override + public void lineRead(String line) { + addCLIData(line); + } + }; + mspMote.setCLIListener(myListener); + } + // Tries to select this plugin + try { + setSelected(true); + } catch (java.beans.PropertyVetoException e) { + // Could not select + } + } + + public void closePlugin() { + if (myListener != null) { + mspMote.setCLIListener(null); + } + } + + public void addCLIData(final String text) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + String current = logArea.getText(); + int len = current.length(); + if (len > 4096) { + current = current.substring(len - 4096); + } + current = len > 0 ? (current + '\n' + text) : text; + logArea.setText(current); + logArea.setCaretPosition(current.length()); + } + }); + } + + private String trim(String text) { + return (text != null) && ((text = text.trim()).length() > 0) ? text : null; + } + +}