added cooja; 'The Contiki OS Java Simulator'

This commit is contained in:
fros4943 2006-08-21 12:11:16 +00:00
parent fbd527bc8f
commit e81861a0cd
148 changed files with 23162 additions and 0 deletions

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2006, 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: ClassDescription.java,v 1.1 2006/08/21 12:12:57 fros4943 Exp $
*/
package se.sics.cooja;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Annotation type to describe a class.
* Description may be shown in menues etc.
*
* @author Fredrik Osterlind
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassDescription {
String value();
}

View file

@ -0,0 +1,176 @@
/*
* Copyright (c) 2006, 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: ConnectionLogger.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
*/
package se.sics.cooja;
import java.io.File;
import java.io.FileOutputStream;
import org.apache.log4j.Logger;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.plugins.SimControl;
/**
* ConnectionLogger is a simple connection information outputter. All
* connections given via the method logConnection will be written to either
* default Log4J info stream, a log file or both.
*
* Log files have the following structure (spaces are tabs): SRC_POS [src_x]
* [src_y] [src_z] SRC_DATA [sent data bytes] DEST_POS [dest_x] [dest_y]
* [dest_z] DEST_DATA [received data bytes] [newline]
*
* @see RadioConnection
* @see RadioMedium
*
* @author Fredrik Osterlind
*/
public class ConnectionLogger {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(SimControl.class);
private static int LOG_TO_FILE = 1;
private static int LOG_TO_LOG4J = 2;
private static int LOG_TO_FILE_AND_LOG4J = 3;
private int myType;
private File myFile;
/**
* Creates a new connection logger outputting to Log4J info stream.
*/
public ConnectionLogger() {
myType = LOG_TO_LOG4J;
}
/**
* Creates a new connection logger outputting to a file.
*
* @param logFile
* Log file
*/
public ConnectionLogger(File logFile) {
myType = LOG_TO_FILE;
myFile = logFile;
if (myFile.exists())
myFile.delete();
}
/**
* Output given connection to either Log4J info stream or a file.
*
* @param conn
* Connection to output
*/
public void logConnection(RadioConnection conn) {
if (myType == LOG_TO_LOG4J || myType == LOG_TO_FILE_AND_LOG4J) {
if (conn.getDestinationPositons() != null
&& conn.getDestinationPositons().length > 0)
for (Position destPos : conn.getDestinationPositons()) {
logger.info("RADIODATA from " + conn.getSourcePosition() + " to "
+ destPos + "\tsize:" + conn.getSourceData().length);
}
else
logger.info("RADIODATA from " + conn.getSourcePosition() + " to "
+ "[NOWHERE]" + "\tsize:" + conn.getSourceData().length);
}
if (myType == LOG_TO_FILE || myType == LOG_TO_FILE_AND_LOG4J) {
try {
FileOutputStream out = new FileOutputStream(myFile, true);
if (conn.getDestinationPositons() != null
&& conn.getDestinationPositons().length > 0) {
for (int i = 0; i < conn.getDestinationPositons().length; i++) {
// Source pos
out.write("SRC_POS\t".getBytes());
Position pos = conn.getSourcePosition();
out.write(Double.toString(pos.getXCoordinate()).getBytes());
out.write("\t".getBytes());
out.write(Double.toString(pos.getYCoordinate()).getBytes());
out.write("\t".getBytes());
out.write(Double.toString(pos.getZCoordinate()).getBytes());
out.write("\t".getBytes());
// Source data
out.write("SRC_DATA\t".getBytes());
for (byte b : conn.getSourceData())
out.write(Integer.toHexString((int) b).getBytes());
out.write("\t".getBytes());
// Destination pos
out.write("DEST_POS\t".getBytes());
pos = conn.getDestinationPositons()[i];
out.write(Double.toString(pos.getXCoordinate()).getBytes());
out.write("\t".getBytes());
out.write(Double.toString(pos.getYCoordinate()).getBytes());
out.write("\t".getBytes());
out.write(Double.toString(pos.getZCoordinate()).getBytes());
out.write("\t".getBytes());
// Source data
out.write("DEST_DATA\t".getBytes());
for (byte b : conn.getDestinationData()[i])
out.write(Integer.toHexString((int) b).getBytes());
out.write("\t".getBytes());
out.write("\n".getBytes());
}
} else {
// Source pos
out.write("SRC_POS\t".getBytes());
Position pos = conn.getSourcePosition();
out.write(Double.toString(pos.getXCoordinate()).getBytes());
out.write("\t".getBytes());
out.write(Double.toString(pos.getYCoordinate()).getBytes());
out.write("\t".getBytes());
out.write(Double.toString(pos.getZCoordinate()).getBytes());
out.write("\t".getBytes());
// Source data
out.write("SRC_DATA\t".getBytes());
for (byte b : conn.getSourceData())
out.write(Integer.toHexString((int) b).getBytes());
out.write("\n".getBytes());
}
out.close();
} catch (Exception e) {
logger.fatal("Exception while logging to file: " + e);
myType = LOG_TO_LOG4J;
return;
}
}
}
}

View file

@ -0,0 +1,225 @@
/*
* Copyright (c) 2006, 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: CoreComm.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
*/
package se.sics.cooja;
import java.io.File;
import se.sics.cooja.corecomm.*;
/**
* The package corecomm's purpose is communicating with the simulation core
* using Java Native Interface (JNI). Each implementing class (named Lib[1-MAX]),
* loads a shared library which belongs to one mote type. The reason for this
* somewhat strange design is that once loaded, a native library cannot be unloaded
* in Java (yet). Therefore if we wish to load several libraries, the names and associated
* native functions must have unique names. And those names are defined via the calling class in JNI.
* For example, the native tick function in class Lib1 is named contiki_javasim_corecomm_Lib1_tick.
* When creating a new mote type, the main contiki source file is generated with function names
* compatible with the next available corecomm.
* This also implies that even if a mote type is deleted, a new one cannot be created without
* restarting the JVM and thus the entire simulation.
*
* Each implemented CoreComm class needs read access to the following core variables:
* <ul>
* <li>referenceVar
* </ul>
* and the following native functions:
* <ul>
* <li>init()
* <li>tick()
* <li>getReferenceAbsAddr()
* <li>getMemory(int start, int length)
* <li>setMemory(int start, int length, byte[] mem)
* </ul>
* @author Fredrik Osterlind
*/
public abstract class CoreComm {
/**
* Maximum supported core communicators in a simulation.
*/
private final static int MAX_LIBRARIES = 8;
// Static pointers to current libraries
private final static CoreComm[] coreComms = new CoreComm[MAX_LIBRARIES];
private final static File[] coreCommFiles = new File[MAX_LIBRARIES];
/**
* Has any library been loaded? Since libraries can't be unloaded
* the entire simulator may have to be restarted.
*
* @return True if any library has been loaded this session
*/
public static boolean hasLibraryBeenLoaded() {
for (int i=0; i < coreComms.length; i++)
if (coreComms[i] != null)
return true;
return false;
}
/**
* Has given library file already been loaded during this session?
* A loaded library can be removed, but not unloaded
* during one session. And a new library file, named
* the same as an earlier loaded and removed file,
* can't be loaded either.
*
* @param libraryFile Library file
* @return True if a library has already been loaded from the given file's filename
*/
public static boolean hasLibraryFileBeenLoaded(File libraryFile) {
for (File libFile: coreCommFiles)
if (libFile != null && libFile.getName().equals(libraryFile.getName()))
return true;
return false;
}
/**
* Get the class name of next free core communicator class.
* If null is returned, no classes are available.
*
* @return Class name
*/
public static String getAvailableClassName() {
if (coreComms[0] == null)
return "Lib1";
if (coreComms[1] == null)
return "Lib2";
if (coreComms[2] == null)
return "Lib3";
if (coreComms[3] == null)
return "Lib4";
if (coreComms[4] == null)
return "Lib5";
if (coreComms[5] == null)
return "Lib6";
if (coreComms[6] == null)
return "Lib7";
if (coreComms[7] == null)
return "Lib8";
return null;
}
/**
* Create and return an instance of the core communicator identified
* by className. This core communicator will load the native library libFile.
*
* @param className Class name of core communicator
* @param libFile Native library file
* @return Core Communicator
*/
public static CoreComm createCoreComm(String className, File libFile) {
if (className.equals("Lib1") && coreComms[0] == null) {
coreComms[0] = new Lib1(libFile);
coreCommFiles[0] = libFile;
return coreComms[0];
}
if (className.equals("Lib2") && coreComms[1] == null) {
coreComms[1] = new Lib2(libFile);
coreCommFiles[1] = libFile;
return coreComms[1];
}
if (className.equals("Lib3") && coreComms[2] == null) {
coreComms[2] = new Lib3(libFile);
coreCommFiles[2] = libFile;
return coreComms[2];
}
if (className.equals("Lib4") && coreComms[3] == null) {
coreComms[3] = new Lib4(libFile);
coreCommFiles[3] = libFile;
return coreComms[3];
}
if (className.equals("Lib5") && coreComms[4] == null) {
coreComms[4] = new Lib5(libFile);
coreCommFiles[4] = libFile;
return coreComms[4];
}
if (className.equals("Lib6") && coreComms[5] == null) {
coreComms[5] = new Lib6(libFile);
coreCommFiles[5] = libFile;
return coreComms[5];
}
if (className.equals("Lib7") && coreComms[6] == null) {
coreComms[6] = new Lib7(libFile);
coreCommFiles[6] = libFile;
return coreComms[6];
}
if (className.equals("Lib8") && coreComms[7] == null) {
coreComms[7] = new Lib8(libFile);
coreCommFiles[7] = libFile;
return coreComms[7];
}
return null;
}
/**
* Ticks a mote once. This should not be used directly,
* but instead via Mote.tick().
*/
public abstract void tick();
/**
* Initializes a mote by running a startup script in the core.
* (Should only by run once, at the same time as the library is loaded)
*/
protected abstract void init();
/**
* Returns absolute memory location of the core variable
* referenceVar. Used to get offset between relative and absolute
* memory addresses.
*
* @return Absolute memory address
*/
public abstract int getReferenceAbsAddr();
/**
* Returns a memory segment identified by start and length.
*
* @param start Start address of segment
* @param length Length of segment
* @return Memory segment
*/
public abstract byte[] getMemory(int start, int length);
/**
* Overwrites a memory segment identified by start and length.
*
* @param start Start address of segment
* @param length Length of segment
* @param mem Data to fill memory segment
*/
public abstract void setMemory(int start, int length, byte[] mem);
}

View file

@ -0,0 +1,143 @@
/*
* Copyright (c) 2006, 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: DirectoryClassLoader.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
*/
package se.sics.cooja;
import java.io.*;
import org.apache.log4j.Logger;
/**
* Loads an external file from the given directory as a Java class.
*
* @author Fredrik Osterlind
*/
public class DirectoryClassLoader extends ClassLoader {
private static Logger logger = Logger.getLogger(DirectoryClassLoader.class);
private File directory;
/**
* Creates a new class loader reading from given directory.
*
* @param directory
* Directory
*/
public DirectoryClassLoader(File directory) {
super();
this.directory = directory;
}
/**
* Creates a new class loader reading from given directory, with the given
* class loader as parent class loader.
*
* @param parent
* Parent class loader
* @param directory
* Directory
*/
public DirectoryClassLoader(ClassLoader parent, File directory) {
super(parent);
this.directory = directory;
}
public Class<?> findClass(String name) throws ClassNotFoundException {
String fullFilePath = directory.getPath() + File.separatorChar + name
+ ".class";
// Read external file
//logger.info("Directory class loader reading file: " + fullFilePath);
byte[] classData = loadClassData(fullFilePath);
if (classData == null) {
throw new ClassNotFoundException();
}
// Create class
return defineClass(name, classData, 0, classData.length);
}
private byte[] loadClassData(String name) {
// Support for fill class names in configuration file
// TODO Quick-fix (may contain bugs)
name = name.replace('.', File.separatorChar);
name = name.replace(File.separatorChar + "class", ".class");
// Open file for read access
File classFile = new File(name);
InputStream inputStream = null;
if (!classFile.exists()) {
//logger.fatal("File " + classFile + " does not exist!");
return null;
}
try {
inputStream = new FileInputStream(classFile);
if (inputStream == null) {
logger.fatal("File input stream is null!");
return null;
}
} catch (FileNotFoundException e) {
logger.fatal("Could not open file (not found?)!");
return null;
}
long fileSize = classFile.length();
if (fileSize > Integer.MAX_VALUE) {
logger.fatal("Class file is too large");
return null;
}
// Read class data
byte[] classData = new byte[(int) fileSize];
int offset = 0;
int numRead = 0;
try {
while (offset < classData.length
&& (numRead = inputStream.read(classData, offset, classData.length
- offset)) >= 0) {
offset += numRead;
}
inputStream.close();
} catch (IOException e) {
logger.fatal("Error when reading class file");
return null;
}
// Ensure all the bytes have been read in
if (offset < classData.length) {
logger.fatal("Could not read entire class file");
return null;
}
return classData;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2006, 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: IPDistributor.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
*/
package se.sics.cooja;
import java.lang.reflect.Constructor;
import java.util.Vector;
import org.apache.log4j.Logger;
/**
* A IP distributor is used for determining IP addresses of newly created motes.
*
* @author Fredrik Osterlind
*/
public abstract class IPDistributor {
private static Logger logger = Logger.getLogger(IPDistributor.class);
/**
* This method creates an instance of the given class with the given vector as
* constructor argument. Instead of calling the constructors directly this
* method may be used.
*
* @param ipDistClass Class
* @param newMotes All motes that later should be assigned IP numbers
* @return IP distributor instance
*/
public static final IPDistributor generateInterface(
Class<? extends IPDistributor> ipDistClass, Vector<Mote> newMotes) {
try {
// Generating IP distributor
Constructor constr = ipDistClass
.getConstructor(new Class[]{Vector.class});
return (IPDistributor) constr.newInstance(new Object[]{newMotes});
} catch (Exception e) {
logger.fatal("Exception when creating " + ipDistClass + ": " + e);
return null;
}
}
/**
* Returns the next mote position.
*
* @return Position
*/
public abstract String getNextIPAddress();
}

View file

@ -0,0 +1,208 @@
/*
* Copyright (c) 2006, 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: Mote.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
*/
package se.sics.cooja;
import java.util.Collection;
import java.util.Observer;
import org.jdom.Element;
/**
* This interface represents a simulated mote.
*
* A mote is always in some state, describing the status of the CPU etc.
* Motes in different states may be handled differently by the for example simulation loops and plugins.
*
* All motes must also have an interface handler, a mote type and a mote memory.
*
* @see se.sics.cooja.MoteInterfaceHandler
* @see se.sics.cooja.MoteMemory
* @see se.sics.cooja.MoteType
*
* @author Fredrik Osterlind
*/
public interface Mote {
/**
* Active state.
*/
public static int STATE_ACTIVE = 1;
/**
* Sleeping state.
*/
public static int STATE_LPM = 2;
/**
* Dead state (may be out of batteries).
*/
public static int STATE_DEAD = 3;
/**
* Tries to change state to given argument.
* A dead mote can typically not change state, while a sleeping or active mote can.
*
* @param newState New state of mote.
*/
public void setState(int newState);
/**
* @return Current mote state
*/
public int getState();
/**
* Adds new state observer.
* This observer is notified if mote changes state.
*
* @see #deleteStateObserver(Observer)
* @param newObserver New observer
*/
public void addStateObserver(Observer newObserver);
/**
* Delete existing state observer.
*
* @see #addStateObserver(Observer)
* @param newObserver Registered state observer
*/
public void deleteStateObserver(Observer newObserver);
/**
* Returns the interface handler of this mote.
*
* @see #setInterfaces(MoteInterfaceHandler)
* @return Mote interface handler
*/
public MoteInterfaceHandler getInterfaces();
/**
* Sets the interface handler of this mote.
*
* @param moteInterfaceHandler New interface handler
* @see #getInterfaces()
*/
public void setInterfaces(MoteInterfaceHandler moteInterfaceHandler);
/**
* Returns the memory of this mote.
*
* @see #setMemory(MoteMemory)
* @return Mote memory
*/
public MoteMemory getMemory();
/**
* Sets the memory of this mote.
*
* @see #getMemory()
* @param memory Mote memory
*/
public void setMemory(MoteMemory memory);
/**
* Returns mote type.
*
* @see #setType(MoteType)
* @return Mote type
*/
public MoteType getType();
/**
* Sets mote type to given argument.
*
* @see #getType()
* @param type New type
*/
public void setType(MoteType type);
/**
* Returns simulation which holds this mote.
*
* @see #setSimulation(Simulation)
* @return Simulation
*/
public Simulation getSimulation();
/**
* Sets the simulation which holds this mote.
*
* @see #getSimulation()
* @param simulation Simulation
*/
public void setSimulation(Simulation simulation);
/**
* Ticks this mote and increases any internal time to given argument.
*
* Each mote implementation may handle calls to this method differently,
* but, if existing, the simulated mote should at least handle one event.
*
* This method is responsible for updating the mote interfaces, the memory and the mote state.
*
* A call to this method typically
* polls all interfaces,
* activates the memory,
* lets the underlying mote software handle one event,
* fetches the updated memory and
* finally polls all interfaces again.
*
* @param simTime New simulation time
*/
public void tick(int simTime);
/**
* Returns XML elements representing the current config of this mote.
* This is fetched by the simulator for example when saving a simulation configuration file.
* For example a mote may return the configs of all its interfaces.
* This method should however not return state specific information such as the mote state.
* (All nodes are restarted when loading a simulation.)
*
* @see #setConfigXML(Simulation, Collection)
* @return XML elements representing the current mote config
*/
public abstract Collection<Element> getConfigXML();
/**
* Sets the current mote config depending on the given XML elements.
*
* @param simulation Simulation holding this mote
* @param configXML Config XML elements
*
* @see #getConfigXML()
*/
public abstract boolean setConfigXML(Simulation simulation, Collection<Element> configXML);
}

View file

@ -0,0 +1,158 @@
/*
* Copyright (c) 2006, 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: MoteInterface.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
*/
package se.sics.cooja;
import java.util.Collection;
import java.util.Observable;
import javax.swing.JPanel;
import org.apache.log4j.Logger;
import org.jdom.Element;
/**
* A mote interface represents a mote property.
* Often this is a simulated hardware peripheral such as a button or a led.
* This can also be a property the mote software itself is unaware of,
* for example the current position of the mote.
*
* Interfaces are the main way for the simulator to interact with a simulated mote.
*
* Interfaces are divided into active and passive interfaces, and are handled differently.
* In order to create a passive interfaces, the class should also implement the dummy Java interface PassiveMoteInterface.
* For an explanation of the differences of active and passive interfaces see class PassiveMoteInterface.
*
* @see PassiveMoteInterface
* @author Fredrik Osterlind
*/
public abstract class MoteInterface extends Observable {
private static Logger logger = Logger.getLogger(MoteInterface.class);
/**
* This method creates an instance of the given class with the given mote as constructor
* argument. Instead of calling the interface constructors directly this method may be used.
*
* @param interfaceClass Mote interface class
* @param mote Mote that will hold the interface
* @return Mote interface instance
*/
public static final MoteInterface generateInterface(Class<? extends MoteInterface> interfaceClass, Mote mote) {
try {
// Generating interface
MoteInterface instance = (MoteInterface) interfaceClass.getConstructor(
new Class[] { Mote.class }).newInstance(new Object[] { mote });
return instance;
} catch (Exception e) {
logger.fatal("Exception when creating " + interfaceClass + ": " + e);
return null;
}
}
/**
* Actions to be performed just before the holding mote is ticked
*/
public abstract void doActionsBeforeTick();
/**
* Actions to be performed just after the holding mote has been ticked
*/
public abstract void doActionsAfterTick();
/**
* Returns a panel with interesting data for this interface.
* This could for example show last messages sent/received for
* a radio interface, or logged message for a log interface.
*
* All panels returned from this method must later be released
* for memory reasons.
*
* If returned panel is null, this interface will not be visualized.
*
* @see #releaseInterfaceVisualizer(JPanel)
* @return Interface visualizer or null
*/
public abstract JPanel getInterfaceVisualizer();
/**
* This method should be called when a visualizer panel is no longer in use.
* Any resources of that panel, for example registered observers, will be released.
*
* @see #getInterfaceVisualizer()
* @param panel A interface visualizer panel fetched earlier for this mote interface.
*/
public abstract void releaseInterfaceVisualizer(JPanel panel);
/**
* Returns approximated energy consumed (mQ) during the current tick.
* If the interface is active, this information must be available after the doActionsAfterTick method.
* If the interface is passive, this information must be available after the doActionsBeforeTick method.
*
* The interface is responsible to gather information about the current internal state,
* and calculate whatever energy it needs in that state and during one tick.
*
* If the holding mote is dead, this method will not be called.
* If the holding mote is sleeping and this interface is active, this method will not be called.
*
* For example, a radio transmitter or a PIR sensor often has a much higher energy
* usage than a button sensor which virtually needs no energy at all.
* If the radio is turned off in hardware, it should return a zero energy consumption.
* If the radio is sending something which would take longer than one tick, it may either return
* the total energy used directly, or a smaller amount during several ticks.
*
* This method may typically be used by the passive interface battery, which sums up
* all energy used during one tick and decreases the battery energy left.
*
* @see se.sics.cooja.interfaces.Battery
* @return Energy consumption of this device during the current tick
*/
public abstract double energyConsumptionPerTick();
/**
* Returns XML elements representing the current config of this mote interface.
* This is fetched by the simulator for example when saving a simulation configuration file.
* For example an IP interface may return one element with the mote IP address.
* This method should however not return state specific information such as a log history.
* (All nodes are restarted when loading a simulation.)
*
* @see #setConfigXML(Collection)
* @return XML elements representing the current interface config
*/
public abstract Collection<Element> getConfigXML();
/**
* Sets the current mote interface config depending on the given XML elements.
*
* @see #getConfigXML()
* @param configXML Config XML elements
*/
public abstract void setConfigXML(Collection<Element> configXML);
}

View file

@ -0,0 +1,358 @@
/*
* Copyright (c) 2006, 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: MoteInterfaceHandler.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
*/
package se.sics.cooja;
import java.util.*;
import org.apache.log4j.Logger;
import se.sics.cooja.interfaces.*;
/**
* A mote interface handler holds all interfaces for a specific mote. Even
* though an interface handler strictly does not need any interfaces at all, a
* position interface is highly recommended. (A lot of plugins depend on a mote
* position, for example when visualizing nodes.)
*
* Interfaces are divided into active and passive interfaces. Active interfaces
* are only polled if the mote is active, while passive interfaces are polled in
* all states except dead state.
*
* Interfaces should be polled via this class when the mote is ticked.
*
* @author Fredrik Osterlind
*/
public class MoteInterfaceHandler {
private static Logger logger = Logger.getLogger(MoteInterfaceHandler.class);
private Battery myBattery;
private Beeper myBeeper;
private Button myButton;
private Clock myClock;
private IPAddress myIPAddress;
private LED myLED;
private Log myLog;
private MoteID myMoteID;
private PIR myPIR;
private Position myPosition;
private Radio myRadio;
private Vector<MoteInterface> myActiveInterfaces = new Vector<MoteInterface>();
private Vector<MoteInterface> myPassiveInterfaces = new Vector<MoteInterface>();
/**
* Creates a new empty mote interface handler.
*/
public MoteInterfaceHandler() {
}
/**
* Creates a new mote interface handler. All given interfaces are loaded.
*
* @param mote
* The mote holding this interface handler
* @param allInterfaces
* Simulation interfaces to load
*/
public MoteInterfaceHandler(Mote mote,
Vector<Class<? extends MoteInterface>> allInterfaces) {
// Load all interfaces
for (Class<? extends MoteInterface> interfaceClass : allInterfaces) {
boolean isPassive = false;
// Check if interface is active or passive
if (PassiveMoteInterface.class.isAssignableFrom(interfaceClass))
isPassive = true;
// Load interface
MoteInterface loadedInterface = MoteInterface.generateInterface(
interfaceClass, mote);
if (loadedInterface != null)
if (isPassive)
addPassiveInterface(loadedInterface);
else
addActiveInterface(loadedInterface);
else
logger.warn("Interface could not be loaded: " + interfaceClass);
}
}
/**
* Get an interface (active or passive) of the given type. Returns the first
* loaded interface found, that is either of the given class or of a subclass.
*
* For example, if the current radio interface is wanted, this method would be
* called like the following: getInterfaceOfType(Radio.class)
*
* @param interfaceType
* Type of interface to return
* @return Interface or null if no interface loaded of given type
*/
public <N extends MoteInterface> N getInterfaceOfType(Class<N> interfaceType) {
Enumeration<? extends MoteInterface> allActive = myActiveInterfaces.elements();
while (allActive.hasMoreElements()) {
N nextInterface = (N) allActive.nextElement();
if (interfaceType.isAssignableFrom(nextInterface.getClass()))
return nextInterface;
}
Enumeration<? extends MoteInterface> allPassive = myPassiveInterfaces.elements();
while (allPassive.hasMoreElements()) {
N nextInterface = (N) allPassive.nextElement();
if (interfaceType.isAssignableFrom(nextInterface.getClass()))
return nextInterface;
}
return null;
}
/**
* Returns the battery interface (if any).
*
* @return Battery interface
*/
public Battery getBattery() {
if (myBattery == null) {
myBattery = getInterfaceOfType(Battery.class);
}
return myBattery;
}
/**
* Returns the beeper interface (if any).
*
* @return Beeper interface
*/
public Beeper getBeeper() {
if (myBeeper == null) {
myBeeper = getInterfaceOfType(Beeper.class);
}
return myBeeper;
}
/**
* Returns the button interface (if any).
*
* @return Button interface
*/
public Button getButton() {
if (myButton == null) {
myButton = getInterfaceOfType(Button.class);
}
return myButton;
}
/**
* Returns the clock interface (if any).
*
* @return Clock interface
*/
public Clock getClock() {
if (myClock == null) {
myClock = getInterfaceOfType(Clock.class);
}
return myClock;
}
/**
* Returns the IP address interface (if any).
*
* @return IPAddress interface
*/
public IPAddress getIPAddress() {
if (myIPAddress == null) {
myIPAddress = getInterfaceOfType(IPAddress.class);
}
return myIPAddress;
}
/**
* Returns the LED interface (if any).
*
* @return LED interface
*/
public LED getLED() {
if (myLED == null) {
myLED = getInterfaceOfType(LED.class);
}
return myLED;
}
/**
* Returns the log interface (if any).
*
* @return Log interface
*/
public Log getLog() {
if (myLog == null) {
myLog = getInterfaceOfType(Log.class);
}
return myLog;
}
/**
* Returns the mote ID interface (if any).
*
* @return Mote ID interface
*/
public MoteID getMoteID() {
if (myMoteID == null) {
myMoteID = getInterfaceOfType(MoteID.class);
}
return myMoteID;
}
/**
* Returns the PIR interface (if any).
*
* @return PIR interface
*/
public PIR getPIR() {
if (myPIR == null) {
myPIR = getInterfaceOfType(PIR.class);
}
return myPIR;
}
/**
* Returns the position interface (if any).
*
* @return Position interface
*/
public Position getPosition() {
if (myPosition == null) {
myPosition = getInterfaceOfType(Position.class);
}
return myPosition;
}
/**
* Returns the radio interface (if any).
*
* @return Radio interface
*/
public Radio getRadio() {
if (myRadio == null) {
myRadio = getInterfaceOfType(Radio.class);
}
return myRadio;
}
/**
* Polls all active interfaces. This method should be called during a mote
* tick before the mote software is executed.
*/
public void doActiveActionsBeforeTick() {
for (int i = 0; i < myActiveInterfaces.size(); i++)
myActiveInterfaces.get(i).doActionsBeforeTick();
}
/**
* Polls all active interfaces. This method should be called during a mote
* tick after the mote software has executed.
*/
public void doActiveActionsAfterTick() {
for (int i = 0; i < myActiveInterfaces.size(); i++)
myActiveInterfaces.get(i).doActionsAfterTick();
}
/**
* Polls all passive interfaces. This method should be called during a mote
* tick before the mote software is executed.
*/
public void doPassiveActionsBeforeTick() {
for (int i = 0; i < myPassiveInterfaces.size(); i++)
myPassiveInterfaces.get(i).doActionsBeforeTick();
}
/**
* Polls all passive interfaces. This method should be called during a mote
* tick after the mote software has executed.
*/
public void doPassiveActionsAfterTick() {
for (int i = 0; i < myPassiveInterfaces.size(); i++)
myPassiveInterfaces.get(i).doActionsAfterTick();
}
/**
* Returns all passive mote interfaces.
*
* @return All passive mote interface
*/
public Vector<MoteInterface> getAllPassiveInterfaces() {
return myPassiveInterfaces;
}
/**
* Returns all active mote interfaces.
*
* @return All active mote interface
*/
public Vector<MoteInterface> getAllActiveInterfaces() {
return myActiveInterfaces;
}
/**
* Add an active interface to corresponding mote. An active interface is only
* allowed to act if the mote is in active state. However, since interfaces
* may awaken a sleeping mote up via external interrupts, most of the
* interfaces should be active.
*
* For example a button interface should be active. When the button is
* pressed, the interface will wake the mote up (simulated external
* interrupt), and then that button will be allowed to act before next tick.
*
* A passive interface is an interface which will always act if the mote is
* not dead. For example a battery should always be allowed to act since a
* mote needs energy even if it is in sleep mode.
*
* @see #addPassiveInterface(MoteInterface)
* @param newInterface
* New interface
*/
public void addActiveInterface(MoteInterface newInterface) {
myActiveInterfaces.add(newInterface);
}
/**
* Add a passive interface to corresponding mote. For explanation of passive
* vs active interfaces, see addActiveInterface(MoteInterface).
*
* @see #addActiveInterface(MoteInterface)
* @param newInterface
* New interface
*/
public void addPassiveInterface(MoteInterface newInterface) {
myPassiveInterfaces.add(newInterface);
}
}

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2006, 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: MoteMemory.java,v 1.1 2006/08/21 12:12:55 fros4943 Exp $
*/
package se.sics.cooja;
/**
* This interface represents a mote memory.
*
* Mote memory is represented by byte arrays and this
* interface provides a few of basic operations.
*
* Note that this memory internally may consist of several
* different memory sections, not covering the entire range
* between the start address and the end address of this memory.
*
* @author Fredrik Osterlind
*/
public interface MoteMemory {
/**
* Clears the entire memory.
*/
public void clearMemory();
/**
* Returns a memory segment.
*
* @param address Start address of memory segment
* @param size Size of memory segment
* @return Memory segment or null if segment not available
*/
public byte[] getMemorySegment(int address, int size);
/**
* Sets a memory segment.
*
* @param address Start address of memory segment
* @param data Data
*/
public void setMemorySegment(int address, byte[] data);
/**
* Returns the sum of all byte array sizes in this memory.
* This is not neccessarily the the same as the total memory range,
* since the entire memory range may not be handled by this memory.
*
* @return Total size
*/
public int getTotalSize();
}

View file

@ -0,0 +1,149 @@
/*
* Copyright (c) 2006, 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: MoteType.java,v 1.1 2006/08/21 12:12:57 fros4943 Exp $
*/
package se.sics.cooja;
import java.util.Collection;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jdom.Element;
/**
* Every simulated motes belongs to a mote type.
*
* The mote type defines properties common for several motes. These properties
* may differ between different implementations, but typically includes how a
* mote of that type is initialized, which hardware peripherals each mote has
* etc.
*
* A mote type may also hold the connection to an underlying simulation
* framework.
*
* @author Fredrik Osterlind
*/
public interface MoteType {
/**
* Returns the mote type description.
*
* @return Description
*/
public String getDescription();
/**
* Sets the mote type description.
*
* @param description
* New description
*/
public void setDescription(String description);
/**
* Returns the mote type identifier.
*
* @return Mote type identifier
*/
public String getIdentifier();
/**
* Sets the mote type identifier.
*
* @param identifier
* New identifier
*/
public void setIdentifier(String identifier);
/**
* Returns a panel with interesting data for this mote type.
*
* @return Mote type visualizer
*/
public JPanel getTypeVisualizer();
/**
* Returns this mote type's platform configuration.
*
* @return Platform configuration
*/
public PlatformConfig getConfig();
/**
* Generates a mote of this mote type.
*
* @param simulation
* Newly created mote's simulation
* @return New mote
*/
public Mote generateMote(Simulation simulation);
/**
* This method configures and initializes a mote type ready to be used. It is
* called from the simulator when a new mote type is created. It may simply
* confirm that all settings are valid and return true, or display a dialog
* allowing a user to manually configure the mote type.
*
* This method need normally only be run once per mote type!
*
* @param parentFrame
* Parent frame or null
* @param simulation
* Simulation holding (or that should hold) mote type
* @return True if mote type has valid settings and is ready to be used
*/
public boolean configureAndInit(JFrame parentFrame, Simulation simulation);
/**
* Returns XML elements representing the current config of this mote type.
* This is fetched by the simulator for example when saving a simulation
* configuration file. For example a Contiki base directory may be saved.
*
* @see #setConfigXML(Simulation, Collection)
* @return XML elements representing the current mote type's config
*/
public Collection<Element> getConfigXML();
/**
* Sets the current mote type config depending on the given XML elements.
* Observe that this method is responsible for restoring the configuration
* depending on the given arguments. This may include recompiling and loading
* libraries.
*
* @see #getConfigXML()
* @param simulation
* Simulation that will hold the mote type
* @param configXML
* Config XML elements
* @return True if config was set successfully, false otherwise
*/
public boolean setConfigXML(Simulation simulation,
Collection<Element> configXML);
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2006, 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: PassiveMoteInterface.java,v 1.1 2006/08/21 12:12:57 fros4943 Exp $
*/
package se.sics.cooja;
/**
* Mote interfaces are divided into active and passive interfaces.
*
* A passive mote interface is treated different than an ordinary (active)
* mote interface;
* Passive interfaces are allowed to act even when the mote is sleeping,
* while active interface only acts when the mote is in active state.
*
* A typical active interface is the radio interface, since radio
* messages only can be received when the mote is active.
*
* A typical passive interface is the battery interface, since a mote
* consumes energy even though it is sleeping.
*
* All passive interface should implement this interface.
* All interfaces not implemented this interface will be handled as active interfaces.
*
* Any energy required by this interface must be available after the
* doActionsBeforeTick method.
*
* @author Fredrik Osterlind
*/
public interface PassiveMoteInterface {
}

View file

@ -0,0 +1,359 @@
/*
* Copyright (c) 2006, 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: PlatformConfig.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
*/
package se.sics.cooja;
import java.io.*;
import java.util.*;
import org.apache.log4j.Logger;
/**
* A platform configuration may hold the configuration for one or several user
* platforms as well as a general simulator configuration.
*
* The configuration for a user platform may for example consist of which
* plugins, interfaces and processes that the specific platform supplies. Each
* user platform configuration is read from the property file cooja.config, a
* file which is required in each user platform.
*
* Values can be fetched as String, Boolean, Integer, Double or String array.
*
* Several configurations can be merged, together forming a final overall
* configuration. The order of the how configurations are merged matter - later
* values will overwrite earlier. For example merging two configurations with
* the key 'SOMEKEY' in the following order:
*
* SOMEKEY = a b c
*
* SOMEKEY = d e
*
* will result in the final value "d e".
*
* If a specific value should be extended instead of overwritten, the value must
* start with a single space-surrounded '+'. For example, merging two
* configurations with the key as above in the following order:
*
* SOMEKEY = a b c
*
* SOMEKEY = + d e
*
* will result in the final value "a b c d e".
*
* The simulator will hold a merged platform configuration, depending on which
* user platforms are used. Additionally. each mote type may also have a
* configuration of its own, that differs from the general simulator
* configuration.
*
* Often, but not necessarily, keys are named depending on which class is
* associated with the information. For example, let's say a battery interface
* wants to store its initial capacity (a double) using this approach. Data
* stored in the external configuration file can look like the following:
* se.sics.cooja.interfaces.Battery.initial_capacity 54.123321
*
* This value is then be read by: myMoteTypeConfig.getDoubleValue(Battery.class,
* "initial_capacity");
*
* @author Fredrik Osterlind
*/
public class PlatformConfig {
private static Logger logger = Logger.getLogger(PlatformConfig.class);
private Properties myConfig = new Properties();
/**
* Creates a new empty platform configuration.
*/
public PlatformConfig() {
myConfig = new Properties();
}
/**
* Loads the given property file and appends it to the current configuration.
* If a property already exists it will be overwritten, unless the new value
* begins with a '+' in which case the old value will be extended.
*
* @param propertyFile
* Property file to read
* @return True if file was read ok, false otherwise
* @throws FileNotFoundException
* If file was not found
* @throws IOException
* Stream read error
*/
public boolean appendConfig(File propertyFile) throws FileNotFoundException,
IOException {
return appendConfig(myConfig, propertyFile);
}
private static boolean appendConfig(Properties currentValues,
File propertyFile) throws FileNotFoundException, IOException {
// Open file
FileInputStream in = new FileInputStream(propertyFile);
return appendConfig(currentValues, in);
}
/**
* Reads propertues from the given stream and appends them to the current
* configuration. If a property already exists it will be overwritten, unless
* the new value begins with a '+' in which case the old value will be
* extended.
*
* @param configFileStream
* Stream to read from
* @return True if stream was read ok, false otherwise
* @throws IOException
* Stream read error
*/
public boolean appendConfig(InputStream configFileStream) throws IOException {
return appendConfig(myConfig, configFileStream);
}
private static boolean appendConfig(Properties currentValues,
InputStream configFileStream) throws IOException {
// Read from stream
Properties newProps = new Properties();
newProps.load(configFileStream);
configFileStream.close();
// Read new properties
Enumeration en = newProps.keys();
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
String property = newProps.getProperty(key);
if (property.startsWith("+ ")) {
if (currentValues.getProperty(key) != null)
currentValues.setProperty(key, currentValues.getProperty(key) + " " + property.substring(1).trim());
else
currentValues.setProperty(key, property.substring(1).trim());
} else
currentValues.setProperty(key, property);
}
return true;
}
/**
* @return All property names in configuration
*/
public Enumeration<String> getPropertyNames() {
return (Enumeration<String>) myConfig.propertyNames();
}
/**
* Get string value with given id.
*
* @param callingClass
* Class which value belongs to
* @param id
* Id of value to return
* @param defaultValue
* Default value to return if id is not found
* @return Value or defaultValue if id wasn't found
*/
public String getStringValue(Class callingClass, String id,
String defaultValue) {
return getStringValue(myConfig, callingClass, id, defaultValue);
}
private static String getStringValue(Properties currentValues,
Class callingClass, String id, String defaultValue) {
String val = currentValues.getProperty(callingClass.getName() + "." + id);
if (val == null) {
logger.warn("Could not find key named '" + callingClass.getName() + "." + id + "'");
return defaultValue;
}
return val;
}
/**
* Returns value of given name.
*
* @param name
* Name
* @return Value as string
*/
public String getStringValue(String name) {
if (!myConfig.containsKey(name))
logger.debug("Could not find key named '" + name + "'");
return myConfig.getProperty(name);
}
/**
* Get string value with given id.
*
* @param callingClass
* Class which value belongs to
* @param id
* Id of value to return
* @return Value or null if id wasn't found
*/
public String getStringValue(Class callingClass, String id) {
return getStringValue(callingClass, id, null);
}
/**
* Get string array value with given id.
*
* @param callingClass
* Class which value belongs to
* @param id
* Id of value to return
* @return Value or null if id wasn't found
*/
public String[] getStringArrayValue(Class callingClass, String id) {
String stringVal = getStringValue(callingClass, id, null);
if (stringVal == null)
return new String[0];
return getStringValue(callingClass, id, "").split(" ");
}
/**
* Get string value with given id.
*
* @param callingClass
* Class which value belongs to
* @param id
* Id of value to return
* @return Value or null if id wasn't found
*/
public String getValue(Class callingClass, String id) {
return getStringValue(callingClass, id);
}
/**
* Get integer value with given id.
*
* @param callingClass
* Class which value belongs to
* @param id
* Id of value to return
* @param defaultValue
* Default value to return if id is not found
* @return Value or defaultValue if id wasn't found
*/
public int getIntegerValue(Class callingClass, String id, int defaultValue) {
String str = getStringValue(callingClass, id);
if (str == null)
return defaultValue;
return Integer.parseInt(str);
}
/**
* Get integer value with given id.
*
* @param callingClass
* Class which value belongs to
* @param id
* Id of value to return
* @return Value or 0 if id wasn't found
*/
public int getIntegerValue(Class callingClass, String id) {
return getIntegerValue(callingClass, id, 0);
}
/**
* Get double value with given id.
*
* @param callingClass
* Class which value belongs to
* @param id
* Id of value to return
* @param defaultValue
* Default value to return if id is not found
* @return Value or defaultValue if id wasn't found
*/
public double getDoubleValue(Class callingClass, String id,
double defaultValue) {
String str = getStringValue(callingClass, id);
if (str == null)
return defaultValue;
return Double.parseDouble(str);
}
/**
* Get double value with given id.
*
* @param callingClass
* Class which value belongs to
* @param id
* Id of value to return
* @return Value or 0.0 if id wasn't found
*/
public double getDoubleValue(Class callingClass, String id) {
return getDoubleValue(callingClass, id, 0.0);
}
/**
* Get boolean value with given id.
*
* @param callingClass
* Class which value belongs to
* @param id
* Id of value to return
* @param defaultValue
* Default value to return if id is not found
* @return Value or defaultValue if id wasn't found
*/
public boolean getBooleanValue(Class callingClass, String id,
boolean defaultValue) {
String str = getStringValue(callingClass, id);
if (str == null)
return defaultValue;
return Boolean.parseBoolean(str);
}
/**
* Get boolean value with given id.
*
* @param callingClass
* Class which value belongs to
* @param id
* Id of value to return
* @return Value or false if id wasn't found
*/
public boolean getBooleanValue(Class callingClass, String id) {
return getBooleanValue(callingClass, id, false);
}
public PlatformConfig clone() {
PlatformConfig clone = new PlatformConfig();
clone.myConfig = (Properties) this.myConfig.clone();
return clone;
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2006, 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: Positioner.java,v 1.1 2006/08/21 12:12:51 fros4943 Exp $
*/
package se.sics.cooja;
import java.lang.reflect.Constructor;
import org.apache.log4j.Logger;
/**
* A positioner is used for determining positions of newly created motes.
*
* @author Fredrik Osterlind
*/
public abstract class Positioner {
private static Logger logger = Logger.getLogger(Positioner.class);
/**
* This method creates an instance of the given class with the given interval
* information as constructor arguments. Instead of calling the constructors
* directly this method may be used.
*
* @param positionerClass
* Positioner class
* @param totalNumberOfMotes
* Total number of motes that should be generated using this
* positioner
* @param startX
* Lowest X value of positions generated using returned positioner
* @param endX
* Highest X value of positions generated using returned positioner
* @param startY
* Lowest Y value of positions generated using returned positioner
* @param endY
* Highest Y value of positions generated using returned positioner
* @param startZ
* Lowest Z value of positions generated using returned positioner
* @param endZ
* Highest Z value of positions generated using returned positioner
* @return Postioner instance
*/
public static final Positioner generateInterface(
Class<? extends Positioner> positionerClass, int totalNumberOfMotes,
double startX, double endX, double startY, double endY, double startZ,
double endZ) {
try {
// Generating positioner
Constructor constr = positionerClass.getConstructor(new Class[]{
int.class, double.class, double.class, double.class, double.class,
double.class, double.class});
return (Positioner) constr.newInstance(new Object[]{totalNumberOfMotes,
startX, endX, startY, endY, startZ, endZ});
} catch (Exception e) {
logger.fatal("Exception when creating " + positionerClass + ": " + e);
return null;
}
}
/**
* Returns the next mote position.
*
* @return Position
*/
public abstract double[] getNextPosition();
}

View file

@ -0,0 +1,150 @@
/*
* Copyright (c) 2006, 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: RadioConnection.java,v 1.1 2006/08/21 12:12:55 fros4943 Exp $
*/
package se.sics.cooja;
import java.util.Vector;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio;
/**
* RadioConnection represents a radio connection between a sending radio
* and zero or more receiving radios.
* By registering as an observer to the current radio medium, all
* radio connections and data sent in that medium can be accessed.
*
* Each radio is associated with a position and some radio data.
* Often the destinations' and source's data will refer to the same object,
* but some radio mediums may want to distort the transferred data, hence
* resulting in different data sent and received.
*
* @see RadioMedium
* @author Fredrik Osterlind
*/
public class RadioConnection {
private Radio sourceRadio;
private Position sourcePosition;
private byte[] sourceData;
private Vector<Radio> destinationRadios = new Vector<Radio>();
private Vector<Position> destinationPositions = new Vector<Position>();
private Vector<byte[]> destinationData = new Vector<byte[]>();
/**
* Set source of this connection.
*
* @param radio Source radio
* @param position Source position
* @param data Source data
*/
public void setSource(Radio radio, Position position, byte[] data) {
sourceRadio = radio;
sourcePosition = position;
sourceData = data;
}
/**
* Add a connection destination.
*
* @param radio Source radio
* @param position Source position
* @param data Source data
*/
public void addDestination(Radio radio, Position position, byte[] data) {
destinationRadios.add(radio);
destinationPositions.add(position);
destinationData.add(data);
}
/**
* @return Source radio
*/
public Radio getSourceRadio() {
return sourceRadio;
}
/**
* @return Source position
*/
public Position getSourcePosition() {
return sourcePosition;
}
/**
* Returns the data actually sent by source radio.
* @return Source data
*/
public byte[] getSourceData() {
return sourceData;
}
/**
* @return Array of destination radios
*/
public Radio[] getDestinationRadios() {
Radio[] radioArrayType;
Radio[] radioArray;
radioArrayType = new Radio[destinationRadios.size()];
radioArray = (Radio[]) destinationRadios.toArray(radioArrayType);
return radioArray;
}
/**
* @return Array of destination positions
*/
public Position[] getDestinationPositons() {
Position[] positionArrayType;
Position[] positionArray;
positionArrayType = new Position[destinationPositions.size()];
positionArray = (Position[]) destinationPositions.toArray(positionArrayType);
return positionArray;
}
/**
* Returns an array of data actually received by each radio.
* @return Array of destination data
*/
public byte[][] getDestinationData() {
byte[][] dataArrayType;
byte[][] dataArray;
dataArrayType = new byte[destinationData.size()][];
dataArray = (byte[][]) destinationData.toArray(dataArrayType);
return dataArray;
}
}

View file

@ -0,0 +1,176 @@
/*
* Copyright (c) 2006, 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: RadioMedium.java,v 1.1 2006/08/21 12:12:55 fros4943 Exp $
*/
package se.sics.cooja;
import java.util.Collection;
import java.util.Observer;
import org.jdom.Element;
import se.sics.cooja.interfaces.Position;
import se.sics.cooja.interfaces.Radio;
/**
* This interface represents a radio medium. Radios registered to this medium
* can both send and receive radio data. Depending on the implementation of this
* interface, more or less accurate radio behaviour imitation is aquired.
*
* Often a radio medium, at initialization, registers one or several dynamic
* plugins. These plugins shows the user some radio medium specific details,
* such as radio transmission radius etc.
*
* @author Fredrik Osterlind
*/
public abstract class RadioMedium {
/**
* Registers a mote to this medium.
*
* How radio data will be received from and sent to this mote depends on the
* medium implementation. Common factors may be random, distance from sending
* to receiving mote and interference with other radio transmitters in some
* range.
*
* @param mote
* Mote to register
* @param sim
* Simulation holding mote
*/
public abstract void registerMote(Mote mote, Simulation sim);
/**
* Unregisters a mote from this medium.
*
* @param mote
* Mote to unregister
* @param sim
* Simulation holding mote
*/
public abstract void unregisterMote(Mote mote, Simulation sim);
/**
* Register a radio to this medium at a given position.
*
* Concerning radio data, this radio will be treated the same way as a mote's
* radio. This method can be used to add non-mote radio devices, such as a
* packet generator or a sniffer.
*
* @param radio
* Radio
* @param position
* Position
* @param sim
* Simulation holding radio
*/
public abstract void registerRadioInterface(Radio radio, Position position,
Simulation sim);
/**
* Unregisters a radio interface from this medium.
*
* @param radio
* Radio interface to unregister
* @param sim
* Simulation holding radio
*/
public abstract void unregisterRadioInterface(Radio radio, Simulation sim);
/**
* Adds an observer which is notified after the radio connections has been
* calculated. Often a radio medium is a tick observer and makes these
* calculations after each tick loop. A radio medium observer may then gather
* network data by being notified every time the radio medium has delivered
* data. The radio medium observable MUST notify observers every time the
* getLastTickConnections returns a new value, even if the new value is null.
*
* @see #getLastTickConnections()
* @see #deleteRadioMediumObserver(Observer)
* @param observer
* New observer
*/
public abstract void addRadioMediumObserver(Observer observer);
/**
* Deletes an radio medium observer.
*
* @see #addRadioMediumObserver(Observer)
* @param observer
* Observer to delete
*/
public abstract void deleteRadioMediumObserver(Observer observer);
/**
* Returns all connections made during last tick loop.
*
* Typically a radio medium is a tick observer and transfers data between
* radios after each tick loop. When these calculations are finished, it will
* in turn notify all radio medium observers. A radio medium observer may get
* information about which connections were made by using this method. Observe
* that this method may return null of no connections were made.
*
* @see RadioConnection
* @return All connections made during last tick loop or null if none
*/
public abstract RadioConnection[] getLastTickConnections();
/**
* Set an overall connection logger. This logger will see all connections in
* the radio medium.
*
* @param logger
* New overall connection logger.
*/
public abstract void setConnectionLogger(ConnectionLogger logger);
/**
* Returns XML elements representing the current config of this radio medium.
* This is fetched by the simulator for example when saving a simulation
* configuration file. For example a radio medium may return user altered
* range parameters. This method should however not return state specific
* information such as a current radio status. (All nodes are restarted when
* loading a simulation.)
*
* @see #setConfigXML(Collection)
* @return XML elements representing the current radio medium config
*/
public abstract Collection<Element> getConfigXML();
/**
* Sets the current radio medium config depending on the given XML elements.
*
* @see #getConfigXML()
* @param configXML
* Config XML elements
* @return True if config was set successfully, false otherwise
*/
public abstract boolean setConfigXML(Collection<Element> configXML);
}

View file

@ -0,0 +1,512 @@
/*
* Copyright (c) 2006, 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: SectionMoteMemory.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
*/
package se.sics.cooja;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import org.apache.log4j.Logger;
import se.sics.cooja.MoteMemory;
/**
* Represents a mote memory consisting of non-overlapping
* memory sections. This memory also contains information
* about variable starts addresses.
* <p>
* When an unhandled memory segment is set a new section is
* automatically created for this segment.
* <p>
* @author Fredrik Osterlind
*/
public class SectionMoteMemory implements MoteMemory {
private static Logger logger = Logger.getLogger(SectionMoteMemory.class);
private Vector<MoteMemorySection> sections = new Vector<MoteMemorySection>();
private final Properties variableAddresses;
/**
* Create a new mote memory with information about which
* variables exist and their relative memory addresses.
*
* @param variableAddresses Variable addresses
*/
public SectionMoteMemory(Properties variableAddresses) {
this.variableAddresses = variableAddresses;
}
/**
* @return All variable names known and residing in this memory
*/
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 void clearMemory() {
sections.clear();
}
public byte[] getMemorySegment(int address, int size) {
for (int i=0; i < sections.size(); i++) {
if (sections.elementAt(i).includesAddr(address) && sections.elementAt(i).includesAddr(address + size - 1)) {
return sections.elementAt(i).getMemorySegment(address, size);
}
}
return null;
}
public void setMemorySegment(int address, byte[] data) {
// TODO Creating overlapping memory sections possible
for (int i=0; i < sections.size(); i++) {
if (sections.elementAt(i).includesAddr(address) && sections.elementAt(i).includesAddr(address + data.length - 1)) {
sections.elementAt(i).setMemorySegment(address, data);
return;
}
}
sections.add(new MoteMemorySection(address, data));
}
public int getTotalSize() {
int totalSize = 0;
for (MoteMemorySection section: sections)
totalSize += section.getSize();
return totalSize;
}
/**
* Returns the total number of sections in this memory.
*
* @return Number of sections
*/
public int getNumberOfSections() {
return sections.size();
}
/**
* Removes a memory segment from this memory.
* The section containing the segment may be split into two sections.
*
* @param startAddr Start address
* @param size Length
*/
public void removeSegmentFromMemory(int startAddr, int size) {
for (MoteMemorySection section: sections)
// Find section containing segment to remove
if (section.includesAddr(startAddr) &&
section.includesAddr(startAddr + size - 1)) {
MoteMemorySection oldSection = section;
byte[] dataFirstPart = oldSection.getMemorySegment(
oldSection.startAddr,
(int) (startAddr - oldSection.startAddr)
);
byte[] dataSecondPart = oldSection.getMemorySegment(
startAddr + size,
(int) (oldSection.startAddr + oldSection.getSize() - (startAddr + size)));
MoteMemorySection newSectionFirstPart = new MoteMemorySection(oldSection.startAddr, dataFirstPart);
MoteMemorySection newSectionSecondPart = new MoteMemorySection(startAddr + size, dataSecondPart);
// Remove old section, add new sections
sections.remove(oldSection);
if (newSectionFirstPart.getSize() > 0)
sections.add(newSectionFirstPart);
if (newSectionSecondPart.getSize() > 0)
sections.add(newSectionSecondPart);
}
}
/**
* Get start address of section at given position.
*
* @param sectionNr Section position
* @return Start address of section
*/
public int getStartAddrOfSection(int sectionNr) {
if (sectionNr >= sections.size())
return 0;
return sections.elementAt(sectionNr).getStartAddr();
}
/**
* Get size of section at given position.
*
* @param sectionNr Section position
* @return Size of section
*/
public int getSizeOfSection(int sectionNr) {
if (sectionNr >= sections.size())
return 0;
return sections.elementAt(sectionNr).getSize();
}
/**
* Get data of section at given position.
*
* @param sectionNr Section position
* @return Data at section
*/
public byte[] getDataOfSection(int sectionNr) {
if (sectionNr >= sections.size())
return null;
return sections.elementAt(sectionNr).getData();
}
/**
* Returns a value of the integer variable with the given name.
*
* @param varName Name of integer variable
* @return Value of integer variable
*/
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, 4);
int retVal = 0;
int pos = 0;
retVal += ((int) (varData[pos++] & 0xFF)) << 24;
retVal += ((int) (varData[pos++] & 0xFF)) << 16;
retVal += ((int) (varData[pos++] & 0xFF)) << 8;
retVal += ((int) (varData[pos++] & 0xFF)) << 0;
// TODO Check if small/big-endian when coming from JNI?
retVal = Integer.reverseBytes(retVal);
return retVal;
}
/**
* Set integer value of variable with given name.
*
* @param varName Name of integer variable
* @param newVal New value to set
*/
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);
}
/**
* Returns a value of the byte variable with the given name.
*
* @param varName Name of byte variable
* @return Value of byte variable
*/
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];
}
/**
* Set byte value of variable with given name.
*
* @param varName Name of byte variable
* @param newVal New value to set
*/
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);
}
/**
* Returns byte array of given length and with the given name.
*
* @param varName Name of array
* @param length Length of array
* @return Data of array
*/
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);
}
/**
* Set byte array of the variable with the given name.
*
* @param varName Name of array
* @param data New data of array
*/
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);
}
/**
* A memory section represented of a byte array and a start address.
*
* @author Fredrik Osterlind
*/
private class MoteMemorySection {
private byte[] data = null;
private int startAddr;
/**
* Create a new memory section.
*
* @param startAddr Start address of section
* @param data Data of section
*/
public MoteMemorySection(int startAddr, byte[] data) {
this.startAddr = startAddr;
this.data = data;
}
/**
* Returns start address of this memory section.
*
* @return Start address
*/
public int getStartAddr() {
return startAddr;
}
/**
* Returns size of this memory section.
*
* @return Size
*/
public int getSize() {
return data.length;
}
/**
* Returns the entire byte array which defines this section.
*
* @return Byte array
*/
public byte[] getData() {
return data;
}
/**
* True if given address is part of this memory section.
*
* @param addr Address
* @return True if given address is part of this memory section, false otherwise
*/
public boolean includesAddr(int addr) {
if (data == null)
return false;
return (addr >= startAddr && addr < (startAddr + data.length));
}
/**
* Returns memory segment.
*
* @param addr Start address of memory segment
* @param size Size of memory segment
* @return Memory segment
*/
public byte[] getMemorySegment(int addr, int size) {
byte[] ret = new byte[size];
for (int i = 0; i < size; i++)
ret[i] = data[(int) (addr - startAddr + i)];
return ret;
}
/**
* Sets a memory segment.
* @param addr Start of memory segment
* @param data Data of memory segment
*/
public void setMemorySegment(int addr, byte[] data) {
int nonnull=0;
for (int i = 0; i < data.length; i++) {
if (data[i] != 0) nonnull++;
this.data[(int) (addr - startAddr + i)] = data[i];
}
}
public MoteMemorySection clone() {
byte[] dataClone = new byte[data.length];
for (int i=0; i < data.length; i++)
dataClone[i] = data[i];
MoteMemorySection clone = new MoteMemorySection(startAddr, dataClone);
return clone;
}
}
// EXPERIMENTAL AND DEBUG METHODS
public SectionMoteMemory clone() {
Vector<MoteMemorySection> clonedSections = new Vector<MoteMemorySection>();
for (int i=0; i < sections.size(); i++) {
clonedSections.add((MoteMemorySection) sections.elementAt(i).clone());
}
SectionMoteMemory clone = new SectionMoteMemory(variableAddresses);
clone.sections = clonedSections;
return clone;
}
protected byte[] getChecksum() {
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance("MD5");
for (int i=0; i < sections.size(); i++) {
messageDigest.update(sections.get(i).data, 0, sections.get(i).getSize());
}
} catch (NoSuchAlgorithmException e) {
return null;
}
return messageDigest.digest();
}
protected Vector<Integer> getDifferenceAddressesOf(SectionMoteMemory anotherMem) {
Vector<Integer> differences = new Vector<Integer>();
if (this.getNumberOfSections() != anotherMem.getNumberOfSections()) {
logger.fatal("Number of section do not match!");
return null;
}
for (int i=0; i < sections.size(); i++) {
if (this.getSizeOfSection(i) != anotherMem.getSizeOfSection(i)) {
logger.fatal("Section " + i + " sizes do not match!");
return null;
}
if (this.getStartAddrOfSection(i) != anotherMem.getStartAddrOfSection(i)) {
logger.fatal("Section " + i + " start addresses do not match!");
return null;
}
for (int j=0; j < sections.get(i).getSize(); j++)
if (this.sections.get(i).data[j] != anotherMem.getDataOfSection(i)[j])
differences.add(new Integer(sections.get(i).startAddr + j));
System.err.println();
}
return differences;
}
protected void printMemory() {
for (int i=0; i < sections.size(); i++) {
System.err.print("Section[" + i + "]: ");
for (int j=0; j < sections.get(i).getSize(); j++)
System.err.print(sections.get(i).getData()[j] + ",");
System.err.println();
}
}
protected void printDifferences(SectionMoteMemory anotherMem) {
if (this.getNumberOfSections() != anotherMem.getNumberOfSections()) {
logger.fatal("Number of section do not match!");
return;
}
for (int i=0; i < sections.size(); i++) {
if (this.getSizeOfSection(i) != anotherMem.getSizeOfSection(i)) {
logger.fatal("Section " + i + " sizes do not match!");
return;
}
if (this.getStartAddrOfSection(i) != anotherMem.getStartAddrOfSection(i)) {
logger.fatal("Section " + i + " start addresses do not match!");
return;
}
System.err.print("Section[" + i + "]: ");
for (int j=0; j < sections.get(i).getSize(); j++)
if (this.sections.get(i).data[j] != anotherMem.getDataOfSection(i)[j])
System.err.print(j + ",");
System.err.println();
}
}
protected void printChecksum() {
byte[] checksum = this.getChecksum();
System.err.print("Checksum: ");
for (int i=0; i < checksum.length; i++) {
System.err.print(checksum[i] + ",");
}
System.err.println();
}
}

