*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_12;
import java.io.*;
import java.util.*;
import java.text.*;
import java.util.concurrent.*;
-public class AltosEepromDownload implements Runnable {
+class AltosEepromNameData extends AltosDataListener {
+ AltosGPS gps = null;
- AltosLink link;
- boolean remote;
- Thread eeprom_thread;
- AltosEepromMonitor monitor;
+ public void set_rssi(int rssi, int status) { }
+ public void set_received_time(long received_time) { }
- boolean want_file;
- FileWriter eeprom_file;
- LinkedList<String> eeprom_pending;
+ public void set_acceleration(double accel) { }
+ public void set_pressure(double pa) { }
+ public void set_thrust(double N) { }
- AltosEepromList flights;
- boolean success;
- ParseException parse_exception;
- AltosState state;
-
- private void FlushPending() throws IOException {
- for (String s : flights.config_data) {
- eeprom_file.write(s);
- eeprom_file.write('\n');
- }
+ public void set_temperature(double deg_c) { }
+ public void set_battery_voltage(double volts) { }
- for (String s : eeprom_pending)
- eeprom_file.write(s);
- }
+ public void set_apogee_voltage(double volts) { }
+ public void set_main_voltage(double volts) { }
- private void CheckFile(boolean force) throws IOException {
- if (eeprom_file != null)
- return;
- if (force || (state.flight != 0 && want_file)) {
- AltosFile eeprom_name;
- AltosGPS gps = state.gps;
-
- if (gps != null &&
- gps.year != AltosLib.MISSING &&
- gps.month != AltosLib.MISSING &&
- gps.day != AltosLib.MISSING)
- {
- eeprom_name = new AltosFile(gps.year, gps.month, gps.day,
- state.serial, state.flight, "eeprom");
- } else
- eeprom_name = new AltosFile(state.serial, state.flight, "eeprom");
-
- eeprom_file = new FileWriter(eeprom_name);
- if (eeprom_file != null) {
- monitor.set_filename(eeprom_name.getName());
- FlushPending();
- eeprom_pending = null;
- }
+ public void set_gps(AltosGPS gps) {
+ if (gps != null &&
+ gps.year != AltosLib.MISSING &&
+ gps.month != AltosLib.MISSING &&
+ gps.day != AltosLib.MISSING) {
+ this.gps = gps;
}
}
- boolean done;
- boolean start;
+ public boolean done() {
+ if (gps == null)
+ return false;
+ return true;
+ }
- void LogEeprom(AltosEeprom r) throws IOException {
- if (r.cmd != AltosLib.AO_LOG_INVALID) {
- String line = r.string();
- if (eeprom_file != null)
- eeprom_file.write(line);
- else
- eeprom_pending.add(line);
- }
+ public void set_gyro(double roll, double pitch, double yaw) { }
+ public void set_accel_ground(double along, double across, double through) { }
+ public void set_accel(double along, double across, double through) { }
+ public void set_mag(double along, double across, double through) { }
+ public void set_pyro_voltage(double volts) { }
+ public void set_igniter_voltage(double[] voltage) { }
+ public void set_pyro_fired(int pyro_mask) { }
+ public void set_companion(AltosCompanion companion) { }
+ public void set_kalman(double height, double speed, double acceleration) { }
+ public void set_orient(double new_orient) { }
+
+ public AltosEepromNameData(AltosCalData cal_data) {
+ super(cal_data);
}
+}
- void CaptureEeprom(AltosEepromChunk eechunk, int log_format) throws IOException, ParseException {
- boolean any_valid = false;
- boolean got_flight = false;
+public class AltosEepromDownload implements Runnable {
- int record_length = 8;
+ AltosLink link;
+ boolean remote;
+ Thread eeprom_thread;
+ AltosEepromMonitor monitor;
- state.set_serial(flights.config_data.serial);
- monitor.set_serial(flights.config_data.serial);
+ AltosEepromList flights;
+ String parse_errors;
- for (int i = 0; i < AltosEepromChunk.chunk_size && !done; i += record_length) {
- AltosEeprom r = eechunk.eeprom(i, log_format, state);
+ private boolean has_gps_date(AltosState state) {
+ if (state == null)
+ return false;
- if (r == null)
- continue;
+ AltosGPS gps = state.gps;
- record_length = r.record_length();
+ return gps != null &&
+ gps.year != AltosLib.MISSING &&
+ gps.month != AltosLib.MISSING &&
+ gps.day != AltosLib.MISSING;
+ }
- r.update_state(state);
+ private AltosFile MakeFile(int serial, int flight, AltosEepromNameData name_data) throws IOException {
+ AltosFile eeprom_name;
- if (!got_flight && state.flight != AltosLib.MISSING)
- monitor.set_flight(state.flight);
+ if (name_data.gps != null) {
+ AltosGPS gps = name_data.gps;
+ eeprom_name = new AltosFile(gps.year, gps.month, gps.day,
+ serial, flight, "eeprom");
+ } else
+ eeprom_name = new AltosFile(serial, flight, "eeprom");
- /* Monitor state transitions to update display */
- if (state.state != AltosLib.ao_flight_invalid &&
- state.state <= AltosLib.ao_flight_landed)
- {
- if (state.state > AltosLib.ao_flight_pad)
- want_file = true;
- if (state.state == AltosLib.ao_flight_landed)
- done = true;
- }
+ return eeprom_name;
+ }
- if (state.gps != null)
- want_file = true;
+ boolean done;
+ int prev_state;
+ int state_block;
+
+ void LogError(String error) {
+ if (parse_errors != null)
+ parse_errors.concat(error.concat("\n"));
+ else
+ parse_errors = error;
+ }
- if (r.valid) {
- any_valid = true;
- LogEeprom(r);
- }
+ class BlockCache extends Hashtable<Integer,AltosEepromChunk> {
+ AltosEepromLog log;
+
+ AltosEepromChunk get(int start, boolean add) throws TimeoutException, InterruptedException {
+ if (contains(start))
+ return super.get(start);
+ AltosEepromChunk eechunk = new AltosEepromChunk(link, start, start == log.start_block);
+ if (add)
+ put(start, eechunk);
+ return eechunk;
}
- if (!any_valid)
- done = true;
- CheckFile(false);
+ public BlockCache(AltosEepromLog log) {
+ this.log = log;
+ }
+ }
+
+ int FindLastLog(AltosEepromLog log, BlockCache cache) throws TimeoutException, InterruptedException {
+ int low = log.start_block;
+ int high = log.end_block - 1;
+
+ while (low <= high) {
+ int mid = (high + low) / 2;
+
+ if (!cache.get(mid, true).erased())
+ low = mid + 1;
+ else
+ high = mid - 1;
+ }
+ return low;
}
void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException, ParseException {
int block, state_block = 0;
int log_format = flights.config_data.log_format;
-
- state = new AltosState();
+ BlockCache cache = new BlockCache(log);
done = false;
- start = true;
if (flights.config_data.serial < 0)
throw new IOException("no serial number found");
- /* Reset per-capture variables */
- want_file = false;
- eeprom_file = null;
- eeprom_pending = new LinkedList<String>();
-
/* Set serial number in the monitor dialog window */
- /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */
-
- state_block = log.start_block;
- for (block = log.start_block; !done && block < log.end_block; block++) {
- monitor.set_value(state.state_name(),
- state.state,
- block - state_block,
- block - log.start_block);
-
- AltosEepromChunk eechunk = new AltosEepromChunk(link, block, block == log.start_block);
-
- /*
- * Guess what kind of data is there if the device
- * didn't tell us
- */
-
- if (log_format == AltosLib.AO_LOG_FORMAT_UNKNOWN) {
- if (block == log.start_block) {
- if (eechunk.data(0) == AltosLib.AO_LOG_FLIGHT)
- log_format = AltosLib.AO_LOG_FORMAT_FULL;
- else
- log_format = AltosLib.AO_LOG_FORMAT_TINY;
- }
- }
+ monitor.set_serial(log.serial);
+ monitor.set_flight(log.flight);
+
+ int start_block = log.start_block;
+ int end_block = FindLastLog(log, cache);
- CaptureEeprom (eechunk, log_format);
+ monitor.set_max(end_block - start_block - 1);
+
+ ArrayList<Byte> data = new ArrayList<Byte>();
+
+ /* Now scan the eeprom, reading blocks of data to create a byte array of data */
+
+ for (block = start_block; block < end_block; block++) {
+ monitor.set_block(block - start_block);
+
+ AltosEepromChunk eechunk = cache.get(block, false);
+
+ for (int i = 0; i < eechunk.data.length; i++)
+ data.add((byte) eechunk.data[i]);
}
- CheckFile(true);
- if (eeprom_file != null) {
- eeprom_file.flush();
- eeprom_file.close();
+
+ /* Construct our internal representation of the eeprom data */
+ AltosEeprom eeprom = new AltosEeprom(flights.config_data, data);
+
+ /* Now see if we can't actually parse the resulting
+ * file to generate a better filename. Note that this
+ * doesn't need to work; we'll still save the data using
+ * a less accurate name.
+ */
+ AltosEepromRecordSet set = new AltosEepromRecordSet(eeprom);
+ AltosEepromNameData name_data = new AltosEepromNameData(set.cal_data());
+
+ for (AltosEepromRecord record : set.ordered) {
+ record.provide_data(name_data, set.cal_data());
+ if (name_data.done())
+ break;
}
+
+ AltosFile f = MakeFile(flights.config_data.serial, log.flight, name_data);
+
+ monitor.set_filename(f.toString());
+
+ FileWriter w = new FileWriter(f);
+
+ eeprom.write(w);
+ w.close();
}
public void run () {
+ boolean success = false;
+
try {
boolean failed = false;
if (remote)
link.start_remote();
for (AltosEepromLog log : flights) {
- parse_exception = null;
+ parse_errors = null;
if (log.selected) {
monitor.reset();
try {
CaptureLog(log);
} catch (ParseException e) {
- parse_exception = e;
+ LogError(e.getMessage());
}
}
- if (parse_exception != null) {
+ if (parse_errors != null) {
failed = true;
- monitor.show_message(String.format("Flight %d download error\n%s\nValid log data saved",
+ monitor.show_message(String.format("Flight %d download error. Valid log data saved\n%s",
log.flight,
- parse_exception.getMessage()),
+ parse_errors),
link.name,
AltosEepromMonitor.WARNING_MESSAGE);
}
link = given_link;
remote = given_remote;
flights = given_flights;
- success = false;
-
- monitor.set_states(AltosLib.ao_flight_boost, AltosLib.ao_flight_landed);
monitor.start();
}