altosdroid: Add quit. Restart. Show freq in title.
authorKeith Packard <keithp@keithp.com>
Sun, 31 Aug 2014 05:08:33 +0000 (00:08 -0500)
committerKeith Packard <keithp@keithp.com>
Sun, 31 Aug 2014 05:08:33 +0000 (00:08 -0500)
Add a quit button to menu.
When restarting, reconnect to previous device.
When connecting, set the freq/rate to previous values.

Signed-off-by: Keith Packard <keithp@keithp.com>
altosdroid/res/layout/device_list.xml
altosdroid/res/menu/option_menu.xml
altosdroid/res/values/strings.xml
altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/src/org/altusmetrum/AltosDroid/GoNoGoLights.java
altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java
altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java

index 395695f82e16d48334783bc5a7d41ed2d9a2fd75..93d655172d608655323207004068f85d59b49626 100644 (file)
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     >
-    <TextView android:id="@+id/title_paired_devices"
+    <Button android:id="@+id/button_scan"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="@string/title_paired_devices"
+        android:text="@string/button_scan"
+    />
+    <TextView android:id="@+id/title_new_devices"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/title_other_devices"
         android:visibility="gone"
         android:background="#666"
         android:textColor="#fff"
         android:paddingLeft="5dp"
     />
-    <ListView android:id="@+id/paired_devices"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:stackFromBottom="true"
-        android:layout_weight="1"
-    />
-    <TextView android:id="@+id/title_new_devices"
+    <TextView android:id="@+id/title_paired_devices"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="@string/title_other_devices"
+        android:text="@string/title_paired_devices"
         android:visibility="gone"
         android:background="#666"
         android:textColor="#fff"
         android:paddingLeft="5dp"
     />
-    <ListView android:id="@+id/new_devices"
+    <ListView android:id="@+id/paired_devices"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:stackFromBottom="true"
-        android:layout_weight="2"
+        android:layout_weight="1"
     />
-    <Button android:id="@+id/button_scan"
+    <ListView android:id="@+id/new_devices"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="@string/button_scan"
+        android:stackFromBottom="true"
+        android:layout_weight="2"
     />
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
index ee9d475f88029931288eab3a5b370df2390fba71..4321d6e74d469872dcde4be0ff15b1cb0413bfa4 100644 (file)
@@ -17,6 +17,9 @@
     <item android:id="@+id/connect_scan"
           android:icon="@android:drawable/ic_menu_search"
           android:title="@string/connect_device" />
+    <item android:id="@+id/quit"
+          android:icon="@android:drawable/ic_menu_close_clear_cancel"
+          android:title="@string/quit" />
     <item android:id="@+id/select_freq"
           android:icon="@android:drawable/ic_menu_preferences"
           android:title="@string/select_freq" />
index ce335b76be47e9751ec108d3c1af60018e09716f..0384b9b8e12e59e1cb92b4a6a6e751ef36b28099 100644 (file)
@@ -27,6 +27,7 @@
 
        <!-- Options Menu -->
        <string name="connect_device">Connect a device</string>
+       <string name="quit">Quit</string>
        <string name="select_freq">Select radio frequency</string>
        <string name="select_rate">Select data rate</string>
 