View file

@ -0,0 +1,735 @@
/*
* Copyright (c) 2006, 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: Simulation.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
*/
package se.sics.cooja;
import java.io.*;
import java.util.*;
import org.apache.log4j.Logger;
import org.jdom.*;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import se.sics.cooja.dialogs.*;
/**
* A simulation contains motes and ticks them one by one. When all motes has
* been ticked once, the simulation sleeps for some specified time, and the
* current simulation time is updated. Some observers (tick observers) are also
* notified.
*
* When observing the simulation itself, the simulation state, added or deleted
* motes etc are observed, as opposed to individual mote changes. Changes of
* individual motes should instead be observed via corresponding mote
* interfaces.
*
* @author Fredrik Osterlind
*/
public class Simulation extends Observable implements Runnable {
private Vector<Mote> motes = new Vector<Mote>();
private Vector<MoteType> moteTypes = new Vector<MoteType>();
private int delayTime = 100;
private int currentSimulationTime = 0;
private int tickTime = 1;
private String title = null;
// Radio Medium
private RadioMedium currentRadioMedium = null;
private static Logger logger = Logger.getLogger(Simulation.class);
private boolean isRunning = false;
private boolean stopSimulation = false;
private Thread thread = null;
// Tick observable
private class TickObservable extends Observable {
private void allTicksPerformed() {
setChanged();
notifyObservers();
}
}
private TickObservable tickObservable = new TickObservable();
/**
* Add tick observer. This observer is notified once every tick loop, that is,
* when all motes have been ticked.
*
* @see #deleteTickObserver(Observer)
* @param newObserver
* New observer
*/
public void addTickObserver(Observer newObserver) {
tickObservable.addObserver(newObserver);
}
/**
* Delete an existing tick observer.
*
* @see #addTickObserver(Observer)
* @param observer
* Observer to delete
*/
public void deleteTickObserver(Observer observer) {
tickObservable.deleteObserver(observer);
}
public void run() {
long lastStartTime = System.currentTimeMillis();
logger.info("Simulation main loop started, system time: " + lastStartTime);
isRunning = true;
// Notify observers simulation is starting
this.setChanged();
this.notifyObservers(this);
while (isRunning) {
try {
// Tick all motes
for (Mote moteToTick : motes) {
moteToTick.tick(currentSimulationTime);
}
// Increase simulation time
currentSimulationTime += tickTime;
// Notify tick observers
tickObservable.allTicksPerformed();
// Sleep
if (delayTime > 0)
Thread.sleep(delayTime);
if (stopSimulation) {
// We should only tick once (and we just did), so abort now
stopSimulation = false;
isRunning = false;
thread = null;
}
} catch (InterruptedException e) {
isRunning = false;
thread = null;
break;
} catch (IllegalArgumentException e) {
logger.warn("llegalArgumentException:" + e);
isRunning = false;
thread = null;
break;
} catch (IllegalMonitorStateException e) {
logger.warn("IllegalMonitorStateException:" + e);
isRunning = false;
thread = null;
break;
}
}
isRunning = false;
thread = null;
stopSimulation = false;
// Notify observers simulation has stopped
this.setChanged();
this.notifyObservers(this);
logger.info("Simulation main loop stopped, system time: "
+ System.currentTimeMillis() + "\tDuration: "
+ (System.currentTimeMillis() - lastStartTime) + " ms");
}
/**
* Creates a new simulation with a delay time of 1 second.
*/
public Simulation() {
// New simulation instance
// logger.fatal("WARNING ADDING 10000 BLINKER NODES NOW!!!");
// for (int i=0; i < 10000; i++)
// addMote(new BlinkerNode());
}
/**
* Starts this simulation (notifies observers).
*/
public void startSimulation() {
if (!isRunning()) {
thread = new Thread(this);
thread.start();
}
}
/**
* Stops this simulation (notifies observers).
*/
public void stopSimulation() {
if (isRunning()) {
stopSimulation = true;
thread.interrupt();
// Wait until simulation stops
if (Thread.currentThread() != thread)
while (thread != null && thread.isAlive()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
} // else logger.fatal("Could not stop simulation: isRunning=" + isRunning +
// ", thread=" + thread);
}
/**
* Starts simulation if stopped, ticks all motes once, and finally stop
* simulation again.
*/
public void tickSimulation() {
stopSimulation = true;
if (!isRunning()) {
thread = new Thread(this);
thread.start();
}
// Wait until simulation stops
while (thread != null && thread.isAlive()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}
/**
* Loads a simulation configuration from given file.
*
* When loading mote types, user must recompile the actual library of each
* type. User may also change mote type settings at this point.
*
* @see #saveSimulationConfig(File)
* @param file
* File to read
* @return New simulation or null if recompiling failed or aborted
* @throws UnsatisfiedLinkError
* If associated libraries could not be loaded
*/
public static Simulation loadSimulationConfig(File file)
throws UnsatisfiedLinkError {
Simulation newSim = null;
try {
// Open config file
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(file);
Element root = doc.getRootElement();
// Check that config file version is correct
if (!root.getName().equals("simulation")) {
logger.fatal("Not a COOJA simulation config xml file!");
return null;
}
// Build new simulation
Collection<Element> config = root.getChildren();
newSim = new Simulation();
boolean createdOK = newSim.setConfigXML(config);
if (!createdOK) {
logger.info("Simulation not loaded");
return null;
}
} catch (JDOMException e) {
logger.fatal("File not wellformed: " + e.getMessage());
return null;
} catch (IOException e) {
logger.fatal("No access to file: " + e.getMessage());
return null;
} catch (Exception e) {
logger.fatal("Exception when loading file: " + e);
e.printStackTrace();
return null;
}
return newSim;
}
/**
* Saves current simulation configuration to given file and notifies
* observers.
*
* @see #loadSimulationConfig(File file)
* @see #getConfigXML()
* @param file
* File to write
*/
public void saveSimulationConfig(File file) {
try {
// Create simulation XML
Element root = new Element("simulation");
root.addContent(getConfigXML());
// Create config
Document doc = new Document(root);
// Write to file
FileOutputStream out = new FileOutputStream(file);
XMLOutputter outputter = new XMLOutputter();
outputter.setFormat(Format.getPrettyFormat());
outputter.output(doc, out);
out.close();
logger.info("Saved to file: " + file.getAbsolutePath());
} catch (Exception e) {
logger.warn("Exception while saving simulation config: " + e);
}
this.setChanged();
this.notifyObservers(this);
}
/**
* Returns the current simulation config represented by XML elements. This
* config also includes the current radio medium, all mote types and motes.
*
* @see #saveSimulationConfig(File file)
* @return Current simulation config
*/
public Collection<Element> getConfigXML() {
Vector<Element> config = new Vector<Element>();
Element element;
// Title
element = new Element("title");
element.setText(title);
config.add(element);
// Delay time
element = new Element("delaytime");
element.setText(Integer.toString(delayTime));
config.add(element);
// Simulation time
element = new Element("simtime");
element.setText(Integer.toString(currentSimulationTime));
config.add(element);
// Tick time
element = new Element("ticktime");
element.setText(Integer.toString(tickTime));
config.add(element);
// Radio Medium
element = new Element("radiomedium");
element.setText(currentRadioMedium.getClass().getName());
Collection radioMediumXML = currentRadioMedium.getConfigXML();
if (radioMediumXML != null)
element.addContent(radioMediumXML);
config.add(element);
// Mote types
for (MoteType moteType : getMoteTypes()) {
element = new Element("motetype");
element.setText(moteType.getClass().getName());
Collection moteTypeXML = moteType.getConfigXML();
if (moteTypeXML != null)
element.addContent(moteTypeXML);
config.add(element);
}
// Motes
for (Mote mote : motes) {
element = new Element("mote");
element.setText(mote.getClass().getName());
Collection moteXML = mote.getConfigXML();
if (moteXML != null)
element.addContent(moteXML);
config.add(element);
}
return config;
}
/**
* Sets the current simulation config depending on the given XML elements.
*
* @see #getConfigXML()
* @param configXML
* Config XML elements
*/
public boolean setConfigXML(Collection<Element> configXML) throws Exception {
// Parse elements
for (Element element : configXML) {
// Title
if (element.getName().equals("title")) {
title = element.getText();
}
// Delay time
if (element.getName().equals("delaytime")) {
delayTime = Integer.parseInt(element.getText());
}
// Simulation time
if (element.getName().equals("simtime")) {
currentSimulationTime = Integer.parseInt(element.getText());
}
// Tick time
if (element.getName().equals("ticktime")) {
tickTime = Integer.parseInt(element.getText());
}
// Radio medium
if (element.getName().equals("radiomedium")) {
String radioMediumClassName = element.getText().trim();
Class<? extends RadioMedium> radioMediumClass = GUI.currentGUI
.tryLoadClass(this, RadioMedium.class, radioMediumClassName);
if (radioMediumClass != null)
// Create radio medium specified in config
currentRadioMedium = radioMediumClass.newInstance();
else
logger.warn("Could not find radio medium class: "
+ radioMediumClassName);
// Show configure simulation dialog
boolean createdOK = CreateSimDialog.showDialog(GUI.frame, this);
if (!createdOK) {
logger.debug("Simulation not created, aborting");
throw new Exception("Load aborted by user");
}
// Check if radio medium specific config should be applied
if (radioMediumClassName
.equals(currentRadioMedium.getClass().getName())) {
currentRadioMedium.setConfigXML(element.getChildren());
} else {
logger
.info("Radio Medium changed - ignoring radio medium specific config");
}
}
// Mote type
if (element.getName().equals("motetype")) {
String moteTypeClassName = element.getText().trim();
Class<? extends MoteType> moteTypeClass = GUI.currentGUI.tryLoadClass(
this, MoteType.class, moteTypeClassName);
if (moteTypeClass == null) {
logger.fatal("Could not load mote type class: " + moteTypeClassName);
return false;
}
MoteType moteType = moteTypeClass.getConstructor((Class[]) null)
.newInstance();
boolean createdOK = moteType.setConfigXML(this, element.getChildren());
if (createdOK) {
addMoteType(moteType);
} else {
logger
.fatal("Mote type was not created: " + element.getText().trim());
throw new Exception("All mote types were not recreated");
}
}
// Mote
if (element.getName().equals("mote")) {
Class<? extends Mote> moteClass = GUI.currentGUI.tryLoadClass(this,
Mote.class, element.getText().trim());
Mote mote = moteClass.getConstructor((Class[]) null).newInstance();
if (mote.setConfigXML(this, element.getChildren())) {
addMote(mote);
} else {
logger.fatal("Mote was not created: " + element.getText().trim());
throw new Exception("All motes were not recreated");
}
}
}
return true;
}
/**
* Removes a mote from this simulation
*
* @param mote
* Mote to remove
*/
public void removeMote(Mote mote) {
if (isRunning()) {
stopSimulation();
motes.remove(mote);
startSimulation();
} else
motes.remove(mote);
currentRadioMedium.unregisterMote(mote, this);
this.setChanged();
this.notifyObservers(this);
}
/**
* Adds a mote to this simulation
*
* @param mote
* Mote to add
*/
public void addMote(Mote mote) {
if (isRunning()) {
stopSimulation();
motes.add(mote);
startSimulation();
} else
motes.add(mote);
currentRadioMedium.registerMote(mote, this);
this.setChanged();
this.notifyObservers(this);
}
/**
* Get a mote from this simulation.
*
* @param pos
* Position of mote
* @return Mote
*/
public Mote getMote(int pos) {
return motes.get(pos);
}
/**
* Returns number of motes in this simulation.
*
* @return Number of motes
*/
public int getMotesCount() {
return motes.size();
}
/**
* Returns all mote types in simulation.
*
* @return All mote types
*/
public Vector<MoteType> getMoteTypes() {
return moteTypes;
}
/**
* Returns mote type with given identifier.
*
* @param identifier
* Mote type identifier
* @return Mote type or null if not found
*/
public MoteType getMoteType(String identifier) {
for (MoteType moteType : getMoteTypes()) {
if (moteType.getIdentifier().equals(identifier))
return moteType;
}
return null;
}
/**
* Adds given mote type to simulation.
*
* @param newMoteType
*/
public void addMoteType(MoteType newMoteType) {
moteTypes.add(newMoteType);
this.setChanged();
this.notifyObservers(this);
}
/**
* Set delay time to delayTime. When all motes have been ticked, the
* simulation waits for this time before ticking again.
*
* @param delayTime
* New delay time (ms)
*/
public void setDelayTime(int delayTime) {
this.delayTime = delayTime;
this.setChanged();
this.notifyObservers(this);
}
/**
* Returns current delay time.
*
* @return Delay time (ms)
*/
public int getDelayTime() {
return delayTime;
}
/**
* Set simulation time to simulationTime.
*
* @param simulationTime
* New simulation time (ms)
*/
public void setSimulationTime(int simulationTime) {
currentSimulationTime = simulationTime;
this.setChanged();
this.notifyObservers(this);
}
/**
* Returns current simulation time.
*
* @return Simulation time (ms)
*/
public int getSimulationTime() {
return currentSimulationTime;
}
/**
* Set tick time to tickTime. The tick time is the simulated time every tick
* takes. When all motes have been ticked, current simulation time is
* increased with tickTime. Default tick time is 1 ms.
*
* @see #getTickTime()
* @see #getTickTimeInSeconds()
* @param tickTime
* New tick time (ms)
*/
public void setTickTime(int tickTime) {
this.tickTime = tickTime;
this.setChanged();
this.notifyObservers(this);
}
/**
* Changes radio medium of this simulation to the given.
*
* @param radioMedium
* New radio medium
*/
public void setRadioMedium(RadioMedium radioMedium) {
// Remove current radio medium from observing motes
if (currentRadioMedium != null)
for (int i = 0; i < motes.size(); i++)
currentRadioMedium.unregisterMote(motes.get(i), this);
// Change current radio medium to new one
if (radioMedium == null) {
logger.fatal("Radio medium could not be created!");
return;
}
this.currentRadioMedium = radioMedium;
// Add all current motes to be observered by new radio medium
for (int i = 0; i < motes.size(); i++)
currentRadioMedium.registerMote(motes.get(i), this);
}
/**
* Get currently used radio medium.
*
* @return Currently used radio medium
*/
public RadioMedium getRadioMedium() {
return currentRadioMedium;
}
/**
* Get current tick time (ms).
*
* @see #setTickTime(int)
* @return Current tick time (ms)
*/
public int getTickTime() {
return tickTime;
}
/**
* Get current tick time (seconds).
*
* @see #setTickTime(int)
* @return Current tick time (seconds)
*/
public double getTickTimeInSeconds() {
return ((double) tickTime) / 1000.0;
}
/**
* Return true is simulation is running.
*
* @return True if simulation is running
*/
public boolean isRunning() {
return isRunning && thread != null;
}
/**
* Get current simulation title (short description).
*
* @return Title
*/
public String getTitle() {
return title;
}
/**
* Set simulation title.
*
* @param title
* New title
*/
public void setTitle(String title) {
this.title = title;
}
}

View file

@ -0,0 +1,95 @@
/*
* Copyright (c) 2006, 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: VisPlugin.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
*/
package se.sics.cooja;
import javax.swing.JInternalFrame;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
/**
* Abstract class VisPlugin should be implemented by plugins for COOJA Simulator.
* By extending JInternalFrame, the visual apperence is decided by the plugin itself.
*
* An implemented plugin should be registered at runtime using the following method:
* GUI.registerPlugin(Class<? extends VisPlugin>, String)
*
* For example how to implement a plugin see classes SimControl or Vis2D.
*
* @author Fredrik Osterlind
*/
public abstract class VisPlugin extends JInternalFrame {
/**
* Sets frame title
* @param title Frame title
*/
public VisPlugin(String title) {
super(title, true, true, true, true);
final VisPlugin thisPlugin = this;
// Close via gui
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
// Detect frame events
addInternalFrameListener(new InternalFrameListener() {
public void internalFrameClosing(InternalFrameEvent e) {
GUI.currentGUI.removePlugin(thisPlugin, true);
}
public void internalFrameClosed(InternalFrameEvent e) {
// NOP
}
public void internalFrameOpened(InternalFrameEvent e) {
// NOP
}
public void internalFrameIconified(InternalFrameEvent e) {
// NOP
}
public void internalFrameDeiconified(InternalFrameEvent e) {
// NOP
}
public void internalFrameActivated(InternalFrameEvent e) {
// NOP
}
public void internalFrameDeactivated(InternalFrameEvent e) {
// NOP
}
}
);
}
/**
* This method is called when an opened plugin is about to close.
* It should release any resources such as registered observers or
* opened interface visualizers.
*/
public abstract void closePlugin();
}

View file

@ -0,0 +1,109 @@
/*
* Copyright (c) 2006, 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: VisPluginType.java,v 1.1 2006/08/21 12:12:57 fros4943 Exp $
*/
package se.sics.cooja;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Annotation type to describe a plugin type.
*
* @author Fredrik Osterlind
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface VisPluginType {
public static final int UNDEFINED_PLUGIN = 0;
/**
* Mote Plugin
*
* A mote plugin concerns one specific mote.
*
* An example of such a plugin may be to display
* some mote information in a frame.
*
* Mote plugins can not be instantiated from the
* regular menu bar, but are instead started from
* other plugins, for example a visualizer that let's
* a user select a mote.
*
* When constructed, a mote plugin is given a Mote.
*
* If the current simulation is removed, so are
* all instances of this plugin.
*/
public static final int MOTE_PLUGIN = 1;
/**
* Simulation Plugin
*
* A simulation plugin concerns one specific simulation.
*
* An example of such a plugin may be to display
* number of motes and current simulation time in a window.
*
* Simulation plugins are available via the plugins menubar.
*
* When constructed, a simulation plugin is given the current
* active simulation.
*
* If the current simulation is removed, so are
* all instances of this plugin.
*/
public static final int SIM_PLUGIN = 2;
/**
* GUI Plugin
*
* A GUI plugin does not depend on the current simulation to function.
*
* An example of such a plugin may be a control panel
* where a user can control the current simulation.
*
* GUI plugins are available via the plugins menubar.
*
* When constructed, a GUI plugin is given the current GUI.
*/
public static final int GUI_PLUGIN = 3;
/**
* Simulation Standard Plugin
*
* This is treated exactly like a Simulation Plugin, with the
* only difference that this will automatically be opened
* when a new simulation is created.
*/
public static final int SIM_STANDARD_PLUGIN = 4;
int value();
}

View file

@ -0,0 +1,317 @@
/*
* Copyright (c) 2006, 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: ContikiMote.java,v 1.1 2006/08/21 12:13:10 fros4943 Exp $
*/
package se.sics.cooja.contikimote;
import java.util.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
/**
* A Contiki mote executes an actual Contiki system via
* a loaded shared library and JNI.
* It contains a section mote memory, a mote interface handler and a
* Contiki mote type.
*
* The mote type is responsible for the connection to the loaded
* Contiki system.
*
* When ticked a Contiki mote polls all interfaces, copies the mote
* memory to the core, lets the Contiki system handle one event,
* fetches the updated memory and finally polls all interfaces again.
* The mote state is also updated during a mote tick.
*
* @author Fredrik Osterlind
*/
public class ContikiMote implements Mote {
private static Logger logger = Logger.getLogger(ContikiMote.class);
private ContikiMoteType myType = null;
private SectionMoteMemory myMemory = null;
private MoteInterfaceHandler myInterfaceHandler = null;
private Simulation mySim = null;
// Time to wake up if sleeping
private int wakeUpTime = 0;
private int myState = STATE_ACTIVE;
// State observable
private class StateObservable extends Observable {
private void stateChanged() {
setChanged();
notifyObservers();
}
}
private StateObservable stateObservable = new StateObservable();
/**
* Creates a new uninitialized Contiki mote.
*
* This mote needs at least a type, a memory, a mote interface handler
* and to be connected to a simulation.
*/
public ContikiMote() {
}
/**
* Creates a new mote of given type.
* Both the initial mote memory and the interface handler
* are supplied from the mote type.
*
* @param moteType Mote type
* @param sim Mote's simulation
*/
public ContikiMote(ContikiMoteType moteType, Simulation sim) {
this.mySim = sim;
this.myType = moteType;
this.myMemory = moteType.createInitialMemory();
this.myInterfaceHandler = new MoteInterfaceHandler((Mote) this, moteType.getMoteInterfaces());
myState = STATE_ACTIVE;
}
public void setState(int newState) {
if (myState == STATE_DEAD) {
return;
}
if (myState == STATE_ACTIVE && newState != STATE_ACTIVE) {
myState = newState;
stateObservable.stateChanged();
}
if (myState == STATE_LPM && newState != STATE_LPM) {
myState = newState;
stateObservable.stateChanged();
}
}
public int getState() {
return myState;
}
public void addStateObserver(Observer newObserver) {
stateObservable.addObserver(newObserver);
}
public void deleteStateObserver(Observer newObserver) {
stateObservable.deleteObserver(newObserver);
}
public MoteInterfaceHandler getInterfaces() {
return myInterfaceHandler;
}
public void setInterfaces(MoteInterfaceHandler newInterfaces) {
myInterfaceHandler = newInterfaces;
}
public MoteMemory getMemory() {
return myMemory;
}
public void setMemory(MoteMemory memory) {
myMemory = (SectionMoteMemory) memory;
}
public MoteType getType() {
return myType;
}
public void setType(MoteType type) {
myType = (ContikiMoteType) type;
}
public Simulation getSimulation() {
return mySim;
}
public void setSimulation(Simulation simulation) {
mySim = simulation;
}
/**
* Ticks this mote once. This is done by first polling all interfaces
* and letting them act on the stored memory before the memory is set. Then
* the mote is ticked, and the new memory is received.
* Finally all interfaces are allowing to act on the new memory in order to
* discover relevant changes. This method also checks if mote should go to sleep
* depending on Contiki specifics; pending timers and polled processes.
*
* @param simTime Current simulation time
*/
public void tick(int simTime) {
// If mote is dead, do nothing at all
if (getState() == STATE_DEAD)
return;
// If mote is sleeping and has a wake up time, should it wake up now?
if (getState() == STATE_LPM && wakeUpTime > 0 && wakeUpTime <= simTime) {
setState(STATE_ACTIVE);
wakeUpTime = 0;
}
// If mote is active..
if (getState() == STATE_ACTIVE) {
// Let all active interfaces act before tick
// Observe that each interface may put the mote to sleep at this point
myInterfaceHandler.doActiveActionsBeforeTick();
}
// And let passive interfaces act even if mote is sleeping
myInterfaceHandler.doPassiveActionsBeforeTick();
// If mote is still active, complete this tick
if (getState() == STATE_ACTIVE) {
// Copy mote memory to core
myType.setCoreMemory(myMemory);
// Tick node
myType.tick();
// Fetch new updated memory from core
myType.getCoreMemory(myMemory);
// Let all active interfaces act again after tick
myInterfaceHandler.doActiveActionsAfterTick();
}
// Finally let all passive interfaces act
myInterfaceHandler.doPassiveActionsAfterTick();
// If mote is awake, should it go to sleep?
if (getState() == STATE_ACTIVE) {
// Check if this mote should sleep (no more pending timers or processes to poll)
int processRunValue = myMemory.getIntValueOf("simProcessRunValue");
int etimersPending = myMemory.getIntValueOf("simEtimerPending");
int nextExpirationTime = myMemory.getIntValueOf("simNextExpirationTime");
if (processRunValue == 0 && etimersPending == 0) {
setState(STATE_LPM);
wakeUpTime = 0;
}
if (processRunValue == 0 && etimersPending == 1 && nextExpirationTime > 0) {
setState(STATE_LPM);
wakeUpTime = nextExpirationTime;
}
}
}
/**
* Returns the current Contiki mote config represented by XML elements.
* This config also includes all mote interface configs.
*
* @return Current simulation config
*/
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;
}
public boolean setConfigXML(Simulation simulation, Collection<Element> configXML) {
mySim = simulation;
myState = STATE_ACTIVE;
for (Element element: configXML) {
String name = element.getName();
if (name.equals("motetype_identifier")) {
myType = (ContikiMoteType) simulation.getMoteType(element.getText());
myMemory = myType.createInitialMemory();
myInterfaceHandler = new MoteInterfaceHandler((Mote) this, myType.getMoteInterfaces());
} else if (name.equals("interface_config")) {
Class<? extends MoteInterface> moteInterfaceClass =
GUI.currentGUI.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 = myInterfaceHandler.getInterfaceOfType(moteInterfaceClass);
moteInterface.setConfigXML(element.getChildren());
}
}
return true;
}
public String toString() {
if (getInterfaces().getMoteID() != null) {
return "Contiki Mote, ID=" + getInterfaces().getMoteID().getMoteID();
} else
return "Contiki Mote, ID=null";
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2006, 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: ContikiMoteInterface.java,v 1.1 2006/08/21 12:13:09 fros4943 Exp $
*/
package se.sics.cooja.contikimote;
/**
* A Contiki mote interface has information about which, if any, core interfaces
* it needs.
*
* All classes implementing this interface should also define a static method:
* public String[] getCoreInterfaceDependencies() {
* ...
* }
*
* The method should return the names of all needed core interfaces.
*
* @author Fredrik Osterlind
*/
public interface ContikiMoteInterface {
}

View file

@ -0,0 +1,898 @@
/*
* Copyright (c) 2006, 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: ContikiMoteType.java,v 1.1 2006/08/21 12:13:09 fros4943 Exp $
*/
package se.sics.cooja.contikimote;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.io.*;
import java.security.*;
import java.util.*;
import java.util.regex.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
/**
* The Contiki mote type holds the native library used to communicate with an
* underlying Contiki system. All communication with that system should always
* pass through this mote type.
* <p>
* This type also contains information about which processes, sensors and core
* interfaces a mote of this type has, as well as where the Contiki OS, COOJA
* core files and an optional user platform are located.
* <p>
* All core communication with the Contiki mote should be via this class. When a
* mote type is created it allocates a CoreComm to be used with this type, and
* loads a map file. The map file is used to map variable names to addresses.
* <p>
* When a new mote type is created an initialization function is run on the
* Contiki system in order to create the initial memory. When a new mote is
* created the createInitialMemory() method should be called to get this initial
* memory for the mote.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Contiki Mote Type")
public class ContikiMoteType implements MoteType {
private static Logger logger = Logger.getLogger(ContikiMoteType.class);
/**
* Map file suffix
*/
final static public String mapSuffix = ".map";
/**
* Library file suffix
*/
final static public String librarySuffix = ".library";
/**
* Make dependency file suffix
*/
final static public String dependSuffix = ".a";
/**
* Temporary output directory
*/
final static public File tempOutputDirectory = new File("." + File.separatorChar + "obj_cooja" + File.separatorChar);
// Regular expressions for parsing the map file
final static private String bssSectionAddrRegExp = "^.bss[ \t]*0x([0-9A-Fa-f]*)[ \t]*0x[0-9A-Fa-f]*[ \t]*$";
final static private String bssSectionSizeRegExp = "^.bss[ \t]*0x[0-9A-Fa-f]*[ \t]*0x([0-9A-Fa-f]*)[ \t]*$";
final static private String dataSectionAddrRegExp = "^.data[ \t]*0x([0-9A-Fa-f]*)[ \t]*0x[0-9A-Fa-f]*[ \t]*$";
final static private String dataSectionSizeRegExp = "^.data[ \t]*0x[0-9A-Fa-f]*[ \t]*0x([0-9A-Fa-f]*)[ \t]*$";
final static private String varAddressRegExpPrefix = "^[ \t]*0x([0-9A-Fa-f]*)[ \t]*";
final static private String varAddressRegExpSuffix = "[ \t]*$";
final static private String varNameRegExp = "^[ \t]*(0x[0-9A-Fa-f]*)[ \t]*([^ ]*)[ \t]*$";
final static private String varSizeRegExpPrefix = "^";
final static private String varSizeRegExpSuffix = "[ \t]*(0x[0-9A-Fa-f]*)[ \t]*[^ ]*[ \t]*$";
// Mote type specific data
private String identifier = null;
private String description = null;
private String contikiBaseDir = null;
private String contikiCoreDir = null;
private Vector<File> userPlatformDirs = null;
private Vector<String> processes = null;
private Vector<String> sensors = null;
private Vector<String> coreInterfaces = null;
private Vector<Class<? extends MoteInterface>> moteInterfaces = null;
// Simulation holding this mote type
private Simulation mySimulation = null;
// Type specific class configuration
private PlatformConfig myConfig = null;
// Core communication variables
private String libraryClassName = null;
private int offsetRelToAbs = 0;
private CoreComm myCoreComm = null;
// Variable name to address mappings
private Properties varAddresses = new Properties();
// Map file contents
private Vector<String> mapContents = new Vector<String>();
// Initial memory for all motes of this type
private SectionMoteMemory initialMemory = null;
/**
* Creates a new uninitialized Contiki mote type. This mote type needs to load
* a library file and parse a map file before it can be used.
*/
public ContikiMoteType() {
}
/**
* Creates a new Contiki mote type. This type uses two external files: a map
* file for parsing relative addresses of Contiki variables (identifier +
* ".map") and a library file with an actual compiled Contiki system
* (identifier + ".library")
*
* @param identifier
* Unique identifier for this mote type
*/
public ContikiMoteType(String identifier) {
doInit(identifier);
}
public Mote generateMote(Simulation simulation) {
return new ContikiMote(this, simulation);
}
public boolean configureAndInit(JFrame parentFrame, Simulation simulation) {
return ContikiMoteTypeDialog.showDialog(parentFrame, simulation, this);
}
/**
* This is an mote type initialization method and should normally never be
* called by any other part than the mote type constructor. It is called from
* the constructor with an identifier argument. but not from the standard
* constructor. This method may be called from the simulator when loading
* configuration files, and the libraries must be recompiled.
*
* This method allocates a core communicator, loads the Contiki library file,
* loads and parses the map file, creates a variable name to address mapping
* of the Contiki system and finally creates the Contiki mote initial memory.
*
* @param identifier
* Mote type identifier
* @return True if initialization ok, false otherwise
*/
protected boolean doInit(String identifier) {
this.identifier = identifier;
if (myCoreComm != null) {
logger
.fatal("Core communicator not null. Is library already loaded? Aborting");
return false;
}
File libFile = new File(ContikiMoteType.tempOutputDirectory.getPath()
+ File.separatorChar + identifier + librarySuffix);
File mapFile = new File(ContikiMoteType.tempOutputDirectory.getPath()
+ File.separatorChar + identifier + mapSuffix);
// Check that library file exists
if (!libFile.exists()) {
logger.fatal("Library file could not be found: " + libFile);
return false;
}
// Check that map file exists
if (!mapFile.exists()) {
logger.fatal("Map file could not be found: " + mapFile);
return false;
}
// Allocate core communicator class
libraryClassName = CoreComm.getAvailableClassName();
myCoreComm = CoreComm.createCoreComm(libraryClassName, libFile);
// Load map file
mapContents = loadMapFile(mapFile);
if (mapContents == null) {
logger.fatal("Map file could not be loaded: " + mapFile);
return false;
}
// Load variable addresses from Contiki system
varAddresses.clear();
Vector<String> varNames = getAllVariableNames();
for (String varName : varNames) {
int varAddress = getRelVarAddress(varName);
if (varAddress > 0) {
varAddresses.put(varName, new Integer(varAddress));
} else
logger.warn("Parsed Contiki variable '" + varName
+ "' but could not find address");
}
// Get offset between relative and absolute addresses
offsetRelToAbs = getReferenceAbsAddr()
- getRelVarAddr(mapContents, "referenceVar");
// Parse addresses of data and BSS memory sections
int relDataSectionAddr = loadRelDataSectionAddr(mapContents);
int dataSectionSize = loadDataSectionSize(mapContents);
int relBssSectionAddr = loadRelBssSectionAddr(mapContents);
int bssSectionSize = loadBssSectionSize(mapContents);
if (relDataSectionAddr <= 0 || dataSectionSize <= 0
|| relBssSectionAddr <= 0 || bssSectionSize <= 0) {
logger.fatal("Could not parse section addresses correctly");
return false;
}
// Create initial memory
byte[] initialDataSection = getCoreMemory(relDataSectionAddr
+ offsetRelToAbs, dataSectionSize);
byte[] initialBssSection = getCoreMemory(
relBssSectionAddr + offsetRelToAbs, bssSectionSize);
initialMemory = new SectionMoteMemory(varAddresses);
initialMemory.setMemorySegment(relDataSectionAddr, initialDataSection);
initialMemory.setMemorySegment(relBssSectionAddr, initialBssSection);
return false;
}
/**
* Ticks the currently loaded mote. This should not be used directly, but
* rather via ContikiMote.tick().
*/
public void tick() {
myCoreComm.tick();
}
/**
* Creates and returns a copy of this mote type's initial memory (just after
* the init function has been run). When a new mote is created it should get
* it's memory from here.
*
* @return Initial memory of a mote type
*/
public SectionMoteMemory createInitialMemory() {
return initialMemory.clone();
}
/**
* Copy given memory to the Contiki system. This should not be used directly,
* but instead via ContikiMote.setMemory().
*
* @param mem
* New memory
*/
public void setCoreMemory(SectionMoteMemory mem) {
for (int i = 0; i < mem.getNumberOfSections(); i++) {
setCoreMemory(mem.getStartAddrOfSection(i) + offsetRelToAbs, mem
.getSizeOfSection(i), mem.getDataOfSection(i));
}
}
/**
* Copy core memory to given memory. This should not be used directly, but
* instead via ContikiMote.getMemory().
*
* @param mem
* Memory to set
*/
public void getCoreMemory(SectionMoteMemory mem) {
for (int i = 0; i < mem.getNumberOfSections(); i++) {
int startAddr = mem.getStartAddrOfSection(i);
int size = mem.getSizeOfSection(i);
mem.setMemorySegment(startAddr, getCoreMemory(startAddr + offsetRelToAbs,
size));
}
}
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
logger.warn("Contiki mote type is read-only");
}
/**
* @return Contiki mote type's library class name
*/
public String getLibraryClassName() {
return libraryClassName;
}
/**
* Get relative address of variable with given name.
*
* @param varName
* Name of variable
* @return Relative memory address of variable or -1 if not found
*/
protected int getRelVarAddress(String varName) {
int varAddr;
String varAddrString;
if ((varAddrString = varAddresses.getProperty(varName)) != null) {
varAddr = Integer.parseInt(varAddrString);
return varAddr;
}
String regExp = varAddressRegExpPrefix + varName + varAddressRegExpSuffix;
String retString = getFirstMatchGroup(mapContents, regExp, 1);
if (retString != null) {
varAddresses.setProperty(varName, Integer.toString(Integer.parseInt(
retString.trim(), 16)));
return Integer.parseInt(retString.trim(), 16);
} else
return -1;
}
private int getReferenceAbsAddr() {
return myCoreComm.getReferenceAbsAddr();
}
private byte[] getCoreMemory(int start, int length) {
return myCoreComm.getMemory(start, length);
}
private void setCoreMemory(int start, int length, byte[] mem) {
myCoreComm.setMemory(start, length, mem);
}
private static String getFirstMatchGroup(Vector<String> lines, String regexp,
int groupNr) {
Pattern pattern = Pattern.compile(regexp);
for (int i = 0; i < lines.size(); i++) {
Matcher matcher = pattern.matcher(lines.elementAt(i));
if (matcher.find()) {
return matcher.group(groupNr);
}
}
return null;
}
/**
* Returns all variable names in both data and BSS section by parsing the map
* file. These values should not be trusted completely as the parsing may
* fail.
*
* @return Variable names found in the data and bss section
*/
public Vector<String> getAllVariableNames() {
Vector<String> varNames = getAllVariableNames(mapContents,
loadRelDataSectionAddr(mapContents),
loadRelDataSectionAddr(mapContents) + loadDataSectionSize(mapContents));
varNames.addAll(getAllVariableNames(mapContents,
loadRelBssSectionAddr(mapContents), loadRelBssSectionAddr(mapContents)
+ loadBssSectionSize(mapContents)));
return varNames;
}
private Vector<String> getAllVariableNames(Vector<String> lines,
int startAddress, int endAddress) {
Vector<String> varNames = new Vector<String>();
Pattern pattern = Pattern.compile(varNameRegExp);
for (int i = 0; i < lines.size(); i++) {
Matcher matcher = pattern.matcher(lines.elementAt(i));
if (matcher.find()) {
if (Integer.decode(matcher.group(1)).intValue() >= startAddress
&& Integer.decode(matcher.group(1)).intValue() <= endAddress) {
varNames.add(matcher.group(2));
}
}
}
return varNames;
}
protected int getVariableSize(Vector<String> lines, String varName) {
Pattern pattern = Pattern.compile(varSizeRegExpPrefix + varName
+ varSizeRegExpSuffix);
for (int i = 0; i < lines.size(); i++) {
Matcher matcher = pattern.matcher(lines.elementAt(i));
if (matcher.find()) {
return Integer.decode(matcher.group(1));
}
}
return -1;
}
private static int loadRelDataSectionAddr(Vector<String> mapFile) {
String retString = getFirstMatchGroup(mapFile, dataSectionAddrRegExp, 1);
if (retString != null)
return Integer.parseInt(retString.trim(), 16);
else
return 0;
}
private static int loadDataSectionSize(Vector<String> mapFile) {
String retString = getFirstMatchGroup(mapFile, dataSectionSizeRegExp, 1);
if (retString != null)
return Integer.parseInt(retString.trim(), 16);
else
return 0;
}
private static int loadRelBssSectionAddr(Vector<String> mapFile) {
String retString = getFirstMatchGroup(mapFile, bssSectionAddrRegExp, 1);
if (retString != null)
return Integer.parseInt(retString.trim(), 16);
else
return 0;
}
private static int loadBssSectionSize(Vector<String> mapFile) {
String retString = getFirstMatchGroup(mapFile, bssSectionSizeRegExp, 1);
if (retString != null)
return Integer.parseInt(retString.trim(), 16);
else
return 0;
}
private static int getRelVarAddr(Vector<String> mapContents, String varName) {
String regExp = varAddressRegExpPrefix + varName + varAddressRegExpSuffix;
String retString = getFirstMatchGroup(mapContents, regExp, 1);
if (retString != null)
return Integer.parseInt(retString.trim(), 16);
else
return 0;
}
private static Vector<String> loadMapFile(File mapFile) {
Vector<String> mapContents = new Vector<String>();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
new FileInputStream(mapFile)));
while (in.ready()) {
mapContents.add(in.readLine());
}
} catch (FileNotFoundException e) {
logger.fatal("File not found: " + e);
return null;
} catch (IOException e) {
logger.fatal("IO error: " + e);
return null;
}
return mapContents;
}
/**
* Returns simulation holding this mote type
*
* @return Simulation
*/
public Simulation getSimulation() {
return mySimulation;
}
/**
* Sets simulation holding this mote type
*
* @param simulation
* Simulation holding this mote type
*/
public void setSimulation(Simulation simulation) {
mySimulation = simulation;
}
public String getDescription() {
return description;
}
public void setDescription(String newDescription) {
description = newDescription;
}
/**
* Returns path to contiki base dir
*
* @return String containing path
*/
public String getContikiBaseDir() {
return contikiBaseDir;
}
/**
* Sets contiki base dir to path.
*
* @param path
* Contiki base dir
*/
public void setContikiBaseDir(String path) {
contikiBaseDir = path;
}
/**
* Returns path to contiki core dir
*
* @return String containing path
*/
public String getContikiCoreDir() {
return contikiCoreDir;
}
/**
* Sets contiki core dir to path.
*
* @param path
* Contiki core dir
*/
public void setContikiCoreDir(String path) {
contikiCoreDir = path;
}
/**
* Returns user platform directories
*
* @return User platform directories
*/
public Vector<File> getUserPlatformDirs() {
return userPlatformDirs;
}
/**
* Sets user platform directories.
*
* @param dirs
* New user platform directories
*/
public void setUserPlatformDirs(Vector<File> dirs) {
userPlatformDirs = dirs;
}
public PlatformConfig getConfig() {
return myConfig;
}
/**
* Sets mote type platform configuration. This may differ from the general
* simulator platform configuration.
*
* @param moteTypeConfig
* Platform configuration
*/
public void setConfig(PlatformConfig moteTypeConfig) {
myConfig = moteTypeConfig;
}
/**
* Returns all processes of this mote type
*
* @return All processes
*/
public Vector<String> getProcesses() {
return processes;
}
/**
* Set startup processes
*
* @param processes
* New startup processes
*/
public void setProcesses(Vector<String> processes) {
this.processes = processes;
}
/**
* Returns all sensors of this mote type
*
* @return All sensors
*/
public Vector<String> getSensors() {
return sensors;
}
/**
* Set sensors
*
* @param sensors
* New sensors
*/
public void setSensors(Vector<String> sensors) {
this.sensors = sensors;
}
/**
* Returns all core interfaces of this mote type
*
* @return All core interfaces
*/
public Vector<String> getCoreInterfaces() {
return coreInterfaces;
}
/**
* Set core interfaces
*
* @param coreInterfaces
* New core interfaces
*/
public void setCoreInterfaces(Vector<String> coreInterfaces) {
this.coreInterfaces = coreInterfaces;
}
/**
* Returns all mote interfaces of this mote type
*
* @return All mote interfaces
*/
public Vector<Class<? extends MoteInterface>> getMoteInterfaces() {
return moteInterfaces;
}
/**
* Set mote interfaces of this mote type
*
* @param moteInterfaces
* New mote interfaces
*/
public void setMoteInterfaces(
Vector<Class<? extends MoteInterface>> moteInterfaces) {
this.moteInterfaces = moteInterfaces;
}
/**
* Create a checksum of file. Used for checking if needed files are unchanged
* when loading a saved simulation.
*
* @param file
* File containg data to checksum
* @return Checksum
*/
protected byte[] createChecksum(File file) {
int bytesRead = 1;
byte[] readBytes = new byte[128];
MessageDigest messageDigest;
try {
InputStream fileInputStream = new FileInputStream(file);
messageDigest = MessageDigest.getInstance("MD5");
while (bytesRead > 0) {
bytesRead = fileInputStream.read(readBytes);
if (bytesRead > 0)
messageDigest.update(readBytes, 0, bytesRead);
}
fileInputStream.close();
} catch (NoSuchAlgorithmException e) {
return null;
} catch (IOException e) {
return null;
}
return messageDigest.digest();
}
/**
* Returns a panel with interesting data for this mote type.
*
* @return Mote type visualizer
*/
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(identifier);
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(description);
smallPane.add(BorderLayout.EAST, label);
panel.add(smallPane);
// Contiki dir
smallPane = new JPanel(new BorderLayout());
label = new JLabel("Contiki path");
smallPane.add(BorderLayout.WEST, label);
label = new JLabel(contikiBaseDir);
smallPane.add(BorderLayout.EAST, label);
panel.add(smallPane);
// Library class name
smallPane = new JPanel(new BorderLayout());
label = new JLabel("JNI Class");
smallPane.add(BorderLayout.WEST, label);
label = new JLabel(libraryClassName);
smallPane.add(BorderLayout.EAST, label);
panel.add(smallPane);
// Processes
smallPane = new JPanel(new BorderLayout());
label = new JLabel("Processes");
smallPane.add(BorderLayout.WEST, label);
panel.add(smallPane);
for (String process : processes) {
smallPane = new JPanel(new BorderLayout());
label = new JLabel(process);
smallPane.add(BorderLayout.EAST, label);
panel.add(smallPane);
}
// Sensors
smallPane = new JPanel(new BorderLayout());
label = new JLabel("Sensors");
smallPane.add(BorderLayout.WEST, label);
panel.add(smallPane);
for (String sensor : sensors) {
smallPane = new JPanel(new BorderLayout());
label = new JLabel(sensor);
smallPane.add(BorderLayout.EAST, label);
panel.add(smallPane);
}
// Core Interfaces
smallPane = new JPanel(new BorderLayout());
label = new JLabel("Core interfaces");
smallPane.add(BorderLayout.WEST, label);
panel.add(smallPane);
for (String mInterface : coreInterfaces) {
smallPane = new JPanel(new BorderLayout());
label = new JLabel(mInterface);
smallPane.add(BorderLayout.EAST, label);
panel.add(smallPane);
}
// Mote Interfaces
smallPane = new JPanel(new BorderLayout());
label = new JLabel("Mote interfaces");
smallPane.add(BorderLayout.WEST, label);
panel.add(smallPane);
for (Class moteInterface : moteInterfaces) {
smallPane = new JPanel(new BorderLayout());
label = new JLabel(moteInterface.getSimpleName());
smallPane.add(BorderLayout.EAST, label);
panel.add(smallPane);
}
panel.add(Box.createRigidArea(new Dimension(0, 5)));
return panel;
}
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);
// Contiki base directory
element = new Element("contikibasedir");
element.setText(getContikiBaseDir());
config.add(element);
// Contiki core directory
element = new Element("contikicoredir");
element.setText(getContikiCoreDir());
config.add(element);
// User platform directory
for (File userPlatform: userPlatformDirs) {
element = new Element("userplatformdir");
element.setText(userPlatform.getPath());
config.add(element);
}
// Contiki processes
for (String process : getProcesses()) {
element = new Element("process");
element.setText(process);
config.add(element);
}
// Contiki sensors
for (String sensor : getSensors()) {
element = new Element("sensor");
element.setText(sensor);
config.add(element);
}
// Mote interfaces
for (Class moteInterface : getMoteInterfaces()) {
element = new Element("moteinterface");
element.setText(moteInterface.getName());
config.add(element);
}
// Core interfaces
for (String coreInterface : getCoreInterfaces()) {
element = new Element("coreinterface");
element.setText(coreInterface);
config.add(element);
}
return config;
}
public boolean setConfigXML(Simulation simulation,
Collection<Element> configXML) {
userPlatformDirs = new Vector<File>();
processes = new Vector<String>();
sensors = new Vector<String>();
coreInterfaces = new Vector<String>();
moteInterfaces = new Vector<Class<? extends MoteInterface>>();
mySimulation = simulation;
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("contikibasedir")) {
contikiBaseDir = element.getText();
} else if (name.equals("contikicoredir")) {
contikiCoreDir = element.getText();
} else if (name.equals("userplatformdir")) {
userPlatformDirs.add(new File(element.getText()));
} else if (name.equals("process")) {
processes.add(element.getText());
} else if (name.equals("sensor")) {
sensors.add(element.getText());
} else if (name.equals("coreinterface")) {
coreInterfaces.add(element.getText());
} else if (name.equals("moteinterface")) {
Class<? extends MoteInterface> moteInterfaceClass =
GUI.currentGUI.tryLoadClass(this, MoteInterface.class, element.getText().trim());
if (moteInterfaceClass == null) {
logger.warn("Can't find mote interface class: " + element.getText());
} else
moteInterfaces.add(moteInterfaceClass);
} else {
logger.fatal("Unrecognized entry in loaded configuration: " + name);
}
}
boolean createdOK = configureAndInit(GUI.frame, simulation);
return createdOK;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2006, 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: ContikiBeeper.java,v 1.1 2006/08/21 12:13:05 fros4943 Exp $
*/
package se.sics.cooja.contikimote.interfaces;
import java.util.Collection;
import javax.swing.JPanel;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.Beeper;
/**
* Ths class represents a beeper.
*
* It needs read access to the following core variables:
* <ul>
* <li>char simBeeped (1=on, else off)
* </ul>
* <p>
* Dependency core interfaces are:
* <ul>
* <li>beep_interface
* </ul>
* <p>
* This observable is changed and notifies observers whenever the beeper changes
* state.
*
* @author Fredrik Osterlind
*/
public class ContikiBeeper extends Beeper implements ContikiMoteInterface {
private Mote mote = null;
private SectionMoteMemory moteMem = null;
private static Logger logger = Logger.getLogger(ContikiBeeper.class);
/**
* Assuming beep always lasts for 0.1 seconds. ESB measured energy
* consumption: 16.69 mA. Total energy consumption of a beep is then:
* 0.1*16.69
*/
private final double ENERGY_CONSUMPTION_BEEP;
private double myEnergyConsumption = 0.0;
private boolean justBeeped = false;
/**
* Creates an interface to the beeper at mote.
*
* @param mote
* Beeper's mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public ContikiBeeper(Mote mote) {
// Read class configurations of this mote type
ENERGY_CONSUMPTION_BEEP = mote.getType().getConfig().getDoubleValue(
ContikiBeeper.class, "BEEP_CONSUMPTION_mQ");
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
}
public boolean isBeeping() {
return justBeeped;
}
public static String[] getCoreInterfaceDependencies() {
return new String[]{"beep_interface"};
}
public void doActionsBeforeTick() {
// Nothing to do
justBeeped = false;
}
public void doActionsAfterTick() {
if (moteMem.getByteValueOf("simBeeped") == 1) {
this.setChanged();
this.notifyObservers(mote);
justBeeped = true;
moteMem.setByteValueOf("simBeeped", (byte) 0);
myEnergyConsumption = ENERGY_CONSUMPTION_BEEP;
} else
myEnergyConsumption = 0.0;
}
public JPanel getInterfaceVisualizer() {
return null;
}
public void releaseInterfaceVisualizer(JPanel panel) {
}
public double energyConsumptionPerTick() {
return myEnergyConsumption;
}
public Collection<Element> getConfigXML() {
return null;
}
public void setConfigXML(Collection<Element> configXML) {
}
}

View file

@ -0,0 +1,176 @@
/*
* Copyright (c) 2006, 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: ContikiButton.java,v 1.1 2006/08/21 12:13:05 fros4943 Exp $
*/
package se.sics.cooja.contikimote.interfaces;
import java.awt.event.*;
import java.util.Collection;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.Button;
/**
* This class represents a button.
*
* It needs read/write access to the following core variables:
* <ul>
* <li>char simButtonIsDown (1=down, else up)
* <li>char simButtonChanged (1=changed, else not changed)
* <li>char simButtonIsActive (1=active, else inactive)
* </ul>
* Dependency core interfaces are:
* <ul>
* <li>button_interface
* </ul>
* <p>
* This observable notifies observers when the button changes state (between
* pressed and released).
*
* @author Fredrik Osterlind
*/
public class ContikiButton extends Button implements ContikiMoteInterface {
private SectionMoteMemory moteMem;
private Mote mote;
private boolean shouldBeReleased = false;
private static Logger logger = Logger.getLogger(ContikiButton.class);
private final boolean RAISES_EXTERNAL_INTERRUPT;
/**
* Creates an interface to the button at mote.
*
* @param mote
* Button's mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public ContikiButton(Mote mote) {
// Read class configurations of this mote type
RAISES_EXTERNAL_INTERRUPT = mote.getType().getConfig()
.getBooleanValue(ContikiButton.class, "EXTERNAL_INTERRUPT_bool");
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
}
public static String[] getCoreInterfaceDependencies() {
return new String[]{"button_interface"};
}
/**
* Clicks button. Button will be down for one tick, and then released.
*/
public void clickButton() {
pressButton();
shouldBeReleased = true;
}
public void releaseButton() {
moteMem.setByteValueOf("simButtonIsDown", (byte) 0);
if (moteMem.getByteValueOf("simButtonIsActive") == 1) {
moteMem.setByteValueOf("simButtonChanged", (byte) 1);
// If mote is inactive, wake it up
if (RAISES_EXTERNAL_INTERRUPT)
mote.setState(Mote.STATE_ACTIVE);
setChanged();
notifyObservers();
}
}
public void pressButton() {
moteMem.setByteValueOf("simButtonIsDown", (byte) 1);
if (moteMem.getByteValueOf("simButtonIsActive") == 1) {
moteMem.setByteValueOf("simButtonChanged", (byte) 1);
// If mote is inactive, wake it up
if (RAISES_EXTERNAL_INTERRUPT)
mote.setState(Mote.STATE_ACTIVE);
setChanged();
notifyObservers();
}
}
public boolean isPressed() {
return moteMem.getByteValueOf("simButtonIsDown") == 1;
}
public void doActionsBeforeTick() {
// Nothing to do
}
public void doActionsAfterTick() {
// If a button is pressed and should be clicked, release it now
if (shouldBeReleased) {
releaseButton();
shouldBeReleased = false;
}
}
public JPanel getInterfaceVisualizer() {
JPanel panel = new JPanel();
final JButton clickButton = new JButton("Click button");
panel.add(clickButton);
clickButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
clickButton();
}
});
return panel;
}
public void releaseInterfaceVisualizer(JPanel panel) {
}
public double energyConsumptionPerTick() {
return 0.0;
}
public Collection<Element> getConfigXML() {
return null;
}
public void setConfigXML(Collection<Element> configXML) {
}
}

