altosdroid: start restoring from log data on startup
authorKeith Packard <keithp@keithp.com>
Fri, 29 Aug 2014 20:22:43 +0000 (15:22 -0500)
committerKeith Packard <keithp@keithp.com>
Fri, 29 Aug 2014 20:22:43 +0000 (15:22 -0500)
Remember which flight was last being received and reload that file

Signed-off-by: Keith Packard <keithp@keithp.com>
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
altoslib/AltosFlightReader.java
altoslib/AltosLog.java
altoslib/AltosPreferences.java
altoslib/AltosReplayReader.java
altoslib/AltosStateIterable.java
altoslib/AltosTelemetryReader.java

index c9c38d9819a6e7ac798d3a12a800fdcf93dfe300..c94f36fda0d82a233f599d1212b2950e13fa8e55 100644 (file)
@@ -101,9 +101,6 @@ public class AltosDroid extends FragmentActivity {
        private Messenger mService = null;
        final Messenger mMessenger = new Messenger(new IncomingHandler(this));
 
-       // Preferences
-       private AltosDroidPreferences prefs = null;
-
        // TeleBT Config data
        private AltosConfigData mConfigData = null;
        // Local Bluetooth adapter
@@ -343,8 +340,7 @@ public class AltosDroid extends FragmentActivity {
                }
 
                // Initialise preferences
-               prefs = new AltosDroidPreferences(this);
-               AltosPreferences.init(prefs);
+               AltosDroidPreferences.init(this);
 
                // Set up the window layout
                requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
@@ -480,9 +476,7 @@ public class AltosDroid extends FragmentActivity {
                }
        }
 
