From 8c20030ea4eb8e068e1ba88e01d07dfbc27bd7db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jul 2011 18:41:15 -0700 Subject: altosui: Start adding support for scanning radio for available devices This is untested. Signed-off-by: Keith Packard --- altosui/AltosScanUI.java | 365 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 altosui/AltosScanUI.java (limited to 'altosui/AltosScanUI.java') diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java new file mode 100644 index 00000000..e55f317c --- /dev/null +++ b/altosui/AltosScanUI.java @@ -0,0 +1,365 @@ +/* + * Copyright © 2011 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 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.*; + +class AltosScanResult { + String callsign; + int serial; + int flight; + int channel; + int telemetry; + boolean interrupted = false; + + public String toString() { + return String.format("%-9.9s %4d %4d %2d %2d", + callsign, serial, flight, channel, telemetry); + } + + public String toShortString() { + return String.format("%s %d %d %d %d", + callsign, serial, flight, channel, telemetry); + } + + public AltosScanResult(String in_callsign, int in_serial, + int in_flight, int in_channel, int in_telemetry) { + callsign = in_callsign; + serial = in_serial; + flight = in_flight; + channel = in_channel; + telemetry = in_telemetry; + } + + public boolean equals(AltosScanResult other) { + return (callsign.equals(other.callsign) && + serial == other.serial && + flight == other.flight && + channel == other.channel && + telemetry == other.telemetry); + } +} + +class AltosScanResults extends LinkedList implements ListModel { + + LinkedList listeners = new LinkedList(); + + public boolean add(AltosScanResult r) { + for (AltosScanResult old : this) + if (old.equals(r)) + return true; + + super.add(r); + ListDataEvent de = new ListDataEvent(this, + ListDataEvent.INTERVAL_ADDED, + this.size() - 2, this.size() - 1); + for (ListDataListener l : listeners) + l.contentsChanged(de); + return true; + } + + public void addListDataListener(ListDataListener l) { + listeners.add(l); + } + + public void removeListDataListener(ListDataListener l) { + listeners.remove(l); + } + + public AltosScanResult getElementAt(int i) { + return this.get(i); + } + + public int getSize() { + return this.size(); + } +} + +public class AltosScanUI + extends JDialog + implements ActionListener +{ + JFrame owner; + AltosDevice device; + AltosTelemetryReader reader; + private JList list; + private JLabel channel_label; + private JLabel monitor_label; + private JButton ok_button; + javax.swing.Timer timer; + AltosScanResults results = new AltosScanResults(); + + static final int[] monitors = { Altos.ao_telemetry_split_len, + Altos.ao_telemetry_legacy_len }; + int monitor; + int channel; + + final static int timeout = 5 * 1000; + TelemetryHandler handler; + Thread thread; + + void scan_exception(Exception e) { + if (e instanceof FileNotFoundException) { + JOptionPane.showMessageDialog(owner, + String.format("Cannot open device \"%s\"", + device.toShortString()), + "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); + } + close(); + } + + class TelemetryHandler implements Runnable { + + public void run() { + + boolean interrupted = false; + + try { + for (;;) { + try { + AltosRecord record = reader.read(); + if (record == null) + break; + if ((record.seen & AltosRecord.seen_flight) != 0) { + AltosScanResult result = new AltosScanResult(record.callsign, + record.serial, + record.flight, + channel, + monitor); + results.add(result); + } + } catch (ParseException pp) { + System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage()); + } catch (AltosCRCException ce) { + } + } + } catch (InterruptedException ee) { + interrupted = true; + } catch (IOException ie) { + } finally { + reader.close(interrupted); + } + } + } + + void set_channel() { + reader.serial.set_channel(channel); + } + + void set_monitor() { + reader.serial.set_telemetry(monitors[monitor]); + } + + void next() { + ++channel; + if (channel == 10) { + channel = 0; + ++monitor; + if (monitor == monitors.length) + monitor = 0; + set_monitor(); + } + set_channel(); + } + + + void close() { + if (thread != null && thread.isAlive()) { + thread.interrupt(); + try { + thread.join(); + } catch (InterruptedException ie) {} + } + thread = null; + if (timer != null) + timer.stop(); + setVisible(false); + dispose(); + } + + void tick_timer() { + next(); + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if (cmd.equals("close")) { + close(); + } + } + + /* A window listener to catch closing events and tell the config code */ + class ConfigListener extends WindowAdapter { + AltosScanUI ui; + + public ConfigListener(AltosScanUI this_ui) { + ui = this_ui; + } + + public void windowClosing(WindowEvent e) { + ui.actionPerformed(new ActionEvent(e.getSource(), + ActionEvent.ACTION_PERFORMED, + "close")); + } + } + + private boolean open() { + device = AltosDeviceDialog.show(owner, Altos.product_any); + if (device != null) { + try { + reader = new AltosTelemetryReader(device); + set_channel(); + set_monitor(); + handler = new TelemetryHandler(); + thread = new Thread(handler); + thread.start(); + return true; + } catch (Exception e) { + scan_exception(e); + } + } + return false; + } + + public AltosScanUI(JFrame in_owner) { + + owner = in_owner; + + if (!open()) + return; + + Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); + Insets i = new Insets(4,4,4,4); + + timer = new javax.swing.Timer(timeout, this); + timer.setActionCommand("tick"); + timer.restart(); + + owner = in_owner; + + pane.setLayout(new GridBagLayout()); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 3; + c.anchor = GridBagConstraints.CENTER; + + list = new JList(results) { + //Subclass JList to workaround bug 4832765, which can cause the + //scroll pane to not let the user easily scroll up to the beginning + //of the list. An alternative would be to set the unitIncrement + //of the JScrollBar to a fixed value. You wouldn't get the nice + //aligned scrolling, but it should work. + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, + int direction) { + int row; + if (orientation == SwingConstants.VERTICAL && + direction < 0 && (row = getFirstVisibleIndex()) != -1) { + Rectangle r = getCellBounds(row, row); + if ((r.y == visibleRect.y) && (row != 0)) { + Point loc = r.getLocation(); + loc.y--; + int prevIndex = locationToIndex(loc); + Rectangle prevR = getCellBounds(prevIndex, prevIndex); + + if (prevR == null || prevR.y >= r.y) { + return 0; + } + return prevR.height; + } + } + return super.getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + }; + + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.setLayoutOrientation(JList.HORIZONTAL_WRAP); + list.setVisibleRowCount(-1); + +// list.addMouseListener(new MouseAdapter() { +// public void mouseClicked(MouseEvent e) { +// if (e.getClickCount() == 2) { +// select_button.doClick(); //emulate button click +// } +// } +// }); + JScrollPane listScroller = new JScrollPane(list); + listScroller.setPreferredSize(new Dimension(400, 80)); + listScroller.setAlignmentX(LEFT_ALIGNMENT); + + //Create a container so that we can add a title around + //the scroll pane. Can't add a title directly to the + //scroll pane because its background would be white. + //Lay out the label and scroll pane from top to bottom. + JPanel listPane = new JPanel(); + listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); + + JLabel label = new JLabel("Select Device"); + label.setLabelFor(list); + listPane.add(label); + listPane.add(Box.createRigidArea(new Dimension(0,5))); + listPane.add(listScroller); + listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + pane.add(listPane, c); + + pack(); + setLocationRelativeTo(owner); + + addWindowListener(new ConfigListener(this)); + } +} \ No newline at end of file -- cgit v1.2.3 From f32a55ac9a3ebbde2b41782f22491e72258fe05a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jul 2011 19:00:12 -0700 Subject: altosui: Pop up monitor window from scan dialog Signed-off-by: Keith Packard --- altosui/AltosScanUI.java | 120 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 97 insertions(+), 23 deletions(-) (limited to 'altosui/AltosScanUI.java') diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index e55f317c..01b01720 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -35,6 +35,7 @@ class AltosScanResult { int flight; int channel; int telemetry; + boolean interrupted = false; public String toString() { @@ -104,12 +105,14 @@ public class AltosScanUI extends JDialog implements ActionListener { - JFrame owner; + AltosUI owner; AltosDevice device; AltosTelemetryReader reader; private JList list; private JLabel channel_label; private JLabel monitor_label; + private JButton fake_button; + private JButton cancel_button; private JButton ok_button; javax.swing.Timer timer; AltosScanResults results = new AltosScanResults(); @@ -228,8 +231,26 @@ public class AltosScanUI public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); - if (cmd.equals("close")) { + if (cmd.equals("fake")) { + results.add(new AltosScanResult("N0CALL", 300, 1, 0, 1)); + } + + if (cmd.equals("cancel")) { + close(); + } + + if (cmd.equals("ok")) { close(); + AltosScanResult r = (AltosScanResult) (list.getSelectedValue()); + System.out.printf("Selected channel %d telemetry %d\n", + r.channel, r.telemetry); + if (device != null) { + if (reader != null) { + reader.set_telemetry(r.telemetry); + reader.set_channel(r.channel); + owner.telemetry_window(device); + } + } } } @@ -266,12 +287,12 @@ public class AltosScanUI return false; } - public AltosScanUI(JFrame in_owner) { + public AltosScanUI(AltosUI in_owner) { owner = in_owner; - if (!open()) - return; +// if (!open()) +// return; Container pane = getContentPane(); GridBagConstraints c = new GridBagConstraints(); @@ -285,17 +306,6 @@ public class AltosScanUI pane.setLayout(new GridBagLayout()); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 1; - - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 3; - c.anchor = GridBagConstraints.CENTER; - list = new JList(results) { //Subclass JList to workaround bug 4832765, which can cause the //scroll pane to not let the user easily scroll up to the beginning @@ -330,13 +340,13 @@ public class AltosScanUI list.setLayoutOrientation(JList.HORIZONTAL_WRAP); list.setVisibleRowCount(-1); -// list.addMouseListener(new MouseAdapter() { -// public void mouseClicked(MouseEvent e) { -// if (e.getClickCount() == 2) { -// select_button.doClick(); //emulate button click -// } -// } -// }); + list.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + ok_button.doClick(); //emulate button click + } + } + }); JScrollPane listScroller = new JScrollPane(list); listScroller.setPreferredSize(new Dimension(400, 80)); listScroller.setAlignmentX(LEFT_ALIGNMENT); @@ -355,11 +365,75 @@ public class AltosScanUI listPane.add(listScroller); listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 3; + c.anchor = GridBagConstraints.CENTER; + pane.add(listPane, c); + fake_button = new JButton("fake"); + fake_button.addActionListener(this); + fake_button.setActionCommand("fake"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(fake_button, c); + + cancel_button = new JButton("Cancel"); + cancel_button.addActionListener(this); + cancel_button.setActionCommand("cancel"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 1; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(cancel_button, c); + + ok_button = new JButton("OK"); + ok_button.addActionListener(this); + ok_button.setActionCommand("ok"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 2; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(ok_button, c); + pack(); setLocationRelativeTo(owner); addWindowListener(new ConfigListener(this)); + + setVisible(true); } } \ No newline at end of file -- cgit v1.2.3 From 7ef786276b5d5c7d17c3fe4f36aa41db61a9742f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 14:23:08 -0700 Subject: altosui: Finish radio scanning UI Scans all channels and telemetry formats, presenting visible devices in a list. Entries from the list may be selected, in which case a monitor window pops up with the appropriate configuration. Signed-off-by: Keith Packard --- altosui/AltosScanUI.java | 183 ++++++++++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 80 deletions(-) (limited to 'altosui/AltosScanUI.java') diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 01b01720..d94ac3ae 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -35,12 +35,13 @@ class AltosScanResult { int flight; int channel; int telemetry; + static final String[] short_monitor_names = { "Standard", "Original" }; boolean interrupted = false; public String toString() { - return String.format("%-9.9s %4d %4d %2d %2d", - callsign, serial, flight, channel, telemetry); + return String.format("%-9.9s serial %-4d flight %-4d (channel %-2d telemetry %s)", + callsign, serial, flight, channel, short_monitor_names[telemetry]); } public String toShortString() { @@ -109,20 +110,18 @@ public class AltosScanUI AltosDevice device; AltosTelemetryReader reader; private JList list; - private JLabel channel_label; - private JLabel monitor_label; - private JButton fake_button; + private JLabel scanning_label; private JButton cancel_button; - private JButton ok_button; + private JButton monitor_button; javax.swing.Timer timer; AltosScanResults results = new AltosScanResults(); - static final int[] monitors = { Altos.ao_telemetry_split_len, - Altos.ao_telemetry_legacy_len }; + static final String[] monitor_names = { "Standard AltOS Telemetry", "Original TeleMetrum Telemetry" }; + static final int[] monitors = { 2, 1 }; int monitor; int channel; - final static int timeout = 5 * 1000; + final static int timeout = 1200; TelemetryHandler handler; Thread thread; @@ -166,17 +165,21 @@ public class AltosScanUI try { AltosRecord record = reader.read(); if (record == null) - break; + continue; if ((record.seen & AltosRecord.seen_flight) != 0) { - AltosScanResult result = new AltosScanResult(record.callsign, + final AltosScanResult result = new AltosScanResult(record.callsign, record.serial, record.flight, channel, monitor); - results.add(result); + Runnable r = new Runnable() { + public void run() { + results.add(result); + } + }; + SwingUtilities.invokeLater(r); } } catch (ParseException pp) { - System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage()); } catch (AltosCRCException ce) { } } @@ -189,24 +192,29 @@ public class AltosScanUI } } - void set_channel() { - reader.serial.set_channel(channel); - } - - void set_monitor() { - reader.serial.set_telemetry(monitors[monitor]); + void set_label() { + scanning_label.setText(String.format("Scanning: channel %d %s", + channel, + monitor_names[monitor])); } void next() { + reader.serial.set_monitor(false); + try { + Thread.sleep(100); + } catch (InterruptedException ie){ + } ++channel; - if (channel == 10) { + if (channel > 9) { channel = 0; ++monitor; if (monitor == monitors.length) monitor = 0; - set_monitor(); + reader.serial.set_telemetry(monitors[monitor]); } - set_channel(); + reader.serial.set_channel(channel); + set_label(); + reader.serial.set_monitor(true); } @@ -231,24 +239,22 @@ public class AltosScanUI public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); - if (cmd.equals("fake")) { - results.add(new AltosScanResult("N0CALL", 300, 1, 0, 1)); - } - - if (cmd.equals("cancel")) { + if (cmd.equals("cancel")) close(); - } - if (cmd.equals("ok")) { + if (cmd.equals("tick")) + tick_timer(); + + if (cmd.equals("monitor")) { close(); AltosScanResult r = (AltosScanResult) (list.getSelectedValue()); - System.out.printf("Selected channel %d telemetry %d\n", - r.channel, r.telemetry); - if (device != null) { - if (reader != null) { - reader.set_telemetry(r.telemetry); - reader.set_channel(r.channel); - owner.telemetry_window(device); + if (r != null) { + if (device != null) { + if (reader != null) { + reader.set_telemetry(monitors[r.telemetry]); + reader.set_channel(r.channel); + owner.telemetry_window(device); + } } } } @@ -270,20 +276,37 @@ public class AltosScanUI } private boolean open() { - device = AltosDeviceDialog.show(owner, Altos.product_any); - if (device != null) { - try { - reader = new AltosTelemetryReader(device); - set_channel(); - set_monitor(); - handler = new TelemetryHandler(); - thread = new Thread(handler); - thread.start(); - return true; - } catch (Exception e) { - scan_exception(e); - } + device = AltosDeviceDialog.show(owner, Altos.product_basestation); + if (device == null) + return false; + try { + reader = new AltosTelemetryReader(device); + reader.serial.set_channel(channel); + reader.serial.set_telemetry(monitors[monitor]); + handler = new TelemetryHandler(); + thread = new Thread(handler); + thread.start(); + return true; + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(owner, + String.format("Cannot open device \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(owner, + device.toShortString(), + "Unkonwn I/O error", + JOptionPane.ERROR_MESSAGE); } + if (reader != null) + reader.close(false); return false; } @@ -291,8 +314,8 @@ public class AltosScanUI owner = in_owner; -// if (!open()) -// return; + if (!open()) + return; Container pane = getContentPane(); GridBagConstraints c = new GridBagConstraints(); @@ -306,6 +329,23 @@ public class AltosScanUI pane.setLayout(new GridBagLayout()); + scanning_label = new JLabel("Scanning:"); + + set_label(); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 2; + c.anchor = GridBagConstraints.CENTER; + + pane.add(scanning_label, c); + list = new JList(results) { //Subclass JList to workaround bug 4832765, which can cause the //scroll pane to not let the user easily scroll up to the beginning @@ -343,7 +383,7 @@ public class AltosScanUI list.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { - ok_button.doClick(); //emulate button click + monitor_button.doClick(); //emulate button click } } }); @@ -365,24 +405,7 @@ public class AltosScanUI listPane.add(listScroller); listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 1; - - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 3; - c.anchor = GridBagConstraints.CENTER; - - pane.add(listPane, c); - - fake_button = new JButton("fake"); - fake_button.addActionListener(this); - fake_button.setActionCommand("fake"); - - c.fill = GridBagConstraints.NONE; + c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; c.insets = i; c.weightx = 1; @@ -390,10 +413,10 @@ public class AltosScanUI c.gridx = 0; c.gridy = 1; - c.gridwidth = 1; + c.gridwidth = 2; c.anchor = GridBagConstraints.CENTER; - pane.add(fake_button, c); + pane.add(listPane, c); cancel_button = new JButton("Cancel"); cancel_button.addActionListener(this); @@ -405,16 +428,16 @@ public class AltosScanUI c.weightx = 1; c.weighty = 1; - c.gridx = 1; - c.gridy = 1; + c.gridx = 0; + c.gridy = 2; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; pane.add(cancel_button, c); - ok_button = new JButton("OK"); - ok_button.addActionListener(this); - ok_button.setActionCommand("ok"); + monitor_button = new JButton("Monitor"); + monitor_button.addActionListener(this); + monitor_button.setActionCommand("monitor"); c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -422,12 +445,12 @@ public class AltosScanUI c.weightx = 1; c.weighty = 1; - c.gridx = 2; - c.gridy = 1; + c.gridx = 1; + c.gridy = 2; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; - pane.add(ok_button, c); + pane.add(monitor_button, c); pack(); setLocationRelativeTo(owner); -- cgit v1.2.3 From 941b90a4905e34936d24a25ca90ac04eb6f5a792 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 17:38:00 -0700 Subject: altosui: Generalize and centralize telemetry constants, parse v0.8 telemetry Move telemetry constants to Altos class, adding functions to compute names and lengths. Generalize users of these values to use all of the known values. Add support for v0.8 TeleMetrum telemetry Signed-off-by: Keith Packard --- altosui/Altos.java | 34 +++++++++++++++++++++++++++++---- altosui/AltosFlightUI.java | 14 +++++++------- altosui/AltosPreferences.java | 2 +- altosui/AltosScanUI.java | 28 +++++++++++++-------------- altosui/AltosSerial.java | 10 ++-------- altosui/AltosTelemetryRecordLegacy.java | 20 ++++++++++++------- altosui/AltosTelemetryRecordRaw.java | 7 +++++-- 7 files changed, 72 insertions(+), 43 deletions(-) (limited to 'altosui/AltosScanUI.java') diff --git a/altosui/Altos.java b/altosui/Altos.java index 96263797..8d5916ad 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -70,11 +70,23 @@ public class Altos { /* Telemetry modes */ static final int ao_telemetry_off = 0; - static final int ao_telemetry_legacy = 1; - static final int ao_telemetry_split = 2; + static final int ao_telemetry_min = 1; + static final int ao_telemetry_standard = 1; + static final int ao_telemetry_0_9 = 2; + static final int ao_telemetry_0_8 = 3; + static final int ao_telemetry_max = 3; + + static final String[] ao_telemetry_name = { + "Off", "Standard Telemetry", "TeleMetrum v0.9", "TeleMetrum v0.8" + }; + + static final int ao_telemetry_standard_len = 32; + static final int ao_telemetry_0_9_len = 95; + static final int ao_telemetry_0_8_len = 94; - static final int ao_telemetry_split_len = 32; - static final int ao_telemetry_legacy_len = 95; + static final int[] ao_telemetry_len = { + 0, 32, 95, 94 + }; static HashMap string_to_state = new HashMap(); @@ -103,6 +115,20 @@ public class Altos { map_initialized = true; } + static int telemetry_len(int telemetry) { + if (telemetry <= ao_telemetry_max) + return ao_telemetry_len[telemetry]; + throw new IllegalArgumentException(String.format("Invalid telemetry %d", + telemetry)); + } + + static String telemetry_name(int telemetry) { + if (telemetry <= ao_telemetry_max) + return ao_telemetry_name[telemetry]; + throw new IllegalArgumentException(String.format("Invalid telemetry %d", + telemetry)); + } + static String[] state_to_string = { "startup", "idle", diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 9536c4bb..04bfc90d 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -156,14 +156,14 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { // Telemetry format menu telemetries = new JComboBox(); - telemetries.addItem("Original TeleMetrum Telemetry"); - telemetries.addItem("Standard AltOS Telemetry"); - int telemetry = 1; - telemetry = AltosPreferences.telemetry(serial); - if (telemetry > Altos.ao_telemetry_split) - telemetry = Altos.ao_telemetry_split; + for (int i = 1; i <= Altos.ao_telemetry_max; i++) + telemetries.addItem(Altos.telemetry_name(i)); + int telemetry = AltosPreferences.telemetry(serial); + if (telemetry <= Altos.ao_telemetry_off || + telemetry > Altos.ao_telemetry_max) + telemetry = Altos.ao_telemetry_standard; telemetries.setSelectedIndex(telemetry - 1); - telemetries.setMaximumRowCount(2); + telemetries.setMaximumRowCount(Altos.ao_telemetry_max); telemetries.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int telemetry = telemetries.getSelectedIndex() + 1; diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index 5029aff6..c8dee743 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -216,7 +216,7 @@ class AltosPreferences { if (telemetries.containsKey(serial)) return telemetries.get(serial); int telemetry = preferences.getInt(String.format(telemetryPreferenceFormat, serial), - Altos.ao_telemetry_split); + Altos.ao_telemetry_standard); telemetries.put(serial, telemetry); return telemetry; } diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index d94ac3ae..54be4f52 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -35,13 +35,12 @@ class AltosScanResult { int flight; int channel; int telemetry; - static final String[] short_monitor_names = { "Standard", "Original" }; boolean interrupted = false; public String toString() { - return String.format("%-9.9s serial %-4d flight %-4d (channel %-2d telemetry %s)", - callsign, serial, flight, channel, short_monitor_names[telemetry]); + return String.format("%-9.9s serial %-4d flight %-4d (channel %-2d %s)", + callsign, serial, flight, channel, Altos.telemetry_name(telemetry)); } public String toShortString() { @@ -116,9 +115,7 @@ public class AltosScanUI javax.swing.Timer timer; AltosScanResults results = new AltosScanResults(); - static final String[] monitor_names = { "Standard AltOS Telemetry", "Original TeleMetrum Telemetry" }; - static final int[] monitors = { 2, 1 }; - int monitor; + int telemetry; int channel; final static int timeout = 1200; @@ -171,7 +168,7 @@ public class AltosScanUI record.serial, record.flight, channel, - monitor); + telemetry); Runnable r = new Runnable() { public void run() { results.add(result); @@ -195,7 +192,7 @@ public class AltosScanUI void set_label() { scanning_label.setText(String.format("Scanning: channel %d %s", channel, - monitor_names[monitor])); + Altos.telemetry_name(telemetry))); } void next() { @@ -207,10 +204,10 @@ public class AltosScanUI ++channel; if (channel > 9) { channel = 0; - ++monitor; - if (monitor == monitors.length) - monitor = 0; - reader.serial.set_telemetry(monitors[monitor]); + ++telemetry; + if (telemetry > Altos.ao_telemetry_max) + telemetry = Altos.ao_telemetry_min; + reader.serial.set_telemetry(telemetry); } reader.serial.set_channel(channel); set_label(); @@ -251,7 +248,7 @@ public class AltosScanUI if (r != null) { if (device != null) { if (reader != null) { - reader.set_telemetry(monitors[r.telemetry]); + reader.set_telemetry(r.telemetry); reader.set_channel(r.channel); owner.telemetry_window(device); } @@ -282,7 +279,7 @@ public class AltosScanUI try { reader = new AltosTelemetryReader(device); reader.serial.set_channel(channel); - reader.serial.set_telemetry(monitors[monitor]); + reader.serial.set_telemetry(telemetry); handler = new TelemetryHandler(); thread = new Thread(handler); thread.start(); @@ -329,6 +326,9 @@ public class AltosScanUI pane.setLayout(new GridBagLayout()); + channel = 0; + telemetry = Altos.ao_telemetry_min; + scanning_label = new JLabel("Scanning:"); set_label(); diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 3666cb41..2e8ce870 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -326,13 +326,7 @@ public class AltosSerial implements Runnable { } private int telemetry_len() { - switch (telemetry) { - case 1: - default: - return Altos.ao_telemetry_legacy_len; - case 2: - return Altos.ao_telemetry_split_len; - } + return Altos.telemetry_len(telemetry); } public void set_channel(int in_channel) { @@ -404,7 +398,7 @@ public class AltosSerial implements Runnable { line = ""; monitor_mode = false; frame = null; - telemetry = Altos.ao_telemetry_split; + telemetry = Altos.ao_telemetry_standard; monitors = new LinkedList> (); reply_queue = new LinkedBlockingQueue (); open(); diff --git a/altosui/AltosTelemetryRecordLegacy.java b/altosui/AltosTelemetryRecordLegacy.java index e3751ee7..756f3ec9 100644 --- a/altosui/AltosTelemetryRecordLegacy.java +++ b/altosui/AltosTelemetryRecordLegacy.java @@ -385,24 +385,25 @@ public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTele */ int[] bytes; + int adjust; private int int8(int i) { - return Altos.int8(bytes, i + 1); + return Altos.int8(bytes, i + 1 + adjust); } private int uint8(int i) { - return Altos.uint8(bytes, i + 1); + return Altos.uint8(bytes, i + 1 + adjust); } private int int16(int i) { - return Altos.int16(bytes, i + 1); + return Altos.int16(bytes, i + 1 + adjust); } private int uint16(int i) { - return Altos.uint16(bytes, i + 1); + return Altos.uint16(bytes, i + 1 + adjust); } private int uint32(int i) { - return Altos.uint32(bytes, i + 1); + return Altos.uint32(bytes, i + 1 + adjust); } private String string(int i, int l) { - return Altos.string(bytes, i + 1, l); + return Altos.string(bytes, i + 1 + adjust, l); } static final int AO_GPS_NUM_SAT_MASK = (0xf << 0); @@ -428,8 +429,13 @@ public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTele } } version = 4; - callsign = string(62, 8); + adjust = 0; serial = uint16(0); + + if (bytes.length == Altos.ao_telemetry_0_8_len + 4) + adjust = -1; + + callsign = string(62, 8); flight = uint16(2); rssi = in_rssi; status = in_status; diff --git a/altosui/AltosTelemetryRecordRaw.java b/altosui/AltosTelemetryRecordRaw.java index e6c4cfc8..4b34f017 100644 --- a/altosui/AltosTelemetryRecordRaw.java +++ b/altosui/AltosTelemetryRecordRaw.java @@ -72,7 +72,7 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { /* length, data ..., rssi, status, checksum -- 4 bytes extra */ switch (bytes.length) { - case Altos.ao_telemetry_split_len + 4: + case Altos.ao_telemetry_standard_len + 4: int type = Altos.uint8(bytes, 4 + 1); switch (type) { case packet_type_TM_sensor: @@ -94,7 +94,10 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { break; } break; - case Altos.ao_telemetry_legacy_len + 4: + case Altos.ao_telemetry_0_9_len + 4: + r = new AltosTelemetryRecordLegacy(bytes, rssi, status); + break; + case Altos.ao_telemetry_0_8_len + 4: r = new AltosTelemetryRecordLegacy(bytes, rssi, status); break; default: -- cgit v1.2.3 From e905042879147dd86241bf2dcc7437e5a6eb7578 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 20:43:57 -0700 Subject: altosui: Initialize channel and telemetry before use in ScanUI Otherwise we try to use telemetry format 0, which means 'no telemetry'. Signed-off-by: Keith Packard --- altosui/AltosScanUI.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'altosui/AltosScanUI.java') diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 54be4f52..bc1638ed 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -311,6 +311,9 @@ public class AltosScanUI owner = in_owner; + channel = 0; + telemetry = Altos.ao_telemetry_min; + if (!open()) return; @@ -326,9 +329,6 @@ public class AltosScanUI pane.setLayout(new GridBagLayout()); - channel = 0; - telemetry = Altos.ao_telemetry_min; - scanning_label = new JLabel("Scanning:"); set_label(); -- cgit v1.2.3 From 00e6981c2e0a668864fcf391932855cd8942140c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 21:05:06 -0700 Subject: altosui: Flush telemetry lines before starting to watch for scan results This prevents pending telemetry lines from being incorrectly attributed to the wrong channel/telemetry. Signed-off-by: Keith Packard --- altosui/AltosScanUI.java | 5 +++++ altosui/AltosTelemetryReader.java | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'altosui/AltosScanUI.java') diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index bc1638ed..96cab73b 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -280,6 +280,11 @@ public class AltosScanUI reader = new AltosTelemetryReader(device); reader.serial.set_channel(channel); reader.serial.set_telemetry(telemetry); + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + } + reader.flush(); handler = new TelemetryHandler(); thread = new Thread(handler); thread.start(); diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java index 18f17841..23524b2c 100644 --- a/altosui/AltosTelemetryReader.java +++ b/altosui/AltosTelemetryReader.java @@ -39,6 +39,10 @@ class AltosTelemetryReader extends AltosFlightReader { return next; } + void flush() { + telem.clear(); + } + void close(boolean interrupted) { serial.remove_monitor(telem); log.close(); -- cgit v1.2.3