View file

@ -0,0 +1,117 @@
/*
* Copyright (c) 2006, 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: ContikiClock.java,v 1.1 2006/08/21 12:13:05 fros4943 Exp $
*/
package se.sics.cooja.contikimote.interfaces;
import java.util.Collection;
import javax.swing.JPanel;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.Clock;
/**
* The class represents a clock and controls the core time.
*
* It needs read/write access to the following core variables:
* <ul>
* <li>int simCurrentTime
* </ul>
* Dependency core interfaces are:
* <ul>
* <li>clock_interface
* </ul>
* <p>
* This observable never updates.
*
* @author Fredrik Osterlind
*/
public class ContikiClock extends Clock implements ContikiMoteInterface {
private Mote mote = null;
private SectionMoteMemory moteMem = null;
private int timeDrift = 0;
/**
* Creates a time connected to mote.
*
* @param mote
* Mote to connect this time to.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public ContikiClock(Mote mote) {
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
}
public static String[] getCoreInterfaceDependencies() {
return new String[]{"clock_interface"};
}
public void setTime(int newTime) {
moteMem.setIntValueOf("simCurrentTime", newTime);
}
public int getTime() {
return moteMem.getIntValueOf("simCurrentTime");
}
public void doActionsBeforeTick() {
// Update core time to correspond with the simulation time
setTime((int) mote.getSimulation().getSimulationTime() + timeDrift);
}
public void doActionsAfterTick() {
// Nothing to do
}
public JPanel getInterfaceVisualizer() {
return null;
}
public void releaseInterfaceVisualizer(JPanel panel) {
}
public double energyConsumptionPerTick() {
return 0.0;
}
public Collection<Element> getConfigXML() {
return null;
}
public void setConfigXML(Collection<Element> configXML) {
}
}

View file

@ -0,0 +1,187 @@
/*
* Copyright (c) 2006, 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: ContikiIPAddress.java,v 1.1 2006/08/21 12:13:04 fros4943 Exp $
*/
package se.sics.cooja.contikimote.interfaces;
import java.util.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.IPAddress;
/**
* This class represents an uIP IP address.
*
* It needs write access to the following core variables:
* <ul>
* <li>char simIPa
* <li>char simIPb
* <li>char simIPc
* <li>char simIPd
* <li>char simIPChanged (1 if new IP should be set)
* </ul>
* <p>
* The new IP will be "simIPa.simIPb.simIPc.simIPd". Dependency core interfaces
* are:
* <ul>
* <li>ip_interface
* </ul>
*
* This observable notifies observers if the IP address is set or changed.
*
* @author Fredrik Osterlind
*/
public class ContikiIPAddress extends IPAddress implements ContikiMoteInterface {
private SectionMoteMemory moteMem = null;
private static Logger logger = Logger.getLogger(ContikiIPAddress.class);
private boolean setIP;
char a = 0, b = 0, c = 0, d = 0;
/**
* Creates an interface to the IP address at mote.
*
* @param mote
* IP address' mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public ContikiIPAddress(Mote mote) {
this.moteMem = (SectionMoteMemory) mote.getMemory();
setIP = false;
}
public static String[] getCoreInterfaceDependencies() {
return new String[]{"ip_interface"};
}
public String getIPString() {
return "" + (int) a + "." + (int) b + "." + (int) c + "." + (int) d;
}
public void setIPString(String ipAddress) {
String[] ipArray = ipAddress.split("\\.");
if (ipArray.length < 4) {
logger.warn("Could not set ip address (" + ipAddress + ")");
} else
setIPNumber((char) Integer.parseInt(ipArray[0]), (char) Integer
.parseInt(ipArray[1]), (char) Integer.parseInt(ipArray[2]),
(char) Integer.parseInt(ipArray[3]));
}
public void setIPNumber(char a, char b, char c, char d) {
setIP = true;
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
public void doActionsBeforeTick() {
if (setIP) {
setIP = false;
moteMem.setByteValueOf("simIPa", (byte) a);
moteMem.setByteValueOf("simIPb", (byte) b);
moteMem.setByteValueOf("simIPc", (byte) c);
moteMem.setByteValueOf("simIPd", (byte) d);
moteMem.setByteValueOf("simIPChanged", (byte) 1);
setChanged();
notifyObservers();
}
}
public void doActionsAfterTick() {
// Nothing to do
}
public JPanel getInterfaceVisualizer() {
JPanel panel = new JPanel();
final JLabel ipLabel = new JLabel();
ipLabel.setText("Current address: " + (int) a + "." + (int) b + "."
+ (int) c + "." + (int) d);
panel.add(ipLabel);
Observer observer;
this.addObserver(observer = new Observer() {
public void update(Observable obs, Object obj) {
ipLabel.setText("Current address: " + (int) a + "." + (int) b + "."
+ (int) c + "." + (int) d);
}
});
// Saving observer reference for releaseInterfaceVisualizer
panel.putClientProperty("intf_obs", observer);
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 double energyConsumptionPerTick() {
// Virtual interface, does not require any energy
return 0.0;
}
public Collection<Element> getConfigXML() {
Vector<Element> config = new Vector<Element>();
Element element;
// Infinite boolean
element = new Element("ipv4address");
element.setText(getIPString());
config.add(element);
return config;
}
public void setConfigXML(Collection<Element> configXML) {
for (Element element : configXML) {
if (element.getName().equals("ipv4address")) {
setIPString(element.getText());
}
}
}
}

View file

@ -0,0 +1,260 @@
/*
* Copyright (c) 2006, 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: ContikiLED.java,v 1.1 2006/08/21 12:13:05 fros4943 Exp $
*/
package se.sics.cooja.contikimote.interfaces;
import java.awt.*;
import java.util.*;
import javax.swing.JPanel;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.LED;
/**
* This class represents three mote LEDs.
*
* It needs read access to the following core variables:
* <ul>
* <li>char simLedsValue
* </ul>
* <p>
* Dependency core interfaces are:
* <ul>
* <li>leds_interface
* </ul>
* <p>
* This observable is changed and notifies observers whenever any led has
* changed.
*
* @author Fredrik Osterlind
*/
public class ContikiLED extends LED implements ContikiMoteInterface {
private static Logger logger = Logger.getLogger(ContikiLED.class);
private Mote mote = null;
private SectionMoteMemory moteMem = null;
private byte oldLedValue = 0;
private static final byte LEDS_GREEN = 1;
private static final byte LEDS_YELLOW = 2;
private static final byte LEDS_RED = 4;
private static final Color DARK_GREEN = new Color(0, 100, 0);
private static final Color DARK_YELLOW = new Color(100, 100, 0);
private static final Color DARK_RED = new Color(100, 0, 0);
private static final Color GREEN = new Color(0, 255, 0);
private static final Color YELLOW = new Color(255, 255, 0);
private static final Color RED = new Color(255, 0, 0);
private double myEnergyConsumption = 0.0;
/**
* Approximate energy consumption of a green led (mA). ESB measured value:
* 5.69 mA. TODO Measure energy consumption
*/
public final double ENERGY_CONSUMPTION_GREEN_LED;
/**
* Approximate energy consumption of a yellow led (mA). ESB measured value:
* 5.69 mA. TODO Measure energy consumption
*/
public final double ENERGY_CONSUMPTION_YELLOW_LED;
/**
* Approximate energy consumption of a red led (mA). ESB measured value: 5.69
* mA.
*/
public final double ENERGY_CONSUMPTION_RED_LED;
private double energyOfGreenLedPerTick = -1;
private double energyOfYellowLedPerTick = -1;
private double energyOfRedLedPerTick = -1;
public ContikiLED() {
ENERGY_CONSUMPTION_GREEN_LED = 0;
ENERGY_CONSUMPTION_YELLOW_LED = 0;
ENERGY_CONSUMPTION_RED_LED = 0;
}
/**
* Creates an interface to the led at mote.
*
* @param mote
* Led's mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public ContikiLED(Mote mote) {
// Read class configurations of this mote type
ENERGY_CONSUMPTION_GREEN_LED = mote.getType().getConfig()
.getDoubleValue(ContikiLED.class, "GREEN_LED_CONSUMPTION_mA");
ENERGY_CONSUMPTION_YELLOW_LED = mote.getType().getConfig()
.getDoubleValue(ContikiLED.class, "YELLOW_LED_CONSUMPTION_mA");
ENERGY_CONSUMPTION_RED_LED = mote.getType().getConfig()
.getDoubleValue(ContikiLED.class, "RED_LED_CONSUMPTION_mA");
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
if (energyOfGreenLedPerTick < 0) {
energyOfGreenLedPerTick = ENERGY_CONSUMPTION_GREEN_LED
* mote.getSimulation().getTickTimeInSeconds();
energyOfYellowLedPerTick = ENERGY_CONSUMPTION_YELLOW_LED
* mote.getSimulation().getTickTimeInSeconds();
energyOfRedLedPerTick = ENERGY_CONSUMPTION_RED_LED
* mote.getSimulation().getTickTimeInSeconds();
}
}
public static String[] getCoreInterfaceDependencies() {
return new String[]{"leds_interface"};
}
public boolean isAnyOn() {
return oldLedValue > 0;
}
public boolean isGreenOn() {
return (oldLedValue & LEDS_GREEN) > 0;
}
public boolean isYellowOn() {
return (oldLedValue & LEDS_YELLOW) > 0;
}
public boolean isRedOn() {
return (oldLedValue & LEDS_RED) > 0;
}
public void doActionsBeforeTick() {
// Nothing to do
}
public void doActionsAfterTick() {
if (checkLedStatus()) {
this.setChanged();
this.notifyObservers(mote);
}
}
private boolean checkLedStatus() {
boolean ledChanged;
byte newLedsValue = moteMem.getByteValueOf("simLedsValue");
if (newLedsValue != oldLedValue) {
ledChanged = true;
} else {
ledChanged = false;
}
myEnergyConsumption = 0.0;
if ((newLedsValue & LEDS_GREEN) > 0)
myEnergyConsumption += energyOfGreenLedPerTick;
if ((newLedsValue & LEDS_YELLOW) > 0)
myEnergyConsumption += energyOfYellowLedPerTick;
if ((newLedsValue & LEDS_RED) > 0)
myEnergyConsumption += energyOfRedLedPerTick;
oldLedValue = newLedsValue;
return ledChanged;
}
public JPanel getInterfaceVisualizer() {
final JPanel panel = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (isGreenOn()) {
g.setColor(GREEN);
g.fillOval(20, 20, 20, 20);
} else {
g.setColor(DARK_GREEN);
g.fillOval(20, 20, 20, 20);
}
if (isYellowOn()) {
g.setColor(YELLOW);
g.fillOval(60, 20, 20, 20);
} else {
g.setColor(DARK_YELLOW);
g.fillOval(60, 20, 20, 20);
}
if (isRedOn()) {
g.setColor(RED);
g.fillOval(100, 20, 20, 20);
} else {
g.setColor(DARK_RED);
g.fillOval(100, 20, 20, 20);
}
}
};
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 double energyConsumptionPerTick() {
return myEnergyConsumption;
}
public Collection<Element> getConfigXML() {
return null;
}
public void setConfigXML(Collection<Element> configXML) {
}
}

View file

@ -0,0 +1,169 @@
/*
* Copyright (c) 2006, 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: ContikiLog.java,v 1.1 2006/08/21 12:13:05 fros4943 Exp $
*/
package se.sics.cooja.contikimote.interfaces;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.Log;
/**
* The class Log is an abstract interface to a mote's logging output. It needs
* read access to the following core variables:
* <ul>
* <li>char simLoggedFlag
* (1=mote has new outgoing log messages, else no new)
* <li>int simLoggedLength
* (length of new log message)
* <li>byte[] simLoggedData (data of new log messages)
* </ul>
* <p>
* Dependency core interfaces are:
* <ul>
* <li>simlog_interface
* </ul>
* <p>
* This observable is changed and notifies observers whenever a log message has
* been received from the core (checked after each tick). The public method
* getLastLogMessages gives access to the last log message(s).
*
* @author Fredrik Osterlind
*/
public class ContikiLog extends Log implements ContikiMoteInterface {
private static Logger logger = Logger.getLogger(ContikiLog.class);
private Mote mote = null;
private SectionMoteMemory moteMem = null;
private String lastLogMessage = null;
/**
* Creates an interface to mote's logging output.
*
* @param mote Log's mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public ContikiLog(Mote mote) {
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
}
public static String[] getCoreInterfaceDependencies() {
return new String[] { "simlog_interface" };
}
public void doActionsBeforeTick() {
// Nothing to do
}
public void doActionsAfterTick() {
if (moteMem.getByteValueOf("simLoggedFlag") == 1) {
int totalLength = moteMem.getIntValueOf("simLoggedLength");
byte[] bytes = moteMem.getByteArray("simLoggedData", totalLength);
char[] chars = new char[bytes.length];
for (int i=0; i < chars.length; i++)
chars[i] = (char) bytes[i];
String message = String.valueOf(chars);
lastLogMessage = message;
moteMem.setByteValueOf("simLoggedFlag", (byte) 0);
moteMem.setIntValueOf("simLoggedLength", (int) 0);
this.setChanged();
this.notifyObservers(mote);
}
}
public String getLastLogMessages() {
return lastLogMessage;
}
public JPanel getInterfaceVisualizer() {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
final JTextArea logTextPane = new JTextArea();
logTextPane.setOpaque(false);
logTextPane.setEditable(false);
if (lastLogMessage == null)
logTextPane.setText("");
else
logTextPane.append(lastLogMessage);
Observer observer;
this.addObserver(observer = new Observer() {
public void update(Observable obs, Object obj) {
logTextPane.append(lastLogMessage);
logTextPane.setCaretPosition(logTextPane.getDocument().getLength());
}
});
// Saving observer reference for releaseInterfaceVisualizer
panel.putClientProperty("intf_obs", observer);
JScrollPane scrollPane = new JScrollPane(logTextPane);
scrollPane.setPreferredSize(new Dimension(100,100));
panel.add(BorderLayout.NORTH, new JLabel("Last log messages:"));
panel.add(BorderLayout.CENTER, scrollPane);
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 double energyConsumptionPerTick() {
// Does not require energy
return 0.0;
}
public Collection<Element> getConfigXML() {
return null;
}
public void setConfigXML(Collection<Element> configXML) {
}
}

View file

@ -0,0 +1,167 @@
/*
* Copyright (c) 2006, 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: ContikiMoteID.java,v 1.1 2006/08/21 12:13:05 fros4943 Exp $
*/
package se.sics.cooja.contikimote.interfaces;
import java.util.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.MoteID;
/**
* Ths class represents a mote ID number.
*
* It needs write access to the following core variables:
* <ul>
* <li>int simMoteID
* <li>char simMoteIDChanged
* </ul>
* When the mote id is set or changed, the random generator will also be seeded
* with this id (core function random_init()).
* <p>
* Dependency core interfaces are:
* <ul>
* <li>moteid_interface
* </ul>
* This observable notifies observers when the mote ID is set or changed.
*
* @author Fredrik Osterlind
*/
public class ContikiMoteID extends MoteID implements ContikiMoteInterface {
private SectionMoteMemory moteMem = null;
private static Logger logger = Logger.getLogger(ContikiMoteID.class);
private boolean setMoteID;
int moteID = 0;
/**
* Creates an interface to the mote ID at mote.
*
* @param mote
* Mote ID's mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public ContikiMoteID(Mote mote) {
this.moteMem = (SectionMoteMemory) mote.getMemory();
setMoteID = false;
}
public static String[] getCoreInterfaceDependencies() {
return new String[]{"moteid_interface"};
}
public int getMoteID() {
return moteID;
}
public void setMoteID(int newID) {
setMoteID = true;
moteID = newID;
setChanged();
notifyObservers();
}
public void doActionsBeforeTick() {
if (setMoteID) {
setMoteID = false;
moteMem.setIntValueOf("simMoteID", moteID);
moteMem.setByteValueOf("simMoteIDChanged", (byte) 1);
}
setChanged();
notifyObservers();
}
public void doActionsAfterTick() {
// Nothing to do
}
public JPanel getInterfaceVisualizer() {
JPanel panel = new JPanel();
final JLabel idLabel = new JLabel();
idLabel.setText("Mote ID: " + moteID);
panel.add(idLabel);
Observer observer;
this.addObserver(observer = new Observer() {
public void update(Observable obs, Object obj) {
idLabel.setText("Mote ID: " + moteID);
}
});
// Saving observer reference for releaseInterfaceVisualizer
panel.putClientProperty("intf_obs", observer);
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 double energyConsumptionPerTick() {
return 0.0;
}
public Collection<Element> getConfigXML() {
Vector<Element> config = new Vector<Element>();
Element element;
// Infinite boolean
element = new Element("id");
element.setText(Integer.toString(moteID));
config.add(element);
return config;
}
public void setConfigXML(Collection<Element> configXML) {
for (Element element : configXML) {
if (element.getName().equals("id")) {
setMoteID(Integer.parseInt(element.getText()));
}
}
}
}

View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2006, 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: ContikiPIR.java,v 1.1 2006/08/21 12:13:05 fros4943 Exp $
*/
package se.sics.cooja.contikimote.interfaces;
import java.awt.event.*;
import java.util.Collection;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.PIR;
/**
* This class represents a passive infrared sensor.
*
* It needs read/write access to the following core variables:
* <ul>
* <li>char simPirChanged (1=changed, else not changed)
* <li>char simPirIsActive (1=active, else inactive)
* </ul>
* <p>
* Dependency core interfaces are:
* <ul>
* <li>pir_interface
* </ul>
* <p>
* This observable notifies observers if a change is discovered by the PIR.
*
* @author Fredrik Osterlind
*/
public class ContikiPIR extends PIR implements ContikiMoteInterface {
private static Logger logger = Logger.getLogger(ContikiPIR.class);
/**
* Approximate energy consumption of an active PIR sensor. ESB measured energy
* consumption is 0.4 mA. TODO Measure energy consumption
*/
public final double ENERGY_CONSUMPTION_PIR_mA;
private final boolean RAISES_EXTERNAL_INTERRUPT;
private double energyActivePerTick = -1;
private Mote mote;
private SectionMoteMemory moteMem;
private double myEnergyConsumption = 0.0;
/**
* Creates an interface to the pir at mote.
*
* @param mote
* Button's mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public ContikiPIR(Mote mote) {
// Read class configurations of this mote type
ENERGY_CONSUMPTION_PIR_mA = mote.getType().getConfig().getDoubleValue(
ContikiPIR.class, "ACTIVE_CONSUMPTION_mA");
RAISES_EXTERNAL_INTERRUPT = mote.getType().getConfig()
.getBooleanValue(ContikiPIR.class, "EXTERNAL_INTERRUPT_bool");
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
if (energyActivePerTick < 0)
energyActivePerTick = ENERGY_CONSUMPTION_PIR_mA
* mote.getSimulation().getTickTimeInSeconds();
}
public static String[] getCoreInterfaceDependencies() {
return new String[]{"pir_interface"};
}
public void triggerChange() {
if (moteMem.getByteValueOf("simPirIsActive") == 1) {
moteMem.setByteValueOf("simPirChanged", (byte) 1);
// If mote is inactive, wake it up
if (RAISES_EXTERNAL_INTERRUPT)
mote.setState(Mote.STATE_ACTIVE);
this.setChanged();
this.notifyObservers();
}
}
public void doActionsBeforeTick() {
if (moteMem.getByteValueOf("simPirIsActive") == 1) {
myEnergyConsumption = energyActivePerTick;
} else
myEnergyConsumption = 0.0;
}
public void doActionsAfterTick() {
// Nothing to do
}
public JPanel getInterfaceVisualizer() {
JPanel panel = new JPanel();
final JButton clickButton = new JButton("Signal PIR");
panel.add(clickButton);
clickButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
triggerChange();
}
});
return panel;
}
public void releaseInterfaceVisualizer(JPanel panel) {
}
public double energyConsumptionPerTick() {
return myEnergyConsumption;
}
public Collection<Element> getConfigXML() {
return null;
}
public void setConfigXML(Collection<Element> configXML) {
}
}

View file

@ -0,0 +1,256 @@
/*
* Copyright (c) 2006, 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: ContikiRS232.java,v 1.1 2006/08/21 12:13:04 fros4943 Exp $
*/
package se.sics.cooja.contikimote.interfaces;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface;
/**
* The class represents a simple RS232/Serial interface (only shows String
* format).
*
* It needs read/write access to the following core variables:
* <ul>
* <li>char simSerialSendingFlag (1=mote is sending data)
* <li>int simSerialSendingLength (length of data being sent from mote)
* <li>byte[] simSerialSendingData (data being sent from mote)
* <li>char simSerialRecevingFlag (1=mote is receving data)
* <li>int simSerialReceivingLength (length of data being received at mote)
* <li>byte[] simSerialReceivingData (data being received at mote)
* </ul>
* <p>
* Dependency core interfaces are:
* <ul>
* <li>rs232_interface
* </ul>
* <p>
* This observable is changed and notifies observers whenever a serial message
* has been received from the core (checked after each tick). The public method
* getSerialMessages gives access to the last data.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Serial port (RS232)")
public class ContikiRS232 extends MoteInterface implements ContikiMoteInterface {
private static Logger logger = Logger.getLogger(ContikiRS232.class);
private Mote mote = null;
private SectionMoteMemory moteMem = null;
private String lastSerialMessage = null;
private final boolean RAISES_EXTERNAL_INTERRUPT;
private JTextArea logTextPane = null;
/**
* Approximate energy consumption of every sent character over RS232 (mQ).
*/
public final double ENERGY_CONSUMPTION_PER_CHAR_mQ;
private double myEnergyConsumption = 0.0;
/**
* Creates an interface to the RS232 at mote.
*
* @param mote
* RS232's mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public ContikiRS232(Mote mote) {
// Read class configurations of this mote type
ENERGY_CONSUMPTION_PER_CHAR_mQ = mote.getType().getConfig()
.getDoubleValue(ContikiRS232.class, "CONSUMPTION_PER_CHAR_mQ");
RAISES_EXTERNAL_INTERRUPT = mote.getType().getConfig()
.getBooleanValue(ContikiRS232.class, "EXTERNAL_INTERRUPT_bool");
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
}
public static String[] getCoreInterfaceDependencies() {
return new String[]{"rs232_interface"};
}
public void doActionsBeforeTick() {
// Nothing to do
}
public void doActionsAfterTick() {
if (moteMem.getByteValueOf("simSerialSendingFlag") == 1) {
int totalLength = moteMem.getIntValueOf("simSerialSendingLength");
byte[] bytes = moteMem.getByteArray("simSerialSendingData", totalLength);
char[] chars = new char[bytes.length];
for (int i = 0; i < chars.length; i++)
chars[i] = (char) bytes[i];
myEnergyConsumption = ENERGY_CONSUMPTION_PER_CHAR_mQ * totalLength;
String message = String.valueOf(chars);
lastSerialMessage = message;
moteMem.setByteValueOf("simSerialSendingFlag", (byte) 0);
moteMem.setIntValueOf("simSerialSendingLength", (int) 0);
this.setChanged();
this.notifyObservers(mote);
} else
myEnergyConsumption = 0.0;
}
/**
* Returns all serial messages sent by mote the last tick that anything was
* sent.
*
* @return Last serial messages sent by mote.
*/
public String getSerialMessages() {
return lastSerialMessage;
}
/**
* Send a serial message to mote.
*
* @param message
* Message that mote should receive
*/
public void sendSerialMessage(String message) {
if (logTextPane != null) {
logTextPane.append("> " + message + "\n");
}
// Flag for incoming data
moteMem.setByteValueOf("simSerialReceivingFlag", (byte) 1);
byte[] dataToAppend = message.getBytes();
// Increase receiving size
int oldSize = moteMem.getIntValueOf("simSerialReceivingLength");
moteMem.setIntValueOf("simSerialReceivingLength", oldSize
+ dataToAppend.length);
int newSize = moteMem.getIntValueOf("simSerialReceivingLength");
// Write buffer characters
byte[] oldData = moteMem.getByteArray("simSerialReceivingData", oldSize);
byte[] newData = new byte[newSize];
for (int i = 0; i < oldData.length; i++)
newData[i] = oldData[i];
for (int i = 0; i < message.length(); i++)
newData[i + oldSize] = dataToAppend[i];
moteMem.setByteArray("simSerialReceivingData", newData);
if (RAISES_EXTERNAL_INTERRUPT)
mote.setState(Mote.STATE_ACTIVE);
}
public JPanel getInterfaceVisualizer() {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
if (logTextPane == null)
logTextPane = new JTextArea();
// Send RS232 data visualizer
JPanel sendPane = new JPanel();
final JTextField sendTextField = new JTextField(15);
JButton sendButton = new JButton("Send data");
sendButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendSerialMessage(sendTextField.getText());
}
});
sendPane.add(BorderLayout.WEST, sendTextField);
sendPane.add(BorderLayout.EAST, sendButton);
// Receive RS232 data visualizer
logTextPane.setOpaque(false);
logTextPane.setEditable(false);
if (lastSerialMessage == null)
logTextPane.setText("");
else
logTextPane.append(lastSerialMessage);
Observer observer;
this.addObserver(observer = new Observer() {
public void update(Observable obs, Object obj) {
logTextPane.append("< " + lastSerialMessage + "\n");
logTextPane.setCaretPosition(logTextPane.getDocument().getLength());
}
});
// Saving observer reference for releaseInterfaceVisualizer
panel.putClientProperty("intf_obs", observer);
JScrollPane scrollPane = new JScrollPane(logTextPane);
scrollPane.setPreferredSize(new Dimension(100, 100));
panel.add(BorderLayout.NORTH, new JLabel("Last serial data:"));
panel.add(BorderLayout.CENTER, scrollPane);
panel.add(BorderLayout.SOUTH, sendPane);
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 double energyConsumptionPerTick() {
return myEnergyConsumption;
}
public Collection<Element> getConfigXML() {
return null;
}
public void setConfigXML(Collection<Element> configXML) {
}
}

View file

@ -0,0 +1,305 @@
/*
* Copyright (c) 2006, 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: ContikiRadio.java,v 1.1 2006/08/21 12:13:05 fros4943 Exp $
*/
package se.sics.cooja.contikimote.interfaces;
import java.util.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.Radio;
/**
* This class represents a radio transciever.
*
* It needs read/write access to the following core variables:
* <ul>
* <li>char simSentPacket (1=mote has new outgoing data, else no new outgoing
* data)
* <li>char simReceivedPacket (1=mote has new incoming data, else no new
* incoming data)
* <li>char simEtherBusy (1=ether is busy, MAC may try to resend later, else
* not busy)
* <li>int simReceivedPacketSize (size of new received data packet)
* <li>int simSentPacketSize (size of new sent data packet)
* <li>byte[] simSentPacketData (data of new sent data packet)
* <li>byte[] simReceivedPacketData (data of new received data packet)
* <li>char simRadioHWOn (radio hardware status (on/off))
* </ul>
* <p>
* Dependency core interfaces are:
* <ul>
* <li>radio_interface
* </ul>
* <p>
* This observable is changed and notifies observers whenever either the send
* status or listen status is changed. If current listen status is HEARS_PACKET
* just before a mote tick, the current packet data is transferred to the core.
* Otherwise no data will be transferred. If core has sent a packet, current
* sent status will be set to SENT_SOMETHING when returning from the mote tick
* that sent the packet. This status will be reset to SENT_NOTHING just before
* next tick.
*
* @author Fredrik Osterlind
*/
public class ContikiRadio extends Radio implements ContikiMoteInterface {
private Mote myMote;
private SectionMoteMemory myMoteMemory;
private static Logger logger = Logger.getLogger(ContikiRadio.class);
/**
* Approximate energy consumption of an active radio. ESB measured energy
* consumption is 5 mA. TODO Measure energy consumption
*/
public final double ENERGY_CONSUMPTION_RADIO_mA;
private final boolean RAISES_EXTERNAL_INTERRUPT;
private double energyActiveRadioPerTick = -1;
private int mySendState = SENT_NOTHING;
private int myListenState = HEARS_NOTHING;
private byte[] packetToMote = null;
private byte[] packetFromMote = null;
private boolean radioOn = true;
private double myEnergyConsumption=0.0;
/**
* Creates an interface to the radio at mote.
*
* @param mote
* Radio's mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public ContikiRadio(Mote mote) {
// Read class configurations of this mote type
ENERGY_CONSUMPTION_RADIO_mA = mote.getType().getConfig().getDoubleValue(ContikiRadio.class, "ACTIVE_CONSUMPTION_mA");
RAISES_EXTERNAL_INTERRUPT = mote.getType().getConfig().getBooleanValue(ContikiRadio.class, "EXTERNAL_INTERRUPT_bool");
this.myMote = mote;
this.myMoteMemory = (SectionMoteMemory) mote.getMemory();
if (energyActiveRadioPerTick < 0)
energyActiveRadioPerTick = ENERGY_CONSUMPTION_RADIO_mA * mote.getSimulation().getTickTimeInSeconds();
}
public static String[] getCoreInterfaceDependencies() {
return new String[] { "radio_interface" };
}
public byte[] getLastPacketSent() {
return packetFromMote;
}
public byte[] getLastPacketReceived() {
return packetToMote;
}
public void receivePacket(byte[] data) {
packetToMote = data;
}
public int getSendState() {
return mySendState;
}
public int getListenState() {
return myListenState;
}
public void setListenState(int newStatus) {
if (newStatus != myListenState) {
myListenState = newStatus;
this.setChanged();
this.notifyObservers(myMote.getInterfaces().getPosition());
}
// If mote is inactive, wake it up
if (RAISES_EXTERNAL_INTERRUPT)
myMote.setState(Mote.STATE_ACTIVE);
}
public void advanceListenState() {
if (myListenState == HEARS_NOTHING) {
setListenState(HEARS_PACKET);
} else
setListenState(HEARS_NOISE);
}
public void doActionsBeforeTick() {
// If radio hardware is turned off, we don't need to do anything..
if (!radioOn) {
myEnergyConsumption = 0.0;
return;
}
myEnergyConsumption = energyActiveRadioPerTick;
// Set ether status
if (getListenState() == HEARS_PACKET ||
getListenState() == HEARS_NOISE ||
getSendState() == SENT_SOMETHING) {
myMoteMemory.setByteValueOf("simEtherBusy", (byte) 1);
} else {
myMoteMemory.setByteValueOf("simEtherBusy", (byte) 0);
}
if (getListenState() == HEARS_NOTHING) {
// Haven't heard anything, nothing to do
} else if (getListenState() == HEARS_PACKET) {
// Heard only one packet, transfer to mote ok
myMoteMemory.setByteValueOf("simReceivedPacket", (byte) 1);
myMoteMemory.setIntValueOf("simReceivedPacketSize", packetToMote.length);
myMoteMemory.setByteArray("simReceivedPacketData", packetToMote);
} else if (getListenState() == HEARS_NOISE) {
// Heard several packets or noise, transfer failed
}
// Reset send flag
setSendStatus(SENT_NOTHING);
}
public void doActionsAfterTick() {
// Check new radio hardware status
if (myMoteMemory.getByteValueOf("simRadioHWOn") == 1) {
radioOn = true;
} else {
radioOn = false;
return;
}
// Reset listen flag
setListenState(HEARS_NOTHING);
if (fetchPacketFromCore()) {
setSendStatus(SENT_SOMETHING);
}
}
private void setSendStatus(int newStatus) {
if (newStatus != mySendState) {
mySendState = newStatus;
this.setChanged();
this.notifyObservers(myMote.getInterfaces().getPosition());
}
}
private boolean fetchPacketFromCore() {
if (myMoteMemory.getByteValueOf("simSentPacket") == 1) {
// TODO Increase energy consumption, we are sending a packet...
myMoteMemory.setByteValueOf("simSentPacket", (byte) 0);
int size = myMoteMemory.getIntValueOf("simSentPacketSize");
packetFromMote = myMoteMemory.getByteArray("simSentPacketData", size);
myMoteMemory.setIntValueOf("simSentPacketSize", 0);
return true;
}
return false;
}
public JPanel getInterfaceVisualizer() {
// Location
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
final JLabel listenLabel = new JLabel();
final JLabel sendLabel = new JLabel();
if (getListenState() == HEARS_NOISE)
listenLabel.setText("Current listen status: hears noise");
else if (getListenState() == HEARS_NOTHING)
listenLabel.setText("Current listen status: hears nothing");
else if (getListenState() == HEARS_PACKET)
listenLabel.setText("Current listen status: hears a packet");
if (getSendState() == SENT_NOTHING)
sendLabel.setText("Current sending status: sent nothing");
else if (getSendState() == SENT_SOMETHING)
sendLabel.setText("Current sending status: sent a packet");
panel.add(listenLabel);
panel.add(sendLabel);
Observer observer;
this.addObserver(observer = new Observer() {
public void update(Observable obs, Object obj) {
if (getListenState() == HEARS_NOISE)
listenLabel.setText("Current listen status: hears noise");
else if (getListenState() == HEARS_NOTHING)
listenLabel.setText("Current listen status: hears nothing");
else if (getListenState() == HEARS_PACKET)
listenLabel.setText("Current listen status: hears a packet");
if (getSendState() == SENT_NOTHING)
sendLabel.setText("Current sending status: sent nothing");
else if (getSendState() == SENT_SOMETHING)
sendLabel.setText("Current sending status: sent a packet");
}
});
// Saving observer reference for releaseInterfaceVisualizer
panel.putClientProperty("intf_obs", observer);
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 double energyConsumptionPerTick() {
return myEnergyConsumption;
}
public Collection<Element> getConfigXML() {
return null;
}
public void setConfigXML(Collection<Element> configXML) {
}
}

View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2006, 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: ContikiVib.java,v 1.1 2006/08/21 12:13:05 fros4943 Exp $
*/
package se.sics.cooja.contikimote.interfaces;
import java.awt.event.*;
import java.util.Collection;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.contikimote.ContikiMoteInterface;
/**
* This class represents a vibration sensor.
*
* It needs read/write access to the following core variables:
* <ul>
* <li>char simVibChanged (1=changed, else not changed)
* <li>char simVibIsActive (1=active, else inactive)
* </ul>
* <p>
* Dependency core interfaces are:
* <ul>
* <li>vib_interface
* </ul>
* <p>
* This observable never notifies observers.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Vibration sensor")
public class ContikiVib extends MoteInterface implements ContikiMoteInterface {
private static Logger logger = Logger.getLogger(ContikiVib.class);
/**
* Approximate energy consumption of an active vibrator sensor. ESB measured
* energy consumption is 1.58 mA.
*/
public final double ENERGY_CONSUMPTION_VIB_mA;
private final boolean RAISES_EXTERNAL_INTERRUPT;
private double energyActiveVibPerTick = -1;
private Mote mote;
private SectionMoteMemory moteMem;
private double myEnergyConsumption = 0.0;
/**
* Creates an interface to the vibration sensor at mote.
*
* @param mote
* Vib's mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public ContikiVib(Mote mote) {
// Read class configurations of this mote type
ENERGY_CONSUMPTION_VIB_mA = mote.getType().getConfig().getDoubleValue(
ContikiVib.class, "ACTIVE_CONSUMPTION_mA");
RAISES_EXTERNAL_INTERRUPT = mote.getType().getConfig()
.getBooleanValue(ContikiVib.class, "EXTERNAL_INTERRUPT_bool");
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
if (energyActiveVibPerTick < 0)
energyActiveVibPerTick = ENERGY_CONSUMPTION_VIB_mA
* mote.getSimulation().getTickTimeInSeconds();
}
public static String[] getCoreInterfaceDependencies() {
return new String[]{"vib_interface"};
}
/**
* Simulates a change in the vibration sensor.
*/
public void triggerChange() {
if (moteMem.getByteValueOf("simVibIsActive") == 1) {
moteMem.setByteValueOf("simVibChanged", (byte) 1);
// If mote is inactive, wake it up
if (RAISES_EXTERNAL_INTERRUPT)
mote.setState(Mote.STATE_ACTIVE);
}
}
public void doActionsBeforeTick() {
if (moteMem.getByteValueOf("simVibIsActive") == 1) {
myEnergyConsumption = energyActiveVibPerTick; // ESB measured value
} else
myEnergyConsumption = 0.0;
}
public void doActionsAfterTick() {
// Nothing to do
}
public JPanel getInterfaceVisualizer() {
JPanel panel = new JPanel();
final JButton clickButton = new JButton("Vibrate!");
panel.add(clickButton);
clickButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
triggerChange();
}
});
return panel;
}
public void releaseInterfaceVisualizer(JPanel panel) {
}
public double energyConsumptionPerTick() {
return myEnergyConsumption;
}
public Collection<Element> getConfigXML() {
return null;
}
public void setConfigXML(Collection<Element> configXML) {
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2006, 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: Lib1.java,v 1.1 2006/08/21 12:12:57 fros4943 Exp $
*/
package se.sics.cooja.corecomm;
import java.io.File;
import se.sics.cooja.*;
/**
* @see CoreComm
* @author Fredrik Osterlind
*/
public class Lib1 extends CoreComm {
/**
* Loads library libFile.
*
* @see CoreComm
* @param libFile Library file
*/
public Lib1(File libFile) {
System.load(libFile.getAbsolutePath());
init();
}
public native void tick();
public native void init();
public native int getReferenceAbsAddr();
public native byte[] getMemory(int start, int length);
public native void setMemory(int start, int length, byte[] mem);
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2006, 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: Lib2.java,v 1.1 2006/08/21 12:12:57 fros4943 Exp $
*/
package se.sics.cooja.corecomm;
import java.io.File;
import se.sics.cooja.*;
/**
* @see CoreComm
* @author Fredrik Osterlind
*/
public class Lib2 extends CoreComm {
/**
* Loads library libFile.
*
* @see CoreComm
* @param libFile Library file
*/
public Lib2(File libFile) {
System.load(libFile.getAbsolutePath());
init();
}
public native void tick();
public native void init();
public native int getReferenceAbsAddr();
public native byte[] getMemory(int start, int length);
public native void setMemory(int start, int length, byte[] mem);
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2006, 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: Lib3.java,v 1.1 2006/08/21 12:12:57 fros4943 Exp $
*/
package se.sics.cooja.corecomm;
import java.io.File;
import se.sics.cooja.*;
/**
* @see CoreComm
* @author Fredrik Osterlind
*/
public class Lib3 extends CoreComm {
/**
* Loads library libFile.
*
* @see CoreComm
* @param libFile Library file
*/
public Lib3(File libFile) {
System.load(libFile.getAbsolutePath());
init();
}
public native void tick();
public native void init();
public native int getReferenceAbsAddr();
public native byte[] getMemory(int start, int length);
public native void setMemory(int start, int length, byte[] mem);
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2006, 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: Lib4.java,v 1.1 2006/08/21 12:12:57 fros4943 Exp $
*/
package se.sics.cooja.corecomm;
import java.io.File;
import se.sics.cooja.*;
/**
* @see CoreComm
* @author Fredrik Osterlind
*/
public class Lib4 extends CoreComm {
/**
* Loads library libFile.
*
* @see CoreComm
* @param libFile Library file
*/
public Lib4(File libFile) {
System.load(libFile.getAbsolutePath());
init();
}
public native void tick();
public native void init();
public native int getReferenceAbsAddr();
public native byte[] getMemory(int start, int length);
public native void setMemory(int start, int length, byte[] mem);
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2006, 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: Lib5.java,v 1.1 2006/08/21 12:12:57 fros4943 Exp $
*/
package se.sics.cooja.corecomm;
import java.io.File;
import se.sics.cooja.*;
/**
* @see CoreComm
* @author Fredrik Osterlind
*/
public class Lib5 extends CoreComm {
/**
* Loads library libFile.
*
* @see CoreComm
* @param libFile Library file
*/
public Lib5(File libFile) {
System.load(libFile.getAbsolutePath());
init();
}
public native void tick();
public native void init();
public native int getReferenceAbsAddr();
public native byte[] getMemory(int start, int length);
public native void setMemory(int start, int length, byte[] mem);
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2006, 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: Lib6.java,v 1.1 2006/08/21 12:12:58 fros4943 Exp $
*/
package se.sics.cooja.corecomm;
import java.io.File;
import se.sics.cooja.*;
/**
* @see CoreComm
* @author Fredrik Osterlind
*/
public class Lib6 extends CoreComm {
/**
* Loads library libFile.
*
* @see CoreComm
* @param libFile Library file
*/
public Lib6(File libFile) {
System.load(libFile.getAbsolutePath());
init();
}
public native void tick();
public native void init();
public native int getReferenceAbsAddr();
public native byte[] getMemory(int start, int length);
public native void setMemory(int start, int length, byte[] mem);
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2006, 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: Lib7.java,v 1.1 2006/08/21 12:12:58 fros4943 Exp $
*/
package se.sics.cooja.corecomm;
import java.io.File;
import se.sics.cooja.*;
/**
* @see CoreComm
* @author Fredrik Osterlind
*/
public class Lib7 extends CoreComm {
/**
* Loads library libFile.
*
* @see CoreComm
* @param libFile Library file
*/
public Lib7(File libFile) {
System.load(libFile.getAbsolutePath());
init();
}
public native void tick();
public native void init();
public native int getReferenceAbsAddr();
public native byte[] getMemory(int start, int length);
public native void setMemory(int start, int length, byte[] mem);
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2006, 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: Lib8.java,v 1.1 2006/08/21 12:12:58 fros4943 Exp $
*/
package se.sics.cooja.corecomm;
import java.io.File;
import se.sics.cooja.*;
/**
* @see CoreComm
* @author Fredrik Osterlind
*/
public class Lib8 extends CoreComm {
/**
* Loads library libFile.
*
* @see CoreComm
* @param libFile Library file
*/
public Lib8(File libFile) {
System.load(libFile.getAbsolutePath());
init();
}
public native void tick();
public native void init();
public native int getReferenceAbsAddr();
public native byte[] getMemory(int start, int length);
public native void setMemory(int start, int length, byte[] mem);
}

View file

@ -0,0 +1,502 @@
/*
* Copyright (c) 2006, 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: AddMoteDialog.java,v 1.1 2006/08/21 12:13:01 fros4943 Exp $
*/
package se.sics.cooja.dialogs;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.*;
/**
* A dialog for adding motes.
*
* @author Fredrik Osterlind
*/
public class AddMoteDialog extends JDialog {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(AddMoteDialog.class);
private AddMotesEventHandler myEventHandler = new AddMotesEventHandler();
private final static int LABEL_WIDTH = 170;
private final static int LABEL_HEIGHT = 15;
private Vector<Mote> newMotes = null;
private boolean settingsOK = true;
private JButton addButton;
private MoteType moteType = null;
private JFormattedTextField numberOfMotesField, startX, endX, startY, endY,
startZ, endZ;
private JComboBox positionDistributionBox, ipDistributionBox;
/**
* Shows a dialog which enables a user to create and add motes of the given
* type.
*
* @param parentFrame
* Parent frame for dialog
* @param moteType
* Mote type
* @return New motes or null if aborted
*/
public static Vector<Mote> showDialog(Frame parentFrame, MoteType moteType) {
AddMoteDialog myDialog = new AddMoteDialog(parentFrame, moteType);
myDialog.setLocationRelativeTo(parentFrame);
myDialog.checkSettings();
if (myDialog != null) {
myDialog.setVisible(true);
}
return myDialog.newMotes;
}
private AddMoteDialog(Frame frame, MoteType moteType) {
super(frame, "Add motes (" + moteType.getDescription() + ")", true);
this.moteType = moteType;
JLabel label;
JPanel mainPane = new JPanel();
mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
JPanel smallPane;
JFormattedTextField numberField;
JButton button;
JComboBox comboBox;
NumberFormat integerFormat = NumberFormat.getIntegerInstance();
NumberFormat doubleFormat = NumberFormat.getNumberInstance();
// BOTTOM BUTTON PART
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonPane.add(Box.createHorizontalGlue());
button = new JButton("Cancel");
button.setActionCommand("cancel");
button.addActionListener(myEventHandler);
buttonPane.add(button);
button = new JButton("Create and Add");
button.setEnabled(settingsOK);
button.setActionCommand("add");
button.addActionListener(myEventHandler);
this.getRootPane().setDefaultButton(button);
addButton = button;
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
buttonPane.add(button);
// MAIN PART
// Number of new motes
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Number of new motes");
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
numberField = new JFormattedTextField(integerFormat);
numberField.setValue(new Integer(1));
numberField.setColumns(10);
numberField.addPropertyChangeListener("value", myEventHandler);
numberOfMotesField = numberField;
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
smallPane.add(numberField);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
// IP address distribution
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("IP Addressing");
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
Vector<Class<? extends IPDistributor>> ipDistributors = GUI.currentGUI
.getRegisteredIPDistributors();
String[] ipDistributions = new String[ipDistributors.size()];
for (int i = 0; i < ipDistributions.length; i++)
ipDistributions[i] = GUI.getDescriptionOf(ipDistributors.get(i));
comboBox = new JComboBox(ipDistributions);
comboBox.setSelectedIndex(0);
comboBox.addActionListener(myEventHandler);
comboBox.addFocusListener(myEventHandler);
ipDistributionBox = comboBox;
label.setLabelFor(comboBox);
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
smallPane.add(comboBox);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
// Position distribution
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Positioning");
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
Vector<Class<? extends Positioner>> positioners = GUI.currentGUI
.getRegisteredPositioners();
String[] posDistributions = new String[positioners.size()];
for (int i = 0; i < posDistributions.length; i++)
posDistributions[i] = GUI.getDescriptionOf(positioners.get(i));
comboBox = new JComboBox(posDistributions);
comboBox.setSelectedIndex(0);
comboBox.addActionListener(myEventHandler);
comboBox.addFocusListener(myEventHandler);
positionDistributionBox = comboBox;
label.setLabelFor(comboBox);
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
smallPane.add(comboBox);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
// Position interval X
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Position interval");
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
label = new JLabel("X ");
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
numberField = new JFormattedTextField(doubleFormat);
numberField.setValue(new Double(0.0));
numberField.setColumns(4);
numberField.addPropertyChangeListener("value", myEventHandler);
startX = numberField;
smallPane.add(numberField);
smallPane.add(Box.createHorizontalStrut(10));
label = new JLabel("<->");
label.setPreferredSize(new Dimension(LABEL_WIDTH / 4, LABEL_HEIGHT));
smallPane.add(label);
numberField = new JFormattedTextField(doubleFormat);
numberField.setValue(new Double(100.0));
numberField.setColumns(4);
numberField.addPropertyChangeListener("value", myEventHandler);
endX = numberField;
smallPane.add(numberField);
smallPane.add(Box.createHorizontalStrut(10));
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
// Position interval Y
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("");
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
label = new JLabel("Y ");
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
numberField = new JFormattedTextField(doubleFormat);
numberField.setValue(new Double(0.0));
numberField.setColumns(4);
numberField.addPropertyChangeListener("value", myEventHandler);
startY = numberField;
smallPane.add(numberField);
smallPane.add(Box.createHorizontalStrut(10));
label = new JLabel("<->");
label.setPreferredSize(new Dimension(LABEL_WIDTH / 4, LABEL_HEIGHT));
smallPane.add(label);
numberField = new JFormattedTextField(doubleFormat);
numberField.setValue(new Double(100.0));
numberField.setColumns(4);
numberField.addPropertyChangeListener("value", myEventHandler);
endY = numberField;
smallPane.add(numberField);
smallPane.add(Box.createHorizontalStrut(10));
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
// Position interval Z
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("");
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
label = new JLabel("Z ");
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
numberField = new JFormattedTextField(doubleFormat);
numberField.setValue(new Double(0.0));
numberField.setColumns(4);
numberField.addPropertyChangeListener("value", myEventHandler);
startZ = numberField;
smallPane.add(numberField);
smallPane.add(Box.createHorizontalStrut(10));
label = new JLabel("<->");
label.setPreferredSize(new Dimension(LABEL_WIDTH / 4, LABEL_HEIGHT));
smallPane.add(label);
numberField = new JFormattedTextField(doubleFormat);
numberField.setValue(new Double(0.0));
numberField.setColumns(4);
numberField.addPropertyChangeListener("value", myEventHandler);
endZ = numberField;
smallPane.add(numberField);
smallPane.add(Box.createHorizontalStrut(10));
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
mainPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
Container contentPane = getContentPane();
contentPane.add(mainPane, BorderLayout.NORTH);
contentPane.add(buttonPane, BorderLayout.SOUTH);
pack();
}
private void checkSettings() {
// Check settings
settingsOK = true;
// Check X interval
if (((Number) startX.getValue()).doubleValue() > ((Number) endX.getValue())
.doubleValue()) {
startX.setBackground(Color.RED);
startX.setToolTipText("Malformed interval");
endX.setBackground(Color.RED);
endX.setToolTipText("Malformed interval");
settingsOK = false;
} else {
startX.setBackground(Color.WHITE);
startX.setToolTipText(null);
endX.setBackground(Color.WHITE);
endX.setToolTipText(null);
}
// Check Y interval
if (((Number) startY.getValue()).doubleValue() > ((Number) endY.getValue())
.doubleValue()) {
startY.setBackground(Color.RED);
startY.setToolTipText("Malformed interval");
endY.setBackground(Color.RED);
endY.setToolTipText("Malformed interval");
settingsOK = false;
} else {
startY.setBackground(Color.WHITE);
startY.setToolTipText(null);
endY.setBackground(Color.WHITE);
endY.setToolTipText(null);
}
// Check Z interval
if (((Number) startZ.getValue()).doubleValue() > ((Number) endZ.getValue())
.doubleValue()) {
startZ.setBackground(Color.RED);
startZ.setToolTipText("Malformed interval");
endZ.setBackground(Color.RED);
endZ.setToolTipText("Malformed interval");
settingsOK = false;
} else {
startZ.setBackground(Color.WHITE);
startZ.setToolTipText(null);
endZ.setBackground(Color.WHITE);
endZ.setToolTipText(null);
}
// Check number of new motes
if (((Number) numberOfMotesField.getValue()).intValue() < 1) {
numberOfMotesField.setBackground(Color.RED);
numberOfMotesField.setToolTipText("Must be >= 1");
settingsOK = false;
} else {
numberOfMotesField.setBackground(Color.WHITE);
numberOfMotesField.setToolTipText(null);
}
addButton.setEnabled(settingsOK);
}
private class AddMotesEventHandler
implements
ActionListener,
FocusListener,
PropertyChangeListener {
public void propertyChange(PropertyChangeEvent e) {
checkSettings();
}
public void focusGained(FocusEvent e) {
// NOP
}
public void focusLost(FocusEvent e) {
checkSettings();
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("cancel")) {
newMotes = null;
dispose();
} else if (e.getActionCommand().equals("add")) {
newMotes = new Vector<Mote>();
// Create new motes
int motesToAdd = ((Number) numberOfMotesField.getValue()).intValue();
while (newMotes.size() < motesToAdd) {
Mote newMote = moteType.generateMote(GUI.currentSimulation);
newMotes.add(newMote);
}
// Position new motes
Class<? extends Positioner> positionerClass = null;
for (Class<? extends Positioner> positioner : GUI.currentGUI
.getRegisteredPositioners()) {
if (GUI.getDescriptionOf(positioner).equals(
(String) positionDistributionBox.getSelectedItem()))
positionerClass = positioner;
}
Positioner positioner = Positioner.generateInterface(positionerClass,
((Number) numberOfMotesField.getValue()).intValue(),
((Number) startX.getValue()).doubleValue(), ((Number) endX
.getValue()).doubleValue(), ((Number) startY.getValue())
.doubleValue(), ((Number) endY.getValue()).doubleValue(),
((Number) startZ.getValue()).doubleValue(), ((Number) endZ
.getValue()).doubleValue());
if (positioner == null) {
logger.fatal("Could not create positioner");
dispose();
return;
}
for (int i = 0; i < newMotes.size(); i++) {
Position newPosition = newMotes.get(i).getInterfaces().getPosition();
if (newPosition != null) {
double[] newPositionArray = positioner.getNextPosition();
if (newPositionArray.length >= 3)
newPosition.setCoordinates(newPositionArray[0],
newPositionArray[1], newPositionArray[2]);
else if (newPositionArray.length >= 2)
newPosition.setCoordinates(newPositionArray[0],
newPositionArray[1], 0);
else if (newPositionArray.length >= 1)
newPosition.setCoordinates(newPositionArray[0], 0, 0);
else
newPosition.setCoordinates(0, 0, 0);
}
}
// Set unique mote id's for all new motes
int nextMoteID = 1;
for (int i = 0; i < GUI.currentSimulation.getMotesCount(); i++) {
MoteID moteID = GUI.currentSimulation.getMote(i).getInterfaces()
.getMoteID();
if (moteID != null && moteID.getMoteID() >= nextMoteID)
nextMoteID = moteID.getMoteID() + 1;
}
for (int i = 0; i < newMotes.size(); i++) {
MoteID moteID = newMotes.get(i).getInterfaces().getMoteID();
if (moteID != null) {
moteID.setMoteID(nextMoteID++);
}
}
// IP address new motes
Class<? extends IPDistributor> ipDistClass = null;
for (Class<? extends IPDistributor> ipDistributor : GUI.currentGUI
.getRegisteredIPDistributors()) {
if (GUI.getDescriptionOf(ipDistributor).equals(
(String) ipDistributionBox.getSelectedItem()))
ipDistClass = ipDistributor;
}
IPDistributor ipDistributor = IPDistributor.generateInterface(
ipDistClass, newMotes);
if (ipDistributor == null) {
logger.fatal("Could not create IP distributor");
dispose();
return;
}
for (int i = 0; i < newMotes.size(); i++) {
String newIPString = ipDistributor.getNextIPAddress();
if (newMotes.get(i).getInterfaces().getIPAddress() != null)
newMotes.get(i).getInterfaces().getIPAddress().setIPString(
newIPString);
}
dispose();
}
}
}
}

View file

@ -0,0 +1,339 @@
/*
* Copyright (c) 2006, 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: CreateSimDialog.java,v 1.1 2006/08/21 12:13:02 fros4943 Exp $
*/
package se.sics.cooja.dialogs;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.text.*;
import java.util.Vector;
import javax.swing.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
/**
* A dialog for creating and configuring a simulation.
*
* @author Fredrik Osterlind
*/
public class CreateSimDialog extends JDialog {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(CreateSimDialog.class);
private AddSimEventHandler myEventHandler = new AddSimEventHandler();
private final static int LABEL_WIDTH = 170;
private final static int LABEL_HEIGHT = 15;
private Simulation mySimulation = null;
private CreateSimDialog myDialog;
private JFormattedTextField delayTime, simulationTime, tickTime;
private JTextField title;
private JComboBox radioMediumBox;
private JTextField logFilename;
private JCheckBox logCheckBox;
/**
* Shows a dialog for configuring a simulation.
*
* @param parentFrame Parent frame for dialog
* @param simulationToConfigure Simulation to configure
* @return True if simulation configured correctly
*/
public static boolean showDialog(Frame parentFrame, Simulation simulationToConfigure) {
CreateSimDialog myDialog = new CreateSimDialog(parentFrame);
myDialog.mySimulation = simulationToConfigure;
// Set title
if (simulationToConfigure.getTitle() != null) {
// Title already preset
myDialog.title.setText(simulationToConfigure.getTitle());
} else {
// Suggest title
myDialog.title.setText("[enter simulation title]");
}
// Set delay time
myDialog.delayTime.setValue(new Integer(simulationToConfigure.getDelayTime()));
// Set simulation time
myDialog.simulationTime.setValue(new Integer(simulationToConfigure.getSimulationTime()));
// Set tick time
myDialog.tickTime.setValue(new Integer(simulationToConfigure.getTickTime()));
// Select radio medium
if (simulationToConfigure.getRadioMedium() != null) {
Class<? extends RadioMedium> radioMediumClass =
simulationToConfigure.getRadioMedium().getClass();
String currentDescription = GUI.getDescriptionOf(radioMediumClass);
for (int i=0; i < myDialog.radioMediumBox.getItemCount(); i++) {
String menuDescription = (String) myDialog.radioMediumBox.getItemAt(i);
if (menuDescription.equals(currentDescription)) {
myDialog.radioMediumBox.setSelectedIndex(i);
break;
}
}
}
// Set position and focus of dialog
myDialog.setLocationRelativeTo(parentFrame);
myDialog.title.requestFocus();
myDialog.title.select(0, myDialog.title.getText().length());
myDialog.setVisible(true);
if (myDialog.mySimulation != null) {
// Simulation configured correctly
return true;
}
return false;
}
private CreateSimDialog(Frame frame) {
super(frame, "Create new simulation", true);
myDialog = this;
JPanel mainPane = new JPanel();
mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
JLabel label;
JTextField textField;
JPanel smallPane;
JButton button;
JComboBox comboBox;
JFormattedTextField numberField;
NumberFormat integerFormat = NumberFormat.getIntegerInstance();
// BOTTOM BUTTON PART
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonPane.add(Box.createHorizontalGlue());
button = new JButton("Cancel");
button.setActionCommand("cancel");
button.addActionListener(myEventHandler);
buttonPane.add(button);
button = new JButton("Create");
button.setActionCommand("create");
button.addActionListener(myEventHandler);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
myDialog.rootPane.setDefaultButton(button);
buttonPane.add(button);
// MAIN PART
// Title
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Simulation title");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
textField = new JTextField();
textField.setText("[no title]");
textField.setColumns(25);
title = textField;
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
smallPane.add(textField);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
// Radio Medium selection
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Radio Medium");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
Vector<String> radioMediumDescriptions = new Vector<String>();
for (Class<? extends RadioMedium> radioMediumClass: GUI.currentGUI.getRegisteredRadioMediums()) {
String description = GUI.getDescriptionOf(radioMediumClass);
radioMediumDescriptions.add(description);
}
comboBox = new JComboBox(radioMediumDescriptions);
comboBox.setSelectedIndex(0);
radioMediumBox = comboBox;
label.setLabelFor(comboBox);
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
smallPane.add(comboBox);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
// Radio Medium Logging selection
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
logCheckBox = new JCheckBox("Log all radio traffic?");
logCheckBox.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
textField = new JTextField();
textField.setText("[filename]");
textField.setColumns(25);
logFilename = textField;
smallPane.add(logCheckBox);
smallPane.add(Box.createHorizontalStrut(10));
smallPane.add(textField);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
// Delay time
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Delay time (ms)");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
numberField = new JFormattedTextField(integerFormat);
numberField.setValue(new Integer(100));
numberField.setColumns(4);
delayTime = numberField;
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(150));
smallPane.add(numberField);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
// Simulation start time
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Simulation start time (ms)");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
numberField = new JFormattedTextField(integerFormat);
numberField.setValue(new Integer(0));
numberField.setColumns(4);
simulationTime = numberField;
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(150));
smallPane.add(numberField);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
// Tick time
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Tick time (ms)");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
numberField = new JFormattedTextField(integerFormat);
numberField.setValue(new Integer(1));
numberField.setColumns(4);
tickTime = numberField;
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(150));
smallPane.add(numberField);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
mainPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
Container contentPane = getContentPane();
contentPane.add(mainPane, BorderLayout.NORTH);
contentPane.add(buttonPane, BorderLayout.SOUTH);
pack();
}
private class AddSimEventHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("cancel")) {
mySimulation = null;
dispose();
} else if (e.getActionCommand().equals("create")) {
mySimulation.setDelayTime(((Number) delayTime.getValue()).intValue());
mySimulation.setSimulationTime(((Number) simulationTime.getValue()).intValue());
mySimulation.setTickTime(((Number) tickTime.getValue()).intValue());
mySimulation.setTitle(title.getText());
String currentRadioMediumDescription = (String) radioMediumBox.getSelectedItem();
for (Class<? extends RadioMedium> radioMediumClass: GUI.currentGUI.getRegisteredRadioMediums()) {
String radioMediumDescription = GUI.getDescriptionOf(radioMediumClass);
if (currentRadioMediumDescription.equals(radioMediumDescription)) {
try {
mySimulation.setRadioMedium(radioMediumClass.newInstance());
} catch (Exception ex) {
logger.fatal("Exception when creating radio medium: " + ex);
mySimulation.setRadioMedium(null);
}
break;
}
}
if (logCheckBox.isSelected()) {
ConnectionLogger connLogger = new ConnectionLogger(new File(logFilename.getText()));
mySimulation.getRadioMedium().setConnectionLogger(connLogger);
}
dispose();
}
}
}
}

View file

@ -0,0 +1,180 @@
/*
* Copyright (c) 2006, 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: ExternalToolsDialog.java,v 1.1 2006/08/21 12:13:01 fros4943 Exp $
*/
package se.sics.cooja.dialogs;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
/**
* A dialog for viewing/editing external tools settings.
* Allows user to change paths and arguments to compilers, linkers etc.
*
* @author Fredrik Osterlind
*/
public class ExternalToolsDialog extends JDialog {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(ExternalToolsDialog.class);
private ExternalToolsEventHandler myEventHandler = new ExternalToolsEventHandler();
private final static int LABEL_WIDTH = 220;
private final static int LABEL_HEIGHT = 15;
private ExternalToolsDialog myDialog;
private JTextField textFields[];
/**
* Creates a dialog for viewing/editing external tools settings.
*
* @param parentFrame
* Parent frame for dialog
*/
public static void showDialog(Frame parentFrame) {
ExternalToolsDialog myDialog = new ExternalToolsDialog(parentFrame);
myDialog.setLocationRelativeTo(parentFrame);
if (myDialog != null) {
myDialog.setVisible(true);
}
}
private ExternalToolsDialog(Frame frame) {
super(frame, "Edit Settings", true);
myDialog = this;
JLabel label;
JPanel mainPane = new JPanel();
mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
JPanel smallPane;
JButton button;
JTextField textField;
// BOTTOM BUTTON PART
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonPane.add(Box.createHorizontalGlue());
button = new JButton("Cancel");
button.setActionCommand("cancel");
button.addActionListener(myEventHandler);
buttonPane.add(button);
button = new JButton("Reset");
button.setActionCommand("reset");
button.addActionListener(myEventHandler);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
buttonPane.add(button);
button = new JButton("OK (Saves)");
button.setActionCommand("ok");
button.addActionListener(myEventHandler);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
buttonPane.add(button);
// MAIN PART
textFields = new JTextField[GUI.getExternalToolsSettingsCount()];
for (int i = 0; i < GUI.getExternalToolsSettingsCount(); i++) {
// Add text fields for every changable property
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel(GUI.getExternalToolsSettingName(i));
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
textField = new JTextField(35);
textField.setText("");
textField.addFocusListener(myEventHandler);
textFields[i] = textField;
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
smallPane.add(textField);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
}
// Set actual used values into all text fields
updateTextFields();
mainPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
Container contentPane = getContentPane();
contentPane.add(mainPane, BorderLayout.NORTH);
contentPane.add(buttonPane, BorderLayout.SOUTH);
pack();
}
private void updateTextFields() {
for (int i = 0; i < GUI.getExternalToolsSettingsCount(); i++) {
textFields[i].setText(GUI.getExternalToolsSetting(GUI.getExternalToolsSettingName(i), ""));
}
}
private class ExternalToolsEventHandler
implements
ActionListener,
FocusListener {
public void focusGained(FocusEvent e) {
// NOP
}
public void focusLost(FocusEvent e) {
// NOP
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("reset")) {
GUI.loadExternalToolsDefaultSettings();
updateTextFields();
} else if (e.getActionCommand().equals("ok")) {
for (int i = 0; i < GUI.getExternalToolsSettingsCount(); i++) {
GUI.setExternalToolsSetting(GUI.getExternalToolsSettingName(i), textFields[i].getText()
.trim());
}
GUI.saveExternalToolsUserSettings();
myDialog.dispose();
} else if (e.getActionCommand().equals("cancel")) {
myDialog.dispose();
} else
logger.debug("Unhandled command: " + e.getActionCommand());
}
}
}

View file

@ -0,0 +1,152 @@
/*
* Copyright (c) 2006, 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: MessageList.java,v 1.1 2006/08/21 12:13:01 fros4943 Exp $
*
* -----------------------------------------------------------------
*
* Author : Adam Dunkels, Joakim Eriksson, Niclas Finne, Fredrik Osterlind
* Created : 2006-06-14
* Updated : $Date: 2006/08/21 12:13:01 $
* $Revision: 1.1 $
*/
package se.sics.cooja.dialogs;
import java.awt.Color;
import java.awt.Component;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
public class MessageList extends JList {
public static final int NORMAL = 0;
public static final int WARNING = 1;
public static final int ERROR = 2;
private Color[] foregrounds = new Color[] { null, Color.red };
private Color[] backgrounds = new Color[] { null, null };
public MessageList() {
super.setModel(new DefaultListModel());
setCellRenderer(new MessageRenderer());
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
public Color getForeground(int type) {
Color c = type > 0 && type <= foregrounds.length
? foregrounds[type - 1] : null;
return c == null ? getForeground() : c;
}
public void setForeground(int type, Color color) {
if (type > 0 && type <= foregrounds.length) {
foregrounds[type - 1] = color;
} else if (type == NORMAL) {
setForeground(color);
}
}
public Color getBackground(int type) {
Color c = type > 0 && type <= backgrounds.length
? backgrounds[type - 1] : null;
return c == null ? getBackground() : c;
}
public void setBackground(int type, Color color) {
if (type > 0 && type <= backgrounds.length) {
backgrounds[type - 1] = color;
} else if (type == NORMAL) {
setBackground(color);
}
}
public void addMessage(String message) {
addMessage(message, NORMAL);
}
public void addMessage(String message, int type) {
MessageContainer msg = new MessageContainer(message, type);
((DefaultListModel) getModel()).addElement(msg);
ensureIndexIsVisible(getModel().getSize() - 1);
}
public void clearMessages() {
((DefaultListModel) getModel()).clear();
}
public void setModel(ListModel model) {
throw new IllegalArgumentException("changing model not permitted");
}
// -------------------------------------------------------------------
// MessageContainer
// -------------------------------------------------------------------
private static class MessageContainer {
public final int type;
public final String message;
public MessageContainer(String message, int type) {
this.message = message;
this.type = type;
}
public String toString() {
return message;
}
} // end of inner class MessageContainer
// -------------------------------------------------------------------
// Renderer for messages
// -------------------------------------------------------------------
private static class MessageRenderer extends DefaultListCellRenderer {
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus)
{
super.getListCellRendererComponent(list, value, index, isSelected,
cellHasFocus);
MessageContainer msg = (MessageContainer) value;
setForeground(((MessageList) list).getForeground(msg.type));
setBackground(((MessageList) list).getBackground(msg.type));
return this;
}
} // end of inner class MessageRenderer
} // end of MessagList

View file

@ -0,0 +1,428 @@
/*
* Copyright (c) 2006, 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: UserPlatformsDialog.java,v 1.1 2006/08/21 12:13:02 fros4943 Exp $
*/
package se.sics.cooja.dialogs;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.*;
import org.apache.log4j.Logger;
import se.sics.cooja.GUI;
import se.sics.cooja.PlatformConfig;
/**
* This dialog allows a user to manage the user platforms configuration. User
* platforms can be added, removed or reordered. The resulting platform
* configuration can also be viewed.
*
* This dialog reads from the external platform configuration files in each user
* platform, as well as from any specified default configuration files.
*
* @author Fredrik Osterlind
*/
public class UserPlatformsDialog extends JDialog {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(UserPlatformsDialog.class);
private List changablePlatformsList = new List();
private List fixedPlatformsList = null;
private Vector<File> fixedUserPlatforms = null;
private Vector<File> changableUserPlatforms = null;
private UserPlatformsDialog myDialog;
private Frame myParentFrame;
/**
* Allows user to alter the given user platforms list by adding new,
* reordering or removing user platforms. Only the changable user platforms
* may be changed,
*
* @param parentFrame
* Parent frame
* @param changablePlatforms
* Changeable user platforms
* @param fixedPlatforms
* Fixed user platform
* @return Null if dialog aborted, else the new CHANGEABLE user platform list.
*/
public static Vector<File> showDialog(Frame parentFrame,
Vector<File> changablePlatforms, Vector<File> fixedPlatforms) {
UserPlatformsDialog myDialog = new UserPlatformsDialog(parentFrame,
changablePlatforms, fixedPlatforms);
myDialog.setLocationRelativeTo(parentFrame);
if (myDialog != null) {
myDialog.setVisible(true);
}
return myDialog.changableUserPlatforms;
}
private UserPlatformsDialog(Frame frame, Vector<File> changablePlatforms,
Vector<File> fixedPlatforms) {
super(frame, "Manage User Platforms", true);
myParentFrame = frame;
myDialog = this;
JPanel mainPane = new JPanel();
mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
JPanel smallPane;
JButton button;
// BOTTOM BUTTON PART
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonPane.add(Box.createHorizontalGlue());
button = new JButton("Cancel");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
changableUserPlatforms = null;
dispose();
}
});
buttonPane.add(button);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
button = new JButton("OK");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
changableUserPlatforms = new Vector<File>();
for (String directory : changablePlatformsList.getItems()) {
File userPlatform = new File(directory);
if (userPlatform.exists() && userPlatform.isDirectory())
changableUserPlatforms.add(userPlatform);
else
logger.fatal("Can't find user platform: " + userPlatform);
}
dispose();
}
});
buttonPane.add(button);
this.getRootPane().setDefaultButton(button);
// LIST PART
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.X_AXIS));
listPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JPanel listPane2 = new JPanel();
listPane2.setLayout(new BoxLayout(listPane2, BoxLayout.Y_AXIS));
if (fixedPlatforms != null) {
fixedPlatformsList = new List();
fixedPlatformsList.setEnabled(false);
listPane2.add(new JLabel("Fixed:"));
listPane2.add(fixedPlatformsList);
}
listPane2.add(new JLabel("Changable:"));
listPane2.add(changablePlatformsList);
listPane.add(listPane2);
smallPane = new JPanel();
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.Y_AXIS));
button = new JButton("Move up");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int selectedIndex = changablePlatformsList.getSelectedIndex();
if (selectedIndex <= 0)
return;
File file = new File(changablePlatformsList.getItem(selectedIndex));
removeUserPlatform(selectedIndex);
addUserPlatform(file, selectedIndex - 1);
changablePlatformsList.select(selectedIndex - 1);
}
});
smallPane.add(button);
button = new JButton("Move down");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int selectedIndex = changablePlatformsList.getSelectedIndex();
if (selectedIndex < 0)
return;
if (selectedIndex >= changablePlatformsList.getItemCount() - 1)
return;
File file = new File(changablePlatformsList.getItem(selectedIndex));
removeUserPlatform(selectedIndex);
addUserPlatform(file, selectedIndex + 1);
changablePlatformsList.select(selectedIndex + 1);
}
});
smallPane.add(button);
smallPane.add(Box.createRigidArea(new Dimension(10, 10)));
button = new JButton("Remove");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (changablePlatformsList.getSelectedIndex() < 0)
return;
removeUserPlatform(changablePlatformsList.getSelectedIndex());
}
});
smallPane.add(button);
listPane.add(smallPane);
// ADD/REMOVE PART
JPanel addRemovePane = new JPanel();
addRemovePane.setLayout(new BoxLayout(addRemovePane, BoxLayout.X_AXIS));
addRemovePane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
button = new JButton("View resulting config");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Create default configuration
PlatformConfig config = new PlatformConfig();
try {
config.appendConfig(new File(GUI.PLATFORM_DEFAULT_CONFIG_FILENAME));
} catch (FileNotFoundException ex) {
logger.fatal("Could not find default platform config file: "
+ GUI.PLATFORM_DEFAULT_CONFIG_FILENAME);
return;
} catch (IOException ex) {
logger.fatal("Error when reading default platform config file: "
+ GUI.PLATFORM_DEFAULT_CONFIG_FILENAME);
return;
}
// Add the fixed platform configurations
if (fixedPlatformsList != null) {
for (String userPlatform : fixedPlatformsList.getItems()) {
File userPlatformConfig = new File(userPlatform + File.separatorChar
+ GUI.PLATFORM_CONFIG_FILENAME);
try {
config.appendConfig(userPlatformConfig);
} catch (Exception ex) {
logger.fatal("Error when merging configurations: " + ex);
return;
}
}
}
// Add the user platform configurations
for (String userPlatform : changablePlatformsList.getItems()) {
File userPlatformConfig = new File(userPlatform + File.separatorChar
+ GUI.PLATFORM_CONFIG_FILENAME);
try {
config.appendConfig(userPlatformConfig);
} catch (Exception ex) {
logger.fatal("Error when merging configurations: " + ex);
return;
}
}
// Show merged configuration
ConfigViewer.showDialog(myParentFrame, config);
}
});
addRemovePane.add(button);
addRemovePane.add(Box.createRigidArea(new Dimension(10, 0)));
button = new JButton("Add manually");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String newUserPlatformPath = JOptionPane.showInputDialog(myDialog,
"Enter path to user platform", "Enter path",
JOptionPane.QUESTION_MESSAGE);
if (newUserPlatformPath != null) {
addUserPlatform(new File(newUserPlatformPath));
}
}
});
addRemovePane.add(button);
addRemovePane.add(Box.createRigidArea(new Dimension(10, 0)));
button = new JButton("Browse");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new java.io.File("."));
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fc.setDialogTitle("Select user platform");
if (fc.showOpenDialog(myDialog) == JFileChooser.APPROVE_OPTION) {
addUserPlatform(fc.getSelectedFile());
}
}
});
addRemovePane.add(button);
// Add components
Container contentPane = getContentPane();
mainPane.add(listPane);
mainPane.add(addRemovePane);
contentPane.add(mainPane, BorderLayout.CENTER);
contentPane.add(buttonPane, BorderLayout.SOUTH);
// Add fixed user platforms if any
if (fixedPlatforms != null) {
for (File userPlatform : fixedPlatforms) {
fixedPlatformsList.add(userPlatform.getPath());
}
}
// Add already existing user platforms
for (File userPlatform : changablePlatforms) {
addUserPlatform(userPlatform);
}
pack();
}
private void addUserPlatform(File userPlatform) {
addUserPlatform(userPlatform, changablePlatformsList.getItemCount());
}
private void addUserPlatform(File userPlatform, int index) {
// Check that file exists, is a directory and contains the correct files
if (!userPlatform.exists()) {
logger.fatal("Can't find user platform: " + userPlatform);
return;
}
if (!userPlatform.isDirectory()) {
logger.fatal("User platform is not a directory: " + userPlatform);
return;
}
File userPlatformConfigFile = new File(userPlatform.getPath()
+ File.separatorChar + GUI.PLATFORM_CONFIG_FILENAME);
if (!userPlatformConfigFile.exists()) {
logger.fatal("User platform has no configuration file: "
+ userPlatformConfigFile);
return;
}
changablePlatformsList.add(userPlatform.getPath(), index);
}
private void removeUserPlatform(int index) {
changablePlatformsList.remove(index);
}
}
/**
* Modal frame that shows all keys with their respective values of a given class
* configuration.
*
* @author Fredrik Osterlind
*/
class ConfigViewer extends JDialog {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(ConfigViewer.class);
public static void showDialog(Frame parentFrame, PlatformConfig config) {
ConfigViewer myDialog = new ConfigViewer(parentFrame, config);
myDialog.setLocationRelativeTo(parentFrame);
if (myDialog != null) {
myDialog.setVisible(true);
}
}
private ConfigViewer(Frame frame, PlatformConfig config) {
super(frame, "Current class configuration", true);
JPanel mainPane = new JPanel(new BorderLayout());
JLabel label;
JButton button;
// BOTTOM BUTTON PART
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonPane.add(Box.createHorizontalGlue());
button = new JButton("Close");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
}
});
buttonPane.add(button);
// LIST PART
JPanel keyPane = new JPanel();
keyPane.setLayout(new BoxLayout(keyPane, BoxLayout.Y_AXIS));
mainPane.add(keyPane, BorderLayout.WEST);
JPanel valuePane = new JPanel();
valuePane.setLayout(new BoxLayout(valuePane, BoxLayout.Y_AXIS));
mainPane.add(valuePane, BorderLayout.CENTER);
label = new JLabel("KEY");
label.setForeground(Color.RED);
keyPane.add(label);
label = new JLabel("VALUE");
label.setForeground(Color.RED);
valuePane.add(label);
Enumeration<String> allPropertyNames = config.getPropertyNames();
while (allPropertyNames.hasMoreElements()) {
String propertyName = allPropertyNames.nextElement();
keyPane.add(new JLabel(propertyName));
valuePane.add(new JLabel(config.getStringValue(propertyName)));
}
// Add components
Container contentPane = getContentPane();
contentPane.add(new JScrollPane(mainPane), BorderLayout.CENTER);
contentPane.add(buttonPane, BorderLayout.SOUTH);
pack();
}
}

