altosui: Make sure packet mode is turned off when the connection fails
[fw/altos] / ao-tools / altosui / AltosUI.java
index 89eaac156b17d34f5c3b39d02191316536b7357e..94c4dd2aa4b10bb2ae6424268344f0c9ace981f6 100644 (file)
@@ -20,47 +20,174 @@ package altosui;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
 import java.io.*;
 import java.util.*;
 import java.text.*;
-import gnu.io.CommPortIdentifier;
+import java.util.prefs.*;
+import java.util.concurrent.LinkedBlockingQueue;
 
-import altosui.AltosSerial;
-import altosui.AltosSerialMonitor;
+import libaltosJNI.*;
 
-class AltosUIMonitor implements AltosSerialMonitor {
-       public void data(String data) {
-               System.out.println(data);
+public class AltosUI extends JFrame {
+       public AltosVoice voice = new AltosVoice();
+
+       public static boolean load_library(Frame frame) {
+               if (!AltosDevice.load_library()) {
+                       JOptionPane.showMessageDialog(frame,
+                                                     String.format("No AltOS library in \"%s\"",
+                                                                   System.getProperty("java.library.path","<undefined>")),
+                                                     "Cannot load device access library",
+                                                     JOptionPane.ERROR_MESSAGE);
+                       return false;
+               }
+               return true;
        }
-}
 
-public class AltosUI extends JFrame {
-       private int channel = -1;
+       void telemetry_window(AltosDevice device) {
+               try {
+                       AltosFlightReader reader = new AltosTelemetryReader(device);
+                       if (reader != null)
+                               new AltosFlightUI(voice, reader, device.getSerial());
+               } catch (FileNotFoundException ee) {
+                       JOptionPane.showMessageDialog(AltosUI.this,
+                                                     String.format("Cannot open device \"%s\"",
+                                                                   device.toShortString()),
+                                                     "Cannot open target device",
+                                                     JOptionPane.ERROR_MESSAGE);
+               } catch (AltosSerialInUseException si) {
+                       JOptionPane.showMessageDialog(AltosUI.this,
+                                                     String.format("Device \"%s\" already in use",
+                                                                   device.toShortString()),
+                                                     "Device in use",
+                                                     JOptionPane.ERROR_MESSAGE);
+               } catch (IOException ee) {
+                       JOptionPane.showMessageDialog(AltosUI.this,
+                                                     device.toShortString(),
+                                                     "Unkonwn I/O error",
+                                                     JOptionPane.ERROR_MESSAGE);
+               }
+       }
+
+       Container       pane;
+       GridBagLayout   gridbag;
 
-       private JTable flightStatus;
-       private JTable flightInfo;
-       private AltosSerial serialLine;
+       JButton addButton(int x, int y, String label) {
+               GridBagConstraints      c;
+               JButton                 b;
+
+               c = new GridBagConstraints();
+               c.gridx = x; c.gridy = y;
+               c.fill = GridBagConstraints.BOTH;
+               c.weightx = 1;
+               c.weighty = 1;
+               b = new JButton(label);
+
+               Dimension ps = b.getPreferredSize();
+
+               gridbag.setConstraints(b, c);
+               add(b, c);
+               return b;
+       }
 
        public AltosUI() {
 
-               String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" };
-               Object[][] statusData = { { "0", "pad", "-50", "0" } };
+               load_library(null);
+
+               java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
+               if (imgURL != null)
+                       setIconImage(new ImageIcon(imgURL).getImage());
+
+               AltosPreferences.init(this);
+
+               pane = getContentPane();
+               gridbag = new GridBagLayout();
+               pane.setLayout(gridbag);
+
+               JButton b;
+
+               b = addButton(0, 0, "Monitor Flight");
+               b.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               ConnectToDevice();
+                                       }
+                               });
+               b = addButton(1, 0, "Save Flight Data");
+               b.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               SaveFlightData();
+                                       }
+                               });
+               b = addButton(2, 0, "Replay Flight");
+               b.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               Replay();
+                                       }
+                               });
+               b = addButton(3, 0, "Graph Data");
+               b.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               GraphData();
+                                       }
+                               });
+               b = addButton(4, 0, "Export Data");
+               b.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               ExportData();
+                                       }
+                               });
+               b = addButton(0, 1, "Configure TeleMetrum");
+               b.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               ConfigureTeleMetrum();
+                                       }
+                               });
+
+               b = addButton(1, 1, "Configure AltosUI");
+               b.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       ConfigureAltosUI();
+                               }
+                       });
 
-               flightStatus = new JTable(statusData, statusNames);
+               b = addButton(2, 1, "Flash Image");
+               b.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       FlashImage();
+                               }
+                       });
 
