2 * Copyright © 2010 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 package org.altusmetrum.telegps;
25 import org.altusmetrum.altoslib_14.*;
26 import org.altusmetrum.altosuilib_14.*;
28 public class TeleGPSDisplayThread extends Thread {
31 IdleThread idle_thread;
33 AltosFlightReader reader;
35 int old_state = AltosLib.ao_flight_invalid;
36 boolean old_gps_ready = false;
37 AltosListenerState listener_state;
38 AltosFlightDisplay display;
40 synchronized void show_safely() {
41 final AltosState my_state = state;
42 final AltosListenerState my_listener_state = listener_state;
43 Runnable r = new Runnable() {
46 display.show(my_state, my_listener_state);
47 } catch (Exception ex) {
51 SwingUtilities.invokeLater(r);
54 void reading_error_internal() {
55 JOptionPane.showMessageDialog(parent,
56 String.format("Error reading from \"%s\"", reader.name),
57 "Telemetry Read Error",
58 JOptionPane.ERROR_MESSAGE);
61 void reading_error_safely() {
62 Runnable r = new Runnable() {
65 reading_error_internal();
66 } catch (Exception ex) {
70 SwingUtilities.invokeLater(r);
73 class IdleThread extends Thread {
79 public synchronized void report(boolean last) {
83 if (state.height() != AltosLib.MISSING) {
84 if (state.from_pad != null) {
85 voice.speak("Height %s, bearing %s %d, elevation %d, range %s, .\n",
86 AltosConvert.height.say(state.gps_height()),
87 state.from_pad.bearing_words(
88 AltosGreatCircle.BEARING_VOICE),
89 (int) (state.from_pad.bearing + 0.5),
90 (int) (state.elevation + 0.5),
91 AltosConvert.distance.say(state.range));
93 voice.speak("Height %s.\n",
94 AltosConvert.height.say(state.height()));
100 return System.currentTimeMillis();
103 void set_report_time() {
104 report_time = now() + report_interval;
110 if (reader.has_monitor_battery()) {
111 listener_state.battery = reader.monitor_battery();
117 synchronized (this) {
118 long sleep_time = report_time - now();
127 } catch (InterruptedException ie) {
130 } catch (InterruptedException iie) { }
134 public synchronized void notice(boolean spoken) {
135 if (old_state != state.state()) {
140 old_state = state.state();
143 public IdleThread() {
144 report_interval = 10000;
148 synchronized boolean tell() {
150 if (old_gps_ready != state.gps_ready) {
151 if (state.gps_ready) {
152 voice.speak("GPS ready");
155 else if (old_gps_ready) {
156 voice.speak("GPS lost");
159 old_gps_ready = state.gps_ready;
165 boolean interrupted = false;
168 idle_thread = new IdleThread();
174 state = reader.read();
176 listener_state.running = false;
181 idle_thread.notice(told);
182 } catch (ParseException pp) {
183 System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage());
184 } catch (AltosCRCException ce) {
185 ++listener_state.crc_errors;
189 } catch (InterruptedException ee) {
191 } catch (IOException ie) {
192 reading_error_safely();
195 idle_thread.report(true);
196 reader.close(interrupted);
197 idle_thread.interrupt();
200 } catch (InterruptedException ie) {}
204 public TeleGPSDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) {
205 listener_state = new AltosListenerState();
208 display = in_display;