+ final static String AO_TELEM_VERSION = "VERSION";
+ final static String AO_TELEM_CALL = "c";
+ final static String AO_TELEM_SERIAL = "n";
+ final static String AO_TELEM_FLIGHT = "f";
+ final static String AO_TELEM_RSSI = "r";
+ final static String AO_TELEM_STATE = "s";
+ final static String AO_TELEM_TICK = "t";
+
+ /*
+ * Raw sensor values
+ *
+ * Name Value
+ * r_a Accelerometer reading (integer)
+ * r_b Barometer reading (integer)
+ * r_t Thermometer reading (integer)
+ * r_v Battery reading (integer)
+ * r_d Drogue continuity (integer)
+ * r_m Main continuity (integer)
+ */
+
+ final static String AO_TELEM_RAW_ACCEL = "r_a";
+ final static String AO_TELEM_RAW_BARO = "r_b";
+ final static String AO_TELEM_RAW_THERMO = "r_t";
+ final static String AO_TELEM_RAW_BATT = "r_v";
+ final static String AO_TELEM_RAW_DROGUE = "r_d";
+ final static String AO_TELEM_RAW_MAIN = "r_m";
+
+ /*
+ * Sensor calibration values
+ *
+ * Name Value
+ * c_a Ground accelerometer reading (integer)
+ * c_b Ground barometer reading (integer)
+ * c_p Accelerometer reading for +1g
+ * c_m Accelerometer reading for -1g
+ */
+
+ final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a";
+ final static String AO_TELEM_CAL_BARO_GROUND = "c_b";
+ final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p";
+ final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m";
+
+ /*
+ * Kalman state values
+ *
+ * Name Value
+ * k_h Height above pad (integer, meters)
+ * k_s Vertical speeed (integer, m/s * 16)
+ * k_a Vertical acceleration (integer, m/s² * 16)
+ */
+
+ final static String AO_TELEM_KALMAN_HEIGHT = "k_h";
+ final static String AO_TELEM_KALMAN_SPEED = "k_s";
+ final static String AO_TELEM_KALMAN_ACCEL = "k_a";
+
+ /*
+ * Ad-hoc flight values
+ *
+ * Name Value
+ * a_a Acceleration (integer, sensor units)
+ * a_s Speed (integer, integrated acceleration value)
+ * a_b Barometer reading (integer, sensor units)
+ */
+
+ final static String AO_TELEM_ADHOC_ACCEL = "a_a";
+ final static String AO_TELEM_ADHOC_SPEED = "a_s";
+ final static String AO_TELEM_ADHOC_BARO = "a_b";
+
+ /*
+ * GPS values
+ *
+ * Name Value
+ * g_s GPS state (string):
+ * l locked
+ * u unlocked
+ * e error (missing or broken)
+ * g_n Number of sats used in solution
+ * g_ns Latitude (degrees * 10e7)
+ * g_ew Longitude (degrees * 10e7)
+ * g_a Altitude (integer meters)
+ * g_Y GPS year (integer)
+ * g_M GPS month (integer - 1-12)
+ * g_D GPS day (integer - 1-31)
+ * g_h GPS hour (integer - 0-23)
+ * g_m GPS minute (integer - 0-59)
+ * g_s GPS second (integer - 0-59)
+ * g_v GPS vertical speed (integer, cm/sec)
+ * g_s GPS horizontal speed (integer, cm/sec)
+ * g_c GPS course (integer, 0-359)
+ * g_hd GPS hdop (integer * 10)
+ * g_vd GPS vdop (integer * 10)
+ * g_he GPS h error (integer)
+ * g_ve GPS v error (integer)
+ */
+
+ final static String AO_TELEM_GPS_STATE = "g";
+ final static String AO_TELEM_GPS_STATE_LOCKED = "l";
+ final static String AO_TELEM_GPS_STATE_UNLOCKED = "u";
+ final static String AO_TELEM_GPS_STATE_ERROR = "e";
+ final static String AO_TELEM_GPS_NUM_SAT = "g_n";
+ final static String AO_TELEM_GPS_LATITUDE = "g_ns";
+ final static String AO_TELEM_GPS_LONGITUDE = "g_ew";
+ final static String AO_TELEM_GPS_ALTITUDE = "g_a";
+ final static String AO_TELEM_GPS_YEAR = "g_Y";
+ final static String AO_TELEM_GPS_MONTH = "g_M";
+ final static String AO_TELEM_GPS_DAY = "g_D";
+ final static String AO_TELEM_GPS_HOUR = "g_h";
+ final static String AO_TELEM_GPS_MINUTE = "g_m";
+ final static String AO_TELEM_GPS_SECOND = "g_s";
+ final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v";
+ final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g";
+ final static String AO_TELEM_GPS_COURSE = "g_c";
+ final static String AO_TELEM_GPS_HDOP = "g_hd";
+ final static String AO_TELEM_GPS_VDOP = "g_vd";
+ final static String AO_TELEM_GPS_HERROR = "g_he";
+ final static String AO_TELEM_GPS_VERROR = "g_ve";
+
+ /*
+ * GPS satellite values
+ *
+ * Name Value
+ * s_n Number of satellites reported (integer)
+ * s_v0 Space vehicle ID (integer) for report 0
+ * s_c0 C/N0 number (integer) for report 0
+ * s_v1 Space vehicle ID (integer) for report 1
+ * s_c1 C/N0 number (integer) for report 1
+ * ...
+ */
+
+ final static String AO_TELEM_SAT_NUM = "s_n";
+ final static String AO_TELEM_SAT_SVID = "s_v";
+ final static String AO_TELEM_SAT_C_N_0 = "s_c";
+
+ private void parse_v4(String[] words, int i) throws ParseException {
+ AltosTelemetryMap map = new AltosTelemetryMap(words, i);
+
+ callsign = map.get_string(AO_TELEM_CALL, "N0CALL");
+ serial = map.get_int(AO_TELEM_SERIAL, MISSING);
+ flight = map.get_int(AO_TELEM_FLIGHT, MISSING);
+ rssi = map.get_int(AO_TELEM_RSSI, MISSING);
+ state = Altos.state(map.get_string(AO_TELEM_STATE, "invalid"));
+ tick = map.get_int(AO_TELEM_TICK, 0);
+
+ /* raw sensor values */
+ accel = map.get_int(AO_TELEM_RAW_ACCEL, MISSING);
+ pres = map.get_int(AO_TELEM_RAW_BARO, MISSING);
+ temp = map.get_int(AO_TELEM_RAW_THERMO, MISSING);
+ batt = map.get_int(AO_TELEM_RAW_BATT, MISSING);
+ drogue = map.get_int(AO_TELEM_RAW_DROGUE, MISSING);
+ main = map.get_int(AO_TELEM_RAW_MAIN, MISSING);
+
+ /* sensor calibration information */
+ ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, MISSING);
+ ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, MISSING);
+ accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, MISSING);
+ accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, MISSING);
+
+ /* flight computer values */
+ acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, MISSING, 1/16.0);
+ speed = map.get_double(AO_TELEM_KALMAN_SPEED, MISSING, 1/16.0);
+ height = map.get_int(AO_TELEM_KALMAN_HEIGHT, MISSING);
+
+ flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, MISSING);
+ flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, MISSING);
+ flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, MISSING);
+
+ if (map.has(AO_TELEM_GPS_STATE))
+ gps = new AltosGPS(map);
+ else
+ gps = null;
+ }
+
+ private void parse_legacy(String[] words, int i) throws ParseException {