2 * Copyright © 2010 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 import java.awt.event.*;
23 import javax.swing.filechooser.FileNameExtensionFilter;
24 import javax.swing.table.AbstractTableModel;
28 import gnu.io.CommPortIdentifier;
30 import altosui.AltosSerial;
31 import altosui.AltosSerialMonitor;
32 import altosui.AltosTelemetry;
33 import altosui.AltosState;
35 class AltosUIMonitor implements AltosSerialMonitor {
36 public void data(String data) {
37 System.out.println(data);
41 class AltosFlightStatusTableModel extends AbstractTableModel {
42 private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" };
43 private Object[] data = { 0, "idle", 0, 0 };
45 public int getColumnCount() { return columnNames.length; }
46 public int getRowCount() { return 1; }
47 public String getColumnName(int col) { return columnNames[col]; }
48 public Object getValueAt(int row, int col) { return data[col]; }
50 public void setValueAt(Object value, int col) {
52 fireTableCellUpdated(0, col);
55 public void setValueAt(Object value, int row, int col) {
56 setValueAt(value, col);
59 public void set(AltosState state) {
60 setValueAt(state.height, 0);
61 setValueAt(state.data.state, 1);
62 setValueAt(state.data.rssi, 2);
63 setValueAt(state.speed, 3);
67 public class AltosUI extends JFrame {
68 private int channel = -1;
70 private JTable flightStatus;
71 private JTable flightInfo;
72 private AltosSerial serialLine;
76 String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" };
77 Object[][] statusData = { { "0", "pad", "-50", "0" } };
79 flightStatus = new JTable(statusData, statusNames);
81 flightStatus.setShowGrid(false);
83 this.add(flightStatus);
89 serialLine = new AltosSerial();
90 serialLine.monitor(new AltosUIMonitor());
91 int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
92 this.setSize(new Dimension (dpi * 5, dpi * 4));
94 setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
95 addWindowListener(new WindowAdapter() {
97 public void windowClosing(WindowEvent e) {
103 final JFileChooser deviceChooser = new JFileChooser();
104 final JFileChooser logdirChooser = new JFileChooser();
105 final String logdirName = "TeleMetrum";
108 private void setLogdir() {
110 logdir = new File(logdirChooser.getCurrentDirectory(), logdirName);
111 logdirChooser.setCurrentDirectory(logdir);
114 private void makeLogdir() {
116 if (!logdir.exists()) {
117 if (!logdir.mkdirs())
118 JOptionPane.showMessageDialog(AltosUI.this,
120 "Cannot create directory",
121 JOptionPane.ERROR_MESSAGE);
122 } else if (!logdir.isDirectory()) {
123 JOptionPane.showMessageDialog(AltosUI.this,
125 "Is not a directory",
126 JOptionPane.ERROR_MESSAGE);
130 private void PickSerialDevice() {
131 java.util.Enumeration<CommPortIdentifier> port_list = CommPortIdentifier.getPortIdentifiers();
132 while (port_list.hasMoreElements()) {
133 CommPortIdentifier identifier = port_list.nextElement();
134 System.out.println("Serial port " + identifier.getName());
138 private void ConnectToDevice() {
140 int returnVal = deviceChooser.showOpenDialog(AltosUI.this);
142 if (returnVal == JFileChooser.APPROVE_OPTION) {
143 File file = deviceChooser.getSelectedFile();
145 serialLine.open(file);
146 } catch (FileNotFoundException ee) {
147 JOptionPane.showMessageDialog(AltosUI.this,
149 "Cannot open serial port",
150 JOptionPane.ERROR_MESSAGE);
155 String readline(FileInputStream s) throws IOException {
159 while ((c = s.read()) != -1) {
164 line = line + (char) c;
170 * Open an existing telemetry file and replay it in realtime
173 private void Replay() {
175 logdirChooser.setDialogTitle("Select Telemetry File");
176 logdirChooser.setFileFilter(new FileNameExtensionFilter("Telemetry file", "telem"));
177 int returnVal = logdirChooser.showOpenDialog(AltosUI.this);
179 if (returnVal == JFileChooser.APPROVE_OPTION) {
180 File file = logdirChooser.getSelectedFile();
182 System.out.println("No file selected?");
183 String filename = file.getName();
185 FileInputStream replay = new FileInputStream(file);
189 while ((line = readline(replay)) != null) {
191 AltosTelemetry t = new AltosTelemetry(line);
192 System.out.println ("Version " + t.version + t.callsign);
193 } catch (ParseException pp) {
194 JOptionPane.showMessageDialog(AltosUI.this,
197 JOptionPane.ERROR_MESSAGE);
201 } catch (IOException ee) {
202 JOptionPane.showMessageDialog(AltosUI.this,
205 JOptionPane.ERROR_MESSAGE);
209 } catch (IOException e) {}
211 } catch (FileNotFoundException ee) {
212 JOptionPane.showMessageDialog(AltosUI.this,
214 "Cannot open serial port",
215 JOptionPane.ERROR_MESSAGE);
220 private void SaveFlightData() {
223 private void createMenu() {
224 JMenuBar menubar = new JMenuBar();
227 JRadioButtonMenuItem radioitem;
231 menu = new JMenu("File");
232 menu.setMnemonic(KeyEvent.VK_F);
235 item = new JMenuItem("Quit",KeyEvent.VK_Q);
236 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
237 ActionEvent.CTRL_MASK));
238 item.addActionListener(new ActionListener() {
239 public void actionPerformed(ActionEvent e) {
248 menu = new JMenu("Device");
249 menu.setMnemonic(KeyEvent.VK_D);
252 item = new JMenuItem("Connect to Device",KeyEvent.VK_C);
253 item.addActionListener(new ActionListener() {
254 public void actionPerformed(ActionEvent e) {
260 item = new JMenuItem("Disconnect from Device",KeyEvent.VK_D);
261 item.addActionListener(new ActionListener() {
262 public void actionPerformed(ActionEvent e) {
270 item = new JMenuItem("Save Flight Data",KeyEvent.VK_S);
271 item.addActionListener(new ActionListener() {
272 public void actionPerformed(ActionEvent e) {
278 item = new JMenuItem("Replay",KeyEvent.VK_R);
279 item.addActionListener(new ActionListener() {
280 public void actionPerformed(ActionEvent e) {
288 menu = new JMenu("Log");
289 menu.setMnemonic(KeyEvent.VK_L);
292 item = new JMenuItem("New Log",KeyEvent.VK_N);
293 item.addActionListener(new ActionListener() {
294 public void actionPerformed(ActionEvent e) {
299 item = new JMenuItem("Configure Log",KeyEvent.VK_C);
300 item.addActionListener(new ActionListener() {
301 public void actionPerformed(ActionEvent e) {
308 menu = new JMenu("Voice", true);
309 menu.setMnemonic(KeyEvent.VK_V);
312 radioitem = new JRadioButtonMenuItem("Enable Voice");
313 radioitem.addActionListener(new ActionListener() {
314 public void actionPerformed(ActionEvent e) {
322 menu = new JMenu("Channel", true);
323 menu.setMnemonic(KeyEvent.VK_C);
325 ButtonGroup group = new ButtonGroup();
327 for (int c = 0; c <= 9; c++) {
328 radioitem = new JRadioButtonMenuItem(String.format("Channel %1d (%7.3fMHz)", c,
331 radioitem.setActionCommand(String.format("%d", c));
332 radioitem.addActionListener(new ActionListener() {
333 public void actionPerformed(ActionEvent e) {
334 System.out.println("Command: " + e.getActionCommand() + " param: " +
339 group.add(radioitem);
343 this.setJMenuBar(menubar);
346 public static void main(final String[] args) {
347 AltosUI altosui = new AltosUI();
348 altosui.setVisible(true);