2 * Copyright © 2011 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.AltosLib;
22 import java.util.concurrent.*;
26 public abstract class AltosLink implements Runnable {
28 public final static int ERROR = -1;
29 public final static int TIMEOUT = -2;
31 public abstract int getchar();
32 public abstract void print(String data);
33 public abstract void close();
35 public static boolean debug = false;
36 public static void set_debug(boolean in_debug) { debug = in_debug; }
37 LinkedList<String> pending_output = new LinkedList<String>();
39 public LinkedList<LinkedBlockingQueue<AltosLine>> monitors = new LinkedList<LinkedBlockingQueue<AltosLine>> ();;
40 public LinkedBlockingQueue<AltosLine> reply_queue = new LinkedBlockingQueue<AltosLine>();
42 public void add_monitor(LinkedBlockingQueue<AltosLine> q) {
47 public void remove_monitor(LinkedBlockingQueue<AltosLine> q) {
49 if (monitors.isEmpty())
53 public void printf(String format, Object ... arguments) {
54 String line = String.format(format, arguments);
56 pending_output.add(line);
60 public String get_reply_no_dialog(int timeout) throws InterruptedException, TimeoutException {
62 AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS);
68 public String get_reply() throws InterruptedException {
69 return get_reply(5000);
73 public abstract boolean can_cancel_reply();
74 public abstract boolean show_reply_timeout();
75 public abstract void hide_reply_timeout();
77 public boolean reply_abort;
80 boolean reply_timeout_shown = false;
82 private boolean check_reply_timeout() {
83 if (!reply_timeout_shown)
84 reply_timeout_shown = show_reply_timeout();
88 private void cleanup_reply_timeout() {
89 if (reply_timeout_shown) {
90 reply_timeout_shown = false;
98 byte[] line_bytes = null;
104 if (Thread.interrupted()) {
106 System.out.printf("INTERRUPTED\n");
111 System.out.printf("ERROR\n");
112 add_telem (new AltosLine());
113 add_reply (new AltosLine());
118 System.out.printf("TIMEOUT\n");
125 if (line_count != 0) {
126 add_bytes(line_bytes, line_count);
130 if (line_bytes == null) {
131 line_bytes = new byte[256];
132 } else if (line_count == line_bytes.length) {
133 byte[] new_line_bytes = new byte[line_count * 2];
134 System.arraycopy(line_bytes, 0, new_line_bytes, 0, line_count);
135 line_bytes = new_line_bytes;
137 line_bytes[line_count] = (byte) c;
142 } catch (InterruptedException e) {
146 public String get_reply(int timeout) throws InterruptedException {
147 boolean can_cancel = can_cancel_reply();
150 if (!can_cancel && remote)
151 System.out.printf("Uh-oh, reading remote serial device from swing thread\n");
153 if (remote && can_cancel)
161 reply_timeout_shown = false;
163 AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS);
165 cleanup_reply_timeout();
169 if (!remote || !can_cancel || check_reply_timeout()) {
180 public void add_telem(AltosLine line) throws InterruptedException {
181 for (int e = 0; e < monitors.size(); e++) {
182 LinkedBlockingQueue<AltosLine> q = monitors.get(e);
187 public void add_reply(AltosLine line) throws InterruptedException {
188 reply_queue.put (line);
191 public void abort_reply() {
193 add_telem (new AltosLine());
194 add_reply (new AltosLine());
195 } catch (InterruptedException e) {
199 public void add_string(String line) throws InterruptedException {
200 if (line.startsWith("TELEM") || line.startsWith("VERSION") || line.startsWith("CRC")) {
201 add_telem(new AltosLine(line));
203 add_reply(new AltosLine(line));
207 public void add_bytes(byte[] bytes, int len) throws InterruptedException {
210 line = new String(bytes, 0, len, "UTF-8");
211 } catch (UnsupportedEncodingException ue) {
213 for (int i = 0; i < len; i++)
214 line = line + bytes[i];
217 System.out.printf("\t\t\t\t\t%s\n", line);
221 public void flush_output() {
222 for (String s : pending_output)
224 pending_output.clear();
227 public void flush_input(int timeout) throws InterruptedException {
232 Thread.sleep(timeout);
233 got_some = !reply_queue.isEmpty();
239 public void flush_input() throws InterruptedException {
248 * Various command-level operations on
251 public boolean monitor_mode = false;
252 public int telemetry = AltosLib.ao_telemetry_standard;
253 public double frequency;
254 AltosConfigData config_data;
256 private int telemetry_len() {
257 return AltosLib.telemetry_len(telemetry);
260 private void set_radio_freq(int frequency) {
262 printf("m 0\nc F %d\nm %x\n",
263 frequency, telemetry_len());
265 printf("c F %d\n", frequency);
269 public void set_radio_frequency(double frequency,
270 boolean has_frequency,
274 System.out.printf("set_radio_frequency %7.3f (freq %b) (set %b) %d\n", frequency, has_frequency, has_setting, cal);
278 set_radio_freq((int) Math.floor (frequency * 1000));
279 else if (has_setting)
280 set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal));
282 set_channel(AltosConvert.radio_frequency_to_channel(frequency));
285 public void set_radio_frequency(double in_frequency) throws InterruptedException, TimeoutException {
286 frequency = in_frequency;
288 set_radio_frequency(frequency,
289 config_data.radio_frequency != 0,
290 config_data.radio_setting != 0,
291 config_data.radio_calibration);
294 public void set_telemetry(int in_telemetry) {
295 telemetry = in_telemetry;
297 printf("m 0\nm %x\n", telemetry_len());
301 public void set_monitor(boolean monitor) {
302 monitor_mode = monitor;
304 printf("m %x\n", telemetry_len());
310 private void set_channel(int channel) {
312 printf("m 0\nc r %d\nm %x\n",
313 channel, telemetry_len());
315 printf("c r %d\n", channel);
319 private void set_radio_setting(int setting) {
321 printf("m 0\nc R %d\nm %x\n",
322 setting, telemetry_len());
324 printf("c R %d\n", setting);
328 public AltosConfigData config_data() throws InterruptedException, TimeoutException {
329 if (config_data == null)
330 config_data = new AltosConfigData(this);
334 public void set_callsign(String callsign) {
335 printf ("c c %s\n", callsign);
339 public boolean remote;
343 public void start_remote() throws TimeoutException, InterruptedException {
345 System.out.printf("start remote %7.3f\n", frequency);
346 if (frequency == 0.0)
347 frequency = AltosPreferences.frequency(serial);
348 set_radio_frequency(frequency);
349 set_callsign(AltosPreferences.callsign());
355 public void stop_remote() throws InterruptedException {
357 System.out.printf("stop remote\n");