altosui: Add map to MonitorIdle display
[fw/altos] / altosui / AltosIdleMonitorUI.java
index eb6ec5e7da1eb70133b9f8afbc5c1b162bc64ad0..88243c5d396150eb744758305053dae89f752c1c 100644 (file)
@@ -20,349 +20,227 @@ package altosui;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import javax.swing.filechooser.FileNameExtensionFilter;
-import javax.swing.table.*;
+import javax.swing.event.*;
 import java.io.*;
-import java.util.*;
-import java.text.*;
-import java.util.prefs.*;
 import java.util.concurrent.*;
-import org.altusmetrum.AltosLib.*;
-
-class AltosADC {
-       int     tick;
-       int     accel;
-       int     pres;
-       int     temp;
-       int     batt;
-       int     drogue;
-       int     main;
-
-       public AltosADC(AltosSerial serial) throws InterruptedException, TimeoutException {
-               serial.printf("a\n");
-               for (;;) {
-                       String line = serial.get_reply_no_dialog(5000);
-                       if (line == null) {
-                               throw new TimeoutException();
-                       }
-                       if (!line.startsWith("tick:"))
-                               continue;
-                       String[] items = line.split("\\s+");
-                       for (int i = 0; i < items.length;) {
-                               if (items[i].equals("tick:")) {
-                                       tick = Integer.parseInt(items[i+1]);
-                                       i += 2;
-                                       continue;
-                               }
-                               if (items[i].equals("accel:")) {
-                                       accel = Integer.parseInt(items[i+1]);
-                                       i += 2;
-                                       continue;
-                               }
-                               if (items[i].equals("pres:")) {
-                                       pres = Integer.parseInt(items[i+1]);
-                                       i += 2;
-                                       continue;
-                               }
-                               if (items[i].equals("temp:")) {
-                                       temp = Integer.parseInt(items[i+1]);
-                                       i += 2;
-                                       continue;
-                               }
-                               if (items[i].equals("batt:")) {
-                                       batt = Integer.parseInt(items[i+1]);
-                                       i += 2;
-                                       continue;
-                               }
-                               if (items[i].equals("drogue:")) {
-                                       drogue = Integer.parseInt(items[i+1]);
-                                       i += 2;
-                                       continue;
-                               }
-                               if (items[i].equals("main:")) {
-                                       main = Integer.parseInt(items[i+1]);
-                                       i += 2;
-                                       continue;
-                               }
+import java.util.Arrays;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
+
+public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
+       AltosDevice             device;
+       JTabbedPane             pane;
+       AltosPad                pad;
+       AltosInfoTable          flightInfo;
+       AltosFlightStatus       flightStatus;
+       AltosIgnitor            ignitor;
+       AltosIdleMonitor        thread;
+       AltosUIMap              sitemap;
+       int                     serial;
+       boolean                 remote;
+       boolean                 has_ignitor;
+       boolean                 has_map;
+
+       void stop_display() {
+               if (thread != null) {
+                       try {
+                               thread.abort();
+                       } catch (InterruptedException ie) {
                        }
-                       break;
                }
+               thread = null;
        }
-}
 
-class AltosGPSQuery extends AltosGPS {
-       public AltosGPSQuery (AltosSerial serial, AltosConfigData config_data)
-               throws TimeoutException, InterruptedException {
-               boolean says_done = config_data.compare_version("1.0") >= 0;
-               serial.printf("g\n");
-               for (;;) {
-                       String line = serial.get_reply_no_dialog(5000);
-                       if (line == null)
-                               throw new TimeoutException();
-                       String[] bits = line.split("\\s+");
-                       if (bits.length == 0)
-                               continue;
-                       if (line.startsWith("Date:")) {
-                               if (bits.length < 2)
-                                       continue;
-                               String[] d = bits[1].split(":");
-                               if (d.length < 3)
-                                       continue;
-                               year = Integer.parseInt(d[0]) + 2000;
-                               month = Integer.parseInt(d[1]);
-                               day = Integer.parseInt(d[2]);
-                               continue;
-                       }
-                       if (line.startsWith("Time:")) {
-                               if (bits.length < 2)
-                                       continue;
-                               String[] d = bits[1].split("/");
-                               if (d.length < 3)
-                                       continue;
-                               hour = Integer.parseInt(d[0]);
-                               minute = Integer.parseInt(d[1]);
-                               second = Integer.parseInt(d[2]);
-                               continue;
-                       }
-                       if (line.startsWith("Lat/Lon:")) {
-                               if (bits.length < 3)
-                                       continue;
-                               lat = Integer.parseInt(bits[1]) * 1.0e-7;
-                               lon = Integer.parseInt(bits[2]) * 1.0e-7;
-                               continue;
-                       }
-                       if (line.startsWith("Alt:")) {
-                               if (bits.length < 2)
-                                       continue;
-                               alt = Integer.parseInt(bits[1]);
-                               continue;
-                       }
-                       if (line.startsWith("Flags:")) {
-                               if (bits.length < 2)
-                                       continue;
-                               int status = Integer.decode(bits[1]);
-                               connected = (status & Altos.AO_GPS_RUNNING) != 0;
-                               locked = (status & Altos.AO_GPS_VALID) != 0;
-                               if (!says_done)
-                                       break;
-                               continue;
-                       }
-                       if (line.startsWith("Sats:")) {
-                               if (bits.length < 2)
-                                       continue;
-                               nsat = Integer.parseInt(bits[1]);
-                               cc_gps_sat = new AltosGPSSat[nsat];
-                               for (int i = 0; i < nsat; i++) {
-                                       int     svid = Integer.parseInt(bits[2+i*2]);
-                                       int     cc_n0 = Integer.parseInt(bits[3+i*2]);
-                                       cc_gps_sat[i] = new AltosGPSSat(svid, cc_n0);
-                               }
-                       }
-                       if (line.startsWith("done"))
-                               break;
-                       if (line.startsWith("Syntax error"))
-                               break;
-               }
+       void disconnect() {
+               stop_display();
        }
-}
 
-class AltosIdleMonitor extends Thread {
-       AltosDevice             device;
-       AltosSerial             serial;
-       AltosIdleMonitorUI      ui;
-       AltosState              state;
-       boolean                 remote;
-       double                  frequency;
-       AltosState              previous_state;
-       AltosConfigData         config_data;
-       AltosADC                adc;
-       AltosGPS                gps;
-
-       int AltosRSSI() throws TimeoutException, InterruptedException {
-               serial.printf("s\n");
-               String line = serial.get_reply_no_dialog(5000);
-               if (line == null)
-                       throw new TimeoutException();
-               String[] items = line.split("\\s+");
-               if (items.length < 2)
-                       return 0;
-               if (!items[0].equals("RSSI:"))
-                       return 0;
-               int rssi = Integer.parseInt(items[1]);
-               return rssi;
+       public void reset() {
+               pad.reset();
+               flightInfo.clear();
        }
 
-       void update_state() throws InterruptedException, TimeoutException {
-               AltosRecordTM   record = new AltosRecordTM();
-               int             rssi;
+       public void font_size_changed(int font_size) {
+               pad.font_size_changed(font_size);
+               flightInfo.font_size_changed(font_size);
+       }
 
-               try {
-                       if (remote) {
-                               serial.set_radio_frequency(frequency);
-                               serial.start_remote();
-                       } else
-                               serial.flush_input();
-                       config_data = new AltosConfigData(serial);
-                       adc = new AltosADC(serial);
-                       gps = new AltosGPSQuery(serial, config_data);
-               } finally {
-                       if (remote) {
-                               serial.stop_remote();
-                               rssi = AltosRSSI();
-                       } else
-                               rssi = 0;
+       public void units_changed(boolean imperial_units) {
+               pad.units_changed(imperial_units);
+               flightInfo.units_changed(imperial_units);
+       }
+
+       AltosFlightStatusUpdate status_update;
+
+       public void show(AltosState state, AltosListenerState listener_state) {
+               status_update.saved_state = state;
+               if (ignitor.should_show(state)) {
+                       if (!has_ignitor) {
+                               pane.add("Ignitor", ignitor);
+                               has_ignitor = true;
+                       }
+               } else {
+                       if (has_ignitor) {
+                               pane.remove(ignitor);
+                               has_ignitor = false;
+                       }
+               }
+               if (state.gps != null && state.gps.connected) {
+                       if (!has_map) {
+                               pane.add("Site Map", sitemap);
+                               has_map = true;
+                       }
+               } else {
+                       if (has_map) {
+                               pane.remove(sitemap);
+                               has_map = false;
+                       }
                }
 
-               record.version = 0;
-               record.callsign = config_data.callsign;
-               record.serial = config_data.serial;
-               record.flight = config_data.log_available() > 0 ? 255 : 0;
-               record.rssi = rssi;
-               record.status = 0;
-               record.state = Altos.ao_flight_idle;
-
-               record.tick = adc.tick;
-
-               record.accel = adc.accel;
-               record.pres = adc.pres;
-               record.batt = adc.batt;
-               record.temp = adc.temp;
-               record.drogue = adc.drogue;
-               record.main = adc.main;
-
-               record.ground_accel = record.accel;
-               record.ground_pres = record.pres;
-               record.accel_plus_g = config_data.accel_cal_plus;
-               record.accel_minus_g = config_data.accel_cal_minus;
-               record.acceleration = 0;
-               record.speed = 0;
-               record.height = 0;
-               record.gps = gps;
-               state = new AltosState (record, state);
+//             try {
+                       pad.show(state, listener_state);
+                       flightStatus.show(state, listener_state);
+                       flightInfo.show(state, listener_state);
+                       if (has_ignitor)
+                               ignitor.show(state, listener_state);
+                       if (has_map)
+                               sitemap.show(state, listener_state);
+//             } catch (Exception e) {
+//                     System.out.print("Show exception " + e);
+//             }
        }
 
-       void set_frequency(double in_frequency) {
-               frequency = in_frequency;
+       public void update(final AltosState state, final AltosListenerState listener_state) {
+               Runnable r = new Runnable() {
+                               public void run() {
+                                       show(state, listener_state);
+                               }
+                       };
+               SwingUtilities.invokeLater(r);
        }
 
-       public void post_state() {
+       public void failed() {
                Runnable r = new Runnable() {
                                public void run() {
-                                       ui.update(state);
+                                       close();
                                }
                        };
                SwingUtilities.invokeLater(r);
        }
 
-       public void run() {
-               try {
-                       for (;;) {
-                               try {
-                                       update_state();
-                                       post_state();
-                               } catch (TimeoutException te) {
-                                       if (AltosSerial.debug)
-                                               System.out.printf ("monitor idle data timeout\n");
-                               }
-                               Thread.sleep(1000);
-                       }
-               } catch (InterruptedException ie) {
-                       serial.close();
+       Container       bag;
+       AltosUIFreqList frequencies;
+       JTextField      callsign_value;
+
+       /* DocumentListener interface methods */
+       public void changedUpdate(DocumentEvent e) {
+               if (callsign_value != null) {
+                       String  callsign = callsign_value.getText();
+                       thread.set_callsign(callsign);
+                       AltosUIPreferences.set_callsign(callsign);
                }
        }
 
-       public AltosIdleMonitor(AltosIdleMonitorUI in_ui, AltosDevice in_device, boolean in_remote)
-               throws FileNotFoundException, AltosSerialInUseException, InterruptedException, TimeoutException {
-               device = in_device;
-               ui = in_ui;
-               serial = new AltosSerial(device);
-               remote = in_remote;
-               state = null;
+       public void insertUpdate(DocumentEvent e) {
+               changedUpdate(e);
        }
-}
 
-public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener {
-       AltosDevice             device;
-       JTabbedPane             pane;
-       AltosPad                pad;
-       AltosInfoTable          flightInfo;
-       AltosFlightStatus       flightStatus;
-       AltosIdleMonitor        thread;
-       int                     serial;
-       boolean                 remote;
-
-       void stop_display() {
-               if (thread != null && thread.isAlive()) {
-                       thread.interrupt();
-                       try {
-                               thread.join();
-                       } catch (InterruptedException ie) {}
-               }
-               thread = null;
+       public void removeUpdate(DocumentEvent e) {
+               changedUpdate(e);
        }
 
-       void disconnect() {
-               stop_display();
-       }
+       int row = 0;
 
-       public void reset() {
-               pad.reset();
-               flightInfo.clear();
+       public GridBagConstraints constraints (int x, int width, int fill) {
+               GridBagConstraints c = new GridBagConstraints();
+               Insets insets = new Insets(4, 4, 4, 4);
+
+               c.insets = insets;
+               c.fill = fill;
+               if (width == 3)
+                       c.anchor = GridBagConstraints.CENTER;
+               else if (x == 2)
+                       c.anchor = GridBagConstraints.EAST;
+               else
+                       c.anchor = GridBagConstraints.WEST;
+               c.gridx = x;
+               c.gridwidth = width;
+               c.gridy = row;
+               return c;
        }
 
-       public void set_font() {
-               pad.set_font();
-               flightInfo.set_font();
+       public GridBagConstraints constraints(int x, int width) {
+               return constraints(x, width, GridBagConstraints.NONE);
        }
 
-       public void font_size_changed(int font_size) {
-               set_font();
+       void idle_exception(JFrame owner, Exception e) {
+               if (e instanceof FileNotFoundException) {
+                       JOptionPane.showMessageDialog(owner,
+                                                     ((FileNotFoundException) e).getMessage(),
+                                                     "Cannot open target device",
+                                                     JOptionPane.ERROR_MESSAGE);
+               } else if (e instanceof AltosSerialInUseException) {
+                       JOptionPane.showMessageDialog(owner,
+                                                     String.format("Device \"%s\" already in use",
+                                                                   device.toShortString()),
+                                                     "Device in use",
+                                                     JOptionPane.ERROR_MESSAGE);
+               } else if (e instanceof IOException) {
+                       IOException ee = (IOException) e;
+                       JOptionPane.showMessageDialog(owner,
+                                                     device.toShortString(),
+                                                     ee.getLocalizedMessage(),
+                                                     JOptionPane.ERROR_MESSAGE);
+               } else {
+                       JOptionPane.showMessageDialog(owner,
+                                                     String.format("Connection to \"%s\" failed",
+                                                                   device.toShortString()),
+                                                     "Connection Failed",
+                                                     JOptionPane.ERROR_MESSAGE);
+               }
        }
 
-       AltosFlightStatusUpdate status_update;
-
-       public void show(AltosState state, int crc_errors) {
-               status_update.saved_state = state;
+       private void close() {
                try {
-                       pad.show(state, crc_errors);
-                       flightStatus.show(state, crc_errors);
-                       flightInfo.show(state, crc_errors);
-               } catch (Exception e) {
-                       System.out.print("Show exception" + e);
+                       disconnect();
+               } catch (Exception ex) {
+                       System.out.printf("Exception %s\n", ex.toString());
+                       for (StackTraceElement el : ex.getStackTrace())
+                               System.out.printf("%s\n", el.toString());
                }
+               setVisible(false);
+               dispose();
+               AltosUIPreferences.unregister_font_listener(AltosIdleMonitorUI.this);
        }
 
-       public void update(AltosState state) {
-               show (state, 0);
-       }
-
-       Container       bag;
-       AltosFreqList   frequencies;
-
        public AltosIdleMonitorUI(JFrame in_owner)
-               throws FileNotFoundException, AltosSerialInUseException, TimeoutException, InterruptedException {
+               throws FileNotFoundException, TimeoutException, InterruptedException {
 
-               device = AltosDeviceDialog.show(in_owner, Altos.product_any);
+               device = AltosDeviceUIDialog.show(in_owner, Altos.product_any);
                remote = false;
                if (!device.matchProduct(Altos.product_altimeter))
                        remote = true;
 
                serial = device.getSerial();
-               bag = getContentPane();
-               bag.setLayout(new GridBagLayout());
 
-               GridBagConstraints c = new GridBagConstraints();
+               AltosSerial link;
+               try {
+                       link = new AltosSerial(device);
+                       link.set_frame(this);
+               } catch (Exception ex) {
+                       idle_exception(in_owner, ex);
+                       return;
+               }
 
-               java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
-               if (imgURL != null)
-                       setIconImage(new ImageIcon(imgURL).getImage());
+               bag = getContentPane();
+               bag.setLayout(new GridBagLayout());
 
                setTitle(String.format("AltOS %s", device.toShortString()));
 
                /* Stick frequency selector at top of table for telemetry monitoring */
                if (remote && serial >= 0) {
                        // Frequency menu
-                       frequencies = new AltosFreqList(AltosUIPreferences.frequency(serial));
+                       frequencies = new AltosUIFreqList(AltosUIPreferences.frequency(serial));
                        frequencies.addActionListener(new ActionListener() {
                                        public void actionPerformed(ActionEvent e) {
                                                double frequency = frequencies.frequency();
@@ -371,23 +249,21 @@ public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay
                                                                               frequency);
                                        }
                        });
-                       c.gridx = 0;
-                       c.gridy = 0;
-                       c.insets = new Insets(3, 3, 3, 3);
-                       c.anchor = GridBagConstraints.WEST;
-                       bag.add (frequencies, c);
+                       bag.add (frequencies, constraints(0, 1));
+                       bag.add (new JLabel("Callsign:"), constraints(1, 1));
+                       /* Add callsign configuration */
+                       callsign_value = new JTextField(AltosUIPreferences.callsign());
+                       callsign_value.getDocument().addDocumentListener(this);
+                       callsign_value.setToolTipText("Callsign sent in packet mode");
+                       bag.add(callsign_value, constraints(2, 1, GridBagConstraints.BOTH));
+                       row++;
                }
 
 
                /* Flight status is always visible */
                flightStatus = new AltosFlightStatus();
-               c.gridx = 0;
-               c.gridy = 1;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.gridwidth = 2;
-               bag.add(flightStatus, c);
-               c.gridwidth = 1;
+               bag.add(flightStatus, constraints(0, 3, GridBagConstraints.HORIZONTAL));
+               row++;
 
                /* The rest of the window uses a tabbed pane to
                 * show one of the alternate data views
@@ -400,14 +276,12 @@ public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay
                flightInfo = new AltosInfoTable();
                pane.add("Table", new JScrollPane(flightInfo));
 
+               ignitor = new AltosIgnitor();
+
+               sitemap = new AltosUIMap();
+
                /* Make the tabbed pane use the rest of the window space */
-               c.gridx = 0;
-               c.gridy = 2;
-               c.fill = GridBagConstraints.BOTH;
-               c.weightx = 1;
-               c.weighty = 1;
-               c.gridwidth = 2;
-               bag.add(pane, c);
+               bag.add(pane, constraints(0, 3, GridBagConstraints.BOTH));
 
                setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
 
@@ -416,17 +290,14 @@ public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay
                addWindowListener(new WindowAdapter() {
                                @Override
                                public void windowClosing(WindowEvent e) {
-                                       disconnect();
-                                       setVisible(false);
-                                       dispose();
-                                       AltosUIPreferences.unregister_font_listener(AltosIdleMonitorUI.this);
+                                       close();
                                }
                        });
 
                pack();
                setVisible(true);
 
-               thread = new AltosIdleMonitor(this, device, remote);
+               thread = new AltosIdleMonitor((AltosIdleMonitorListener) this, link, (boolean) remote);
 
                status_update = new AltosFlightStatusUpdate(flightStatus);