-       private void connectDevice(Intent data) {
-               // Get the device MAC address
-               String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
+       private void connectDevice(String address) {
                // Get the BLuetoothDevice object
                BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
                // Attempt to connect to the device
@@ -493,6 +487,12 @@ public class AltosDroid extends FragmentActivity {
                }
        }
 
+       private void connectDevice(Intent data) {
+               // Get the device MAC address
+               String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
+               connectDevice(address);
+       }
+
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
                MenuInflater inflater = getMenuInflater();
index 70d7def828706a972211872d4f82cb80e6d20cc9..7c12c9a0972d7b8453a6203a50dc3d36da22c12c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
  *
  * 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
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
-
 package org.altusmetrum.AltosDroid;
 
-import java.io.File;
-import java.util.Map;
 import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Environment;
-
 import org.altusmetrum.altoslib_5.*;
 
-public class AltosDroidPreferences implements AltosPreferencesBackend {
-       public final static String        NAME    = "org.altusmetrum.AltosDroid";
-       private Context                   context = null;
-       private SharedPreferences         prefs   = null;
-       private SharedPreferences.Editor  editor  = null;
+public class AltosDroidPreferences extends AltosPreferences {
 
-       public AltosDroidPreferences(Context in_context) {
-               this(in_context, NAME);
-       }
+       /* Active device preference name */
+       final static String activeDevicePreference = "ACTIVE-DEVICE";
 
-       public AltosDroidPreferences(Context in_context, String in_prefs) {
-               context = in_context;
-               prefs   = context.getSharedPreferences(in_prefs, 0);
-               editor  = prefs.edit();
-       }
+       static String active_device_address;
 
-       public String[] keys() {
-               Map<String, ?> all = prefs.getAll();
-               return (String[])all.keySet().toArray();
-       }
-
-       public AltosPreferencesBackend node(String key) {
-               return new AltosDroidPreferences(context, key);
-       }
-
-       public boolean nodeExists(String key) {
-               return prefs.contains(key);
-       }
-
-       public boolean getBoolean(String key, boolean def) {
-               return prefs.getBoolean(key, def);
-       }
-
-       public double getDouble(String key, double def) {
-               Float f = Float.valueOf(prefs.getFloat(key, (float)def));
-               return f.doubleValue();
-       }
-
-       public int getInt(String key, int def) {
-               return prefs.getInt(key, def);
-       }
-
-       public String getString(String key, String def) {
-               return prefs.getString(key, def);
-       }
-
-       public void putBoolean(String key, boolean value) {
-               editor.putBoolean(key, value);
-       }
-
-       public void putDouble(String key, double value) {
-               editor.putFloat(key, (float)value);
-       }
-
-       public void putInt(String key, int value) {
-               editor.putInt(key, value);
-       }
-
-       public void putString(String key, String value) {
-               editor.putString(key, value);
-       }
+       public static void init(Context context) {
+               AltosPreferences.init(new AltosDroidPreferencesBackend(context));
 
-       public void remove(String key) {
-               editor.remove(key);
+               active_device_address = backend.getGetString(activeDevicePreference, null);
        }
 
-       public void flush() {
-               editor.apply();
+       public static void set_active_device(String address) {
+               synchronized(backend) {
+                       active_device_address = address;
+                       backend.putString(activeDevicePreference, active_device_address);
+                       flush_preferences();
+               }
        }
 
-       public File homeDirectory() {
-               return Environment.getExternalStorageDirectory();
+       public static String active_device() {
+               synchronized(backend) {
+                       return active_device_address;
+               }
        }
 }
index c0565e8898d926a6320f43a1191d1d575aa8a019..be103838a2ccd683df7dd48f47c1d9a91a142b9d 100644 (file)
@@ -21,16 +21,16 @@ import java.text.*;
 import java.io.*;
 import java.util.concurrent.*;
 
-public class AltosFlightReader {
+public abstract class AltosFlightReader {
        public String name;
 
        public int serial;
 
-       public void init() { }
+       public void init() {}
 
-       public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; }
+       public abstract AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException;
 
-       public void close(boolean interrupted) { }
+       public abstract void close(boolean interrupted);
 
        public void set_frequency(double frequency) throws InterruptedException, TimeoutException { }
 
index 1cac6b5205a1b6c731b42447a2ef132919114018..28116e3dcdb801a062199a8c7c8f070b1a72b1f8 100644 (file)
@@ -72,6 +72,7 @@ public class AltosLog implements Runnable {
                        }
                        log_file.flush();
                        file = a;
+                       AltosPreferences.set_logfile(link.serial, file);
                }
                return log_file != null;
        }
index 72cfeb4bc5a47e81c63c2ba0582e0de3438b5263..0e91e4f475d5673bd4a21ef667d5147d7a84ddda 100644 (file)
@@ -38,6 +38,9 @@ public class AltosPreferences {
        /* telemetry rate format preference name */
        public final static String telemetryRatePreferenceFormat = "RATE-%d";
 
+       /* log file format preference name */
+       public final static String logfilePreferenceFormat = "LOGFILE-%d";
+
        /* voice preference name */
        public final static String voicePreference = "VOICE";
 
@@ -83,6 +86,9 @@ public class AltosPreferences {
        /* Telemetry rate (map serial to telemetry format) */
        public static Hashtable<Integer, Integer> telemetry_rates;
 
+       /* Log file (map serial to logfile name) */
+       public static Hashtable<Integer, File> logfiles;
+
        /* Voice preference */
        public static boolean voice;
 
@@ -300,6 +306,27 @@ public class AltosPreferences {
                }
        }
 
+       public static void set_logfile(int serial, File new_logfile) {
+               synchronized(backend) {
+                       logfiles.put(serial, new_logfile);
+                       backend.putString(String.format(logfilePreferenceFormat, serial), new_logfile.getPath());
+                       flush_preferences();
+               }
+       }
+
+       public static File logfile(int serial) {
+               synchronized(backend) {
+                       if (logfiles.containsKey(serial))
+                               return logfiles.get(serial);
+                       String logfile_string = backend.getString(String.format(logfilePreferenceFormat, serial), null);
+                       if (logfile_string == null)
+                               return null;
+                       File logfile = new File(logfile_string);
+                       logfiles.put(serial, logfile);
+                       return logfile;
+               }
+       }
+
        public static void set_scanning_telemetry(int new_scanning_telemetry) {
                synchronized (backend) {
                        scanning_telemetry = new_scanning_telemetry;
index 15093af18410a1180e4c8c3bf8a66dee5718ba4d..2864e02a272bb0ba60f27407b0fdf03d27803c0d 100644 (file)
@@ -27,6 +27,7 @@ import java.util.*;
 public class AltosReplayReader extends AltosFlightReader {
        Iterator<AltosState>    iterator;
        File    file;
+       boolean real_time;
 
        public AltosState read() {
                if (iterator.hasNext())
@@ -39,16 +40,22 @@ public class AltosReplayReader extends AltosFlightReader {
 
        public void update(AltosState state) throws InterruptedException {
                /* Make it run in realtime after the rocket leaves the pad */
-               if (state.state > AltosLib.ao_flight_pad && state.time_change > 0)
+               if (real_time && state.state > AltosLib.ao_flight_pad && state.time_change > 0)
                        Thread.sleep((int) (Math.min(state.time_change,10) * 1000));
                state.set_received_time(System.currentTimeMillis());
        }
 
        public File backing_file() { return file; }
 
-       public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) {
+       public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file,
+                                boolean in_real_time) {
                iterator = in_iterator;
                file = in_file;
+               real_time = in_real_time;
                name = file.getName();
        }
+
+       public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) {
+               this(in_iterator, in_file, false);
+       }
 }
index f7cd424d554a82422b8f403775f178ad717e3b84..4154b71ceec90a8d77473e0432977b0c47ae6f32 100644 (file)
@@ -26,4 +26,18 @@ public abstract class AltosStateIterable implements Iterable<AltosState> {
        }
 
        public abstract void write(PrintStream out);
+
+       public static AltosStateIterable iterable(File file) {
+               FileInputStream in;
+               try {
+                       in = new FileInputStream(file);
+               } catch (Exception e) {
+                       System.out.printf("Failed to open file '%s'\n", file);
+                       return null;
+               }
+               if (file.getName().endsWith("telem"))
+                       return new AltosTelemetryFile(in);
+               else
+                       return new AltosEepromFile(in);
+       }
 }
index 5ed501348b07174bb0debee09d499ada26bffb56..8803e19f74087b528fdc0281877d03bb85a00ec9 100644 (file)
@@ -28,10 +28,17 @@ public class AltosTelemetryReader extends AltosFlightReader {
        int             telemetry;
        int             telemetry_rate;
        AltosState      state = null;
+       AltosFlightReader       stacked;
 
        LinkedBlockingQueue<AltosLine> telem;
 
        public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException {
+               if (stacked != null) {
+                       state = stacked.read();
+                       if (state != null)
+                               return state;
+                       stacked = null;
+               }
                AltosLine l = telem.take();
                if (l.line == null)
                        throw new IOException("IO error");
@@ -53,6 +60,12 @@ public class AltosTelemetryReader extends AltosFlightReader {
        }
 
        public void close(boolean interrupted) {
+
+               if (stacked != null) {
+                       stacked.close(interrupted);
+                       stacked = null;
+               }
+
                link.remove_monitor(telem);
                log.close();
                try {
@@ -148,9 +161,10 @@ public class AltosTelemetryReader extends AltosFlightReader {
                return link.monitor_battery();
        }
 
-       public AltosTelemetryReader (AltosLink in_link)
+       public AltosTelemetryReader (AltosLink in_link, AltosFlightReader in_stacked)
                throws IOException, InterruptedException, TimeoutException {
                link = in_link;
+               stacked = in_stacked;
                boolean success = false;
                try {
                        log = new AltosLog(link);
@@ -169,4 +183,19 @@ public class AltosTelemetryReader extends AltosFlightReader {
                                close(true);
                }
        }
+
+       private static AltosFlightReader existing_data(AltosLink link) {
+               File    file = AltosPreferences.logfile(link.serial);
+               if (file != null) {
+                       AltosStateIterable      iterable = AltosStateIterable.iterable(file);
+                       if (iterable != null)
+                               return new AltosReplayReader(iterable.iterator(), file, false);
+               }
+               return null;
+       }
+
+       public AltosTelemetryReader(AltosLink link)
+               throws IOException, InterruptedException, TimeoutException {
+               this(link, existing_data(link));
+       }
 }