View file

@ -0,0 +1,287 @@
/*
* Copyright (c) 2006, 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: Battery.java,v 1.1 2006/08/21 12:12:59 fros4943 Exp $
*/
package se.sics.cooja.interfaces;
import java.util.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
/**
* A Battery represents the energy source for a mote. This implementation has no
* connection with any underlying simulated software, hence a mote does not know
* the current energy levels.
* <p>
* This Battery decreases current energy left each tick depending on the current
* mote state. If the mote is sleeping all passive interfaces' energy
* consumptions will be summed up and detracted from the current energy. If the
* mote is awake both the active and passive interfaces' energy consumptions
* will be used. Also, the energy used by the CPU (depends on mote state) will
* be detracted each tick.
* <p>
* This observable is changed and notifies observers every time the energy left
* is changed. When current energy left has decreased below 0 the mote state is
* set to dead.
*
* @see MoteInterface
* @see MoteInterface#energyConsumptionPerTick()
*
* @author Fredrik Osterlind
*/
@ClassDescription("Battery")
public class Battery extends MoteInterface implements PassiveMoteInterface {
/**
* Approximate energy consumption of a mote's CPU in active mode (mA). ESB
* measured energy consumption is 1.49 mA.
*/
public final double ENERGY_CONSUMPTION_AWAKE_mA;
/**
* Approximate energy consumption of a mote's CPU in low power mode (mA). ESB
* measured energy consumption is 1.34 mA.
*/
public final double ENERGY_CONSUMPTION_LPM_mA;
/**
* Initial energy of battery in milli coulomb (mQ). ESB mote: 3 regular AA
* batteries, each ~1.25 Ah. 3 * 1.25 Ah = 3 * 1.25 * 3600 Q = 13,500 Q =
* 13,500,000 mQ
*/
public final double INITIAL_ENERGY;
private double energyConsumptionLPMPerTick = -1.0;
private double energyConsumptionAwakePerTick = -1.0;
private Mote mote = null;
private static Logger logger = Logger.getLogger(Battery.class);
private double myEnergy;
private boolean hasInfiniteEnergy;
/**
* Creates a new battery connected to given mote.
*
* @see #INITIAL_ENERGY
* @param mote
* Mote holding battery
*/
public Battery(Mote mote) {
// Read class configurations of this mote type
ENERGY_CONSUMPTION_AWAKE_mA = mote.getType().getConfig()
.getDoubleValue(Battery.class, "CPU_AWAKE_mA");
ENERGY_CONSUMPTION_LPM_mA = mote.getType().getConfig().getDoubleValue(
Battery.class, "CPU_LPM_mA");
INITIAL_ENERGY = mote.getType().getConfig().getDoubleValue(
Battery.class, "INITIAL_ENERGY_mQ");
hasInfiniteEnergy = mote.getType().getConfig().getBooleanValue(
Battery.class, "INFINITE_ENERGY_bool");
if (energyConsumptionAwakePerTick < 0) {
energyConsumptionAwakePerTick = ENERGY_CONSUMPTION_AWAKE_mA
* mote.getSimulation().getTickTimeInSeconds();
energyConsumptionLPMPerTick = ENERGY_CONSUMPTION_LPM_mA
* mote.getSimulation().getTickTimeInSeconds();
}
this.mote = mote;
myEnergy = INITIAL_ENERGY;
}
public void doActionsBeforeTick() {
// Nothing to do
}
public void doActionsAfterTick() {
// If infinite energy, do nothing
if (hasInfiniteEnergy)
return;
// If mote is dead, do nothing
if (mote.getState() == Mote.STATE_DEAD)
return;
// Check mote state
if (mote.getState() == Mote.STATE_LPM) {
// Mote is sleeping. Sum up energy usage.
double totalEnergyConsumption = 0.0;
totalEnergyConsumption += energyConsumptionLPMPerTick;
for (MoteInterface passiveInterface : mote.getInterfaces()
.getAllPassiveInterfaces()) {
totalEnergyConsumption += passiveInterface.energyConsumptionPerTick();
}
decreaseEnergy(totalEnergyConsumption);
} else {
// Mote is awake. Sum up energy usage.
double totalEnergyConsumption = 0.0;
totalEnergyConsumption += energyConsumptionAwakePerTick;
for (MoteInterface activeInterface : mote.getInterfaces()
.getAllActiveInterfaces()) {
totalEnergyConsumption += activeInterface.energyConsumptionPerTick();
}
for (MoteInterface passiveInterface : mote.getInterfaces()
.getAllPassiveInterfaces()) {
totalEnergyConsumption += passiveInterface.energyConsumptionPerTick();
}
decreaseEnergy(totalEnergyConsumption);
}
// Check if we are out of energy
if (getCurrentEnergy() <= 0.0) {
setChanged();
notifyObservers();
mote.setState(Mote.STATE_DEAD);
}
}
/**
* @param inf
* Set infinite energy state
*/
public void setInfiniteEnergy(boolean inf) {
hasInfiniteEnergy = inf;
setChanged();
notifyObservers();
}
/**
* @return True if this battery has inifinite energy
*/
public boolean hasInfiniteEnergy() {
return hasInfiniteEnergy;
}
/**
* @return Initial energy
*/
public double getInitialEnergy() {
return INITIAL_ENERGY;
}
/**
* @return Current energy left
*/
public double getCurrentEnergy() {
return myEnergy;
}
private void decreaseEnergy(double consumption) {
if (!hasInfiniteEnergy) {
myEnergy -= consumption;
setChanged();
notifyObservers();
}
}
public JPanel getInterfaceVisualizer() {
// Battery energy left
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
final JLabel energyLabel = new JLabel("");
final JLabel energyPercentLabel = new JLabel("");
if (hasInfiniteEnergy()) {
energyLabel.setText("INFINITE");
energyPercentLabel.setText("");
} else {
energyLabel.setText("Energy left (mQ) = " + getCurrentEnergy());
energyPercentLabel.setText("Energy left (%) = "
+ (getCurrentEnergy() / getInitialEnergy() * 100) + "%");
}
panel.add(energyLabel);
panel.add(energyPercentLabel);
Observer observer;
this.addObserver(observer = new Observer() {
public void update(Observable obs, Object obj) {
if (hasInfiniteEnergy()) {
energyLabel.setText("INFINITE");
energyPercentLabel.setText("");
} else {
energyLabel.setText("Energy left (mQ) = " + getCurrentEnergy());
energyPercentLabel.setText("Energy left (%) = "
+ (getCurrentEnergy() / getInitialEnergy() * 100) + "%");
}
}
});
// Saving observer reference for releaseInterfaceVisualizer
panel.putClientProperty("intf_obs", observer);
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 double energyConsumptionPerTick() {
// The battery itself does not require any power.
return 0.0;
}
public Collection<Element> getConfigXML() {
Vector<Element> config = new Vector<Element>();
Element element;
// Infinite boolean
element = new Element("infinite");
element.setText(Boolean.toString(hasInfiniteEnergy));
config.add(element);
return config;
}
public void setConfigXML(Collection<Element> configXML) {
for (Element element : configXML) {
if (element.getName().equals("infinite")) {
hasInfiniteEnergy = Boolean.parseBoolean(element.getText());
}
}
}
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2006, 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: Beeper.java,v 1.1 2006/08/21 12:12:58 fros4943 Exp $
*/
package se.sics.cooja.interfaces;
import se.sics.cooja.*;
/**
* A Beeper represents a mote beeper. An implementation should notify all
* observers when the beeper changes state and typically requires more energy if
* beeping than when quiet.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Beeper")
public abstract class Beeper extends MoteInterface {
/**
* @return True if beeper is beeping
*/
public abstract boolean isBeeping();
}

View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2006, 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: Button.java,v 1.1 2006/08/21 12:12:58 fros4943 Exp $
*/
package se.sics.cooja.interfaces;
import se.sics.cooja.*;
/**
* A Button represents a mote button. An implementation should notify all
* observers when the button changes state, and may simulate external interrupts
* by waking up a mote if button state changes.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Button")
public abstract class Button extends MoteInterface {
/**
* Clicks button. Button will be pressed for some time and then automatically
* released.
*/
public abstract void clickButton();
/**
* Releases button (if pressed).
*/
public abstract void releaseButton();
/**
* Presses button (if not already pressed).
*/
public abstract void pressButton();
/**
* @return True if button is pressed
*/
public abstract boolean isPressed();
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2006, 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: Clock.java,v 1.1 2006/08/21 12:12:59 fros4943 Exp $
*/
package se.sics.cooja.interfaces;
import se.sics.cooja.*;
/**
* A Clock represents a mote's internal clock. Notice that the overall
* simulation time and the mote's own time may differ.
*
* This observable never needs to update.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Clock")
public abstract class Clock extends MoteInterface {
/**
* Set mote's time to given time.
*
* @param newTime
* New time
*/
public abstract void setTime(int newTime);
/**
* @return Current time
*/
public abstract int getTime();
}

