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_11.*;
26 import org.altusmetrum.altosuilib_11.*;
28 public class TeleGPSDisplayThread extends Thread {
31 IdleThread idle_thread;
33 AltosFlightReader reader;
34 AltosState old_state, state;
35 AltosListenerState listener_state;
36 AltosFlightDisplay display;
38 synchronized void show_safely() {
39 final AltosState my_state = state;
40 final AltosListenerState my_listener_state = listener_state;
41 Runnable r = new Runnable() {
44 display.show(my_state, my_listener_state);
45 } catch (Exception ex) {
49 SwingUtilities.invokeLater(r);
52 void reading_error_internal() {
53 JOptionPane.showMessageDialog(parent,
54 String.format("Error reading from \"%s\"", reader.name),
55 "Telemetry Read Error",
56 JOptionPane.ERROR_MESSAGE);
59 void reading_error_safely() {
60 Runnable r = new Runnable() {
63 reading_error_internal();
64 } catch (Exception ex) {
68 SwingUtilities.invokeLater(r);
71 class IdleThread extends Thread {
77 public synchronized void report(boolean last) {
81 if (state.height() != AltosLib.MISSING) {
82 if (state.from_pad != null) {
83 voice.speak("Height %s, bearing %s %d, elevation %d, range %s, .\n",
84 AltosConvert.height.say(state.gps_height()),
85 state.from_pad.bearing_words(
86 AltosGreatCircle.BEARING_VOICE),
87 (int) (state.from_pad.bearing + 0.5),
88 (int) (state.elevation + 0.5),
89 AltosConvert.distance.say(state.range));
91 voice.speak("Height %s.\n",
92 AltosConvert.height.say(state.height()));
98 return System.currentTimeMillis();
101 void set_report_time() {
102 report_time = now() + report_interval;
108 if (reader.has_monitor_battery()) {
109 listener_state.battery = reader.monitor_battery();
115 synchronized (this) {
116 long sleep_time = report_time - now();
125 } catch (InterruptedException ie) {
128 } catch (InterruptedException iie) { }
132 public synchronized void notice(boolean spoken) {
133 if (old_state != null && old_state.state() != state.state()) {
140 public IdleThread() {
141 report_interval = 10000;
145 synchronized boolean tell() {
147 if (old_state == null || old_state.gps_ready != state.gps_ready) {
148 if (state.gps_ready) {
149 voice.speak("GPS ready");
152 else if (old_state != null) {
153 voice.speak("GPS lost");
162 boolean interrupted = false;
165 idle_thread = new IdleThread();
171 state = reader.read();
173 listener_state.running = false;
176 reader.update(state);
179 idle_thread.notice(told);
180 } catch (ParseException pp) {
181 System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage());
182 } catch (AltosCRCException ce) {
183 ++listener_state.crc_errors;
187 } catch (InterruptedException ee) {
189 } catch (IOException ie) {
190 reading_error_safely();
193 idle_thread.report(true);
194 reader.close(interrupted);
195 idle_thread.interrupt();
198 } catch (InterruptedException ie) {}
202 public TeleGPSDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) {
203 listener_state = new AltosListenerState();
206 display = in_display;