altos: More cleanups for moving files to altoslib
[fw/altos] / altoslib / AltosLink.java
1 /*
2  * Copyright © 2011 Keith Packard <keithp@keithp.com>
3  *
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.
7  *
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.
12  *
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.
16  */
17
18 package org.altusmetrum.AltosLib;
19
20 import java.lang.*;
21 import java.io.*;
22 import java.util.concurrent.*;
23 import java.util.*;
24 import java.text.*;
25
26 public abstract class AltosLink {
27         public abstract void print(String data);
28         public abstract void close();
29
30         public static boolean debug = false;
31         public static void set_debug(boolean in_debug) { debug = in_debug; }
32         LinkedList<String> pending_output = new LinkedList<String>();
33
34         public LinkedList<LinkedBlockingQueue<AltosLine>> monitors = new LinkedList<LinkedBlockingQueue<AltosLine>> ();;
35         public LinkedBlockingQueue<AltosLine> reply_queue = new LinkedBlockingQueue<AltosLine>();
36
37         public void add_monitor(LinkedBlockingQueue<AltosLine> q) {
38                 set_monitor(true);
39                 monitors.add(q);
40         }
41
42         public void remove_monitor(LinkedBlockingQueue<AltosLine> q) {
43                 monitors.remove(q);
44                 if (monitors.isEmpty())
45                         set_monitor(false);
46         }
47
48         public void printf(String format, Object ... arguments) {
49                 String  line = String.format(format, arguments);
50                 if (debug)
51                         pending_output.add(line);
52                 print(line);
53         }
54
55         public String get_reply_no_dialog(int timeout) throws InterruptedException, TimeoutException {
56                 flush_output();
57                 AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS);
58                 if (line != null)
59                         return line.line;
60                 return null;
61         }
62
63         public String get_reply(int timeout) throws InterruptedException {
64                 try {
65                         return get_reply_no_dialog(timeout);
66                 } catch (TimeoutException te) {
67                         return null;
68                 }
69         }
70
71         public String get_reply() throws InterruptedException {
72                 return get_reply(5000);
73         }
74
75         public void add_telem(AltosLine line) throws InterruptedException {
76                 for (int e = 0; e < monitors.size(); e++) {
77                         LinkedBlockingQueue<AltosLine> q = monitors.get(e);
78                         q.put(line);
79                 }
80         }
81
82         public void add_reply(AltosLine line) throws InterruptedException {
83                 reply_queue.put (line);
84         }
85
86         public void add_string(String line) throws InterruptedException {
87                 if (line.startsWith("TELEM") || line.startsWith("VERSION") || line.startsWith("CRC")) {
88                         add_telem(new AltosLine(line));
89                 } else {
90                         add_reply(new AltosLine(line));
91                 }
92         }
93
94         public void add_bytes(byte[] bytes, int len) throws InterruptedException {
95                 String  line;
96                 try {
97                         line = new String(bytes, 0, len, "UTF-8");
98                 } catch (UnsupportedEncodingException ue) {
99                         line = "";
100                         for (int i = 0; i < len; i++)
101                                 line = line + bytes[i];
102                 }
103                 if (debug)
104                         System.out.printf("\t\t\t\t\t%s\n", line);
105                 add_string(line);
106         }
107
108         public void flush_output() {
109                 for (String s : pending_output)
110                         System.out.print(s);
111                 pending_output.clear();
112         }
113
114         public void flush_input(int timeout) throws InterruptedException {
115                 flush_output();
116                 boolean got_some;
117
118                 do {
119                         Thread.sleep(timeout);
120                         got_some = !reply_queue.isEmpty();
121                         reply_queue.clear();
122                 } while (got_some);
123         }
124
125
126         public void flush_input() throws InterruptedException {
127                 flush_input(100);
128         }
129
130
131         /*
132          * Various command-level operations on
133          * the link
134          */
135         public boolean monitor_mode = false;
136         public int telemetry = AltosLib.ao_telemetry_standard;
137         public double frequency;
138         AltosConfigData config_data;
139
140         private int telemetry_len() {
141                 return AltosLib.telemetry_len(telemetry);
142         }
143
144         private void set_radio_freq(int frequency) {
145                 if (monitor_mode)
146                         printf("m 0\nc F %d\nm %x\n",
147                                frequency, telemetry_len());
148                 else
149                         printf("c F %d\n", frequency);
150                 flush_output();
151         }
152
153         public void set_radio_frequency(double frequency,
154                                         boolean has_frequency,
155                                         boolean has_setting,
156                                         int cal) {
157                 if (debug)
158                         System.out.printf("set_radio_frequency %7.3f (freq %b) (set %b) %d\n", frequency, has_frequency, has_setting, cal);
159                 if (frequency == 0)
160                         return;
161                 if (has_frequency)
162                         set_radio_freq((int) Math.floor (frequency * 1000));
163                 else if (has_setting)
164                         set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal));
165                 else
166                         set_channel(AltosConvert.radio_frequency_to_channel(frequency));
167         }
168
169         public void set_telemetry(int in_telemetry) {
170                 telemetry = in_telemetry;
171                 if (monitor_mode)
172                         printf("m 0\nm %x\n", telemetry_len());
173                 flush_output();
174         }
175
176         public void set_monitor(boolean monitor) {
177                 monitor_mode = monitor;
178                 if (monitor)
179                         printf("m %x\n", telemetry_len());
180                 else
181                         printf("m 0\n");
182                 flush_output();
183         }
184
185         private void set_channel(int channel) {
186                 if (monitor_mode)
187                         printf("m 0\nc r %d\nm %x\n",
188                                channel, telemetry_len());
189                 else
190                         printf("c r %d\n", channel);
191                 flush_output();
192         }
193
194         private void set_radio_setting(int setting) {
195                 if (monitor_mode)
196                         printf("m 0\nc R %d\nm %x\n",
197                                setting, telemetry_len());
198                 else
199                         printf("c R %d\n", setting);
200                 flush_output();
201         }
202
203         public void set_radio_frequency(double frequency,
204                                         boolean has_setting,
205                                         int cal) {
206                 if (debug)
207                         System.out.printf("set_radio_frequency %7.3f %b %d\n", frequency, has_setting, cal);
208                 if (has_setting)
209                         set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal));
210                 else
211                         set_channel(AltosConvert.radio_frequency_to_channel(frequency));
212         }
213
214         public AltosConfigData config_data() throws InterruptedException, TimeoutException {
215                 if (config_data == null)
216                         config_data = new AltosConfigData(this);
217                 return config_data;
218         }
219
220         public void set_radio_frequency(double in_frequency) throws InterruptedException, TimeoutException {
221                 frequency = in_frequency;
222                 config_data();
223                 set_radio_frequency(frequency,
224                                     config_data.radio_setting != 0,
225                                     config_data.radio_calibration);
226         }
227
228         public void set_callsign(String callsign) {
229                 printf ("c c %s\n", callsign);
230                 flush_output();
231         }
232
233         public boolean remote;
234         public int serial;
235         public String name;
236
237         public void start_remote() throws TimeoutException, InterruptedException {
238                 if (debug)
239                         System.out.printf("start remote %7.3f\n", frequency);
240                 if (frequency == 0.0)
241                         frequency = AltosPreferences.frequency(serial);
242                 set_radio_frequency(frequency);
243                 set_callsign(AltosPreferences.callsign());
244                 printf("p\nE 0\n");
245                 flush_input();
246                 remote = true;
247         }
248
249         public void stop_remote() throws InterruptedException {
250                 if (debug)
251                         System.out.printf("stop remote\n");
252                 try {
253                         flush_input();
254                 } finally {
255                         printf ("~\n");
256                         flush_output();
257                 }
258                 remote = false;
259         }
260
261         public AltosLink() {
262         }
263 }