From 019b984b7a262cfee01a69b558ebd9a4fb76aeda Mon Sep 17 00:00:00 2001 From: Fredrik Osterlind Date: Thu, 7 Jun 2012 12:33:29 +0200 Subject: [PATCH] simplified SerialUI implementation: code was both complex, buggy and contained unused broken functionality (slip, tos mode) --- .../java/se/sics/cooja/dialogs/SerialUI.java | 356 +++++++----------- 1 file changed, 138 insertions(+), 218 deletions(-) diff --git a/tools/cooja/java/se/sics/cooja/dialogs/SerialUI.java b/tools/cooja/java/se/sics/cooja/dialogs/SerialUI.java index 788e9f6f0..edc88ff5c 100644 --- a/tools/cooja/java/se/sics/cooja/dialogs/SerialUI.java +++ b/tools/cooja/java/se/sics/cooja/dialogs/SerialUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Swedish Institute of Computer Science. + * Copyright (c) 2012, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,8 +44,6 @@ import java.util.Observable; import java.util.Observer; import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; @@ -58,161 +56,165 @@ import org.jdom.Element; import se.sics.cooja.Mote; import se.sics.cooja.interfaces.Log; import se.sics.cooja.interfaces.SerialPort; -import se.sics.cooja.plugins.SLIP; public abstract class SerialUI extends Log implements SerialPort { private static Logger logger = Logger.getLogger(SerialUI.class); - private final static byte SLIP_END = (byte)0300; - private final static byte SLIP_ESC = (byte)0333; - private final static byte SLIP_ESC_END = (byte)0334; - private final static byte SLIP_ESC_ESC = (byte)0335; - - private final static int MAX_LENGTH = 1024; - private String lastLogMessage = ""; - private StringBuilder newMessage = new StringBuilder(); + private byte lastSerialData = 0; /* SerialPort */ + private String lastLogMessage = ""; /* Log */ + private StringBuilder newMessage = new StringBuilder(); /* Log */ - private JTextArea logTextPane = null; - private JTextField commandField; - private JCheckBox slipCheckbox; - private String[] history = new String[50]; - private int historyPos = 0; - private int historyCount = 0; + /* Command history */ + private final static int HISTORY_SIZE = 15; + private ArrayList history = new ArrayList(); + private int historyPos = -1; - private class SerialDataObservable extends Observable { - private void notifyNewData() { + /* Log */ + public String getLastLogMessage() { + return lastLogMessage; + } + + /* SerialPort */ + private abstract class SerialDataObservable extends Observable { + public abstract void notifyNewData(); + } + private SerialDataObservable serialDataObservable = new SerialDataObservable() { + public void notifyNewData() { if (this.countObservers() == 0) { return; } setChanged(); notifyObservers(SerialUI.this); } - } - - private SerialDataObservable serialDataObservable = new SerialDataObservable(); - private byte lastSerialData = 0; - - public String getLastLogMessage() { - return lastLogMessage; - } - - public abstract Mote getMote(); - + }; public void addSerialDataObserver(Observer o) { serialDataObservable.addObserver(o); } - public void deleteSerialDataObserver(Observer o) { serialDataObservable.deleteObserver(o); } - public byte getLastSerialData() { return lastSerialData; } - - public JPanel getInterfaceVisualizer() { - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - - if (logTextPane == null) { - logTextPane = new JTextArea(); + public void dataReceived(int data) { + if (data == '\n') { + /* Notify observers of new log */ + lastLogMessage = newMessage.toString(); + lastLogMessage = lastLogMessage.replaceAll("[^\\p{Print}]", ""); + newMessage.setLength(0); + this.setChanged(); + this.notifyObservers(getMote()); + } else { + newMessage.append((char) data); + if (newMessage.length() > MAX_LENGTH) { + /*logger.warn("Dropping too large log message (>" + MAX_LENGTH + " bytes).");*/ + lastLogMessage = "# [1024 bytes binary data]"; + newMessage.setLength(0); + this.setChanged(); + this.notifyObservers(getMote()); + } } - // Send RS232 data visualizer - JPanel sendPane = new JPanel(new BorderLayout()); - commandField = new JTextField(15); + /* Notify observers of new serial character */ + lastSerialData = (byte) data; + serialDataObservable.notifyNewData(); + } + + + /* Mote interface visualizer */ + public JPanel getInterfaceVisualizer() { + JPanel panel = new JPanel(new BorderLayout()); + JPanel commandPane = new JPanel(new BorderLayout()); + + final JTextArea logTextPane = new JTextArea(); + final JTextField commandField = new JTextField(15); JButton sendButton = new JButton("Send data"); - ActionListener action = new ActionListener() { + ActionListener sendCommandAction = 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 (slipCheckbox.isSelected()) { - addToLog("SLIP> " + command); - command += "\n"; - writeArray(SLIP.asSlip(command.getBytes())); - } else { - addToLog("> " + command); - writeString(command); - } - commandField.setText(""); - } catch (Exception ex) { - System.err.println("could not send '" + command + "':"); - ex.printStackTrace(); - JOptionPane.showMessageDialog(logTextPane, - "could not send '" + command + "':\n" - + ex, "ERROR", - JOptionPane.ERROR_MESSAGE); - } - } else { + final String command = trim(commandField.getText()); + if (command == null) { commandField.getToolkit().beep(); + return; + } + + try { + /* Add to history */ + if (history.size() > 0 && command.equals(history.get(0))) { + /* Ignored */ + } else { + history.add(0, command); + while (history.size() > HISTORY_SIZE) { + history.remove(HISTORY_SIZE-1); + } + } + historyPos = -1; + + appendToTextArea(logTextPane, "> " + command); + commandField.setText(""); + if (getMote().getSimulation().isRunning()) { + getMote().getSimulation().invokeSimulationThread(new Runnable() { + public void run() { + writeString(command); + } + }); + } else { + writeString(command); + } + } catch (Exception ex) { + System.err.println("could not send '" + command + "':"); + ex.printStackTrace(); + JOptionPane.showMessageDialog( + logTextPane, + "Could not send '" + command + "':\n" + ex.getMessage(), "Error sending message", + JOptionPane.ERROR_MESSAGE); } } - }; + commandField.addActionListener(sendCommandAction); + sendButton.addActionListener(sendCommandAction); + + /* History */ 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) { + historyPos++; + if (historyPos >= history.size()) { + historyPos = history.size() - 1; commandField.getToolkit().beep(); + } + if (historyPos >= 0 && historyPos < history.size()) { + commandField.setText(history.get(historyPos)); } else { - String cmd = trim(commandField.getText()); - if (cmd != null) { - history[historyPos] = cmd; - } - historyPos = nextPos; - commandField.setText(history[historyPos]); + commandField.setText(""); } break; } case KeyEvent.VK_DOWN: { - int nextPos = (historyPos + 1) % history.length; - if (nextPos == historyCount) { - historyPos = nextPos; + historyPos--; + if (historyPos < 0) { + historyPos = -1; commandField.setText(""); - } else if (historyPos == historyCount || history[nextPos] == null) { commandField.getToolkit().beep(); + break; + } + if (historyPos >= 0 && historyPos < history.size()) { + commandField.setText(history.get(historyPos)); } else { - String cmd = trim(commandField.getText()); - if (cmd != null) { - history[historyPos] = cmd; - } - historyPos = nextPos; - commandField.setText(history[historyPos]); + commandField.setText(""); } break; } } } - }); - slipCheckbox = new JCheckBox("", false); - slipCheckbox.setToolTipText("Wrap data as SLIP"); + commandPane.add(BorderLayout.CENTER, commandField); + commandPane.add(BorderLayout.EAST, sendButton); - commandField.addActionListener(action); - sendButton.addActionListener(action); - sendPane.add(BorderLayout.WEST, slipCheckbox); - sendPane.add(BorderLayout.CENTER, commandField); - sendPane.add(BorderLayout.EAST, sendButton); - - // Receive RS232 data visualizer logTextPane.setOpaque(false); logTextPane.setEditable(false); logTextPane.addKeyListener(new KeyAdapter() { @@ -223,52 +225,28 @@ public abstract class SerialUI extends Log implements SerialPort { commandField.requestFocusInWindow(); } }); - if (getLastLogMessage() == null) { - logTextPane.setText(""); - } else { - logTextPane.append(getLastLogMessage()); - } + /* Mote interface observer */ Observer observer; this.addObserver(observer = new Observer() { public void update(Observable obs, Object obj) { final String logMessage = getLastLogMessage(); EventQueue.invokeLater(new Runnable() { public void run() { - addToLog(logMessage); + appendToTextArea(logTextPane, logMessage); } }); } }); - - // Saving observer reference for releaseInterfaceVisualizer panel.putClientProperty("intf_obs", observer); JScrollPane scrollPane = new JScrollPane(logTextPane); scrollPane.setPreferredSize(new Dimension(100, 100)); - panel.add(BorderLayout.NORTH, new JLabel("Last serial data:")); panel.add(BorderLayout.CENTER, scrollPane); - panel.add(BorderLayout.SOUTH, sendPane); + panel.add(BorderLayout.SOUTH, commandPane); return panel; } - protected void addToLog(String text) { - String current = logTextPane.getText(); - int len = current.length(); - if (len > 8192) { - current = current.substring(len - 8192); - } - current = len > 0 ? (current + '\n' + text) : text; - logTextPane.setText(current); - logTextPane.setCaretPosition(current.length()); - - Rectangle visRect = logTextPane.getVisibleRect(); - if (visRect.x > 0) { - visRect.x = 0; - logTextPane.scrollRectToVisible(visRect); - } - } - public void releaseInterfaceVisualizer(JPanel panel) { Observer observer = (Observer) panel.getClientProperty("intf_obs"); if (observer == null) { @@ -279,13 +257,14 @@ public abstract class SerialUI extends Log implements SerialPort { this.deleteObserver(observer); } + private static final String HISTORY_SEPARATOR = "~;"; public Collection getConfigXML() { StringBuilder sb = new StringBuilder(); for (String s: history) { if (s == null) { continue; } - sb.append(s + "~;"); + sb.append(s + HISTORY_SEPARATOR); } if (sb.length() == 0) { return null; @@ -302,101 +281,42 @@ public abstract class SerialUI extends Log implements SerialPort { public void setConfigXML(Collection configXML, boolean visAvailable) { for (Element element : configXML) { if (element.getName().equals("history")) { - String[] history = element.getText().split("~;"); - System.arraycopy(history, 0, this.history, 0, history.length); - historyCount = history.length; - historyPos = historyCount; + String[] history = element.getText().split(HISTORY_SEPARATOR); + for (String h: history) { + this.history.add(h); + } + historyPos = -1; } } } - private int tosChars = 0; - boolean tosMode = false; - private int tosPos = 0; - private int tosLen = 0; - - private int slipCounter = 0; - private int totalTOSChars = 0; - - public void dataReceived(int data) { - if (data == SLIP_END || data == SLIP_ESC) { - slipCounter++; - } - if (tosMode) { - int tmpData = data; - /* needs to add checks to CRC */ - // System.out.println("Received: " + Integer.toString(data, 16) + " = " + (char) data + " tosPos: " + tosPos); - if (data == 0x7e) { - if (tosPos > 6) { - lastLogMessage = "TinyOS: " + newMessage.toString(); - newMessage.setLength(0); - this.setChanged(); - this.notifyObservers(getMote()); - // System.out.println("*** Printing TOS String: " + lastLogMessage); - tosPos = 0; - tosLen = 0; - } else { - /* start of new message! */ - tosPos = 0; - tosLen = 0; - } - } - if (tosPos == 7) { - tosLen = data; - // System.out.println("TOS Payload len: " + tosLen); - } - if (tosPos > 9 && tosPos < 10 + tosLen) { - if (data < 32) { - tmpData = 32; - } - newMessage.append((char) tmpData); - } - } else { - if (data == 0x7e) { - tosChars++; - totalTOSChars = 0; /* XXX Disabled TOS mode due to error */ - totalTOSChars++; - if (tosChars == 2) { - if (totalTOSChars > slipCounter) { - tosMode = true; - tosMode = false; /* XXX Disabled TOS mode due to error */ - /* already read one char here */ - tosPos = 1; - } else { - tosChars = 0; - } - } - } else { - tosChars = 0; - } - if (data == '\n') { - lastLogMessage = newMessage.toString(); - lastLogMessage = lastLogMessage.replaceAll("[^\\p{Print}]", ""); - newMessage.setLength(0); - this.setChanged(); - this.notifyObservers(getMote()); - } else { - newMessage.append((char) data); - if (newMessage.length() > MAX_LENGTH) { - /*logger.warn("Dropping too large log message (>" + MAX_LENGTH + " bytes).");*/ - lastLogMessage = "# [1024 bytes binary data]"; - this.setChanged(); - this.notifyObservers(getMote()); - newMessage.setLength(0); - } - } - } - lastSerialData = (byte) data; - serialDataObservable.notifyNewData(); - } - public void close() { } public void flushInput() { } - private String trim(String text) { + public abstract Mote getMote(); + + + protected static void appendToTextArea(JTextArea textArea, String text) { + String current = textArea.getText(); + int len = current.length(); + if (len > 8192) { + current = current.substring(len - 8192); + } + current = len > 0 ? (current + '\n' + text) : text; + textArea.setText(current); + textArea.setCaretPosition(current.length()); + + Rectangle visRect = textArea.getVisibleRect(); + if (visRect.x > 0) { + visRect.x = 0; + textArea.scrollRectToVisible(visRect); + } + } + + private static String trim(String text) { return (text != null) && ((text = text.trim()).length() > 0) ? text : null; } }