View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2006, 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: IPAddress.java,v 1.1 2006/08/21 12:12:59 fros4943 Exp $
*/
package se.sics.cooja.interfaces;
import se.sics.cooja.*;
/**
* A IPAdress represents a mote Internet address. An implementation should notify all
* observers if the address is set or changed.
*
* @author Fredrik Osterlind
*/
@ClassDescription("IPv4 Address")
public abstract class IPAddress extends MoteInterface {
/**
* Get current IP address on the form a.b.c.d.
* @return IP address string
*/
public abstract String getIPString();
/**
* Change/Set IP address.
* @param ipAddress IP string on the form a.b.c.d
*/
public abstract void setIPString(String ipAddress);
/**
* Change/Set IP address.
* @param a First byte of IP address
* @param b Second byte of IP address
* @param c Third byte of IP address
* @param d Fourth byte of IP address
*/
public abstract void setIPNumber(char a, char b, char c, char d);
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2006, 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: LED.java,v 1.1 2006/08/21 12:12:59 fros4943 Exp $
*/
package se.sics.cooja.interfaces;
import se.sics.cooja.*;
/**
* A LED represents three mote LEDs (green, yellow and red). An implementation should notify all
* observers if any of the LEDs states are changed.
*
* @author Fredrik Osterlind
*/
@ClassDescription("LEDs")
public abstract class LED extends MoteInterface {
/**
* @return True if any LED is on, false otherwise
*/
public abstract boolean isAnyOn();
/**
* @return True if green LED is on, false otherwise
*/
public abstract boolean isGreenOn();
/**
* @return True if yellow LED is on, false otherwise
*/
public abstract boolean isYellowOn();
/**
* @return True if red LED is on, false otherwise
*/
public abstract boolean isRedOn();
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2006, 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: Log.java,v 1.1 2006/08/21 12:12:59 fros4943 Exp $
*/
package se.sics.cooja.interfaces;
import se.sics.cooja.*;
/**
* A Log represents a mote logging output. An implementation should notify all
* observers whenever new logging output is available.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Log Output")
public abstract class Log extends MoteInterface {
/**
* @return Last log messages available
*/
public abstract String getLastLogMessages();
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2006, 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: MoteID.java,v 1.1 2006/08/21 12:12:58 fros4943 Exp $
*/
package se.sics.cooja.interfaces;
import se.sics.cooja.*;
/**
* A MoteID represents a mote ID number. An implementation should notify all
* observers if the mote ID is set or changed.
*
* @author Fredrik Osterlind
*/
@ClassDescription("ID")
public abstract class MoteID extends MoteInterface {
/**
* @return Current mote ID number
*/
public abstract int getMoteID();
/**
* Sets mote ID to given number.
* @param newID New mote ID number
*/
public abstract void setMoteID(int newID);
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2006, 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: PIR.java,v 1.1 2006/08/21 12:12:59 fros4943 Exp $
*/
package se.sics.cooja.interfaces;
import se.sics.cooja.*;
/**
* A PIR represents a passive infrared sensor. An implementation should notify all
* observers if the PIR discovers any changes.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Passive IR")
public abstract class PIR extends MoteInterface {
/**
* Simulates a change in the PIR sensor.
*/
public abstract void triggerChange();
}

View file

@ -0,0 +1,234 @@
/*
* Copyright (c) 2006, 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: Position.java,v 1.1 2006/08/21 12:12:59 fros4943 Exp $
*/
package se.sics.cooja.interfaces;
import java.text.NumberFormat;
import java.util.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
/**
* A Position represents the simulated 3D position of a mote. This
* implementation has no connection with any underlying simulated software,
* hence a mote does not know its current position.
* <p>
* This observable is changed and notifies observers whenever new coordinates
* are set.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Position")
public class Position extends MoteInterface {
private static Logger logger = Logger.getLogger(Position.class);
private Mote mote = null;
private double[] coords = new double[3];
/**
* Creates a position for given mote with coordinates (x=0, y=0, z=0).
*
* @param mote
* Led's mote.
* @see Mote
* @see se.sics.cooja.MoteInterfaceHandler
*/
public Position(Mote mote) {
this.mote = mote;
coords[0] = 0.0f;
coords[1] = 0.0f;
coords[2] = 0.0f;
}
/**
* Updates coordiantes of associated mote to (x,y,z).
*
* @param x
* New X coordinate
* @param y
* New Y coordinate
* @param z
* New Z coordinate
*/
public void setCoordinates(double x, double y, double z) {
coords[0] = x;
coords[1] = y;
coords[2] = z;
this.setChanged();
this.notifyObservers(mote);
}
/**
* @return X coordinate
*/
public double getXCoordinate() {
return coords[0];
}
/**
* @return Y coordinate
*/
public double getYCoordinate() {
return coords[1];
}
/**
* @return Z coordinate
*/
public double getZCoordinate() {
return coords[2];
}
/**
* Calculates distance from this position to given position.
*
* @param pos
* Compared position
* @return Distance
*/
public double getDistanceTo(Position pos) {
return Math.sqrt(Math.abs(coords[0] - pos.getXCoordinate())
* Math.abs(coords[0] - pos.getXCoordinate())
+ Math.abs(coords[1] - pos.getYCoordinate())
* Math.abs(coords[1] - pos.getYCoordinate())
+ Math.abs(coords[2] - pos.getZCoordinate())
* Math.abs(coords[2] - pos.getZCoordinate()));
}
/**
* Calculates distance from associated mote to another mote.
*
* @param m
* Another mote
* @return Distance
*/
public double getDistanceTo(Mote m) {
return getDistanceTo(m.getInterfaces().getPosition());
}
public void doActionsBeforeTick() {
// Nothing to do
}
public void doActionsAfterTick() {
// Nothing to do
}
public JPanel getInterfaceVisualizer() {
// Location
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
final NumberFormat form = NumberFormat.getNumberInstance();
final JLabel positionLabel = new JLabel();
positionLabel.setText("(" + form.format(getXCoordinate()) + ","
+ form.format(getYCoordinate()) + "," + form.format(getZCoordinate())
+ ")");
panel.add(positionLabel);
Observer observer;
this.addObserver(observer = new Observer() {
public void update(Observable obs, Object obj) {
positionLabel.setText("(" + form.format(getXCoordinate()) + ","
+ form.format(getYCoordinate()) + ","
+ form.format(getZCoordinate()) + ")");
}
});
// Saving observer reference for releaseInterfaceVisualizer
panel.putClientProperty("intf_obs", observer);
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 double energyConsumptionPerTick() {
return 0.0;
}
public Collection<Element> getConfigXML() {
Vector<Element> config = new Vector<Element>();
Element element;
// X coordinate
element = new Element("x");
element.setText(Double.toString(getXCoordinate()));
config.add(element);
// Y coordinate
element = new Element("y");
element.setText(Double.toString(getYCoordinate()));
config.add(element);
// Z coordinate
element = new Element("z");
element.setText(Double.toString(getZCoordinate()));
config.add(element);
return config;
}
public void setConfigXML(Collection<Element> configXML) {
double x = 0, y = 0, z = 0;
for (Element element : configXML) {
if (element.getName().equals("x")) {
x = Double.parseDouble(element.getText());
}
if (element.getName().equals("y")) {
y = Double.parseDouble(element.getText());
}
if (element.getName().equals("z")) {
z = Double.parseDouble(element.getText());
}
}
setCoordinates(x, y, z);
}
}

View file

@ -0,0 +1,133 @@
/*
* Copyright (c) 2006, 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: Radio.java,v 1.1 2006/08/21 12:12:59 fros4943 Exp $
*/
package se.sics.cooja.interfaces;
import se.sics.cooja.*;
/**
* A Radio represents a mote radio transceiver. An implementation should notify
* all observers both when packets are received and transmitted. The static
* constants should be used for describing the radio status when the observers
* are notified.
*
* @see #SENT_NOTHING
* @see #SENT_SOMETHING
* @see #HEARS_NOTHING
* @see #HEARS_PACKET
* @see #HEARS_NOISE
* @author Fredrik Osterlind
*/
@ClassDescription("Packet Radio")
public abstract class Radio extends MoteInterface {
/**
* This radio has not sent anything last tick.
*/
public static final int SENT_NOTHING = 1;
/**
* This radio has sent something last tick.
*/
public static final int SENT_SOMETHING = 2;
/**
* This radio is not hearing anything.
*/
public static final int HEARS_NOTHING = 1;
/**
* This radio is hearing exactly one packet right now.
*/
public static final int HEARS_PACKET = 2;
/**
* This radio is hearing a lot of noise right now (may be several packets).
*/
public static final int HEARS_NOISE = 3;
/**
* @return Last packet data sent from this radio.
*/
public abstract byte[] getLastPacketSent();
/**
* @return Last packet data received by this radio.
*/
public abstract byte[] getLastPacketReceived();
/**
* Send given packet data to this radio. The radio may or may not receive the
* data correctly depending on the current listen state.
*
* @param data
*/
public abstract void receivePacket(byte[] data);
/**
* @return Current send state
* @see #SENT_NOTHING
* @see #SENT_SOMETHING
*/
public abstract int getSendState();
/**
* @return Current listen state
*
* @see #setListenState(int)
* @see #HEARS_NOTHING
* @see #HEARS_PACKET
* @see #HEARS_NOISE
*/
public abstract int getListenState();
/**
* Changes listen state to given state
* @param newState
* New listen state
*
* @see #getListenState()
* @see #HEARS_NOTHING
* @see #HEARS_PACKET
* @see #HEARS_NOISE
*/
public abstract void setListenState(int newState);
/**
* Advances listen state one step. If listen state was 'hears nothing', it
* will become 'hears packet'. If it was 'hears packet', it will become 'hears
* noise'. If it was 'hears noise', it will stay that way.
*
* @see #getListenState()
*/
public abstract void advanceListenState();
}

View file

@ -0,0 +1,77 @@
/*
* Copyright (c) 2006, 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: IdIPDistributor.java,v 1.1 2006/08/21 12:13:06 fros4943 Exp $
*/
package se.sics.cooja.ipdistributors;
import java.util.Vector;
import se.sics.cooja.*;
/**
* Generates IP addresses on the form 10.[id/256 mod 256*256].[id mod 256].1.
*
* Observe!
* - ID must be set before this is called (otherwise IP=0.0.0.0).
* - Only supports 256*256 motes, (IPs will wrap if above).
*
* @author Fredrik Osterlind
*/
@ClassDescription("From ID (10.id.id.1)")
public class IdIPDistributor extends IPDistributor {
private Vector<String> generatedIPAddresses;
/**
* Creates a Id IP distributor.
* @param newMotes All motes which later will be assigned IP numbers.
*/
public IdIPDistributor(Vector<Mote> newMotes) {
generatedIPAddresses = new Vector<String>();
for (int i=0; i < newMotes.size(); i++) {
if (newMotes.get(i).getInterfaces().getMoteID() != null) {
int moteId = newMotes.get(i).getInterfaces().getMoteID().getMoteID();
generatedIPAddresses.add("10." +
(moteId / 256 % (256*256))
+ "." +
(moteId % 256)
+ ".1");
} else
generatedIPAddresses.add("0.0.0.0");
}
}
public String getNextIPAddress() {
if (generatedIPAddresses.size() > 0)
return generatedIPAddresses.remove(0);
else
return "0.0.0.0";
}
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2006, 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: RandomIPDistributor.java,v 1.1 2006/08/21 12:13:06 fros4943 Exp $
*/
package se.sics.cooja.ipdistributors;
import java.util.Vector;
import se.sics.cooja.*;
/**
* Generates IP addresses randomly on the form 10.10.[1-20].[1-20].
* Nothing prevents several motes from getting the same IP number.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Random (10.10.?.?)")
public class RandomIPDistributor extends IPDistributor {
/**
* Creates a random IP distributor.
* @param newMotes All motes which later will be assigned IP numbers.
*/
public RandomIPDistributor(Vector<Mote> newMotes) {
// NOP
}
public String getNextIPAddress() {
return "" + 10 + "." + 10 + "." + (Math.round(Math.random()*20) + 1) + "." + (Math.round(Math.random()*20) + 1);
}
}

View file

@ -0,0 +1,106 @@
/*
* Copyright (c) 2006, 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: SpatialIPDistributor.java,v 1.1 2006/08/21 12:13:07 fros4943 Exp $
*/
package se.sics.cooja.ipdistributors;
import java.util.Vector;
import se.sics.cooja.*;
/**
* Generates spatial IP addresses on the form 10.[z-coord].[y-coord].[x-coord].
* The smallest coordinate in each interval will be mapped onto address 1,
* and the biggest coordinate onto address 200.
* Nothing prevents several motes from getting the same IP number.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Spatial (10.x.y.z)")
public class SpatialIPDistributor extends IPDistributor {
private double lowestX, biggestX, lowestY, biggestY, lowestZ, biggestZ;
private Vector<String> generatedIPAddresses;
/**
* Creates a random IP distributor.
* @param newMotes All motes which later will be assigned IP numbers.
*/
public SpatialIPDistributor(Vector<Mote> newMotes) {
lowestX = newMotes.get(0).getInterfaces().getPosition().getXCoordinate();
biggestX = newMotes.get(0).getInterfaces().getPosition().getXCoordinate();
lowestY = newMotes.get(0).getInterfaces().getPosition().getYCoordinate();
biggestY = newMotes.get(0).getInterfaces().getPosition().getYCoordinate();
lowestZ = newMotes.get(0).getInterfaces().getPosition().getZCoordinate();
biggestZ = newMotes.get(0).getInterfaces().getPosition().getZCoordinate();
for (int i=0; i < newMotes.size(); i++) {
if (newMotes.get(i).getInterfaces().getPosition().getXCoordinate() < lowestX)
lowestX = newMotes.get(i).getInterfaces().getPosition().getXCoordinate();
if (newMotes.get(i).getInterfaces().getPosition().getXCoordinate() > biggestX)
biggestX = newMotes.get(i).getInterfaces().getPosition().getXCoordinate();
if (newMotes.get(i).getInterfaces().getPosition().getYCoordinate() < lowestY)
lowestY = newMotes.get(i).getInterfaces().getPosition().getYCoordinate();
if (newMotes.get(i).getInterfaces().getPosition().getYCoordinate() > biggestY)
biggestY = newMotes.get(i).getInterfaces().getPosition().getYCoordinate();
if (newMotes.get(i).getInterfaces().getPosition().getZCoordinate() < lowestZ)
lowestZ = newMotes.get(i).getInterfaces().getPosition().getZCoordinate();
if (newMotes.get(i).getInterfaces().getPosition().getZCoordinate() > biggestZ)
biggestZ = newMotes.get(i).getInterfaces().getPosition().getZCoordinate();
}
generatedIPAddresses = new Vector<String>();
for (int i=0; i < newMotes.size(); i++) {
String ipAddress = "10.";
int partIP;
// Z coord
partIP = (int) (1 + 199*(newMotes.get(i).getInterfaces().getPosition().getZCoordinate() - lowestZ) / (biggestZ - lowestZ));
ipAddress = ipAddress.concat(partIP + ".");
// Y coord
partIP = (int) (1 + 199*(newMotes.get(i).getInterfaces().getPosition().getYCoordinate() - lowestY) / (biggestY - lowestY));
ipAddress = ipAddress.concat(partIP + ".");
// X coord
partIP = (int) (1 + 199*(newMotes.get(i).getInterfaces().getPosition().getXCoordinate() - lowestX) / (biggestX - lowestX));
ipAddress = ipAddress.concat(partIP + "");
generatedIPAddresses.add(ipAddress);
}
}
public String getNextIPAddress() {
if (generatedIPAddresses.size() > 0)
return generatedIPAddresses.remove(0);
else
return "0.0.0.0";
}
}

View file

@ -0,0 +1,222 @@
/*
* Copyright (c) 2006, 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: DummyMote.java,v 1.1 2006/08/21 12:13:12 fros4943 Exp $
*/
package se.sics.cooja.motes;
import java.util.Collection;
import java.util.Observer;
import java.util.Properties;
import java.util.Random;
import java.util.Vector;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.Position;
/**
* A dummy mote is a purely Java-based mote, and can be used as an example of
* how to implement motes other than the usual Contiki mote.
*
* The dummy mote uses an empty section mote memory without any variable
* mappings.
*
* The mote interface handler has a position interface, added when the mote is
* constructed.
*
* When the dummy mote is ticked all (one!) interfaces are polled and a random
* variable decides if the position should be changed. The node never leaves the
* active state.
*
* @author Fredrik Osterlind
*/
public class DummyMote implements Mote {
private static Logger logger = Logger.getLogger(DummyMote.class);
private MoteType myType = null;
private SectionMoteMemory myMemory = null;
private MoteInterfaceHandler myInterfaceHandler = null;
private Simulation mySim = null;
private Random myRandom = new Random();
/**
* Creates a new uninitialized dummy mote.
*/
public DummyMote() {
}
/**
* Creates a new dummy mote of the given type in the given simulation. An
* empty mote memory and a position interface is added to this mote.
*
* @param moteType
* Mote type
* @param sim
* Simulation
*/
public DummyMote(MoteType moteType, Simulation sim) {
mySim = sim;
myType = moteType;
// Create memory
myMemory = new SectionMoteMemory(new Properties());
// Create interface handler
myInterfaceHandler = new MoteInterfaceHandler();
Position myPosition = new Position(this);
myPosition.setCoordinates(myRandom.nextDouble() * 100, myRandom
.nextDouble() * 100, myRandom.nextDouble() * 100);
myInterfaceHandler.addPassiveInterface(myPosition);
}
public void setState(int newState) {
logger.fatal("Dummy mote can not change state");
}
public int getState() {
return Mote.STATE_ACTIVE;
}
public void addStateObserver(Observer newObserver) {
}
public void deleteStateObserver(Observer newObserver) {
}
public MoteInterfaceHandler getInterfaces() {
return myInterfaceHandler;
}
public void setInterfaces(MoteInterfaceHandler moteInterfaceHandler) {
myInterfaceHandler = moteInterfaceHandler;
}
public MoteMemory getMemory() {
return myMemory;
}
public void setMemory(MoteMemory memory) {
myMemory = (SectionMoteMemory) memory;
}
public MoteType getType() {
return myType;
}
public void setType(MoteType type) {
myType = type;
}
public Simulation getSimulation() {
return mySim;
}
public void setSimulation(Simulation simulation) {
this.mySim = simulation;
}
public void tick(int simTime) {
// Perform some dummy task
if (myRandom.nextDouble() > 0.9) {
// Move mote randomly
Position myPosition = myInterfaceHandler.getPosition();
myPosition.setCoordinates(myPosition.getXCoordinate()
+ myRandom.nextDouble() - 0.5, myPosition.getYCoordinate()
+ myRandom.nextDouble() - 0.5, myPosition.getZCoordinate()
+ myRandom.nextDouble() - 0.5);
}
}
public Collection<Element> getConfigXML() {
Vector<Element> config = new Vector<Element>();
Element element;
// We need to save the mote type identifier
element = new Element("motetype_identifier");
element.setText(getType().getIdentifier());
config.add(element);
// The position interface should also save its config
element = new Element("interface_config");
element.setText(myInterfaceHandler.getPosition().getClass().getName());
Collection interfaceXML = myInterfaceHandler.getPosition().getConfigXML();
if (interfaceXML != null) {
element.addContent(interfaceXML);
config.add(element);
}
return config;
}
public boolean setConfigXML(Simulation simulation,
Collection<Element> configXML) {
mySim = simulation;
myMemory = new SectionMoteMemory(new Properties());
myInterfaceHandler = new MoteInterfaceHandler();
myInterfaceHandler.addPassiveInterface(new Position(this));
for (Element element : configXML) {
String name = element.getName();
if (name.equals("motetype_identifier")) {
myType = simulation.getMoteType(element.getText());
} else if (name.equals("interface_config")) {
Class<? extends MoteInterface> moteInterfaceClass = GUI.currentGUI
.tryLoadClass(this, MoteInterface.class, element.getText().trim());
if (moteInterfaceClass == null) {
logger.warn("Can't find mote interface class: " + element.getText());
return false;
}
MoteInterface moteInterface = myInterfaceHandler
.getInterfaceOfType(moteInterfaceClass);
moteInterface.setConfigXML(element.getChildren());
}
}
return true;
}
public String toString() {
if (getInterfaces().getMoteID() != null) {
return "Dummy Mote, ID=" + getInterfaces().getMoteID().getMoteID();
} else
return "Dummy Mote, ID=null";
}
}

View file

@ -0,0 +1,158 @@
/*
* Copyright (c) 2006, 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: DummyMoteType.java,v 1.1 2006/08/21 12:13:12 fros4943 Exp $
*/
package se.sics.cooja.motes;
import java.util.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.jdom.Element;
import se.sics.cooja.*;
@ClassDescription("Dummy Mote Type")
public class DummyMoteType implements MoteType {
private static Logger logger = Logger.getLogger(DummyMoteType.class);
// Mote type specific data
private String identifier = null;
private String description = null;
public DummyMoteType() {
}
public DummyMoteType(String identifier) {
this.identifier = identifier;
description = "Dummy Mote Type #" + identifier;
}
public Mote generateMote(Simulation simulation) {
return new DummyMote(this, simulation);
}
public boolean configureAndInit(JFrame parentFrame, Simulation simulation) {
if (identifier == null) {
// Create unique identifier
int counter = 0;
boolean identifierOK = false;
while (!identifierOK) {
counter++;
identifier = "dummy" + counter;
identifierOK = true;
// Check if identifier is already used by some other type
for (MoteType existingMoteType : simulation.getMoteTypes()) {
if (existingMoteType != this
&& existingMoteType.getIdentifier().equals(identifier)) {
identifierOK = false;
break;
}
}
}
if (description == null) {
// Create description
description = "Dummy Mote Type #" + counter;
}
}
if (description == null) {
// Create description
description = "Dummy Mote Type #" + identifier;
}
return true;
}
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;
}
public JPanel getTypeVisualizer() {
return null;
}
public PlatformConfig getConfig() {
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);
return config;
}
public boolean setConfigXML(Simulation simulation, Collection<Element> configXML) {
for (Element element : configXML) {
String name = element.getName();
if (name.equals("identifier")) {
identifier = element.getText();
} else if (name.equals("description")) {
description = element.getText();
} else {
logger.fatal("Unrecognized entry in loaded configuration: " + name);
}
}
boolean createdOK = configureAndInit(GUI.frame, simulation);
return createdOK;
}
}

