Merge branch 'master' of ssh://contiki.git.sourceforge.net/gitroot/contiki/contiki
This commit is contained in:
commit
2e961f8ef2
8 changed files with 2172 additions and 28 deletions
|
@ -144,7 +144,7 @@ collect_common_send(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rtmetric = dag->rank;
|
rtmetric = dag->rank;
|
||||||
beacon_interval = (uint16_t) ((2L << dag->dio_intcurrent) / 1000);
|
beacon_interval = (uint16_t) ((2L << dag->instance->dio_intcurrent) / 1000);
|
||||||
num_neighbors = RPL_PARENT_COUNT(dag);
|
num_neighbors = RPL_PARENT_COUNT(dag);
|
||||||
} else {
|
} else {
|
||||||
rtmetric = 0;
|
rtmetric = 0;
|
||||||
|
|
|
@ -271,4 +271,8 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote {
|
||||||
return "MicaZ " + getID();
|
return "MicaZ " + getID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MemoryMonitor createMemoryMonitor(MemoryEventHandler meh) {
|
||||||
|
logger.fatal("Not implemented");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,16 +57,21 @@ import se.sics.cooja.motes.AbstractEmulatedMote;
|
||||||
import se.sics.cooja.mspmote.interfaces.MspSerial;
|
import se.sics.cooja.mspmote.interfaces.MspSerial;
|
||||||
import se.sics.cooja.mspmote.plugins.CodeVisualizerSkin;
|
import se.sics.cooja.mspmote.plugins.CodeVisualizerSkin;
|
||||||
import se.sics.cooja.mspmote.plugins.MspBreakpointContainer;
|
import se.sics.cooja.mspmote.plugins.MspBreakpointContainer;
|
||||||
|
import se.sics.cooja.plugins.BufferListener.BufferAccess;
|
||||||
import se.sics.cooja.plugins.Visualizer;
|
import se.sics.cooja.plugins.Visualizer;
|
||||||
import se.sics.mspsim.cli.CommandHandler;
|
import se.sics.mspsim.cli.CommandHandler;
|
||||||
import se.sics.mspsim.cli.LineListener;
|
import se.sics.mspsim.cli.LineListener;
|
||||||
import se.sics.mspsim.cli.LineOutputStream;
|
import se.sics.mspsim.cli.LineOutputStream;
|
||||||
|
import se.sics.mspsim.core.CPUMonitor;
|
||||||
import se.sics.mspsim.core.EmulationException;
|
import se.sics.mspsim.core.EmulationException;
|
||||||
import se.sics.mspsim.core.MSP430;
|
import se.sics.mspsim.core.MSP430;
|
||||||
|
import se.sics.mspsim.core.MSP430Constants;
|
||||||
import se.sics.mspsim.platform.GenericNode;
|
import se.sics.mspsim.platform.GenericNode;
|
||||||
import se.sics.mspsim.ui.JFrameWindowManager;
|
import se.sics.mspsim.ui.JFrameWindowManager;
|
||||||
import se.sics.mspsim.util.ComponentRegistry;
|
import se.sics.mspsim.util.ComponentRegistry;
|
||||||
import se.sics.mspsim.util.ConfigManager;
|
import se.sics.mspsim.util.ConfigManager;
|
||||||
|
import se.sics.mspsim.util.DebugInfo;
|
||||||
|
import se.sics.mspsim.util.ELF;
|
||||||
import se.sics.mspsim.util.MapEntry;
|
import se.sics.mspsim.util.MapEntry;
|
||||||
import se.sics.mspsim.util.MapTable;
|
import se.sics.mspsim.util.MapTable;
|
||||||
|
|
||||||
|
@ -484,7 +489,163 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getExecutionDetails() {
|
public String getExecutionDetails() {
|
||||||
return executeCLICommand("stacktrace");
|
return executeCLICommand("stacktrace");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPCString() {
|
||||||
|
int pc = myCpu.reg[MSP430Constants.PC];
|
||||||
|
ELF elf = (ELF)myCpu.getRegistry().getComponent(ELF.class);
|
||||||
|
DebugInfo di = elf.getDebugInfo(pc);
|
||||||
|
|
||||||
|
/* Following code examples from MSPsim, DebugCommands.java */
|
||||||
|
if (di == null) {
|
||||||
|
di = elf.getDebugInfo(pc + 1);
|
||||||
|
}
|
||||||
|
if (di == null) {
|
||||||
|
/* Return PC value */
|
||||||
|
return String.format("*%02x", myCpu.reg[MSP430Constants.PC]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lineNo = di.getLine();
|
||||||
|
String file = di.getFile();
|
||||||
|
file = file==null?"?":file;
|
||||||
|
if (file.contains("/")) {
|
||||||
|
/* strip path */
|
||||||
|
file = file.substring(file.lastIndexOf('/')+1, file.length());
|
||||||
|
}
|
||||||
|
String function = di.getFunction();
|
||||||
|
function = function==null?"?":function;
|
||||||
|
if (function.contains(":")) {
|
||||||
|
/* strip arguments */
|
||||||
|
function = function.substring(0, function.lastIndexOf(':'));
|
||||||
|
}
|
||||||
|
return file + ":" + function + ":" + lineNo;
|
||||||
|
|
||||||
|
/*return executeCLICommand("line " + myCpu.reg[MSP430Constants.PC]);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MultiCPUMonitor implements CPUMonitor {
|
||||||
|
private ArrayList<CPUMonitor> ms = new ArrayList<CPUMonitor>();
|
||||||
|
public void add(CPUMonitor m) {
|
||||||
|
ms.add(m);
|
||||||
|
}
|
||||||
|
public void remove(CPUMonitor m) {
|
||||||
|
ms.remove(m);
|
||||||
|
}
|
||||||
|
public void cpuAction(int type, int adr, int data) {
|
||||||
|
for (CPUMonitor m: ms) {
|
||||||
|
m.cpuAction(type, adr, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public MemoryMonitor createMemoryMonitor(final MemoryEventHandler meh) {
|
||||||
|
return new MemoryMonitor() {
|
||||||
|
private boolean started = false;
|
||||||
|
private int address = -1;
|
||||||
|
private int size = -1;
|
||||||
|
private CPUMonitor myMonitor = null;
|
||||||
|
private boolean isPointer = false;
|
||||||
|
private MemoryMonitor pointedMemory = null;
|
||||||
|
public boolean start(int address, int size) {
|
||||||
|
if (started) {
|
||||||
|
return started;
|
||||||
|
}
|
||||||
|
|
||||||
|
final MemoryMonitor thisMonitor = this;
|
||||||
|
myMonitor = new CPUMonitor() {
|
||||||
|
public void cpuAction(int type, int adr, int data) {
|
||||||
|
MemoryEventType t;
|
||||||
|
if (type == CPUMonitor.MEMORY_WRITE) {
|
||||||
|
t = MemoryEventType.WRITE;
|
||||||
|
} else if (type == CPUMonitor.MEMORY_READ) {
|
||||||
|
t = MemoryEventType.READ;
|
||||||
|
} else {
|
||||||
|
t = MemoryEventType.UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
meh.event(thisMonitor, t, adr, data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TODO Make sure no other part of Cooja overrides this! */
|
||||||
|
|
||||||
|
for (int a = address; a < address+size; a++) {
|
||||||
|
if (myCpu.hasBreakPoint(a)) {
|
||||||
|
if (myCpu.breakPoints[a] instanceof MultiCPUMonitor) {
|
||||||
|
/* Extend */
|
||||||
|
((MultiCPUMonitor)myCpu.breakPoints[a]).add(myMonitor);
|
||||||
|
} else {
|
||||||
|
/* Create multi and replace */
|
||||||
|
CPUMonitor existingMonitor = myCpu.breakPoints[a];
|
||||||
|
MultiCPUMonitor multiMonitor = new MultiCPUMonitor();
|
||||||
|
multiMonitor.add(existingMonitor);
|
||||||
|
multiMonitor.add(myMonitor);
|
||||||
|
myCpu.clearBreakPoint(a);
|
||||||
|
myCpu.setBreakPoint(a, multiMonitor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
myCpu.setBreakPoint(a, myMonitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.address = address;
|
||||||
|
this.size = size;
|
||||||
|
started = true;
|
||||||
|
return started;
|
||||||
|
}
|
||||||
|
public void stop() {
|
||||||
|
if (!started) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
started = false;
|
||||||
|
|
||||||
|
for (int a = address; a < address+size; a++) {
|
||||||
|
if (!myCpu.hasBreakPoint(a)) {
|
||||||
|
logger.fatal("Memory breakpoint was previously removed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myCpu.breakPoints[a] instanceof MultiCPUMonitor) {
|
||||||
|
/* Remove */
|
||||||
|
((MultiCPUMonitor)myCpu.breakPoints[a]).remove(myMonitor);
|
||||||
|
} else {
|
||||||
|
/* Clear */
|
||||||
|
if (myCpu.breakPoints[a] != myMonitor) {
|
||||||
|
logger.fatal("Memory breakpoint is not mine");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
myCpu.clearBreakPoint(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Mote getMote() {
|
||||||
|
return MspMote.this;
|
||||||
|
}
|
||||||
|
public int getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPointer() {
|
||||||
|
return isPointer;
|
||||||
|
}
|
||||||
|
public void setPointer(boolean isPointer, MemoryMonitor pointedMemory) {
|
||||||
|
this.isPointer = isPointer;
|
||||||
|
this.pointedMemory = pointedMemory;
|
||||||
|
}
|
||||||
|
public MemoryMonitor getPointedMemory() {
|
||||||
|
return pointedMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BufferAccess lastBufferAccess = null;
|
||||||
|
public void setLastBufferAccess(BufferAccess ba) {
|
||||||
|
this.lastBufferAccess = ba;
|
||||||
|
}
|
||||||
|
public BufferAccess getLastBufferAccess() {
|
||||||
|
return lastBufferAccess;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ se.sics.cooja.contikimote.interfaces.ContikiRadio.RADIO_TRANSMISSION_RATE_kbps =
|
||||||
se.sics.cooja.contikimote.ContikiMoteType.MOTE_INTERFACES = se.sics.cooja.interfaces.Position se.sics.cooja.interfaces.Battery se.sics.cooja.contikimote.interfaces.ContikiVib se.sics.cooja.contikimote.interfaces.ContikiMoteID se.sics.cooja.contikimote.interfaces.ContikiRS232 se.sics.cooja.contikimote.interfaces.ContikiBeeper se.sics.cooja.interfaces.RimeAddress se.sics.cooja.contikimote.interfaces.ContikiIPAddress se.sics.cooja.contikimote.interfaces.ContikiRadio se.sics.cooja.contikimote.interfaces.ContikiButton se.sics.cooja.contikimote.interfaces.ContikiPIR se.sics.cooja.contikimote.interfaces.ContikiClock se.sics.cooja.contikimote.interfaces.ContikiLED se.sics.cooja.contikimote.interfaces.ContikiCFS se.sics.cooja.interfaces.Mote2MoteRelations se.sics.cooja.interfaces.MoteAttributes
|
se.sics.cooja.contikimote.ContikiMoteType.MOTE_INTERFACES = se.sics.cooja.interfaces.Position se.sics.cooja.interfaces.Battery se.sics.cooja.contikimote.interfaces.ContikiVib se.sics.cooja.contikimote.interfaces.ContikiMoteID se.sics.cooja.contikimote.interfaces.ContikiRS232 se.sics.cooja.contikimote.interfaces.ContikiBeeper se.sics.cooja.interfaces.RimeAddress se.sics.cooja.contikimote.interfaces.ContikiIPAddress se.sics.cooja.contikimote.interfaces.ContikiRadio se.sics.cooja.contikimote.interfaces.ContikiButton se.sics.cooja.contikimote.interfaces.ContikiPIR se.sics.cooja.contikimote.interfaces.ContikiClock se.sics.cooja.contikimote.interfaces.ContikiLED se.sics.cooja.contikimote.interfaces.ContikiCFS se.sics.cooja.interfaces.Mote2MoteRelations se.sics.cooja.interfaces.MoteAttributes
|
||||||
se.sics.cooja.contikimote.ContikiMoteType.C_SOURCES =
|
se.sics.cooja.contikimote.ContikiMoteType.C_SOURCES =
|
||||||
se.sics.cooja.GUI.MOTETYPES = se.sics.cooja.motes.ImportAppMoteType se.sics.cooja.motes.DisturberMoteType se.sics.cooja.contikimote.ContikiMoteType
|
se.sics.cooja.GUI.MOTETYPES = se.sics.cooja.motes.ImportAppMoteType se.sics.cooja.motes.DisturberMoteType se.sics.cooja.contikimote.ContikiMoteType
|
||||||
se.sics.cooja.GUI.PLUGINS = se.sics.cooja.plugins.Visualizer se.sics.cooja.plugins.LogListener se.sics.cooja.plugins.TimeLine se.sics.cooja.plugins.MoteInformation se.sics.cooja.plugins.MoteInterfaceViewer se.sics.cooja.plugins.VariableWatcher se.sics.cooja.plugins.EventListener se.sics.cooja.plugins.RadioLogger se.sics.cooja.plugins.ScriptRunner se.sics.cooja.plugins.Notes
|
se.sics.cooja.GUI.PLUGINS = se.sics.cooja.plugins.Visualizer se.sics.cooja.plugins.LogListener se.sics.cooja.plugins.TimeLine se.sics.cooja.plugins.MoteInformation se.sics.cooja.plugins.MoteInterfaceViewer se.sics.cooja.plugins.VariableWatcher se.sics.cooja.plugins.EventListener se.sics.cooja.plugins.RadioLogger se.sics.cooja.plugins.ScriptRunner se.sics.cooja.plugins.Notes se.sics.cooja.plugins.BufferListener
|
||||||
se.sics.cooja.GUI.IP_DISTRIBUTORS = se.sics.cooja.ipdistributors.RandomIPDistributor se.sics.cooja.ipdistributors.SpatialIPDistributor se.sics.cooja.ipdistributors.IdIPDistributor
|
se.sics.cooja.GUI.IP_DISTRIBUTORS = se.sics.cooja.ipdistributors.RandomIPDistributor se.sics.cooja.ipdistributors.SpatialIPDistributor se.sics.cooja.ipdistributors.IdIPDistributor
|
||||||
se.sics.cooja.GUI.POSITIONERS = se.sics.cooja.positioners.RandomPositioner se.sics.cooja.positioners.LinearPositioner se.sics.cooja.positioners.EllipsePositioner se.sics.cooja.positioners.ManualPositioner
|
se.sics.cooja.GUI.POSITIONERS = se.sics.cooja.positioners.RandomPositioner se.sics.cooja.positioners.LinearPositioner se.sics.cooja.positioners.EllipsePositioner se.sics.cooja.positioners.ManualPositioner
|
||||||
se.sics.cooja.GUI.RADIOMEDIUMS = se.sics.cooja.radiomediums.UDGM se.sics.cooja.radiomediums.UDGMConstantLoss se.sics.cooja.radiomediums.DirectedGraphMedium se.sics.cooja.radiomediums.SilentRadioMedium
|
se.sics.cooja.GUI.RADIOMEDIUMS = se.sics.cooja.radiomediums.UDGM se.sics.cooja.radiomediums.UDGMConstantLoss se.sics.cooja.radiomediums.DirectedGraphMedium se.sics.cooja.radiomediums.SilentRadioMedium
|
||||||
|
|
|
@ -139,7 +139,7 @@ public class IPAddress extends MoteInterface {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String compressIPv6Address(String ipString) {
|
public static String compressIPv6Address(String ipString) {
|
||||||
while (ipString.contains(":0000:")) {
|
while (ipString.contains(":0000:")) {
|
||||||
ipString = ipString.replaceAll(":0000:", "::");
|
ipString = ipString.replaceAll(":0000:", "::");
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
package se.sics.cooja.motes;
|
package se.sics.cooja.motes;
|
||||||
|
|
||||||
import se.sics.cooja.Mote;
|
import se.sics.cooja.Mote;
|
||||||
|
import se.sics.cooja.plugins.BufferListener;
|
||||||
|
import se.sics.cooja.plugins.BufferListener.BufferAccess;
|
||||||
|
import se.sics.cooja.plugins.TimeLine;
|
||||||
|
|
||||||
public abstract class AbstractEmulatedMote extends AbstractWakeupMote implements Mote {
|
public abstract class AbstractEmulatedMote extends AbstractWakeupMote implements Mote {
|
||||||
|
|
||||||
|
@ -42,8 +45,42 @@ public abstract class AbstractEmulatedMote extends AbstractWakeupMote implements
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Execution details, for instance a stack trace
|
* @return Execution details, for instance a stack trace
|
||||||
|
* @see TimeLine
|
||||||
*/
|
*/
|
||||||
public String getExecutionDetails() {
|
public String getExecutionDetails() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return One-liner describing current PC, for instance source file and line.
|
||||||
|
* May return null.
|
||||||
|
*
|
||||||
|
* @see BufferListener
|
||||||
|
*/
|
||||||
|
public String getPCString() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface MemoryMonitor {
|
||||||
|
public boolean start(int address, int size);
|
||||||
|
public void stop();
|
||||||
|
public Mote getMote();
|
||||||
|
public int getAddress();
|
||||||
|
public int getSize();
|
||||||
|
|
||||||
|
public void setLastBufferAccess(BufferAccess ba);
|
||||||
|
public BufferAccess getLastBufferAccess();
|
||||||
|
|
||||||
|
public boolean isPointer();
|
||||||
|
public void setPointer(boolean isPointer, MemoryMonitor pointedMemory);
|
||||||
|
public MemoryMonitor getPointedMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MemoryEventType { READ, WRITE, UNKNOWN };
|
||||||
|
public interface MemoryEventHandler {
|
||||||
|
public void event(MemoryMonitor mm, MemoryEventType type, int adr, int data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract MemoryMonitor createMemoryMonitor(MemoryEventHandler meh);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
1831
tools/cooja/java/se/sics/cooja/plugins/BufferListener.java
Normal file
1831
tools/cooja/java/se/sics/cooja/plugins/BufferListener.java
Normal file
File diff suppressed because it is too large
Load diff
|
@ -48,9 +48,11 @@ import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.PatternSyntaxException;
|
import java.util.regex.PatternSyntaxException;
|
||||||
|
|
||||||
|
@ -146,6 +148,8 @@ public class LogListener extends VisPlugin {
|
||||||
private boolean hideDebug = false;
|
private boolean hideDebug = false;
|
||||||
private JCheckBoxMenuItem hideDebugCheckbox;
|
private JCheckBoxMenuItem hideDebugCheckbox;
|
||||||
|
|
||||||
|
private JCheckBoxMenuItem appendCheckBox;
|
||||||
|
|
||||||
private static final int UPDATE_INTERVAL = 250;
|
private static final int UPDATE_INTERVAL = 250;
|
||||||
private UpdateAggregator<LogData> logUpdateAggregator = new UpdateAggregator<LogData>(UPDATE_INTERVAL) {
|
private UpdateAggregator<LogData> logUpdateAggregator = new UpdateAggregator<LogData>(UPDATE_INTERVAL) {
|
||||||
private Runnable scroll = new Runnable() {
|
private Runnable scroll = new Runnable() {
|
||||||
|
@ -348,6 +352,8 @@ public class LogListener extends VisPlugin {
|
||||||
popupMenu.add(new JMenuItem(clearAction));
|
popupMenu.add(new JMenuItem(clearAction));
|
||||||
popupMenu.addSeparator();
|
popupMenu.addSeparator();
|
||||||
popupMenu.add(new JMenuItem(saveAction));
|
popupMenu.add(new JMenuItem(saveAction));
|
||||||
|
appendCheckBox = new JCheckBoxMenuItem(appendAction);
|
||||||
|
popupMenu.add(appendCheckBox);
|
||||||
popupMenu.addSeparator();
|
popupMenu.addSeparator();
|
||||||
JMenu focusMenu = new JMenu("Show in");
|
JMenu focusMenu = new JMenu("Show in");
|
||||||
focusMenu.add(new JMenuItem(showInAllAction));
|
focusMenu.add(new JMenuItem(showInAllAction));
|
||||||
|
@ -436,7 +442,16 @@ public class LogListener extends VisPlugin {
|
||||||
hasHours = true;
|
hasHours = true;
|
||||||
repaintTimeColumn();
|
repaintTimeColumn();
|
||||||
}
|
}
|
||||||
logUpdateAggregator.add(new LogData(ev));
|
LogData data = new LogData(ev);
|
||||||
|
logUpdateAggregator.add(data);
|
||||||
|
if (appendToFile) {
|
||||||
|
appendToFile(appendStreamFile,
|
||||||
|
data.getTime() + "\t" +
|
||||||
|
data.getID() + "\t" +
|
||||||
|
data.ev.getMessage() + "\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public void removedLogOutput(LogOutputEvent ev) {
|
public void removedLogOutput(LogOutputEvent ev) {
|
||||||
}
|
}
|
||||||
|
@ -498,6 +513,7 @@ public class LogListener extends VisPlugin {
|
||||||
|
|
||||||
public void closePlugin() {
|
public void closePlugin() {
|
||||||
/* Stop observing motes */
|
/* Stop observing motes */
|
||||||
|
appendToFile(null, null);
|
||||||
logUpdateAggregator.stop();
|
logUpdateAggregator.stop();
|
||||||
simulation.getEventCentral().removeLogOutputListener(logOutputListener);
|
simulation.getEventCentral().removeLogOutputListener(logOutputListener);
|
||||||
}
|
}
|
||||||
|
@ -526,6 +542,11 @@ public class LogListener extends VisPlugin {
|
||||||
element = new Element("inversefilter");
|
element = new Element("inversefilter");
|
||||||
config.add(element);
|
config.add(element);
|
||||||
}
|
}
|
||||||
|
if (appendToFile) {
|
||||||
|
element = new Element("append");
|
||||||
|
element.setText(simulation.getGUI().createPortablePath(appendStreamFile).getPath());
|
||||||
|
config.add(element);
|
||||||
|
}
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,6 +572,16 @@ public class LogListener extends VisPlugin {
|
||||||
} else if ("formatted_time".equals(name)) {
|
} else if ("formatted_time".equals(name)) {
|
||||||
formatTimeString = true;
|
formatTimeString = true;
|
||||||
repaintTimeColumn();
|
repaintTimeColumn();
|
||||||
|
} else if ("append".equals(name)) {
|
||||||
|
appendToFile = true;
|
||||||
|
appendStreamFile = simulation.getGUI().restorePortablePath(new File(element.getText()));
|
||||||
|
appendCheckBox.setSelected(true);
|
||||||
|
if (!appendStreamFile.exists()) {
|
||||||
|
try {
|
||||||
|
appendStreamFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,29 +656,29 @@ public class LogListener extends VisPlugin {
|
||||||
this.ev = ev;
|
this.ev = ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getID() {
|
public String getID() {
|
||||||
return "ID:" + ev.getMote().getID();
|
return "ID:" + ev.getMote().getID();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTime() {
|
public String getTime() {
|
||||||
if (formatTimeString) {
|
if (formatTimeString) {
|
||||||
long t = ev.getTime();
|
long t = ev.getTime();
|
||||||
long h = (t / TIME_HOUR);
|
long h = (t / TIME_HOUR);
|
||||||
t -= (t / TIME_HOUR)*TIME_HOUR;
|
t -= (t / TIME_HOUR)*TIME_HOUR;
|
||||||
long m = (t / TIME_MINUTE);
|
long m = (t / TIME_MINUTE);
|
||||||
t -= (t / TIME_MINUTE)*TIME_MINUTE;
|
t -= (t / TIME_MINUTE)*TIME_MINUTE;
|
||||||
long s = (t / TIME_SECOND);
|
long s = (t / TIME_SECOND);
|
||||||
t -= (t / TIME_SECOND)*TIME_SECOND;
|
t -= (t / TIME_SECOND)*TIME_SECOND;
|
||||||
long ms = t / Simulation.MILLISECOND;
|
long ms = t / Simulation.MILLISECOND;
|
||||||
if (hasHours) {
|
if (hasHours) {
|
||||||
return String.format("%d:%02d:%02d.%03d", h,m,s,ms);
|
return String.format("%d:%02d:%02d.%03d", h,m,s,ms);
|
||||||
} else {
|
} else {
|
||||||
return String.format("%02d:%02d.%03d", m,s,ms);
|
return String.format("%02d:%02d.%03d", m,s,ms);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return "" + ev.getTime() / Simulation.MILLISECOND;
|
return "" + ev.getTime() / Simulation.MILLISECOND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Action saveAction = new AbstractAction("Save to file") {
|
private Action saveAction = new AbstractAction("Save to file") {
|
||||||
|
@ -699,6 +730,86 @@ public class LogListener extends VisPlugin {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private boolean appendToFile = false;
|
||||||
|
private File appendStreamFile = null;
|
||||||
|
private boolean appendToFileWroteHeader = false;
|
||||||
|
private PrintWriter appendStream = null;
|
||||||
|
public boolean appendToFile(File file, String text) {
|
||||||
|
/* Close stream */
|
||||||
|
if (file == null) {
|
||||||
|
if (appendStream != null) {
|
||||||
|
appendStream.close();
|
||||||
|
appendStream = null;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open stream */
|
||||||
|
if (appendStream == null || file != appendStreamFile) {
|
||||||
|
try {
|
||||||
|
if (appendStream != null) {
|
||||||
|
appendStream.close();
|
||||||
|
appendStream = null;
|
||||||
|
}
|
||||||
|
appendStream = new PrintWriter(new FileWriter(file,true));
|
||||||
|
appendStreamFile = file;
|
||||||
|
appendToFileWroteHeader = false;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.fatal("Append file failed: " + ex.getMessage(), ex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append to file */
|
||||||
|
if (!appendToFileWroteHeader) {
|
||||||
|
appendStream.println("-- Log Listener [" + simulation.getTitle() + "]: Started at " + (new Date()).toString());
|
||||||
|
appendToFileWroteHeader = true;
|
||||||
|
}
|
||||||
|
appendStream.print(text);
|
||||||
|
appendStream.flush();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Action appendAction = new AbstractAction("Append to file") {
|
||||||
|
private static final long serialVersionUID = -3041714249257346688L;
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
JCheckBoxMenuItem cb = (JCheckBoxMenuItem) e.getSource();
|
||||||
|
appendToFile = cb.isSelected();
|
||||||
|
if (!appendToFile) {
|
||||||
|
appendToFile(null, null);
|
||||||
|
appendStreamFile = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JFileChooser fc = new JFileChooser();
|
||||||
|
File suggest = new File(GUI.getExternalToolsSetting("LOG_LISTENER_APPENDFILE", "loglistener_append.txt"));
|
||||||
|
fc.setSelectedFile(suggest);
|
||||||
|
int returnVal = fc.showSaveDialog(GUI.getTopParentContainer());
|
||||||
|
if (returnVal != JFileChooser.APPROVE_OPTION) {
|
||||||
|
appendToFile = false;
|
||||||
|
cb.setSelected(appendToFile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File saveFile = fc.getSelectedFile();
|
||||||
|
GUI.setExternalToolsSetting("LOG_LISTENER_APPENDFILE", saveFile.getPath());
|
||||||
|
if (saveFile.exists() && !saveFile.canWrite()) {
|
||||||
|
logger.fatal("No write access to file: " + saveFile);
|
||||||
|
appendToFile = false;
|
||||||
|
cb.setSelected(appendToFile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
appendToFile = true;
|
||||||
|
appendStreamFile = saveFile;
|
||||||
|
if (!appendStreamFile.exists()) {
|
||||||
|
try {
|
||||||
|
appendStreamFile.createNewFile();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private Action timeLineAction = new AbstractAction("Timeline") {
|
private Action timeLineAction = new AbstractAction("Timeline") {
|
||||||
private static final long serialVersionUID = -6358463434933029699L;
|
private static final long serialVersionUID = -6358463434933029699L;
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
|
Loading…
Reference in a new issue