altosui: Make sure packet mode is turned off when the connection fails
[fw/altos] / ao-tools / altosui / AltosUI.java
index 71481519910ece9d9f75e1d060c240b663e45402..94c4dd2aa4b10bb2ae6424268344f0c9ace981f6 100644 (file)
@@ -28,41 +28,9 @@ import java.text.*;
 import java.util.prefs.*;
 import java.util.concurrent.LinkedBlockingQueue;
 
-import altosui.Altos;
-import altosui.AltosSerial;
-import altosui.AltosSerialMonitor;
-import altosui.AltosRecord;
-import altosui.AltosTelemetry;
-import altosui.AltosState;
-import altosui.AltosDeviceDialog;
-import altosui.AltosPreferences;
-import altosui.AltosLog;
-import altosui.AltosVoice;
-import altosui.AltosFlightInfoTableModel;
-import altosui.AltosChannelMenu;
-import altosui.AltosFlashUI;
-import altosui.AltosLogfileChooser;
-import altosui.AltosCSVUI;
-import altosui.AltosLine;
-import altosui.AltosStatusTable;
-import altosui.AltosInfoTable;
-import altosui.AltosDisplayThread;
-
 import libaltosJNI.*;
 
 public class AltosUI extends JFrame {
-       private int channel = -1;
-
-       private AltosStatusTable flightStatus;
-       private AltosInfoTable flightInfo;
-       private AltosSerial serial_line;
-       private AltosLog altos_log;
-       private Box vbox;
-
-       private Font statusFont = new Font("SansSerif", Font.BOLD, 24);
-       private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14);
-       private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14);
-
        public AltosVoice voice = new AltosVoice();
 
        public static boolean load_library(Frame frame) {
@@ -77,39 +45,149 @@ public class AltosUI extends JFrame {
                return true;
        }
 
+       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;
+
+       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() {
 
                load_library(null);
 
-               String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" };
-               Object[][] statusData = { { "0", "pad", "-50", "0" } };
-
                java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
                if (imgURL != null)
                        setIconImage(new ImageIcon(imgURL).getImage());
 
                AltosPreferences.init(this);
 
-               vbox = Box.createVerticalBox();
-               this.add(vbox);
+               pane = getContentPane();
+               gridbag = new GridBagLayout();
+               pane.setLayout(gridbag);
 
-               flightStatus = new AltosStatusTable(this);
+               JButton b;
 
-               vbox.add(flightStatus);
+               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();
+                               }
+                       });
 
-               flightInfo = new AltosInfoTable();
-               vbox.add(flightInfo.box());
+               b = addButton(2, 1, "Flash Image");
+               b.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       FlashImage();
+                               }
+                       });
+
+               b = addButton(3, 1, "Fire Igniter");
+               b.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       FireIgniter();
+                               }
+                       });
+
+               b = addButton(4, 1, "Quit");
+               b.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       System.exit(0);
+                               }
+                       });
 
                setTitle("AltOS");
 
-               createMenu();
+               pane.doLayout();
+               pane.validate();
 
-               serial_line = new AltosSerial();
-               altos_log = new AltosLog(serial_line);
-               int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
-               this.setSize(new Dimension (flightInfo.width(),
-                                           flightStatus.height() + flightInfo.height()));
-               this.validate();
+               doLayout();
+               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
@@ -117,63 +195,14 @@ public class AltosUI extends JFrame {
                                System.exit(0);
                        }
                });