View file

@ -0,0 +1,122 @@
/*
* Copyright (c) 2006, 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: LogListener.java,v 1.1 2006/08/21 12:13:08 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.Insets;
import java.util.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.Log;
/**
* A simple mote log listener.
* When instantiated, is registers as a listener on all currently existing
* motes' log interfaces. (Observe that if new motes are added to a simulation,
* a new log listener must be created to listen to those motes also).
*
* @author Fredrik Osterlind
*/
@ClassDescription("Log Listener")
@VisPluginType(VisPluginType.SIM_PLUGIN)
public class LogListener extends VisPlugin {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(LogListener.class);
private JTextArea logTextArea;
private Observer logObserver;
private Simulation simulation;
/**
* Create a new simulation control panel.
*
* @param simulationToControl Simulation to control
*/
public LogListener(final Simulation simulationToControl) {
super("Log Listener - Listening on ?? mote logs");
simulation = simulationToControl;
int nrLogs = 0;
// Log observer
logObserver = new Observer() {
public void update(Observable obs, Object obj) {
logTextArea.append("\n");
Mote mote = (Mote) obj;
Log moteLogInterface = (Log) obs;
String outputString = "TIME:" + simulation.getSimulationTime() + "\t";
if (mote != null && mote.getInterfaces().getMoteID() != null) {
outputString = outputString.concat("ID:" + mote.getInterfaces().getMoteID().getMoteID() + "\t");
}
outputString = outputString.concat(moteLogInterface.getLastLogMessages());
logTextArea.append(outputString);
logTextArea.setCaretPosition(logTextArea.getDocument().getLength());
}
};
// Register as loglistener on all currently active motes
for (int i=0; i < simulation.getMotesCount(); i++) {
if (simulation.getMote(i).getInterfaces().getLog() != null) {
simulation.getMote(i).getInterfaces().getLog().addObserver(logObserver);
nrLogs++;
}
}
// Main panel
logTextArea = new JTextArea(8,50);
logTextArea.setMargin(new Insets(5,5,5,5));
logTextArea.setEditable(false);
logTextArea.setCursor(null);
setContentPane(new JScrollPane(logTextArea));
setTitle("Log Listener - Listening on " + nrLogs + " mote logs");
pack();
try {
setSelected(true);
} catch (java.beans.PropertyVetoException e) {
// Could not select
}
}
public void closePlugin() {
// Remove log observer from all log interfaces
for (int i=0; i < simulation.getMotesCount(); i++) {
if (simulation.getMote(i).getInterfaces().getLog() != null)
simulation.getMote(i).getInterfaces().getLog().deleteObserver(logObserver);
}
}
}

View file

