added test files for future support of mantis os.
not working yet due to threading vs jni problems
This commit is contained in:
parent
38fe078d38
commit
d6a2211918
5 changed files with 1614 additions and 1 deletions
|
@ -29,9 +29,10 @@ se.sics.cooja.contikimote.interfaces.ContikiCFS.CONSUMPTION_PER_READ_CHAR_mQ = 1
|
||||||
|
|
||||||
se.sics.cooja.contikimote.ContikiMoteType.MOTE_INTERFACES = se.sics.cooja.interfaces.Position se.sics.cooja.interfaces.Battery se.sics.cooja.contikimote.interfaces.ContikiVib se.sics.cooja.contikimote.interfaces.ContikiMoteID se.sics.cooja.contikimote.interfaces.ContikiRS232 se.sics.cooja.contikimote.interfaces.ContikiBeeper se.sics.cooja.contikimote.interfaces.ContikiIPAddress se.sics.cooja.contikimote.interfaces.ContikiRadio se.sics.cooja.contikimote.interfaces.ContikiButton se.sics.cooja.contikimote.interfaces.ContikiPIR se.sics.cooja.contikimote.interfaces.ContikiClock se.sics.cooja.contikimote.interfaces.ContikiLED se.sics.cooja.contikimote.interfaces.ContikiLog se.sics.cooja.contikimote.interfaces.ContikiCFS
|
se.sics.cooja.contikimote.ContikiMoteType.MOTE_INTERFACES = se.sics.cooja.interfaces.Position se.sics.cooja.interfaces.Battery se.sics.cooja.contikimote.interfaces.ContikiVib se.sics.cooja.contikimote.interfaces.ContikiMoteID se.sics.cooja.contikimote.interfaces.ContikiRS232 se.sics.cooja.contikimote.interfaces.ContikiBeeper se.sics.cooja.contikimote.interfaces.ContikiIPAddress se.sics.cooja.contikimote.interfaces.ContikiRadio se.sics.cooja.contikimote.interfaces.ContikiButton se.sics.cooja.contikimote.interfaces.ContikiPIR se.sics.cooja.contikimote.interfaces.ContikiClock se.sics.cooja.contikimote.interfaces.ContikiLED se.sics.cooja.contikimote.interfaces.ContikiLog se.sics.cooja.contikimote.interfaces.ContikiCFS
|
||||||
se.sics.cooja.contikimote.ContikiMoteType.C_SOURCES =
|
se.sics.cooja.contikimote.ContikiMoteType.C_SOURCES =
|
||||||
se.sics.cooja.GUI.MOTETYPES = se.sics.cooja.contikimote.ContikiMoteType se.sics.cooja.motes.DummyMoteType
|
se.sics.cooja.GUI.MOTETYPES = se.sics.cooja.contikimote.ContikiMoteType se.sics.cooja.motes.DummyMoteType se.sics.cooja.mantismote.MantisMoteType
|
||||||
se.sics.cooja.GUI.PLUGINS = se.sics.cooja.plugins.VisState se.sics.cooja.plugins.VisBattery se.sics.cooja.plugins.VisTraffic se.sics.cooja.plugins.LogListener se.sics.cooja.plugins.MoteInformation se.sics.cooja.plugins.MoteInterfaceViewer se.sics.cooja.plugins.VariableWatcher
|
se.sics.cooja.GUI.PLUGINS = se.sics.cooja.plugins.VisState se.sics.cooja.plugins.VisBattery se.sics.cooja.plugins.VisTraffic se.sics.cooja.plugins.LogListener se.sics.cooja.plugins.MoteInformation se.sics.cooja.plugins.MoteInterfaceViewer se.sics.cooja.plugins.VariableWatcher
|
||||||
se.sics.cooja.GUI.IP_DISTRIBUTORS = se.sics.cooja.ipdistributors.RandomIPDistributor se.sics.cooja.ipdistributors.SpatialIPDistributor se.sics.cooja.ipdistributors.IdIPDistributor
|
se.sics.cooja.GUI.IP_DISTRIBUTORS = se.sics.cooja.ipdistributors.RandomIPDistributor se.sics.cooja.ipdistributors.SpatialIPDistributor se.sics.cooja.ipdistributors.IdIPDistributor
|
||||||
se.sics.cooja.GUI.POSITIONERS = se.sics.cooja.positioners.RandomPositioner se.sics.cooja.positioners.LinearPositioner se.sics.cooja.positioners.EllipsePositioner
|
se.sics.cooja.GUI.POSITIONERS = se.sics.cooja.positioners.RandomPositioner se.sics.cooja.positioners.LinearPositioner se.sics.cooja.positioners.EllipsePositioner
|
||||||
se.sics.cooja.GUI.RADIOMEDIUMS = se.sics.cooja.radiomediums.StandardRadioMedium se.sics.cooja.radiomediums.SilentRadioMedium
|
se.sics.cooja.GUI.RADIOMEDIUMS = se.sics.cooja.radiomediums.StandardRadioMedium se.sics.cooja.radiomediums.SilentRadioMedium
|
||||||
|
|
||||||
|
se.sics.cooja.mantismote.MantisMoteType.MOTE_INTERFACES = se.sics.cooja.interfaces.Position
|
||||||
|
|
178
tools/cooja/config/mantis_template.c
Normal file
178
tools/cooja/config/mantis_template.c
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* 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: mantis_template.c,v 1.1 2006/11/09 19:32:53 fros4943 Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* C code template for generating Mantis source code files from COOJA
|
||||||
|
* Simulator. This file should not be compiled directly.
|
||||||
|
* \author
|
||||||
|
* Fredrik Osterlind <fros@sics.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include "mos.h"
|
||||||
|
#include "sem.h"
|
||||||
|
#include "msched.h"
|
||||||
|
|
||||||
|
extern int main(); /* in mantis/src/mos/sys/main.c */
|
||||||
|
extern uint32_t cooja_time; /* in mantis/src/mos/sys/main.c */
|
||||||
|
extern pthread_cond_t cooja_cv; /* in mantis/src/mos/sys/main.c */
|
||||||
|
extern mos_thread_t threads[MAX_THREADS]; /* in mantis/src/mos/sys/main.c */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* referenceVar is used for comparing absolute and process relative memory.
|
||||||
|
* (this must not be static due to memory locations)
|
||||||
|
*/
|
||||||
|
int referenceVar;
|
||||||
|
|
||||||
|
int dataVar = 1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* \brief Initialize a mote by starting processes etc.
|
||||||
|
*
|
||||||
|
* This function initializes a mote by starting certain
|
||||||
|
* processes and setting up the environment.
|
||||||
|
*
|
||||||
|
* This is a JNI function and should only be called via the
|
||||||
|
* responsible Java part (MoteType.java).
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_se_sics_cooja_corecomm_[CLASS_NAME]_init(JNIEnv *env, jobject obj)
|
||||||
|
{
|
||||||
|
main();
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* \brief Get a segment from the process memory.
|
||||||
|
* \param start Start address of segment
|
||||||
|
* \param length Size of memory segment
|
||||||
|
* \return Java byte array containing a copy of memory segment.
|
||||||
|
*
|
||||||
|
* Fetches a memory segment from the process memory starting at
|
||||||
|
* (start), with size (length). This function does not perform
|
||||||
|
* ANY error checking, and the process may crash if addresses are
|
||||||
|
* not available/readable.
|
||||||
|
*
|
||||||
|
* This is a JNI function and should only be called via the
|
||||||
|
* responsible Java part (MoteType.java).
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_se_sics_cooja_corecomm_[CLASS_NAME]_getMemory(JNIEnv *env, jobject obj, jint start, jint length, jbyteArray mem_arr)
|
||||||
|
{
|
||||||
|
(*env)->SetByteArrayRegion(env, mem_arr, 0, (size_t) length, (jbyte *) start);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* \brief Replace a segment of the process memory with given byte array.
|
||||||
|
* \param start Start address of segment
|
||||||
|
* \param length Size of memory segment
|
||||||
|
* \param mem_arr Byte array contaning new memory
|
||||||
|
*
|
||||||
|
* Replaces a process memory segment with given byte array.
|
||||||
|
* This function does not perform ANY error checking, and the
|
||||||
|
* process may crash if addresses are not available/writable.
|
||||||
|
*
|
||||||
|
* This is a JNI function and should only be called via the
|
||||||
|
* responsible Java part (MoteType.java).
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_se_sics_cooja_corecomm_[CLASS_NAME]_setMemory(JNIEnv *env, jobject obj, jint start, jint length, jbyteArray mem_arr)
|
||||||
|
{
|
||||||
|
jbyte *mem = (*env)->GetByteArrayElements(env, mem_arr, 0);
|
||||||
|
memcpy((void *) start, mem, length);
|
||||||
|
(*env)->ReleaseByteArrayElements(env, mem_arr, mem, 0);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* \brief Let mote execute one "block" of code (tick mote).
|
||||||
|
*
|
||||||
|
* This is a JNI function and should only be called via the
|
||||||
|
* responsible Java part (MoteType.java).
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_se_sics_cooja_corecomm_[CLASS_NAME]_tick(JNIEnv *env, jobject obj)
|
||||||
|
{
|
||||||
|
int readyexist = 0;
|
||||||
|
|
||||||
|
/* Ugly hack, setting all ready threads to BLOCKED just to discover which ones wake up */
|
||||||
|
for(i=0; i<MAX_THREADS; i++) {
|
||||||
|
if (threads[i].state == READY) {
|
||||||
|
threads[i].state = BLOCKED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cooja_time += 1; // increase time
|
||||||
|
//printf("CORE> tick, time is now %i\n", cooja_time);
|
||||||
|
|
||||||
|
/* Signal all threads to start working again */
|
||||||
|
for(i=0; i<MAX_THREADS; i++) {
|
||||||
|
if (threads[i].state == BLOCKED) {
|
||||||
|
mos_thread_resume(&threads[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until all threads are blocked again. ??!?!!
|
||||||
|
* For now we just assume all threads will be done within 1ms. */
|
||||||
|
do {
|
||||||
|
readyexist=0;
|
||||||
|
for(i=0; i<MAX_THREADS; i++) {
|
||||||
|
if (threads[i].state == READY) {
|
||||||
|
readyexist = 1;
|
||||||
|
//printf("waiting until thread finished...: %p\n", &threads[i]);
|
||||||
|
//fflush(stdout);
|
||||||
|
usleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (readyexist);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* \brief Get the absolute memory address of a special variable.
|
||||||
|
* \return Absolute memory address.
|
||||||
|
*
|
||||||
|
* Returns the absolute memory address of a special variable
|
||||||
|
* "referenceVar". By comparing this address with the relative
|
||||||
|
* address (from the map file) for referenceVar, an runtime offset
|
||||||
|
* can be calculated.
|
||||||
|
*
|
||||||
|
* This is a JNI function and should only be called via the
|
||||||
|
* responsible Java part (MoteType.java).
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL
|
||||||
|
Java_se_sics_cooja_corecomm_[CLASS_NAME]_getReferenceAbsAddr(JNIEnv *env, jobject obj)
|
||||||
|
{
|
||||||
|
return (jint) &referenceVar;
|
||||||
|
}
|
234
tools/cooja/java/se/sics/cooja/mantismote/MantisMote.java
Normal file
234
tools/cooja/java/se/sics/cooja/mantismote/MantisMote.java
Normal 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: MantisMote.java,v 1.1 2006/11/09 19:31:15 fros4943 Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.sics.cooja.mantismote;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import se.sics.cooja.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Mantis mote simulation works the same way as the native Contiki mote. The
|
||||||
|
* Mantis OS is compiled and linked together with a JNI-enabled object file
|
||||||
|
* generated from COOJA.
|
||||||
|
*
|
||||||
|
* Each tick the all interfaces are polled, the memory is copied and the tick is
|
||||||
|
* forwarded to the core Mantis system.
|
||||||
|
*
|
||||||
|
* A Mantis mote is always active.
|
||||||
|
*
|
||||||
|
* @author Fredrik Osterlind
|
||||||
|
*/
|
||||||
|
public class MantisMote implements Mote {
|
||||||
|
private static Logger logger = Logger.getLogger(MantisMote.class);
|
||||||
|
|
||||||
|
private MantisMoteType myType = null;
|
||||||
|
|
||||||
|
private SectionMoteMemory myMemory = null;
|
||||||
|
|
||||||
|
private MoteInterfaceHandler myInterfaceHandler = null;
|
||||||
|
|
||||||
|
private Simulation mySimulation = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new uninitialized Mantis mote.
|
||||||
|
*
|
||||||
|
* This mote needs at least a type, a memory, a mote interface handler and to
|
||||||
|
* be connected to a simulation.
|
||||||
|
*/
|
||||||
|
public MantisMote() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 MantisMote(MantisMoteType moteType, Simulation sim) {
|
||||||
|
this.mySimulation = sim;
|
||||||
|
this.myType = moteType;
|
||||||
|
this.myMemory = moteType.createInitialMemory();
|
||||||
|
this.myInterfaceHandler = new MoteInterfaceHandler((Mote) this, moteType
|
||||||
|
.getMoteInterfaces());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(State newState) {
|
||||||
|
logger.fatal("Mantis motes can't change state");
|
||||||
|
}
|
||||||
|
|
||||||
|
public State getState() {
|
||||||
|
return 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 = (MantisMoteType) type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Simulation getSimulation() {
|
||||||
|
return mySimulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSimulation(Simulation simulation) {
|
||||||
|
mySimulation = simulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick(int simTime) {
|
||||||
|
// Poll all interfaces before tick
|
||||||
|
myInterfaceHandler.doActiveActionsBeforeTick();
|
||||||
|
myInterfaceHandler.doPassiveActionsBeforeTick();
|
||||||
|
|
||||||
|
// Copy memory to core
|
||||||
|
myType.setCoreMemory(myMemory);
|
||||||
|
|
||||||
|
// Tick node
|
||||||
|
myType.tick();
|
||||||
|
|
||||||
|
// Fetch new updated memory from core
|
||||||
|
myType.getCoreMemory(myMemory);
|
||||||
|
|
||||||
|
// Poll all interfaces after tick
|
||||||
|
myInterfaceHandler.doActiveActionsBeforeTick();
|
||||||
|
myInterfaceHandler.doPassiveActionsBeforeTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
mySimulation = simulation;
|
||||||
|
|
||||||
|
for (Element element : configXML) {
|
||||||
|
String name = element.getName();
|
||||||
|
|
||||||
|
if (name.equals("motetype_identifier")) {
|
||||||
|
myType = (MantisMoteType) 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);
|
||||||
|
if (moteInterface != null)
|
||||||
|
moteInterface.setConfigXML(element.getChildren());
|
||||||
|
else
|
||||||
|
logger
|
||||||
|
.warn("Can't restore configuration for non-existing interface: "
|
||||||
|
+ moteInterfaceClass.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
if (getInterfaces().getMoteID() != null) {
|
||||||
|
return "Mantis Mote, ID=" + getInterfaces().getMoteID().getMoteID();
|
||||||
|
} else
|
||||||
|
return "Mantis Mote, ID=null";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
407
tools/cooja/java/se/sics/cooja/mantismote/MantisMoteType.java
Normal file
407
tools/cooja/java/se/sics/cooja/mantismote/MantisMoteType.java
Normal file
|
@ -0,0 +1,407 @@
|
||||||
|
/*
|
||||||
|
* 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: MantisMoteType.java,v 1.1 2006/11/09 19:31:15 fros4943 Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.sics.cooja.mantismote;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import javax.swing.Box;
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.jdom.Element;
|
||||||
|
|
||||||
|
import se.sics.cooja.*;
|
||||||
|
import se.sics.cooja.contikimote.ContikiMoteType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Mantis mote type holds the native library used to communicate with an
|
||||||
|
* underlying Mantis system. All communication with that system should always
|
||||||
|
* pass through this mote type.
|
||||||
|
* <p>
|
||||||
|
* All core communication with the Mantis mote should be via this class. When a
|
||||||
|
* mote type is created it allocates a CoreComm to be used with this type.
|
||||||
|
* <p>
|
||||||
|
* When a new mote type is created an initialization function is run on the
|
||||||
|
* Mantis 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("Mantis Mote Type")
|
||||||
|
public class MantisMoteType implements MoteType {
|
||||||
|
private static Logger logger = Logger.getLogger(MantisMoteType.class);
|
||||||
|
private Simulation mySimulation = null;
|
||||||
|
|
||||||
|
// Mote type specific information
|
||||||
|
private String myIdentifier = null;
|
||||||
|
private String myDescription = null;
|
||||||
|
private String myObjectFilename = null;
|
||||||
|
private SectionMoteMemory myInitialMemory = null;
|
||||||
|
private Vector<Class<? extends MoteInterface>> moteInterfaceClasses = 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();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new uninitialized Mantis mote type. This mote type's doInit
|
||||||
|
* method must be called and succeed before it can be used.
|
||||||
|
*/
|
||||||
|
public MantisMoteType() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new initialized Mantis mote type. The given library file is
|
||||||
|
* loaded by the first available CoreComm. Each mote generated from this mote
|
||||||
|
* type will have the interfaces specified in the given mote interface class
|
||||||
|
* list.
|
||||||
|
*
|
||||||
|
* @param libFile
|
||||||
|
* Library file to load
|
||||||
|
* @param objFile
|
||||||
|
* Object file
|
||||||
|
* @param moteInterfaceClasses
|
||||||
|
* List of mote interfaces
|
||||||
|
*/
|
||||||
|
public MantisMoteType(File libFile, File objFile,
|
||||||
|
Vector<Class<? extends MoteInterface>> moteInterfaceClasses) {
|
||||||
|
if (!doInit(libFile, objFile, moteInterfaceClasses))
|
||||||
|
logger.fatal("Mantis mote type creation failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 Mantis library file,
|
||||||
|
* creates variable name to address mappings and finally creates the Mantis
|
||||||
|
* mote initial memory.
|
||||||
|
*
|
||||||
|
* @param libFile Library file
|
||||||
|
* @param objFile Object file
|
||||||
|
* @param moteInterfaceClasses Mote interface classes
|
||||||
|
* @return True if initialization ok, false otherwise
|
||||||
|
*/
|
||||||
|
protected boolean doInit(File libFile, File objFile,
|
||||||
|
Vector<Class<? extends MoteInterface>> moteInterfaceClasses) {
|
||||||
|
myObjectFilename = objFile.getAbsolutePath();
|
||||||
|
myIdentifier = libFile.getName();
|
||||||
|
myDescription = libFile.getAbsolutePath();
|
||||||
|
|
||||||
|
// Allocate core communicator class
|
||||||
|
libraryClassName = CoreComm.getAvailableClassName();
|
||||||
|
myCoreComm = CoreComm.createCoreComm(libraryClassName, libFile);
|
||||||
|
|
||||||
|
// Parse variable name to addresses mappings using nm
|
||||||
|
varAddresses.clear();
|
||||||
|
Vector<String> nmData = ContikiMoteType.loadNmData(libFile);
|
||||||
|
if (nmData == null || !ContikiMoteType.parseNmData(nmData, varAddresses)) {
|
||||||
|
logger.fatal("Nm response parsing failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Bug. Both sections sizes must be > 0!
|
||||||
|
|
||||||
|
// Parse section offsets and sizes using objdump
|
||||||
|
Vector<String> objdumpData = ContikiMoteType.loadObjdumpData(libFile);
|
||||||
|
int relDataSectionAddr = -1;
|
||||||
|
int dataSectionSize = -1;
|
||||||
|
int relBssSectionAddr = -1;
|
||||||
|
int bssSectionSize = -1;
|
||||||
|
String dataRegExp = "^[ \t]*[0-9]*[ \t]*.data[ \t]*([0-9A-Fa-f]*)[ \t]*[0-9A-Fa-f]*[ \t]*([0-9A-Fa-f]*)[ \t]*[0-9A-Fa-f]*[ \t]*";
|
||||||
|
String bssRegExp = "^[ \t]*[0-9]*[ \t]*.bss[ \t]*([0-9A-Fa-f]*)[ \t]*[0-9A-Fa-f]*[ \t]*([0-9A-Fa-f]*)[ \t]*[0-9A-Fa-f]*[ \t]*";
|
||||||
|
Pattern dataPattern = Pattern.compile(dataRegExp);
|
||||||
|
Pattern bssPattern = Pattern.compile(bssRegExp);
|
||||||
|
Matcher matcher;
|
||||||
|
for (String objdumpLine: objdumpData) {
|
||||||
|
matcher = dataPattern.matcher(objdumpLine);
|
||||||
|
if (matcher.find()) {
|
||||||
|
String size = matcher.group(1);
|
||||||
|
String offset = matcher.group(2);
|
||||||
|
dataSectionSize = Integer.parseInt(size, 16);
|
||||||
|
relDataSectionAddr = Integer.parseInt(offset, 16);
|
||||||
|
}
|
||||||
|
matcher = bssPattern.matcher(objdumpLine);
|
||||||
|
if (matcher.find()) {
|
||||||
|
String size = matcher.group(1);
|
||||||
|
String offset = matcher.group(2);
|
||||||
|
bssSectionSize = Integer.parseInt(size, 16);
|
||||||
|
relBssSectionAddr = Integer.parseInt(offset, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relDataSectionAddr == -1) {
|
||||||
|
logger.fatal("Data section address parsing failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (dataSectionSize == -1) {
|
||||||
|
logger.fatal("Data section size parsing failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (relBssSectionAddr == -1) {
|
||||||
|
logger.fatal("BSS section address parsing failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bssSectionSize == -1) {
|
||||||
|
logger.fatal("BSS section size parsing failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get offset between relative and absolute addresses
|
||||||
|
offsetRelToAbs = myCoreComm.getReferenceAbsAddr() - (Integer) varAddresses.get("referenceVar");
|
||||||
|
|
||||||
|
// Read initial memory from Mantis system
|
||||||
|
byte[] initialDataSection = new byte[dataSectionSize];
|
||||||
|
myCoreComm.getMemory(relDataSectionAddr + offsetRelToAbs, dataSectionSize, initialDataSection);
|
||||||
|
byte[] initialBssSection = new byte[bssSectionSize];
|
||||||
|
myCoreComm.getMemory(relBssSectionAddr + offsetRelToAbs, bssSectionSize, initialBssSection);
|
||||||
|
|
||||||
|
// Store initial memory for later use
|
||||||
|
myInitialMemory = new SectionMoteMemory(varAddresses);
|
||||||
|
myInitialMemory.setMemorySegment(relDataSectionAddr, initialDataSection);
|
||||||
|
myInitialMemory.setMemorySegment(relBssSectionAddr, initialBssSection);
|
||||||
|
|
||||||
|
this.moteInterfaceClasses = moteInterfaceClasses;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 myInitialMemory.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ticks the currently loaded mote. This should not be used directly, but
|
||||||
|
* rather via MantisMote.tick().
|
||||||
|
*/
|
||||||
|
public void tick() {
|
||||||
|
myCoreComm.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy core memory to given memory. This should not be used directly, but
|
||||||
|
* instead via MantisMote.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);
|
||||||
|
byte[] data = mem.getDataOfSection(i);
|
||||||
|
|
||||||
|
getCoreMemory(startAddr + offsetRelToAbs,
|
||||||
|
size, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy given memory to the Mantis system. This should not be used directly,
|
||||||
|
* but instead via MantisMote.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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getCoreMemory(int start, int length, byte[] data) {
|
||||||
|
myCoreComm.getMemory(start, length, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCoreMemory(int start, int length, byte[] mem) {
|
||||||
|
myCoreComm.setMemory(start, length, mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all mote interfaces of this mote type
|
||||||
|
*
|
||||||
|
* @return All mote interfaces
|
||||||
|
*/
|
||||||
|
public Vector<Class<? extends MoteInterface>> getMoteInterfaces() {
|
||||||
|
return moteInterfaceClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return myDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
myDescription = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdentifier() {
|
||||||
|
return myIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdentifier(String identifier) {
|
||||||
|
myIdentifier = identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getObjectFilename() {
|
||||||
|
return myObjectFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setObjectFilename(String objectFilename) {
|
||||||
|
myObjectFilename = objectFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(myIdentifier);
|
||||||
|
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(myDescription);
|
||||||
|
smallPane.add(BorderLayout.EAST, label);
|
||||||
|
panel.add(smallPane);
|
||||||
|
|
||||||
|
// Object file
|
||||||
|
smallPane = new JPanel(new BorderLayout());
|
||||||
|
label = new JLabel("Object file");
|
||||||
|
smallPane.add(BorderLayout.WEST, label);
|
||||||
|
label = new JLabel(myObjectFilename);
|
||||||
|
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);
|
||||||
|
|
||||||
|
panel.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlatformConfig getConfig() {
|
||||||
|
logger.debug("MantisMoteType::getConfig");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mote generateMote(Simulation simulation) {
|
||||||
|
return new MantisMote(this, mySimulation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean configureAndInit(JFrame parentFrame, Simulation simulation) {
|
||||||
|
return MantisMoteTypeDialog.showDialog(parentFrame, simulation, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Object file
|
||||||
|
element = new Element("objectfile");
|
||||||
|
element.setText(getObjectFilename());
|
||||||
|
config.add(element);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setConfigXML(Simulation simulation,
|
||||||
|
Collection<Element> configXML) {
|
||||||
|
mySimulation = simulation;
|
||||||
|
|
||||||
|
for (Element element : configXML) {
|
||||||
|
String name = element.getName();
|
||||||
|
|
||||||
|
if (name.equals("identifier")) {
|
||||||
|
myIdentifier = element.getText();
|
||||||
|
} else if (name.equals("description")) {
|
||||||
|
myDescription = element.getText();
|
||||||
|
} else if (name.equals("objectfile")) {
|
||||||
|
myObjectFilename = element.getText();
|
||||||
|
} else {
|
||||||
|
logger.fatal("Unrecognized entry in loaded configuration: " + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean createdOK = configureAndInit(GUI.frame, simulation);
|
||||||
|
return createdOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,793 @@
|
||||||
|
/*
|
||||||
|
* 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: MantisMoteTypeDialog.java,v 1.1 2006/11/09 19:31:14 fros4943 Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.sics.cooja.mantismote;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import se.sics.cooja.*;
|
||||||
|
import se.sics.cooja.dialogs.MessageList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dialog for configuring Mantis mote types and compiling KMantis mote type
|
||||||
|
* libraries.
|
||||||
|
*
|
||||||
|
* The dialog takes a Mantis mote type as argument and pre-selects the values
|
||||||
|
* already set in that mote type before showing the dialog. Any changes made to
|
||||||
|
* the settings are written to the mote type if the compilation is successful
|
||||||
|
* and the user presses OK.
|
||||||
|
*
|
||||||
|
* This dialog uses external tools to scan for sources and compile libraries.
|
||||||
|
*
|
||||||
|
* @author Fredrik Osterlind
|
||||||
|
*/
|
||||||
|
public class MantisMoteTypeDialog extends JDialog {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static Logger logger = Logger.getLogger(MantisMoteTypeDialog.class);
|
||||||
|
|
||||||
|
private MoteTypeEventHandler myEventHandler = new MoteTypeEventHandler();
|
||||||
|
private Thread compilationThread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suggested mote type identifier prefix
|
||||||
|
*/
|
||||||
|
public static final String ID_PREFIX = "mtype";
|
||||||
|
|
||||||
|
private final static int LABEL_WIDTH = 170;
|
||||||
|
private final static int LABEL_HEIGHT = 15;
|
||||||
|
|
||||||
|
private MantisMoteType myMoteType = null;
|
||||||
|
|
||||||
|
private JTextField textID, textOutputFiles, textDescription, textMantisBinary;
|
||||||
|
private JButton createButton, compileButton;
|
||||||
|
|
||||||
|
private File objFile = null;
|
||||||
|
private File workingDir = null;
|
||||||
|
private File libFile = null;
|
||||||
|
private File srcFile = null;
|
||||||
|
|
||||||
|
private Vector<Class<? extends MoteInterface>> moteInterfaceClasses = null;
|
||||||
|
|
||||||
|
private boolean settingsOK = false; // Do all settings seem correct?
|
||||||
|
private boolean compilationSucceded = false; // Did compilation succeed?
|
||||||
|
private boolean libraryCreatedOK = false; // Was a library created?
|
||||||
|
|
||||||
|
private Vector<MoteType> allOtherTypes = null; // Used to check for conflicting parameters
|
||||||
|
|
||||||
|
private MantisMoteTypeDialog myDialog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a dialog for configuring a Mantis mote type.
|
||||||
|
*
|
||||||
|
* @param parentFrame
|
||||||
|
* Parent frame for dialog
|
||||||
|
* @param simulation
|
||||||
|
* Simulation holding (or that will hold) mote type
|
||||||
|
* @param moteTypeToConfigure
|
||||||
|
* Mote type to configure
|
||||||
|
* @return True if mote type configuration succeded and library is ready to be loaded
|
||||||
|
*/
|
||||||
|
public static boolean showDialog(Frame parentFrame, Simulation simulation,
|
||||||
|
MantisMoteType moteTypeToConfigure) {
|
||||||
|
|
||||||
|
final MantisMoteTypeDialog myDialog = new MantisMoteTypeDialog(
|
||||||
|
parentFrame);
|
||||||
|
|
||||||
|
myDialog.myMoteType = moteTypeToConfigure;
|
||||||
|
myDialog.allOtherTypes = simulation.getMoteTypes();
|
||||||
|
|
||||||
|
// Set identifier of mote type
|
||||||
|
if (moteTypeToConfigure.getIdentifier() != null) {
|
||||||
|
// Identifier already preset, assuming recompilation of mote type library
|
||||||
|
// Use preset identifier (read-only)
|
||||||
|
myDialog.textID.setText(moteTypeToConfigure.getIdentifier());
|
||||||
|
myDialog.textID.setEditable(false);
|
||||||
|
myDialog.textID.setEnabled(false);
|
||||||
|
|
||||||
|
// Change title to indicate this is a recompilation
|
||||||
|
myDialog.setTitle("Recompile Mote Type");
|
||||||
|
} else {
|
||||||
|
// Suggest new identifier
|
||||||
|
int counter = 0;
|
||||||
|
String testIdentifier = "";
|
||||||
|
boolean identifierOK = false;
|
||||||
|
while (!identifierOK) {
|
||||||
|
counter++;
|
||||||
|
testIdentifier = ID_PREFIX + counter;
|
||||||
|
identifierOK = true;
|
||||||
|
|
||||||
|
// Check if identifier is already used by some other type
|
||||||
|
for (MoteType existingMoteType : myDialog.allOtherTypes) {
|
||||||
|
if (existingMoteType != myDialog.myMoteType
|
||||||
|
&& existingMoteType.getIdentifier().equals(testIdentifier)) {
|
||||||
|
identifierOK = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
myDialog.textID.setText(testIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set preset description of mote type
|
||||||
|
if (moteTypeToConfigure.getDescription() != null) {
|
||||||
|
myDialog.textDescription.setText(moteTypeToConfigure.getDescription());
|
||||||
|
} else {
|
||||||
|
myDialog.textDescription.setText("mantis type, id=" + myDialog.textID.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set preset object file of mote type
|
||||||
|
if (moteTypeToConfigure.getObjectFilename() != null) {
|
||||||
|
myDialog.textMantisBinary.setText(moteTypeToConfigure.getObjectFilename());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load all mote interface classes
|
||||||
|
String[] moteInterfaces = GUI.currentGUI.getPlatformConfig().getStringArrayValue(MantisMoteType.class, "MOTE_INTERFACES");
|
||||||
|
myDialog.moteInterfaceClasses = new Vector<Class<? extends MoteInterface>>();
|
||||||
|
for (String moteInterface : moteInterfaces) {
|
||||||
|
try {
|
||||||
|
Class<? extends MoteInterface> newMoteInterfaceClass =
|
||||||
|
GUI.currentGUI.tryLoadClass(GUI.currentGUI, MoteInterface.class, moteInterface);
|
||||||
|
myDialog.moteInterfaceClasses.add(newMoteInterfaceClass);
|
||||||
|
/*logger.info("Loaded Mantis mote interface: " + newMoteInterfaceClass);*/
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.fatal("Failed to load mote interface, aborting: " + moteInterface + ", " + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set position and focus of dialog
|
||||||
|
myDialog.pack();
|
||||||
|
myDialog.setLocationRelativeTo(parentFrame);
|
||||||
|
myDialog.textDescription.requestFocus();
|
||||||
|
myDialog.textDescription.select(0, myDialog.textDescription.getText().length());
|
||||||
|
myDialog.pathsWereUpdated();
|
||||||
|
myDialog.setVisible(true);
|
||||||
|
|
||||||
|
if (myDialog.myMoteType != null) {
|
||||||
|
// Library was compiled and loaded
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MantisMoteTypeDialog(Frame frame) {
|
||||||
|
super(frame, "Configure Mantis Mote Type", true);
|
||||||
|
|
||||||
|
myDialog = this;
|
||||||
|
|
||||||
|
JLabel label;
|
||||||
|
JPanel mainPane = new JPanel();
|
||||||
|
mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
|
||||||
|
JPanel smallPane;
|
||||||
|
JTextField textField;
|
||||||
|
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));
|
||||||
|
|
||||||
|
button = new JButton("Compile");
|
||||||
|
button.setActionCommand("compile");
|
||||||
|
button.addActionListener(myEventHandler);
|
||||||
|
compileButton = button;
|
||||||
|
this.getRootPane().setDefaultButton(button);
|
||||||
|
buttonPane.add(button);
|
||||||
|
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||||
|
|
||||||
|
buttonPane.add(Box.createHorizontalGlue());
|
||||||
|
|
||||||
|
button = new JButton("Clean");
|
||||||
|
button.setActionCommand("clean");
|
||||||
|
button.addActionListener(myEventHandler);
|
||||||
|
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||||
|
buttonPane.add(button);
|
||||||
|
|
||||||
|
button = new JButton("Cancel");
|
||||||
|
button.setActionCommand("cancel");
|
||||||
|
button.addActionListener(myEventHandler);
|
||||||
|
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||||
|
buttonPane.add(button);
|
||||||
|
|
||||||
|
button = new JButton("Create");
|
||||||
|
button.setEnabled(libraryCreatedOK);
|
||||||
|
button.setActionCommand("create");
|
||||||
|
button.addActionListener(myEventHandler);
|
||||||
|
createButton = button;
|
||||||
|
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
|
||||||
|
buttonPane.add(button);
|
||||||
|
|
||||||
|
// MAIN PART
|
||||||
|
|
||||||
|
// Identifier
|
||||||
|
smallPane = new JPanel();
|
||||||
|
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
|
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
|
||||||
|
label = new JLabel("Identifier");
|
||||||
|
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
|
||||||
|
|
||||||
|
textField = new JTextField();
|
||||||
|
|
||||||
|
textField.setText("");
|
||||||
|
|
||||||
|
textField.getDocument().addDocumentListener(myEventHandler);
|
||||||
|
textID = textField;
|
||||||
|
label.setLabelFor(textField);
|
||||||
|
smallPane.add(label);
|
||||||
|
smallPane.add(Box.createHorizontalStrut(10));
|
||||||
|
smallPane.add(Box.createHorizontalGlue());
|
||||||
|
smallPane.add(textField);
|
||||||
|
|
||||||
|
mainPane.add(smallPane);
|
||||||
|
|
||||||
|
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||||
|
|
||||||
|
// Output filenames
|
||||||
|
smallPane = new JPanel();
|
||||||
|
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
|
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
|
||||||
|
label = new JLabel("Output files");
|
||||||
|
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
|
||||||
|
|
||||||
|
textField = new JTextField();
|
||||||
|
textField.setText("");
|
||||||
|
textField.setEnabled(false);
|
||||||
|
textOutputFiles = textField;
|
||||||
|
label.setLabelFor(textField);
|
||||||
|
smallPane.add(label);
|
||||||
|
smallPane.add(Box.createHorizontalStrut(10));
|
||||||
|
smallPane.add(Box.createHorizontalGlue());
|
||||||
|
smallPane.add(textField);
|
||||||
|
|
||||||
|
mainPane.add(smallPane);
|
||||||
|
|
||||||
|
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||||
|
|
||||||
|
// Description
|
||||||
|
smallPane = new JPanel();
|
||||||
|
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
|
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
|
||||||
|
label = new JLabel("Description");
|
||||||
|
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
|
||||||
|
|
||||||
|
textField = new JTextField();
|
||||||
|
textField.setBackground(Color.GREEN);
|
||||||
|
textField.setText("");
|
||||||
|
textField.getDocument().addDocumentListener(myEventHandler);
|
||||||
|
textDescription = textField;
|
||||||
|
label.setLabelFor(textField);
|
||||||
|
smallPane.add(label);
|
||||||
|
smallPane.add(Box.createHorizontalStrut(10));
|
||||||
|
smallPane.add(Box.createHorizontalGlue());
|
||||||
|
smallPane.add(textField);
|
||||||
|
|
||||||
|
mainPane.add(smallPane);
|
||||||
|
|
||||||
|
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||||
|
|
||||||
|
// Mantis binary
|
||||||
|
smallPane = new JPanel();
|
||||||
|
smallPane.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
|
smallPane.setLayout(new BoxLayout(smallPane, BoxLayout.X_AXIS));
|
||||||
|
label = new JLabel("Mantis x86 object");
|
||||||
|
label.setPreferredSize(new Dimension(LABEL_WIDTH, LABEL_HEIGHT));
|
||||||
|
|
||||||
|
textField = new JTextField();
|
||||||
|
textField.setText("");
|
||||||
|
textField.getDocument().addDocumentListener(myEventHandler);
|
||||||
|
textMantisBinary = textField;
|
||||||
|
label.setLabelFor(textField);
|
||||||
|
|
||||||
|
button = new JButton("Browse");
|
||||||
|
button.setActionCommand("browsemantis");
|
||||||
|
button.addActionListener(myEventHandler);
|
||||||
|
|
||||||
|
smallPane.add(label);
|
||||||
|
smallPane.add(Box.createHorizontalStrut(10));
|
||||||
|
smallPane.add(Box.createHorizontalGlue());
|
||||||
|
smallPane.add(textField);
|
||||||
|
smallPane.add(button);
|
||||||
|
mainPane.add(smallPane);
|
||||||
|
|
||||||
|
mainPane.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||||
|
mainPane.add(Box.createVerticalGlue());
|
||||||
|
|
||||||
|
// Add everything!
|
||||||
|
mainPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||||
|
|
||||||
|
Container contentPane = getContentPane();
|
||||||
|
contentPane.add(mainPane, BorderLayout.NORTH);
|
||||||
|
contentPane.add(buttonPane, BorderLayout.SOUTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to compile library using current settings.
|
||||||
|
*/
|
||||||
|
public void doCompileCurrentSettings() {
|
||||||
|
libraryCreatedOK = false;
|
||||||
|
|
||||||
|
JPanel progressPanel = new JPanel(new BorderLayout());
|
||||||
|
final JDialog progressDialog = new JDialog(myDialog, null);
|
||||||
|
JProgressBar progressBar;
|
||||||
|
JButton button;
|
||||||
|
final MessageList taskOutput;
|
||||||
|
progressDialog.setLocationRelativeTo(myDialog);
|
||||||
|
|
||||||
|
progressBar = new JProgressBar(0, 100);
|
||||||
|
progressBar.setValue(0);
|
||||||
|
progressBar.setStringPainted(true);
|
||||||
|
progressBar.setIndeterminate(true);
|
||||||
|
|
||||||
|
taskOutput = new MessageList();
|
||||||
|
|
||||||
|
button = new JButton("Close/Abort");
|
||||||
|
button.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (compilationThread != null && compilationThread.isAlive()) {
|
||||||
|
compilationThread.interrupt();
|
||||||
|
}
|
||||||
|
progressDialog.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
progressPanel.add(BorderLayout.CENTER, new JScrollPane(taskOutput));
|
||||||
|
progressPanel.add(BorderLayout.NORTH, progressBar);
|
||||||
|
progressPanel.add(BorderLayout.SOUTH, button);
|
||||||
|
progressPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||||
|
progressPanel.setVisible(true);
|
||||||
|
|
||||||
|
progressDialog.getContentPane().add(progressPanel);
|
||||||
|
progressDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||||
|
progressDialog.pack();
|
||||||
|
|
||||||
|
progressDialog.getRootPane().setDefaultButton(button);
|
||||||
|
progressDialog.setVisible(true);
|
||||||
|
|
||||||
|
// Generate main mantis source file
|
||||||
|
try {
|
||||||
|
// Remove old file is existing
|
||||||
|
if (srcFile.exists()) {
|
||||||
|
srcFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcFile.exists()) {
|
||||||
|
throw new Exception("could not remove old source file");
|
||||||
|
}
|
||||||
|
|
||||||
|
generateSourceFile(srcFile);
|
||||||
|
|
||||||
|
if (!srcFile.exists()) {
|
||||||
|
throw new Exception("source file not created");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
libraryCreatedOK = false;
|
||||||
|
progressBar.setBackground(Color.ORANGE);
|
||||||
|
if (e.getMessage() != null)
|
||||||
|
progressBar.setString("source file generation failed: " + e.getMessage());
|
||||||
|
else
|
||||||
|
progressBar.setString("source file generation failed");
|
||||||
|
|
||||||
|
progressBar.setIndeterminate(false);
|
||||||
|
progressBar.setValue(0);
|
||||||
|
createButton.setEnabled(libraryCreatedOK);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test compile shared library
|
||||||
|
progressBar.setString("..compiling..");
|
||||||
|
|
||||||
|
if (libFile.exists()) {
|
||||||
|
libFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
compilationThread = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
compilationSucceded =
|
||||||
|
MantisMoteTypeDialog.compileLibrary(
|
||||||
|
libFile,
|
||||||
|
objFile,
|
||||||
|
srcFile,
|
||||||
|
workingDir,
|
||||||
|
taskOutput.getInputStream(MessageList.NORMAL),
|
||||||
|
taskOutput.getInputStream(MessageList.ERROR));
|
||||||
|
}
|
||||||
|
}, "compilation thread");
|
||||||
|
compilationThread.start();
|
||||||
|
|
||||||
|
while (compilationThread.isAlive()) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// NOP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!compilationSucceded) {
|
||||||
|
if (libFile.exists()) {
|
||||||
|
libFile.delete();
|
||||||
|
}
|
||||||
|
libraryCreatedOK = false;
|
||||||
|
} else {
|
||||||
|
libraryCreatedOK = true;
|
||||||
|
if (!libFile.exists())
|
||||||
|
libraryCreatedOK = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (libraryCreatedOK) {
|
||||||
|
progressBar.setBackground(Color.GREEN);
|
||||||
|
progressBar.setString("compilation succeded");
|
||||||
|
button.grabFocus();
|
||||||
|
myDialog.getRootPane().setDefaultButton(createButton);
|
||||||
|
} else {
|
||||||
|
progressBar.setBackground(Color.ORANGE);
|
||||||
|
progressBar.setString("compilation failed");
|
||||||
|
myDialog.getRootPane().setDefaultButton(compileButton);
|
||||||
|
}
|
||||||
|
progressBar.setIndeterminate(false);
|
||||||
|
progressBar.setValue(0);
|
||||||
|
createButton.setEnabled(libraryCreatedOK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates new source file by reading default source template and replacing
|
||||||
|
* certain field in order to be loadable from given Java class.
|
||||||
|
*
|
||||||
|
* @param outputFile Source file to create
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static void generateSourceFile(File outputFile)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
// CHECK JNI CLASS AVAILABILITY
|
||||||
|
String libString = CoreComm.getAvailableClassName();
|
||||||
|
if (libString == null) {
|
||||||
|
logger.fatal("No more libraries can be loaded!");
|
||||||
|
throw new Exception("Maximum number of mote types already exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
// GENERATE NEW FILE
|
||||||
|
BufferedWriter destFile = null;
|
||||||
|
BufferedReader sourceFile = null;
|
||||||
|
try {
|
||||||
|
Reader reader;
|
||||||
|
String mainTemplate = GUI
|
||||||
|
.getExternalToolsSetting("MANTIS_MAIN_TEMPLATE_FILENAME");
|
||||||
|
if ((new File(mainTemplate)).exists()) {
|
||||||
|
reader = new FileReader(mainTemplate);
|
||||||
|
} else {
|
||||||
|
InputStream input = MantisMoteTypeDialog.class
|
||||||
|
.getResourceAsStream('/' + mainTemplate);
|
||||||
|
if (input == null) {
|
||||||
|
throw new FileNotFoundException(mainTemplate + " not found");
|
||||||
|
}
|
||||||
|
reader = new InputStreamReader(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceFile = new BufferedReader(reader);
|
||||||
|
|
||||||
|
destFile = new BufferedWriter(new OutputStreamWriter(
|
||||||
|
new FileOutputStream(outputFile)));
|
||||||
|
|
||||||
|
// Replace fields in template
|
||||||
|
String line;
|
||||||
|
while ((line = sourceFile.readLine()) != null) {
|
||||||
|
line = line.replaceFirst("\\[CLASS_NAME\\]", libString);
|
||||||
|
destFile.write(line + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
destFile.close();
|
||||||
|
sourceFile.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
try {
|
||||||
|
if (destFile != null)
|
||||||
|
destFile.close();
|
||||||
|
if (sourceFile != null)
|
||||||
|
sourceFile.close();
|
||||||
|
} catch (Exception e2) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward exception
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles a mote type shared library using the standard Mantis makefile.
|
||||||
|
*
|
||||||
|
* @param libFile Library file to create
|
||||||
|
* @param binFile Binary file to link against
|
||||||
|
* @param sourceFile Source file to compile
|
||||||
|
* @param workingDir Working directory
|
||||||
|
* @param outputStream
|
||||||
|
* Output stream from compilation (optional)
|
||||||
|
* @param errorStream
|
||||||
|
* Error stream from compilation (optional)
|
||||||
|
* @return True if compilation succeeded, false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean compileLibrary(File libFile, File binFile, File sourceFile, File workingDir,
|
||||||
|
final PrintStream outputStream, final PrintStream errorStream) {
|
||||||
|
|
||||||
|
// Check needed files
|
||||||
|
if (!workingDir.exists()) {
|
||||||
|
if (errorStream != null)
|
||||||
|
errorStream.println("Bad paths");
|
||||||
|
logger.fatal("Working directory does not exist");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!workingDir.isDirectory()) {
|
||||||
|
if (errorStream != null)
|
||||||
|
errorStream.println("Bad paths");
|
||||||
|
logger.fatal("Working directory is not a directory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (libFile.exists()) {
|
||||||
|
if (errorStream != null)
|
||||||
|
errorStream.println("Bad output filenames");
|
||||||
|
logger.fatal("Library already exists");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sourceFile.exists()) {
|
||||||
|
if (errorStream != null)
|
||||||
|
errorStream.println("Bad dependency files");
|
||||||
|
logger.fatal("Source file not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!binFile.exists()) {
|
||||||
|
if (errorStream != null)
|
||||||
|
errorStream.println("Bad dependency files");
|
||||||
|
logger.fatal("Link object file not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CoreComm.hasLibraryFileBeenLoaded(libFile)) {
|
||||||
|
if (errorStream != null)
|
||||||
|
errorStream.println("Bad output filenames");
|
||||||
|
logger.fatal("A library has already been loaded with the same name before");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Call make file
|
||||||
|
String[] cmd = new String[]{
|
||||||
|
GUI.getExternalToolsSetting("PATH_MAKE"),
|
||||||
|
libFile.getName()};
|
||||||
|
|
||||||
|
String[] env = new String[]{
|
||||||
|
"COOJA_LINKFILE=" + binFile.getName(),
|
||||||
|
"COOJA_SOURCE=" + sourceFile.getName(),
|
||||||
|
"PATH=" + System.getenv("PATH")};
|
||||||
|
|
||||||
|
Process p = Runtime.getRuntime().exec(cmd, env, workingDir);
|
||||||
|
|
||||||
|
final BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||||
|
final BufferedReader err = new BufferedReader(new InputStreamReader(p.getErrorStream()));
|
||||||
|
|
||||||
|
Thread readInput = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
String readLine;
|
||||||
|
try {
|
||||||
|
while ((readLine = input.readLine()) != null) {
|
||||||
|
if (outputStream != null && readLine != null)
|
||||||
|
outputStream.println(readLine);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.warn("Error while reading from process");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "read input stream thread");
|
||||||
|
|
||||||
|
Thread readError = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
String readLine;
|
||||||
|
try {
|
||||||
|
while ((readLine = err.readLine()) != null) {
|
||||||
|
if (errorStream != null && readLine != null)
|
||||||
|
errorStream.println(readLine);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.warn("Error while reading from process");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "read input stream thread");
|
||||||
|
|
||||||
|
readInput.start();
|
||||||
|
readError.start();
|
||||||
|
|
||||||
|
while (readInput.isAlive() || readError.isAlive()) {
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
input.close();
|
||||||
|
err.close();
|
||||||
|
|
||||||
|
p.waitFor();
|
||||||
|
if (p.exitValue() != 0) {
|
||||||
|
logger.fatal("Make file returned error: " + p.exitValue());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.fatal("Error while compiling library: " + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pathsWereUpdated() {
|
||||||
|
updateVisualFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateVisualFields() {
|
||||||
|
settingsOK = true;
|
||||||
|
|
||||||
|
// Check for non-unique identifier
|
||||||
|
textID.setBackground(Color.WHITE);
|
||||||
|
textID.setToolTipText(null);
|
||||||
|
|
||||||
|
for (MoteType otherType : allOtherTypes) {
|
||||||
|
if (otherType != myMoteType
|
||||||
|
&& otherType.getIdentifier().equalsIgnoreCase(textID.getText())) {
|
||||||
|
textID.setBackground(Color.RED);
|
||||||
|
textID.setToolTipText("Conflicting name - must be unique");
|
||||||
|
settingsOK = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for non-unique description
|
||||||
|
textDescription.setBackground(Color.WHITE);
|
||||||
|
textDescription.setToolTipText(null);
|
||||||
|
|
||||||
|
for (MoteType otherType : allOtherTypes) {
|
||||||
|
if (otherType != myMoteType
|
||||||
|
&& otherType.getDescription().equals(textDescription.getText())) {
|
||||||
|
textDescription.setBackground(Color.RED);
|
||||||
|
textDescription.setToolTipText("Conflicting name - must be unique");
|
||||||
|
settingsOK = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that binary exists
|
||||||
|
textMantisBinary.setBackground(Color.WHITE);
|
||||||
|
textMantisBinary.setToolTipText(null);
|
||||||
|
|
||||||
|
objFile = new File(textMantisBinary.getText());
|
||||||
|
workingDir = objFile.getParentFile();
|
||||||
|
libFile = new File(workingDir, textID.getText() + ".library");
|
||||||
|
srcFile = new File(workingDir, textID.getText() + ".c");
|
||||||
|
// TODO Check that file is correct type (.o or something)
|
||||||
|
if (objFile == null || !objFile.exists()) {
|
||||||
|
textMantisBinary.setBackground(Color.RED);
|
||||||
|
textMantisBinary.setToolTipText("Incorrect object file");
|
||||||
|
objFile = null;
|
||||||
|
libFile = null;
|
||||||
|
srcFile = null;
|
||||||
|
workingDir = null;
|
||||||
|
settingsOK = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update output text field
|
||||||
|
if (settingsOK) {
|
||||||
|
textOutputFiles.setText(libFile.getName() + ", " + srcFile.getName() + ", " + textID.getText() + ".o");
|
||||||
|
} else {
|
||||||
|
textOutputFiles.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
createButton.setEnabled(libraryCreatedOK = false);
|
||||||
|
compileButton.setEnabled(settingsOK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class MoteTypeEventHandler
|
||||||
|
implements
|
||||||
|
ActionListener,
|
||||||
|
DocumentListener {
|
||||||
|
public void insertUpdate(DocumentEvent e) {
|
||||||
|
if (myDialog.isVisible())
|
||||||
|
javax.swing.SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
pathsWereUpdated();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public void removeUpdate(DocumentEvent e) {
|
||||||
|
if (myDialog.isVisible())
|
||||||
|
javax.swing.SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
pathsWereUpdated();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public void changedUpdate(DocumentEvent e) {
|
||||||
|
if (myDialog.isVisible())
|
||||||
|
javax.swing.SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
pathsWereUpdated();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (e.getActionCommand().equals("cancel")) {
|
||||||
|
// Cancel creation of mote type
|
||||||
|
myMoteType = null;
|
||||||
|
dispose();
|
||||||
|
} else if (e.getActionCommand().equals("clean")) {
|
||||||
|
// Delete any created intermediate files
|
||||||
|
// TODO Not implemented
|
||||||
|
logger.fatal("Clean functionality not implemented");
|
||||||
|
} else if (e.getActionCommand().equals("create")) {
|
||||||
|
// Create mote type and set related fields
|
||||||
|
boolean ret = myMoteType.doInit(libFile, objFile, moteInterfaceClasses);
|
||||||
|
myMoteType.setDescription(textDescription.getText());
|
||||||
|
myMoteType.setIdentifier(textID.getText());
|
||||||
|
if (ret) {
|
||||||
|
dispose();
|
||||||
|
} else {
|
||||||
|
logger.fatal("Mote type creation failed.");
|
||||||
|
}
|
||||||
|
} else if (e.getActionCommand().equals("compile")) {
|
||||||
|
compileButton.requestFocus();
|
||||||
|
Thread testSettingsThread = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
doCompileCurrentSettings();
|
||||||
|
}
|
||||||
|
}, "test settings thread");
|
||||||
|
testSettingsThread.start();
|
||||||
|
} else if (e.getActionCommand().equals("browsemantis")) {
|
||||||
|
JFileChooser fc = new JFileChooser();
|
||||||
|
fc.setCurrentDirectory(new java.io.File("."));
|
||||||
|
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||||
|
fc.setDialogTitle("Mantis binary to link against");
|
||||||
|
|
||||||
|
if (fc.showOpenDialog(myDialog) == JFileChooser.APPROVE_OPTION) {
|
||||||
|
textMantisBinary.setText(fc.getSelectedFile().getPath());
|
||||||
|
}
|
||||||
|
createButton.setEnabled(libraryCreatedOK = false);
|
||||||
|
pathsWereUpdated();
|
||||||
|
} else
|
||||||
|
logger.warn("Unhandled action: " + e.getActionCommand());
|
||||||
|
|
||||||
|
createButton.setEnabled(libraryCreatedOK = false);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue