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.
24 * Telemetry data contents
35 int parse_int(String v) throws ParseException {
37 return Integer.parseInt(v);
38 } catch (NumberFormatException e) {
39 throw new ParseException(v, 0);
43 public AltosGPSTime(String date, String time) throws ParseException {
44 String[] ymd = date.split("-");
45 if (ymd.length != 3) {
46 System.out.println("Error parsing GPS date " + date + " got " + ymd.length);
47 throw new ParseException(date, 0);
49 year = parse_int(ymd[0]);
50 month = parse_int(ymd[1]);
51 day = parse_int(ymd[2]);
53 String[] hms = time.split(":");
54 if (hms.length != 3) {
55 System.out.println("Error parsing GPS time " + time + " got " + hms.length);
56 throw new ParseException(time, 0);
58 hour = parse_int(hms[0]);
59 minute = parse_int(hms[1]);
60 second = parse_int(hms[2]);
63 public AltosGPSTime() {
64 year = month = day = 0;
65 hour = minute = second = 0;
73 AltosGPSTime gps_time;
74 double lat; /* degrees (+N -S) */
75 double lon; /* degrees (+E -W) */
78 int gps_extended; /* has extra data */
79 double ground_speed; /* m/s */
80 int course; /* degrees */
81 double climb_rate; /* m/s */
82 double hdop; /* unitless? */
93 class AltosGPSTracking {
95 AltosGPSSat[] cc_gps_sat;
98 public class AltosTelemetry {
121 AltosGPSTracking gps_tracking;
123 int parse_int(String v) throws ParseException {
125 return Integer.parseInt(v);
126 } catch (NumberFormatException e) {
127 System.out.println("error parsing int " + v);
128 throw new ParseException(v, 0);
132 int parse_hex(String v) throws ParseException {
134 return Integer.parseInt(v, 16);
135 } catch (NumberFormatException e) {
136 System.out.println("error parsing hex " + v);
137 throw new ParseException(v, 0);
141 double parse_double(String v) throws ParseException {
143 return Double.parseDouble(v);
144 } catch (NumberFormatException e) {
145 System.out.println("error parsing double " + v);
146 throw new ParseException(v, 0);
150 double parse_coord(String coord) throws ParseException {
151 String[] dsf = coord.split("\\D+");
153 if (dsf.length != 3) {
154 System.out.println("error parsing coord " + coord);
155 throw new ParseException(coord, 0);
157 int deg = parse_int(dsf[0]);
158 int min = parse_int(dsf[1]);
159 int frac = parse_int(dsf[2]);
161 double r = deg + (min + frac / 10000.0) / 60.0;
162 if (coord.endsWith("S") || coord.endsWith("W"))
167 String strip_suffix(String v, String suffix) {
168 if (v.endsWith(suffix))
169 return v.substring(0, v.length() - suffix.length());
173 void word(String v, String m) throws ParseException {
175 System.out.println("error matching '" + v + "' '" + m + "'");
176 throw new ParseException(v, 0);
180 public AltosTelemetry(String line) throws ParseException {
181 String[] words = line.split("\\s+");
185 word (words[i++], "VERSION");
186 version = parse_int(words[i++]);
188 word (words[i++], "CALL");
189 callsign = words[i++];
191 word (words[i++], "SERIAL");
192 serial = parse_int(words[i++]);
194 word (words[i++], "FLIGHT");
195 flight = parse_int(words[i++]);
197 word(words[i++], "RSSI");
198 rssi = parse_int(words[i++]);
200 word(words[i++], "STATUS");
201 status = parse_hex(words[i++]);
203 word(words[i++], "STATE");
206 tick = parse_int(words[i++]);
208 word(words[i++], "a:");
209 accel = parse_int(words[i++]);
211 word(words[i++], "p:");
212 pres = parse_int(words[i++]);
214 word(words[i++], "t:");
215 temp = parse_int(words[i++]);
217 word(words[i++], "v:");
218 batt = parse_int(words[i++]);
220 word(words[i++], "d:");
221 drogue = parse_int(words[i++]);
223 word(words[i++], "m:");
224 main = parse_int(words[i++]);
226 word(words[i++], "fa:");
227 flight_accel = parse_int(words[i++]);
229 word(words[i++], "ga:");
230 ground_accel = parse_int(words[i++]);
232 word(words[i++], "fv:");
233 flight_vel = parse_int(words[i++]);
235 word(words[i++], "fp:");
236 flight_pres = parse_int(words[i++]);
238 word(words[i++], "gp:");
239 ground_pres = parse_int(words[i++]);
241 word(words[i++], "a+:");
242 accel_plus_g = parse_int(words[i++]);
244 word(words[i++], "a-:");
245 accel_minus_g = parse_int(words[i++]);
247 word(words[i++], "GPS");
248 gps = new AltosGPS();
249 gps.nsat = parse_int(words[i++]);
250 word(words[i++], "sat");
252 gps.gps_connected = 0;
254 gps.lat = gps.lon = 0;
256 if ((words[i]).equals("unlocked")) {
257 gps.gps_connected = 1;
258 gps.gps_time = new AltosGPSTime();
260 } else if (words.length >= 40) {
262 gps.gps_connected = 1;
264 gps.gps_time = new AltosGPSTime(words[i], words[i+1]); i += 2;
265 gps.lat = parse_coord(words[i++]);
266 gps.lon = parse_coord(words[i++]);
267 gps.alt = parse_int(strip_suffix(words[i++], "m"));
268 gps.ground_speed = parse_double(strip_suffix(words[i++], "m/s(H)"));
269 gps.course = parse_int(strip_suffix(words[i++], "°"));
270 gps.climb_rate = parse_double(strip_suffix(words[i++], "m/s(V)"));
271 gps.hdop = parse_double(strip_suffix(words[i++], "(hdop)"));
272 gps.h_error = parse_int(strip_suffix(words[i++], "(herr)"));
273 gps.v_error = parse_int(strip_suffix(words[i++], "(verr)"));
275 gps.gps_time = new AltosGPSTime();
277 word(words[i++], "SAT");
278 gps_tracking = new AltosGPSTracking();
279 gps_tracking.channels = parse_int(words[i++]);
280 gps_tracking.cc_gps_sat = new AltosGPSSat[gps_tracking.channels];
281 for (int chan = 0; chan < gps_tracking.channels; chan++) {
282 gps_tracking.cc_gps_sat[chan] = new AltosGPSSat();
283 gps_tracking.cc_gps_sat[chan].svid = parse_int(words[i++]);
284 gps_tracking.cc_gps_sat[chan].c_n0 = parse_int(words[i++]);