diff --git a/tools/cooja/config/cooja_default.config b/tools/cooja/config/cooja_default.config index c76e29a45..de73be4fe 100644 --- a/tools/cooja/config/cooja_default.config +++ b/tools/cooja/config/cooja_default.config @@ -29,7 +29,7 @@ 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.C_SOURCES = -se.sics.cooja.GUI.MOTETYPES = se.sics.cooja.contikimote.ContikiMoteType se.sics.cooja.motes.DummyMoteType se.sics.cooja.mantismote.MantisMoteType +se.sics.cooja.GUI.MOTETYPES = se.sics.cooja.contikimote.ContikiMoteType se.sics.cooja.motes.DummyMoteType se.sics.cooja.mantismote.MantisMoteType se.sics.cooja.motes.DisturberMoteType 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.POSITIONERS = se.sics.cooja.positioners.RandomPositioner se.sics.cooja.positioners.LinearPositioner se.sics.cooja.positioners.EllipsePositioner diff --git a/tools/cooja/java/se/sics/cooja/motes/DisturberMote.java b/tools/cooja/java/se/sics/cooja/motes/DisturberMote.java new file mode 100644 index 000000000..aee692bdb --- /dev/null +++ b/tools/cooja/java/se/sics/cooja/motes/DisturberMote.java @@ -0,0 +1,235 @@ +/* + * 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: DisturberMote.java,v 1.1 2006/12/07 14:25:22 fros4943 Exp $ + */ + +package se.sics.cooja.motes; + +import java.util.*; + +import org.apache.log4j.Logger; +import org.jdom.Element; + +import se.sics.cooja.*; +import se.sics.cooja.interfaces.Position; +import se.sics.cooja.motes.DisturberRadio; + +/** + * A disturber mote is a purely Java-based mote. It is used to disturb + * transmission of other nodes on a certain channel (currently this is + * hard-coded in the DisturberRadio. + * + * @author Fredrik Osterlind, Thiemo Voigt + */ +public class DisturberMote implements Mote { + + private static Logger logger = Logger.getLogger(DisturberMote.class); + + private MoteType myType = null; + + private SectionMoteMemory myMemory = null; + + private MoteInterfaceHandler myInterfaceHandler = null; + + private Simulation mySim = null; + + private Random myRandom = new Random(); + + private DisturberRadio myDisturberRadio; + + /** + * Creates a new uninitialized dummy mote. + */ + public DisturberMote() { + } + + /** + * 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 DisturberMote(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); + + // create interface handler for radio + myDisturberRadio = new DisturberRadio(this); + myInterfaceHandler.addActiveInterface(myDisturberRadio); + } + + public void setState(State newState) { + logger.fatal("Disturber mote can not change state"); + } + + public State 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) { + myInterfaceHandler.doPassiveActionsBeforeTick(); + myInterfaceHandler.doActiveActionsBeforeTick(); + myInterfaceHandler.doActiveActionsAfterTick(); + myInterfaceHandler.doPassiveActionsAfterTick(); + } + + public Collection getConfigXML() { + Vector config = new Vector(); + + 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()); + + // 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 configXML) { + + // Set initial configuration + mySim = simulation; + myMemory = new SectionMoteMemory(new Properties()); + myInterfaceHandler = new MoteInterfaceHandler(); + Position myPosition = new Position(this); + myInterfaceHandler.addPassiveInterface(myPosition); + myDisturberRadio = new DisturberRadio(this); + myInterfaceHandler.addActiveInterface(myDisturberRadio); + + + 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 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 "Disturber Mote, ID=" + getInterfaces().getMoteID().getMoteID(); + } else + return "Disturber Mote, ID=null"; + } + +} diff --git a/tools/cooja/java/se/sics/cooja/motes/DisturberMoteType.java b/tools/cooja/java/se/sics/cooja/motes/DisturberMoteType.java new file mode 100644 index 000000000..5ed3848a4 --- /dev/null +++ b/tools/cooja/java/se/sics/cooja/motes/DisturberMoteType.java @@ -0,0 +1,257 @@ +/* + * 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. + * + * + */ + +package se.sics.cooja.motes; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.util.*; +import javax.swing.*; +import org.apache.log4j.Logger; +import org.jdom.Element; + +import se.sics.cooja.*; +import se.sics.cooja.interfaces.Position; + +/** + * + * + * @author Fredrik Osterlind, Thiemo Voigt + */ +@ClassDescription("Disturber Mote Type") +public class DisturberMoteType implements MoteType { + private static Logger logger = Logger.getLogger(DisturberMoteType.class); + + // Mote type specific data + private String identifier = null; + + private String description = null; + + private Vector> moteInterfaces = null; + + // Type specific class configuration + private PlatformConfig myConfig = null; + + // Simulation holding this mote type + private Simulation mySimulation = null; + + public DisturberMoteType() { + } + + public DisturberMoteType(String identifier) { + this.identifier = identifier; + description = "Disturber Mote Type #" + identifier; + } + + public Mote generateMote(Simulation simulation) { + return new DisturberMote(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 = "dist" + 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 = "Disturber Mote Type #" + counter; + } + + } + + if (description == null) { + // Create description + description = "Disturber Mote Type #" + identifier; + } + + moteInterfaces = new Vector>(); + moteInterfaces.add(Position.class); + moteInterfaces.add(DisturberRadio.class); + + return true; + } + + /* TV: add next two for interfaces */ + /** + * Returns all mote interfaces of this mote type + * + * @return All mote interfaces + */ + public Vector> getMoteInterfaces() { + return moteInterfaces; + } + + /** + * Set mote interfaces of this mote type + * + * @param moteInterfaces + * New mote interfaces + */ + public void setMoteInterfaces( + Vector> moteInterfaces) { + this.moteInterfaces = moteInterfaces; + } + + 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; + } + + /* TV replaced return null with this */ + 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); + + // 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 PlatformConfig getConfig() { + return myConfig; + //return null; /* TV */ + } + + public Collection getConfigXML() { + Vector config = new Vector(); + + Element element; + + // Identifier + element = new Element("identifier"); + element.setText(getIdentifier()); + config.add(element); + + // Description + element = new Element("description"); + element.setText(getDescription()); + config.add(element); + + // Mote interfaces + for (Class moteInterface : getMoteInterfaces()) { + element = new Element("moteinterface"); + element.setText(moteInterface.getName()); + config.add(element); + } + + return config; + } + + public boolean setConfigXML(Simulation simulation, + Collection configXML) { + for (Element element : configXML) { + moteInterfaces = new Vector>(); /* TV */ + mySimulation = simulation; /* TV */ + + String name = element.getName(); + + if (name.equals("identifier")) { + identifier = element.getText(); + } else if (name.equals("description")) { + description = element.getText(); + } else if (name.equals("moteinterface")) { /* TV */ + Class 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; + } + +} diff --git a/tools/cooja/java/se/sics/cooja/motes/DisturberRadio.java b/tools/cooja/java/se/sics/cooja/motes/DisturberRadio.java new file mode 100644 index 000000000..4849b4b75 --- /dev/null +++ b/tools/cooja/java/se/sics/cooja/motes/DisturberRadio.java @@ -0,0 +1,255 @@ +/* + * 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: DisturberRadio.java,v 1.1 2006/12/07 14:25:22 fros4943 Exp $ + */ + +package se.sics.cooja.motes; + +import java.text.NumberFormat; +import java.util.*; +import javax.swing.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import org.apache.log4j.Logger; +import org.jdom.Element; + +import se.sics.cooja.*; +import se.sics.cooja.interfaces.Radio; + +/** + * This radio periodically transmits data on a configurable channel. + * + * @author Fredrik Osterlind, Thiemo Voigt + */ +public class DisturberRadio extends Radio { + private Mote myMote; + + private static Logger logger = Logger.getLogger(DisturberRadio.class); + + private static byte[] packetFromMote = new byte[] { 1, 2, 3, 4, 5 }; + + private boolean transmitting = false; + + private int distChannel = -1; // channel mote is disturbing + + private int transEndTime = 0; + + private RadioEvent lastEvent = RadioEvent.UNKNOWN; + + private int lastEventTime = 0; + + public static int TRANSMISSION_INTERVAL = 100; + public static int TRANSMISSION_DURATION = 98; + + /** + * Creates an interface to the radio at mote. + * + * @param mote + * Radio's mote. + * @see Mote + * @see se.sics.cooja.MoteInterfaceHandler + */ + public DisturberRadio(Mote mote) { + this.myMote = mote; + } + + public byte[] getLastPacketTransmitted() { + return packetFromMote; + } + + public byte[] getLastPacketReceived() { + return null; + } + + public boolean isTransmitting() { + return transmitting; + } + + public int getTransmissionEndTime() { + return transEndTime; + } + + public boolean isReceiving() { + if (isLockedAtReceiving()) + return true; + return false; + } + + public int getChannel() { + return distChannel; + } + + public RadioEvent getLastEvent() { + return lastEvent; + } + + /** + * @return True if locked at receiving + */ + private boolean isLockedAtReceiving() { + return false; + } + + public void receivePacket(byte[] data, int endTime) { + } + + public void interferReception(int endTime) { + } + + public boolean isInterfered() { + return false; + } + + public double getCurrentOutputPower() { + // TODO Implement method + logger.warn("Not implemeted, always returning 1.5 dBm"); + return 1.5; + } + + public int getCurrentOutputPowerIndicator() { + return 100; + } + + public double getCurrentSignalStrength() { + return 2.0; + } + + public void setCurrentSignalStrength(double signalStrength) { + } + + public void doActionsBeforeTick() { + int currentTime = myMote.getSimulation().getSimulationTime(); + + if (!transmitting && currentTime % TRANSMISSION_INTERVAL == 0) { + transmitting = true; + lastEvent = RadioEvent.TRANSMISSION_STARTED; + lastEventTime = currentTime; + transEndTime = currentTime + TRANSMISSION_DURATION; + this.setChanged(); + this.notifyObservers(); + } else if (transmitting && currentTime >= transEndTime) { + transmitting = false; + lastEvent = RadioEvent.TRANSMISSION_FINISHED; + lastEventTime = currentTime; + this.setChanged(); + this.notifyObservers(); + } + } + + public void doActionsAfterTick() { + } + + public JPanel getInterfaceVisualizer() { + // Location + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + + final JLabel statusLabel = new JLabel(""); + final JLabel lastEventLabel = new JLabel(""); + final JLabel channelLabel = new JLabel(""); + final JFormattedTextField channelPicker = new JFormattedTextField(NumberFormat.getIntegerInstance()); + + panel.add(statusLabel); + panel.add(lastEventLabel); + panel.add(Box.createVerticalStrut(3)); + panel.add(channelLabel); + panel.add(channelPicker); + panel.add(Box.createVerticalGlue()); + + channelPicker.setValue(distChannel); + channelPicker.setColumns(3); + channelPicker.setText(Integer.toString(distChannel)); + + final Observer observer = new Observer() { + public void update(Observable obs, Object obj) { + if (isTransmitting()) + statusLabel.setText("Transmitting now!"); + else + statusLabel.setText("Disturber resting..."); + + channelLabel.setText("Channel: " + getChannel()); + + lastEventLabel.setText("Last event (time=" + lastEventTime + "): " + lastEvent); + } + }; + this.addObserver(observer); + + channelPicker.addPropertyChangeListener("value", new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + distChannel = ((Number) channelPicker.getValue()).intValue(); + if (observer != null) + observer.update(null, null); + } + }); + + observer.update(null, null); + + // 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; + } + + public Collection getConfigXML() { + Vector config = new Vector(); + Element element; + + // We need to save the mote type identifier + element = new Element("channel"); + element.setText(Integer.toString(distChannel)); + config.add(element); + + return config; + } + + public void setConfigXML(Collection configXML) { + for (Element element : configXML) { + String name = element.getName(); + + if (name.equals("channel")) { + distChannel = Integer.parseInt(element.getText()); + } else + logger.fatal("Read unknown configuration: " + name); + } + } +}