-               flightStatus.setShowGrid(false);
+               b = addButton(3, 1, "Fire Igniter");
+               b.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       FireIgniter();
+                               }
+                       });
 
-               this.add(flightStatus);
+               b = addButton(4, 1, "Quit");
+               b.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       System.exit(0);
+                               }
+                       });
 
                setTitle("AltOS");
 
-               createMenu();
+               pane.doLayout();
+               pane.validate();
+
+               doLayout();
+               validate();
 
-               serialLine = new AltosSerial();
-               serialLine.monitor(new AltosUIMonitor());
-               int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
-               this.setSize(new Dimension (dpi * 5, dpi * 4));
-               this.validate();
+               setVisible(true);
+
+               Insets i = getInsets();
+               Dimension ps = rootPane.getPreferredSize();
+               ps.width += i.left + i.right;
+               ps.height += i.top + i.bottom;
+               setPreferredSize(ps);
+               setSize(ps);
                setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                addWindowListener(new WindowAdapter() {
                        @Override
@@ -70,219 +197,209 @@ public class AltosUI extends JFrame {
                });
        }
 
-       final JFileChooser deviceChooser = new JFileChooser();
+       private void ConnectToDevice() {
+               AltosDevice     device = AltosDeviceDialog.show(AltosUI.this,
+                                                               AltosDevice.product_basestation);
 
-       private void PickSerialDevice() {
-               java.util.Enumeration<CommPortIdentifier> port_list = CommPortIdentifier.getPortIdentifiers();
-               while (port_list.hasMoreElements()) {
-                       CommPortIdentifier identifier = port_list.nextElement();
-                       System.out.println("Serial port " + identifier.getName());
-               }
+               if (device != null)
+                       telemetry_window(device);
        }
 
-       private void ConnectToDevice() {
-               PickSerialDevice();
-               int returnVal = deviceChooser.showOpenDialog(AltosUI.this);
+       void ConfigureCallsign() {
+               String  result;
+               result = JOptionPane.showInputDialog(AltosUI.this,
+                                                    "Configure Callsign",
+                                                    AltosPreferences.callsign());
+               if (result != null)
+                       AltosPreferences.set_callsign(result);
+       }
 
-               if (returnVal == JFileChooser.APPROVE_OPTION) {
-                       File file = deviceChooser.getSelectedFile();
-                       try {
-                               serialLine.open(file);
-                       } catch (FileNotFoundException ee) {
-                               JOptionPane.showMessageDialog(AltosUI.this,
-                                                             file.getName(),
-                                                             "Cannot open serial port",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       }
-               }
+       void ConfigureTeleMetrum() {
+               new AltosConfig(AltosUI.this);
        }
 
-       String readline(FileInputStream s) throws IOException {
-               int c;
-               String  line = "";
+       void FlashImage() {
+               new AltosFlashUI(AltosUI.this);
+       }
 
-               while ((c = s.read()) != -1) {
-                       if (c == '\r')
-                               continue;
-                       if (c == '\n')
-                               return line;
-                       line = line + (char) c;
-               }
-               return null;
+       void FireIgniter() {
+               new AltosIgniteUI(AltosUI.this);
        }
 
+       /*
+        * Replay a flight from telemetry data
+        */
        private void Replay() {
-//             int returnVal = deviceChooser.showOpenDialog(AltosUI.this);
-
-               /*              if (returnVal == JFileChooser.APPROVE_OPTION) */ {
-//                     File file = deviceChooser.getSelectedFile();
-//                     String  filename = file.getName();
-                       String  filename = "/home/keithp/src/cc1111/flights/2010-02-13-serial-051-flight-002.telem";
-                       try {
-//                             FileInputStream replay = new FileInputStream(file);
-                               FileInputStream replay = new FileInputStream(filename);
-                               String  line;
-
-                               try {
-                                       while ((line = readline(replay)) != null) {
-                                               try {
-                                                       AltosTelemetry  t = new AltosTelemetry(line);
-                                                       System.out.println ("Version " + t.version + t.callsign);
-                                               } catch (ParseException pp) {
-                                                       JOptionPane.showMessageDialog(AltosUI.this,
-                                                                                     line,
-                                                                                     "error parsing",
-                                                                                     JOptionPane.ERROR_MESSAGE);
-                                                       break;
-                                               }
-                                       }
-                               } catch (IOException ee) {
-                                       JOptionPane.showMessageDialog(AltosUI.this,
-                                                                     filename,
-                                                                     "error reading",
-                                                                     JOptionPane.ERROR_MESSAGE);
-                               } finally {
-                                       try {
-                                               replay.close();
-                                       } catch (IOException e) {}
-                               }
-                       } catch (FileNotFoundException ee) {
-                               JOptionPane.showMessageDialog(AltosUI.this,
-                                                             filename,
-                                                             "Cannot open serial port",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       }
+               AltosDataChooser chooser = new AltosDataChooser(
+                       AltosUI.this);
+
+               AltosRecordIterable iterable = chooser.runDialog();
+               if (iterable != null) {
+                       AltosFlightReader reader = new AltosReplayReader(iterable.iterator(),
+                                                                        chooser.filename());
+                       new AltosFlightUI(voice, reader);
                }
        }
 
+       /* Connect to TeleMetrum, either directly or through
+        * a TeleDongle over the packet link
+        */
        private void SaveFlightData() {
+               new AltosEepromDownload(AltosUI.this);
        }
 
-       private void createMenu() {
-               JMenuBar menubar = new JMenuBar();
-               JMenu menu;
-               JMenuItem item;
-               JRadioButtonMenuItem radioitem;
-
-               // File menu
-               {
-                       menu = new JMenu("File");
-                       menu.setMnemonic(KeyEvent.VK_F);
-                       menubar.add(menu);
-
-                       item = new JMenuItem("Quit",KeyEvent.VK_Q);
-                       item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
-                                                                  ActionEvent.CTRL_MASK));
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               System.exit(0);
-                                       }
-                               });
-                       menu.add(item);
-               }
-
-               // Device menu
-               {
-                       menu = new JMenu("Device");
-                       menu.setMnemonic(KeyEvent.VK_D);
-                       menubar.add(menu);
-
-                       item = new JMenuItem("Connect to Device",KeyEvent.VK_C);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               ConnectToDevice();
-                                       }
-                               });
-                       menu.add(item);
+       /* Load a flight log file and write out a CSV file containing
+        * all of the data in standard units
+        */
+
+       private void ExportData() {
+               AltosDataChooser chooser;
+               chooser = new AltosDataChooser(this);
+               AltosRecordIterable record_reader = chooser.runDialog();
+               if (record_reader == null)
+                       return;
+               new AltosCSVUI(AltosUI.this, record_reader, chooser.file());
+       }
 