@ -0,0 +1,234 @@
/*
* Copyright (c) 2006, 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: MoteInformation.java,v 1.1 2006/08/21 12:13:07 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
/**
* MoteInformation is a simple information window for motes.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Mote Information")
@VisPluginType(VisPluginType.MOTE_PLUGIN)
public class MoteInformation extends VisPlugin {
private static Logger logger = Logger.getLogger(MoteInformation.class);
private static final long serialVersionUID = 1L;
private Mote mote;
private final static int LABEL_WIDTH = 170;
private final static int LABEL_HEIGHT = 15;
private final JLabel stateLabel;
private Observer stateObserver;
private Vector<JPanel> visibleMoteInterfaces = new Vector<JPanel>();
/**
* Create a new mote information window.
*
* @param moteToView Mote to view
*/
public MoteInformation(Mote moteToView) {
super("Mote Information (" + moteToView + ")");
mote = moteToView;
JLabel label;
JPanel mainPane = new JPanel();
mainPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
JPanel smallPane;
// Remove mote button
smallPane = new JPanel(new BorderLayout());
label = new JLabel("Remove mote");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
smallPane.add(BorderLayout.WEST, label);
JButton button = new JButton("Remove");
button.setActionCommand("removeMote");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
GUI.currentSimulation.removeMote(mote);
dispose();
}
});
smallPane.add(BorderLayout.EAST, button);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,25)));
// Visualize mote type
smallPane = new JPanel(new BorderLayout());
label = new JLabel("-- STATE --");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
smallPane.add(BorderLayout.WEST, label);
if (mote.getState() == Mote.STATE_ACTIVE)
label = new JLabel("active");
else if (mote.getState() == Mote.STATE_LPM)
label = new JLabel("low power mode");
else
label = new JLabel("dead");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
stateLabel = label;
smallPane.add(BorderLayout.EAST, label);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,25)));
// Visualize mote type
smallPane = new JPanel(new BorderLayout());
label = new JLabel("-- MOTE TYPE --");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
smallPane.add(BorderLayout.NORTH, label);
JPanel moteVis = mote.getType().getTypeVisualizer();
if (moteVis != null) {
moteVis.setBorder(BorderFactory.createEtchedBorder());
smallPane.add(moteVis);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,25)));
}
// All interfaces
smallPane = new JPanel(new BorderLayout());
label = new JLabel("-- INTERFACES --");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
smallPane.add(BorderLayout.NORTH, label);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,10)));
for (int i=0; i < mote.getInterfaces().getAllActiveInterfaces().size(); i++) {
smallPane = new JPanel();
smallPane.setLayout(new BorderLayout());
MoteInterface moteInterface = mote.getInterfaces().getAllActiveInterfaces().get(i);
String interfaceDescription = GUI.getDescriptionOf(moteInterface);
JPanel interfaceVisualizer = moteInterface.getInterfaceVisualizer();
label = new JLabel(interfaceDescription);
label.setAlignmentX(JLabel.CENTER_ALIGNMENT);
smallPane.add(BorderLayout.NORTH, label);
if (interfaceVisualizer != null) {
interfaceVisualizer.setBorder(BorderFactory.createEtchedBorder());
smallPane.add(BorderLayout.CENTER, interfaceVisualizer);
// Tag each visualized interface to easier release them later
interfaceVisualizer.putClientProperty("my_interface", moteInterface);
visibleMoteInterfaces.add(interfaceVisualizer);
}
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
}
for (int i=0; i < mote.getInterfaces().getAllPassiveInterfaces().size(); i++) {
smallPane = new JPanel();
smallPane.setLayout(new BorderLayout());
MoteInterface moteInterface = mote.getInterfaces().getAllPassiveInterfaces().get(i);
String interfaceDescription = GUI.getDescriptionOf(moteInterface);
JPanel interfaceVisualizer = moteInterface.getInterfaceVisualizer();
label = new JLabel(interfaceDescription);
label.setAlignmentX(JLabel.CENTER_ALIGNMENT);
smallPane.add(BorderLayout.NORTH, label);
if (interfaceVisualizer != null) {
interfaceVisualizer.setBorder(BorderFactory.createEtchedBorder());
smallPane.add(BorderLayout.CENTER, interfaceVisualizer);
// Tag each visualized interface to easier release them later
interfaceVisualizer.putClientProperty("my_interface", moteInterface);
visibleMoteInterfaces.add(interfaceVisualizer);
}
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
}
this.setContentPane(new JScrollPane(mainPane,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
pack();
setPreferredSize(new Dimension(350,500));
setSize(new Dimension(350,500));
try {
setSelected(true);
} catch (java.beans.PropertyVetoException e) {
// Could not select
}
// Register as state observer to detect if mote changes state
mote.addStateObserver(stateObserver = new Observer() {
public void update(Observable obs, Object obj) {
if (mote.getState() == Mote.STATE_ACTIVE)
stateLabel.setText("active");
else if (mote.getState() == Mote.STATE_LPM)
stateLabel.setText("low power mode");
else
stateLabel.setText("dead");
}
});
}
public void closePlugin() {
// Remove state observer
mote.deleteStateObserver(stateObserver);
// Release all interface visualizations
for (JPanel interfaceVisualization: visibleMoteInterfaces) {
MoteInterface moteInterface = (MoteInterface) interfaceVisualization.getClientProperty("my_interface");
if (moteInterface != null && interfaceVisualization != null)
moteInterface.releaseInterfaceVisualizer(interfaceVisualization);
else
logger.warn("Could not release panel");
}
}
}

View file

@ -0,0 +1,152 @@
/*
* Copyright (c) 2006, 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: MoteInterfaceViewer.java,v 1.1 2006/08/21 12:13:09 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import se.sics.cooja.*;
/**
* MoteInterfaceViewer allows a user to select and view information about a node's interfaces.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Mote Interface Viewer")
@VisPluginType(VisPluginType.MOTE_PLUGIN)
public class MoteInterfaceViewer extends VisPlugin {
private static final long serialVersionUID = 1L;
private Mote mote;
private MoteInterface selectedMoteInterface = null;
private JPanel currentInterfaceVisualizer = null;
/**
* Create a new mote interface viewer.
*
* @param moteToView Mote to view
*/
public MoteInterfaceViewer(Mote moteToView) {
super("Mote Interface Viewer (" + moteToView + ")");
mote = moteToView;
JLabel label;
JPanel mainPane = new JPanel();
mainPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
mainPane.setLayout(new BorderLayout());
JPanel smallPane;
// Select interface combo box
smallPane = new JPanel(new BorderLayout());
label = new JLabel("Select interface:");
final JComboBox selectInterfaceComboBox = new JComboBox();
final JPanel interfacePanel = new JPanel();
for (int i=0; i < mote.getInterfaces().getAllActiveInterfaces().size(); i++) {
selectInterfaceComboBox.addItem(GUI.getDescriptionOf(mote.getInterfaces().getAllActiveInterfaces().get(i)));
}
for (int i=0; i < mote.getInterfaces().getAllPassiveInterfaces().size(); i++) {
selectInterfaceComboBox.addItem(GUI.getDescriptionOf(mote.getInterfaces().getAllPassiveInterfaces().get(i)));
}
selectInterfaceComboBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Release old interface visualizer if any
if (selectedMoteInterface != null && currentInterfaceVisualizer != null)
selectedMoteInterface.releaseInterfaceVisualizer(currentInterfaceVisualizer);
// View selected interface if any
interfacePanel.removeAll();
String interfaceDescription = (String) selectInterfaceComboBox.getSelectedItem();
selectedMoteInterface = null;
for (int i=0; i < mote.getInterfaces().getAllActiveInterfaces().size(); i++) {
if (GUI.getDescriptionOf(mote.getInterfaces().getAllActiveInterfaces().get(i)).equals(interfaceDescription))
selectedMoteInterface = mote.getInterfaces().getAllActiveInterfaces().get(i);
}
for (int i=0; i < mote.getInterfaces().getAllPassiveInterfaces().size(); i++) {
if (GUI.getDescriptionOf(mote.getInterfaces().getAllPassiveInterfaces().get(i)).equals(interfaceDescription))
selectedMoteInterface = mote.getInterfaces().getAllPassiveInterfaces().get(i);
}
currentInterfaceVisualizer = selectedMoteInterface.getInterfaceVisualizer();
if (currentInterfaceVisualizer != null) {
currentInterfaceVisualizer.setBorder(BorderFactory.createEtchedBorder());
interfacePanel.add(BorderLayout.CENTER, currentInterfaceVisualizer);
currentInterfaceVisualizer.setVisible(true);
} else {
interfacePanel.add(new JLabel("No interface visualizer exists!"));
currentInterfaceVisualizer = null;
}
setSize(getSize());
}
});
selectInterfaceComboBox.setSelectedIndex(0);
smallPane.add(BorderLayout.WEST, label);
smallPane.add(BorderLayout.EAST, selectInterfaceComboBox);
mainPane.add(BorderLayout.NORTH, smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,10)));
// Add selected interface
interfacePanel.setLayout(new BorderLayout());
if (selectInterfaceComboBox.getItemCount() > 0) {
selectInterfaceComboBox.setSelectedIndex(0);
selectInterfaceComboBox.dispatchEvent(new ActionEvent(selectInterfaceComboBox, ActionEvent.ACTION_PERFORMED, ""));
}
mainPane.add(BorderLayout.CENTER, interfacePanel);
this.setContentPane(new JScrollPane(mainPane,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
pack();
setPreferredSize(new Dimension(350,300));
setSize(new Dimension(350,300));
try {
setSelected(true);
} catch (java.beans.PropertyVetoException e) {
// Could not select
}
}
public void closePlugin() {
// Release old interface visualizer if any
if (selectedMoteInterface != null && currentInterfaceVisualizer != null)
selectedMoteInterface.releaseInterfaceVisualizer(currentInterfaceVisualizer);
}
}

View file

@ -0,0 +1,123 @@
/*
* Copyright (c) 2006, 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: MoteTypeInformation.java,v 1.1 2006/08/21 12:13:08 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
/**
* Shows a summary of all created mote types.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Mote Type Information")
@VisPluginType(VisPluginType.SIM_PLUGIN)
public class MoteTypeInformation extends VisPlugin {
private static Logger logger = Logger.getLogger(MoteTypeInformation.class);
private static final long serialVersionUID = 1L;
private Simulation mySimulation;
private final static int LABEL_WIDTH = 170;
private final static int LABEL_HEIGHT = 15;
/**
* Create a new mote type information window.
*
* @param simulation Simulation
*/
public MoteTypeInformation(Simulation simulation) {
super("Mote Type Information *frozen*");
mySimulation = simulation;
JLabel label;
JPanel mainPane = new JPanel();
mainPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
JPanel smallPane;
// Visualize mote types
smallPane = new JPanel(new BorderLayout());
label = new JLabel("-- MOTE TYPES AT TIME " + simulation.getSimulationTime() + " --");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
smallPane.add(BorderLayout.NORTH, label);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,10)));
for (MoteType moteType: mySimulation.getMoteTypes()) {
smallPane = new JPanel();
smallPane.setLayout(new BorderLayout());
label = new JLabel(GUI.getDescriptionOf(moteType) +": " +
"ID=" + moteType.getIdentifier() +
", \"" + moteType.getDescription() + "\"");
label.setAlignmentX(JLabel.CENTER_ALIGNMENT);
smallPane.add(BorderLayout.NORTH, label);
JPanel moteTypeVisualizer = moteType.getTypeVisualizer();
if (moteTypeVisualizer != null) {
moteTypeVisualizer.setBorder(BorderFactory.createEtchedBorder());
smallPane.add(BorderLayout.CENTER, moteTypeVisualizer);
} else
smallPane.add(BorderLayout.CENTER, Box.createVerticalStrut(25));
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,25)));
}
this.setContentPane(new JScrollPane(mainPane,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
pack();
setPreferredSize(new Dimension(350,500));
setSize(new Dimension(350,500));
try {
setSelected(true);
} catch (java.beans.PropertyVetoException e) {
// Could not select
}
}
public void closePlugin() {
}
}

View file

@ -0,0 +1,262 @@
/*
* Copyright (c) 2006, 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: SimControl.java,v 1.1 2006/08/21 12:13:08 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
/**
* The Control Panel is a simple control panel for simulations.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Control Panel")
@VisPluginType(VisPluginType.SIM_STANDARD_PLUGIN)
public class SimControl extends VisPlugin {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(SimControl.class);
private static final int MIN_DELAY_TIME = 0;
private static final int MAX_DELAY_TIME = 100;
private Simulation simulation;
private JSlider sliderDelay;
private JLabel simulationTime;
private JButton startButton, stopButton;
private JFormattedTextField stopTimeTextField;
private int simulationStopTime = -1;
private Observer simObserver;
private Observer tickObserver;
private long lastTextUpdateTime = -1;
/**
* Create a new simulation control panel.
*
* @param simulationToControl Simulation to control
*/
public SimControl(Simulation simulationToControl) {
super("Control Panel - " + simulationToControl.getTitle());
simulation = simulationToControl;
JButton button;
JPanel smallPanel;
// Register as tickobserver
simulation.addTickObserver(tickObserver = new Observer() {
public void update(Observable obs, Object obj) {
// During simulation running, only update text 10 times each second
if (lastTextUpdateTime < System.currentTimeMillis() - 100) {
lastTextUpdateTime = System.currentTimeMillis();
simulationTime.setText("Current simulation time: " + simulation.getSimulationTime());
}
if (simulationStopTime > 0 && simulationStopTime <= simulation.getSimulationTime() && simulation.isRunning()) {
// Time to stop simulation now
simulation.stopSimulation();
simulationStopTime = -1;
}
}
});
// Register as simulation observer
simulation.addObserver(simObserver = new Observer() {
public void update(Observable obs, Object obj) {
if (simulation.isRunning()) {
startButton.setEnabled(false);
stopButton.setEnabled(true);
} else {
startButton.setEnabled(true);
stopButton.setEnabled(false);
simulationStopTime = -1;
}
sliderDelay.setValue((int) simulation.getDelayTime());
simulationTime.setText("Current simulation time: " + simulation.getSimulationTime());
}
});
// Main panel
JPanel controlPanel = new JPanel();
controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS));
setContentPane(controlPanel);
// Add control buttons
smallPanel = new JPanel();
smallPanel.setLayout(new BoxLayout(smallPanel, BoxLayout.X_AXIS));
smallPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5));
button = new JButton("Start");
button.setActionCommand("start");
button.addActionListener(myEventHandler);
startButton = button;
smallPanel.add(button);
button = new JButton("Stop");
button.setActionCommand("stop");
button.addActionListener(myEventHandler);
stopButton = button;
smallPanel.add(button);
button = new JButton("Tick all motes once");
button.setActionCommand("tickall");
button.addActionListener(myEventHandler);
smallPanel.add(button);
smallPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
controlPanel.add(smallPanel);
smallPanel = new JPanel();
smallPanel.setLayout(new BoxLayout(smallPanel, BoxLayout.X_AXIS));
smallPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 10, 5));
button = new JButton("Run until");
button.setActionCommand("rununtil");
button.addActionListener(myEventHandler);
smallPanel.add(button);
smallPanel.add(Box.createHorizontalStrut(10));
NumberFormat integerFormat = NumberFormat.getIntegerInstance();
stopTimeTextField = new JFormattedTextField(integerFormat);
stopTimeTextField.setValue(simulation.getSimulationTime());
stopTimeTextField.addPropertyChangeListener("value", new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
JFormattedTextField numberTextField = (JFormattedTextField) e.getSource();
int untilTime = ((Number) numberTextField.getValue()).intValue();
if (untilTime < simulation.getSimulationTime()) {
numberTextField.setValue(new Integer(simulation.getSimulationTime() + simulation.getTickTime()));
}
}
});
smallPanel.add(stopTimeTextField);
smallPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
controlPanel.add(smallPanel);
// Add delay slider
smallPanel = new JPanel();
smallPanel.setLayout(new BoxLayout(smallPanel, BoxLayout.Y_AXIS));
smallPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
simulationTime = new JLabel();
simulationTime.setText("Current simulation time: " + simulation.getSimulationTime());
smallPanel.add(simulationTime);
smallPanel.add(Box.createRigidArea(new Dimension(0, 10)));
smallPanel.add(new JLabel("Delay (ms) between each tick"));
JSlider slider;
if (simulation.getDelayTime() > MAX_DELAY_TIME)
slider = new JSlider(JSlider.HORIZONTAL, MIN_DELAY_TIME, simulation.getDelayTime(), simulation.getDelayTime());
else
slider = new JSlider(JSlider.HORIZONTAL, MIN_DELAY_TIME, MAX_DELAY_TIME, simulation.getDelayTime());
slider.addChangeListener(myEventHandler);
slider.setMajorTickSpacing(20);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
sliderDelay = slider;
smallPanel.add(slider);
controlPanel.add(smallPanel);
pack();
try {
setSelected(true);
} catch (java.beans.PropertyVetoException e) {
// Could not select
}
}
private class MyEventHandler implements ActionListener, ChangeListener {
public void stateChanged(ChangeEvent e) {
if (e.getSource() == sliderDelay) {
simulation.setDelayTime(sliderDelay.getValue());
} else
logger.debug("Unhandled state change: " + e);
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("start")) {
simulationStopTime = -1; // Reset until time
simulation.startSimulation();
} else if (e.getActionCommand().equals("stop")) {
simulationStopTime = -1; // Reset until time
if (simulation.isRunning())
simulation.stopSimulation();
} else if (e.getActionCommand().equals("tickall")) {
simulationStopTime = -1; // Reset until time
simulation.tickSimulation();
} else if (e.getActionCommand().equals("rununtil")) {
// Set new stop time
simulationStopTime = ((Number) stopTimeTextField.getValue()).intValue();
if (simulationStopTime > simulation.getSimulationTime() && !simulation.isRunning()) {
simulation.startSimulation();
} else {
if (simulation.isRunning())
simulation.stopSimulation();
simulationStopTime = -1;
}
} else
logger.debug("Unhandled action: " + e.getActionCommand());
}
} MyEventHandler myEventHandler = new MyEventHandler();
public void closePlugin() {
// Remove log observer from all log interfaces
if (simObserver != null)
simulation.deleteObserver(simObserver);
if (tickObserver != null)
simulation.deleteTickObserver(tickObserver);
}
}

View file

@ -0,0 +1,231 @@
/*
* Copyright (c) 2006, 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: SimInformation.java,v 1.1 2006/08/21 12:13:07 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import se.sics.cooja.*;
/**
* SimInformation is a simple information window for simulations.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Simulation Information")
@VisPluginType(VisPluginType.SIM_PLUGIN)
public class SimInformation extends VisPlugin {
private static final long serialVersionUID = 1L;
private Simulation simulation;
private final static int LABEL_WIDTH = 170;
private final static int LABEL_HEIGHT = 15;
private JLabel labelStatus;
private JLabel labelSimTime;
private JLabel labelNrMotes;
private JLabel labelNrMoteTypes;
private Observer simObserver;
private Observer tickObserver;
/**
* Create a new simulation information window.
*
* @param simulationToView Simulation to view
*/
public SimInformation(Simulation simulationToView) {
super("Simulation Information");
simulation = simulationToView;
// Register as simulation observer
simulation.addObserver(simObserver = new Observer() {
public void update(Observable obs, Object obj) {
if (simulation.isRunning()) {
labelStatus.setText("RUNNING");
} else {
labelStatus.setText("STOPPED");
}
labelNrMotes.setText("" + simulation.getMotesCount());
labelNrMoteTypes.setText("" + simulation.getMoteTypes().size());
}
});
// Register as tick observer
simulation.addTickObserver(tickObserver = new Observer() {
public void update(Observable obs, Object obj) {
labelSimTime.setText("" + simulation.getSimulationTime());
}
});
JLabel label;
JPanel mainPane = new JPanel();
mainPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
JPanel smallPane;
// Status information
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Status");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
smallPane.add(Box.createHorizontalGlue());
label = new JLabel();
if (simulation.isRunning())
label.setText("RUNNING");
else
label.setText("STOPPED");
labelStatus = label;
smallPane.add(label);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
// Current simulation time
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Simulation time");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
smallPane.add(Box.createHorizontalGlue());
label = new JLabel();
label.setText("" + simulation.getSimulationTime());
labelSimTime = label;
smallPane.add(label);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
// Number of motes
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Number of motes");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
smallPane.add(Box.createHorizontalGlue());
label = new JLabel();
label.setText("" + simulation.getMotesCount());
labelNrMotes = label;
smallPane.add(label);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
// Number of mote types
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Number of mote types");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
smallPane.add(Box.createHorizontalGlue());
label = new JLabel();
label.setText("" + simulation.getMoteTypes().size());
labelNrMoteTypes = label;
smallPane.add(label);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
// Radio Medium type
smallPane = new JPanel();
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
label = new JLabel("Radio medium");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
smallPane.add(label);
smallPane.add(Box.createHorizontalStrut(10));
smallPane.add(Box.createHorizontalGlue());
Class<? extends RadioMedium> radioMediumClass = simulation.getRadioMedium().getClass();
String description = GUI.getDescriptionOf(radioMediumClass);
label = new JLabel(description);
smallPane.add(label);
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,5)));
this.setContentPane(mainPane);
pack();
try {
setSelected(true);
} catch (java.beans.PropertyVetoException e) {
// Could not select
}
}
public void closePlugin() {
// Remove log observer from all log interfaces
if (simObserver != null)
simulation.deleteObserver(simObserver);
if (tickObserver != null)
simulation.deleteTickObserver(tickObserver);
}
}

View file

@ -0,0 +1,310 @@
/*
* Copyright (c) 2006, 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: VariableWatcher.java,v 1.1 2006/08/21 12:13:07 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.text.NumberFormat;
import javax.swing.*;
import se.sics.cooja.*;
/**
* Variable Watcher enables a user to watch mote variables during a simulation.
* Variables can be read or written either as bytes, integers (4 bytes) or byte arrays.
*
* User can also see which variables seems to be available on the selected node.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Variable Watcher")
@VisPluginType(VisPluginType.MOTE_PLUGIN)
public class VariableWatcher extends VisPlugin {
private static final long serialVersionUID = 1L;
private SectionMoteMemory moteMemory;
private final static int LABEL_WIDTH = 170;
private final static int LABEL_HEIGHT = 15;
private final static int BYTE_INDEX = 0;
private final static int INT_INDEX = 1;
private final static int ARRAY_INDEX = 2;
private JPanel lengthPane;
private JPanel valuePane;
private JComboBox varName;
private JFormattedTextField[] varValues;
private JFormattedTextField varLength;
private JButton writeButton;
private NumberFormat integerFormat;
/**
* Create a variable watcher window.
*
* @param moteToView Mote to view
*/
public VariableWatcher(Mote moteToView) {
super("Variable Watcher (" + moteToView + ")");
moteMemory = (SectionMoteMemory) moteToView.getMemory();
JLabel label;
integerFormat = NumberFormat.getIntegerInstance();
JPanel mainPane = new JPanel();
mainPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
JPanel smallPane;
// Variable name
smallPane = new JPanel(new BorderLayout());
label = new JLabel("Variable name");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
smallPane.add(BorderLayout.WEST, label);
varName = new JComboBox();
varName.setEditable(true);
varName.setSelectedItem("[enter or pick name]");
String[] allPotentialVarNames = moteMemory.getVariableNames();
for (String aVarName: allPotentialVarNames)
varName.addItem(aVarName);
varName.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
writeButton.setEnabled(false);
}
public void keyTyped(KeyEvent e) {
writeButton.setEnabled(false);
}
public void keyReleased(KeyEvent e) {
writeButton.setEnabled(false);
}
});
smallPane.add(BorderLayout.EAST, varName);
mainPane.add(smallPane);
// Variable type
smallPane = new JPanel(new BorderLayout());
label = new JLabel("Variable type");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
smallPane.add(BorderLayout.WEST, label);
final JComboBox varType = new JComboBox();
varType.addItem("Byte (1 byte)"); // BYTE_INDEX = 0
varType.addItem("Integer (4 bytes)"); // INT_INDEX = 1
varType.addItem("Byte array (x bytes)"); // ARRAY_INDEX = 2
varType.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (varType.getSelectedIndex() == ARRAY_INDEX) {
lengthPane.setVisible(true);
setNumberOfValues(((Number) varLength.getValue()).intValue());
} else {
lengthPane.setVisible(false);
setNumberOfValues(1);
}
pack();
}
});
smallPane.add(BorderLayout.EAST, varType);
mainPane.add(smallPane);
// Variable length
lengthPane = new JPanel(new BorderLayout());
label = new JLabel("Variable length");
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
lengthPane.add(BorderLayout.WEST, label);
varLength = new JFormattedTextField(integerFormat);
varLength.setValue(new Integer(1));
varLength.setColumns(4);
varLength.addPropertyChangeListener("value", new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
setNumberOfValues(((Number) varLength.getValue()).intValue());
}
});
lengthPane.add(BorderLayout.EAST, varLength);
mainPane.add(lengthPane);
mainPane.add(Box.createRigidArea(new Dimension(0,25)));
lengthPane.setVisible(false);
// Variable value label
label = new JLabel("Variable value");
label.setAlignmentX(JLabel.CENTER_ALIGNMENT);
label.setPreferredSize(new Dimension(LABEL_WIDTH,LABEL_HEIGHT));
mainPane.add(label);
// Variable value(s)
valuePane = new JPanel();
valuePane.setLayout(new BoxLayout(valuePane, BoxLayout.X_AXIS));
varValues = new JFormattedTextField[1];
varValues[0] = new JFormattedTextField(integerFormat);
varValues[0].setValue(new Integer(0));
varValues[0].setColumns(3);
varValues[0].setText("?");
for (JFormattedTextField varValue: varValues) {
valuePane.add(varValue);
}
mainPane.add(valuePane);
mainPane.add(Box.createRigidArea(new Dimension(0,25)));
// Read/write buttons
smallPane = new JPanel(new BorderLayout());
JButton button = new JButton("Read");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (varType.getSelectedIndex() == BYTE_INDEX) {
try {
byte val = moteMemory.getByteValueOf((String) varName.getSelectedItem());
varValues[0].setValue(new Integer(val));
varName.setBackground(Color.WHITE);
writeButton.setEnabled(true);
} catch (Exception ex) {
varName.setBackground(Color.RED);
writeButton.setEnabled(false);
}
} else if (varType.getSelectedIndex() == INT_INDEX) {
try {
int val = moteMemory.getIntValueOf((String) varName.getSelectedItem());
varValues[0].setValue(new Integer(val));
varName.setBackground(Color.WHITE);
writeButton.setEnabled(true);
} catch (Exception ex) {
varName.setBackground(Color.RED);
writeButton.setEnabled(false);
}
} else if (varType.getSelectedIndex() == ARRAY_INDEX) {
try {
int length = ((Number) varLength.getValue()).intValue();
byte[] vals = moteMemory.getByteArray((String) varName.getSelectedItem(), length);
for (int i=0; i < length; i++)
varValues[i].setValue(new Integer(vals[i]));
varName.setBackground(Color.WHITE);
writeButton.setEnabled(true);
} catch (Exception ex) {
varName.setBackground(Color.RED);
writeButton.setEnabled(false);
}
}
}
});
smallPane.add(BorderLayout.WEST, button);
button = new JButton("Write");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (varType.getSelectedIndex() == BYTE_INDEX) {
try {
byte val = (byte) ((Number) varValues[0].getValue()).intValue();
moteMemory.setByteValueOf((String) varName.getSelectedItem(), val);
varName.setBackground(Color.WHITE);
} catch (Exception ex) {
varName.setBackground(Color.RED);
}
} else if (varType.getSelectedIndex() == INT_INDEX) {
try {
int val = ((Number) varValues[0].getValue()).intValue();
moteMemory.setIntValueOf((String) varName.getSelectedItem(), val);
varName.setBackground(Color.WHITE);
} catch (Exception ex) {
varName.setBackground(Color.RED);
}
} else if (varType.getSelectedIndex() == ARRAY_INDEX) {
try {
int length = ((Number) varLength.getValue()).intValue();
byte[] vals = new byte[length];
for (int i=0; i < length; i++) {
vals[i] = (byte) ((Number) varValues[i].getValue()).intValue();
}
moteMemory.setByteArray((String) varName.getSelectedItem(), vals);
varName.setBackground(Color.WHITE);
writeButton.setEnabled(true);
} catch (Exception ex) {
varName.setBackground(Color.RED);
writeButton.setEnabled(false);
}
}
}
});
smallPane.add(BorderLayout.EAST, button);
button.setEnabled(false);
writeButton = button;
mainPane.add(smallPane);
mainPane.add(Box.createRigidArea(new Dimension(0,25)));
this.setContentPane(new JScrollPane(mainPane,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
pack();
try {
setSelected(true);
} catch (java.beans.PropertyVetoException e) {
// Could not select
}
}
private void setNumberOfValues(int nr) {
valuePane.removeAll();
if (nr > 0) {
varValues = new JFormattedTextField[nr];
for (int i=0; i < nr; i++) {
varValues[i] = new JFormattedTextField(integerFormat);
varValues[i] .setValue(new Integer(0));
varValues[i] .setColumns(3);
varValues[i] .setText("?");
valuePane.add(varValues[i]);
}
}
pack();
}
public void closePlugin() {
}
}

View file

@ -0,0 +1,138 @@
/*
* Copyright (c) 2006, 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: VisBattery.java,v 1.1 2006/08/21 12:13:08 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.util.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.Battery;
/**
* A Battery Visualizer indicates mote energy levels by painting them in
* different colors. The mote is painted in a grayscale where white is max
* energy and black is no energy left. If a mote has no battery interface or
* infinite energy, it is painted blue. If a mote is dead it is painted red.
*
* A VisBattery observers both the simulation and all mote batteries.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Battery Visualizer")
@VisPluginType(VisPluginType.SIM_PLUGIN)
public class VisBattery extends Visualizer2D {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(VisBattery.class);
private Simulation simulation;
private Observer simObserver = null; // Watches simulation changes
private Observer batteryObserver = null; // Watches mote battery changes
/**
* Creates a new battery visualizer.
*
* @param simulationToVisualize
* Simulation to visualize
*/
public VisBattery(Simulation simulationToVisualize) {
super(simulationToVisualize);
setTitle("Battery Visualizer");
simulation = simulationToVisualize;
// Always observe all motes in simulation
batteryObserver = new Observer() {
public void update(Observable obs, Object obj) {
getCurrentCanvas().repaint();
}
};
simulation.addObserver(simObserver = new Observer() {
public void update(Observable obs, Object obj) {
// Register (or reregister) as observer on all motes
for (int i = 0; i < simulation.getMotesCount(); i++) {
Battery battery = simulation.getMote(i).getInterfaces().getBattery();
if (battery != null) {
battery.addObserver(batteryObserver);
}
}
}
});
simObserver.update(null, null);
}
public void postVisualizeSimulation(Graphics g) {
}
public Color[] getColorOf(Mote mote) {
if (mote.getState() == Mote.STATE_DEAD)
return new Color[]{Color.RED};
Battery battery = mote.getInterfaces().getBattery();
if (battery == null) {
return new Color[]{Color.BLUE};
}
if (battery.hasInfiniteEnergy()) {
return new Color[]{Color.BLUE};
}
double currentEnergy = battery.getCurrentEnergy();
if (currentEnergy < 0.0) {
return new Color[]{Color.RED};
}
int grayValue = (int) (255 * (currentEnergy / battery.getInitialEnergy()));
return new Color[]{new Color(grayValue, grayValue, grayValue)};
}
public void closePlugin() {
if (simObserver != null) {
simulation.deleteObserver(simObserver);
// Delete all state observers
for (int i = 0; i < simulation.getMotesCount(); i++) {
Battery battery = simulation.getMote(i).getInterfaces().getBattery();
if (battery != null) {
battery.deleteObserver(batteryObserver);
}
}
}
super.closePlugin();
}
}

View file

@ -0,0 +1,151 @@
/*
* Copyright (c) 2006, 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: VisState.java,v 1.1 2006/08/21 12:13:07 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.util.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
/**
* A State Visualizer indicates mote states by painting them in different colors.
* Active motes are green, sleeping motes are gray and dead motes are read.
*
* The inner color indicates the mote type.
*
* A VisState observes both the simulation and all mote states.
*
* @author Fredrik Osterlind
*/
@ClassDescription("State Visualizer")
@VisPluginType(VisPluginType.SIM_PLUGIN)
public class VisState extends Visualizer2D {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(VisState.class);
private Simulation simulation;
private static final Color moteTypeColors[] = new Color[] {
Color.MAGENTA,
Color.CYAN,
Color.ORANGE,
Color.GREEN,
Color.BLUE,
Color.RED,
Color.YELLOW,
};
private Observer simObserver = null; // Watches simulation changes
private Observer stateObserver = null; // Watches mote state changes
/**
* Creates a new state visualizer.
*
* @param simulationToVisualize Simulation to visualize
*/
public VisState(Simulation simulationToVisualize) {
super(simulationToVisualize);
setTitle("State Visualizer");
simulation = simulationToVisualize;
// Always observe all motes in simulation
stateObserver = new Observer() {
public void update(Observable obs, Object obj) {
getCurrentCanvas().repaint();
}
};
simulation.addObserver(simObserver = new Observer() {
public void update(Observable obs, Object obj) {
// Register (or reregister) as observer on all motes
for (int i=0; i < simulation.getMotesCount(); i++) {
Mote mote = simulation.getMote(i);
if (mote != null) {
mote.addStateObserver(stateObserver);
}
}
}
});
simObserver.update(null, null);
}
public void postVisualizeSimulation(Graphics g) {
}
public Color[] getColorOf(Mote mote) {
Color[] returnColors = new Color[2];
// If mote is sleeping, make outer circle blue
if (mote.getState() == Mote.STATE_LPM)
returnColors[1] = Color.GRAY;
// If mote is dead, make outer circle red
else if (mote.getState() == Mote.STATE_DEAD)
returnColors[1] = Color.RED;
else
returnColors[1] = Color.GREEN; // make outer circle green
// Associate different colors with different mote types
Vector<MoteType> allTypes = simulation.getMoteTypes();
int numberOfTypes = allTypes.size();
for (int colCounter=0; colCounter < numberOfTypes && colCounter < moteTypeColors.length; colCounter++) {
if (mote.getType() == allTypes.get(colCounter)) {
returnColors[0] = moteTypeColors[colCounter];
return returnColors;
}
}
returnColors[0] = Color.WHITE;
return returnColors;
}
public void closePlugin() {
if (simObserver != null) {
simulation.deleteObserver(simObserver);
// Delete all state observers
for (int i=0; i < simulation.getMotesCount(); i++) {
Mote mote = simulation.getMote(i);
if (mote != null) {
mote.deleteStateObserver(stateObserver);
}
}
}
super.closePlugin();
}
}

View file

@ -0,0 +1,184 @@
/*
* Copyright (c) 2006, 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: VisTraffic.java,v 1.1 2006/08/21 12:13:07 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Observable;
import java.util.Observer;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.Position;
/**
* A Traffic Visualizer visualizes radio traffic by painting lines between
* communicating motes.
*
* A VisTraffic observers the current simulation radio medium.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Traffic Visualizer")
@VisPluginType(VisPluginType.SIM_PLUGIN)
public class VisTraffic extends Visualizer2D {
private static final long serialVersionUID = 1L;
private RadioMedium radioMedium;
/**
* The image painted on screen at repaint().
*/
public BufferedImage image;
private Position oldSmallPosition = null;
private Position oldBigPosition = null;
private Simulation simulation;
private int oldNrMotes;
private Observer radioObserver = null;
/**
* Creates a new VisTraffic visualizer.
*
* @param simulationToVisualize
* Simulation to visualize
*/
public VisTraffic(Simulation simulationToVisualize) {
super(simulationToVisualize);
setTitle("Traffic Visualizer");
simulation = simulationToVisualize;
oldNrMotes = simulation.getMotesCount();
radioMedium = simulationToVisualize.getRadioMedium();
// Repaint when radio medium has sent data
simulationToVisualize.getRadioMedium().addRadioMediumObserver(radioObserver = new Observer() {
public void update(Observable obs, Object obj) {
Graphics2D g2d = image.createGraphics();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f));
if (radioMedium != null && radioMedium.getLastTickConnections() != null) {
for (RadioConnection conn: radioMedium.getLastTickConnections()) {
paintConnection(conn, g2d);
}
}
getCurrentCanvas().repaint();
}
});
}
/**
* Paints given connection on given graphics.
*
* @param connection Connection
* @param g2d Graphics to paint on
*/
protected void paintConnection(RadioConnection connection, Graphics g2d) {
Point sourcePixelPosition = transformPositionToPixel(connection.getSourcePosition());
for (Position destPosition: connection.getDestinationPositons()) {
Point destPixelPosition = transformPositionToPixel(destPosition);
g2d.setColor(getColorOf(connection));
g2d.drawLine(sourcePixelPosition.x, sourcePixelPosition.y,
destPixelPosition.x, destPixelPosition.y);
}
}
/**
* Returns color a specific connection should be painted in.
*
* @param connection Connection
*/
protected Color getColorOf(RadioConnection connection) {
return Color.BLACK;
}
protected void calculateTransformations() {
super.calculateTransformations();
Dimension imageDimension = getCurrentCanvas().getPreferredSize();
if (imageDimension.height <= 0 || imageDimension.width <= 0)
return;
// Recreate image if ..
if (
// .. it hasn't been painted before
oldSmallPosition == null ||
oldBigPosition == null ||
image == null ||
simulation == null ||
// .. mote changes may have changed the transformation.
simulation.getMotesCount() != oldNrMotes ||
// .. visualization window has changed the transformation.
imageDimension.height != image.getHeight() ||
imageDimension.width != image.getWidth()
) {
if (simulation != null)
oldNrMotes = simulation.getMotesCount();
BufferedImage oldImage = image;
image = new BufferedImage(imageDimension.width, imageDimension.height, BufferedImage.TYPE_4BYTE_ABGR);
image.createGraphics().setColor(Color.WHITE);
image.createGraphics().fillRect(0, 0, imageDimension.width, imageDimension.height);
// If old data exists, keep it
if (oldSmallPosition != null && oldBigPosition != null) {
Point oldSmallPixelPos = transformPositionToPixel(oldSmallPosition);
Point oldBigPixelPos = transformPositionToPixel(oldBigPosition);
image.createGraphics().drawImage(oldImage,
oldSmallPixelPos.x,
oldSmallPixelPos.y,
oldBigPixelPos.x-oldSmallPixelPos.x,
oldBigPixelPos.y-oldSmallPixelPos.y,
null);
}
oldSmallPosition = transformPixelToPositon(new Point(0,0));
oldBigPosition = transformPixelToPositon(new Point(imageDimension.width, imageDimension.height));
}
}
public void closePlugin() {
super.closePlugin();
// Remove radio observer
radioMedium.deleteRadioMediumObserver(radioObserver);
}
public Color[] getColorOf(Mote m) {
return null;
}
protected void visualizeSimulation(Graphics g) {
g.drawImage(image, 0, 0, null);
}
}