index 484efaf833a6ee4ad2e41ddc13e771d60473e82f..4a1fc3716c9320d6cbf8bca44990832d1edce89c 100644 (file)
@@ -52,6 +52,7 @@ public class AltosBluetooth extends AltosLink {
 
        // Constructor
        public AltosBluetooth(BluetoothDevice in_device, Handler in_handler) {
+//             set_debug(D);
                adapter = BluetoothAdapter.getDefaultAdapter();
                device = in_device;
                handler = in_handler;
@@ -136,6 +137,22 @@ public class AltosBluetooth extends AltosLink {
                }
        }
 
+       public double frequency() {
+               return frequency;
+       }
+
+       public int telemetry_rate() {
+               return telemetry_rate;
+       }
+
+       public void save_frequency() {
+               AltosPreferences.set_frequency(serial, frequency);
+       }
+
+       public void save_telemetry_rate() {
+               AltosPreferences.set_telemetry_rate(serial, telemetry_rate);
+       }
+
        private synchronized void wait_connected() throws InterruptedException, IOException {
                if (input == null) {
                        wait();
index c94f36fda0d82a233f599d1212b2950e13fa8e55..db1ca6916c643fc448ad69639e860fdf8e0f058c 100644 (file)
@@ -44,8 +44,10 @@ import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.Window;
+import android.view.View;
 import android.widget.TabHost;
 import android.widget.TextView;
+import android.widget.RelativeLayout;
 import android.widget.Toast;
 import android.app.AlertDialog;
 import android.location.Location;
@@ -63,6 +65,8 @@ public class AltosDroid extends FragmentActivity {
        public static final int MSG_UPDATE_AGE      = 3;
        public static final int MSG_LOCATION        = 4;
        public static final int MSG_CRC_ERROR       = 5;
+       public static final int MSG_FREQUENCY       = 6;
+       public static final int MSG_TELEMETRY_RATE  = 7;
 
        // Intent request codes
        private static final int REQUEST_CONNECT_DEVICE = 1;
@@ -78,12 +82,16 @@ public class AltosDroid extends FragmentActivity {
        private TextView mRSSIView;
        private TextView mSerialView;
        private TextView mFlightView;
+       private RelativeLayout mStateLayout;
        private TextView mStateView;
        private TextView mAgeView;
 
        // field to display the version at the bottom of the screen
        private TextView mVersion;
 
+       private double frequency;
+       private int telemetry_rate;
+
        // Tabs
        TabHost         mTabHost;
        AltosViewPager  mViewPager;
@@ -122,11 +130,7 @@ public class AltosDroid extends FragmentActivity {
                                if(D) Log.d(TAG, "MSG_STATE_CHANGE: " + msg.arg1);
                                switch (msg.arg1) {
                                case TelemetryService.STATE_CONNECTED:
-                                       ad.mConfigData = (AltosConfigData) msg.obj;
-                                       String str = String.format(" %s S/N: %d", ad.mConfigData.product, ad.mConfigData.serial);
-                                       ad.mTitle.setText(R.string.title_connected_to);
-                                       ad.mTitle.append(str);
-                                       Toast.makeText(ad.getApplicationContext(), "Connected to " + str, Toast.LENGTH_SHORT).show();
+                                       ad.set_config_data((AltosConfigData) msg.obj);
                                        break;
                                case TelemetryService.STATE_CONNECTING:
                                        ad.mTitle.setText(R.string.title_connecting);
@@ -135,6 +139,9 @@ public class AltosDroid extends FragmentActivity {
                                case TelemetryService.STATE_NONE:
                                        ad.mConfigData = null;
                                        ad.mTitle.setText(R.string.title_not_connected);
+                                       String  active_device = AltosDroidPreferences.active_device();
+                                       if (active_device != null)
+                                               ad.connectDevice(active_device);
                                        break;
                                }
                                break;
@@ -151,6 +158,12 @@ public class AltosDroid extends FragmentActivity {
                                        ad.mAgeView.setText(String.format("%d", (System.currentTimeMillis() - ad.saved_state.received_time + 500) / 1000));
                                }
                                break;
+                       case MSG_FREQUENCY:
+                               ad.set_frequency((Double) msg.obj);
+                               break;
+                       case MSG_TELEMETRY_RATE:
+                               ad.set_telemetry_rate((Integer) msg.obj);
+                               break;
                        }
                }
        };
@@ -211,6 +224,33 @@ public class AltosDroid extends FragmentActivity {
                update_ui(saved_state);
        }
 
+       void set_title() {
+               if (mConfigData != null) {
+                       String str = String.format("S/N %d %6.3f MHz", mConfigData.serial, frequency);
+
+                       if (telemetry_rate != AltosLib.ao_telemetry_rate_38400)
+                               str = str.concat(String.format(" %d bps", AltosLib.ao_telemetry_rate_values[telemetry_rate]));
+                       mTitle.setText(str);
+               }
+       }
+
+       void set_frequency(double frequency) {
+               if (D) Log.d(TAG, String.format("AltosDroid: set_frequency %f\n", frequency));
+               this.frequency = frequency;
+               set_title();
+       }
+
+       void set_telemetry_rate(int telemetry_rate) {
+               if (D) Log.d(TAG, String.format("AltosDroid: set_telemetry_rate %d\n", telemetry_rate));
+               this.telemetry_rate = telemetry_rate;
+               set_title();
+       }
+
+       void set_config_data(AltosConfigData config_data) {
+               mConfigData = config_data;
+               set_title();
+       }
+
        boolean same_string(String a, String b) {
                if (a == null) {
                        if (b == null)
@@ -226,8 +266,15 @@ public class AltosDroid extends FragmentActivity {
        void update_ui(AltosState state) {
 
                Log.d(TAG, "update_ui");
-               if (state != null && saved_state != null) {
-                       if (saved_state.state != state.state) {
+
+               int prev_state = AltosLib.ao_flight_invalid;
+
+               if (saved_state != null)
+                       prev_state = saved_state.state;
+
+               if (state != null) {
+                       Log.d(TAG, String.format("prev state %d new state  %d\n", prev_state, state.state));
+                       if (prev_state != state.state) {
                                String currentTab = mTabHost.getCurrentTabTag();
                                Log.d(TAG, "switch state");
                                switch (state.state) {
@@ -240,6 +287,9 @@ public class AltosDroid extends FragmentActivity {
                                case AltosLib.ao_flight_landed:
                                        if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("landed");
                                        break;
+                               case AltosLib.ao_flight_stateless:
+                                       if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("descent");
+                                       break;
                                }
                        }
                }
@@ -273,7 +323,12 @@ public class AltosDroid extends FragmentActivity {
                        }
                        if (saved_state == null || state.state != saved_state.state) {
                                Log.d(TAG, "update state");
-                               mStateView.setText(state.state_name());
+                               if (state.state == AltosLib.ao_flight_stateless) {
+                                       mStateLayout.setVisibility(View.GONE);
+                               } else {
+                                       mStateView.setText(state.state_name());
+                                       mStateLayout.setVisibility(View.VISIBLE);
+                               }
                        }
                        if (saved_state == null || state.rssi != saved_state.rssi) {
                                Log.d(TAG, "update rssi");
@@ -399,6 +454,7 @@ public class AltosDroid extends FragmentActivity {
                mRSSIView      = (TextView) findViewById(R.id.rssi_value);
                mSerialView    = (TextView) findViewById(R.id.serial_value);
                mFlightView    = (TextView) findViewById(R.id.flight_value);
+               mStateLayout   = (RelativeLayout) findViewById(R.id.state_container);
                mStateView     = (TextView) findViewById(R.id.state_value);
                mAgeView       = (TextView) findViewById(R.id.age_value);
 
@@ -421,6 +477,7 @@ public class AltosDroid extends FragmentActivity {
                startService(new Intent(AltosDroid.this, TelemetryService.class));
 
                doBindService();
+
        }
 
        @Override
@@ -490,6 +547,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);
+               AltosDroidPreferences.set_active_device(address);
                connectDevice(address);
        }
 
@@ -550,6 +608,11 @@ public class AltosDroid extends FragmentActivity {
                        serverIntent = new Intent(this, DeviceListActivity.class);
                        startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
                        return true;
+               case R.id.quit:
+                       Log.d(TAG, "R.id.quit");
+                       stopService(new Intent(AltosDroid.this, TelemetryService.class));
+                       finish();
+                       return true;
                case R.id.select_freq:
                        // Set the TBT radio frequency
 
index 8e8d9c03a32c9105f0d6553b461a107d773a785e..267c90f8e57cc2f0df621f82959e5b9a344a4573 100644 (file)
@@ -20,6 +20,7 @@ package org.altusmetrum.AltosDroid;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.widget.ImageView;
+import android.view.View;
 
 public class GoNoGoLights {
        private Boolean state;
@@ -51,14 +52,27 @@ public class GoNoGoLights {
                missing = m;
                set = true;
                if (missing) {
+                       hide();
                        red.setImageDrawable(dGray);
                        green.setImageDrawable(dGray);
                } else if (state) {
                        red.setImageDrawable(dGray);
                        green.setImageDrawable(dGreen);
+                       show();
                } else {
                        red.setImageDrawable(dRed);
                        green.setImageDrawable(dGray);
+                       show();
                }
        }
+
+       public void show() {
+               red.setVisibility(View.VISIBLE);
+               green.setVisibility(View.VISIBLE);
+       }
+
+       public void hide() {
+               red.setVisibility(View.GONE);
+               green.setVisibility(View.GONE);
+       }
 }
index 16427d8b19204f9d3445007e9504441929472475..32c235e1b627dfbb0a2dbc48f94034cf2b94550c 100644 (file)
@@ -92,7 +92,10 @@ public class TabLanded extends AltosDroidTab {
 
                if (state != null) {
                        mMaxHeightView.setText(String.format("%6.0f m", state.max_height()));
-                       mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration()));
+                       if (state.max_acceleration() != AltosLib.MISSING)
+                               mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration()));
+                       else
+                               mMaxAccelView.setText("missing");
                        mMaxSpeedView.setText(String.format("%6.0f m/s", state.max_speed()));
                }
        }
index 03b78b75dbf29a0cfa9e24b766358bee9d388853..1068fa46f63ed11fa3fd803429054a81470f3d2e 100644 (file)
@@ -33,10 +33,13 @@ public class TabPad extends AltosDroidTab {
        AltosDroid mAltosDroid;
 
        private TextView mBatteryVoltageView;
+       private TextView mBatteryVoltageLabel;
        private GoNoGoLights mBatteryLights;
        private TextView mApogeeVoltageView;
+       private TextView mApogeeVoltageLabel;
        private GoNoGoLights mApogeeLights;
        private TextView mMainVoltageView;
+       private TextView mMainVoltageLabel;
        private GoNoGoLights mMainLights;
        private TextView mDataLoggingView;
        private GoNoGoLights mDataLoggingLights;
@@ -59,16 +62,19 @@ public class TabPad extends AltosDroidTab {
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                View v = inflater.inflate(R.layout.tab_pad, container, false);
                mBatteryVoltageView = (TextView) v.findViewById(R.id.battery_voltage_value);
+               mBatteryVoltageLabel = (TextView) v.findViewById(R.id.battery_voltage_label);
                mBatteryLights = new GoNoGoLights((ImageView) v.findViewById(R.id.battery_redled),
                                                  (ImageView) v.findViewById(R.id.battery_greenled),
                                                  getResources());
 
                mApogeeVoltageView = (TextView) v.findViewById(R.id.apogee_voltage_value);
+               mApogeeVoltageLabel = (TextView) v.findViewById(R.id.apogee_voltage_label);
                mApogeeLights = new GoNoGoLights((ImageView) v.findViewById(R.id.apogee_redled),
                                                 (ImageView) v.findViewById(R.id.apogee_greenled),
                                                 getResources());
 
                mMainVoltageView = (TextView) v.findViewById(R.id.main_voltage_value);
+               mMainVoltageLabel = (TextView) v.findViewById(R.id.main_voltage_label);
                mMainLights = new GoNoGoLights((ImageView) v.findViewById(R.id.main_redled),
                                               (ImageView) v.findViewById(R.id.main_greenled),
                                               getResources());
@@ -107,11 +113,23 @@ public class TabPad extends AltosDroidTab {
                if (state != null) {
                        mBatteryVoltageView.setText(AltosDroid.number("%4.2f V", state.battery_voltage));
                        mBatteryLights.set(state.battery_voltage >= AltosLib.ao_battery_good, state.battery_voltage == AltosLib.MISSING);
-
-                       mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
+                       if (state.apogee_voltage == AltosLib.MISSING) {
+                               mApogeeVoltageView.setVisibility(View.GONE);
+                               mApogeeVoltageLabel.setVisibility(View.GONE);
+                       } else {
+                               mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
+                               mApogeeVoltageView.setVisibility(View.VISIBLE);
+                               mApogeeVoltageLabel.setVisibility(View.VISIBLE);
+                       }
                        mApogeeLights.set(state.apogee_voltage >= AltosLib.ao_igniter_good, state.apogee_voltage == AltosLib.MISSING);
-
-                       mMainVoltageView.setText(AltosDroid.number("%4.2f V", state.main_voltage));
+                       if (state.main_voltage == AltosLib.MISSING) {
+                               mMainVoltageView.setVisibility(View.GONE);
+                               mMainVoltageLabel.setVisibility(View.GONE);
+                       } else {
+                               mMainVoltageView.setText(AltosDroid.number("%4.2f V", state.main_voltage));
+                               mMainVoltageView.setVisibility(View.VISIBLE);
+                               mMainVoltageLabel.setVisibility(View.VISIBLE);
+                       }
                        mMainLights.set(state.main_voltage >= AltosLib.ao_igniter_good, state.main_voltage == AltosLib.MISSING);
 
                        if (state.flight != 0) {
index 3ba5afa9a25aa0b3055b2bca87c0224e75952df2..0c437f87a7fd3f20513b2dfb9bb197e75622c04c 100644 (file)
@@ -66,7 +66,7 @@ public class TelemetryReader extends Thread {
                AltosState  state = null;
 
                try {
-                       for (;;) {
+                       while (telemQueue != null) {
                                try {
                                        state = read();
                                        handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget();
@@ -91,5 +91,14 @@ public class TelemetryReader extends Thread {
                state = null;
                telemQueue = new LinkedBlockingQueue<AltosLine>();
                link.add_monitor(telemQueue);
+               try {
+                       link.set_radio_frequency(AltosPreferences.frequency(link.serial));
+                       link.set_telemetry(AltosLib.ao_telemetry_standard);
+                       link.set_telemetry_rate(AltosPreferences.telemetry_rate(link.serial));
+               } catch (InterruptedException ee) {
+                       close();
+               } catch (TimeoutException te) {
+                       close();
+               }
        }
 }
index 4ec353e30e88ff2d298b8bea8cb7005607061699..8e5c7903149c6648ef016ad953d4f878c3ab378b 100644 (file)
@@ -115,6 +115,10 @@ public class TelemetryService extends Service implements LocationListener {
                                        if (s.last_state      != null) msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_TELEMETRY, s.last_state     ));
                                        if (s.last_location   != null) msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_LOCATION , s.last_location  ));
                                        if (s.last_crc_errors != 0   ) msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_CRC_ERROR, s.last_crc_errors));
+                                       if (s.state == STATE_CONNECTED) {
+                                               msg.replyTo.send(s.frequency_message());
+                                               msg.replyTo.send(s.telemetry_rate_message());
+                                       }
                                } catch (RemoteException e) {
                                        s.mClients.remove(msg.replyTo);
                                }
@@ -131,13 +135,17 @@ public class TelemetryService extends Service implements LocationListener {
                                break;
                        case MSG_CONNECTED:
                                if (D) Log.d(TAG, "Connected to device");
-                               s.connected();
+                               try {
+                                       s.connected();
+                               } catch (InterruptedException ie) {
+                               }
                                break;
                        case MSG_CONNECT_FAILED:
                                if (D) Log.d(TAG, "Connection failed... retrying");
                                s.startAltosBluetooth();
                                break;
                        case MSG_DISCONNECTED:
+                               Log.d(TAG, "MSG_DISCONNECTED");
                                // Only do the following if we haven't been shutdown elsewhere..
                                if (s.device != null) {
                                        if (D) Log.d(TAG, "Disconnected from " + s.device.getName());
@@ -158,6 +166,8 @@ public class TelemetryService extends Service implements LocationListener {
                                if (s.state == STATE_CONNECTED) {
                                        try {
                                                s.mAltosBluetooth.set_radio_frequency((Double) msg.obj);
+                                               s.mAltosBluetooth.save_frequency();
+                                               s.sendMessageToClients(s.frequency_message());
                                        } catch (InterruptedException e) {
                                        } catch (TimeoutException e) {
                                        }
@@ -166,6 +176,8 @@ public class TelemetryService extends Service implements LocationListener {
                        case MSG_SETBAUD:
                                if (s.state == STATE_CONNECTED) {
                                        s.mAltosBluetooth.set_telemetry_rate((Integer) msg.obj);
+                                       s.mAltosBluetooth.save_telemetry_rate();
+                                       s.sendMessageToClients(s.telemetry_rate_message());
                                }
                                break;
                        default:
@@ -184,6 +196,16 @@ public class TelemetryService extends Service implements LocationListener {
                }
        }
 
+       private Message frequency_message() {
+               if (D) Log.d(TAG, String.format("frequency_message %f\n", mAltosBluetooth.frequency()));
+               return Message.obtain(null, AltosDroid.MSG_FREQUENCY, mAltosBluetooth.frequency());
+       }
+
+       private Message telemetry_rate_message() {
+               if (D) Log.d(TAG, String.format("telemetry_rate_message %d\n", mAltosBluetooth.telemetry_rate()));
+               return Message.obtain(null, AltosDroid.MSG_TELEMETRY_RATE, mAltosBluetooth.telemetry_rate());
+       }
+
        private void stopAltosBluetooth() {
                if (D) Log.d(TAG, "stopAltosBluetooth(): begin");
                setState(STATE_READY);
@@ -241,12 +263,14 @@ public class TelemetryService extends Service implements LocationListener {
                sendMessageToClients(Message.obtain(null, AltosDroid.MSG_STATE_CHANGE, state, -1, acd));
        }
 
-       private void connected() {
+       private void connected() throws InterruptedException {
                try {
                        if (mAltosBluetooth == null)
                                throw new InterruptedException("no bluetooth");
                        mConfigData = mAltosBluetooth.config_data();
-               } catch (InterruptedException e) {
+                       if (D) Log.d(TAG, "send frequency/rate messages\n");
+                       sendMessageToClients(frequency_message());
+                       sendMessageToClients(telemetry_rate_message());
                } catch (TimeoutException e) {
                        // If this timed out, then we really want to retry it, but
                        // probably safer to just retry the connection from scratch.
@@ -258,10 +282,12 @@ public class TelemetryService extends Service implements LocationListener {
 
                mTelemetryReader = new TelemetryReader(mAltosBluetooth, mHandler);
                mTelemetryReader.start();
-               
+
                mTelemetryLogger = new TelemetryLogger(this, mAltosBluetooth);
-       }
 
+               sendMessageToClients(frequency_message());
+               sendMessageToClients(telemetry_rate_message());
+       }
 
        private void onTimerTick() {
                if (D) Log.d(TAG, "Timer wakeup");