-                       item = new JMenuItem("Disconnect from Device",KeyEvent.VK_D);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               serialLine.close();
-                                       }
-                               });
-                       menu.add(item);
+       /* Load a flight log CSV file and display a pretty graph.
+        */
 
-                       menu.addSeparator();
+       private void GraphData() {
+               AltosDataChooser chooser;
+               chooser = new AltosDataChooser(this);
+               AltosRecordIterable record_reader = chooser.runDialog();
+               if (record_reader == null)
+                       return;
+               new AltosGraphUI(record_reader);
+       }
 
-                       item = new JMenuItem("Save Flight Data",KeyEvent.VK_S);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               SaveFlightData();
-                                       }
-                               });
-                       menu.add(item);
+       private void ConfigureAltosUI() {
+               new AltosConfigureUI(AltosUI.this, voice);
+       }
 
-                       item = new JMenuItem("Replay",KeyEvent.VK_R);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               Replay();
-                                       }
-                               });
-                       menu.add(item);
+       static AltosRecordIterable open_logfile(String filename) {
+               File file = new File (filename);
+               try {
+                       FileInputStream in;
+
+                       in = new FileInputStream(file);
+                       if (filename.endsWith("eeprom"))
+                               return new AltosEepromIterable(in);
+                       else
+                               return new AltosTelemetryIterable(in);
+               } catch (FileNotFoundException fe) {
+                       System.out.printf("Cannot open '%s'\n", filename);
+                       return null;
                }
-               // Log menu
-               {
-                       menu = new JMenu("Log");
-                       menu.setMnemonic(KeyEvent.VK_L);
-                       menubar.add(menu);
-
-                       item = new JMenuItem("New Log",KeyEvent.VK_N);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                       }
-                               });
-                       menu.add(item);
+       }
 
-                       item = new JMenuItem("Configure Log",KeyEvent.VK_C);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                       }
-                               });
-                       menu.add(item);
+       static AltosWriter open_csv(String filename) {
+               File file = new File (filename);
+               try {
+                       return new AltosCSV(file);
+               } catch (FileNotFoundException fe) {
+                       System.out.printf("Cannot open '%s'\n", filename);
+                       return null;
                }
-               // Voice menu
-               {
-                       menu = new JMenu("Voice", true);
-                       menu.setMnemonic(KeyEvent.VK_V);
-                       menubar.add(menu);
-
-                       radioitem = new JRadioButtonMenuItem("Enable Voice");
-                       radioitem.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                       }
-                               });
-                       menu.add(radioitem);
+       }
+
+       static AltosWriter open_kml(String filename) {
+               File file = new File (filename);
+               try {
+                       return new AltosKML(file);
+               } catch (FileNotFoundException fe) {
+                       System.out.printf("Cannot open '%s'\n", filename);
+                       return null;
                }
+       }
 
