diff options
Diffstat (limited to 'telegps/TeleGPS.java')
| -rw-r--r-- | telegps/TeleGPS.java | 543 |
1 files changed, 543 insertions, 0 deletions
diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java new file mode 100644 index 00000000..45482dec --- /dev/null +++ b/telegps/TeleGPS.java @@ -0,0 +1,543 @@ +/* + * Copyright © 2014 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.telegps; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.util.concurrent.*; +import java.util.*; +import org.altusmetrum.altoslib_4.*; +import org.altusmetrum.altosuilib_2.*; + +public class TeleGPS extends AltosUIFrame implements AltosFlightDisplay, AltosFontListener, ActionListener { + + static String[] telegps_icon_names = { + "/telegps-16.png", + "/telegps-32.png", + "/telegps-48.png", + "/telegps-64.png", + "/telegps-128.png", + "/telegps-256.png" + }; + + static { set_icon_names(telegps_icon_names); } + + static AltosVoice voice; + + static AltosVoice voice() { + if (voice == null) + voice = new AltosVoice(); + return voice; + } + + AltosFlightReader reader; + AltosDisplayThread thread; + + JTabbedPane pane; + + AltosSiteMap sitemap; + boolean has_map; + + JMenuBar menu_bar; + JMenu file_menu; + JMenu monitor_menu; + JMenu device_menu; + + /* File menu */ + final static String new_command = "new"; + final static String preferences_command = "preferences"; + final static String load_maps_command = "loadmaps"; + final static String close_command = "close"; + final static String exit_command = "exit"; + + static final String[][] file_menu_entries = new String[][] { + { "New Window", new_command }, + { "Preferences", preferences_command }, + { "Load Maps", load_maps_command }, + { "Close", close_command }, + { "Exit", exit_command }, + }; + + /* Monitor menu */ + final static String monitor_command = "monitor"; + final static String disconnect_command = "disconnect"; + final static String scan_command = "scan"; + + static final String[][] monitor_menu_entries = new String[][] { + { "Monitor Device", monitor_command }, + { "Disconnect", disconnect_command }, + { "Scan Channels", scan_command }, + }; + + /* Device menu */ + final static String download_command = "download"; + final static String configure_command = "configure"; + final static String export_command = "export"; + final static String graph_command = "graph"; + + static final String[][] device_menu_entries = new String[][] { + { "Download Data", download_command }, + { "Configure Device", configure_command }, + { "Export Data", export_command }, + { "Graph Data", graph_command }, + }; + +// private AltosInfoTable flightInfo; + + boolean exit_on_close = false; + + void stop_display() { + if (thread != null && thread.isAlive()) { + thread.interrupt(); + try { + thread.join(); + } catch (InterruptedException ie) {} + } + thread = null; + } + + public void reset() { + sitemap.reset(); + } + + public void set_font() { + sitemap.set_font(); + } + + public void font_size_changed(int font_size) { + set_font(); + } + + +// AltosFlightStatusUpdate status_update; + + public void show(AltosState state, AltosListenerState listener_state) { +// status_update.saved_state = state; + + if (state == null) + state = new AltosState(); + + sitemap.show(state, listener_state); + telegps_status.show(state, listener_state); + } + + Container bag; + AltosFreqList frequencies; + JLabel telemetry; + TeleGPSStatus telegps_status; + TeleGPSStatusUpdate status_update; + + ActionListener show_timer; + + void new_window() { + new TeleGPS(); + } + + void preferences() { + } + + void load_maps() { + new AltosSiteMapPreload(this); + } + + void monitor() { + AltosDevice device = AltosDeviceUIDialog.show(this, + AltosLib.product_basestation); + if (device == null) + return; + if (reader != null) + disconnect(); + try { + AltosFlightReader reader = new AltosTelemetryReader(new AltosSerial(device)); + set_reader(reader); + add_frequency_menu(device.getSerial(), reader); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(this, + ee.getMessage(), + String.format ("Cannot open %s", device.toShortString()), + JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(this, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(this, + String.format ("Unknown I/O error on %s", device.toShortString()), + "Unknown I/O error", + JOptionPane.ERROR_MESSAGE); + } catch (TimeoutException te) { + JOptionPane.showMessageDialog(this, + String.format ("Timeout on %s", device.toShortString()), + "Timeout error", + JOptionPane.ERROR_MESSAGE); + } catch (InterruptedException ie) { + JOptionPane.showMessageDialog(this, + String.format("Interrupted %s", device.toShortString()), + "Interrupted exception", + JOptionPane.ERROR_MESSAGE); + } + } + + void disconnect() { + setTitle("TeleGPS"); + stop_display(); + remove_frequency_menu(); + } + + void scan() { + } + + void download(){ + } + + void configure() { + } + + void export() { + } + + void graph() { + } + + public void actionPerformed(ActionEvent ev) { + + /* File menu */ + if (new_command.equals(ev.getActionCommand())) { + new_window(); + return; + } + if (preferences_command.equals(ev.getActionCommand())) { + preferences(); + return; + } + if (load_maps_command.equals(ev.getActionCommand())) { + load_maps(); + return; + } + if (close_command.equals(ev.getActionCommand())) { + close(); + return; + } + if (exit_command.equals(ev.getActionCommand())) + System.exit(0); + + /* Monitor menu */ + if (monitor_command.equals(ev.getActionCommand())) { + monitor(); + return; + } + if (disconnect_command.equals(ev.getActionCommand())) { + disconnect(); + return; + } + if (scan_command.equals(ev.getActionCommand())) { + scan(); + return; + } + + /* Device menu */ + if (download_command.equals(ev.getActionCommand())) { + download(); + return; + } + if (configure_command.equals(ev.getActionCommand())) { + configure(); + return; + } + if (export_command.equals(ev.getActionCommand())) { + export(); + return; + } + if (graph_command.equals(ev.getActionCommand())) { + graph(); + return; + } + } + + void add_frequency_menu(int serial, final AltosFlightReader reader) { + // Channel menu + frequencies = new AltosFreqList(AltosUIPreferences.frequency(serial)); + frequencies.set_product("Monitor"); + frequencies.set_serial(serial); + frequencies.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + double frequency = frequencies.frequency(); + try { + reader.set_frequency(frequency); + } catch (TimeoutException te) { + } catch (InterruptedException ie) { + } + reader.save_frequency(); + } + }); + menu_bar.add(frequencies); + } + + void remove_frequency_menu() { + if (frequencies != null) { + menu_bar.remove(frequencies); + frequencies = null; + } + } + + public void set_reader(AltosFlightReader reader) { + setTitle(String.format("TeleGPS %s", reader.name)); + thread = new AltosDisplayThread(this, voice(), this, reader); + thread.start(); + } + + static int number_of_windows; + + private void close() { + AltosUIPreferences.unregister_font_listener(this); + setVisible(false); + dispose(); + --number_of_windows; + if (number_of_windows == 0) + System.exit(0); + } + + private void add_menu(JMenu menu, String label, String action) { + JMenuItem item = new JMenuItem(label); + menu.add(item); + item.addActionListener(this); + item.setActionCommand(action); + } + + + private JMenu make_menu(String label, String[][] items) { + JMenu menu = new JMenu(label); + for (int i = 0; i < items.length; i++) + add_menu(menu, items[i][0], items[i][1]); + menu_bar.add(menu); + return menu; + } + + public TeleGPS() { + + AltosUIPreferences.set_component(this); + + reader = null; + + bag = getContentPane(); + bag.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + + setTitle("TeleGPS"); + + menu_bar = new JMenuBar(); + setJMenuBar(menu_bar); + + file_menu = make_menu("File", file_menu_entries); + monitor_menu = make_menu("Monitor", monitor_menu_entries); + device_menu = make_menu("Device", device_menu_entries); + + int serial = -1; + + /* TeleGPS status is always visible */ + telegps_status = new TeleGPSStatus(); + c.gridx = 0; + c.gridy = 1; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.gridwidth = 2; + bag.add(telegps_status, c); + c.gridwidth = 1; + + + /* The rest of the window uses a tabbed pane to + * show one of the alternate data views + */ + pane = new JTabbedPane(); + + /* 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); + + sitemap = new AltosSiteMap(); + pane.add("Site Map", sitemap); + + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + + AltosUIPreferences.register_font_listener(this); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + close(); + } + }); + + pack(); + setVisible(true); + + ++number_of_windows; + + status_update = new TeleGPSStatusUpdate(telegps_status); + + new javax.swing.Timer(100, status_update).start(); + } + + public TeleGPS(AltosFlightReader reader) { + this(); + set_reader(reader); + } + + static AltosStateIterable record_iterable(File file) { + FileInputStream in; + try { + in = new FileInputStream(file); + } catch (Exception e) { + System.out.printf("Failed to open file '%s'\n", file); + return null; + } + if (file.getName().endsWith("telem")) + return new AltosTelemetryFile(in); + else + return new AltosEepromFile(in); + } + + static AltosReplayReader replay_file(File file) { + AltosStateIterable states = record_iterable(file); + if (states == null) + return null; + return new AltosReplayReader(states.iterator(), file); + } + + static boolean process_replay(File file) { + AltosReplayReader new_reader = replay_file(file); + if (new_reader == null) + return false; + + new TeleGPS(new_reader); + return true; + } + + static final int process_none = 0; + static final int process_csv = 1; + static final int process_kml = 2; + static final int process_graph = 3; + static final int process_replay = 4; + static final int process_summary = 5; + static final int process_cat = 6; + + public static boolean load_library(Frame frame) { + if (!AltosUILib.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 static void help(int code) { + 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(" --graph <filename>\t\tgraph a flight\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"); + System.exit(code); + } + + public static void main(String[] args) { + int errors = 0; + + load_library(null); + try { + UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel()); + } catch (Exception e) { + } + + boolean any_created = false; + + + /* Handle batch-mode */ + int process = process_none; + for (int i = 0; i < args.length; i++) { + if (args[i].equals("--help")) + help(0); + else if (args[i].equals("--fetchmaps")) { + if (args.length < i + 3) { + help(1); + } else { + double lat = Double.parseDouble(args[i+1]); + double lon = Double.parseDouble(args[i+2]); + AltosSiteMap.prefetchMaps(lat, lon); + i += 2; + } + } else if (args[i].equals("--replay")) + process = process_replay; + else if (args[i].equals("--kml")) + process = process_kml; + else if (args[i].equals("--csv")) + process = process_csv; + else if (args[i].equals("--graph")) + process = process_graph; + else if (args[i].equals("--summary")) + process = process_summary; + else if (args[i].equals("--cat")) + process = process_cat; + else if (args[i].startsWith("--")) + help(1); + else { + File file = new File(args[i]); + switch (process) { + case process_graph: + ++errors; + break; + case process_none: + case process_replay: + if (!process_replay(file)) + ++errors; + any_created = true; + break; + case process_kml: + ++errors; + break; + case process_csv: + ++errors; + break; + case process_summary: + ++errors; + break; + case process_cat: + ++errors; + } + } + } + if (errors != 0) + System.exit(errors); + if (!any_created) + new TeleGPS(); + } +} |
