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; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18 package org.altusmetrum.telegps;
24 import org.altusmetrum.altoslib_9.*;
25 import org.altusmetrum.altosuilib_9.*;
27 public class TeleGPSDisplayThread extends Thread {
30 IdleThread idle_thread;
32 AltosFlightReader reader;
33 AltosState old_state, state;
34 AltosListenerState listener_state;
35 AltosFlightDisplay display;
37 synchronized void show_safely() {
38 final AltosState my_state = state;
39 final AltosListenerState my_listener_state = listener_state;
40 Runnable r = new Runnable() {
43 display.show(my_state, my_listener_state);
44 } catch (Exception ex) {
48 SwingUtilities.invokeLater(r);
51 void reading_error_internal() {
52 JOptionPane.showMessageDialog(parent,
53 String.format("Error reading from \"%s\"", reader.name),
54 "Telemetry Read Error",
55 JOptionPane.ERROR_MESSAGE);
58 void reading_error_safely() {
59 Runnable r = new Runnable() {
62 reading_error_internal();
63 } catch (Exception ex) {
67 SwingUtilities.invokeLater(r);
70 class IdleThread extends Thread {
76 public synchronized void report(boolean last) {
80 if (state.height() != AltosLib.MISSING) {
81 if (state.from_pad != null) {
82 voice.speak("Height %s, bearing %s %d, elevation %d, range %s, .\n",
83 AltosConvert.height.say(state.gps_height()),
84 state.from_pad.bearing_words(
85 AltosGreatCircle.BEARING_VOICE),
86 (int) (state.from_pad.bearing + 0.5),
87 (int) (state.elevation + 0.5),
88 AltosConvert.distance.say(state.range));
90 voice.speak("Height %s.\n",
91 AltosConvert.height.say(state.height()));
97 return System.currentTimeMillis();
100 void set_report_time() {
101 report_time = now() + report_interval;
107 if (reader.has_monitor_battery()) {
108 listener_state.battery = reader.monitor_battery();
114 synchronized (this) {
115 long sleep_time = report_time - now();
124 } catch (InterruptedException ie) {
127 } catch (InterruptedException iie) { }
131 public synchronized void notice(boolean spoken) {
132 if (old_state != null && old_state.state() != state.state()) {
139 public IdleThread() {
140 report_interval = 10000;
144 synchronized boolean tell() {
146 if (old_state == null || old_state.gps_ready != state.gps_ready) {
147 if (state.gps_ready) {
148 voice.speak("GPS ready");
151 else if (old_state != null) {
152 voice.speak("GPS lost");
161 boolean interrupted = false;
164 idle_thread = new IdleThread();
170 state = reader.read();
172 listener_state.running = false;
175 reader.update(state);
178 idle_thread.notice(told);
179 } catch (ParseException pp) {
180 System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage());
181 } catch (AltosCRCException ce) {
182 ++listener_state.crc_errors;
186 } catch (InterruptedException ee) {
188 } catch (IOException ie) {
189 reading_error_safely();
192 idle_thread.report(true);
193 reader.close(interrupted);
194 idle_thread.interrupt();
197 } catch (InterruptedException ie) {}
201 public TeleGPSDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) {
202 listener_state = new AltosListenerState();
205 display = in_display;