-               // Channel menu
-               {
-                       menu = new JMenu("Channel", true);
-                       menu.setMnemonic(KeyEvent.VK_C);
-                       menubar.add(menu);
-                       ButtonGroup group = new ButtonGroup();
-
-                       for (int c = 0; c <= 9; c++) {
-                               radioitem = new JRadioButtonMenuItem(String.format("Channel %1d (%7.3fMHz)", c,
-                                                                                  434.550 + c * 0.1),
-                                                                    c == 0);
-                               radioitem.setActionCommand(String.format("%d", c));
-                               radioitem.addActionListener(new ActionListener() {
-                                               public void actionPerformed(ActionEvent e) {
-                                                       System.out.println("Command: " + e.getActionCommand() + " param: " +
-                                                                          e.paramString());
-                                               }
-                                       });
-                               menu.add(radioitem);
-                               group.add(radioitem);
+       static final int process_csv = 1;
+       static final int process_kml = 2;
+
+       static void process_file(String input, int process) {
+               AltosRecordIterable iterable = open_logfile(input);
+               if (iterable == null)
+                       return;
+               if (process == 0)
+                       process = process_csv;
+               if ((process & process_csv) != 0) {
+                       String output = Altos.replace_extension(input,".csv");
+                       System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
+                       if (input.equals(output)) {
+                               System.out.printf("Not processing '%s'\n", input);
+                       } else {
+                               AltosWriter writer = open_csv(output);
+                               if (writer != null) {
+                                       writer.write(iterable);
+                                       writer.close();
+                               }
+                       }
+               }
+               if ((process & process_kml) != 0) {
+                       String output = Altos.replace_extension(input,".kml");
+                       System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
+                       if (input.equals(output)) {
+                               System.out.printf("Not processing '%s'\n", input);
+                       } else {
+                               AltosWriter writer = open_kml(output);
+                               if (writer == null)
+                                       return;
+                               writer.write(iterable);
+                               writer.close();
                        }
                }
-
-               this.setJMenuBar(menubar);
-
        }
+
        public static void main(final String[] args) {
-               AltosUI altosui = new AltosUI();
-               altosui.setVisible(true);
+               int     process = 0;
+               /* Handle batch-mode */
+        if (args.length == 1 && args[0].equals("--help")) {
+               System.out.printf("Usage: altosui [OPTION]... [FILE]...\n");
+               System.out.printf("  Options:\n");
+               System.out.printf("    --fetchmaps <lat> <lon>\tpre-fetch maps for site map view\n");
+               System.out.printf("    --replay <filename>\t\trelive the glory of past flights \n");
+               System.out.printf("    --csv\tgenerate comma separated output for spreadsheets, etc\n");
+               System.out.printf("    --kml\tgenerate KML output for use with Google Earth\n");
+        } else if (args.length == 3 && args[0].equals("--fetchmaps")) {
+            double lat = Double.parseDouble(args[1]);
+            double lon = Double.parseDouble(args[2]);
+            AltosSiteMap.prefetchMaps(lat, lon, 5, 5);
+        } else if (args.length == 2 && args[0].equals("--replay")) {
+                       String filename = args[1];
+                       FileInputStream in;
+                       try {
+                               in = new FileInputStream(filename);
+                       } catch (Exception e) {
+                               System.out.printf("Failed to open file '%s'\n", filename);
+                               return;
+                       }
+                       AltosRecordIterable recs;
+                       AltosReplayReader reader;
+                       if (filename.endsWith("eeprom")) {
+                               recs = new AltosEepromIterable(in);
+                       } else {
+                               recs = new AltosTelemetryIterable(in);
+                       }
+                       reader = new AltosReplayReader(recs.iterator(), filename);
+                       AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader);
+                       flight_ui.set_exit_on_close();
+                       return;
+               } else if (args.length > 0) {
+                       for (int i = 0; i < args.length; i++) {
+                               if (args[i].equals("--kml"))
+                                       process |= process_kml;
+                               else if (args[i].equals("--csv"))
+                                       process |= process_csv;
+                               else
+                                       process_file(args[i], process);
+                       }
+               } else {
+                       AltosUI altosui = new AltosUI();
+                       altosui.setVisible(true);
+
+                       AltosDevice[] devices = AltosDevice.list(AltosDevice.product_basestation);
+                       for (int i = 0; i < devices.length; i++)
+                               altosui.telemetry_window(devices[i]);
+               }
        }
-}
\ No newline at end of file
+}