21c3e7a27367e9fd4815998709cdb3dc30a65bd4
[fw/altos] / ao-tools / altosui / AltosUI.java
1 /*
2  * Copyright © 2010 Keith Packard <keithp@keithp.com>
3  *
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.
7  *
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.
12  *
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.
16  */
17
18 package altosui;
19
20 import java.awt.*;
21 import java.awt.event.*;
22 import javax.swing.*;
23 import javax.swing.filechooser.FileNameExtensionFilter;
24 import javax.swing.table.AbstractTableModel;
25 import java.io.*;
26 import java.util.*;
27 import java.text.*;
28 import gnu.io.CommPortIdentifier;
29
30 import altosui.AltosSerial;
31 import altosui.AltosSerialMonitor;
32 import altosui.AltosTelemetry;
33 import altosui.AltosState;
34
35 class AltosUIMonitor implements AltosSerialMonitor {
36         public void data(String data) {
37                 System.out.println(data);
38         }
39 }
40
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 };
44
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]; }
49
50         public void setValueAt(Object value, int col) {
51                 data[col] = value;
52                 fireTableCellUpdated(0, col);
53         }
54
55         public void setValueAt(Object value, int row, int col) {
56                 setValueAt(value, col);
57         }
58
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);
64         }
65 }
66
67 public class AltosUI extends JFrame {
68         private int channel = -1;
69
70         private JTable flightStatus;
71         private JTable flightInfo;
72         private AltosSerial serialLine;
73
74         public AltosUI() {
75
76                 String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" };
77                 Object[][] statusData = { { "0", "pad", "-50", "0" } };
78
79                 flightStatus = new JTable(statusData, statusNames);
80
81                 flightStatus.setShowGrid(false);
82
83                 this.add(flightStatus);
84
85                 setTitle("AltOS");
86
87                 createMenu();
88
89                 serialLine = new AltosSerial();
90                 serialLine.monitor(new AltosUIMonitor());
91                 int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
92                 this.setSize(new Dimension (dpi * 5, dpi * 4));
93                 this.validate();
94                 setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
95                 addWindowListener(new WindowAdapter() {
96                         @Override
97                         public void windowClosing(WindowEvent e) {
98                                 System.exit(0);
99                         }
100                 });
101         }
102
103         final JFileChooser deviceChooser = new JFileChooser();
104         final JFileChooser logdirChooser = new JFileChooser();
105         final String logdirName = "TeleMetrum";
106         File logdir = null;
107
108         private void setLogdir() {
109                 if (logdir == null)
110                         logdir = new File(logdirChooser.getCurrentDirectory(), logdirName);
111                 logdirChooser.setCurrentDirectory(logdir);
112         }
113
114         private void makeLogdir() {
115                 setLogdir();
116                 if (!logdir.exists()) {
117                         if (!logdir.mkdirs())
118                                 JOptionPane.showMessageDialog(AltosUI.this,
119                                                               logdir.getName(),
120                                                               "Cannot create directory",
121                                                               JOptionPane.ERROR_MESSAGE);
122                 } else if (!logdir.isDirectory()) {
123                         JOptionPane.showMessageDialog(AltosUI.this,
124                                                       logdir.getName(),
125                                                       "Is not a directory",
126                                                       JOptionPane.ERROR_MESSAGE);
127                 }
128         }
129
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());
135                 }
136         }
137
138         private void ConnectToDevice() {
139                 PickSerialDevice();
140                 int returnVal = deviceChooser.showOpenDialog(AltosUI.this);
141
142                 if (returnVal == JFileChooser.APPROVE_OPTION) {
143                         File file = deviceChooser.getSelectedFile();
144                         try {
145                                 serialLine.open(file);
146                         } catch (FileNotFoundException ee) {
147                                 JOptionPane.showMessageDialog(AltosUI.this,
148                                                               file.getName(),
149                                                               "Cannot open serial port",
150                                                               JOptionPane.ERROR_MESSAGE);
151                         }
152                 }
153         }
154
155         String readline(FileInputStream s) throws IOException {
156                 int c;
157                 String  line = "";
158
159                 while ((c = s.read()) != -1) {
160                         if (c == '\r')
161                                 continue;
162                         if (c == '\n')
163                                 return line;
164                         line = line + (char) c;
165                 }
166                 return null;
167         }
168
169         /*
170          * Open an existing telemetry file and replay it in realtime
171          */
172
173         private void Replay() {
174                 setLogdir();
175                 logdirChooser.setDialogTitle("Select Telemetry File");
176                 logdirChooser.setFileFilter(new FileNameExtensionFilter("Telemetry file", "telem"));
177                 int returnVal = logdirChooser.showOpenDialog(AltosUI.this);
178
179                 if (returnVal == JFileChooser.APPROVE_OPTION) {
180                         File file = logdirChooser.getSelectedFile();
181                         if (file == null)
182                                 System.out.println("No file selected?");
183                         String  filename = file.getName();
184                         try {
185                                 FileInputStream replay = new FileInputStream(file);
186                                 String  line;
187
188                                 try {
189                                         while ((line = readline(replay)) != null) {
190                                                 try {
191                                                         AltosTelemetry  t = new AltosTelemetry(line);
192                                                         System.out.println ("Version " + t.version + t.callsign);
193                                                 } catch (ParseException pp) {
194                                                         JOptionPane.showMessageDialog(AltosUI.this,
195                                                                                       line,
196                                                                                       "error parsing",
197                                                                                       JOptionPane.ERROR_MESSAGE);
198                                                         break;
199                                                 }
200                                         }
201                                 } catch (IOException ee) {
202                                         JOptionPane.showMessageDialog(AltosUI.this,
203                                                                       filename,
204                                                                       "error reading",
205                                                                       JOptionPane.ERROR_MESSAGE);
206                                 } finally {
207                                         try {
208                                                 replay.close();
209                                         } catch (IOException e) {}
210                                 }
211                         } catch (FileNotFoundException ee) {
212                                 JOptionPane.showMessageDialog(AltosUI.this,
213                                                               filename,
214                                                               "Cannot open serial port",
215                                                               JOptionPane.ERROR_MESSAGE);
216                         }
217                 }
218         }
219
220         private void SaveFlightData() {
221         }
222
223         private void createMenu() {
224                 JMenuBar menubar = new JMenuBar();
225                 JMenu menu;
226                 JMenuItem item;
227                 JRadioButtonMenuItem radioitem;
228
229                 // File menu
230                 {
231                         menu = new JMenu("File");
232                         menu.setMnemonic(KeyEvent.VK_F);
233                         menubar.add(menu);
234
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) {
240                                                 System.exit(0);
241                                         }
242                                 });
243                         menu.add(item);
244                 }
245
246                 // Device menu
247                 {
248                         menu = new JMenu("Device");
249                         menu.setMnemonic(KeyEvent.VK_D);
250                         menubar.add(menu);
251
252                         item = new JMenuItem("Connect to Device",KeyEvent.VK_C);
253                         item.addActionListener(new ActionListener() {
254                                         public void actionPerformed(ActionEvent e) {
255                                                 ConnectToDevice();
256                                         }
257                                 });
258                         menu.add(item);
259
260                         item = new JMenuItem("Disconnect from Device",KeyEvent.VK_D);
261                         item.addActionListener(new ActionListener() {
262                                         public void actionPerformed(ActionEvent e) {
263                                                 serialLine.close();
264                                         }
265                                 });
266                         menu.add(item);
267
268                         menu.addSeparator();
269
270                         item = new JMenuItem("Save Flight Data",KeyEvent.VK_S);
271                         item.addActionListener(new ActionListener() {
272                                         public void actionPerformed(ActionEvent e) {
273                                                 SaveFlightData();
274                                         }
275                                 });
276                         menu.add(item);
277
278                         item = new JMenuItem("Replay",KeyEvent.VK_R);
279                         item.addActionListener(new ActionListener() {
280                                         public void actionPerformed(ActionEvent e) {
281                                                 Replay();
282                                         }
283                                 });
284                         menu.add(item);
285                 }
286                 // Log menu
287                 {
288                         menu = new JMenu("Log");
289                         menu.setMnemonic(KeyEvent.VK_L);
290                         menubar.add(menu);
291
292                         item = new JMenuItem("New Log",KeyEvent.VK_N);
293                         item.addActionListener(new ActionListener() {
294                                         public void actionPerformed(ActionEvent e) {
295                                         }
296                                 });
297                         menu.add(item);
298
299                         item = new JMenuItem("Configure Log",KeyEvent.VK_C);
300                         item.addActionListener(new ActionListener() {
301                                         public void actionPerformed(ActionEvent e) {
302                                         }
303                                 });
304                         menu.add(item);
305                 }
306                 // Voice menu
307                 {
308                         menu = new JMenu("Voice", true);
309                         menu.setMnemonic(KeyEvent.VK_V);
310                         menubar.add(menu);
311
312                         radioitem = new JRadioButtonMenuItem("Enable Voice");
313                         radioitem.addActionListener(new ActionListener() {
314                                         public void actionPerformed(ActionEvent e) {
315                                         }
316                                 });
317                         menu.add(radioitem);
318                 }
319
320                 // Channel menu
321                 {
322                         menu = new JMenu("Channel", true);
323                         menu.setMnemonic(KeyEvent.VK_C);
324                         menubar.add(menu);
325                         ButtonGroup group = new ButtonGroup();
326
327                         for (int c = 0; c <= 9; c++) {
328                                 radioitem = new JRadioButtonMenuItem(String.format("Channel %1d (%7.3fMHz)", c,
329                                                                                    434.550 + c * 0.1),
330                                                                      c == 0);
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: " +
335                                                                            e.paramString());
336                                                 }
337                                         });
338                                 menu.add(radioitem);
339                                 group.add(radioitem);
340                         }
341                 }
342
343                 this.setJMenuBar(menubar);
344
345         }
346         public static void main(final String[] args) {
347                 AltosUI altosui = new AltosUI();
348                 altosui.setVisible(true);
349         }
350 }