-               voice.speak("Rocket flight monitor ready.");
-       }
-
-       class DeviceThread extends AltosDisplayThread {
-               AltosSerial     serial;
-               LinkedBlockingQueue<AltosLine> telem;
-
-               AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException {
-                       AltosLine l = telem.take();
-                       if (l.line == null)
-                               throw new IOException("IO error");
-                       return new AltosTelemetry(l.line);
-               }
-
-               void close(boolean interrupted) {
-                       serial.close();
-                       serial.remove_monitor(telem);
-               }
-
-               public DeviceThread(AltosSerial s, String in_name, AltosVoice voice, AltosStatusTable status, AltosInfoTable info) {
-                       super(AltosUI.this, voice, status, info);
-                       serial = s;
-                       telem = new LinkedBlockingQueue<AltosLine>();
-                       serial.add_monitor(telem);
-                       name = in_name;
-               }
        }
 
        private void ConnectToDevice() {
                AltosDevice     device = AltosDeviceDialog.show(AltosUI.this,
                                                                AltosDevice.product_basestation);
 
-               if (device != null) {
-                       try {
-                               stop_display();
-                               serial_line.open(device);
-                               DeviceThread thread = new DeviceThread(serial_line, device.getPath(), voice, flightStatus, flightInfo);
-                               serial_line.set_channel(AltosPreferences.channel());
-                               serial_line.set_callsign(AltosPreferences.callsign());
-                               run_display(thread);
-                       } catch (FileNotFoundException ee) {
-                               JOptionPane.showMessageDialog(AltosUI.this,
-                                                             String.format("Cannot open device \"%s\"",
-                                                                           device.getPath()),
-                                                             "Cannot open target device",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       } catch (IOException ee) {
-                               JOptionPane.showMessageDialog(AltosUI.this,
-                                                             device.getPath(),
-                                                             "Unkonwn I/O error",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       }
-               }
-       }
-
-       void DisconnectFromDevice () {
-               stop_display();
+               if (device != null)
+                       telemetry_window(device);
        }
 
        void ConfigureCallsign() {
@@ -181,11 +210,8 @@ public class AltosUI extends JFrame {
                result = JOptionPane.showInputDialog(AltosUI.this,
                                                     "Configure Callsign",
                                                     AltosPreferences.callsign());
-               if (result != null) {
+               if (result != null)
                        AltosPreferences.set_callsign(result);
-                       if (serial_line != null)
-                               serial_line.set_callsign(result);
-               }
        }
 
        void ConfigureTeleMetrum() {
@@ -196,38 +222,23 @@ public class AltosUI extends JFrame {
                new AltosFlashUI(AltosUI.this);
        }
 
-
-       Thread          display_thread;
-
-       private void stop_display() {
-               if (display_thread != null && display_thread.isAlive()) {
-                       display_thread.interrupt();
-                       try {
-                               display_thread.join();
-                       } catch (InterruptedException ie) {}
-               }
-               display_thread = null;
-       }
-
-       private void run_display(Thread thread) {
-               stop_display();
-               display_thread = thread;
-               display_thread.start();
+       void FireIgniter() {
+               new AltosIgniteUI(AltosUI.this);
        }
 
        /*
         * Replay a flight from telemetry data
         */
        private void Replay() {
-               AltosLogfileChooser chooser = new AltosLogfileChooser(
+               AltosDataChooser chooser = new AltosDataChooser(
                        AltosUI.this);
+
                AltosRecordIterable iterable = chooser.runDialog();
-               if (iterable != null)
-                       run_display(new AltosReplayThread(this, iterable.iterator(),
-                                                         chooser.filename(),
-                                                         voice,
-                                                         flightStatus,
-                                                         flightInfo));
+               if (iterable != null) {
+                       AltosFlightReader reader = new AltosReplayReader(iterable.iterator(),
+                                                                        chooser.filename());
+                       new AltosFlightUI(voice, reader);
+               }
        }
 
        /* Connect to TeleMetrum, either directly or through
@@ -242,188 +253,28 @@ public class AltosUI extends JFrame {
         */
 
        private void ExportData() {
-               new AltosCSVUI(AltosUI.this);
+               AltosDataChooser chooser;
+               chooser = new AltosDataChooser(this);
+               AltosRecordIterable record_reader = chooser.runDialog();
+               if (record_reader == null)
+                       return;
+               new AltosCSVUI(AltosUI.this, record_reader, chooser.file());
        }
 
        /* Load a flight log CSV file and display a pretty graph.
         */
 
        private void GraphData() {
-               new AltosGraphUI(AltosUI.this);
+               AltosDataChooser chooser;
+               chooser = new AltosDataChooser(this);
+               AltosRecordIterable record_reader = chooser.runDialog();
+               if (record_reader == null)
+                       return;
+               new AltosGraphUI(record_reader);
        }
 
-       /* Create the AltosUI menus
-        */
-       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("Replay File",KeyEvent.VK_R);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               Replay();
-                                       }
-                               });
-                       menu.add(item);
-
-                       item = new JMenuItem("Save Flight Data",KeyEvent.VK_S);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               SaveFlightData();
-                                       }
-                               });
-                       menu.add(item);
-
-                       item = new JMenuItem("Flash Image",KeyEvent.VK_F);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               FlashImage();
-                                       }
-                               });
-                       menu.add(item);
-
-                       item = new JMenuItem("Export Data",KeyEvent.VK_F);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               ExportData();
-                                       }
-                               });
-                       menu.add(item);
-
-                       item = new JMenuItem("Graph Data",KeyEvent.VK_F);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               GraphData();
-                                       }
-                               });
-                       menu.add(item);
-
-                       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);
-
-                       item = new JMenuItem("Disconnect from Device",KeyEvent.VK_D);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               DisconnectFromDevice();
-                                       }
-                               });
-                       menu.add(item);
-
-                       menu.addSeparator();
-
-                       item = new JMenuItem("Set Callsign",KeyEvent.VK_S);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               ConfigureCallsign();
-                                       }
-                               });
-
-                       menu.add(item);
-
-                       item = new JMenuItem("Configure TeleMetrum device",KeyEvent.VK_T);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               ConfigureTeleMetrum();
-                                       }
-                               });
-
-                       menu.add(item);
-               }
-               // 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) {
-                                               AltosPreferences.ConfigureLog();
-                                       }
-                               });
-                       menu.add(item);
-               }
-               // Voice menu
-               {
-                       menu = new JMenu("Voice", true);
-                       menu.setMnemonic(KeyEvent.VK_V);
-                       menubar.add(menu);
-
-                       radioitem = new JRadioButtonMenuItem("Enable Voice", AltosPreferences.voice());
-                       radioitem.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               JRadioButtonMenuItem item = (JRadioButtonMenuItem) e.getSource();
-                                               boolean enabled = item.isSelected();
-                                               AltosPreferences.set_voice(enabled);
-                                               if (enabled)
-                                                       voice.speak_always("Enable voice.");
-                                               else
-                                                       voice.speak_always("Disable voice.");
-                                       }
-                               });
-                       menu.add(radioitem);
-                       item = new JMenuItem("Test Voice",KeyEvent.VK_T);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               voice.speak("That's one small step for man; one giant leap for mankind.");
-                                       }
-                               });
-                       menu.add(item);
-               }
-
-               // Channel menu
-               {
-                       menu = new AltosChannelMenu(AltosPreferences.channel());
-                       menu.addActionListener(new ActionListener() {
-                                               public void actionPerformed(ActionEvent e) {
-                                                       int new_channel = Integer.parseInt(e.getActionCommand());
-                                                       AltosPreferences.set_channel(new_channel);
-                                                       serial_line.set_channel(new_channel);
-                                               }
-                               });
-                       menu.setMnemonic(KeyEvent.VK_C);
-                       menubar.add(menu);
-               }
-
-               this.setJMenuBar(menubar);
-
+       private void ConfigureAltosUI() {
+               new AltosConfigureUI(AltosUI.this, voice);
        }
 
        static AltosRecordIterable open_logfile(String filename) {
@@ -502,7 +353,38 @@ public class AltosUI extends JFrame {
        public static void main(final String[] args) {
                int     process = 0;
                /* Handle batch-mode */
-               if (args.length > 0) {
+        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;
@@ -514,6 +396,10 @@ public class AltosUI extends JFrame {
                } 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]);
                }
        }
 }