X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altosdroid%2Fsrc%2Forg%2Faltusmetrum%2FAltosDroid%2FAltosDroid.java;h=0776fa0027fb382270e06107657341e20935f3ed;hp=fb669c5dcbfd3d72b408ebca9a0c17ec6e7e92a2;hb=bc1cc0db1251e351d862dffbf618d0ce926c389d;hpb=ee656c9d41238ab2c56859a03fe6b8ce8ff2df4e diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index fb669c5d..0776fa00 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -3,7 +3,8 @@ * * 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 @@ -18,10 +19,9 @@ package org.altusmetrum.AltosDroid; import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Timer; -import java.util.TimerTask; import java.text.*; +import java.util.*; +import java.io.*; import android.app.Activity; import android.app.PendingIntent; @@ -46,13 +46,107 @@ import android.view.*; import android.widget.*; import android.app.AlertDialog; import android.location.Location; +import android.location.LocationManager; +import android.location.LocationListener; import android.hardware.usb.*; import android.graphics.*; import android.graphics.drawable.*; -import org.altusmetrum.altoslib_7.*; +import org.altusmetrum.altoslib_12.*; + +class SavedState { + long received_time; + int state; + boolean locked; + String callsign; + int serial; + int flight; + int rssi; + + SavedState(AltosState state) { + received_time = state.received_time; + this.state = state.state(); + if (state.gps != null) + locked = state.gps.locked; + else + locked = false; + callsign = state.cal_data().callsign; + serial = state.cal_data().serial; + flight = state.cal_data().flight; + rssi = state.rssi; + } +} + +class Tracker implements CharSequence, Comparable { + int serial; + String call; + double frequency; + + String display; + + public Tracker(int serial, String call, double frequency) { + if (call == null) + call = "none"; + + this.serial = serial; + this.call = call; + this.frequency = frequency; + if (frequency == 0.0) + display = "Auto"; + else if (frequency == AltosLib.MISSING) { + display = String.format("%-8.8s %6d", call, serial); + } else { + display = String.format("%-8.8s %7.3f %6d", call, frequency, serial); + } + } -public class AltosDroid extends FragmentActivity implements AltosUnitsListener { + public Tracker(AltosState s) { + this(s == null ? 0 : s.cal_data().serial, + s == null ? null : s.cal_data().callsign, + s == null ? 0.0 : s.frequency); + } + + /* CharSequence */ + public char charAt(int index) { + return display.charAt(index); + } + + public int length() { + return display.length(); + } + + public CharSequence subSequence(int start, int end) throws IndexOutOfBoundsException { + return display.subSequence(start, end); + } + + public String toString() { + return display.toString(); + } + + /* Comparable */ + public int compareTo (Object other) { + Tracker o = (Tracker) other; + if (frequency == 0.0) { + if (o.frequency == 0.0) + return 0; + return -1; + } + if (o.frequency == 0.0) + return 1; + + int a = serial - o.serial; + int b = call.compareTo(o.call); + int c = (int) Math.signum(frequency - o.frequency); + + if (b != 0) + return b; + if (c != 0) + return c; + return a; + } +} + +public class AltosDroid extends FragmentActivity implements AltosUnitsListener, LocationListener { // Actions sent to the telemetry server at startup time @@ -63,14 +157,26 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { public static final int MSG_STATE = 1; public static final int MSG_UPDATE_AGE = 2; + public static final int MSG_IDLE_MODE = 3; + public static final int MSG_IGNITER_STATUS = 4; // Intent request codes public static final int REQUEST_CONNECT_DEVICE = 1; public static final int REQUEST_ENABLE_BT = 2; public static final int REQUEST_PRELOAD_MAPS = 3; - public static final int REQUEST_MAP_TYPE = 4; + public static final int REQUEST_IDLE_MODE = 5; + public static final int REQUEST_IGNITERS = 6; + public static final int REQUEST_SETUP = 7; - public int map_type = AltosMap.maptype_hybrid; + public static final String EXTRA_IDLE_MODE = "idle_mode"; + public static final String EXTRA_IDLE_RESULT = "idle_result"; + public static final String EXTRA_TELEMETRY_SERVICE = "telemetry_service"; + + // Setup result bits + public static final int SETUP_BAUD = 1; + public static final int SETUP_UNITS = 2; + public static final int SETUP_MAP_SOURCE = 4; + public static final int SETUP_MAP_TYPE = 8; public static FragmentManager fm; @@ -88,11 +194,20 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { private int mAgeNewColor; private int mAgeOldColor; + public static final String tab_pad_name = "pad"; + public static final String tab_flight_name = "flight"; + public static final String tab_recover_name = "recover"; + public static final String tab_map_name = "map"; + // field to display the version at the bottom of the screen private TextView mVersion; - private double frequency; - private int telemetry_rate; + private boolean idle_mode = false; + + public Location location = null; + + private AltosState state; + private SavedState saved_state; // Tabs TabHost mTabHost; @@ -103,9 +218,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { // Timer and Saved flight state for Age calculation private Timer timer; - AltosState saved_state; + TelemetryState telemetry_state; - Integer[] serials; + Tracker[] trackers; + UsbDevice pending_usb_device; boolean start_with_usb; @@ -129,7 +245,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { switch (msg.what) { case MSG_STATE: - AltosDebug.debug("MSG_STATE"); if (msg.obj == null) { AltosDebug.debug("telemetry_state null!"); return; @@ -137,9 +252,12 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { ad.update_state((TelemetryState) msg.obj); break; case MSG_UPDATE_AGE: - AltosDebug.debug("MSG_UPDATE_AGE"); ad.update_age(); break; + case MSG_IDLE_MODE: + ad.idle_mode = (Boolean) msg.obj; + ad.update_state(null); + break; } } }; @@ -210,8 +328,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { switch (telemetry_state.connect) { case TelemetryState.CONNECT_CONNECTED: if (telemetry_state.config != null) { - String str = String.format("S/N %d %6.3f MHz", telemetry_state.config.serial, - telemetry_state.frequency); + String str = String.format("S/N %d %6.3f MHz%s", telemetry_state.config.serial, + telemetry_state.frequency, idle_mode ? " (idle)" : ""); if (telemetry_state.telemetry_rate != AltosLib.ao_telemetry_rate_38400) str = str.concat(String.format(" %d bps", AltosLib.ao_telemetry_rate_values[telemetry_state.telemetry_rate])); @@ -248,11 +366,13 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { } } + int selected_serial = 0; int current_serial; long switch_time; void set_switch_time() { switch_time = System.currentTimeMillis(); + selected_serial = 0; } boolean registered_units_listener; @@ -262,6 +382,9 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { if (new_telemetry_state != null) telemetry_state = new_telemetry_state; + if (selected_serial != 0) + current_serial = selected_serial; + if (current_serial == 0) current_serial = telemetry_state.latest_serial; @@ -270,7 +393,20 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { AltosPreferences.register_units_listener(this); } - serials = telemetry_state.states.keySet().toArray(new Integer[0]); + int num_trackers = 0; + for (AltosState s : telemetry_state.states.values()) { + num_trackers++; + } + + trackers = new Tracker[num_trackers + 1]; + + int n = 0; + trackers[n++] = new Tracker(0, "auto", 0.0); + + for (AltosState s : telemetry_state.states.values()) + trackers[n++] = new Tracker(s); + + Arrays.sort(trackers); update_title(telemetry_state); @@ -279,10 +415,12 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { if (telemetry_state.states.containsKey(current_serial)) { state = telemetry_state.states.get(current_serial); - int age = state_age(state); + int age = state_age(state.received_time); if (age < 20) aged = false; - if (switch_time != 0 && (switch_time - state.received_time) > 0) + if (current_serial == selected_serial) + aged = false; + else if (switch_time != 0 && (switch_time - state.received_time) > 0) aged = true; } @@ -292,7 +430,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { for (int serial : telemetry_state.states.keySet()) { AltosState existing = telemetry_state.states.get(serial); - int existing_age = state_age(existing); + int existing_age = state_age(existing.received_time); if (newest_state == null || existing_age < newest_age) { newest_state = existing; @@ -304,7 +442,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { state = newest_state; } - update_ui(telemetry_state, state, telemetry_state.location); + update_ui(telemetry_state, state, telemetry_state.quiet); start_timer(); } @@ -332,8 +470,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { blend_component(a, b, r, 24, 0xff)); } - int state_age(AltosState state) { - return (int) ((System.currentTimeMillis() - state.received_time + 500) / 1000); + int state_age(long received_time) { + return (int) ((System.currentTimeMillis() - received_time + 500) / 1000); } void set_screen_on(int age) { @@ -345,7 +483,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { void update_age() { if (saved_state != null) { - int age = state_age(saved_state); + int age = state_age(saved_state.received_time); double age_scale = age / 100.0; @@ -369,7 +507,9 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { } } - void update_ui(TelemetryState telem_state, AltosState state, Location location) { + void update_ui(TelemetryState telem_state, AltosState state, boolean quiet) { + + this.state = state; int prev_state = AltosLib.ao_flight_invalid; @@ -379,39 +519,36 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { prev_state = saved_state.state; if (state != null) { - set_screen_on(state_age(state)); + set_screen_on(state_age(state.received_time)); - if (state.state == AltosLib.ao_flight_stateless) { + if (state.state() == AltosLib.ao_flight_stateless) { boolean prev_locked = false; boolean locked = false; if(state.gps != null) locked = state.gps.locked; - if (saved_state != null && saved_state.gps != null) - prev_locked = saved_state.gps.locked; + if (saved_state != null) + prev_locked = saved_state.locked; if (prev_locked != locked) { String currentTab = mTabHost.getCurrentTabTag(); if (locked) { - if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("descent"); + if (currentTab.equals(tab_pad_name)) mTabHost.setCurrentTabByTag(tab_flight_name); } else { - if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("pad"); + if (currentTab.equals(tab_flight_name)) mTabHost.setCurrentTabByTag(tab_pad_name); } } } else { - if (prev_state != state.state) { + if (prev_state != state.state()) { String currentTab = mTabHost.getCurrentTabTag(); - switch (state.state) { + switch (state.state()) { case AltosLib.ao_flight_boost: - if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("ascent"); - break; - case AltosLib.ao_flight_drogue: - if (currentTab.equals("ascent")) mTabHost.setCurrentTabByTag("descent"); + if (currentTab.equals(tab_pad_name)) mTabHost.setCurrentTabByTag(tab_flight_name); break; case AltosLib.ao_flight_landed: - if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("landed"); + if (currentTab.equals(tab_flight_name)) mTabHost.setCurrentTabByTag(tab_recover_name); break; case AltosLib.ao_flight_stateless: - if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("descent"); + if (currentTab.equals(tab_pad_name)) mTabHost.setCurrentTabByTag(tab_flight_name); break; } } @@ -429,20 +566,23 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { state.gps.alt); } - if (saved_state == null || !same_string(saved_state.callsign, state.callsign)) { - mCallsignView.setText(state.callsign); + if (saved_state == null || !same_string(saved_state.callsign, state.cal_data().callsign)) { + mCallsignView.setText(state.cal_data().callsign); } - if (saved_state == null || state.serial != saved_state.serial) { - mSerialView.setText(String.format("%d", state.serial)); + if (saved_state == null || state.cal_data().serial != saved_state.serial) { + if (state.cal_data().serial == AltosLib.MISSING) + mSerialView.setText(""); + else + mSerialView.setText(String.format("%d", state.cal_data().serial)); } - if (saved_state == null || state.flight != saved_state.flight) { - if (state.flight == AltosLib.MISSING) + if (saved_state == null || state.cal_data().flight != saved_state.flight) { + if (state.cal_data().flight == AltosLib.MISSING) mFlightView.setText(""); else - mFlightView.setText(String.format("%d", state.flight)); + mFlightView.setText(String.format("%d", state.cal_data().flight)); } - if (saved_state == null || state.state != saved_state.state) { - if (state.state == AltosLib.ao_flight_stateless) { + if (saved_state == null || state.state() != saved_state.state) { + if (state.state() == AltosLib.ao_flight_stateless) { mStateLayout.setVisibility(View.GONE); } else { mStateView.setText(state.state_name()); @@ -450,17 +590,21 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { } } if (saved_state == null || state.rssi != saved_state.rssi) { - mRSSIView.setText(String.format("%d", state.rssi)); + if (state.rssi == AltosLib.MISSING) + mRSSIView.setText(""); + else + mRSSIView.setText(String.format("%d", state.rssi)); } + saved_state = new SavedState(state); } for (AltosDroidTab mTab : mTabs) mTab.update_ui(telem_state, state, from_receiver, location, mTab == mTabsAdapter.currentItem()); - if (state != null && mAltosVoice != null) - mAltosVoice.tell(state, from_receiver); + AltosDebug.debug("quiet %b\n", quiet); + if (mAltosVoice != null) + mAltosVoice.tell(telem_state, state, from_receiver, location, (AltosDroidTab) mTabsAdapter.currentItem(), quiet); - saved_state = state; } private void onTimerTick() { @@ -503,9 +647,6 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { return tab_view; } - public void set_map_source() { - } - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -529,18 +670,17 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager); - mTabsAdapter.addTab(mTabHost.newTabSpec("pad").setIndicator(create_tab_view("Pad")), TabPad.class, null); - mTabsAdapter.addTab(mTabHost.newTabSpec("ascent").setIndicator(create_tab_view("Ascent")), TabAscent.class, null); - mTabsAdapter.addTab(mTabHost.newTabSpec("descent").setIndicator(create_tab_view("Descent")), TabDescent.class, null); - mTabsAdapter.addTab(mTabHost.newTabSpec("landed").setIndicator(create_tab_view("Landed")), TabLanded.class, null); - mTabsAdapter.addTab(mTabHost.newTabSpec("map").setIndicator(create_tab_view("Map")), TabMap.class, null); - mTabsAdapter.addTab(mTabHost.newTabSpec("offmap").setIndicator(create_tab_view("OffMap")), TabMapOffline.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec(tab_pad_name).setIndicator(create_tab_view("Pad")), TabPad.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec(tab_flight_name).setIndicator(create_tab_view("Flight")), TabFlight.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec(tab_recover_name).setIndicator(create_tab_view("Recover")), TabRecover.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec(tab_map_name).setIndicator(create_tab_view("Map")), TabMap.class, null); // Display the Version mVersion = (TextView) findViewById(R.id.version); mVersion.setText("Version: " + BuildInfo.version + - " Built: " + BuildInfo.builddate + " " + BuildInfo.buildtime + " " + BuildInfo.buildtz + - " (" + BuildInfo.branch + "-" + BuildInfo.commitnum + "-" + BuildInfo.commithash + ")"); + (AltosVersion.has_google_maps_api_key() ? " maps" : "") + + " Built: " + BuildInfo.builddate + " " + BuildInfo.buildtime + " " + BuildInfo.buildtz + + " (" + BuildInfo.branch + "-" + BuildInfo.commitnum + "-" + BuildInfo.commithash + ")"); mCallsignView = (TextView) findViewById(R.id.callsign_value); mRSSIView = (TextView) findViewById(R.id.rssi_value); @@ -553,22 +693,15 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { mAgeOldColor = getResources().getColor(R.color.old_color); } - private boolean ensureBluetooth() { + private void ensureBluetooth() { // Get local Bluetooth adapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - // If the adapter is null, then Bluetooth is not supported - if (mBluetoothAdapter == null) { - Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show(); - return false; - } - - if (!mBluetoothAdapter.isEnabled()) { + /* if there is a BT adapter and it isn't turned on, then turn it on */ + if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, AltosDroid.REQUEST_ENABLE_BT); } - - return true; } private boolean check_usb() { @@ -634,9 +767,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { return; } AltosDebug.debug("Starting by looking for bluetooth devices"); - if (ensureBluetooth()) - return; - finish(); + ensureBluetooth(); } } @@ -645,6 +776,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { super.onStart(); AltosDebug.debug("++ ON START ++"); + set_switch_time(); + noticeIntent(getIntent()); // Start Telemetry Service @@ -670,24 +803,33 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { public void onResume() { super.onResume(); AltosDebug.debug("+ ON RESUME +"); + + // Listen for GPS and Network position updates + LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this); + + location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); + + if (location != null) + AltosDebug.debug("Resume, location is %f,%f\n", + location.getLatitude(), + location.getLongitude()); + + update_ui(telemetry_state, state, true); } @Override public void onPause() { super.onPause(); AltosDebug.debug("- ON PAUSE -"); + // Stop listening for location updates + ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this); } @Override public void onStop() { super.onStop(); AltosDebug.debug("-- ON STOP --"); - - doUnbindService(); - if (mAltosVoice != null) { - mAltosVoice.stop(); - mAltosVoice = null; - } } @Override @@ -695,7 +837,11 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { super.onDestroy(); AltosDebug.debug("--- ON DESTROY ---"); - if (mAltosVoice != null) mAltosVoice.stop(); + doUnbindService(); + if (mAltosVoice != null) { + mAltosVoice.stop(); + mAltosVoice = null; + } stop_timer(); } @@ -713,21 +859,48 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { if (resultCode == Activity.RESULT_OK) { // Bluetooth is now enabled, so set up a chat session //setupChat(); + AltosDebug.debug("BT enabled"); + bluetoothEnabled(data); } else { // User did not enable Bluetooth or an error occured - AltosDebug.error("BT not enabled"); - stopService(new Intent(AltosDroid.this, TelemetryService.class)); - Toast.makeText(this, R.string.bt_not_enabled, Toast.LENGTH_SHORT).show(); - finish(); + AltosDebug.debug("BT not enabled"); } break; - case REQUEST_MAP_TYPE: + case REQUEST_IDLE_MODE: + if (resultCode == Activity.RESULT_OK) + idle_mode(data); + break; + case REQUEST_IGNITERS: + break; + case REQUEST_SETUP: if (resultCode == Activity.RESULT_OK) - set_map_type(data); + note_setup_changes(data); break; } } + private void note_setup_changes(Intent data) { + int changes = data.getIntExtra(SetupActivity.EXTRA_SETUP_CHANGES, 0); + + if ((changes & SETUP_BAUD) != 0) { + try { + mService.send(Message.obtain(null, TelemetryService.MSG_SETBAUD, + AltosPreferences.telemetry_rate(1))); + } catch (RemoteException re) { + } + } + if ((changes & SETUP_UNITS) != 0) { + /* nothing to do here */ + } + if ((changes & SETUP_MAP_SOURCE) != 0) { + /* nothing to do here */ + } + if ((changes & SETUP_MAP_TYPE) != 0) { + /* nothing to do here */ + } + set_switch_time(); + } + private void connectUsb(UsbDevice device) { if (mService == null) pending_usb_device = device; @@ -742,6 +915,14 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { } } + private void bluetoothEnabled(Intent data) { + try { + mService.send(Message.obtain(null, TelemetryService.MSG_BLUETOOTH_ENABLED, null)); + } catch (RemoteException e) { + AltosDebug.debug("send BT enabled message failed"); + } + } + private void connectDevice(Intent data) { // Attempt to connect to the device try { @@ -757,21 +938,44 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { } } - private void disconnectDevice() { + private void disconnectDevice(boolean remember) { try { - mService.send(Message.obtain(null, TelemetryService.MSG_DISCONNECT, null)); + mService.send(Message.obtain(null, TelemetryService.MSG_DISCONNECT, (Boolean) remember)); } catch (RemoteException e) { } } - private void set_map_type(Intent data) { - int type = data.getIntExtra(MapTypeActivity.EXTRA_MAP_TYPE, -1); + private void idle_mode(Intent data) { + int type = data.getIntExtra(IdleModeActivity.EXTRA_IDLE_RESULT, -1); + Message msg; - AltosDebug.debug("intent set_map_type %d\n", type); - if (type != -1) { - map_type = type; - for (AltosDroidTab mTab : mTabs) - mTab.set_map_type(map_type); + AltosDebug.debug("intent idle_mode %d", type); + switch (type) { + case IdleModeActivity.IDLE_MODE_CONNECT: + msg = Message.obtain(null, TelemetryService.MSG_MONITOR_IDLE_START); + try { + mService.send(msg); + } catch (RemoteException re) { + } + break; + case IdleModeActivity.IDLE_MODE_DISCONNECT: + msg = Message.obtain(null, TelemetryService.MSG_MONITOR_IDLE_STOP); + try { + mService.send(msg); + } catch (RemoteException re) { + } + break; + case IdleModeActivity.IDLE_MODE_REBOOT: + msg = Message.obtain(null, TelemetryService.MSG_REBOOT); + try { + mService.send(msg); + } catch (RemoteException re) { + } + break; + case IdleModeActivity.IDLE_MODE_IGNITERS: + Intent serverIntent = new Intent(this, IgniterActivity.class); + startActivityForResult(serverIntent, REQUEST_IGNITERS); + break; } } @@ -790,11 +994,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { } } - void setFrequency(String freq) { - try { - setFrequency (AltosParse.parse_double_net(freq.substring(11, 17))); - } catch (ParseException e) { - } + void setFrequency(AltosFrequency frequency) { + setFrequency (frequency.frequency); } void setBaud(int baud) { @@ -827,16 +1028,54 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { void select_tracker(int serial) { int i; - for (i = 0; i < serials.length; i++) - if (serials[i] == serial) - break; - if (i == serials.length) + + AltosDebug.debug("select tracker %d\n", serial); + + if (serial == selected_serial) { + AltosDebug.debug("%d already selected\n", serial); return; + } + + if (serial != 0) { + for (i = 0; i < trackers.length; i++) + if (trackers[i].serial == serial) + break; - current_serial = serial; + if (i == trackers.length) { + AltosDebug.debug("attempt to select unknown tracker %d\n", serial); + return; + } + } + + current_serial = selected_serial = serial; update_state(null); } + void touch_trackers(Integer[] serials) { + AlertDialog.Builder builder_tracker = new AlertDialog.Builder(this); + builder_tracker.setTitle("Select Tracker"); + + final Tracker[] my_trackers = new Tracker[serials.length + 1]; + + my_trackers[0] = new Tracker(null); + + for (int i = 0; i < serials.length; i++) { + AltosState s = telemetry_state.states.get(serials[i]); + my_trackers[i+1] = new Tracker(s); + } + builder_tracker.setItems(my_trackers, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + if (item == 0) + select_tracker(0); + else + select_tracker(my_trackers[item].serial); + } + }); + AlertDialog alert_tracker = builder_tracker.create(); + alert_tracker.show(); + } + void delete_track(int serial) { try { mService.send(Message.obtain(null, TelemetryService.MSG_DELETE_SERIAL, (Integer) serial)); @@ -849,41 +1088,36 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { Intent serverIntent = null; switch (item.getItemId()) { case R.id.connect_scan: - if (ensureBluetooth()) { - // Launch the DeviceListActivity to see devices and do scan - serverIntent = new Intent(this, DeviceListActivity.class); - startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE); - } + ensureBluetooth(); + // Launch the DeviceListActivity to see devices and do scan + serverIntent = new Intent(this, DeviceListActivity.class); + startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE); return true; case R.id.disconnect: /* Disconnect the device */ - disconnectDevice(); + disconnectDevice(false); return true; case R.id.quit: AltosDebug.debug("R.id.quit"); - disconnectDevice(); + disconnectDevice(true); finish(); return true; + case R.id.setup: + serverIntent = new Intent(this, SetupActivity.class); + startActivityForResult(serverIntent, REQUEST_SETUP); + return true; case R.id.select_freq: // Set the TBT radio frequency - final String[] frequencies = { - "Channel 0 (434.550MHz)", - "Channel 1 (434.650MHz)", - "Channel 2 (434.750MHz)", - "Channel 3 (434.850MHz)", - "Channel 4 (434.950MHz)", - "Channel 5 (435.050MHz)", - "Channel 6 (435.150MHz)", - "Channel 7 (435.250MHz)", - "Channel 8 (435.350MHz)", - "Channel 9 (435.450MHz)" - }; + final AltosFrequency[] frequencies = AltosPreferences.common_frequencies(); + String[] frequency_strings = new String[frequencies.length]; + for (int i = 0; i < frequencies.length; i++) + frequency_strings[i] = frequencies[i].toString(); AlertDialog.Builder builder_freq = new AlertDialog.Builder(this); builder_freq.setTitle("Pick a frequency"); - builder_freq.setItems(frequencies, + builder_freq.setItems(frequency_strings, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { setFrequency(frequencies[item]); @@ -892,55 +1126,18 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { AlertDialog alert_freq = builder_freq.create(); alert_freq.show(); return true; - case R.id.select_rate: - // Set the TBT baud rate - - final String[] rates = { - "38400", - "9600", - "2400", - }; - - AlertDialog.Builder builder_rate = new AlertDialog.Builder(this); - builder_rate.setTitle("Pick a baud rate"); - builder_rate.setItems(rates, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - setBaud(rates[item]); - } - }); - AlertDialog alert_rate = builder_rate.create(); - alert_rate.show(); - return true; - case R.id.change_units: - boolean imperial = AltosPreferences.imperial_units(); - AltosPreferences.set_imperial_units(!imperial); - return true; - case R.id.preload_maps: - serverIntent = new Intent(this, PreloadMapActivity.class); - startActivityForResult(serverIntent, REQUEST_PRELOAD_MAPS); - return true; - case R.id.map_type: - serverIntent = new Intent(this, MapTypeActivity.class); - startActivityForResult(serverIntent, REQUEST_MAP_TYPE); - return true; - case R.id.map_source: - int source = AltosDroidPreferences.map_source(); - int new_source = source == AltosDroidPreferences.MAP_SOURCE_ONLINE ? AltosDroidPreferences.MAP_SOURCE_OFFLINE : AltosDroidPreferences.MAP_SOURCE_ONLINE; - AltosDroidPreferences.set_map_source(new_source); - set_map_source(); - return true; case R.id.select_tracker: - if (serials != null) { - String[] trackers = new String[serials.length]; - for (int i = 0; i < serials.length; i++) - trackers[i] = String.format("%d", serials[i]); + if (trackers != null) { AlertDialog.Builder builder_serial = new AlertDialog.Builder(this); builder_serial.setTitle("Select a tracker"); builder_serial.setItems(trackers, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { - select_tracker(serials[item]); + System.out.printf("select item %d %s\n", item, trackers[item].display); + if (item == 0) + select_tracker(0); + else + select_tracker(trackers[item].serial); } }); AlertDialog alert_serial = builder_serial.create(); @@ -949,16 +1146,16 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { } return true; case R.id.delete_track: - if (serials != null) { - String[] trackers = new String[serials.length]; - for (int i = 0; i < serials.length; i++) - trackers[i] = String.format("%d", serials[i]); + if (trackers != null) { AlertDialog.Builder builder_serial = new AlertDialog.Builder(this); builder_serial.setTitle("Delete a track"); - builder_serial.setItems(trackers, + final Tracker[] my_trackers = new Tracker[trackers.length - 1]; + for (int i = 0; i < trackers.length - 1; i++) + my_trackers[i] = trackers[i+1]; + builder_serial.setItems(my_trackers, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { - delete_track(serials[item]); + delete_track(my_trackers[item].serial); } }); AlertDialog alert_serial = builder_serial.create(); @@ -966,7 +1163,63 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { } return true; + case R.id.idle_mode: + serverIntent = new Intent(this, IdleModeActivity.class); + serverIntent.putExtra(EXTRA_IDLE_MODE, idle_mode); + startActivityForResult(serverIntent, REQUEST_IDLE_MODE); + return true; } return false; } + + static String direction(AltosGreatCircle from_receiver, + Location receiver) { + if (from_receiver == null) + return null; + + if (receiver == null) + return null; + + if (!receiver.hasBearing()) + return null; + + float bearing = receiver.getBearing(); + float heading = (float) from_receiver.bearing - bearing; + + while (heading <= -180.0f) + heading += 360.0f; + while (heading > 180.0f) + heading -= 360.0f; + + int iheading = (int) (heading + 0.5f); + + if (-1 < iheading && iheading < 1) + return "ahead"; + else if (iheading < -179 || 179 < iheading) + return "backwards"; + else if (iheading < 0) + return String.format("left %d°", -iheading); + else + return String.format("right %d°", iheading); + } + + public void onLocationChanged(Location location) { + this.location = location; + AltosDebug.debug("Location changed to %f,%f", + location.getLatitude(), + location.getLongitude()); + update_ui(telemetry_state, state, false); + } + + public void onStatusChanged(String provider, int status, Bundle extras) { + AltosDebug.debug("Location status now %d\n", status); + } + + public void onProviderEnabled(String provider) { + AltosDebug.debug("Location provider enabled %s\n", provider); + } + + public void onProviderDisabled(String provider) { + AltosDebug.debug("Location provider disabled %s\n", provider); + } }