X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altosdroid%2Fsrc%2Forg%2Faltusmetrum%2FAltosDroid%2FAltosDroid.java;h=db7815f3a7ab5ac4fcd069bd6f35bff95785b305;hp=8c9ff31f0b44d6e1777743d00bd974d8e4f75309;hb=bfa6cd8934b993bd4a67cfc7a4eeecf9b11915ef;hpb=7c75ec6e11a9287b2360bb62ef4ddb4f0e2083c7 diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 8c9ff31f..db7815f3 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -18,10 +18,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; @@ -42,16 +41,8 @@ import android.content.res.Resources; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.util.DisplayMetrics; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.Window; -import android.view.View; -import android.view.LayoutInflater; -import android.widget.TabHost; -import android.widget.TextView; -import android.widget.RelativeLayout; -import android.widget.Toast; +import android.view.*; +import android.widget.*; import android.app.AlertDialog; import android.location.Location; import android.hardware.usb.*; @@ -96,6 +87,11 @@ 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; @@ -112,6 +108,8 @@ 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; UsbDevice pending_usb_device; boolean start_with_usb; @@ -136,13 +134,11 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { switch (msg.what) { case MSG_STATE: AltosDebug.debug("MSG_STATE"); - TelemetryState telemetry_state = (TelemetryState) msg.obj; - if (telemetry_state == null) { + if (msg.obj == null) { AltosDebug.debug("telemetry_state null!"); return; } - - ad.update_state(telemetry_state); + ad.update_state((TelemetryState) msg.obj); break; case MSG_UPDATE_AGE: AltosDebug.debug("MSG_UPDATE_AGE"); @@ -256,19 +252,73 @@ 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; - void update_state(TelemetryState telemetry_state) { + void update_state(TelemetryState new_telemetry_state) { + + 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; if (!registered_units_listener) { registered_units_listener = true; AltosPreferences.register_units_listener(this); } + serials = telemetry_state.states.keySet().toArray(new Integer[0]); + Arrays.sort(serials); + update_title(telemetry_state); - update_ui(telemetry_state.state, telemetry_state.location); - if (telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) - start_timer(); + + AltosState state = null; + boolean aged = true; + + if (telemetry_state.states.containsKey(current_serial)) { + state = telemetry_state.states.get(current_serial); + int age = state_age(state); + if (age < 20) + aged = false; + if (current_serial == selected_serial) + aged = false; + else if (switch_time != 0 && (switch_time - state.received_time) > 0) + aged = true; + } + + if (aged) { + AltosState newest_state = null; + int newest_age = 0; + + for (int serial : telemetry_state.states.keySet()) { + AltosState existing = telemetry_state.states.get(serial); + int existing_age = state_age(existing); + + if (newest_state == null || existing_age < newest_age) { + newest_state = existing; + newest_age = existing_age; + } + } + + if (newest_state != null) + state = newest_state; + } + + update_ui(telemetry_state, state, telemetry_state.location); + + start_timer(); } boolean same_string(String a, String b) { @@ -283,22 +333,55 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { } } + + private int blend_component(int a, int b, double r, int shift, int mask) { + return ((int) (((a >> shift) & mask) * r + ((b >> shift) & mask) * (1 - r)) & mask) << shift; + } + private int blend_color(int a, int b, double r) { + return (blend_component(a, b, r, 0, 0xff) | + blend_component(a, b, r, 8, 0xff) | + blend_component(a, b, r, 16, 0xff) | + blend_component(a, b, r, 24, 0xff)); + } + + int state_age(AltosState state) { + return (int) ((System.currentTimeMillis() - state.received_time + 500) / 1000); + } + + void set_screen_on(int age) { + if (age < 60) + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + else + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + void update_age() { if (saved_state != null) { - int age = (int) ((System.currentTimeMillis() - saved_state.received_time + 500) / 1000); - boolean old = age >= 10; - if (old != mAgeViewOld) { - if (old) - mAgeView.setTextColor(mAgeOldColor); - else - mAgeView.setTextColor(mAgeNewColor); - mAgeViewOld = old; - } - mAgeView.setText(String.format("%d", age)); + int age = state_age(saved_state); + + double age_scale = age / 100.0; + + if (age_scale > 1.0) + age_scale = 1.0; + + mAgeView.setTextColor(blend_color(mAgeOldColor, mAgeNewColor, age_scale)); + + set_screen_on(age); + + String text; + if (age < 60) + text = String.format("%ds", age); + else if (age < 60 * 60) + text = String.format("%dm", age / 60); + else if (age < 60 * 60 * 24) + text = String.format("%dh", age / (60 * 60)); + else + text = String.format("%dd", age / (24 * 60 * 60)); + mAgeView.setText(text); } } - void update_ui(AltosState state, Location location) { + void update_ui(TelemetryState telem_state, AltosState state, Location location) { int prev_state = AltosLib.ao_flight_invalid; @@ -308,6 +391,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { prev_state = saved_state.state; if (state != null) { + set_screen_on(state_age(state)); + if (state.state == AltosLib.ao_flight_stateless) { boolean prev_locked = false; boolean locked = false; @@ -319,9 +404,9 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { 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 { @@ -329,16 +414,13 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { String currentTab = mTabHost.getCurrentTabTag(); 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; } } @@ -382,10 +464,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { } for (AltosDroidTab mTab : mTabs) - mTab.update_ui(state, from_receiver, location, mTab == mTabsAdapter.currentItem()); + mTab.update_ui(telem_state, state, from_receiver, location, mTab == mTabsAdapter.currentItem()); - if (state != null && mAltosVoice != null) - mAltosVoice.tell(state, from_receiver); + if (mAltosVoice != null) + mAltosVoice.tell(telem_state, state, from_receiver, location, (AltosDroidTab) mTabsAdapter.currentItem()); saved_state = state; } @@ -430,12 +512,20 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { return tab_view; } + public void set_map_source(int source) { + for (AltosDroidTab mTab : mTabs) + mTab.set_map_source(source); + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AltosDebug.init(this); AltosDebug.debug("+++ ON CREATE +++"); + // Initialise preferences + AltosDroidPreferences.init(this); + fm = getSupportFragmentManager(); // Set up the window layout @@ -450,12 +540,10 @@ 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); @@ -706,6 +794,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { void setFrequency(double freq) { try { mService.send(Message.obtain(null, TelemetryService.MSG_SETFREQUENCY, freq)); + set_switch_time(); } catch (RemoteException e) { } } @@ -720,6 +809,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { void setBaud(int baud) { try { mService.send(Message.obtain(null, TelemetryService.MSG_SETBAUD, baud)); + set_switch_time(); } catch (RemoteException e) { } } @@ -744,6 +834,38 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { } } + void select_tracker(int serial) { + int i; + + 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 < serials.length; i++) + if (serials[i] == serial) + break; + + if (i == serials.length) { + AltosDebug.debug("attempt to select unknown tracker %d\n", serial); + return; + } + } + + current_serial = selected_serial = serial; + update_state(null); + } + + void delete_track(int serial) { + try { + mService.send(Message.obtain(null, TelemetryService.MSG_DELETE_SERIAL, (Integer) serial)); + } catch (Exception ex) { + } + } + @Override public boolean onOptionsItemSelected(MenuItem item) { Intent serverIntent = null; @@ -824,8 +946,78 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener { 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(new_source); + return true; + case R.id.select_tracker: + if (serials != null) { + String[] trackers = new String[serials.length+1]; + trackers[0] = "Auto"; + for (int i = 0; i < serials.length; i++) + trackers[i+1] = String.format("%d", serials[i]); + 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) { + if (item == 0) + select_tracker(0); + else + select_tracker(serials[item-1]); + } + }); + AlertDialog alert_serial = builder_serial.create(); + alert_serial.show(); + + } + 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]); + AlertDialog.Builder builder_serial = new AlertDialog.Builder(this); + builder_serial.setTitle("Delete a track"); + builder_serial.setItems(trackers, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + delete_track(serials[item]); + } + }); + AlertDialog alert_serial = builder_serial.create(); + alert_serial.show(); + + } + return true; } return false; } + static String direction(AltosGreatCircle from_receiver, + Location receiver) { + 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); + } }