diff --git a/.gitignore b/.gitignore index 74bef3888..f8f72f54b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,8 +20,6 @@ tools/tunslip6 build tools/coffee-manager/build/ tools/coffee-manager/coffee.jar -tools/collect-view/build/ -tools/collect-view/dist/ COOJA.testlog # platform build artifacts diff --git a/tools/collect-view/build.xml b/tools/collect-view/build.xml deleted file mode 100644 index 5e7458eb7..000000000 --- a/tools/collect-view/build.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/collect-view/collect-init.script b/tools/collect-view/collect-init.script deleted file mode 100644 index 493cd46c5..000000000 --- a/tools/collect-view/collect-init.script +++ /dev/null @@ -1,6 +0,0 @@ -echo ~K -echo killall -sleep 2 -echo mac 0 -sleep 2 -echo time %TIME% | null diff --git a/tools/collect-view/lib/jcommon-1.0.13.jar b/tools/collect-view/lib/jcommon-1.0.13.jar deleted file mode 100644 index 634447d2f..000000000 Binary files a/tools/collect-view/lib/jcommon-1.0.13.jar and /dev/null differ diff --git a/tools/collect-view/lib/jfreechart-1.0.10.jar b/tools/collect-view/lib/jfreechart-1.0.10.jar deleted file mode 100644 index f6f7bbf2d..000000000 Binary files a/tools/collect-view/lib/jfreechart-1.0.10.jar and /dev/null differ diff --git a/tools/collect-view/src/org/contikios/contiki/collect/CollectServer.java b/tools/collect-view/src/org/contikios/contiki/collect/CollectServer.java deleted file mode 100644 index 582a4dacd..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/CollectServer.java +++ /dev/null @@ -1,1592 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * ----------------------------------------------------------------- - * - * CollectServer - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - */ - -package org.contikios.contiki.collect; -import java.awt.BorderLayout; -import java.awt.GraphicsEnvironment; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; -import java.util.Properties; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; -import javax.swing.ListCellRenderer; -import javax.swing.SwingUtilities; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.contikios.contiki.collect.gui.AggregatedTimeChartPanel; -import org.contikios.contiki.collect.gui.BarChartPanel; -import org.contikios.contiki.collect.gui.MapPanel; -import org.contikios.contiki.collect.gui.NodeControl; -import org.contikios.contiki.collect.gui.NodeInfoPanel; -import org.contikios.contiki.collect.gui.SerialConsole; -import org.contikios.contiki.collect.gui.TimeChartPanel; - -/** - * - */ -public class CollectServer implements SerialConnectionListener { - - public static final String WINDOW_TITLE = "Sensor Data Collect with Contiki"; - public static final String STDIN_COMMAND = ""; - - public static final String CONFIG_FILE = "collect.conf"; - public static final String SENSORDATA_FILE = "sensordata.log"; - public static final String CONFIG_DATA_FILE = "collect-data.conf"; - public static final String INIT_SCRIPT = "collect-init.script"; - public static final String FIRMWARE_FILE = "collect-view-shell.ihex"; - - /* Categories for the tab pane */ - private static final String MAIN = "main"; - private static final String NETWORK = "Network"; - private static final String SENSORS = "Sensors"; - private static final String POWER = "Power"; - - private Properties config = new Properties(); - - private String configFile; - private Properties configTable = new Properties(); - - private ArrayList sensorDataList = new ArrayList(); - private PrintWriter sensorDataOutput; - private boolean isSensorLogUsed; - - private Hashtable nodeTable = new Hashtable(); - private Node[] nodeCache; - - private JFrame window; - private JTabbedPane mainPanel; - private HashMap categoryTable = new HashMap(); - private JMenuItem runInitScriptItem; - - private final Visualizer[] visualizers; - private final MapPanel mapPanel; - private final SerialConsole serialConsole; - private final ConnectSerialAction connectSerialAction; - private final MoteProgramAction moteProgramAction; - private JFileChooser fileChooser; - - private JList nodeList; - private DefaultListModel nodeModel; - private Node[] selectedNodes; - - private SerialConnection serialConnection; - private boolean hasSerialOpened; - /* Do not auto send init script at startup */ - private boolean doSendInitAtStartup = false; - private String initScript; - - private boolean hasStarted = false; - private boolean doExitOnRequest = true; - private JMenuItem exitItem; - - private int defaultMaxItemCount = 250; - private long nodeTimeDelta; - - @SuppressWarnings("serial") - public CollectServer() { - loadConfig(config, CONFIG_FILE); - - this.configFile = config.getProperty("config.datafile", CONFIG_DATA_FILE); - if (this.configFile != null) { - loadConfig(configTable, this.configFile); - } - this.initScript = config.getProperty("init.script", INIT_SCRIPT); - - /* Make sure we have nice window decorations */ -// JFrame.setDefaultLookAndFeelDecorated(true); -// JDialog.setDefaultLookAndFeelDecorated(true); - Rectangle maxSize = GraphicsEnvironment.getLocalGraphicsEnvironment() - .getMaximumWindowBounds(); - - /* Create and set up the window */ - window = new JFrame(WINDOW_TITLE + " (not connected)"); - window.setLocationByPlatform(true); - if (maxSize != null) { - window.setMaximizedBounds(maxSize); - } - window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - - window.addWindowListener(new WindowAdapter() { - - public void windowClosing(WindowEvent e) { - exit(); - } - }); - - moteProgramAction = new MoteProgramAction("Program Nodes..."); - connectSerialAction = new ConnectSerialAction("Connect to serial"); - - nodeModel = new DefaultListModel(); - nodeModel.addElement(""); - nodeList = new JList(nodeModel); - nodeList.setPrototypeCellValue("888.888"); - nodeList.addListSelectionListener(new ListSelectionListener() { - - @Override - public void valueChanged(ListSelectionEvent e) { - if (!e.getValueIsAdjusting() && e.getSource() == nodeList) { - Node[] selected; - int iMin = nodeList.getMinSelectionIndex(); - int iMax = nodeList.getMaxSelectionIndex(); - if ((iMin < 0) || (iMax < 0)) { - selected = null; - } else if (nodeList.getSelectedIndex() == 0) { - selected = getNodes(); - if (nodeModel.size() > 1) { - nodeList.setSelectionInterval(1, nodeModel.size() - 1); - } - } else { - Node[] tmp = new Node[1 + (iMax - iMin)]; - int n = 0; - if (iMin < 1) { - iMin = 1; - } - for(int i = iMin; i <= iMax; i++) { - if (nodeList.isSelectedIndex(i)) { - tmp[n++] = (Node) nodeModel.getElementAt(i); - } - } - if (n != tmp.length) { - Node[] t = new Node[n]; - System.arraycopy(tmp, 0, t, 0, n); - tmp = t; - } - selected = tmp; - } - selectNodes(selected, false); - } - - }}); - nodeList.setBorder(BorderFactory.createTitledBorder("Nodes")); - ListCellRenderer renderer = nodeList.getCellRenderer(); - if (renderer instanceof JLabel) { - ((JLabel)renderer).setHorizontalAlignment(JLabel.CENTER); - } - window.getContentPane().add(new JScrollPane(nodeList), BorderLayout.WEST); - - mainPanel = new JTabbedPane(); - mainPanel.setBackground(nodeList.getBackground()); - mainPanel.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); - categoryTable.put(MAIN, mainPanel); - - serialConsole = new SerialConsole(this, MAIN); - mapPanel = new MapPanel(this, "Sensor Map", MAIN, true); - String image = getConfig("collect.mapimage"); - if (image != null) { - mapPanel.setMapBackground(image); - } - NodeControl nodeControl = new NodeControl(this, MAIN); - - visualizers = new Visualizer[] { - nodeControl, - mapPanel, - new MapPanel(this, "Network Graph", MAIN, false), - new BarChartPanel(this, SENSORS, "Average Temperature", "Temperature", "Nodes", "Celsius", - new String[] { "Celsius" }) { - { - chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - String nodeName = node.getName(); - SensorDataAggregator aggregator = node.getSensorDataAggregator(); - dataset.addValue(aggregator.getAverageTemperature(), categories[0], nodeName); - } - }, - new TimeChartPanel(this, SENSORS, "Temperature", "Temperature", "Time", "Celsius") { - { - chart.getXYPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - setRangeTick(5); - setRangeMinimumSize(10.0); - setGlobalRange(true); - } - protected double getSensorDataValue(SensorData data) { - return data.getTemperature(); - } - }, - new TimeChartPanel(this, SENSORS, "Battery Voltage", "Battery Voltage", - "Time", "Volt") { - { - setRangeTick(1); - setRangeMinimumSize(4.0); - setGlobalRange(true); - } - protected double getSensorDataValue(SensorData data) { - return data.getBatteryVoltage(); - } - }, - new TimeChartPanel(this, SENSORS, "Battery Indicator", "Battery Indicator", - "Time", "Indicator") { - { - chart.getXYPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - setRangeTick(5); - setRangeMinimumSize(10.0); - setGlobalRange(true); - } - protected double getSensorDataValue(SensorData data) { - return data.getBatteryIndicator(); - } - }, - new TimeChartPanel(this, SENSORS, "Relative Humidity", "Humidity", "Time", "%") { - { - chart.getXYPlot().getRangeAxis().setRange(0.0, 100.0); - } - protected double getSensorDataValue(SensorData data) { - return data.getHumidity(); - } - }, - new TimeChartPanel(this, SENSORS, "Light 1", "Light 1", "Time", "-") { - protected double getSensorDataValue(SensorData data) { - return data.getLight1(); - } - }, - new TimeChartPanel(this, SENSORS, "Light 2", "Light 2", "Time", "-") { - protected double getSensorDataValue(SensorData data) { - return data.getLight2(); - } - }, - new TimeChartPanel(this, NETWORK, "Neighbors", "Neighbor Count", "Time", "Neighbors") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getValue(SensorData.NUM_NEIGHBORS); - } - }, - new TimeChartPanel(this, NETWORK, "Beacon Interval", "Beacon interval", "Time", "Interval (s)") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getValue(SensorData.BEACON_INTERVAL); - } - }, - new TimeChartPanel(this, NETWORK, "Network Hops (Over Time)", "Network Hops", "Time", "Hops") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getValue(SensorData.HOPS); - } - }, - new BarChartPanel(this, NETWORK, "Network Hops (Per Node)", "Network Hops", "Nodes", "Hops", - new String[] { "Last Hop", "Average Hops" }, false) { - { - chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected void addSensorData(SensorData data) { - dataset.addValue(data.getValue(SensorData.HOPS), categories[0], data.getNode().getName()); - dataset.addValue(data.getNode().getSensorDataAggregator().getAverageValue(SensorData.HOPS), categories[1], data.getNode().getName()); - } - }, - new TimeChartPanel(this, NETWORK, "Routing Metric (Over Time)", "Routing Metric", "Time", "Routing Metric") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getValue(SensorData.RTMETRIC); - } - }, - new AggregatedTimeChartPanel(this, NETWORK, "Avg Routing Metric (Over Time)", "Time", - "Average Routing Metric") { - private int nodeCount; - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - @Override - protected boolean[] createState(Node node) { - return new boolean[1]; - } - @Override - protected void clearState(Map map) { - nodeCount = 0; - for(boolean[] value : map.values()) { - value[0] = false; - } - } - @Override - protected String getTitle(int selectedCount, int dataCount, int duplicateCount) { - return "Average Routing Metric (" + dataCount + " packets from " + nodeCount + " node" - + (nodeCount > 1 ? "s" : "") + ')'; - } - @Override - protected int getTotalDataValue(int value) { - // Return average value - return nodeCount > 0 ? (value / nodeCount) : value; - } - @Override - protected int getSensorDataValue(SensorData data, boolean[] nodeState) { - if (!nodeState[0]) { - nodeCount++; - nodeState[0] = true; - } - return data.getValue(SensorData.RTMETRIC); - } - }, - new TimeChartPanel(this, NETWORK, "ETX (Over Time)", "ETX to Next Hop", "Time", "ETX") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected double getSensorDataValue(SensorData data) { - return data.getBestNeighborETX(); - } - }, - new AggregatedTimeChartPanel(this, NETWORK, - "Next Hop (Over Time)", "Time", "Next Hop Changes") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - @Override - protected int[] createState(Node node) { - return new int[1]; - } - @Override - protected void clearState(Map map) { - for(int[] value : map.values()) { - value[0] = 0; - } - } - @Override - protected int getSensorDataValue(SensorData sd, int[] nodeState) { - boolean hasBest = nodeState[0] != 0; - int bestNeighbor = sd.getValue(SensorData.BEST_NEIGHBOR); - if (bestNeighbor != 0 && bestNeighbor != nodeState[0]) { - nodeState[0] = bestNeighbor; - return hasBest ? 1 : 0; - } - return 0; - } - }, - new TimeChartPanel(this, NETWORK, "Latency", "Latency", "Time", "Seconds") { - protected double getSensorDataValue(SensorData data) { - return data.getLatency(); - } - }, - new AggregatedTimeChartPanel(this, NETWORK, - "Received (Over Time)", "Time", "Received Packets") { - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - @Override - protected String getTitle(int nodeCount, int dataCount, int duplicateCount) { - return "Received " + dataCount + " packets from " + nodeCount + " node" - + (nodeCount > 1 ? "s" : "") - + (duplicateCount > 0 ? (" (" + duplicateCount + " duplicates)") : ""); - } - @Override - protected Node createState(Node node) { - return node; - } - @Override - protected int getSensorDataValue(SensorData sd, Node node) { - return 1; - } - }, - new AggregatedTimeChartPanel(this, NETWORK, - "Lost (Over Time)", "Time", "Estimated Lost Packets") { - private int totalLost; - { - ValueAxis axis = chart.getXYPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - @Override - protected String getTitle(int nodeCount, int dataCount, int duplicateCount) { - return "Received " + dataCount + " packets from " + nodeCount - + " node" + (nodeCount > 1 ? "s" : "") + ". Estimated " - + totalLost + " lost packet" + (totalLost == 1 ? "" : "s") - + '.'; - } - @Override - protected int[] createState(Node node) { - return new int[1]; - } - @Override - protected void clearState(Map map) { - totalLost = 0; - for(int[] v : map.values()) { - v[0] = 0; - } - } - @Override - protected int getSensorDataValue(SensorData sd, int[] nodeState) { - int lastSeqno = nodeState[0]; - int seqno = sd.getSeqno(); - nodeState[0] = seqno; - if (seqno > lastSeqno + 1 && lastSeqno != 0) { - int estimatedLost = seqno - lastSeqno - 1; - totalLost += estimatedLost; - return estimatedLost; - } - return 0; - } - }, - new BarChartPanel(this, NETWORK, "Received (Per Node)", "Received Packets Per Node", "Nodes", "Packets", - new String[] { "Packets", "Duplicates" }) { - { - chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - SensorDataAggregator sda = node.getSensorDataAggregator(); - dataset.addValue(sda.getDataCount(), categories[0], node.getName()); - dataset.addValue(sda.getDuplicateCount(), categories[1], node.getName()); - } - }, - new BarChartPanel(this, NETWORK, "Received (5 min)", "Received Packets (last 5 min)", "Nodes", "Packets", - new String[] { "Packets", "Duplicates" }) { - { - chart.getCategoryPlot().getRangeAxis().setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - int packetCount = 0; - int duplicateCount = 0; - long earliestData = System.currentTimeMillis() - (5 * 60 * 1000); - for(int index = node.getSensorDataCount() - 1; index >= 0; index--) { - SensorData sd = node.getSensorData(index); - if (sd.getNodeTime() < earliestData) { - break; - } - if (sd.isDuplicate()) { - duplicateCount++; - } else { - packetCount++; - } - } - dataset.addValue(packetCount, categories[0], node.getName()); - dataset.addValue(duplicateCount, categories[1], node.getName()); - } - }, - new BarChartPanel(this, POWER, "Average Power", "Average Power Consumption", - "Nodes", "Power (mW)", - new String[] { "LPM", "CPU", "Radio listen", "Radio transmit" }) { - { - ValueAxis axis = chart.getCategoryPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - String nodeName = node.getName(); - SensorDataAggregator aggregator = node.getSensorDataAggregator(); - dataset.addValue(aggregator.getLPMPower(), categories[0], nodeName); - dataset.addValue(aggregator.getCPUPower(), categories[1], nodeName); - dataset.addValue(aggregator.getListenPower(), categories[2], nodeName); - dataset.addValue(aggregator.getTransmitPower(), categories[3], nodeName); - } - }, - new BarChartPanel(this, POWER, "Radio Duty Cycle", "Average Radio Duty Cycle", - "Nodes", "Duty Cycle (%)", - new String[] { "Radio listen", "Radio transmit" }) { - { - ValueAxis axis = chart.getCategoryPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - String nodeName = node.getName(); - SensorDataAggregator aggregator = node.getSensorDataAggregator(); - dataset.addValue(100 * aggregator.getAverageDutyCycle(SensorInfo.TIME_LISTEN), - categories[0], nodeName); - dataset.addValue(100 * aggregator.getAverageDutyCycle(SensorInfo.TIME_TRANSMIT), - categories[1], nodeName); - } - }, - new BarChartPanel(this, POWER, "Instantaneous Power", - "Instantaneous Power Consumption", "Nodes", "Power (mW)", - new String[] { "LPM", "CPU", "Radio listen", "Radio transmit" }) { - { - ValueAxis axis = chart.getCategoryPlot().getRangeAxis(); - ((NumberAxis)axis).setAutoRangeIncludesZero(true); - } - protected void addSensorData(SensorData data) { - Node node = data.getNode(); - String nodeName = node.getName(); - dataset.addValue(data.getLPMPower(), categories[0], nodeName); - dataset.addValue(data.getCPUPower(), categories[1], nodeName); - dataset.addValue(data.getListenPower(), categories[2], nodeName); - dataset.addValue(data.getTransmitPower(), categories[3], nodeName); - } - }, - new TimeChartPanel(this, POWER, "Power History", "Historical Power Consumption", "Time", "mW") { - protected double getSensorDataValue(SensorData data) { - return data.getAveragePower(); - } - }, - new NodeInfoPanel(this, MAIN), - serialConsole - }; - for (int i = 0, n = visualizers.length; i < n; i++) { - String category = visualizers[i].getCategory(); - JTabbedPane pane = categoryTable.get(category); - if (pane == null) { - pane = new JTabbedPane(); - pane.setBackground(nodeList.getBackground()); - pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); - categoryTable.put(category, pane); - mainPanel.add(category, pane); - } - pane.add(visualizers[i].getTitle(), visualizers[i].getPanel()); - } - JTabbedPane pane = categoryTable.get(nodeControl.getCategory()); - if (pane != null) { - pane.setSelectedComponent(nodeControl.getPanel()); - } - window.getContentPane().add(mainPanel, BorderLayout.CENTER); - - // Setup menu - JMenuBar menuBar = new JMenuBar(); - - JMenu fileMenu = new JMenu("File"); - fileMenu.setMnemonic(KeyEvent.VK_F); - menuBar.add(fileMenu); - fileMenu.add(new JMenuItem(connectSerialAction)); - fileMenu.add(new JMenuItem(moteProgramAction)); - - fileMenu.addSeparator(); - final JMenuItem clearMapItem = new JMenuItem("Remove Map Background"); - clearMapItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - mapPanel.setMapBackground(null); - clearMapItem.setEnabled(false); - configTable.remove("collect.mapimage"); - } - - }); - clearMapItem.setEnabled(mapPanel.getMapBackground() != null); - - JMenuItem item = new JMenuItem("Select Map Background..."); - item.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - if (fileChooser == null) { - fileChooser = new JFileChooser(); - } - int reply = fileChooser.showOpenDialog(window); - if (reply == JFileChooser.APPROVE_OPTION) { - File file = fileChooser.getSelectedFile(); - String name = file.getAbsolutePath(); - if (!mapPanel.setMapBackground(file.getAbsolutePath())) { - JOptionPane.showMessageDialog(window, "Failed to set background image", "Error", JOptionPane.ERROR_MESSAGE); - } else { - configTable.put("collect.mapimage", name); - save(); - } - clearMapItem.setEnabled(mapPanel.getMapBackground() != null); - } - } - - }); - fileMenu.add(item); - fileMenu.add(clearMapItem); - - item = new JMenuItem("Save Settings"); - item.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - save(); - JOptionPane.showMessageDialog(window, "Settings have been saved."); - } - - }); - fileMenu.add(item); - - fileMenu.addSeparator(); - item = new JMenuItem("Clear Sensor Data..."); - item.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - int reply = isSensorLogUsed - ? JOptionPane.showConfirmDialog(window, "Also clear the sensor data log file?") - : JOptionPane.NO_OPTION; - if (reply == JOptionPane.YES_OPTION) { - // Clear data from both memory and sensor log file - clearSensorDataLog(); - clearSensorData(); - } else if (reply == JOptionPane.NO_OPTION) { - // Only clear data from memory - clearSensorData(); - } - } - - }); - fileMenu.add(item); - - fileMenu.addSeparator(); - exitItem = new JMenuItem("Exit", KeyEvent.VK_X); - exitItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - exit(); - } - - }); - fileMenu.add(exitItem); - - JMenu toolsMenu = new JMenu("Tools"); - toolsMenu.setMnemonic(KeyEvent.VK_T); - menuBar.add(toolsMenu); - - runInitScriptItem = new JMenuItem("Run Init Script"); - runInitScriptItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - mainPanel.setSelectedComponent(serialConsole.getPanel()); - if (serialConnection != null && serialConnection.isOpen()) { - runInitScript(); - } else { - JOptionPane.showMessageDialog(mainPanel, "No serial port connection", "No connected node", JOptionPane.ERROR_MESSAGE); - } - } - - }); - runInitScriptItem.setEnabled(false); - toolsMenu.add(runInitScriptItem); - toolsMenu.addSeparator(); - - item = new JMenuItem("Set Max Item Count..."); - item.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - int value = getUserInputAsInteger("Specify Max Item Count", - "Please specify max item count for the time charts.\n" + - "Charts with more values will aggregate the values into fewer items.", - defaultMaxItemCount); - if (value > 0) { - defaultMaxItemCount = value; - if (visualizers != null) { - for(Visualizer v : visualizers) { - if (v instanceof TimeChartPanel) { - ((TimeChartPanel)v).setMaxItemCount(defaultMaxItemCount); - } - } - } - } - } - - }); - toolsMenu.add(item); - - final JCheckBoxMenuItem baseShapeItem = new JCheckBoxMenuItem("Base Shape Visible"); - baseShapeItem.setSelected(true); - baseShapeItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - boolean visible = baseShapeItem.getState(); - if (visualizers != null) { - for(Visualizer v : visualizers) { - if (v instanceof TimeChartPanel) { - ((TimeChartPanel)v).setBaseShapeVisible(visible); - } - } - } - } - - }); - toolsMenu.add(baseShapeItem); - - window.setJMenuBar(menuBar); - window.pack(); - - String bounds = configTable.getProperty("collect.bounds"); - if (bounds != null) { - String[] b = bounds.split(","); - if (b.length == 4) { - window.setBounds(Integer.parseInt(b[0]), Integer.parseInt(b[1]), - Integer.parseInt(b[2]), Integer.parseInt(b[3])); - } - } - - for(Object key: configTable.keySet()) { - String property = key.toString(); - if (!property.startsWith("collect")) { - getNode(property, true); - } - } - } - - private int getUserInputAsInteger(String title, String message, int defaultValue) { - String s = (String)JOptionPane.showInputDialog( - window, message, title, JOptionPane.PLAIN_MESSAGE, null, null, Integer.toString(defaultValue)); - if (s != null) { - try { - return Integer.parseInt(s); - } catch (Exception e) { - JOptionPane.showMessageDialog(window, "Illegal value", "Error", JOptionPane.ERROR_MESSAGE); - } - } - return -1; - } - - public void start(SerialConnection connection) { - if (hasStarted) { - throw new IllegalStateException("already started"); - } - hasStarted = true; - this.serialConnection = connection; - if (isSensorLogUsed) { - initSensorData(); - } - SwingUtilities.invokeLater(new Runnable() { - public void run() { - window.setVisible(true); - } - }); - connectToSerial(); - } - - protected void connectToSerial() { - if (serialConnection != null && !serialConnection.isOpen()) { - String comPort = serialConnection.getComPort(); - if (comPort == null && serialConnection.isMultiplePortsSupported()) { - comPort = MoteFinder.selectComPort(window); - } - if (comPort != null || !serialConnection.isMultiplePortsSupported()) { - serialConnection.open(comPort); - } - } - } - - public void stop() { - save(); - if (serialConnection != null) { - serialConnection.close(); - } - PrintWriter output = this.sensorDataOutput; - if (output != null) { - output.close(); - } - window.setVisible(false); - } - - public void setUseSensorDataLog(boolean useSensorLog) { - this.isSensorLogUsed = useSensorLog; - } - - public void setExitOnRequest(boolean doExit) { - this.doExitOnRequest = doExit; - if (exitItem != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - exitItem.setEnabled(doExitOnRequest); - } - }); - } - } - - private void exit() { - if (doExitOnRequest) { - stop(); - System.exit(0); - } else { - Toolkit.getDefaultToolkit().beep(); - } - } - - private void sleep(long delay) { - try { - Thread.sleep(delay); - } catch (InterruptedException e1) { - // Ignore - } - } - - protected boolean hasInitScript() { - return initScript != null && new File(initScript).canRead(); - } - - protected void runInitScript() { - if (initScript != null) { - runScript(initScript); - } - } - - protected void runScript(final String scriptFileName) { - new Thread("scripter") { - public void run() { - try { - BufferedReader in = new BufferedReader(new FileReader(scriptFileName)); - String line; - while ((line = in.readLine()) != null) { - if (line.length() == 0 || line.charAt(0) == '#') { - // Ignore empty lines and comments - } else if (line.startsWith("echo ")) { - line = line.substring(5).trim(); - if (line.indexOf('%') >= 0) { - line = line.replace("%TIME%", "" + (System.currentTimeMillis() / 1000)); - } - sendToNode(line); - } else if (line.startsWith("sleep ")) { - long delay = Integer.parseInt(line.substring(6).trim()); - Thread.sleep(delay * 1000); - } else { - System.err.println("Unknown script command: " + line); - break; - } - } - in.close(); - } catch (Exception e) { - System.err.println("Failed to run script: " + scriptFileName); - e.printStackTrace(); - } - } - }.start(); - } - - public String getConfig(String property) { - return getConfig(property, null); - } - - public String getConfig(String property, String defaultValue) { - return configTable.getProperty(property, config.getProperty(property, defaultValue)); - } - - public void setConfig(String property, String value) { - configTable.setProperty(property, value); - } - - public void removeConfig(String property) { - configTable.remove(property); - } - - public int getDefaultMaxItemCount() { - return defaultMaxItemCount; - } - - public Action getMoteProgramAction() { - return moteProgramAction; - } - - public Action getConnectSerialAction() { - return connectSerialAction; - } - - protected void setSystemMessage(final String message) { - SwingUtilities.invokeLater(new Runnable() { - - public void run() { - boolean isOpen = serialConnection != null && serialConnection.isOpen(); - if (message == null) { - window.setTitle(WINDOW_TITLE); - } else { - window.setTitle(WINDOW_TITLE + " (" + message + ')'); - } - connectSerialAction.putValue(ConnectSerialAction.NAME, - isOpen ? "Disconnect from serial" : "Connect to serial"); - runInitScriptItem.setEnabled(isOpen - && serialConnection.isSerialOutputSupported() && hasInitScript()); - } - - }); - } - - // ------------------------------------------------------------------- - // Node Handling - // ------------------------------------------------------------------- - - public synchronized Node[] getNodes() { - if (nodeCache == null) { - Node[] tmp = nodeTable.values().toArray(new Node[nodeTable.size()]); - Arrays.sort(tmp); - nodeCache = tmp; - } - return nodeCache; - } - - public Node addNode(String nodeID) { - return getNode(nodeID, true); - } - - private Node getNode(final String nodeID, boolean notify) { - Node node = nodeTable.get(nodeID); - if (node == null) { - node = new Node(nodeID); - nodeTable.put(nodeID, node); - - synchronized (this) { - nodeCache = null; - } - - if (notify) { - final Node newNode = node; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - boolean added = false; - for (int i = 1, n = nodeModel.size(); i < n; i++) { - int cmp = newNode.compareTo((Node) nodeModel.get(i)); - if (cmp < 0) { - nodeModel.insertElementAt(newNode, i); - added = true; - break; - } else if (cmp == 0) { - // node already added - added = true; - break; - } - } - if (!added) { - nodeModel.addElement(newNode); - } - if (visualizers != null) { - for (int i = 0, n = visualizers.length; i < n; i++) { - visualizers[i].nodeAdded(newNode); - } - } - } - }); - } - } - return node; - } - - public void selectNodes(Node[] nodes) { - selectNodes(nodes, true); - } - - private void selectNodes(Node[] nodes, boolean updateList) { - if (nodes != selectedNodes) { - selectedNodes = nodes; - if (updateList) { - nodeList.clearSelection(); - if (selectedNodes != null) { - for (int i = 0, n = selectedNodes.length; i < n; i++) { - int index = nodeModel.indexOf(selectedNodes[i]); - if (index >= 0) { - nodeList.addSelectionInterval(index, index); - } - } - } - } - if (visualizers != null) { - for (int i = 0, n = visualizers.length; i < n; i++) { - visualizers[i].nodesSelected(nodes); - } - } - } - } - - public Node[] getSelectedNodes() { - return selectedNodes; - } - - - // ------------------------------------------------------------------- - // Node location handling - // ------------------------------------------------------------------- - - private boolean loadConfig(Properties properties, String configFile) { - try { - BufferedInputStream input = - new BufferedInputStream(new FileInputStream(configFile)); - try { - properties.load(input); - } finally { - input.close(); - } - return true; - } catch (FileNotFoundException e) { - // No configuration file exists. - } catch (IOException e) { - System.err.println("Failed to read configuration file: " + configFile); - e.printStackTrace(); - } - return false; - } - - private void save() { - if (configFile != null) { - configTable.setProperty("collect.bounds", "" + window.getX() + ',' + window.getY() + ',' + window.getWidth() + ',' + window.getHeight()); - if (visualizers != null) { - for(Visualizer v : visualizers) { - if (v instanceof Configurable) { - ((Configurable)v).updateConfig(configTable); - } - } - } - saveConfig(configTable, configFile); - } - } - - private void saveConfig(Properties properties, String configFile) { - try { - File fp = new File(configFile); - if (fp.exists()) { - File targetFp = new File(configFile + ".bak"); - if (targetFp.exists()) { - targetFp.delete(); - } - fp.renameTo(targetFp); - } - FileOutputStream output = new FileOutputStream(configFile); - try { - properties.store(output, "Configuration for Collect"); - } finally { - output.close(); - } - } catch (IOException e) { - System.err.println("failed to save configuration to " + configFile); - e.printStackTrace(); - } - } - - - // ------------------------------------------------------------------- - // Serial communication - // ------------------------------------------------------------------- - - public boolean sendToNode(String data) { - if (serialConnection != null && serialConnection.isOpen() && serialConnection.isSerialOutputSupported()) { - serialConsole.addSerialData("SEND: " + data); - serialConnection.writeSerialData(data); - return true; - } - return false; - } - - public void handleIncomingData(long systemTime, String line) { - if (line.length() == 0 || line.charAt(0) == '#') { - // Ignore empty lines, comments, and annotations. - return; - } - SensorData sensorData = SensorData.parseSensorData(this, line, systemTime); - if (sensorData != null) { - // Sensor data received - handleSensorData(sensorData); - return; - } - System.out.println("SERIAL: " + line); - serialConsole.addSerialData(line); - } - - // ------------------------------------------------------------------- - // Node time estimation - // ------------------------------------------------------------------- - - public long getNodeTime() { - return System.currentTimeMillis() + nodeTimeDelta; - } - - private void updateNodeTime(SensorData sensorData) { - this.nodeTimeDelta = sensorData.getNodeTime() - System.currentTimeMillis(); - } - - - // ------------------------------------------------------------------- - // SensorData handling - // ------------------------------------------------------------------- - - public int getSensorDataCount() { - return sensorDataList.size(); - } - - public SensorData getSensorData(int i) { - return sensorDataList.get(i); - } - - private void handleSensorData(final SensorData sensorData) { - System.out.println("SENSOR DATA: " + sensorData); - saveSensorData(sensorData); - if (sensorData.getNode().addSensorData(sensorData)) { - updateNodeTime(sensorData); - sensorDataList.add(sensorData); - handleLinks(sensorData); - if (visualizers != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - for (int i = 0, n = visualizers.length; i < n; i++) { - visualizers[i].nodeDataReceived(sensorData); - } - } - }); - } - } - } - - private void handleLinks(SensorData sensorData) { - String nodeID = sensorData.getBestNeighborID(); - if (nodeID != null) { - Node neighbor = addNode(nodeID); - Node source = sensorData.getNode(); - Link link = source.getLink(neighbor); - link.setETX(sensorData.getBestNeighborETX()); - link.setLastActive(sensorData.getNodeTime()); - } - } - - private void initSensorData() { - loadSensorData(SENSORDATA_FILE, true); - } - - private boolean loadSensorData(String filename, boolean isStrict) { - File fp = new File(filename); - if (fp.exists() && fp.canRead()) { - BufferedReader in = null; - try { - in = new BufferedReader(new FileReader(fp)); - String line; - int no = 0; - while ((line = in.readLine()) != null) { - no++; - if (line.length() == 0 || line.charAt(0) == '#') { - // Ignore empty lines and comments - } else { - SensorData data = SensorData.parseSensorData(this, line); - if (data != null) { - if (data.getNode().addSensorData(data)) { - updateNodeTime(data); - sensorDataList.add(data); - handleLinks(data); - } - } else if (isStrict) { - // TODO exit here? - System.err.println("Failed to parse sensor data from log line " + no + ": " + line); - } - } - } - in.close(); - } catch (IOException e) { - System.err.println("Failed to read sensor data log from " + fp.getAbsolutePath()); - e.printStackTrace(); - return false; - } - } - return true; - } - - private void saveSensorData(SensorData data) { - PrintWriter output = this.sensorDataOutput; - if (output == null && isSensorLogUsed) { - try { - output = sensorDataOutput = new PrintWriter(new FileWriter(SENSORDATA_FILE, true)); - } catch (IOException e) { - System.err.println("Failed to add sensor data to log '" + SENSORDATA_FILE + '\''); - e.printStackTrace(); - } - } - if (output != null) { - output.println(data.toString()); - output.flush(); - } - } - - private void clearSensorData() { - sensorDataList.clear(); - Node[] nodes = getNodes(); - this.selectedNodes = null; - nodeList.clearSelection(); - if (nodeModel.size() > 1) { - nodeModel.removeRange(1, nodeModel.size() - 1); - } - this.nodeTable.clear(); - synchronized (this) { - this.nodeCache = null; - } - if (nodes != null) { - for(Node node : nodes) { - node.removeAllSensorData(); - } - } - if (visualizers != null) { - for(Visualizer v : visualizers) { - v.nodesSelected(null); - v.clearNodeData(); - } - } - // Remove any saved node positions - for(String key: configTable.keySet().toArray(new String[0])) { - String property = key.toString(); - if (!property.startsWith("collect")) { - configTable.remove(property); - } - } - } - - private void clearSensorDataLog() { - PrintWriter output = this.sensorDataOutput; - if (output != null) { - output.close(); - } - // Remove the sensor data log - new File(SENSORDATA_FILE).delete(); - this.sensorDataOutput = null; - } - - protected class ConnectSerialAction extends AbstractAction implements Runnable { - - private static final long serialVersionUID = 1L; - - private boolean isRunning; - - public ConnectSerialAction(String name) { - super(name); - } - - public void actionPerformed(ActionEvent e) { - if (!isRunning) { - isRunning = true; - new Thread(this, "serial").start(); - } - } - - public void run() { - try { - if (serialConnection != null) { - if (serialConnection.isOpen()) { - serialConnection.close(); - } else { - connectToSerial(); - } - } else { - JOptionPane.showMessageDialog(window, "No serial connection configured", "Error", JOptionPane.ERROR_MESSAGE); - } - } finally { - isRunning = false; - } - } - - } - - protected class MoteProgramAction extends AbstractAction implements Runnable { - - private static final long serialVersionUID = 1L; - - private boolean isRunning = false; - - public MoteProgramAction(String name) { - super(name); - } - - public void actionPerformed(ActionEvent e) { - if (!isRunning) { - isRunning = true; - new Thread(this, "program thread").start(); - } - } - - @Override - public void run() { - try { - MoteProgrammer mp = new MoteProgrammer(); - mp.setParentComponent(window); - mp.setFirmwareFile(FIRMWARE_FILE); - mp.searchForMotes(); - String[] motes = mp.getMotes(); - if (motes == null || motes.length == 0) { - JOptionPane.showMessageDialog(window, "Could not find any connected nodes", "Error", JOptionPane.ERROR_MESSAGE); - return; - } - int reply = JOptionPane.showConfirmDialog(window, "Found " + motes.length + " connected nodes.\n" - + "Do you want to upload the firmware " + FIRMWARE_FILE + '?'); - if (reply == JFileChooser.APPROVE_OPTION) { - boolean wasOpen = serialConnection != null && serialConnection.isOpen(); - if (serialConnection != null) { - serialConnection.close(); - } - if (wasOpen) { - Thread.sleep(1000); - } - mp.programMotes(); - mp.waitForProcess(); - if (wasOpen) { - connectToSerial(); - } - } - } catch (Exception e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(window, "Programming failed: " + e, "Error", JOptionPane.ERROR_MESSAGE); - } finally { - isRunning = false; - } - } - - } - - - // ------------------------------------------------------------------- - // SerialConnection Listener - // ------------------------------------------------------------------- - - @Override - public void serialData(SerialConnection connection, String line) { - handleIncomingData(System.currentTimeMillis(), line); - } - - @Override - public void serialOpened(SerialConnection connection) { - String connectionName = connection.getConnectionName(); - serialConsole.addSerialData("*** Serial console listening on " + connectionName + " ***"); - hasSerialOpened = true; - if (connection.isMultiplePortsSupported()) { - String comPort = connection.getComPort(); - // Remember the last selected serial port - configTable.put("collect.serialport", comPort); - } - setSystemMessage("connected to " + connectionName); - - if (!connection.isSerialOutputSupported()) { - serialConsole.addSerialData("*** Serial output not supported ***"); - } else if (doSendInitAtStartup) { - // Send any initial commands - doSendInitAtStartup = false; - - if (hasInitScript()) { - // Wait a short time before running the init script - sleep(3000); - - runInitScript(); - } - } - } - - @Override - public void serialClosed(SerialConnection connection) { - String prefix; - if (hasSerialOpened) { - serialConsole.addSerialData("*** Serial connection terminated ***"); - prefix = "Serial connection terminated.\n"; - hasSerialOpened = false; - setSystemMessage("not connected"); - } else { - prefix = "Failed to connect to " + connection.getConnectionName() + '\n'; - } - if (!connection.isClosed()) { - if (connection.isMultiplePortsSupported()) { - String options[] = {"Retry", "Search for connected nodes", "Cancel"}; - int value = JOptionPane.showOptionDialog(window, - prefix + "Do you want to retry or search for connected nodes?", - "Reconnect to serial port?", - JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, - null, options, options[0]); - if (value == JOptionPane.CLOSED_OPTION || value == 2) { -// exit(); - } else { - String comPort = connection.getComPort(); - if (value == 1) { - // Select new serial port - comPort = MoteFinder.selectComPort(window); - if (comPort == null) { -// exit(); - } - } - // Try to open com port again - if (comPort != null) { - connection.open(comPort); - } - } - } else { -// JOptionPane.showMessageDialog(window, -// prefix, "Serial Connection Closed", JOptionPane.ERROR_MESSAGE); - } - } - } - - - // ------------------------------------------------------------------- - // Main - // ------------------------------------------------------------------- - - public static void main(String[] args) { - boolean resetSensorLog = false; - boolean useSensorLog = true; - boolean useSerialOutput = true; - String host = null; - String command = null; - String logFileToLoad = null; - String comPort = null; - int port = -1; - for(int i = 0, n = args.length; i < n; i++) { - String arg = args[i]; - if (arg.length() == 2 && arg.charAt(0) == '-') { - switch (arg.charAt(1)) { - case 'a': - if (i + 1 < n) { - host = args[++i]; - int pIndex = host.indexOf(':'); - if (pIndex > 0) { - port = Integer.parseInt(host.substring(pIndex + 1)); - host = host.substring(0, pIndex); - } - } else { - usage(arg); - } - break; - case 'c': - if (i + 1 < n) { - command = args[++i]; - } else { - usage(arg); - } - break; - case 'p': - if (i + 1 < n) { - port = Integer.parseInt(args[++i]); - } else { - usage(arg); - } - break; - case 'r': - resetSensorLog = true; - break; - case 'n': - useSensorLog = false; - break; - case 'i': - useSerialOutput = false; - break; - case 'f': - command = STDIN_COMMAND; - if (i + 1 < n && !args[i + 1].startsWith("-")) { - logFileToLoad = args[++i]; - } - break; - case 'h': - usage(null); - break; - default: - usage(arg); - break; - } - } else if (comPort == null) { - comPort = arg; - } else { - usage(arg); - } - } - - CollectServer server = new CollectServer(); - SerialConnection serialConnection; - if (host != null) { - if (port <= 0) { - port = 60001; - } - serialConnection = new TCPClientConnection(server, host, port); - } else if (port > 0) { - serialConnection = new UDPConnection(server, port); - } else if (command == null) { - serialConnection = new SerialDumpConnection(server); - } else if (command == STDIN_COMMAND) { - serialConnection = new StdinConnection(server); - } else { - serialConnection = new CommandConnection(server, command); - } - if (comPort == null) { - comPort = server.getConfig("collect.serialport"); - } - if (comPort != null) { - serialConnection.setComPort(comPort); - } - if (!useSerialOutput) { - serialConnection.setSerialOutputSupported(false); - } - - server.isSensorLogUsed = useSensorLog; - if (useSensorLog && resetSensorLog) { - server.clearSensorDataLog(); - } - if (logFileToLoad != null) { - server.loadSensorData(logFileToLoad, false); - } - server.start(serialConnection); - } - - private static void usage(String arg) { - if (arg != null) { - System.err.println("Unknown argument '" + arg + '\''); - } - System.err.println("Usage: java CollectServer [-n] [-i] [-r] [-f [file]] [-a host:port] [-p port] [-c command] [COMPORT]"); - System.err.println(" -n : Do not read or save sensor data log"); - System.err.println(" -r : Clear any existing sensor data log at startup"); - System.err.println(" -i : Do not allow serial output"); - System.err.println(" -f : Read serial data from standard in"); - System.err.println(" -a : Connect to specified host:port"); - System.err.println(" -p : Read data from specified UDP port"); - System.err.println(" -c : Use specified command for serial data input/output"); - System.err.println(" COMPORT: The serial port to connect to"); - System.exit(arg != null ? 1 : 0); - } -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/CommandConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/CommandConnection.java deleted file mode 100644 index dd19761b7..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/CommandConnection.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2010, 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. - * - * - * ----------------------------------------------------------------- - * - * CommandConnection - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 oct 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; - -/** - * - */ -public class CommandConnection extends SerialConnection { - - protected Process commandProcess; - protected String command; - - public CommandConnection(SerialConnectionListener listener) { - super(listener); - } - - public CommandConnection(SerialConnectionListener listener, String command) { - super(listener); - this.command = command; - } - - @Override - public String getConnectionName() { - return command; - } - - public String getCommand() { - return command; - } - - public void setCommand(String command) { - this.command = command; - } - - @Override - public void open(String comPort) { - close(); - this.comPort = comPort == null ? "" : comPort; - - String fullCommand = getCommand(); - - isClosed = false; - try { - String[] cmd = fullCommand.split(" "); - System.err.println("Running '" + fullCommand + '\''); - - commandProcess = Runtime.getRuntime().exec(cmd); - final BufferedReader input = new BufferedReader(new InputStreamReader(commandProcess.getInputStream())); - final BufferedReader err = new BufferedReader(new InputStreamReader(commandProcess.getErrorStream())); - setSerialOutput(new PrintWriter(new OutputStreamWriter(commandProcess.getOutputStream()))); - - /* Start thread listening on standard out */ - Thread readInput = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = input.readLine()) != null) { - standardData(line); - } - input.close(); - System.err.println("SerialConnection command terminated."); - closeConnection(); - } catch (IOException e) { - lastError = "Error when reading from SerialConnection command: " + e; - System.err.println(lastError); - if (!isClosed) { - e.printStackTrace(); - closeConnection(); - } - } - } - }, "read input stream thread"); - - /* Start thread listening on standard err */ - Thread readError = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = err.readLine()) != null) { - errorData(line); - } - err.close(); - } catch (IOException e) { - if (!isClosed) { - System.err.println("Error when reading from SerialConnection command: " + e); - e.printStackTrace(); - } - } - } - }, "read error stream thread"); - - if (!isOpen) { - isOpen = true; - serialOpened(); - } - readInput.start(); - readError.start(); - } catch (Exception e) { - lastError = "Failed to execute '" + fullCommand + "': " + e; - System.err.println(lastError); - e.printStackTrace(); - closeConnection(); - } - } - - protected void standardData(String line) { - serialData(line); - } - - protected void errorData(String line) { - System.err.println("SerialConnection error stream> " + line); - } - - @Override - protected void doClose() { - if (commandProcess != null) { - commandProcess.destroy(); - commandProcess = null; - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/Configurable.java b/tools/collect-view/src/org/contikios/contiki/collect/Configurable.java deleted file mode 100644 index 285bcca91..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/Configurable.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2010, 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. - * - * - * ----------------------------------------------------------------- - * - * Configurable - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 24 sep 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.util.Properties; - -/** - * - */ -public interface Configurable { - - public void updateConfig(Properties config); - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/Link.java b/tools/collect-view/src/org/contikios/contiki/collect/Link.java deleted file mode 100644 index 6575801b4..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/Link.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * Link - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - -/** - * - */ -public class Link { - - public final Node node; - - private double etx; - private int quality = 100; - private long lastActive = 0L; - - public Link(Node node) { - this.node = node; - this.lastActive = System.currentTimeMillis(); - } - - public Node getNode() { - return node; - } - - public int getQuality() { - return quality; - } - - public void setQuality(int quality) { - this.quality = quality; - } - - public double getETX() { - return etx; - } - - public void setETX(double etx) { - this.etx = etx; - } - - public long getLastActive() { - return lastActive; - } - - public void setLastActive(long time) { - this.lastActive = time; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java b/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java deleted file mode 100644 index 2c3c86d5b..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * Motelist - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 4 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.awt.Component; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.swing.JOptionPane; - -/** - * - */ -public class MoteFinder { - - public static final String MOTELIST_WINDOWS = "./tools/motelist-windows.exe"; - public static final String MOTELIST_LINUX = "./tools/motelist-linux"; - public static final String MOTELIST_MACOS = "./tools/motelist-macos"; - - private final Pattern motePattern; - private final boolean isWindows; - private final boolean isMacos; - private Process moteListProcess; -// private boolean hasVerifiedProcess; - private ArrayList comList = new ArrayList(); - private ArrayList moteList = new ArrayList(); - - public MoteFinder() { - String osName = System.getProperty("os.name", "").toLowerCase(); - isWindows = osName.startsWith("win"); - isMacos = osName.startsWith("mac"); - motePattern = Pattern.compile("\\s(COM|/dev/[a-zA-Z]+|/dev/tty.usbserial-)(\\d+|[A-Z0-9]+)\\s"); - } - - public String[] getMotes() throws IOException { - searchForMotes(); - return getMoteList(); - } - - public String[] getComPorts() throws IOException { - searchForMotes(); - return getComList(); - } - - private void searchForMotes() throws IOException { - comList.clear(); - moteList.clear(); -// hasVerifiedProcess = false; - - /* Connect to COM using external serialdump application */ - String fullCommand; - if (isWindows) { - fullCommand = MOTELIST_WINDOWS; - } else if (isMacos) { - fullCommand = MOTELIST_MACOS; - } else { - fullCommand = MOTELIST_LINUX; - } - - try { - String[] cmd = new String[] { fullCommand }; - moteListProcess = Runtime.getRuntime().exec(cmd); - final BufferedReader input = new BufferedReader(new InputStreamReader(moteListProcess.getInputStream())); - final BufferedReader err = new BufferedReader(new InputStreamReader(moteListProcess.getErrorStream())); - - /* Start thread listening on stdout */ - Thread readInput = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = input.readLine()) != null) { - parseIncomingLine(line); - } - input.close(); - } catch (IOException e) { - System.err.println("Exception when reading from motelist"); - e.printStackTrace(); - } - } - }, "read motelist thread"); - - /* Start thread listening on stderr */ - Thread readError = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = err.readLine()) != null) { - System.err.println("Motelist error stream> " + line); - } - err.close(); - } catch (IOException e) { - System.err.println("Exception when reading from motelist error stream: " + e); - } - } - }, "read motelist error stream thread"); - - readInput.start(); - readError.start(); - - // Wait for the motelist program to finish executing - readInput.join(); - } catch (Exception e) { - throw (IOException) new IOException("Failed to execute '" + fullCommand + "'").initCause(e); - } - } - - private String[] getComList() { - return comList.toArray(new String[comList.size()]); - } - - private String[] getMoteList() { - return moteList.toArray(new String[moteList.size()]); - } - - public void close() { - if (moteListProcess != null) { - moteListProcess.destroy(); - moteListProcess = null; - } - } - - protected void parseIncomingLine(String line) { - if (line.contains("No devices found") || line.startsWith("Reference")) { - // No Sky connected or title before connected motes -// hasVerifiedProcess = true; - } else if (line.startsWith("-------")) { - // Separator - } else { - Matcher matcher = motePattern.matcher(line); - if (matcher.find()) { - String dev = matcher.group(1); - String no = matcher.group(2); - String comPort = dev + no; - String moteID = comPort; - if (isWindows) { - // Special handling of mote id under Windows - int moteNumber = Integer.parseInt(no); - moteID = Integer.toString(moteNumber - 1); - } - comList.add(comPort); - moteList.add(moteID); - } else { - System.err.println("Motelist> " + line); - } - } - } - - public static String selectComPort(Component parent) { - MoteFinder finder = new MoteFinder(); - try { - String[] motes = finder.getComPorts(); - if (motes == null || motes.length == 0) { - JOptionPane.showMessageDialog(parent, "Could not find any connected motes.", "No mote found", JOptionPane.ERROR_MESSAGE); - return null; - } else if (motes.length == 1) { - // Only one node found - return motes[0]; - } else { - // Several motes found - return (String) JOptionPane.showInputDialog( - parent, "Found multiple connected motes. Please select serial port:", - "Select serial port", JOptionPane.QUESTION_MESSAGE, null, motes, motes[0]); - } - } catch (IOException e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(parent, "Failed to search for connected motes:\n" + e, "Error", JOptionPane.ERROR_MESSAGE); - return null; - } finally { - finder.close(); - } - } - - public static void main(String[] args) throws IOException { - MoteFinder finder = new MoteFinder(); - String[] comPorts = args.length > 0 && "-v".equals(args[0]) ? - finder.getMotes() : finder.getComPorts(); - finder.close(); - if (comPorts == null || comPorts.length == 0) { - System.out.println("No motes connected"); - } else { - for(String port: comPorts) { - System.out.println("Found Sky at " + port); - } - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammer.java b/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammer.java deleted file mode 100644 index 11809bf46..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammer.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * MoteProgrammer - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 10 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.awt.BorderLayout; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import java.io.IOException; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JPanel; -import javax.swing.JProgressBar; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.SwingUtilities; - -/** - * - */ -public class MoteProgrammer { - - private MoteProgrammerProcess[] processes; - private String[] motes; - private String firmwareFile; - - private Window parent; - private JProgressBar progressBar; - protected JTextArea logTextArea; - protected JDialog dialog; - protected JButton closeButton; - private boolean isDone; - - public MoteProgrammer() { - } - - public Window getParentComponent() { - return parent; - } - - public void setParentComponent(Window parent) { - this.parent = parent; - } - - public boolean hasMotes() { - return motes != null && motes.length > 0; - } - - public String[] getMotes() { - return motes; - } - - public void setMotes(String[] motes) { - this.motes = motes; - } - - public void searchForMotes() throws IOException { - MoteFinder finder = new MoteFinder(); - motes = finder.getMotes(); - finder.close(); - } - - public String getFirmwareFile() { - return firmwareFile; - } - - public void setFirmwareFile(String firmwareFile) { - this.firmwareFile = firmwareFile; - } - - public void programMotes() throws IOException { - if (firmwareFile == null) { - throw new IllegalStateException("no firmware"); - } - if (!hasMotes()) { - throw new IllegalStateException("no motes"); - } - File fp = new File(firmwareFile); - if (!fp.canRead()) { - throw new IllegalStateException("can not read firmware file '" + fp.getAbsolutePath() + '\''); - } - if (parent != null) { - // Use GUI - dialog = new JDialog(parent, "Mote Programmer"); - progressBar = new JProgressBar(0, 100); - progressBar.setValue(0); - progressBar.setString("Programming..."); - progressBar.setStringPainted(true); - progressBar.setIndeterminate(true); - dialog.getContentPane().add(progressBar, BorderLayout.NORTH); - - logTextArea = new JTextArea(28, 80); - logTextArea.setEditable(false); - logTextArea.setLineWrap(true); - dialog.getContentPane().add(new JScrollPane(logTextArea), BorderLayout.CENTER); - JPanel panel = new JPanel(); - closeButton = new JButton("Cancel"); - closeButton.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - MoteProgrammer.this.close(); - } - - }); - panel.add(closeButton); - dialog.getContentPane().add(panel, BorderLayout.SOUTH); - dialog.pack(); - dialog.setLocationRelativeTo(parent); - dialog.setVisible(true); - } - processes = new MoteProgrammerProcess[motes.length]; - isDone = false; - try { - log("Programming " + motes.length + " motes with '" + firmwareFile + '\'', null); - for (int i = 0, n = processes.length; i < n; i++) { - processes[i] = new MoteProgrammerProcess(motes[i], firmwareFile) { - protected void logLine(String line, boolean stderr, Throwable e) { - if (!handleLogLine(this, line, stderr, e)) { - super.logLine(line, stderr, e); - } - } - protected void processEnded() { - handleProcessEnded(this); - } - }; - processes[i].start(); - } - } catch (Exception e) { - throw (IOException) new IOException("Failed to program motes").initCause(e); - } - } - - public synchronized void waitForProcess() throws InterruptedException { - while (!isDone) { - wait(); - } - } - - public void close() { - MoteProgrammerProcess[] processes = this.processes; - if (processes != null) { - this.processes = null; - for (int i = 0, n = processes.length; i < n; i++) { - if (processes[i] != null) { - processes[i].stop(); - } - } - } - if (dialog != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - dialog.setVisible(false); - } - }); - } - isDone = true; - synchronized (this) { - notifyAll(); - } - } - - protected void handleProcessEnded(MoteProgrammerProcess process) { - // Another process has finished - log("Mote@" + process.getMoteID() + "> finished" + (process.hasError() ? " with errors": ""), null); - MoteProgrammerProcess[] processes = this.processes; - if (processes != null) { - int running = 0; - int errors = 0; - for(MoteProgrammerProcess p: processes) { - if (p.isRunning()) { - running++; - } else if (p.hasError()) { - errors++; - } - } - if (running == 0) { - // All processes has finished - isDone = true; - final String doneMessage = "Programming finished with " + errors + " errors."; - log(doneMessage, null); - if (closeButton != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - progressBar.setValue(100); - progressBar.setIndeterminate(false); - progressBar.setString(doneMessage); - closeButton.setText("Close"); - }}); - } - synchronized (this) { - notifyAll(); - } - } - } - } - - protected boolean handleLogLine(MoteProgrammerProcess moteProgrammerProcess, - String line, boolean stderr, final Throwable e) { - log("Mote@" + moteProgrammerProcess.getMoteID() + "> " + line, e); - return true; - } - - private void log(String line, final Throwable e) { - System.err.println(line); - if (e != null) { - e.printStackTrace(); - line += "\n " + e; - } - final String text = line; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - int len = logTextArea.getDocument().getLength(); - if (len == 0) { - logTextArea.append(text); - } else { - logTextArea.append('\n' + text); - len++; - } - logTextArea.setCaretPosition(len + text.length()); - } - }); - } - - public static void main(String[] args) throws IOException { - MoteProgrammer mp = new MoteProgrammer(); - if (args.length < 1 || args.length > 2) { - System.err.println("Usage: MoteProgrammer [mote]"); - System.exit(1); - } - mp.setFirmwareFile(args[0]); - if (args.length == 2) { - mp.setMotes(new String[] { args[1] }); - } else { - mp.searchForMotes(); - } - if (!mp.hasMotes()) { - System.err.println("No motes connected"); - System.exit(1); - } - mp.programMotes(); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammerProcess.java b/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammerProcess.java deleted file mode 100644 index 1878abc41..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/MoteProgrammerProcess.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * MoteProgrammerProcess - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 10 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -/** - * - */ -public class MoteProgrammerProcess { - - public static final String BSL_WINDOWS = "./tools/msp430-bsl-windows.exe"; - public static final String BSL_LINUX = "./tools/msp430-bsl-linux"; - - private final String moteID; - private final String firmwareFile; - private final String[][] commandSet; - private int retry = 3; - - private Process currentProcess; - private Thread commandThread; - private boolean isRunning; - private boolean hasError; - - public MoteProgrammerProcess(String moteID, String firmwareFile) { - this.moteID = moteID; - this.firmwareFile = firmwareFile; - String osName = System.getProperty("os.name").toLowerCase(); - String bslCommand; - if (osName.startsWith("win")) { - bslCommand = BSL_WINDOWS; - } else { - bslCommand = BSL_LINUX; - } - commandSet = new String[][] { - { bslCommand, "--telosb", "-c", moteID, "-e" }, - { bslCommand, "--telosb", "-c", moteID, "-I", "-p", firmwareFile }, - { bslCommand, "--telosb", "-c", moteID, "-r" } - }; - } - - public String getMoteID() { - return moteID; - } - - public String getFirmwareFile() { - return firmwareFile; - } - - public int getRetry() { - return retry; - } - - public void setRetry(int retry) { - this.retry = retry; - } - - public boolean isRunning() { - return isRunning; - } - - public boolean hasError() { - return hasError; - } - - public void start() { - if (isRunning) { - // Already running - return; - } - isRunning = true; - commandThread = new Thread(new Runnable() { - public void run() { - try { - int count = 0; - do { - if (count > 0) { - logLine("An error occurred. Retrying.", true, null); - } - count++; - hasError = false; - for (int j = 0, m = commandSet.length; j < m && isRunning && !hasError; j++) { - runCommand(commandSet[j]); - Thread.sleep(2000); - } - } while (isRunning && hasError && count < retry); - } catch (Exception e) { - e.printStackTrace(); - } finally { - isRunning = false; - processEnded(); - } - } - }); - commandThread.start(); - } - - public void stop() { - isRunning = false; - Process process = currentProcess; - if (process != null) { - process.destroy(); - } - } - - public void waitForProcess() throws InterruptedException { - if (isRunning && commandThread != null) { - commandThread.join(); - } - } - - protected void processEnded() { - } - - private void runCommand(String[] cmd) throws IOException, InterruptedException { - if (currentProcess != null) { - currentProcess.destroy(); - } - currentProcess = Runtime.getRuntime().exec(cmd); - final BufferedReader input = new BufferedReader(new InputStreamReader(currentProcess.getInputStream())); - final BufferedReader err = new BufferedReader(new InputStreamReader(currentProcess.getErrorStream())); - - /* Start thread listening on stdout */ - Thread readInput = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = input.readLine()) != null) { - handleLine(line, false); - } - input.close(); - } catch (IOException e) { - logLine("Error reading from command", false, e); - } - } - }, "read stdout thread"); - - /* Start thread listening on stderr */ - Thread readError = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = err.readLine()) != null) { - handleLine(line, true); - } - err.close(); - } catch (IOException e) { - logLine("Error reading from command", true, e); - } - } - }, "read stderr thread"); - - readInput.start(); - readError.start(); - - // Wait for the bsl program to finish executing - readInput.join(); - currentProcess = null; - } - - private void handleLine(String line, boolean stderr) { - if (line.toLowerCase().contains("error")) { - hasError = true; - } - logLine(line, stderr, null); - } - - protected void logLine(String line, boolean stderr, Throwable e) { - if (stderr) { - System.err.println("Programmer@" + moteID + "> " + line); - } else { - System.out.println("Programmer@" + moteID + "> " + line); - } - if (e != null) { - e.printStackTrace(); - } - } - - protected String toString(String[] cmd) { - StringBuilder sb = new StringBuilder(); - for (int i = 0, n = cmd.length; i < n; i++) { - if (i > 0) sb.append(' '); - sb.append(cmd[i]); - } - return sb.toString(); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/Node.java b/tools/collect-view/src/org/contikios/contiki/collect/Node.java deleted file mode 100644 index 8dc934bbd..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/Node.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * Node - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.util.ArrayList; -import java.util.Hashtable; - -/** - * - */ -public class Node implements Comparable { - - private static final boolean SINGLE_LINK = true; - - private SensorDataAggregator sensorDataAggregator; - private ArrayList sensorDataList = new ArrayList(); - private ArrayList links = new ArrayList(); - - private final String id; - private final String name; - - private Hashtable objectTable; - - private long lastActive; - - public Node(String nodeID) { - this(nodeID, nodeID); - } - - public Node(String nodeID, String nodeName) { - this.id = nodeID; - this.name = nodeName; - sensorDataAggregator = new SensorDataAggregator(this); - } - - public final String getID() { - return id; - } - - public final String getName() { - return name; - } - - public long getLastActive() { - return lastActive; - } - - public void setLastActive(long lastActive) { - this.lastActive = lastActive; - } - - @Override - public int compareTo(Node o) { - String i1 = id; - String i2 = o.getID(); - // Shorter id first (4.0 before 10.0) - if (i1.length() == i2.length()) { - return i1.compareTo(i2); - } - return i1.length() - i2.length(); - } - - public String toString() { - return name; - } - - - // ------------------------------------------------------------------- - // Attributes - // ------------------------------------------------------------------- - - public Object getAttribute(String key) { - return getAttribute(key, null); - } - - public Object getAttribute(String key, Object defaultValue) { - if (objectTable == null) { - return null; - } - Object val = objectTable.get(key); - return val == null ? defaultValue : val; - } - - public void setAttribute(String key, Object value) { - if (objectTable == null) { - objectTable = new Hashtable(); - } - objectTable.put(key, value); - } - - public void clearAttributes() { - if (objectTable != null) { - objectTable.clear(); - } - } - - - // ------------------------------------------------------------------- - // SensorData - // ------------------------------------------------------------------- - - public SensorDataAggregator getSensorDataAggregator() { - return sensorDataAggregator; - } - - public SensorData[] getAllSensorData() { - return sensorDataList.toArray(new SensorData[sensorDataList.size()]); - } - - public void removeAllSensorData() { - sensorDataList.clear(); - sensorDataAggregator.clear(); - } - - public SensorData getSensorData(int index) { - return sensorDataList.get(index); - } - - public int getSensorDataCount() { - return sensorDataList.size(); - } - - public boolean addSensorData(SensorData data) { - if (sensorDataList.size() > 0) { - SensorData last = sensorDataList.get(sensorDataList.size() - 1); - if (data.getNodeTime() < last.getNodeTime()) { - // Sensor data already added - System.out.println("SensorData: ignoring (time " + (data.getNodeTime() - last.getNodeTime()) - + "msec): " + data); - return false; - } - } - sensorDataList.add(data); - sensorDataAggregator.addSensorData(data); - return true; - } - - - // ------------------------------------------------------------------- - // Links - // ------------------------------------------------------------------- - - public Link getLink(Node node) { - for(Link l: links) { - if (l.node == node) { - return l; - } - } - - // Add new link - Link l = new Link(node); - if (SINGLE_LINK) { - links.clear(); - } - links.add(l); - return l; - } - - public Link getLink(int index) { - return links.get(index); - } - - public int getLinkCount() { - return links.size(); - } - - public void removeLink(Node node) { - for (int i = 0, n = links.size(); i < n; i++) { - Link l = links.get(i); - if (l.node == node) { - links.remove(i); - break; - } - } - } - - public void clearLinks() { - links.clear(); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SensorData.java b/tools/collect-view/src/org/contikios/contiki/collect/SensorData.java deleted file mode 100644 index 8e3445d58..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SensorData.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * SensorData - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2011/01/09 21:06:10 $ - * $Revision: 1.2 $ - */ - -package org.contikios.contiki.collect; -import java.util.Arrays; - -/** - * - */ -public class SensorData implements SensorInfo { - - private final Node node; - private final int[] values; - private final long nodeTime; - private final long systemTime; - private int seqno; - private boolean isDuplicate; - - public SensorData(Node node, int[] values, long systemTime) { - this.node = node; - this.values = values; - this.nodeTime = ((values[TIMESTAMP1] << 16) + values[TIMESTAMP2]) * 1000L; - this.systemTime = systemTime; - this.seqno = values[SEQNO]; - } - - public Node getNode() { - return node; - } - - public String getNodeID() { - return node.getID(); - } - - public boolean isDuplicate() { - return isDuplicate; - } - - public void setDuplicate(boolean isDuplicate) { - this.isDuplicate = isDuplicate; - } - - public int getSeqno() { - return seqno; - } - - public void setSeqno(int seqno) { - this.seqno = seqno; - } - - public int getValue(int index) { - return values[index]; - } - - public int getValueCount() { - return values.length; - } - - public long getNodeTime() { - return nodeTime; - } - - public long getSystemTime() { - return systemTime; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - if (systemTime > 0L) { - sb.append(systemTime).append(' '); - } - for (int i = 0, n = values.length; i < n; i++) { - if (i > 0) sb.append(' '); - sb.append(values[i]); - } - return sb.toString(); - } - - public static SensorData parseSensorData(CollectServer server, String line) { - return parseSensorData(server, line, 0); - } - - public static SensorData parseSensorData(CollectServer server, String line, long systemTime) { - String[] components = line.trim().split("[ \t]+"); - // Check if COOJA log - if (components.length == VALUES_COUNT + 2 && components[1].startsWith("ID:")) { - if (!components[2].equals("" + VALUES_COUNT)) { - // Ignore non sensor data - return null; - } - try { - systemTime = Long.parseLong(components[0]); - components = Arrays.copyOfRange(components, 2, components.length); - } catch (NumberFormatException e) { - // First column does not seem to be system time - } - - } else if (components[0].length() > 8) { - // Sensor data prefixed with system time - try { - systemTime = Long.parseLong(components[0]); - components = Arrays.copyOfRange(components, 1, components.length); - } catch (NumberFormatException e) { - // First column does not seem to be system time - } - } - if (components.length != SensorData.VALUES_COUNT) { - return null; - } - // Sensor data line (probably) - int[] data = parseToInt(components); - if (data == null || data[0] != VALUES_COUNT) { - System.err.println("Failed to parse data line: '" + line + "'"); - return null; - } - String nodeID = mapNodeID(data[NODE_ID]); - Node node = server.addNode(nodeID); - return new SensorData(node, data, systemTime); - } - - public static String mapNodeID(int nodeID) { - return "" + (nodeID & 0xff) + '.' + ((nodeID >> 8) & 0xff); - } - - private static int[] parseToInt(String[] text) { - try { - int[] data = new int[text.length]; - for (int i = 0, n = data.length; i < n; i++) { - data[i] = Integer.parseInt(text[i]); - } - return data; - } catch (NumberFormatException e) { - return null; - } - } - - public double getCPUPower() { - return (values[TIME_CPU] * POWER_CPU) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getLPMPower() { - return (values[TIME_LPM] * POWER_LPM) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getListenPower() { - return (values[TIME_LISTEN] * POWER_LISTEN) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getTransmitPower() { - return (values[TIME_TRANSMIT] * POWER_TRANSMIT) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getAveragePower() { - return (values[TIME_CPU] * POWER_CPU + values[TIME_LPM] * POWER_LPM - + values[TIME_LISTEN] * POWER_LISTEN + values[TIME_TRANSMIT] * POWER_TRANSMIT) - / (values[TIME_CPU] + values[TIME_LPM]); - } - - public long getPowerMeasureTime() { - return (1000L * (values[TIME_CPU] + values[TIME_LPM])) / TICKS_PER_SECOND; - } - - public double getTemperature() { - return -39.6 + 0.01 * values[TEMPERATURE]; - } - - public double getBatteryVoltage() { - return values[BATTERY_VOLTAGE] * 2 * 2.5 / 4096.0; - } - - public double getBatteryIndicator() { - return values[BATTERY_INDICATOR]; - } - - public double getRadioIntensity() { - return values[RSSI]; - } - - public double getLatency() { - return values[LATENCY] / 32678.0; - } - - public double getHumidity() { - double v = -4.0 + 405.0 * values[HUMIDITY] / 10000.0; - if(v > 100) { - return 100; - } - return v; - } - - public double getLight1() { - return 10.0 * values[LIGHT1] / 7.0; - } - - public double getLight2() { - return 46.0 * values[LIGHT2] / 10.0; - } - - public String getBestNeighborID() { - return values[BEST_NEIGHBOR] > 0 ? mapNodeID(values[BEST_NEIGHBOR]): null; - } - - public double getBestNeighborETX() { - return values[BEST_NEIGHBOR_ETX] / 8.0; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SensorDataAggregator.java b/tools/collect-view/src/org/contikios/contiki/collect/SensorDataAggregator.java deleted file mode 100644 index a8bfc2a95..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SensorDataAggregator.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * SensorDataAggregator - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 20 aug 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - -/** - * - */ -public class SensorDataAggregator implements SensorInfo { - - private final Node node; - private long[] values; - private int minSeqno = Integer.MAX_VALUE; - private int maxSeqno = Integer.MIN_VALUE; - private int seqnoDelta = 0; - private int dataCount; - private int duplicates = 0; - private int lost = 0; - private int nodeRestartCount = 0; - private int nextHopChangeCount = 0; - private int lastNextHop = -1; - private long shortestPeriod = Long.MAX_VALUE; - private long longestPeriod = 0; - - public SensorDataAggregator(Node node) { - this.node = node; - this.values = new long[VALUES_COUNT]; - } - - public Node getNode() { - return node; - } - - public String getNodeID() { - return node.getID(); - } - - public long getValue(int index) { - return values[index]; - } - - public double getAverageValue(int index) { - return dataCount > 0 ? (double)values[index] / (double)dataCount : 0; - } - - public int getValueCount() { - return values.length; - } - - public int getDataCount() { - return dataCount; - } - - public void addSensorData(SensorData data) { - int seqn = data.getValue(SEQNO); - int s = seqn + seqnoDelta; - - int bestNeighbor = data.getValue(BEST_NEIGHBOR); - if (lastNextHop != bestNeighbor && lastNextHop >= 0) { - nextHopChangeCount++; - } - lastNextHop = bestNeighbor; - - if (s <= maxSeqno) { - // Check for duplicates among the last 5 packets - for(int n = node.getSensorDataCount() - 1, i = n > 5 ? n - 5 : 0; i < n; i++) { - SensorData sd = node.getSensorData(i); - if (sd.getValue(SEQNO) != seqn || sd == data || sd.getValueCount() != data.getValueCount()) { - // Not a duplicate - } else if (Math.abs(data.getNodeTime() - sd.getNodeTime()) > 180000) { - // Too long time between packets. Not a duplicate. -// System.err.println("Too long time between packets with same seqno from " -// + data.getNode() + ": " -// + (Math.abs(data.getNodeTime() - sd.getNodeTime()) / 1000) -// + " sec, " + (n - i) + " packets ago"); - } else { - data.setDuplicate(true); - - // Verify that the packet is a duplicate - for(int j = DATA_LEN2, m = data.getValueCount(); j < m; j++) { - if (sd.getValue(j) != data.getValue(j)) { - data.setDuplicate(false); -// System.out.println("NOT Duplicate: " + data.getNode() + " (" -// + (n - i) + ": " -// + ((data.getNodeTime() - sd.getNodeTime()) / 1000) + "sek): " -// + seqn + " value[" + j + "]: " + sd.getValue(j) + " != " -// + data.getValue(j)); - break; - } - } - if (data.isDuplicate()) { -// System.out.println("Duplicate: " + data.getNode() + ": " + seqn -// + ": " -// + (Math.abs(data.getNodeTime() - sd.getNodeTime()) / 1000) -// + " sec, " + (n - i) + " packets ago"); - duplicates++; - break; - } - } - } - } - - if (!data.isDuplicate()) { - for (int i = 0, n = Math.min(VALUES_COUNT, data.getValueCount()); i < n; i++) { - values[i] += data.getValue(i); - } - - if (node.getSensorDataCount() > 1) { - long timeDiff = data.getNodeTime() - node.getSensorData(node.getSensorDataCount() - 2).getNodeTime(); - if (timeDiff > longestPeriod) { - longestPeriod = timeDiff; - } - if (timeDiff < shortestPeriod) { - shortestPeriod = timeDiff; - } - } - if (dataCount == 0) { - // First packet from node. - } else if (maxSeqno - s > 2) { - // Handle sequence number overflow. - seqnoDelta = maxSeqno + 1; - s = seqnoDelta + seqn; - if (seqn > 127) { - // Sequence number restarted at 128 (to separate node restarts - // from sequence number overflow). - seqn -= 128; - seqnoDelta -= 128; - s -= 128; - } else { - // Sequence number restarted at 0. This is usually an indication that - // the node restarted. - nodeRestartCount++; - } - if (seqn > 0) { - lost += seqn; - } - } else if (s > maxSeqno + 1){ - lost += s - (maxSeqno + 1); - } - if (s < minSeqno) minSeqno = s; - if (s > maxSeqno) maxSeqno = s; - dataCount++; - } - data.setSeqno(s); - } - - public void clear() { - for (int i = 0, n = values.length; i < n; i++) { - values[i] = 0L; - } - dataCount = 0; - duplicates = 0; - lost = 0; - nodeRestartCount = 0; - nextHopChangeCount = 0; - lastNextHop = 0; - minSeqno = Integer.MAX_VALUE; - maxSeqno = Integer.MIN_VALUE; - seqnoDelta = 0; - shortestPeriod = Long.MAX_VALUE; - longestPeriod = 0; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - for (int i = 0, n = values.length; i < n; i++) { - if (i > 0) sb.append(' '); - sb.append(values[i]); - } - return sb.toString(); - } - - public double getCPUPower() { - return (values[TIME_CPU] * POWER_CPU) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getLPMPower() { - return (values[TIME_LPM] * POWER_LPM) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getListenPower() { - return (values[TIME_LISTEN] * POWER_LISTEN) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getTransmitPower() { - return (values[TIME_TRANSMIT] * POWER_TRANSMIT) / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getAveragePower() { - return (values[TIME_CPU] * POWER_CPU + values[TIME_LPM] * POWER_LPM - + values[TIME_LISTEN] * POWER_LISTEN + values[TIME_TRANSMIT] * POWER_TRANSMIT) - / (values[TIME_CPU] + values[TIME_LPM]); - } - - public double getAverageDutyCycle(int index) { - return (double)(values[index]) / (double)(values[TIME_CPU] + values[TIME_LPM]); - } - - public long getPowerMeasureTime() { - return (1000L * (values[TIME_CPU] + values[TIME_LPM])) / TICKS_PER_SECOND; - } - - public double getAverageTemperature() { - return dataCount > 0 ? (-39.6 + 0.01 * (values[TEMPERATURE] / dataCount)) : 0.0; - } - - public double getAverageRtmetric() { - return getAverageValue(RTMETRIC); - } - - public double getAverageRadioIntensity() { - return getAverageValue(RSSI); - } - - public double getAverageLatency() { - return getAverageValue(LATENCY) / 4096.0; - } - - public double getAverageHumidity() { - double v = 0.0; - if (dataCount > 0) { - v = -4.0 + 405.0 * (values[HUMIDITY] / dataCount) / 10000.0; - } - return v > 100 ? 100 : v; - } - - public double getAverageLight1() { - return 10.0 * getAverageValue(LIGHT1) / 7.0; - } - - public double getAverageLight2() { - return 46.0 * getAverageValue(LIGHT2) / 10.0; - } - - public double getAverageBestNeighborETX() { - return getAverageValue(BEST_NEIGHBOR_ETX) / 8.0; - } - - public int getPacketCount() { - return node.getSensorDataCount(); - } - - public int getNextHopChangeCount() { - return nextHopChangeCount; - } - - public int getEstimatedRestarts() { - return nodeRestartCount; - } - - public int getEstimatedLostCount() { - return lost; - } - - public int getDuplicateCount() { - return duplicates; - } - - public int getMinSeqno() { - return minSeqno; - } - - public int getMaxSeqno() { - return maxSeqno; - } - - public long getAveragePeriod() { - if (dataCount > 1) { - long first = node.getSensorData(0).getNodeTime(); - long last = node.getSensorData(node.getSensorDataCount() - 1).getNodeTime(); - return (last - first) / dataCount; - } - return 0; - } - - public long getShortestPeriod() { - return shortestPeriod < Long.MAX_VALUE ? shortestPeriod : 0; - } - - public long getLongestPeriod() { - return longestPeriod; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SensorInfo.java b/tools/collect-view/src/org/contikios/contiki/collect/SensorInfo.java deleted file mode 100644 index 51043d1c3..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SensorInfo.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * SensorInfo - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 20 aug 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - - -/** - * - */ -public interface SensorInfo { - - public static final long TICKS_PER_SECOND = 4096L; - public static final double VOLTAGE = 3; - public static final double POWER_CPU = 1.800 * VOLTAGE; /* mW */ - public static final double POWER_LPM = 0.0545 * VOLTAGE; /* mW */ - public static final double POWER_TRANSMIT = 17.7 * VOLTAGE; /* mW */ - public static final double POWER_LISTEN = 20.0 * VOLTAGE; /* mW */ - - public static final int DATA_LEN = 0; - public static final int TIMESTAMP1 = 1; - public static final int TIMESTAMP2 = 2; - public static final int TIMESYNCTIMESTAMP = 3; - public static final int NODE_ID = 4; - public static final int SEQNO = 5; - public static final int HOPS = 6; - public static final int LATENCY = 7; - public static final int DATA_LEN2 = 8; - public static final int CLOCK = 9; - public static final int TIMESYNCHTIME = 10; - public static final int TIME_CPU = 11; - public static final int TIME_LPM = 12; - public static final int TIME_TRANSMIT = 13; - public static final int TIME_LISTEN = 14; - public static final int BEST_NEIGHBOR = 15; - public static final int BEST_NEIGHBOR_ETX = 16; - public static final int RTMETRIC = 17; - public static final int NUM_NEIGHBORS = 18; - public static final int BEACON_INTERVAL = 19; - public static final int BATTERY_VOLTAGE = 20; - public static final int BATTERY_INDICATOR = 21; - public static final int LIGHT1 = 22; - public static final int LIGHT2 = 23; - public static final int TEMPERATURE = 24; - public static final int HUMIDITY = 25; - public static final int RSSI = 26; - - public static final int VALUES_COUNT = 30; - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SerialConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/SerialConnection.java deleted file mode 100644 index c2d140a03..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SerialConnection.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * SerialConnection - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.io.PrintWriter; - -/** - * - */ -public abstract class SerialConnection { - - protected final SerialConnectionListener listener; - - protected boolean isSerialOutputSupported = true; - - protected String comPort; - protected boolean isOpen; - protected boolean isClosed = true; - protected String lastError; - - protected PrintWriter serialOutput; - - protected SerialConnection(SerialConnectionListener listener) { - this.listener = listener; - } - - public boolean isMultiplePortsSupported() { - return false; - } - - public void setSerialOutputSupported(boolean isSerialOutputSupported) { - this.isSerialOutputSupported = isSerialOutputSupported; - } - - public boolean isSerialOutputSupported() { - return isSerialOutputSupported; - } - - public boolean isOpen() { - return isOpen; - } - - public boolean isClosed() { - return isClosed; - } - - public abstract String getConnectionName(); - - public String getComPort() { - return comPort; - } - - public void setComPort(String comPort) { - this.comPort = comPort; - } - - public String getLastError() { - return lastError; - } - - protected PrintWriter getSerialOutput() { - return serialOutput; - } - - protected void setSerialOutput(PrintWriter serialOutput) { - this.serialOutput = serialOutput; - } - - public void writeSerialData(String data) { - PrintWriter serialOutput = this.serialOutput; - if (serialOutput != null) { - serialOutput.println(data); - serialOutput.flush(); - } - } - - public abstract void open(String comPort); - - public final void close() { - isClosed = true; - lastError = null; - closeConnection(); - } - - protected final void closeConnection() { - isOpen = false; - if (serialOutput != null) { - serialOutput.close(); - serialOutput = null; - } - doClose(); - serialClosed(); - } - - protected abstract void doClose(); - - protected final void serialData(String line) { - listener.serialData(this, line); - } - - protected final void serialOpened() { - listener.serialOpened(this); - } - - protected final void serialClosed() { - listener.serialClosed(this); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SerialConnectionListener.java b/tools/collect-view/src/org/contikios/contiki/collect/SerialConnectionListener.java deleted file mode 100644 index 5e266c6e1..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SerialConnectionListener.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2010, 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. - * - * - * ----------------------------------------------------------------- - * - * SerialConnectionListener - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 oct 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ -package org.contikios.contiki.collect; - -public interface SerialConnectionListener { - - public void serialData(SerialConnection connection, String line); - - public void serialOpened(SerialConnection connection); - - public void serialClosed(SerialConnection connection); - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java deleted file mode 100644 index c624ea64a..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2010, 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. - * - * - * ----------------------------------------------------------------- - * - * SerialDumpConnection - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 oct 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - -/** - * - */ -public class SerialDumpConnection extends CommandConnection { - - public static final String SERIALDUMP_WINDOWS = "./tools/serialdump-windows.exe"; - public static final String SERIALDUMP_LINUX = "./tools/serialdump-linux"; - public static final String SERIALDUMP_MACOS = "./tools/serialdump-macos"; - - public SerialDumpConnection(SerialConnectionListener listener) { - super(listener); - } - - @Override - public boolean isMultiplePortsSupported() { - return true; - } - - @Override - public String getConnectionName() { - return comPort; - } - - @Override - public void open(String comPort) { - if (comPort == null) { - throw new IllegalStateException("no com port"); - } - - /* Connect to COM using external serialdump application */ - String osName = System.getProperty("os.name").toLowerCase(); - String fullCommand; - if (osName.startsWith("win")) { - fullCommand = SERIALDUMP_WINDOWS + " " + "-b115200" + " " + getMappedComPortForWindows(comPort); - } else if (osName.startsWith("mac")) { - fullCommand = SERIALDUMP_MACOS + " " + "-b115200" + " " + comPort; - } else { - fullCommand = SERIALDUMP_LINUX + " " + "-b115200" + " " + comPort; - } - setCommand(fullCommand); - super.open(comPort); - } - - @Override - protected void standardData(String line) { - serialData(line); - } - - @Override - protected void errorData(String line) { - if (!isOpen && line.startsWith("connecting") && line.endsWith("[OK]")) { - isOpen = true; - serialOpened(); - } else { - super.errorData(line); - } - } - - private String getMappedComPortForWindows(String comPort) { - if (comPort.startsWith("COM")) { - comPort = "/dev/com" + comPort.substring(3); - } - return comPort; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/StdinConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/StdinConnection.java deleted file mode 100644 index 337a01a29..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/StdinConnection.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2010, 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. - * - * - * ----------------------------------------------------------------- - * - * StdinConnection - * - * Authors : Niclas Finne - * Created : 5 oct 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; - -/** - * - */ -public class StdinConnection extends SerialConnection { - - private PrintWriter stdout; - - public StdinConnection(SerialConnectionListener listener) { - super(listener); - // Redirect standard out as standard err to use standard out for serial output - stdout = new PrintWriter(new OutputStreamWriter(System.out)); - System.setOut(System.err); - } - - @Override - public String getConnectionName() { - return ""; - } - - @Override - public void open(String comPort) { - close(); - this.comPort = comPort == null ? "" : comPort; - - isClosed = false; - try { - final BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); - setSerialOutput(stdout); - - /* Start thread listening on standard in */ - Thread readInput = new Thread(new Runnable() { - public void run() { - String line; - try { - while ((line = input.readLine()) != null) { - serialData(line); - // Do not send data too fast - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - input.close(); - System.out.println("SerialConnection stdin terminated."); - closeConnection(); - } catch (IOException e) { - lastError = "Error when reading from SerialConnection stdin: " + e; - System.err.println(lastError); - if (!isClosed) { - e.printStackTrace(); - closeConnection(); - } - } - } - }, "read input stream thread"); - - isOpen = true; - serialOpened(); - readInput.start(); - - } catch (Exception e) { - lastError = "Failed to open stdin for reading: " + e; - System.err.println(lastError); - e.printStackTrace(); - closeConnection(); - } - } - - @Override - protected void doClose() { - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/TCPClientConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/TCPClientConnection.java deleted file mode 100644 index 6a04f8b65..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/TCPClientConnection.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2012, 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. - * - * ----------------------------------------------------------------- - * - * TCPClientConnection - * - * Authors : Niclas Finne - */ - -package org.contikios.contiki.collect; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.net.Socket; - -/** - * - */ -public class TCPClientConnection extends SerialConnection { - - private final String host; - private final int port; - - private Socket client; - private BufferedReader in; - private PrintStream out; - - public TCPClientConnection(SerialConnectionListener listener, String host, int port) { - super(listener); - this.host = host; - this.port = port; - } - - @Override - public String getConnectionName() { - return "'; - } - - @Override - public void open(String comPort) { - close(); - this.comPort = comPort == null ? "" : comPort; - - isClosed = false; - try { - client = new Socket(host, port); - in = new BufferedReader(new InputStreamReader(client.getInputStream())); - out = new PrintStream(client.getOutputStream()); - System.out.println("Opened TCP connection to " + host + ':' + port); - /* Start thread listening on UDP */ - Thread readInput = new Thread(new Runnable() { - public void run() { - try { - String line; - while (isOpen && (line = in.readLine()) != null) { - serialData(line); - } - } catch (IOException e) { - lastError = "Error when reading from SerialConnection TCP: " + e; - System.err.println(lastError); - if (!isClosed) { - e.printStackTrace(); - closeConnection(); - } - } finally { - System.out.println("SerialConnection TCP terminated."); - closeConnection(); - } - } - }, "TCP thread"); - isOpen = true; - serialOpened(); - readInput.start(); - - } catch (Exception e) { - lastError = "Failed to open TCP connection to " + host + ':' + port + ": " + e; - System.err.println(lastError); - e.printStackTrace(); - closeConnection(); - } - } - - @Override - protected void doClose() { - try { - if (in != null) { - in.close(); - in = null; - } - if (out != null) { - out.close(); - out = null; - } - if (client != null) { - client.close(); - client = null; - } - } catch (IOException e) { - e.printStackTrace(); - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/UDPConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/UDPConnection.java deleted file mode 100644 index ae1ed52a9..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/UDPConnection.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2011, 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. - * - * ----------------------------------------------------------------- - * - * UDPConnection - * - * Authors : Niclas Finne - * Created : 1 June 2011 - */ - -package org.contikios.contiki.collect; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.io.*; -/** - * - */ -public class UDPConnection extends SerialConnection { - - private final int port; -private DatagramSocket serverSocket; - - public UDPConnection(SerialConnectionListener listener, int port) { - super(listener); - this.port = port; - } - - @Override - public String getConnectionName() { - return ""; - } - - @Override - public void open(String comPort) { - close(); - this.comPort = comPort == null ? "" : comPort; - - isClosed = false; - try { - serverSocket = new DatagramSocket(port); - System.out.println("Opened UDP port: " + port); - /* Start thread listening on UDP */ - Thread readInput = new Thread(new Runnable() { - public void run() { - byte[] data = new byte[1024]; - try { - while (isOpen) { - DatagramPacket packet = new DatagramPacket(data, data.length); - serverSocket.receive(packet); - - InetAddress addr = packet.getAddress(); - System.out.println("UDP: received " + packet.getLength() + " bytes from " + addr.getHostAddress() + ":" + packet.getPort()); - - StringWriter strOut = new StringWriter(); - PrintWriter out = new PrintWriter(strOut); - int payloadLen = packet.getLength() - 2; - out.printf("%d", 8 + payloadLen / 2); - /* Timestamp. Ignore time synch for now. */ - long time = System.currentTimeMillis() / 1000; - out.printf(" %d %d 0", - ((time >> 16) & 0xffff), time & 0xffff); - byte[] payload = packet.getData(); - int seqno = payload[0] & 0xff; - int hops = 0; /* how to get TTL / hot limit in Java??? */ - byte[] address = addr.getAddress(); - /* Ignore latency for now */ - out.printf(" %d %d %d %d", - ((address[14] & 0xff) + - ((address[15] & 0xff) << 8))&0xffff, seqno, hops, 0); - int d = 0; - for(int i = 0; i < payloadLen ; i += 2) { - d = (payload[i + 2] & 0xff) + ((payload[i + 3] & 0xff) << 8); - out.printf(" %d", d & 0xffff); - } - - String line = strOut.toString(); - serialData(line); - } - System.out.println("SerialConnection UDP terminated."); - closeConnection(); - } catch (IOException e) { - lastError = "Error when reading from SerialConnection UDP: " + e; - System.err.println(lastError); - if (!isClosed) { - e.printStackTrace(); - closeConnection(); - } - } - } - }, "UDP thread"); - isOpen = true; - serialOpened(); - readInput.start(); - - } catch (Exception e) { - lastError = "Failed to open UDP server at port " + port + ": " + e; - System.err.println(lastError); - e.printStackTrace(); - closeConnection(); - } - } - - @Override - protected void doClose() { - if (serverSocket != null) { - serverSocket.close(); - serverSocket = null; - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/Visualizer.java b/tools/collect-view/src/org/contikios/contiki/collect/Visualizer.java deleted file mode 100644 index ea111795a..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/Visualizer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * Visualizer - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect; - -import java.awt.Component; - -/** - * - */ -public interface Visualizer { - - public String getCategory(); - public String getTitle(); - public Component getPanel(); - public void nodesSelected(Node[] node); - public void nodeAdded(Node node); - public void nodeDataReceived(SensorData sensorData); - public void clearNodeData(); - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/AggregatedTimeChartPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/AggregatedTimeChartPanel.java deleted file mode 100644 index f898e0e6a..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/AggregatedTimeChartPanel.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2010, 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. - * - * ----------------------------------------------------------------- - * - * PacketChartPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 6 sep 2010 - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import javax.swing.JPanel; - -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.time.Minute; -import org.jfree.data.time.TimeSeries; -import org.jfree.data.time.TimeSeriesCollection; - -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public abstract class AggregatedTimeChartPanel extends JPanel implements Visualizer { - - private static final long serialVersionUID = 2100788758213434540L; - - protected final CollectServer server; - protected final String category; - protected final String title; - protected final TimeSeries series; - - protected final JFreeChart chart; - protected final ChartPanel chartPanel; - - private Node[] selectedNodes; - private HashMap selectedMap = new HashMap(); - - public AggregatedTimeChartPanel(CollectServer server, String category, String title, - String timeAxisLabel, String valueAxisLabel) { - super(new BorderLayout()); - this.server = server; - this.category = category; - this.title = title; - this.series = new TimeSeries(title, Minute.class); - TimeSeriesCollection timeSeries = new TimeSeriesCollection(series); - this.chart = ChartFactory.createTimeSeriesChart( - title, timeAxisLabel, valueAxisLabel, timeSeries, - false, true, false - ); - this.chartPanel = new ChartPanel(chart); - this.chartPanel.setPreferredSize(new Dimension(500, 270)); - setBaseShapeVisible(false); - add(chartPanel, BorderLayout.CENTER); - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public Component getPanel() { - return this; - } - - @Override - public void nodeAdded(Node node) { - // Ignore - } - - @Override - public void nodesSelected(Node[] nodes) { - if (isVisible()) { - updateSelected(nodes); - } - } - - private void updateSelected(Node[] nodes) { - if (this.selectedNodes != nodes) { - this.selectedNodes = nodes; - this.selectedMap.clear(); - if (nodes != null) { - for(Node node : nodes) { - this.selectedMap.put(node, createState(node)); - } - } - updateCharts(); - } - } - - @Override - public void nodeDataReceived(SensorData data) { - if (isVisible() && selectedMap.get(data.getNode()) != null) { - updateCharts(); - } - } - - @Override - public void clearNodeData() { - if (isVisible()) { - updateCharts(); - } - } - - private void updateCharts() { - int duplicates = 0; - int total = 0; - series.clear(); - if (this.selectedNodes != null && server.getSensorDataCount() > 0) { - long minute = server.getSensorData(0).getNodeTime() / 60000; - long lastMinute = minute; - int count = 0; - clearState(selectedMap); - for(int i = 0; i < server.getSensorDataCount(); i++) { - SensorData sd = server.getSensorData(i); - T nodeState = selectedMap.get(sd.getNode()); - if (nodeState != null) { - if (sd.isDuplicate()) { - duplicates++; - } else { - long min = sd.getNodeTime() / 60000; - if (min != minute) { - if (lastMinute < minute) { - series.add(new Minute(new Date(lastMinute * 60000L)), 0); - if (lastMinute < minute - 1) { - series.add(new Minute(new Date((minute - 1) * 60000L)), 0); - } - } - series.add(new Minute(new Date(minute * 60000L)), getTotalDataValue(count)); - count = 0; - lastMinute = minute + 1; - minute = min; - } - count += getSensorDataValue(sd, nodeState); - } - total++; - } - } - } - chart.setTitle(getTitle(selectedMap.size(), total, duplicates)); - } - - protected String getTitle(int nodeCount, int dataCount, int duplicateCount) { - return title; - } - - protected abstract T createState(Node node); - - protected void clearState(Map map) { - } - - protected int getTotalDataValue(int value) { - return value; - } - - protected abstract int getSensorDataValue(SensorData sd, T nodeState); - - public boolean getBaseShapeVisible() { - return ((XYLineAndShapeRenderer)this.chart.getXYPlot().getRenderer()).getBaseShapesVisible(); - } - - public void setBaseShapeVisible(boolean visible) { - ((XYLineAndShapeRenderer)this.chart.getXYPlot().getRenderer()).setBaseShapesVisible(visible); - } - - public double getRangeMinimumSize() { - return chart.getXYPlot().getRangeAxis().getAutoRangeMinimumSize(); - } - - public void setRangeMinimumSize(double size) { - chart.getXYPlot().getRangeAxis().setAutoRangeMinimumSize(size); - } - - public void setVisible(boolean visible) { - updateSelected(visible ? server.getSelectedNodes() : null); - super.setVisible(visible); - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/BarChartPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/BarChartPanel.java deleted file mode 100644 index cb6969331..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/BarChartPanel.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * PowerPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 5 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GradientPaint; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import javax.swing.JPanel; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.CategoryPlot; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.renderer.category.BarRenderer; -import org.jfree.data.category.DefaultCategoryDataset; -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public abstract class BarChartPanel extends JPanel implements Visualizer { - - private static final long serialVersionUID = 7664283678708048061L; - - protected final CollectServer server; - protected final String category; - protected final String title; - protected final String[] categories; - protected final JFreeChart chart; - protected final ChartPanel chartPanel; - protected final DefaultCategoryDataset dataset; - - private boolean isShowingAllNodes = false; - private int categoryOrder = 0; - - protected BarChartPanel(CollectServer server, String category, String title, - String chartTitle, String domainAxisLabel, String valueAxisLabel, - String[] categories) { - this(server, category, title, chartTitle, domainAxisLabel, valueAxisLabel, categories, true); - } - - protected BarChartPanel(CollectServer server, String category, String title, - String chartTitle, String domainAxisLabel, String valueAxisLabel, - String[] categories, boolean stackedChart) { - super(new BorderLayout()); - this.server = server; - this.category = category; - this.title = title; - this.categories = categories; - - /* Create chart with power of all nodes */ - dataset = new DefaultCategoryDataset(); - if (stackedChart) { - this.chart = ChartFactory.createStackedBarChart(chartTitle, - domainAxisLabel, valueAxisLabel, dataset, PlotOrientation.VERTICAL, - categories.length > 1, true, false); - } else { - this.chart = ChartFactory.createBarChart(chartTitle, - domainAxisLabel, valueAxisLabel, dataset, PlotOrientation.VERTICAL, - categories.length > 1, true, false); - if (categories.length > 1) { - CategoryPlot plot = chart.getCategoryPlot(); - BarRenderer renderer = (BarRenderer) plot.getRenderer(); - renderer.setItemMargin(0); - } - } - this.chartPanel = new ChartPanel(chart, false); - this.chartPanel.setPreferredSize(new Dimension(500, 270)); - if (categories.length > 1) { - this.chartPanel.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - categoryOrder++; - updateCharts(); - } - }); - } - - CategoryPlot plot = (CategoryPlot) chart.getPlot(); - BarRenderer renderer = (BarRenderer) plot.getRenderer(); - if (categories.length < 3) { - renderer.setDrawBarOutline(false); - - GradientPaint gp = new GradientPaint(0.0f, 0.0f, Color.RED, - 0.0f, 0.0f, new Color(128, 0, 0)); - renderer.setSeriesPaint(0, gp); - if (categories.length > 1) { - gp = new GradientPaint(0.0f, 0.0f, Color.BLUE, - 0.0f, 0.0f, new Color(0, 0, 128)); - renderer.setSeriesPaint(1, gp); - } - } else { - renderer.setDrawBarOutline(true); - } - - add(chartPanel, BorderLayout.CENTER); - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public Component getPanel() { - return this; - } - - public boolean isShowingAllNodes() { - return isShowingAllNodes; - } - - public void setShowingAllNodes(boolean isShowingAllNodes) { - if (this.isShowingAllNodes != isShowingAllNodes) { - this.isShowingAllNodes = isShowingAllNodes; - if (isVisible()) { - updateCharts(); - } - } - } - - @Override - public void nodeAdded(Node node) { - if (isVisible()) { - int count = node.getSensorDataCount(); - if (count > 0 || isShowingAllNodes) { - addNode(node); - } - if (count > 0) { - addSensorData(node.getSensorData(count - 1)); - } - } - } - - @Override - public void nodesSelected(Node[] nodes) { - } - - @Override - public void nodeDataReceived(SensorData data) { - if (isVisible()) { - addSensorData(data); - } - } - - @Override - public void clearNodeData() { - if (isVisible()) { - updateCharts(); - } - } - - private void updateCharts() { - dataset.clear(); - Node[] nodes = server.getNodes(); - if (nodes != null) { - for (int i = 0, n = nodes.length; i < n; i++) { - int count = nodes[i].getSensorDataCount(); - if (count > 0 || isShowingAllNodes) { - addNode(nodes[i]); - } - if (count > 0) { - addSensorData(nodes[i].getSensorData(count - 1)); - } - } - } - } - - private void addNode(Node node) { - String name = node.getName(); - for (int j = 0, m = categories.length; j < m; j++) { - dataset.addValue(0, categories[(j + categoryOrder) % categories.length], name); - } - } - - public void setVisible(boolean visible) { - if (visible) { - updateCharts(); - } else { - dataset.clear(); - } - super.setVisible(visible); - } - - protected abstract void addSensorData(SensorData data); - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/MapPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/MapPanel.java deleted file mode 100644 index 5a6652b94..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/MapPanel.java +++ /dev/null @@ -1,851 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * MapPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/23 16:21:48 $ - * $Revision: 1.4 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridLayout; -import java.awt.Polygon; -import java.awt.RenderingHints; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.Properties; -import java.util.logging.Logger; - -import javax.swing.BorderFactory; -import javax.swing.ImageIcon; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JFormattedTextField; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JSlider; -import javax.swing.Timer; -import javax.swing.border.LineBorder; -import javax.swing.border.TitledBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.plaf.basic.BasicGraphicsUtils; - -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Configurable; -import org.contikios.contiki.collect.Link; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public class MapPanel extends JPanel implements Configurable, Visualizer, ActionListener, MouseListener, MouseMotionListener { - - private static final long serialVersionUID = -8256619482599309425L; - - private static final Logger log = - Logger.getLogger(MapPanel.class.getName()); - - private static final boolean VISUAL_DRAG = true; - - private static final Color LINK_COLOR = new Color(0x40, 0x40, 0xf0, 0xff); - - private static final int delta = 7; - - private final CollectServer server; - private final String category; - private final boolean isMap; - private String title; - - private Timer timer; - - private JPopupMenu popupMenu; - private JCheckBoxMenuItem layoutItem; - private JCheckBoxMenuItem lockedItem; - private JMenuItem shakeItem; -// private JCheckBoxMenuItem dragItem; - private JCheckBoxMenuItem backgroundItem; - private JCheckBoxMenuItem showNetworkItem; - private JCheckBoxMenuItem configItem; - private JMenuItem resetNetworkItem; - private MapNode popupNode; - - private Hashtable nodeTable = new Hashtable(); - private MapNode[] nodeList = new MapNode[0]; - private boolean updateNodeList; - - private MapNode selectedNode; - private ArrayList selectedMapNodes = new ArrayList(); - private Node[] selectedNodes; - private MapNode draggedNode; - private long draggedTime; - - private ImageIcon mapImage; - private String mapName; - private boolean showBackground; - - private int layoutRepel = 100; - private int layoutAttract = 50; - private int layoutGravity = 1; - - private double etxFactor = 1.0; - - private boolean isLayoutActive = true; - private boolean hideNetwork = false; - - protected JPanel configPanel; - - public MapPanel(CollectServer server, String title, String category, boolean isMap) { - super(null); - this.server = server; - this.title = title; - this.category = category; - this.isMap = isMap; - setPreferredSize(new Dimension(300, 200)); - - popupMenu = new JPopupMenu(getTitle()); - if (!isMap) { - layoutItem = createCheckBoxMenuItem(popupMenu, "Update Layout", isLayoutActive); - popupMenu.add(layoutItem); - - lockedItem = createCheckBoxMenuItem(popupMenu, "Fixed Node Position", false); - shakeItem = createMenuItem(popupMenu, "Shake Nodes"); - popupMenu.addSeparator(); - } - - showNetworkItem = createCheckBoxMenuItem(popupMenu, "Show Network Info", true); - resetNetworkItem = createMenuItem(popupMenu, "Reset Network"); - popupMenu.addSeparator(); - if (isMap) { - backgroundItem = createCheckBoxMenuItem(popupMenu, "Show Background", false); - backgroundItem.setEnabled(false); - } else { - configItem = createCheckBoxMenuItem(popupMenu, "Show Layout Settings", false); - } - -// popupMenu.addSeparator(); -// dragItem = new JCheckBoxMenuItem("Visible Drag", true); -// popupMenu.add(dragItem); - - setBackground(Color.white); - addMouseListener(this); - addMouseMotionListener(this); - - if (!isMap) { - timer = new Timer(100, this); - - configPanel = new JPanel(new GridLayout(0, 1)); - configPanel.setBorder(LineBorder.createBlackLineBorder()); - - JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 1000, 1000 - layoutAttract); - slider.setBorder(new TitledBorder("Attract Factor: " + (1000 - layoutAttract))); - slider.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - JSlider slider = (JSlider)e.getSource(); - layoutAttract = 1000 - slider.getValue(); - ((TitledBorder)slider.getBorder()).setTitle("Attract Factor: " + slider.getValue()); - } - }); - configPanel.add(slider); - - slider = new JSlider(JSlider.HORIZONTAL, 0, 1000, layoutRepel); - slider.setBorder(new TitledBorder("Repel Range: " + layoutRepel)); - slider.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - JSlider slider = (JSlider)e.getSource(); - layoutRepel = slider.getValue(); - ((TitledBorder)slider.getBorder()).setTitle("Repel Range: " + layoutRepel); - } - }); - configPanel.add(slider); - - slider = new JSlider(JSlider.HORIZONTAL, 0, 100, layoutGravity); - slider.setBorder(new TitledBorder("Gravity: " + layoutGravity)); - slider.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - JSlider slider = (JSlider)e.getSource(); - layoutGravity = slider.getValue(); - ((TitledBorder)slider.getBorder()).setTitle("Gravity: " + layoutGravity); - } - }); - configPanel.add(slider); - - final JFormattedTextField etxField = new JFormattedTextField(new Double(etxFactor)); - etxField.setBorder(BorderFactory.createTitledBorder("ETX factor")); - etxField.setColumns(5); - etxField.addPropertyChangeListener("value", new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent evt) { - etxFactor = ((Number)etxField.getValue()).doubleValue(); - repaint(); - } - }); - configPanel.add(etxField); - - configPanel.setVisible(false); - add(configPanel); - - addComponentListener(new ComponentAdapter() { - public void componentResized(ComponentEvent ev) { - if (configPanel.isVisible()) { - updateConfigLayout(); - } - } - }); - } - } - - public String getMapBackground() { - return isMap ? mapName : null; - } - - public boolean setMapBackground(String image) { - if (!isMap) { - return false; - } - if (image == null) { - mapImage = null; - mapName = null; - backgroundItem.setEnabled(false); - backgroundItem.setSelected(false); - showBackground = false; - repaint(); - return true; - } - - ImageIcon ii = new ImageIcon(image); - if (ii.getIconWidth() <= 0 || ii.getIconHeight() <= 0) { - log.warning("could not find image '" + image + '\''); - return false; - } - mapImage = ii; - mapName = image; - setPreferredSize(new Dimension(ii.getIconWidth(), ii.getIconHeight())); - showBackground = true; - backgroundItem.setEnabled(true); - backgroundItem.setSelected(true); - repaint(); - return true; - } - - private JCheckBoxMenuItem createCheckBoxMenuItem(JPopupMenu menu, String title, boolean isSelected) { - JCheckBoxMenuItem item = new JCheckBoxMenuItem(title, isSelected); - item.addActionListener(this); - menu.add(item); - return item; - } - - private JMenuItem createMenuItem(JPopupMenu menu, String title) { - JMenuItem item = new JMenuItem(title); - item.addActionListener(this); - menu.add(item); - return item; - } - - public void setVisible(boolean visible) { - if (visible) { - clear(); - if (timer != null) { - timer.start(); - } - } else { - if (timer != null) { - timer.stop(); - } - } - super.setVisible(visible); - } - - public void clear() { - setCursor(Cursor.getDefaultCursor()); - draggedNode = null; - updateSelected(); - } - - - // ------------------------------------------------------------------- - // Node handling - // ------------------------------------------------------------------- - - public Node getNode(String id) { - MapNode node = nodeTable.get(id); - return node != null ? node.node : null; - } - - public MapNode getMapNode(String id) { - return nodeTable.get(id); - } - - private MapNode addMapNode(Node nd) { - String id = nd.getID(); - MapNode node = nodeTable.get(id); - if (node == null) { - node = new MapNode(this, nd); - node.y = 10 + (int) (Math.random() * (Math.max(100, getHeight()) - 20)); - node.x = 10 + (int) (Math.random() * (Math.max(100, getWidth()) - 30)); - - String location = server.getConfig(isMap ? id : ("collect.map." + id)); - if (location != null) { - try { - String[] pos = location.split(","); - node.x = Integer.parseInt(pos[0].trim()); - node.y = Integer.parseInt(pos[1].trim()); - node.hasFixedLocation = !isMap; - } catch (Exception e) { - System.err.println("could not parse node location: " + location); - e.printStackTrace(); - } - } - - nodeTable.put(id, node); - updateNodeList = true; - } - return node; - } - - private MapNode[] getNodeList() { - if (updateNodeList) { - synchronized (nodeTable) { - updateNodeList = false; - nodeList = nodeTable.values().toArray(new MapNode[nodeTable.size()]); - } - } - return nodeList; - } - - - // ------------------------------------------------------------------- - // Visualizer - // ------------------------------------------------------------------- - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public Component getPanel() { - return this; - } - - @Override - public void nodesSelected(Node[] nodes) { - if (selectedNodes != nodes) { - selectedNodes = nodes; - if (isVisible()) { - updateSelected(); - } - } - } - - private void updateSelected() { - if (selectedMapNodes.size() > 0) { - for(MapNode node : selectedMapNodes) { - node.isSelected = false; - } - selectedMapNodes.clear(); - } - - if (selectedNodes == null || selectedNodes.length == 0) { - selectedNode = null; - } else { - for (Node node : selectedNodes) { - MapNode mapNode = addMapNode(node); - selectedMapNodes.add(mapNode); - mapNode.isSelected = true; - } - selectedNode = selectedMapNodes.get(0); - } - - repaint(); - } - - @Override - public void nodeAdded(Node nd) { - addMapNode(nd); - if (isVisible()) { - repaint(); - } - } - - @Override - public void nodeDataReceived(SensorData sensorData) { - if (isVisible()) { - repaint(); - } - } - - @Override - public void clearNodeData() { - nodeTable.clear(); - updateNodeList = true; - nodesSelected(null); - if (isVisible()) { - repaint(); - } - } - - - // ------------------------------------------------------------------- - // Graphics - // ------------------------------------------------------------------- - - @Override - protected void paintComponent(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - FontMetrics fm = g.getFontMetrics(); - int fnHeight = fm.getHeight(); - int fnDescent = fm.getDescent(); - int width = getWidth(); - int height = getHeight(); - - g.setColor(getBackground()); - g.fillRect(0, 0, width, height); - if (showBackground && isMap) { - mapImage.paintIcon(this, g, 0, 0); - } - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - - // Display legend - if (!hideNetwork) { - int legendWidth = fm.stringWidth("ETX"); - g.setColor(Color.black); - g.drawString("ETX", width - legendWidth - 10, 10 + fnHeight - fnDescent); - g.drawRect(width - legendWidth - 30, 8, legendWidth + 24, fnHeight + 4); - g.setColor(LINK_COLOR); - g2d.drawLine(width - legendWidth - 25, 10 + fnHeight / 2, - width - legendWidth - 15, 10 + fnHeight / 2); - } - - MapNode[] nodes = getNodeList(); - if (!isMap || !hideNetwork) { - g.setColor(LINK_COLOR); - for (MapNode n : nodes) { - for (int j = 0, mu = n.node.getLinkCount(); j < mu; j++) { - Link link = n.node.getLink(j); - MapNode linkNode = addMapNode(link.node); - int x2 = linkNode.x; - int y2 = linkNode.y; - g2d.drawLine(n.x, n.y, x2, y2); - drawArrow(g, n.x, n.y, x2, y2, 3); - if (!hideNetwork) { - int xn1, xn2, yn1, yn2; - if (n.x <= x2) { - xn1 = n.x; xn2 = x2; - yn1 = n.y; yn2 = y2; - } else { - xn1 = x2; xn2 = n.x; - yn1 = y2; yn2 = n.y; - } - int dx = xn1 + (xn2 - xn1) / 2 + 4; - int dy = yn1 + (yn2 - yn1) / 2 - fnDescent; - if (yn2 < yn1) { - dy += fnHeight - fnDescent; - } - g.drawString( - Double.toString(((int) (link.getETX() * etxFactor * 100 + 0.5)) / 100.0), - dx, dy); - } - } - } - } - - for (MapNode n : nodes) { - n.paint(g, n.x, n.y); - - g.setColor(Color.black); - if (n.isSelected) { - BasicGraphicsUtils.drawDashedRect(g, n.x - delta, n.y - delta, - 2 * delta, 2 * delta); - } - if (selectedNode != null && selectedNode.message != null) { - g.drawString(selectedNode.message, 10, 10); - } - } - } - - private Polygon arrowPoly = new Polygon(); - private void drawArrow(Graphics g, int xSource, int ySource, int xDest, int yDest, int delta) { - double dx = xSource - xDest; - double dy = ySource - yDest; - double dir = Math.atan2(dx, dy); - double len = Math.sqrt(dx * dx + dy * dy); - dx /= len; - dy /= len; - len -= delta; - xDest = xSource - (int) (dx * len); - yDest = ySource - (int) (dy * len); - g.drawLine(xDest, yDest, xSource, ySource); - - final int size = 8; - arrowPoly.reset(); - arrowPoly.addPoint(xDest, yDest); - arrowPoly.addPoint(xDest + xCor(size, dir + 0.5), yDest + yCor(size, dir + 0.5)); - arrowPoly.addPoint(xDest + xCor(size, dir - 0.5), yDest + yCor(size, dir - 0.5)); - arrowPoly.addPoint(xDest, yDest); - g.fillPolygon(arrowPoly); - } - - private int yCor(int len, double dir) { - return (int)(0.5 + len * Math.cos(dir)); - } - - private int xCor(int len, double dir) { - return (int)(0.5 + len * Math.sin(dir)); - } - - - // ------------------------------------------------------------------- - // ActionListener - // ------------------------------------------------------------------- - - public void actionPerformed(ActionEvent e) { - Object source = e.getSource(); - if (!isMap && source == timer) { - if (isLayoutActive) { - updateNodeLayout(); - repaint(); - } - - } else if (!isMap && source == lockedItem) { - if (popupNode != null) { - boolean wasFixed = popupNode.hasFixedLocation; - popupNode.hasFixedLocation = lockedItem.isSelected(); - if (wasFixed && !popupNode.hasFixedLocation) { - server.removeConfig("collect.map." + popupNode.node.getID()); - } else if (!wasFixed && popupNode.hasFixedLocation) { - server.setConfig("collect.map." + popupNode.node.getID(), - "" + popupNode.x + ',' + popupNode.y); - } - repaint(); - } - - } else if (!isMap && source == layoutItem) { - isLayoutActive = layoutItem.isSelected(); - - } else if (!isMap && source == shakeItem) { - for(MapNode n : getNodeList()) { - if (!n.hasFixedLocation) { - n.x += Math.random() * 100 - 50; - n.y += Math.random() * 100 - 50; - } - } - - } else if (!isMap && source == configItem) { - if (configItem.isSelected()) { - configPanel.setSize(getPreferredSize()); - configPanel.validate(); - updateConfigLayout(); - configPanel.setVisible(true); - } else { - configPanel.setVisible(false); - } - repaint(); - - } else if (source == showNetworkItem) { - hideNetwork = !showNetworkItem.isSelected(); - repaint(); - - } else if (source == resetNetworkItem) { - for(MapNode n : getNodeList()) { - n.node.clearLinks(); - } - repaint(); - } else if (isMap && source == backgroundItem) { - showBackground = mapImage != null && backgroundItem.isSelected(); - repaint(); - } - } - - private void updateNodeLayout() { - MapNode[] nodes = getNodeList(); - for (MapNode n : nodes) { - - // Attract connected nodes - for(int i = 0, jn = n.node.getLinkCount(); i < jn; i++) { - Link link = n.node.getLink(i); - MapNode n2 = addMapNode(link.node); - double vx = n2.x - n.x; - double vy = n2.y - n.y; - double dist = Math.sqrt(vx * vx + vy * vy); - dist = dist == 0 ? 0.00001 : dist; - double etx = link.getETX() * etxFactor; - if (etx > 5) etx = 5; - double factor = (etx * layoutAttract - dist) / (dist * 3); - double dx = factor * vx; - double dy = factor * vy; - - n2.dx += dx; - n2.dy += dy; - n.dx -= dx; - n.dy -= dy; - } - - // Repel nodes that are too close - double dx = 0, dy = 0; - for (MapNode n2 : nodes) { - if (n == n2) { - continue; - } - double vx = n.x - n2.x; - double vy = n.y - n2.y; - double dist = vx * vx + vy * vy; - if (dist == 0) { - dx += Math.random() * 5; - dy += Math.random() * 5; - } else if (dist < layoutRepel * layoutRepel) { - dx += vx / dist; - dy += vy / dist; - } - } - double dist = dx * dx + dy * dy; - if (dist > 0) { - dist = Math.sqrt(dist) / 2; - n.dx += dx / dist; - n.dy += dy / dist; - } - - n.dy += layoutGravity; - } - - // Update the node positions - int width = getWidth(); - int height = getHeight(); - for(MapNode n : nodes) { - if (!n.hasFixedLocation && n != draggedNode) { - n.x += Math.max(-5, Math.min(5, n.dx)); - n.y += Math.max(-5, Math.min(5, n.dy)); - if (n.x < 0) { - n.x = 0; - } else if (n.x > width) { - n.x = width; - } - if (n.y < 0) { - n.y = 0; - } else if (n.y > height) { - n.y = height; - } - } - n.dx /= 2; - n.dy /= 2; - } - } - - private void updateConfigLayout() { - configPanel.setLocation(getWidth() - configPanel.getWidth() - 10, - getHeight() - configPanel.getHeight() - 10); - } - - - // ------------------------------------------------------------------- - // Mouselistener - // ------------------------------------------------------------------- - - private MapNode getNodeAt(int mx, int my) { - for(MapNode n : getNodeList()) { - if (mx >= (n.x - delta) - && mx <= (n.x + delta) - && my >= (n.y - delta) - && my <= (n.y + delta)) { - return n; - } - } - return null; - } - - public void mouseClicked(MouseEvent e) { - int mx = e.getX(); - int my = e.getY(); - if (e.getButton() == MouseEvent.BUTTON1) { - MapNode node = getNodeAt(mx, my); - if (node != selectedNode) { - server.selectNodes(node == null ? null : new Node[] { node.node }); - } - } - showPopup(e); - } - - public void mousePressed(MouseEvent e) { - if (e.getButton() == MouseEvent.BUTTON1) { - MapNode aNode = getNodeAt(e.getX(), e.getY()); - if (aNode != selectedNode) { - server.selectNodes(aNode != null ? new Node[] { aNode.node } : null); - } - draggedNode = aNode; - draggedTime = System.currentTimeMillis(); - - } else if (selectedNode != null) { - if (draggedTime < 0) { - setCursor(Cursor.getDefaultCursor()); - draggedTime = 0; - } - selectedNode = draggedNode = null; - server.selectNodes(null); - } - showPopup(e); - } - - public void mouseReleased(MouseEvent e) { - if (draggedNode != null && e.getButton() == MouseEvent.BUTTON1) { - if ((draggedTime > 0) && - (System.currentTimeMillis() - draggedTime) < 300) { - // Do not drag if mouse is only moved during click - - } else { - draggedNode.x = e.getX(); - draggedNode.y = e.getY(); - setCursor(Cursor.getDefaultCursor()); - if (!isMap && draggedNode.hasFixedLocation) { - /* Update fixed location */ - server.setConfig("collect.map." + draggedNode.node.getID(), - "" + draggedNode.x + ',' + draggedNode.y); - } - draggedTime = 0; - draggedNode = null; - repaint(); - } - } - - showPopup(e); - } - - private void showPopup(MouseEvent e) { - if (e.isPopupTrigger() - && (e.getModifiers() & (MouseEvent.SHIFT_MASK|MouseEvent.CTRL_MASK)) == 0) { - popupNode = getNodeAt(e.getX(), e.getY()); - if (!isMap) { - lockedItem.setEnabled(popupNode != null); - lockedItem.setSelected(popupNode != null ? popupNode.hasFixedLocation : false); - } - popupMenu.show(this, e.getX(), e.getY()); - } - } - - public void mouseEntered(MouseEvent e) { - } - - public void mouseExited(MouseEvent e) { - } - - - // ------------------------------------------------------------------- - // MouseMotion - // ------------------------------------------------------------------- - - public void mouseDragged(MouseEvent e) { - if (draggedNode == null) { - // Do nothing - - } else if (draggedTime > 0) { - if ((System.currentTimeMillis() - draggedTime) > 300) { - // No mouse click, time to drag the node - draggedTime = -1; - setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); - } - - } else if (VISUAL_DRAG /* && dragItem.isSelected() */) { - draggedNode.x = e.getX(); - draggedNode.y = e.getY(); - repaint(); - } - } - - public void mouseMoved(MouseEvent e) { - } - - - // ------------------------------------------------------------------- - // MapNode - // ------------------------------------------------------------------- - - private static class MapNode { - - public final Node node; - public int x; - public int y; - public double dx; - public double dy; - public boolean hasFixedLocation; - public boolean isSelected; - public String message; - - MapNode(MapPanel panel, Node node) { - this.node = node; - } - - public void paint(Graphics g, int x, int y) { - final int od = 3; - g.setColor(Color.black); - g.drawString(node.getID(), x + od * 2 + 3, y + 4); - if (hasFixedLocation) { - g.setColor(Color.red); - } - g.fillOval(x - od, y - od, od * 2 + 1, od * 2 + 1); - } - - } // end of inner class MapNode - - - @Override - public void updateConfig(Properties config) { - if (isMap) { - for (MapNode n : getNodeList()) { - config.put(n.node.getID(), "" + n.x + ',' + n.y); - } - } - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeControl.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeControl.java deleted file mode 100644 index 6b0cffbc8..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeControl.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 2010, 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. - * - * - * ----------------------------------------------------------------- - * - * NodeControl - * - * Authors : Niclas Finne - * Created : 27 sep 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.FlowLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JFormattedTextField; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSeparator; -import javax.swing.JTextPane; -import javax.swing.border.LineBorder; - -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public class NodeControl implements Visualizer { - - private final static String SET_TIME_COMMAND = "time %TIME% | null"; - - private final CollectServer server; - private final String category; - private final JPanel panel; - private final JLabel statusLabel; - private final JSeparator statusSeparator; - - public NodeControl(CollectServer server, String category) { - this.server = server; - this.category = category; - this.panel = new JPanel(new BorderLayout()); - - final JFormattedTextField intervalField = new JFormattedTextField(new Integer(60)); - final JFormattedTextField randomField = new JFormattedTextField(new Integer(60)); - final JFormattedTextField reportsField = new JFormattedTextField(new Integer(0)); - final JFormattedTextField rexmitsField = new JFormattedTextField(new Integer(31)); - statusLabel = new JLabel("", JLabel.CENTER); - statusLabel.setOpaque(true); - statusLabel.setBackground(Color.white); - statusLabel.setBorder(LineBorder.createBlackLineBorder()); - statusLabel.setVisible(false); - statusSeparator = new JSeparator(); - statusSeparator.setVisible(false); - - JButton stopButton = createCommandButton("Send stop to nodes", "netcmd killall"); - - JButton sendButton = new JButton("Send command to nodes"); - sendButton.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - int interval = (Integer)intervalField.getValue(); - int random = (Integer)randomField.getValue(); - int reports = (Integer)reportsField.getValue(); - int rexmits = (Integer)rexmitsField.getValue(); - - sendCommand("netcmd { repeat " + reports + " " + interval - + " { randwait " + random + " collect-view-data | send " + rexmits + " } }"); - } - - }); - - JButton collectButton = createCommandButton("Start Collect", - "~K", "killall", - "mac 0", SET_TIME_COMMAND, - "collect | timestamp | binprint &"); - JButton stopCollectButton = createCommandButton("Stop Collect", "~K", "killall"); - - JPanel controlPanel = new JPanel(new GridBagLayout()); - - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 0.5; - c.insets.left = c.insets.right = c.insets.bottom = 3; - c.anchor = GridBagConstraints.WEST; - c.gridy = 0; - - c.gridwidth = 3; - controlPanel.add(statusLabel, c); - c.gridy++; - controlPanel.add(statusSeparator, c); - c.insets.top = 10; - - c.gridy++; - c.gridwidth = 1; - controlPanel.add(new JLabel("Program Connected Nodes", JLabel.RIGHT), c); - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - controlPanel.add(new JButton(server.getMoteProgramAction()), c); - c.fill = GridBagConstraints.HORIZONTAL; - - c.gridy++; - c.gridwidth = 1; - controlPanel.add(new JLabel("Serial Connection", JLabel.RIGHT), c); - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - controlPanel.add(new JButton(server.getConnectSerialAction()), c); - c.fill = GridBagConstraints.HORIZONTAL; - - c.gridy++; - controlPanel.add(new JSeparator(), c); - - c.gridy++; - c.gridwidth = 1; - controlPanel.add(new JLabel("Base Station Control", JLabel.RIGHT), c); - c.gridwidth = 2; - JPanel basePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5)); - basePanel.add(collectButton); - basePanel.add(stopCollectButton); - c.insets.left -= 5; - controlPanel.add(basePanel, c); - c.insets.left += 5; - - c.gridy++; - c.gridwidth = 3; - controlPanel.add(new JSeparator(), c); - - c.gridy++; - JLabel label = new JLabel("Collect Settings", JLabel.CENTER); - controlPanel.add(label, c); - c.gridwidth = 1; - - c.gridy++; - controlPanel.add(label = new JLabel("Report interval", JLabel.RIGHT), c); - label.setLabelFor(intervalField); - controlPanel.add(intervalField, c); - controlPanel.add(new JLabel("seconds"), c); - - c.insets.top = 3; - c.gridy++; - controlPanel.add(label = new JLabel("Report randomness", JLabel.RIGHT), c); - label.setLabelFor(randomField); - controlPanel.add(randomField, c); - controlPanel.add(new JLabel("seconds"), c); - - c.gridy++; - controlPanel.add(label = new JLabel("Hop-by-hop retransmissions", JLabel.RIGHT), c); - label.setLabelFor(rexmitsField); - controlPanel.add(rexmitsField, c); - controlPanel.add(new JLabel("retransmissions (0 - 31)"), c); - - c.gridy++; - controlPanel.add(new JLabel("Number of reports", JLabel.RIGHT), c); - label.setLabelFor(reportsField); - controlPanel.add(reportsField, c); - controlPanel.add(new JLabel("(0 = report forever)"), c); - - c.gridy++; - c.gridwidth = 3; - c.insets.bottom = 10; - JPanel nodePanel = new JPanel(); - nodePanel.add(sendButton); - nodePanel.add(stopButton); - controlPanel.add(nodePanel, c); - - c.gridy++; - controlPanel.add(new JSeparator(), c); - panel.add(controlPanel, BorderLayout.NORTH); - - JTextPane helpPane = new JTextPane(); - helpPane.setContentType("text/html"); - helpPane.setEditable(false); - helpPane.setText("" + - "

