altos/test: Adjust CRC error rate after FEC fix
[fw/altos] / micropeak / MicroPeak.java
1 /*
2  * Copyright © 2012 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; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 package org.altusmetrum.micropeak;
20
21 import java.awt.*;
22 import java.awt.event.*;
23 import javax.swing.*;
24 import java.io.*;
25 import java.util.concurrent.*;
26 import java.util.*;
27 import org.altusmetrum.altoslib_14.*;
28 import org.altusmetrum.altosuilib_14.*;
29
30 public class MicroPeak extends MicroFrame implements ActionListener, ItemListener, AltosFilterListener {
31
32         File            filename;
33         AltosGraph      graph;
34         AltosUIEnable   enable;
35         AltosFlightStatsTable   statsTable;
36         MicroRaw        raw;
37         MicroData       data;
38         Container       container;
39         JTabbedPane     pane;
40         JMenuBar        menu_bar;
41         static int      number_of_windows;
42
43         /* File menu */
44         final static String     open_command = "open";
45         final static String     save_command = "save";
46         final static String     export_command = "export";
47         final static String     preferences_command = "preferences";
48         final static String     close_command = "close";
49         final static String     exit_command = "exit";
50
51         static final String[][] file_menu_entries = new String[][] {
52                 { "Open",               open_command },
53                 { "Save a Copy",        save_command },
54                 { "Export Data",        export_command },
55                 { "Preferences",        preferences_command },
56                 { "Close",              close_command },
57                 { "Exit",               exit_command },
58         };
59
60         /* Download menu */
61         final static String     download_command = "download";
62         final static String     download_label = "Download";
63
64         static final String[][] download_menu_entries = new String[][] {
65                 { download_label,       download_command }
66         };
67
68         MicroPeak SetData(MicroData data) {
69                 MicroPeak       mp = this;
70                 if (this.data != null) {
71                         mp = new MicroPeak();
72                         return mp.SetData(data);
73                 }
74                 this.data = data;
75                 if (data.flight_series == null)
76                         System.out.printf("no data in flight\n");
77                 if (data.flight_stats == null)
78                         System.out.printf("no stats in flight\n");
79                 graph.set_data(data.flight_stats, data.flight_series);
80                 statsTable.set_stats(data.flight_stats);
81                 raw.setData(data);
82                 setTitle(data.name);
83                 return this;
84         }
85
86         void SetName(String name) {
87                 graph.setName(name);
88                 setTitle(name);
89         }
90
91         private static MicroData ReadFile(File filename) throws IOException, FileNotFoundException {
92                 MicroData       data = null;
93                 FileInputStream fis = new FileInputStream(filename);
94                 try {
95                         data = new MicroData((InputStream) fis, filename.getName());
96                         AltosUIPreferences.set_last_logdir(filename);
97                 } catch (MicroData.NonHexcharException nhe) {
98                         data = null;
99                 } catch (MicroData.FileEndedException nhe) {
100                         data = null;
101                 } catch (InterruptedException ie) {
102                         data = null;
103                 } finally {
104                         fis.close();
105                 }
106                 return data;
107         }
108
109         private void OpenFile(File filename) {
110                 try {
111                         SetData(ReadFile(filename));
112                 } catch (FileNotFoundException fne) {
113                         JOptionPane.showMessageDialog(this,
114                                                       fne.getMessage(),
115                                                       "Cannot open file",
116                                                       JOptionPane.ERROR_MESSAGE);
117                 } catch (IOException ioe) {
118                         JOptionPane.showMessageDialog(this,
119                                                       ioe.getMessage(),
120                                                       "File Read Error",
121                                                       JOptionPane.ERROR_MESSAGE);
122                 }
123         }
124
125         private void SelectFile() {
126                 MicroFileChooser        chooser = new MicroFileChooser(this);
127                 File                    file = chooser.runDialog();
128
129                 if (file != null)
130                         OpenFile(file);
131         }
132
133         private void Preferences() {
134                 new AltosUIConfigure(this);
135         }
136
137         private void DownloadData() {
138                 AltosDevice     device = MicroDeviceDialog.show(this);
139                 MicroSerial     serial = null;
140                 try {
141                         serial = new MicroSerial(device);
142                 } catch (FileNotFoundException fe) {
143                         JOptionPane.showMessageDialog(this,
144                                                       fe.getMessage(),
145                                                       "Cannot open device",
146                                                       JOptionPane.ERROR_MESSAGE);
147                         return;
148                 }
149
150                 new MicroDownload(this, device, serial);
151         }
152
153         private void no_data() {
154                         JOptionPane.showMessageDialog(this,
155                                                       "No data available",
156                                                       "No data",
157                                                       JOptionPane.INFORMATION_MESSAGE);
158         }
159
160         private void Save() {
161                 if (data == null) {
162                         no_data();
163                         return;
164                 }
165                 MicroSave       save = new MicroSave (this, data);
166                 if (save.runDialog())
167                         SetName(data.name);
168         }
169
170         private void Export() {
171                 if (data == null) {
172                         no_data();
173                         return;
174                 }
175                 MicroExport     export = new MicroExport (this, data);
176                 export.runDialog();
177         }
178
179         private static void CommandGraph(File file) {
180                 MicroPeak m = new MicroPeak();
181                 m.OpenFile(file);
182         }
183
184         private static void CommandExport(File file) {
185                 try {
186                         MicroData d = ReadFile(file);
187                         if (d != null) {
188                                 File    csv = new File(AltosLib.replace_extension(file.getPath(), ".csv"));
189                                 try {
190                                         System.out.printf ("Export \"%s\" to \"%s\"\n", file.getPath(), csv.getPath());
191                                         MicroExport.export(csv, d);
192                                 } catch (FileNotFoundException fe) {
193                                         System.err.printf("Cannot create file \"%s\" (%s)\n", csv.getName(), fe.getMessage());
194                                 } catch (IOException ie) {
195                                         System.err.printf("Cannot write file \"%s\" (%s)\n", csv.getName(), ie.getMessage());
196                                 }
197                         }
198                 } catch (IOException ie) {
199                         System.err.printf("Cannot read file \"%s\" (%s)\n", file.getName(), ie.getMessage());
200                 }
201         }
202
203         private void Close() {
204                 setVisible(false);
205                 dispose();
206                 --number_of_windows;
207                 if (number_of_windows == 0)
208                         System.exit(0);
209         }
210
211         public void actionPerformed(ActionEvent ev) {
212                 if (open_command.equals(ev.getActionCommand()))
213                         SelectFile();
214                 else if (save_command.equals(ev.getActionCommand()))
215                         Save();
216                 else if (export_command.equals(ev.getActionCommand()))
217                         Export();
218                 else if (preferences_command.equals(ev.getActionCommand()))
219                         Preferences();
220                 else if (close_command.equals(ev.getActionCommand()))
221                         Close();
222                 else if (exit_command.equals(ev.getActionCommand()))
223                         System.exit(0);
224                 else if (download_command.equals(ev.getActionCommand()))
225                         DownloadData();
226         }
227
228         public void itemStateChanged(ItemEvent e) {
229         }
230
231         /* OSXAdapter interfaces */
232         public void macosx_file_handler(String path) {
233                 CommandGraph(new File(path));
234         }
235
236         public void macosx_quit_handler() {
237                 System.exit(0);
238         }
239
240         public void macosx_preferences_handler() {
241                 Preferences();
242         }
243
244         public void filter_changed(double speed_filter, double accel_filter) {
245                 data.flight_series.set_filter(speed_filter, accel_filter);
246                 graph.filter_changed();
247                 data.flight_stats = new AltosFlightStats(data.flight_series);
248                 statsTable.filter_changed(data.flight_stats);
249         }
250
251         public double speed_filter() {
252                 if (data != null && data.flight_series != null)
253                         return data.flight_series.speed_filter_width;
254                 return 4.0;
255         }
256
257         public double accel_filter() {
258                 if (data != null && data.flight_series != null)
259                         return data.flight_series.accel_filter_width;
260                 return 1.0;
261         }
262
263         private void add_menu(JMenu menu, String label, String action) {
264                 JMenuItem       item = new JMenuItem(label);
265                 menu.add(item);
266                 item.addActionListener(this);
267                 item.setActionCommand(action);
268         }
269
270
271         private void make_menu(String label, String[][] items) {
272                 JMenu   menu = new JMenu(label);
273                 for (int i = 0; i < items.length; i++) {
274                         if (MAC_OS_X) {
275                                 if (items[i][1].equals("exit"))
276                                         continue;
277                                 if (items[i][1].equals("preferences"))
278                                         continue;
279                         }
280                         add_menu(menu, items[i][0], items[i][1]);
281                 }
282                 menu_bar.add(menu);
283         }
284
285         public MicroPeak() {
286
287                 ++number_of_windows;
288
289                 register_for_macosx_events();
290
291                 AltosUIPreferences.set_component(this);
292
293                 container = getContentPane();
294                 pane = new JTabbedPane();
295
296                 setTitle("MicroPeak");
297
298                 menu_bar = new JMenuBar();
299                 setJMenuBar(menu_bar);
300
301                 make_menu("File", file_menu_entries);
302
303                 if (MAC_OS_X) {
304                         make_menu(download_label, download_menu_entries);
305                 } else {
306                         JButton download_button = new JButton (download_label);
307                         download_button.setActionCommand(download_command);
308                         download_button.addActionListener(this);
309                         menu_bar.add(download_button);
310                 }
311
312                 setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
313                 addWindowListener(new WindowAdapter() {
314                         @Override
315                         public void windowClosing(WindowEvent e) {
316                                 statsTable.tell_closing();
317                                 raw.tell_closing();
318                                 Close();
319                         }
320                 });
321
322                 enable = new AltosUIEnable(this);
323
324                 graph = new AltosGraph(enable);
325                 statsTable = new AltosFlightStatsTable();
326                 raw = new MicroRaw();
327                 pane.add(graph.panel, "Graph");
328                 pane.add(enable, "Configure Graph");
329                 pane.add(statsTable, "Statistics");
330                 JScrollPane scroll = new JScrollPane(raw);
331                 pane.add(scroll, "Raw Data");
332                 pane.doLayout();
333                 pane.validate();
334                 container.add(pane);
335                 container.doLayout();
336                 container.validate();
337                 doLayout();
338                 validate();
339                 Insets i = getInsets();
340                 Dimension ps = pane.getPreferredSize();
341                 ps.width += i.left + i.right;
342                 ps.height += i.top + i.bottom;
343                 setSize(ps);
344                 pack();
345                 setVisible(true);
346         }
347
348         public static void help(int code) {
349                 System.out.printf("Usage: micropeak [OPTION] ... [FILE]...\n");
350                 System.out.printf("  Options:\n");
351                 System.out.printf("    --csv\tgenerate comma separated output for spreadsheets, etc\n");
352                 System.out.printf("    --graph\tgraph a flight\n");
353                 System.exit(code);
354         }
355
356         public static void main(final String[] args) {
357                 boolean opened = false;
358                 boolean graphing = true;
359
360                 try {
361                         UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel());
362                 } catch (Exception e) {
363                 }
364
365                 for (int i = 0; i < args.length; i++) {
366                         if (args[i].equals("--help"))
367                                 help(0);
368                         else if (args[i].equals("--export"))
369                                 graphing = false;
370                         else if (args[i].equals("--graph"))
371                                 graphing = true;
372                         else if (args[i].startsWith("--"))
373                                 help(1);
374                         else {
375                                 File    file = new File(args[i]);
376                                 try {
377                                         if (graphing)
378                                                 CommandGraph(file);
379                                         else
380                                                 CommandExport(file);
381                                         opened = true;
382                                 } catch (Exception e) {
383                                         System.err.printf("Error processing \"%s\": %s %s\n",
384                                                           file.getName(), e.toString(), e.getMessage());
385                                         e.printStackTrace();
386                                 }
387                         }
388                 }
389                 if (!opened)
390                         new MicroPeak();
391         }
392 }