X-Git-Url: https://git.gag.com/?a=blobdiff_plain;ds=sidebyside;f=telegps%2FTeleGPS.java;fp=telegps%2FTeleGPS.java;h=6e68dd30e5087451d69702a656bddeb2e25bc955;hb=3cf030fffffd223c3717011e03aac82346295d71;hp=0000000000000000000000000000000000000000;hpb=607fbb01710be1cb263625337f5be3d0fb48d5e7;p=fw%2Faltos diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java new file mode 100644 index 00000000..6e68dd30 --- /dev/null +++ b/telegps/TeleGPS.java @@ -0,0 +1,668 @@ +/* + * Copyright © 2014 Keith Packard + * + * 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, AltosUnitsListener, 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; + TeleGPSDisplayThread thread; + + JMenuBar menu_bar; + + JMenu file_menu; + JMenu monitor_menu; + JMenu device_menu; + AltosFreqList frequencies; + ActionListener frequency_listener; + + Container bag; + + TeleGPSStatus telegps_status; + TeleGPSStatusUpdate status_update; + javax.swing.Timer status_timer; + + JTabbedPane pane; + + AltosUIMap map; + TeleGPSInfo gps_info; + TeleGPSState gps_state; + AltosInfoTable info_table; + + LinkedList displays; + + /* File menu */ + final static String new_command = "new"; + final static String graph_command = "graph"; + final static String export_command = "export"; + final static String load_maps_command = "loadmaps"; + final static String preferences_command = "preferences"; + final static String close_command = "close"; + final static String exit_command = "exit"; + + static final String[][] file_menu_entries = new String[][] { + { "New Window", new_command }, + { "Graph Data", graph_command }, + { "Export Data", export_command }, + { "Load Maps", load_maps_command }, + { "Preferences", preferences_command }, + { "Close", close_command }, + { "Exit", exit_command }, + }; + + /* Monitor menu */ + final static String connect_command = "connect"; + final static String disconnect_command = "disconnect"; + final static String scan_command = "scan"; + + static final String[][] monitor_menu_entries = new String[][] { + { "Connect Device", connect_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 flash_command = "flash"; + + static final String[][] device_menu_entries = new String[][] { + { "Download Data", download_command }, + { "Configure Device", configure_command }, + { "Flash Device", flash_command }, + }; + + void stop_display() { + if (thread != null && thread.isAlive()) { + thread.interrupt(); + try { + thread.join(); + } catch (InterruptedException ie) {} + } + thread = null; + } + + public void reset() { + for (AltosFlightDisplay display : displays) + display.reset(); + } + + public void font_size_changed(int font_size) { + for (AltosFlightDisplay display : displays) + display.font_size_changed(font_size); + } + + public void units_changed(boolean imperial_units) { + for (AltosFlightDisplay display : displays) + display.units_changed(imperial_units); + } + + public void show(AltosState state, AltosListenerState listener_state) { + try { + status_update.saved_state = state; + + if (state == null) + state = new AltosState(); + + int i = 0; + for (AltosFlightDisplay display : displays) { + display.show(state, listener_state); + i++; + } + } catch (Exception ex) { + System.out.printf("Exception %s\n", ex.toString()); + for (StackTraceElement e : ex.getStackTrace()) + System.out.printf("%s\n", e.toString()); + } + } + + void new_window() { + new TeleGPS(); + } + + void preferences() { + new TeleGPSPreferences(this, voice()); + } + + void load_maps() { + new AltosUIMapPreload(this); + } + + void disconnect() { + setTitle("TeleGPS"); + stop_display(); + if (status_timer != null) { + status_timer.stop(); + status_timer = null; + status_update = null; + } + + telegps_status.disable_receive(); + disable_frequency_menu(); + } + + void connect(AltosDevice device) { + if (reader != null) + disconnect(); + try { + AltosFlightReader reader = new AltosTelemetryReader(new AltosSerial(device)); + set_reader(reader, device); + } 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 connect() { + AltosDevice device = AltosDeviceUIDialog.show(this, + AltosLib.product_basestation); + if (device == null) + return; + connect(device); + } + + public void scan_device_selected(AltosDevice device) { + connect(device); + } + + void scan() { + new AltosScanUI(this, false); + } + + void download(){ + new AltosEepromManage(this, AltosLib.product_telegps); + } + + void configure() { + new TeleGPSConfig(this); + } + + void export() { + AltosDataChooser chooser; + chooser = new AltosDataChooser(this); + AltosStateIterable states = chooser.runDialog(); + if (states == null) + return; + new AltosCSVUI(this, states, chooser.file()); + } + + void graph() { + AltosDataChooser chooser; + chooser = new AltosDataChooser(this); + AltosStateIterable states = chooser.runDialog(); + if (states == null) + return; + try { + new TeleGPSGraphUI(states, chooser.file()); + } catch (InterruptedException ie) { + } catch (IOException ie) { + } + } + + void flash() { + AltosFlashUI.show(this); + } + + 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 (connect_command.equals(ev.getActionCommand())) { + connect(); + 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; + } + if (flash_command.equals(ev.getActionCommand())) { + flash(); + return; + } + } + + void enable_frequency_menu(int serial, final AltosFlightReader reader) { + + if (frequency_listener != null) + disable_frequency_menu(); + + frequency_listener = 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(); + } + }; + + frequencies.addActionListener(frequency_listener); + frequencies.set_product("Monitor"); + frequencies.set_serial(serial); + frequencies.set_frequency(AltosUIPreferences.frequency(serial)); + frequencies.setEnabled(true); + + } + + void disable_frequency_menu() { + if (frequency_listener != null) { + frequencies.removeActionListener(frequency_listener); + frequencies.setEnabled(false); + frequency_listener = null; + } + + } + + public void set_reader(AltosFlightReader reader, AltosDevice device) { + status_update = new TeleGPSStatusUpdate(telegps_status); + + status_timer = new javax.swing.Timer(100, status_update); + status_timer.start(); + + setTitle(String.format("TeleGPS %s", reader.name)); + thread = new TeleGPSDisplayThread(this, voice(), this, reader); + thread.start(); + + if (device != null) + enable_frequency_menu(device.getSerial(), reader); + } + + static int number_of_windows; + + static public void add_window() { + ++number_of_windows; + } + + static public void subtract_window() { + --number_of_windows; + if (number_of_windows == 0) + System.exit(0); + } + + private void close() { + disconnect(); + AltosUIPreferences.unregister_font_listener(this); + AltosPreferences.unregister_units_listener(this); + setVisible(false); + dispose(); + subtract_window(); + } + + 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); + frequencies = new AltosFreqList(); + frequencies.setEnabled(false); + menu_bar.add(frequencies); + + displays = new LinkedList(); + + 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; + displays.add(telegps_status); + + + /* 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); + + map = new AltosUIMap(); + pane.add(map.getName(), map); + displays.add(map); + + gps_info = new TeleGPSInfo(); + pane.add(gps_info.getName(), gps_info); + displays.add(gps_info); + + gps_state = new TeleGPSState(); + pane.add(gps_state.getName(), gps_state); + displays.add(gps_state); + + info_table = new AltosInfoTable(); + pane.add("Table", info_table); + displays.add(info_table); + + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + + AltosUIPreferences.register_font_listener(this); + AltosPreferences.register_units_listener(this); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + close(); + } + }); + + pack(); + setVisible(true); + + add_window(); + } + + public TeleGPS(AltosFlightReader reader) { + this(); + set_reader(reader, null); + } + + public TeleGPS(AltosDevice device) { + this(); + connect(device); + } + + 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_graph(File file) { + AltosStateIterable states = record_iterable(file); + if (states == null) + return false; + try { + new TeleGPSGraphUI(states, file); + } catch (Exception e) { + return false; + } + return true; + } + + 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","")), + "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 \tpre-fetch maps for site map view\n"); + System.out.printf(" --replay \t\trelive the glory of past flights \n"); + System.out.printf(" --graph \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]); + AltosUIMap.prefetch_maps(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_none: + case process_graph: + if (!process_graph(file)) + ++errors; + break; + 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 (number_of_windows == 0) { + java.util.List devices = AltosUSBDevice.list(AltosLib.product_basestation); + if (devices != null) + for (AltosDevice device : devices) { + new TeleGPS(device); + any_created = true; + } + if (number_of_windows == 0) + new TeleGPS(); + } + } +}