Quick Startup Instructions

" + - "" + - "
  • Connect nodes to USB. Press the Program Nodes... button." + - "
  • Disconnect all except one node. " + - "Press the Connect to Serial button." + - "
  • Press the Start Collect button." + - "
  • Press the Send command to nodes button." + - "" + - ""); - helpPane.setBackground(panel.getBackground()); - JScrollPane helpScroll = new JScrollPane(helpPane, - JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, - JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - helpScroll.setBorder(BorderFactory.createEmptyBorder(3, 10, 10, 10)); - panel.add(helpScroll, BorderLayout.CENTER); - } - - private JButton createCommandButton(String name, final String... command) { - JButton button = new JButton(name); - button.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - try { - // TODO Should use separate thread to send commands - panel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - for(int i = 0, n = command.length; i < n; i++) { - if (i > 0) { - try { - // Do not send multiple commands too fast - Thread.sleep(1000); - } catch (InterruptedException e1) { - } - } - String cmd = command[i]; - if (cmd == SET_TIME_COMMAND) { - cmd = "time " + (System.currentTimeMillis() / 1000) + " | null"; - } - if (!sendCommand(cmd)) { - break; - } - } - } finally { - panel.setCursor(Cursor.getDefaultCursor()); - } - } - - }); - return button; - } - - protected boolean sendCommand(String command) { - if (server.sendToNode(command)) { - setStatus("Sent command '" + command + "'", false); - return true; - } - setStatus("Failed to send command. No serial connection.", true); - return false; - } - - private void setStatus(String text, boolean isWarning) { - statusLabel.setForeground(isWarning ? Color.red : Color.black); - statusLabel.setText(text); - statusLabel.setVisible(true); - statusSeparator.setVisible(true); - } - - public String getCategory() { - return category; - } - - public String getTitle() { - return "Node Control"; - } - - public Component getPanel() { - return panel; - } - - public void nodesSelected(Node[] node) { - } - - public void nodeAdded(Node node) { - } - - public void nodeDataReceived(SensorData sensorData) { - } - - public void clearNodeData() { - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeInfoPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeInfoPanel.java deleted file mode 100644 index dfda52993..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/NodeInfoPanel.java +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright (c) 2010, 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. - * - * - * ----------------------------------------------------------------- - * - * NodeInfoPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 6 sep 2010 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.Comparator; -import java.util.Properties; - -import javax.swing.AbstractAction; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.SwingUtilities; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.JTableHeader; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import javax.swing.table.TableRowSorter; - -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Configurable; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.SensorInfo; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public class NodeInfoPanel extends JPanel implements Visualizer, Configurable { - - private static final long serialVersionUID = -1060893468047793431L; - - private static Comparator NUMBER_COMPARATOR = new Comparator() { - - public int compare(Number o1, Number o2) { - double v1 = o1.doubleValue(); - double v2 = o2.doubleValue(); - return (v1 < v2 ? -1 : (v1 == v2 ? 0 : 1)); - } - - }; - - private final CollectServer server; - private final String category; - private final JTable table; - private final NodeModel nodeModel; - - @SuppressWarnings("serial") - public NodeInfoPanel(CollectServer server, String category) { - super(new BorderLayout()); - this.server = server; - this.category = category; - - TableData[] columns = new TableData[] { - new TableData("Node", Node.class) { - public Object getValue(Node node) { - return node; - } - }, - new TableData("Received", "Packets Received", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getPacketCount(); - } - }, - new TableData("Dups", "Duplicate Packets Received", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getDuplicateCount(); - } - }, - new TableData("Lost", "Estimated Lost Packets", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getEstimatedLostCount(); - } - }, - new TableData("Hops", "Average Hops to Sink", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAverageValue(SensorData.HOPS); - } - }, - new TableData("Rtmetric", "Average Routing Metric", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAverageRtmetric(); - } - }, - new TableData("ETX", "Average ETX to Next Hop", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAverageBestNeighborETX(); - } - }, - new TableData("Churn", "Next Hop Change Count", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getNextHopChangeCount(); - } - }, - new TableData("Beacon Interval", "Average Beacon Interval", Long.class) { - public Object getValue(Node node) { - return (long)(node.getSensorDataAggregator().getAverageValue(SensorData.BEACON_INTERVAL) * 1000); - } - }, - - new TableData("Reboots", "Estimated Node Restart Count", Number.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getEstimatedRestarts(); - } - }, - - // Power - new TableData("CPU Power", "Average CPU Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getCPUPower(); - } - }, - new TableData("LPM Power", "Average LPM Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getLPMPower(); - } - }, - new TableData("Listen Power", "Average Radio Listen Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getListenPower(); - } - }, - new TableData("Transmit Power", "Average Radio Transmit Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getTransmitPower(); - } - }, - new TableData("Power", "Average Power Consumption", Double.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAveragePower(); - } - }, - new TableData("On-time", "Power Measure Time", Long.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getPowerMeasureTime(); - } - }, - - new TableData("Listen Duty Cycle", "Average Radio Listen Duty Cycle (%)", Double.class) { - public Object getValue(Node node) { - return 100 * node.getSensorDataAggregator().getAverageDutyCycle(SensorInfo.TIME_LISTEN); - } - }, - new TableData("Transmit Duty Cycle", "Average Radio Transmit Duty Cycle (%)", Double.class) { - public Object getValue(Node node) { - return 100 * node.getSensorDataAggregator().getAverageDutyCycle(SensorInfo.TIME_TRANSMIT); - } - }, - - // Inter-packet times - new TableData("Avg Inter-packet Time", Long.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getAveragePeriod(); - } - }, - new TableData("Min Inter-packet Time", Long.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getShortestPeriod(); - } - }, - new TableData("Max Inter-packet Time", Long.class) { - public Object getValue(Node node) { - return node.getSensorDataAggregator().getLongestPeriod(); - } - } - }; - nodeModel = new NodeModel(columns); - table = new JTable(nodeModel) { - private static final long serialVersionUID = 1L; - private Font fontForAverage; - - protected JTableHeader createDefaultTableHeader() { - return new JTableHeader(columnModel) { - private static final long serialVersionUID = 1L; - - public String getToolTipText(MouseEvent e) { - int index = columnModel.getColumnIndexAtX(e.getX()); - int modelIndex = index < 0 ? index : columnModel.getColumn(index).getModelIndex(); - return modelIndex < 0 ? null : nodeModel.getColumnToolTip(modelIndex); - } - }; - } - - public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) { - Component c = super.prepareRenderer(renderer, rowIndex, vColIndex); - int row = convertRowIndexToModel(rowIndex); - if (row == nodeModel.getRowCount() - 1) { - if (fontForAverage == null) { - fontForAverage = c.getFont().deriveFont(Font.BOLD); - } - // Last line is average - c.setFont(fontForAverage); - } - return c; - } - - }; - - // Do not sort column when clicking between the columns (resizing) - TableRowSorter sorter = new TableRowSorter(nodeModel) { - public void toggleSortOrder(int column) { - if(table.getTableHeader().getCursor().getType() != Cursor.E_RESIZE_CURSOR) { - super.toggleSortOrder(column); - } - } - }; - for(int c = 0; c < columns.length; c++) { - if (columns[c].dataClass == Number.class) { - sorter.setComparator(c, NUMBER_COMPARATOR); - } - } - table.setRowSorter(sorter); - // Pack the column when double clicking between columns (resizing) - table.getTableHeader().addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if(e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e) && - table.getTableHeader().getCursor().getType() == Cursor.E_RESIZE_CURSOR) { - int index = table.getColumnModel().getColumnIndexAtX(e.getX() - 3); - if (index >= 0) { - packColumn(table, index); - } - } - } - }); - - // Add right aligned renderer for node name - DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(); - renderer.setHorizontalAlignment(JLabel.RIGHT); - table.setDefaultRenderer(Node.class, renderer); - - // Add renderer for time - renderer = new DefaultTableCellRenderer() { - private static final long serialVersionUID = 1L; - - public void setValue(Object value) { - long time = (Long) value; - setText(time > 0 ? getTimeAsString(time) : null); - } - }; - renderer.setHorizontalAlignment(JLabel.RIGHT); - table.setDefaultRenderer(Long.class, renderer); - - // Add renderer for double - renderer = new DefaultTableCellRenderer() { - private static final long serialVersionUID = 1L; - - public void setValue(Object value) { - if (value == null) { - setText(null); - } else { - double v = ((Number) value).doubleValue() + 0.0005; - int dec = ((int)(v * 1000)) % 1000; - setText((long)v + "." + (dec > 99 ? "" : "0") + (dec > 9 ? "" : "0") + dec); - } - } - }; - renderer.setHorizontalAlignment(JLabel.RIGHT); - table.setDefaultRenderer(Double.class, renderer); - - // Add renderer for mixed integers and doubles - renderer = new DefaultTableCellRenderer() { - private static final long serialVersionUID = 1L; - - public void setValue(Object value) { - if (value == null) { - setText(null); - } else if (value instanceof Integer) { - setText(value.toString()); - } else { - double v = ((Number) value).doubleValue() + 0.0005; - int dec = ((int)(v * 1000)) % 1000; - setText((long)v + "." + (dec > 99 ? "" : "0") + (dec > 9 ? "" : "0") + dec); - } - } - }; - renderer.setHorizontalAlignment(JLabel.RIGHT); - table.setDefaultRenderer(Number.class, renderer); - - table.setFillsViewportHeight(true); - table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); - for (int i = 0, n = table.getColumnCount(); i < n; i++) { - packColumn(table, i); - } - - String savedColumnData = server.getConfig("collect.nodeinfo.table"); - if (savedColumnData != null) { - String[] columnList = savedColumnData.split("[ ,]"); - for(int i = 1; i < columns.length; i++) { - columns[i].setVisible(false); - } - for(int i = 0; i < columnList.length; i++) { - int c = Integer.parseInt(columnList[i]); - int index = table.convertColumnIndexToView(c); - if (index >= 0) { - table.getColumnModel().moveColumn(index, i); - } - columns[c].setVisible(true); - } - } - JPopupMenu popupMenu = new JPopupMenu(); - // The first column (the node name) should always be visible. - for(int i = 1; i < columns.length; i++) { - popupMenu.add(new JCheckBoxMenuItem(columns[i].init(table, i))); - } - table.setComponentPopupMenu(popupMenu); - add(new JScrollPane(table), BorderLayout.CENTER); - } - - public void updateConfig(Properties config) { - StringBuilder sb = new StringBuilder(); - for(int i = 0, n = table.getColumnCount(); i < n; i++) { - int index = table.convertColumnIndexToModel(i); - if (index >= 0) { - if (sb.length() > 0) { - sb.append(','); - } - sb.append(index); - } - } - config.setProperty("collect.nodeinfo.table", sb.toString()); - } - - @Override - public Component getPanel() { - return this; - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return "Node Info"; - } - - @Override - public void nodeAdded(Node node) { - nodeModel.setNodes(server.getNodes()); - } - - @Override - public void nodeDataReceived(SensorData sensorData) { - nodeModel.updateNode(sensorData.getNode()); - } - - @Override - public void clearNodeData() { - nodeModel.setNodes(null); - } - - @Override - public void nodesSelected(Node[] nodes) { - // Ignore - } - - @Override - public void setVisible(boolean visible) { - nodeModel.setNodes(visible ? server.getNodes() : null); - super.setVisible(visible); - } - - private String getTimeAsString(long time) { - StringBuilder sb = new StringBuilder(); - time /= 1000; - if (time > 24 * 60 * 60) { - long days = time / (24 * 60 * 60); - sb.append(days).append(days > 1 ? " days, " : " day, "); - time -= days * 24 * 60 * 60; - } - if (time > 60 * 60) { - long hours = time / (60 * 60); - sb.append(hours).append(hours > 1 ? " hours, " : " hour, "); - time -= hours * 60 * 60; - } - long sec = time % 60; - sb.append(time / 60).append(" min, "); - if (sec < 10) { - sb.append('0'); - } - sb.append(sec).append(" sec"); - return sb.toString(); - } - - private static void packColumn(JTable table, int columnIndex) { - TableColumn tableColumn = table.getColumnModel().getColumn(columnIndex); - Object value = tableColumn.getHeaderValue(); - TableCellRenderer columnRenderer = tableColumn.getHeaderRenderer(); - if (columnRenderer == null) { - columnRenderer = table.getTableHeader().getDefaultRenderer(); - } - Component c = columnRenderer.getTableCellRendererComponent(table, value, false, false, -1, columnIndex); - int width = c.getPreferredSize().width + 6; - int intercellSpacing = table.getIntercellSpacing().width; - for(int i = 0, n = table.getRowCount(); i < n; i++) { - TableCellRenderer cellRenderer = table.getCellRenderer(i, columnIndex); - value = table.getValueAt(i, columnIndex); - c = cellRenderer.getTableCellRendererComponent(table, value, false, false, i, columnIndex); - int w = c.getPreferredSize().width + intercellSpacing + 2; - if (w > width) { - width = w; - } - } - table.getTableHeader().setResizingColumn(tableColumn); - tableColumn.setWidth(width); - tableColumn.setPreferredWidth(width); - } - - private static class NodeModel extends AbstractTableModel { - - private static final long serialVersionUID = 1692207305977527004L; - - private final TableData[] columns; - private Node[] nodes; - - public NodeModel(TableData[] columns) { - this.columns = columns; - } - - public void recalculateAverage() { - for(TableData td : columns) { - td.clearAverageCache(); - } - int row = getRowCount() - 1; - fireTableRowsUpdated(row, row); - } - - public Object getValueAt(int row, int col) { - int count = nodes == null ? 0 : nodes.length; - if (row == count) { - return columns[col].getAverageValue(nodes); - } - return columns[col].getValue(nodes[row]); - } - - public Class getColumnClass(int col) { - return columns[col].dataClass; - } - - public String getColumnName(int col) { - return columns[col].name; - } - - public String getColumnToolTip(int col) { - Object v = columns[col].getValue(TableData.SHORT_DESCRIPTION); - return v == null ? null : v.toString(); - } - - public int getColumnCount() { - return columns.length; - } - - public int getRowCount() { - return (nodes == null ? 0 : nodes.length) + 1; - } - - public void setNodes(Node[] nodes) { - if (this.nodes != null && this.nodes.length > 0) { - fireTableRowsDeleted(0, this.nodes.length - 1); - } - this.nodes = nodes; - if (this.nodes != null && this.nodes.length > 0) { - fireTableRowsInserted(0, this.nodes.length - 1); - } - recalculateAverage(); - } - - public void updateNode(Node node) { - if (this.nodes != null) { - for(int row = 0; row < this.nodes.length; row++) { - if (this.nodes[row] == node) { - fireTableRowsUpdated(row, row); - recalculateAverage(); - break; - } - } - } - } - - } - - public static abstract class TableData extends AbstractAction { - private static final long serialVersionUID = -3045755073722516926L; - - private final static Node AVERAGE_NODE = new Node("99999999.9", "Avg"); - - public final String name; - public final Class dataClass; - - private JTable table; - private TableColumn tableColumn; - private int modelIndex = -1; - - private Object averageCache; - - protected TableData(String name, Class dataClass) { - this(name, name, dataClass); - } - - protected TableData(String name, String description, Class dataClass) { - super(name); - this.name = name; - this.dataClass = dataClass; - putValue(SHORT_DESCRIPTION, description); - setVisible(true); - } - - TableData init(JTable table, int modelIndex) { - this.table = table; - this.modelIndex = modelIndex; - if (!isVisible()) { - // The column should initially be hidden - setColumnVisible(false); - } - return this; - } - - public boolean isVisible() { - return Boolean.TRUE.equals(getValue(SELECTED_KEY)); - } - - public TableData setVisible(boolean isVisible) { - putValue(SELECTED_KEY, isVisible); - return this; - } - - public void actionPerformed(ActionEvent event) { - if (modelIndex >= 0) { - setColumnVisible(isVisible()); - } - } - - private void setColumnVisible(boolean isVisible) { - if (isVisible) { - if (tableColumn != null) { - int count = table.getColumnCount(); - table.addColumn(tableColumn); - tableColumn = null; - packColumn(table, count); - - int newIndex = 0; - for(int i = 0; i < modelIndex; i++) { - if (table.convertColumnIndexToView(i) >= 0) { - // The new column should be after this visible column - newIndex++; - } - } - if (newIndex < count) { - table.getColumnModel().moveColumn(count, newIndex); - } - } - } else { - int columnIndex = table.convertColumnIndexToView(modelIndex); - if (columnIndex >= 0 ) { - tableColumn = table.getColumnModel().getColumn(columnIndex); - table.removeColumn(tableColumn); - } - } - } - - public final Object getAverageValue(Node[] nodes) { - Object tmp = averageCache; - if (tmp != null) { - return tmp; - } - - if (dataClass == Long.class || dataClass == Double.class - || dataClass == Number.class) { - double average = 0.0; - if (nodes != null && nodes.length > 0) { - int count = 0; - for(Node node : nodes) { - if (node.getSensorDataAggregator().getDataCount() > 0) { - average += ((Number) getValue(node)).doubleValue(); - count++; - } - } - if (count > 0) { - average = average / count; - } - } - if (dataClass == Long.class) { - tmp = (long) (average + 0.5); - } else { - tmp = average; - } - } else if (dataClass == Node.class) { - tmp = AVERAGE_NODE; - } - averageCache = tmp; - return tmp; - } - - public final void clearAverageCache() { - averageCache = null; - } - - public abstract Object getValue(Node node); - - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/SerialConsole.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/SerialConsole.java deleted file mode 100644 index ef7b0c7e5..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/SerialConsole.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * SerialConsole - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 4 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public class SerialConsole implements Visualizer { - - private final CollectServer server; - private final String category; - private JPanel panel; - private JTextArea logArea; - private JTextField commandField; - private String[] history = new String[50]; - private int historyPos = 0; - private int historyCount = 0; - - public SerialConsole(CollectServer server, String category) { - this.server = server; - this.category = category; - panel = new JPanel(new BorderLayout()); - logArea = new JTextArea(4, 30); - logArea.setEditable(false); - panel.add(new JScrollPane(logArea), BorderLayout.CENTER); - - JPopupMenu popupMenu = new JPopupMenu(); - JMenuItem clearItem = new JMenuItem("Clear"); - clearItem.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - logArea.setText(""); - } - - }); - popupMenu.add(clearItem); - logArea.setComponentPopupMenu(popupMenu); - - commandField = new JTextField(); - commandField.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - String command = trim(commandField.getText()); - if (command != null) { - try { - int previous = historyCount - 1; - if (previous < 0) previous += history.length; - if (!command.equals(history[previous])) { - history[historyCount] = command; - historyCount = (historyCount + 1) % history.length; - } - historyPos = historyCount; - if (SerialConsole.this.server.sendToNode(command)) { - commandField.setText(""); - } else { - addSerialData("*** failed to send command ***"); - } - } catch (Exception ex) { - System.err.println("could not send '" + command + "':"); - ex.printStackTrace(); - JOptionPane.showMessageDialog(panel, - "could not send '" + command + "':\n" - + ex, "ERROR", - JOptionPane.ERROR_MESSAGE); - } - } else { - commandField.getToolkit().beep(); - } - } - - }); - commandField.addKeyListener(new KeyAdapter() { - - @Override - public void keyPressed(KeyEvent e) { - switch (e.getKeyCode()) { - case KeyEvent.VK_UP: { - int nextPos = (historyPos + history.length - 1) % history.length; - if (nextPos == historyCount || history[nextPos] == null) { - commandField.getToolkit().beep(); - } else { - String cmd = trim(commandField.getText()); - if (cmd != null) { - history[historyPos] = cmd; - } - historyPos = nextPos; - commandField.setText(history[historyPos]); - } - break; - } - case KeyEvent.VK_DOWN: { - int nextPos = (historyPos + 1) % history.length; - if (nextPos == historyCount) { - historyPos = nextPos; - commandField.setText(""); - } else if (historyPos == historyCount || history[nextPos] == null) { - commandField.getToolkit().beep(); - } else { - String cmd = trim(commandField.getText()); - if (cmd != null) { - history[historyPos] = cmd; - } - historyPos = nextPos; - commandField.setText(history[historyPos]); - } - break; - } - } - } - - }); - panel.add(commandField, BorderLayout.SOUTH); - } - - @Override - public Component getPanel() { - return panel; - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return "Serial Console"; - } - - @Override - public void nodeAdded(Node node) { - // Ignore - } - - @Override - public void nodeDataReceived(SensorData sensorData) { - // Ignore - } - - @Override - public void clearNodeData() { - // Ignore - } - - @Override - public void nodesSelected(Node[] node) { - // Ignore - } - - public void addSerialData(final String text) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - String current = logArea.getText(); - int len = current.length(); - if (len > 4096) { - current = current.substring(len - 4096); - } - current = len > 0 ? (current + '\n' + text) : text; - logArea.setText(current); - logArea.setCaretPosition(current.length()); - } - }); - } - - private String trim(String text) { - return (text != null) && ((text = text.trim()).length() > 0) ? text : null; - } - -} diff --git a/tools/collect-view/src/org/contikios/contiki/collect/gui/TimeChartPanel.java b/tools/collect-view/src/org/contikios/contiki/collect/gui/TimeChartPanel.java deleted file mode 100644 index 206e25b5c..000000000 --- a/tools/collect-view/src/org/contikios/contiki/collect/gui/TimeChartPanel.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - * - * ----------------------------------------------------------------- - * - * TimeChartPanel - * - * Authors : Joakim Eriksson, Niclas Finne - * Created : 3 jul 2008 - * Updated : $Date: 2010/11/03 14:53:05 $ - * $Revision: 1.1 $ - */ - -package org.contikios.contiki.collect.gui; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.util.Date; -import javax.swing.JPanel; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.time.Second; -import org.jfree.data.time.TimeSeries; -import org.jfree.data.time.TimeSeriesCollection; -import org.contikios.contiki.collect.CollectServer; -import org.contikios.contiki.collect.Node; -import org.contikios.contiki.collect.SensorData; -import org.contikios.contiki.collect.Visualizer; - -/** - * - */ -public abstract class TimeChartPanel extends JPanel implements Visualizer { - - private static final long serialVersionUID = -607864439709540641L; - - protected final CollectServer server; - protected final String category; - protected final String title; - protected final TimeSeriesCollection timeSeries; - protected final JFreeChart chart; - protected final ChartPanel chartPanel; - - private Node[] selectedNodes; - - private double minValue; - private double maxValue; - private int rangeTick = 0; - private boolean hasGlobalRange; - private int maxItemCount; - - public TimeChartPanel(CollectServer server, String category, String title, - String chartTitle, String timeAxisLabel, String valueAxisLabel) { - super(new BorderLayout()); - this.server = server; - this.category = category; - this.title = title; - this.timeSeries = new TimeSeriesCollection(); - this.chart = ChartFactory.createTimeSeriesChart( - chartTitle, timeAxisLabel, valueAxisLabel, timeSeries, - true, true, false - ); - this.chartPanel = new ChartPanel(chart); - this.chartPanel.setPreferredSize(new Dimension(500, 270)); - setBaseShapeVisible(true); - setMaxItemCount(server.getDefaultMaxItemCount()); - add(chartPanel, BorderLayout.CENTER); - } - - @Override - public String getCategory() { - return category; - } - - @Override - public String getTitle() { - return title; - } - - @Override - public Component getPanel() { - return this; - } - - @Override - public void nodeAdded(Node node) { - // Ignore - } - - @Override - public void nodesSelected(Node[] nodes) { - if (this.selectedNodes != nodes) { - this.selectedNodes = nodes; - if (isVisible()) { - updateCharts(); - } - } - } - - @Override - public void nodeDataReceived(SensorData data) { - if (hasGlobalRange) { - boolean update = false; - if (minValue > maxValue) { - update = true; - } else { - double value = getSensorDataValue(data); - if (value < minValue) { - minValue = value; - update = true; - } - if (value > maxValue) { - maxValue = value; - update = true; - } - } - if (update && isVisible()) { - updateGlobalRange(); - } - } - if (isVisible() && selectedNodes != null && selectedNodes.length == timeSeries.getSeriesCount()) { - Node node = data.getNode(); - for (int i = 0, n = selectedNodes.length; i < n; i++) { - if (node == selectedNodes[i]) { - TimeSeries series = timeSeries.getSeries(i); - int groupSize = getGroupSize(node); - if (groupSize > 1) { - series.clear(); - updateSeries(series, node, groupSize); - } else { - series.addOrUpdate(new Second(new Date(data.getNodeTime())), getSensorDataValue(data)); - } - chartPanel.repaint(); - break; - } - } - } - } - - @Override - public void clearNodeData() { - if (isVisible()) { - updateCharts(); - } - } - - private void updateCharts() { - timeSeries.removeAllSeries(); - if (this.selectedNodes != null) { - for(Node node: this.selectedNodes) { - TimeSeries series = new TimeSeries(node.getName(), Second.class); - // Reduce the number of items by grouping them and use the average for each group - int groupSize = getGroupSize(node); - if (groupSize > 1) { - updateSeries(series, node, groupSize); - } else { - for (int i = 0, n = node.getSensorDataCount(); i < n; i++) { - SensorData data = node.getSensorData(i); - series.addOrUpdate(new Second(new Date(data.getNodeTime())), getSensorDataValue(data)); - } - } - timeSeries.addSeries(series); - } - } - } - - protected int getGroupSize(Node node) { - if (maxItemCount > 0) { - int sensorDataCount = node.getSensorDataCount(); - if (sensorDataCount > maxItemCount) { - int groupSize = sensorDataCount / maxItemCount; - if (sensorDataCount / groupSize >= maxItemCount) { - groupSize++; - } - return groupSize; - } - } - return 1; - } - - protected void updateSeries(TimeSeries series, Node node, int groupSize) { - for (int i = 0, n = node.getSensorDataCount(); i < n; i += groupSize) { - double value = 0.0; - long time = 0L; - for (int j = 0; j < groupSize; j++) { - SensorData data = node.getSensorData(i); - value += getSensorDataValue(data); - time += data.getNodeTime() / 1000L; - } - series.addOrUpdate(new Second(new Date((time / groupSize) * 1000L)), value / groupSize); - } - } - - public boolean getBaseShapeVisible() { - return ((XYLineAndShapeRenderer)this.chart.getXYPlot().getRenderer()).getBaseShapesVisible(); - } - - public void setBaseShapeVisible(boolean visible) { - ((XYLineAndShapeRenderer)this.chart.getXYPlot().getRenderer()).setBaseShapesVisible(visible); - } - - public int getRangeTick() { - return rangeTick; - } - - public void setRangeTick(int rangeTick) { - this.rangeTick = rangeTick; - } - - public double getRangeMinimumSize() { - return chart.getXYPlot().getRangeAxis().getAutoRangeMinimumSize(); - } - - public void setRangeMinimumSize(double size) { - chart.getXYPlot().getRangeAxis().setAutoRangeMinimumSize(size); - } - - public boolean hasGlobalRange() { - return hasGlobalRange; - } - - public void setGlobalRange(boolean hasGlobalRange) { - if (this.hasGlobalRange != hasGlobalRange) { - this.hasGlobalRange = hasGlobalRange; - if (hasGlobalRange) { - minValue = Double.MAX_VALUE; - maxValue = Double.MIN_NORMAL; - if (isVisible()) { - updateGlobalRange(); - } - } else { - chart.getXYPlot().getRangeAxis().setAutoRange(true); - } - } - } - - private void updateGlobalRange() { - if (hasGlobalRange) { - if (minValue > maxValue) { - for (int i = 0, n = server.getSensorDataCount(); i < n; i++) { - double value = getSensorDataValue(server.getSensorData(i)); - if (value < minValue) minValue = value; - if (value > maxValue) maxValue = value; - } - } - if (minValue < maxValue) { - double minSize = getRangeMinimumSize(); - double min = minValue; - double max = maxValue; - if (max - min < minSize) { - double d = (minSize - (max - min)) / 2; - min -= d; - max += d; - } - if (rangeTick > 0) { - min = ((int) (min - rangeTick / 2) / rangeTick) * rangeTick; -// max = ((int) (max + rangeTick / 2) / rangeTick) * rangeTick; - } - chart.getXYPlot().getRangeAxis().setRange(min, max); - } - } - } - - /** - * Returns the maximal number of chart items to display for each node. - * - * @return the maximal number of chart items to display for each node or 0 - * for unlimited number of chart items. - */ - public int getMaxItemCount() { - return maxItemCount; - } - - /** - * Sets the maximal number of chart items to display for each node. Items will be - * grouped and replaced by the average value when needed. - * - * @param maxItemCount - the maximal number of chart items to display for each node or - * 0 for unlimited number (default) - */ - public void setMaxItemCount(int maxItemCount) { - this.maxItemCount = maxItemCount; - if (isVisible()) { - updateCharts(); - } - } - - public void setVisible(boolean visible) { - if (visible) { - updateGlobalRange(); - updateCharts(); - } else { - timeSeries.removeAllSeries(); - } - super.setVisible(visible); - } - - protected abstract double getSensorDataValue(SensorData data); - -}