View file

@ -0,0 +1,539 @@
/*
* Copyright (c) 2006, 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: Visualizer2D.java,v 1.1 2006/08/21 12:13:08 fros4943 Exp $
*/
package se.sics.cooja.plugins;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.*;
/**
* Visualizer2D is an abstract mote visualizer for simulations. All motes are
* painted in the XY-plane, as seen from positive Z axis.
*
* An implementation of this class must colorize the different motes, each mote
* has two different colors; inner and outer.
*
* By right-clicking the mouse on a mote a popup menu will be displayed. From
* this menu mote plugins can be started. or the mote can be moved. Each
* implementation may also register its own actions to be accessed from this
* menu.
*
* A Visualizer2D observers both the simulation and all mote positions.
*
* @author Fredrik Osterlind
*/
@ClassDescription("2D Mote Visualizer")
@VisPluginType(VisPluginType.SIM_PLUGIN)
public abstract class Visualizer2D extends VisPlugin {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(Visualizer2D.class);
private double factorXCoordToPixel;
private double factorYCoordToPixel;
private double smallestXCoord;
private double smallestYCoord;
private Simulation simulation = null;
private final JPanel canvas;
private Visualizer2D myPlugin;
private static final int CANVAS_BORDER_WIDTH = 25;
private static final int MOTE_RADIUS = 8;
private boolean moteIsBeingMoved = false;
private Mote moteToMove = null;
private Observer simObserver = null; // Watches simulation changes
private Observer posObserver = null; // Watches position changes
public interface MoteMenuAction {
public boolean isEnabled(Mote mote);
public String getDescription(Mote mote);
public void doAction(Mote mote);
}
private class MoveMoteMenuAction implements MoteMenuAction {
public boolean isEnabled(Mote mote) {
return true;
}
public String getDescription(Mote mote) {
return "Move " + mote;
}
public void doAction(Mote mote) {
beginMoveRequest(mote);
}
};
private Vector<MoteMenuAction> menuActions = new Vector<MoteMenuAction>();
/**
* Registers as an simulation observer and initializes the canvas.
*
* @param simulationToVisualize
* Simulation to visualize
*/
public Visualizer2D(Simulation simulationToVisualize) {
super("Visualizer2D");
myPlugin = this;
// Set initial bounds of frame
this.setBounds(150, 150, 300, 300);
setVisible(true);
simulation = simulationToVisualize;
// Create "canvas" to paint on
canvas = new JPanel() {
private static final long serialVersionUID = 1L;
public void paintComponent(Graphics g) {
super.paintComponent(g);
visualizeSimulation(g);
}
};
canvas.setPreferredSize(new Dimension(getSize().width - 16,
getSize().height - 38));
canvas.setBorder(BorderFactory.createLineBorder(Color.GREEN, 2));
canvas.setBackground(Color.WHITE);
calculateTransformations();
this.setContentPane(canvas);
// Detect general simulation changes
posObserver = new Observer() {
public void update(Observable obs, Object obj) {
calculateTransformations();
canvas.repaint();
}
};
simulation.addObserver(simObserver = new Observer() {
public void update(Observable obs, Object obj) {
canvas.setPreferredSize(new Dimension(getSize().width - 16,
getSize().height - 38));
// Register (or reregister) as observer on all mote positions
for (int i = 0; i < simulation.getMotesCount(); i++) {
Position posIntf = simulation.getMote(i).getInterfaces()
.getPosition();
if (posIntf != null) {
posIntf.addObserver(posObserver);
}
}
calculateTransformations();
canvas.repaint();
}
});
simObserver.update(null, null);
canvas.addMouseMotionListener(new MouseMotionListener() {
public void mouseMoved(MouseEvent e) {
myPlugin.handleMoveRequest(e.getPoint().x, e.getPoint().y, false);
}
public void mouseDragged(MouseEvent e) {
myPlugin.handleMoveRequest(e.getPoint().x, e.getPoint().y, false);
}
});
// Detect mouse events
canvas.addMouseListener(new MouseListener() {
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger())
myPlugin.handlePopupRequest(e.getPoint().x, e.getPoint().y);
else {
myPlugin.handleMoveRequest(e.getPoint().x, e.getPoint().y, false);
}
}
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger())
myPlugin.handlePopupRequest(e.getPoint().x, e.getPoint().y);
else {
myPlugin.handleMoveRequest(e.getPoint().x, e.getPoint().y, true);
}
}
public void mouseEntered(MouseEvent e) {
if (e.isPopupTrigger())
myPlugin.handlePopupRequest(e.getPoint().x, e.getPoint().y);
}
public void mouseExited(MouseEvent e) {
if (e.isPopupTrigger())
myPlugin.handlePopupRequest(e.getPoint().x, e.getPoint().y);
}
public void mouseClicked(MouseEvent e) {
if (e.isPopupTrigger())
myPlugin.handlePopupRequest(e.getPoint().x, e.getPoint().y);
}
});
// Detect component events
addComponentListener(new ComponentListener() {
public void componentMoved(ComponentEvent ce) {
// NOP
}
public void componentShown(ComponentEvent ce) {
// NOP
}
public void componentHidden(ComponentEvent ce) {
// NOP
}
public void componentResized(ComponentEvent ce) {
canvas.setPreferredSize(new Dimension(getSize().width - 16,
getSize().height - 38));
calculateTransformations();
canvas.repaint();
}
});
// Add menu action for moving motes
addMoteMenuAction(new MoveMoteMenuAction());
try {
setSelected(true);
} catch (java.beans.PropertyVetoException e) {
// Could not select
}
}
/**
* Add new mote menu action.
*
* @see MoteMenuAction
* @param menuAction Menu action
*/
public void addMoteMenuAction(MoteMenuAction menuAction) {
menuActions.add(menuAction);
}
private void handlePopupRequest(final int x, final int y) {
final Vector<Mote> foundMotes = findMotesAtPosition(x, y);
if (foundMotes == null || foundMotes.size() == 0)
return;
JPopupMenu pickMoteMenu = new JPopupMenu();
pickMoteMenu.add(new JLabel("Select action:"));
pickMoteMenu.add(new JSeparator());
// Add 'show mote plugins'-actions
for (final Mote mote : foundMotes) {
final Point pos = new Point(canvas.getLocationOnScreen().x + x, canvas
.getLocationOnScreen().y
+ y);
JMenuItem menuItem = new JMenuItem("Open mote plugin for " + mote);
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
GUI.currentGUI.showMotePluginsMenu(canvas, mote, pos);
}
});
pickMoteMenu.add(menuItem);
}
// Add the rest of the actions
for (final MoteMenuAction menuAction : menuActions) {
for (final Mote mote : foundMotes) {
if (menuAction.isEnabled(mote)) {
JMenuItem menuItem = new JMenuItem(menuAction.getDescription(mote));
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
menuAction.doAction(mote);
}
});
pickMoteMenu.add(menuItem);
}
}
}
// Show menu
Point pos = new Point(canvas.getLocationOnScreen().x + x, canvas
.getLocationOnScreen().y
+ y);
pickMoteMenu.setLocation(pos.x, pos.y);
pickMoteMenu.setInvoker(canvas);
pickMoteMenu.setVisible(true);
}
private void beginMoveRequest(Mote moteToMove) {
moteIsBeingMoved = true;
this.moteToMove = moteToMove;
}
private void handleMoveRequest(final int x, final int y,
boolean wasJustReleased) {
if (!moteIsBeingMoved) {
return;
}
if (!wasJustReleased) {
visualizeSimulation(canvas.getGraphics());
canvas.paintImmediately(x - 40, y - 40, 80, 80);
canvas.getGraphics().setColor(Color.GRAY);
canvas.getGraphics().drawOval(x - MOTE_RADIUS, y - MOTE_RADIUS,
2 * MOTE_RADIUS, 2 * MOTE_RADIUS);
}
if (wasJustReleased) {
moteIsBeingMoved = false;
Position newXYValues = transformPixelToPositon(new Point(x, y));
int returnValue = JOptionPane.showConfirmDialog(myPlugin, "Mote mote to"
+ "\nX=" + newXYValues.getXCoordinate() + "\nY="
+ newXYValues.getYCoordinate() + "\nZ="
+ moteToMove.getInterfaces().getPosition().getZCoordinate());
if (returnValue == JOptionPane.OK_OPTION) {
moteToMove.getInterfaces().getPosition().setCoordinates(
newXYValues.getXCoordinate(), newXYValues.getYCoordinate(),
moteToMove.getInterfaces().getPosition().getZCoordinate());
repaint();
}
}
}
/**
* Returns all motes at given position.
*
* @param clickedX
* X coordinate
* @param clickedY
* Y coordinate
* @return All motes at given position
*/
protected Vector<Mote> findMotesAtPosition(int clickedX, int clickedY) {
double xCoord = factorXPixelToCoord(clickedX);
double yCoord = factorYPixelToCoord(clickedY);
Vector<Mote> motesFound = new Vector<Mote>();
// Calculate painted mote radius in coordinates
double paintedMoteWidth = factorXPixelToCoord(MOTE_RADIUS)
- factorXPixelToCoord(0);
double paintedMoteHeight = factorYPixelToCoord(MOTE_RADIUS)
- factorYPixelToCoord(0);
for (int i = 0; i < simulation.getMotesCount(); i++) {
Position pos = simulation.getMote(i).getInterfaces().getPosition();
// Transform to unit circle before checking if mouse hit this mote
double distanceX = Math.abs(xCoord - pos.getXCoordinate())
/ paintedMoteWidth;
double distanceY = Math.abs(yCoord - pos.getYCoordinate())
/ paintedMoteHeight;
if (distanceX * distanceX + distanceY * distanceY <= 1) {
motesFound.add(simulation.getMote(i));
}
}
if (motesFound.size() == 0)
return null;
return motesFound;
}
/**
* Get colors a certain mote should be painted with. May be overridden to get
* a different color scheme.
*
* Normally this method returns an array of two colors, one for the state
* (outer circle), the other for the type (inner circle).
*
* If this method only returns one color, the entire mote will be painted
* using that.
*
* @param mote
* Mote to paint
* @return Color[] { Inner color, Outer color }
*/
abstract public Color[] getColorOf(Mote mote);
protected void visualizeSimulation(Graphics g) {
for (int i = 0; i < simulation.getMotesCount(); i++) {
Mote mote = simulation.getMote(i);
Color moteColors[] = getColorOf(mote);
Position motePos = mote.getInterfaces().getPosition();
Point pixelCoord = transformPositionToPixel(motePos);
int x = pixelCoord.x;
int y = pixelCoord.y;
if (moteColors.length >= 1) {
g.setColor(moteColors[0]);
g.fillOval(x - MOTE_RADIUS, y - MOTE_RADIUS, 2 * MOTE_RADIUS,
2 * MOTE_RADIUS);
}
if (moteColors.length >= 2) {
g.setColor(moteColors[1]);
g.fillOval(x - MOTE_RADIUS / 2, y - MOTE_RADIUS / 2, MOTE_RADIUS,
MOTE_RADIUS);
}
g.setColor(Color.BLACK);
g.drawOval(x - MOTE_RADIUS, y - MOTE_RADIUS, 2 * MOTE_RADIUS,
2 * MOTE_RADIUS);
}
}
/**
* Recalculate size of canvas and factors for transforming between real and
* pixel coordinates. This method is called every time this frame is resized
* or created.
*/
protected void calculateTransformations() {
if (simulation.getMotesCount() == 0) {
smallestXCoord = 0;
smallestYCoord = 0;
factorXCoordToPixel = 1;
factorYCoordToPixel = 1;
return;
}
double biggestXCoord, biggestYCoord;
Position motePos = simulation.getMote(0).getInterfaces().getPosition();
smallestXCoord = biggestXCoord = motePos.getXCoordinate();
smallestYCoord = biggestYCoord = motePos.getYCoordinate();
// Get extreme coordinates
for (int i = 0; i < simulation.getMotesCount(); i++) {
motePos = simulation.getMote(i).getInterfaces().getPosition();
if (motePos.getXCoordinate() < smallestXCoord)
smallestXCoord = motePos.getXCoordinate();
if (motePos.getXCoordinate() > biggestXCoord)
biggestXCoord = motePos.getXCoordinate();
if (motePos.getYCoordinate() < smallestYCoord)
smallestYCoord = motePos.getYCoordinate();
if (motePos.getYCoordinate() > biggestYCoord)
biggestYCoord = motePos.getYCoordinate();
}
if ((biggestXCoord - smallestXCoord) == 0) {
factorXCoordToPixel = 1;
} else
factorXCoordToPixel = ((double) canvas.getPreferredSize().width - 2 * CANVAS_BORDER_WIDTH)
/ (biggestXCoord - smallestXCoord);
if ((biggestYCoord - smallestYCoord) == 0) {
factorYCoordToPixel = 1;
} else
factorYCoordToPixel = ((double) canvas.getPreferredSize().height - 2 * CANVAS_BORDER_WIDTH)
/ (biggestYCoord - smallestYCoord);
}
/**
* Transforms a real-world position to a pixel which can be painted onto the
* current sized canvas.
*
* @param pos
* Real-world position
* @return Pixel coordinates
*/
public Point transformPositionToPixel(Position pos) {
return new Point(factorXCoordToPixel(pos.getXCoordinate()),
factorYCoordToPixel(pos.getYCoordinate()));
}
/**
* Transforms real-world coordinates to a pixel which can be painted onto the
* current sized canvas.
*
* @param x Real world X
* @param y Real world Y
* @param z Real world Z (ignored)
* @return Pixel coordinates
*/
public Point transformPositionToPixel(double x, double y, double z) {
return new Point(factorXCoordToPixel(x), factorYCoordToPixel(y));
}
/**
* Transforms a pixel coordinate to a real-world. Z-value will always be 0.
*
* @param pixelPos
* On-screen pixel coordinate
* @return Real world coordinate (z=0).
*/
public Position transformPixelToPositon(Point pixelPos) {
Position dummyPosition = new Position(null);
dummyPosition.setCoordinates(factorXPixelToCoord(pixelPos.x),
factorYPixelToCoord(pixelPos.y), 0.0);
return dummyPosition;
}
/**
* @return The current canvas to paint on
*/
public JPanel getCurrentCanvas() {
return canvas;
}
private int factorXCoordToPixel(double xCoordinate) {
return (int) ((xCoordinate - smallestXCoord) * factorXCoordToPixel + CANVAS_BORDER_WIDTH);
}
private int factorYCoordToPixel(double yCoordinate) {
return (int) ((yCoordinate - smallestYCoord) * factorYCoordToPixel)
+ CANVAS_BORDER_WIDTH;
}
private double factorXPixelToCoord(int xPixel) {
return ((double) (xPixel - CANVAS_BORDER_WIDTH) / factorXCoordToPixel)
+ smallestXCoord;
}
private double factorYPixelToCoord(int yPixel) {
return ((double) (yPixel - CANVAS_BORDER_WIDTH) / factorYCoordToPixel)
+ smallestYCoord;
}
public void closePlugin() {
if (simObserver != null) {
simulation.deleteObserver(simObserver);
for (int i = 0; i < simulation.getMotesCount(); i++) {
Position posIntf = simulation.getMote(i).getInterfaces().getPosition();
if (posIntf != null) {
posIntf.deleteObserver(posObserver);
}
}
}
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2006, 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: EllipsePositioner.java,v 1.1 2006/08/21 12:13:11 fros4943 Exp $
*/
package se.sics.cooja.positioners;
import se.sics.cooja.*;
/**
* Generates positions in a ellipse in the XY plane.
* (z position will always be start value of interval)
*
* @author Fredrik Osterlind
*/
@ClassDescription("Ellipse positioning")
public class EllipsePositioner extends Positioner {
private double xRadius, yRadius, xMiddle, yMiddle;
private double zValue, deltaAngle, currentAngle;
/**
* Creates a circle positioner.
* @param totalNumberOfMotes Total number of motes
* @param startX X interval start
* @param endX X interval end
* @param startY Y interval start
* @param endY Y interval end
* @param startZ Z interval start
* @param endZ Z interval end
*/
public EllipsePositioner(int totalNumberOfMotes,
double startX, double endX,
double startY, double endY,
double startZ, double endZ) {
xRadius = (endX - startX) / 2.0;
yRadius = (endY - startY) / 2.0;
xMiddle = startX + xRadius;
yMiddle = startY + yRadius;
zValue = startZ;
deltaAngle = 2*Math.PI / (double) totalNumberOfMotes;
currentAngle = 0;
}
public double[] getNextPosition() {
currentAngle += deltaAngle;
return new double[] {
xMiddle + xRadius * Math.cos(currentAngle),
yMiddle + yRadius * Math.sin(currentAngle),
zValue};
}
}

View file

@ -0,0 +1,148 @@
/*
* Copyright (c) 2006, 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: LinearPositioner.java,v 1.1 2006/08/21 12:13:11 fros4943 Exp $
*/
package se.sics.cooja.positioners;
import se.sics.cooja.*;
/**
* Generates positions linearly distributed in a given interval.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Linear positioning")
public class LinearPositioner extends Positioner {
private double startX, startY, startZ;
private int addedInX, addedInY, addedInZ;
private int numberInX, numberInY, numberInZ;
private double xInterval, yInterval, zInterval;
/**
* Creates a linear positioner.
*
* @param totalNumberOfMotes Total number of motes
* @param startX X interval start
* @param endX X interval end
* @param startY Y interval start
* @param endY Y interval end
* @param startZ Z interval start
* @param endZ Z interval end
*/
public LinearPositioner(int totalNumberOfMotes,
double startX, double endX,
double startY, double endY,
double startZ, double endZ) {
this.startX = startX;
this.startY = startY;
this.startZ = startZ;
double widthX = endX - startX;
double widthY = endY - startY;
double widthZ = endZ - startZ;
if (widthX == 0) {
widthX = -1;
}
if (widthY == 0) {
widthY = -1;
}
if (widthZ == 0) {
widthZ = -1;
}
double totalSpace = Math.abs(widthX * widthY * widthZ);
double spaceOfEachMote = totalSpace / (double) totalNumberOfMotes;
int noDimensions = 0;
if (widthX > 0)
noDimensions++;
if (widthY > 0)
noDimensions++;
if (widthZ > 0)
noDimensions++;
double sideLengthOfEachMote = Math.pow(spaceOfEachMote, 1.0/(double) noDimensions);
this.numberInX = 0;
this.numberInY = 0;
this.numberInZ = 0;
if (widthX > 0)
numberInX = (int) (widthX / sideLengthOfEachMote);
if (widthY > 0)
numberInY = (int) (widthY / sideLengthOfEachMote);
if (widthZ > 0)
numberInZ = (int) (widthZ / sideLengthOfEachMote);
this.xInterval = widthX / numberInX;
this.yInterval = widthY / numberInY;
this.zInterval = widthZ / numberInZ;
if (numberInX == 0)
xInterval = 0.0;
if (numberInY == 0)
yInterval = 0.0;
if (numberInZ == 0)
zInterval = 0.0;
this.addedInX = 0;
this.addedInY = 0;
this.addedInZ = 0;
}
public double[] getNextPosition() {
double[] newPosition = new double[] {
startX + addedInX*xInterval,
startY + addedInY*yInterval,
startZ + addedInZ*zInterval
};
addedInZ++;
if (addedInZ >= numberInZ) {
addedInY++;
addedInZ = 0;
}
if (addedInY >= numberInY) {
addedInX++;
addedInY = 0;
}
return newPosition;
}
}

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2006, 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: RandomPositioner.java,v 1.1 2006/08/21 12:13:11 fros4943 Exp $
*/
package se.sics.cooja.positioners;
import se.sics.cooja.*;
/**
* Generates positions randomly distributed in a given interval.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Random positioning")
public class RandomPositioner extends Positioner {
double startX, endX, startY, endY, startZ, endZ;
/**
* Creates a random positioner.
* @param totalNumberOfMotes Total number of motes
* @param startX X interval start
* @param endX X interval end
* @param startY Y interval start
* @param endY Y interval end
* @param startZ Z interval start
* @param endZ Z interval end
*/
public RandomPositioner(int totalNumberOfMotes,
double startX, double endX,
double startY, double endY,
double startZ, double endZ) {
this.startX = startX;
this.endX = endX;
this.startY = startY;
this.endY = endY;
this.startZ = startZ;
this.endZ = endZ;
}
public double[] getNextPosition() {
return new double[] {
startX + Math.random()*(endX - startX),
startY + Math.random()*(endY - startY),
startZ + Math.random()*(endZ - startZ)
};
}
}

View file

@ -0,0 +1,89 @@
/*
* Copyright (c) 2006, 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: SilentRadioMedium.java,v 1.1 2006/08/21 12:13:14 fros4943 Exp $
*/
package se.sics.cooja.radiomediums;
import java.util.Collection;
import java.util.Observer;
import org.jdom.Element;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.*;
/**
* Silent radio. No data is ever transferred through this medium.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Silent Radio")
public class SilentRadioMedium extends RadioMedium {
public void registerMote(Mote mote, Simulation sim) {
// Do nothing
}
public void unregisterMote(Mote mote, Simulation sim) {
// Do nothing
}
public void registerRadioInterface(Radio radio, Position position, Simulation sim) {
// Do nothing
}
public void unregisterRadioInterface(Radio radio, Simulation sim) {
// Do nothing
}
public void addRadioMediumObserver(Observer observer) {
// Do nothing
}
public void deleteRadioMediumObserver(Observer observer) {
// Do nothing
}
public RadioConnection[] getLastTickConnections() {
return null;
}
public void setConnectionLogger(ConnectionLogger connection) {
// Do nothing
}
public Collection<Element> getConfigXML() {
return null;
}
public boolean setConfigXML(Collection<Element> configXML) {
return true;
}
}

View file

@ -0,0 +1,495 @@
/*
* Copyright (c) 2006, 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: StandardRadioMedium.java,v 1.1 2006/08/21 12:13:13 fros4943 Exp $
*/
package se.sics.cooja.radiomediums;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import org.jdom.Element;
import org.apache.log4j.Logger;
import se.sics.cooja.*;
import se.sics.cooja.interfaces.*;
import se.sics.cooja.plugins.Visualizer2D;
/**
* Standard radio medium has two different range parameters; one for
* transmitting and one for interfering other transmissions.
*
* Radio data are analysed when all registered motes have ticked once (this
* medium is registered as a tick observer). For every mote in transmission
* range of a sending mote, current listen status is changed from hearing
* nothing to hearing packet, or hearing packet to hearing noise. This way, if a
* mote hears two packets during one tick loop, it will receive none (noise). If
* a mote is in the interference range, the current listen status will be set to
* hears noise immediately.
*
* This radio medium registers a dynamic visual plugin: Radio Medium - Standard.
* Via this plugin ranges can be viewed and changed. Active connection may also
* be viewed.
*
*
* @author Fredrik Osterlind
*/
@ClassDescription("Standard Radio")
public class StandardRadioMedium extends RadioMedium {
private static Logger logger = Logger.getLogger(StandardRadioMedium.class);
private Vector<Position> registeredPositions = new Vector<Position>();
private Vector<Radio> registeredRadios = new Vector<Radio>();
private Vector<Position> sendingPositions = new Vector<Position>();
private Vector<Radio> sendingRadios = new Vector<Radio>();
private static RadioMedium myRadioMedium;
/**
* Visualizes radio traffic in the current radio medium. Allows a user to
* change transmission ranges.
*
* Sending motes are blue, receiving motes are green and motes that hear noise
* are painted red. Motes without radios are painted gray, and the rest are
* white.
*
* @author Fredrik Osterlind
*/
@ClassDescription("Radio Medium - Standard")
@VisPluginType(VisPluginType.SIM_PLUGIN)
public static class RadioMediumSimPlugin extends Visualizer2D {
private Mote selectedMote = null;
private JSpinner transmissionSpinner = null;
private JSpinner interferenceSpinner = null;
private Observer radioMediumObserver;
private class ChangeRangesMenuAction implements MoteMenuAction {
public boolean isEnabled(Mote mote) {
return true;
}
public String getDescription(Mote mote) {
return "Change transmission ranges";
}
public void doAction(Mote mote) {
transmissionSpinner.setVisible(true);
interferenceSpinner.setVisible(true);
repaint();
}
};
public RadioMediumSimPlugin(Simulation sim) {
super(sim);
setTitle("Radio Medium - Standard");
// Create spinners for changing ranges
SpinnerNumberModel transmissionModel = new SpinnerNumberModel();
transmissionModel.setValue(new Double(TRANSMITTING_RANGE));
transmissionModel.setStepSize(new Double(1.0)); // 1m
transmissionModel.setMinimum(new Double(0.0));
SpinnerNumberModel interferenceModel = new SpinnerNumberModel();
interferenceModel.setValue(new Double(INTERFERENCE_RANGE));
interferenceModel.setStepSize(new Double(1.0)); // 1m
interferenceModel.setMinimum(new Double(0.0));
transmissionSpinner = new JSpinner(transmissionModel);
interferenceSpinner = new JSpinner(interferenceModel);
((JSpinner.DefaultEditor) transmissionSpinner.getEditor()).getTextField()
.setColumns(5);
((JSpinner.DefaultEditor) interferenceSpinner.getEditor()).getTextField()
.setColumns(5);
transmissionSpinner.setToolTipText("Transmitting range");
interferenceSpinner.setToolTipText("Interference range");
transmissionSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
TRANSMITTING_RANGE = ((SpinnerNumberModel) transmissionSpinner
.getModel()).getNumber().doubleValue();
repaint();
}
});
interferenceSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
INTERFERENCE_RANGE = ((SpinnerNumberModel) interferenceSpinner
.getModel()).getNumber().doubleValue();
repaint();
}
});
getCurrentCanvas().add(transmissionSpinner);
getCurrentCanvas().add(interferenceSpinner);
transmissionSpinner.setVisible(false);
interferenceSpinner.setVisible(false);
// Add mouse listener for selecting motes
getCurrentCanvas().addMouseListener(new MouseListener() {
public void mouseExited(MouseEvent e) {
// Do nothing
}
public void mouseEntered(MouseEvent e) {
// Do nothing
}
public void mouseReleased(MouseEvent e) {
// Do nothing
}
public void mousePressed(MouseEvent e) {
Vector<Mote> clickedMotes = findMotesAtPosition(e.getX(), e.getY());
if (clickedMotes == null || clickedMotes.size() == 0) {
selectedMote = null;
transmissionSpinner.setVisible(false);
interferenceSpinner.setVisible(false);
repaint();
return;
}
// Select one of the clicked motes
if (clickedMotes.contains(selectedMote)) {
int pos = clickedMotes.indexOf(selectedMote);
if (pos < clickedMotes.size() - 1)
selectedMote = clickedMotes.get(pos + 1);
else
selectedMote = clickedMotes.firstElement();
} else {
selectedMote = clickedMotes.firstElement();
}
repaint();
}
public void mouseClicked(MouseEvent e) {
}
});
// Register change ranges action
addMoteMenuAction(new ChangeRangesMenuAction());
// Observe our own radio medium
myRadioMedium
.addRadioMediumObserver(radioMediumObserver = new Observer() {
public void update(Observable obs, Object obj) {
getCurrentCanvas().repaint();
}
});
}
public void closePlugin() {
super.closePlugin();
myRadioMedium.deleteRadioMediumObserver(radioMediumObserver);
}
public Color[] getColorOf(Mote mote) {
Radio moteRadio = mote.getInterfaces().getRadio();
if (moteRadio == null)
return new Color[]{Color.GRAY};
if (selectedMote != null && mote == selectedMote)
return new Color[]{Color.CYAN};
if (moteRadio.getSendState() == Radio.SENT_SOMETHING)
return new Color[]{Color.BLUE};
if (moteRadio.getListenState() == Radio.HEARS_PACKET)
return new Color[]{Color.GREEN};
if (moteRadio.getListenState() == Radio.HEARS_NOISE)
return new Color[]{Color.RED};
return new Color[]{Color.WHITE};
}
public void visualizeSimulation(Graphics g) {
// Paint transmission+interference areas for selected mote (if any)
if (selectedMote != null) {
Position motePos = selectedMote.getInterfaces().getPosition();
Point pixelCoord = transformPositionToPixel(motePos);
int x = pixelCoord.x;
int y = pixelCoord.y;
Point translatedZero = transformPositionToPixel(0.0, 0.0, 0.0);
Point translatedInterference = transformPositionToPixel(
INTERFERENCE_RANGE, INTERFERENCE_RANGE, 0.0);
Point translatedTransmission = transformPositionToPixel(
TRANSMITTING_RANGE, TRANSMITTING_RANGE, 0.0);
translatedInterference.x = Math.abs(translatedInterference.x
- translatedZero.x);
translatedInterference.y = Math.abs(translatedInterference.y
- translatedZero.y);
translatedTransmission.x = Math.abs(translatedTransmission.x
- translatedZero.x);
translatedTransmission.y = Math.abs(translatedTransmission.y
- translatedZero.y);
// Interference
g.setColor(Color.DARK_GRAY);
g.fillOval(x - translatedInterference.x, y - translatedInterference.y,
2 * translatedInterference.x, 2 * translatedInterference.y);
// Transmission
g.setColor(Color.GREEN);
g.fillOval(x - translatedTransmission.x, y - translatedTransmission.y,
2 * translatedTransmission.x, 2 * translatedTransmission.y);
}
// Let parent paint motes
super.visualizeSimulation(g);
// Paint last tick connections
if (myRadioMedium != null
&& myRadioMedium.getLastTickConnections() != null) {
for (RadioConnection conn : myRadioMedium.getLastTickConnections()) {
if (conn != null) {
Point sourcePoint = transformPositionToPixel(conn
.getSourcePosition());
// Paint destinations
for (Position destPos : conn.getDestinationPositons()) {
Point destPoint = transformPositionToPixel(destPos);
g.setColor(Color.BLACK);
g
.drawLine(sourcePoint.x, sourcePoint.y, destPoint.x,
destPoint.y);
}
}
}
}
}
}
public StandardRadioMedium() {
// Register this radio medium's plugins
GUI.currentGUI.registerTemporaryPlugin(RadioMediumSimPlugin.class);
myRadioMedium = this;
}
private boolean isTickObserver = false;
private static double TRANSMITTING_RANGE = 20; // 20m
private static double INTERFERENCE_RANGE = 40; // 40m
private static boolean RECEIVE_MY_OWN_PACKETS = false;
private static boolean DETECT_MY_OWN_PACKETS = true;
private class RadioMediumObservable extends Observable {
private void transferredData() {
setChanged();
notifyObservers();
}
}
private RadioMediumObservable radioMediumObservable = new RadioMediumObservable();
private RadioConnection[] lastTickConnections = null;
private ConnectionLogger myLogger = null;
private Observer radioDataObserver = new Observer() {
public void update(Observable radio, Object obj) {
if (((Radio) radio).getSendState() == Radio.SENT_SOMETHING) {
if (!sendingPositions.contains((Position) obj)) {
sendingPositions.add((Position) obj);
sendingRadios.add((Radio) radio);
}
}
}
};
private Observer tickObserver = new Observer() {
public void update(Observable obs, Object obj) {
RadioConnection[] oldTickConnections = lastTickConnections;
lastTickConnections = null;
if (sendingPositions.size() > 0) {
final int numberSending = sendingPositions.size();
lastTickConnections = new RadioConnection[numberSending];
// Loop through all sending radios
for (int sendNr = 0; sendNr < numberSending; sendNr++) {
Radio sendingRadio = sendingRadios.get(sendNr);
byte[] dataToSend = sendingRadio.getLastPacketSent();
lastTickConnections[sendNr] = new RadioConnection();
lastTickConnections[sendNr].setSource(sendingRadios.get(sendNr),
sendingPositions.get(sendNr), dataToSend);
// Set sending radio unable to receive any more data
if (RECEIVE_MY_OWN_PACKETS) {
sendingRadio.receivePacket(dataToSend);
sendingRadio.advanceListenState();
} else if (DETECT_MY_OWN_PACKETS) {
sendingRadio.setListenState(Radio.HEARS_NOISE);
}
// Loop through all radios that are listening
for (int listenNr = 0; listenNr < registeredPositions.size(); listenNr++) {
// If not the sending radio..
if (sendingRadios.get(sendNr) != registeredRadios.get(listenNr)) {
Radio listeningRadio = registeredRadios.get(listenNr);
double distance = sendingPositions.get(sendNr).getDistanceTo(
registeredPositions.get(listenNr));
if (distance <= TRANSMITTING_RANGE) {
lastTickConnections[sendNr].addDestination(registeredRadios
.get(listenNr), registeredPositions.get(listenNr),
dataToSend);
// If close enough to transmit ok..
if (listeningRadio.getListenState() == Radio.HEARS_PACKET) {
// .. but listening radio already received a packet
listeningRadio.advanceListenState();
} else if (listeningRadio.getListenState() == Radio.HEARS_NOISE) {
// .. but listening radio heard interference
listeningRadio.advanceListenState();
} else {
// .. send packet
listeningRadio.receivePacket(dataToSend);
listeningRadio.setListenState(Radio.HEARS_PACKET);
}
} else if (distance <= INTERFERENCE_RANGE) {
// If close enough to sabotage other transmissions..
if (listeningRadio.getListenState() == Radio.HEARS_PACKET) {
// .. and listening radio already received a packet
listeningRadio.advanceListenState();
} else {
// .. and listening radio has done nothing sofar
listeningRadio.setListenState(Radio.HEARS_NOISE);
}
}
// else too far away
}
}
}
sendingPositions.clear();
sendingRadios.clear();
if (myLogger != null) {
for (RadioConnection conn : lastTickConnections)
myLogger.logConnection(conn);
}
}
if (lastTickConnections != oldTickConnections)
radioMediumObservable.transferredData();
}
};
public void registerMote(Mote mote, Simulation sim) {
registerRadioInterface(mote.getInterfaces().getRadio(), mote
.getInterfaces().getPosition(), sim);
}
public void unregisterMote(Mote mote, Simulation sim) {
unregisterRadioInterface(mote.getInterfaces().getRadio(), sim);
}
public void registerRadioInterface(Radio radio, Position position,
Simulation sim) {
if (radio != null && position != null) {
if (!isTickObserver) {
sim.addTickObserver(tickObserver);
isTickObserver = true;
}
registeredPositions.add(position);
registeredRadios.add(radio);
radio.addObserver(radioDataObserver);
} // else logger.warn("Standard Radio Medium not registering mote");
}
public void unregisterRadioInterface(Radio radio, Simulation sim) {
for (int i = 0; i < registeredRadios.size(); i++) {
if (registeredRadios.get(i).equals(radio)) {
registeredRadios.remove(i);
registeredPositions.remove(i);
radio.deleteObserver(radioDataObserver);
return;
}
}
logger.warn("Could not find radio: " + radio + " to unregister");
}
public void addRadioMediumObserver(Observer observer) {
radioMediumObservable.addObserver(observer);
}
public void deleteRadioMediumObserver(Observer observer) {
radioMediumObservable.deleteObserver(observer);
}
public RadioConnection[] getLastTickConnections() {
return lastTickConnections;
}
public void setConnectionLogger(ConnectionLogger connection) {
myLogger = connection;
}
public Collection<Element> getConfigXML() {
Vector<Element> config = new Vector<Element>();
Element element;
// Transmitting range
element = new Element("transmitting_range");
element.setText(Double.toString(TRANSMITTING_RANGE));
config.add(element);
// Interference range
element = new Element("interference_range");
element.setText(Double.toString(INTERFERENCE_RANGE));
config.add(element);
return config;
}
public boolean setConfigXML(Collection<Element> configXML) {
for (Element element : configXML) {
if (element.getName().equals("transmitting_range")) {
TRANSMITTING_RANGE = Double.parseDouble(element.getText());
}
if (element.getName().equals("interference_range")) {
INTERFERENCE_RANGE = Double.parseDouble(element.getText());
}
}
return true;
}
}