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.*;
// 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;
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");
boolean registered_units_listener;
- void update_state(TelemetryState telemetry_state) {
+ int current_serial;
+
+ void update_state(TelemetryState new_telemetry_state) {
+
+ if (new_telemetry_state != null)
+ telemetry_state = new_telemetry_state;
+
+ 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]);
+
update_title(telemetry_state);
- update_ui(telemetry_state.state, telemetry_state.location);
- if (telemetry_state.connect == TelemetryState.CONNECT_CONNECTED)
- start_timer();
+
+ AltosDebug.debug("update state current serial %d\n", current_serial);
+
+ AltosState state = null;
+ if (telemetry_state.states.containsKey(current_serial))
+ state = telemetry_state.states.get(current_serial);
+
+ update_ui(telemetry_state, state, telemetry_state.location);
+
+ start_timer();
}
boolean same_string(String a, String b) {
}
}
+
+ 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;
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;
}
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);
}
}
+ void select_tracker(int serial) {
+ int i;
+ for (i = 0; i < serials.length; i++)
+ if (serials[i] == serial)
+ break;
+ if (i == serials.length)
+ return;
+
+ AltosDebug.debug("Switching to serial %d\n", serial);
+ current_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;
serverIntent = new Intent(this, MapTypeActivity.class);
startActivityForResult(serverIntent, REQUEST_MAP_TYPE);
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]);
+ 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]);
+ }
+ });
+ 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;
}
-
}
public String[] keys() {
Map<String, ?> all = prefs.getAll();
- return (String[])all.keySet().toArray();
+ Object[] ao = all.keySet().toArray();
+
+ String[] as = new String[ao.length];
+ for (int i = 0; i < ao.length; i++)
+ as[i] = (String) ao[i];
+ return as;
}
public AltosPreferencesBackend node(String key) {
}
public void remove(String key) {
+ AltosDebug.debug("remove preference %s\n", key);
editor.remove(key);
}
import android.widget.TextView;
public abstract class AltosDroidTab extends Fragment implements AltosUnitsListener {
+ TelemetryState last_telem_state;
AltosState last_state;
AltosGreatCircle last_from_receiver;
Location last_receiver;
+ AltosDroid altos_droid;
- public abstract void show(AltosState state, AltosGreatCircle from_receiver, Location receiver);
+ public abstract void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver);
public abstract String tab_name();
}
public void units_changed(boolean imperial_units) {
- if (!isHidden() && last_state != null)
- show(last_state, last_from_receiver, last_receiver);
+ if (!isHidden())
+ show(last_telem_state, last_state, last_from_receiver, last_receiver);
}
public void set_value(TextView text_view,
FragmentTransaction ft = AltosDroid.fm.beginTransaction();
AltosDebug.debug("set visible %b %s\n", visible, tab_name());
if (visible) {
- AltosState state = last_state;
- AltosGreatCircle from_receiver = last_from_receiver;
- Location receiver = last_receiver;
-
ft.show(this);
- show(state, from_receiver, receiver);
+ show(last_telem_state, last_state, last_from_receiver, last_receiver);
} else
ft.hide(this);
ft.commitAllowingStateLoss();
}
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ altos_droid = (AltosDroid) activity;
+ altos_droid.registerTab(this);
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ altos_droid.unregisterTab(this);
+ altos_droid = null;
+ }
+
@Override
public void onResume() {
super.onResume();
set_visible(true);
}
- public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver, boolean is_current) {
+ public void update_ui(TelemetryState telem_state, AltosState state,
+ AltosGreatCircle from_receiver, Location receiver, boolean is_current)
+ {
+ last_telem_state = telem_state;
last_state = state;
last_from_receiver = from_receiver;
last_receiver = receiver;
+ AltosDebug.debug("update_ui tab %s is_current %b\n", tab_name(), is_current);
if (is_current)
- show(state, from_receiver, receiver);
+ show(telem_state, state, from_receiver, receiver);
else
return;
}
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
- // Get the BluetoothDevice object from the Intent
+
+ /* Get the BluetoothDevice object from the Intent
+ */
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- // If it's already paired, skip it, because it's been listed already
- if ( device.getBondState() != BluetoothDevice.BOND_BONDED
- && device.getName().startsWith("TeleBT") ) {
- mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
+
+ /* If it's already paired, skip it, because it's been listed already
+ */
+ if (device != null && device.getBondState() != BluetoothDevice.BOND_BONDED)
+ {
+ String name = device.getName();
+ if (name != null && name.startsWith("TeleBT"))
+ mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
- // When discovery is finished, change the Activity title
+
+ /* When discovery is finished, change the Activity title
+ */
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
setProgressBarIndeterminateVisibility(false);
setTitle(R.string.select_device);
import android.location.Location;
public class TabAscent extends AltosDroidTab {
- AltosDroid mAltosDroid;
-
private TextView mHeightView;
private TextView mMaxHeightView;
private TextView mSpeedView;
private TextView mMainVoltageView;
private GoNoGoLights mMainLights;
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- mAltosDroid = (AltosDroid) activity;
- mAltosDroid.registerTab(this);
- }
-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.tab_ascent, container, false);
return v;
}
- @Override
- public void onDestroy() {
- super.onDestroy();
- mAltosDroid.unregisterTab(this);
- mAltosDroid = null;
- }
-
public String tab_name() {
return "ascent";
}
- public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
if (state != null) {
set_value(mHeightView, AltosConvert.height, 6, state.height());
set_value(mHeightView, AltosConvert.height, 6, state.height());
import android.location.Location;
public class TabDescent extends AltosDroidTab {
- AltosDroid mAltosDroid;
-
private TextView mSpeedView;
private TextView mHeightView;
private TextView mElevationView;
private TextView mMainVoltageView;
private GoNoGoLights mMainLights;
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- mAltosDroid = (AltosDroid) activity;
- mAltosDroid.registerTab(this);
- }
-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.tab_descent, container, false);
return v;
}
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mAltosDroid.unregisterTab(this);
- mAltosDroid = null;
- }
-
public String tab_name() { return "descent"; }
- public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
if (state != null) {
set_value(mSpeedView, AltosConvert.speed, 6, state.speed());
set_value(mHeightView, AltosConvert.height, 6, state.height());
import android.location.Location;
public class TabLanded extends AltosDroidTab {
- AltosDroid mAltosDroid;
-
private TextView mBearingView;
private TextView mDistanceView;
private TextView mTargetLatitudeView;
private TextView mMaxSpeedView;
private TextView mMaxAccelView;
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- mAltosDroid = (AltosDroid) activity;
- mAltosDroid.registerTab(this);
- }
-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.tab_landed, container, false);
return v;
}
- @Override
- public void onDestroy() {
- super.onDestroy();
- mAltosDroid.unregisterTab(this);
- mAltosDroid = null;
- }
-
public String tab_name() { return "landed"; }
- public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
if (from_receiver != null) {
mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
import android.app.Activity;
import android.graphics.Color;
+import android.graphics.*;
import android.os.Bundle;
import android.support.v4.app.Fragment;
//import android.support.v4.app.FragmentTransaction;
import android.location.Location;
public class TabMap extends AltosDroidTab {
- AltosDroid mAltosDroid;
-
private SupportMapFragment mMapFragment;
private GoogleMap mMap;
private boolean mapLoaded = false;
private double mapAccuracy = -1;
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- mAltosDroid = (AltosDroid) activity;
- mAltosDroid.registerTab(this);
+ private Bitmap rocket_bitmap(String text) {
+
+ /* From: http://mapicons.nicolasmollet.com/markers/industry/military/missile-2/
+ */
+ Bitmap orig_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.rocket);
+ Bitmap bitmap = orig_bitmap.copy(Bitmap.Config.ARGB_8888, true);
+
+ Canvas canvas = new Canvas(bitmap);
+ Paint paint = new Paint();
+ paint.setTextSize(40);
+ paint.setColor(0xff000000);
+
+ Rect bounds = new Rect();
+ paint.getTextBounds(text, 0, text.length(), bounds);
+
+ int width = bounds.right - bounds.left;
+ int height = bounds.bottom - bounds.top;
+
+ float x = bitmap.getWidth() / 2.0f - width / 2.0f;
+ float y = bitmap.getHeight() / 2.0f - height / 2.0f;
+
+ AltosDebug.debug("map label x %f y %f\n", x, y);
+
+ canvas.drawText(text, 0, text.length(), x, y, paint);
+ return bitmap;
+ }
+
+ private Marker rocket_marker(int serial, double lat, double lon) {
+ Bitmap bitmap = rocket_bitmap(String.format("%d", serial));
+
+ return mMap.addMarker(new MarkerOptions()
+ .icon(BitmapDescriptorFactory.fromBitmap(bitmap))
+ .position(new LatLng(lat, lon))
+ .visible(false));
}
@Override
getChildFragmentManager().beginTransaction().add(R.id.map, mMapFragment).commit();
}
- @Override
- public void onDestroyView() {
- super.onDestroyView();
-
- mAltosDroid.unregisterTab(this);
- mAltosDroid = null;
-
- //Fragment fragment = (getFragmentManager().findFragmentById(R.id.map));
- //FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
- //ft.remove(fragment);
- //ft.commit();
- }
-
private void setupMap() {
mMap = mMapFragment.getMap();
if (mMap != null) {
- set_map_type(mAltosDroid.map_type);
+ set_map_type(altos_droid.map_type);
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setTiltGesturesEnabled(false);
mMap.getUiSettings().setZoomControlsEnabled(false);
- mRocketMarker = mMap.addMarker(
- // From: http://mapicons.nicolasmollet.com/markers/industry/military/missile-2/
- new MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.rocket))
- .position(new LatLng(0,0))
- .visible(false)
- );
+ Bitmap label_bitmap = rocket_bitmap("hello");
+
+ mRocketMarker = rocket_marker(1800,0,0);
mPadMarker = mMap.addMarker(
new MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.drawable.pad))
public String tab_name() { return "map"; }
- public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
if (from_receiver != null) {
mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
if (mapLoaded) {
if (state.gps != null) {
mRocketMarker.setPosition(new LatLng(state.gps.lat, state.gps.lon));
+ mRocketMarker.setTitle("hello world");
+ mRocketMarker.setSnippet("hello");
mRocketMarker.setVisible(true);
mPolyline.setPoints(Arrays.asList(new LatLng(state.pad_lat, state.pad_lon), new LatLng(state.gps.lat, state.gps.lon)));
public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
- AltosDroid mAltosDroid;
-
AltosMap map;
AltosLatLon here;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
- mAltosDroid = (AltosDroid) activity;
- mAltosDroid.registerTab(this);
map = new AltosMap(this);
- map.set_maptype(mAltosDroid.map_type);
+ map.set_maptype(altos_droid.map_type);
pad_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pad);
/* arrow at the bottom of the launchpad image */
here_off_y = here_bitmap.getHeight() / 2;
}
- @Override
- public void onDetach() {
- super.onDetach();
- mAltosDroid = null;
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
public void onDestroyView() {
super.onDestroyView();
- mAltosDroid.unregisterTab(this);
}
private void center(double lat, double lon, double accuracy) {
public String tab_name() { return "offmap"; }
- public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
if (from_receiver != null) {
mBearingView.setText(String.format("%3.0f°", from_receiver.bearing));
set_value(mDistanceView, AltosConvert.distance, 6, from_receiver.distance);
}
if (state.pad_lat != AltosLib.MISSING && pad == null)
pad = new AltosLatLon(state.pad_lat, state.pad_lon);
+ }
- int serial = state.serial;
- if (serial == AltosLib.MISSING)
- serial = 0;
+ if (telem_state != null) {
+ Integer[] old_serial = rockets.keySet().toArray(new Integer[0]);
+ Integer[] new_serial = telem_state.states.keySet().toArray(new Integer[0]);
- Rocket rocket = null;
+ /* remove deleted keys */
+ for (int serial : old_serial) {
+ if (!telem_state.states.containsKey(serial))
+ rockets.remove(serial);
+ }
+
+ /* set remaining keys */
- if (state.gps != null && state.gps.locked) {
- if (!rockets.containsKey(serial)) {
+ for (int serial : new_serial) {
+ Rocket rocket;
+ AltosState t_state = telem_state.states.get(serial);
+ if (rockets.containsKey(serial))
+ rocket = rockets.get(serial);
+ else {
rocket = new Rocket(String.format("%d", serial), this);
rockets.put(serial, rocket);
- } else
- rocket = rockets.get(serial);
- rocket.set_position(new AltosLatLon(state.gps.lat, state.gps.lon));
+ }
+ rocket.set_position(new AltosLatLon(t_state.gps.lat, t_state.gps.lon));
}
}
import android.location.Location;
public class TabPad extends AltosDroidTab {
- AltosDroid mAltosDroid;
-
private TextView mBatteryVoltageView;
private TextView mBatteryVoltageLabel;
private GoNoGoLights mBatteryLights;
private TextView mPadLongitudeView;
private TextView mPadAltitudeView;
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- mAltosDroid = (AltosDroid) activity;
- mAltosDroid.registerTab(this);
- }
-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.tab_pad, container, false);
return v;
}
- @Override
- public void onDestroy() {
- super.onDestroy();
- mAltosDroid.unregisterTab(this);
- mAltosDroid = null;
- }
-
public String tab_name() { return "pad"; }
- public void show(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
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);
logger = null;
}
}
-
+
void handleExternalStorageState() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
import java.text.*;
import java.io.*;
+import java.util.*;
import java.util.concurrent.*;
import android.os.Handler;
Handler handler;
AltosLink link;
- AltosState state = null;
LinkedBlockingQueue<AltosLine> telemQueue;
- public AltosState read() throws ParseException, AltosCRCException, InterruptedException, IOException {
+ public AltosTelemetry read() throws ParseException, AltosCRCException, InterruptedException, IOException {
AltosLine l = telemQueue.take();
if (l.line == null)
throw new IOException("IO error");
AltosTelemetry telem = AltosTelemetryLegacy.parse(l.line);
- if (state == null)
- state = new AltosState();
- else
- state = state.clone();
- telem.update_state(state);
- return state;
+ return telem;
}
public void close() {
- state = null;
link.remove_monitor(telemQueue);
link = null;
telemQueue.clear();
}
public void run() {
- AltosState state = null;
-
try {
AltosDebug.debug("starting loop");
while (telemQueue != null) {
try {
- state = read();
- handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget();
+ AltosTelemetry telem = read();
+ handler.obtainMessage(TelemetryService.MSG_TELEMETRY, telem).sendToTarget();
} catch (ParseException pp) {
AltosDebug.error("Parse error: %d \"%s\"", pp.getErrorOffset(), pp.getMessage());
} catch (AltosCRCException ce) {
}
}
- public TelemetryReader (AltosLink in_link, Handler in_handler, AltosState in_state) {
+ public TelemetryReader (AltosLink in_link, Handler in_handler) {
AltosDebug.debug("connected TelemetryReader create started");
link = in_link;
handler = in_handler;
- state = in_state;
telemQueue = new LinkedBlockingQueue<AltosLine>();
link.add_monitor(telemQueue);
link.set_telemetry(AltosLib.ao_telemetry_standard);
package org.altusmetrum.AltosDroid;
import java.lang.ref.WeakReference;
-import java.util.ArrayList;
import java.util.concurrent.TimeoutException;
-import java.util.Timer;
-import java.util.TimerTask;
+import java.util.*;
import android.app.Notification;
//import android.app.NotificationManager;
static final int MSG_CRC_ERROR = 10;
static final int MSG_SETBAUD = 11;
static final int MSG_DISCONNECT = 12;
+ static final int MSG_DELETE_SERIAL = 13;
// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
s.address = null;
s.disconnect(true);
break;
+ case MSG_DELETE_SERIAL:
+ AltosDebug.debug("Delete Serial command received");
+ s.delete_serial((Integer) msg.obj);
+ break;
case MSG_SETFREQUENCY:
AltosDebug.debug("MSG_SETFREQUENCY");
s.telemetry_state.frequency = (Double) msg.obj;
* Messages from TelemetryReader
*/
case MSG_TELEMETRY:
- s.telemetry_state.state = (AltosState) msg.obj;
- if (s.telemetry_state.state != null) {
- AltosDebug.debug("Save state");
- AltosPreferences.set_state(0, s.telemetry_state.state, null);
- }
AltosDebug.debug("MSG_TELEMETRY");
- s.send_to_clients();
+ s.telemetry((AltosTelemetry) msg.obj);
break;
case MSG_CRC_ERROR:
// forward crc error messages
}
}
+ /* Handle telemetry packet
+ */
+ private void telemetry(AltosTelemetry telem) {
+ AltosState state;
+
+ if (telemetry_state.states.containsKey(telem.serial))
+ state = telemetry_state.states.get(telem.serial).clone();
+ else
+ state = new AltosState();
+ telem.update_state(state);
+ telemetry_state.states.put(telem.serial, state);
+ if (state != null) {
+ AltosDebug.debug("Save state %d", telem.serial);
+ AltosPreferences.set_state(telem.serial, state, null);
+ }
+ send_to_clients();
+ }
+
/* Construct the message to deliver to clients
*/
private Message message() {
if (telemetry_state == null)
AltosDebug.debug("telemetry_state null!");
- if (telemetry_state.state == null)
- AltosDebug.debug("telemetry_state.state null!");
+ if (telemetry_state.states == null)
+ AltosDebug.debug("telemetry_state.states null!");
return Message.obtain(null, AltosDroid.MSG_STATE, telemetry_state);
}
}
}
+ private void delete_serial(int serial) {
+ telemetry_state.states.remove((Integer) serial);
+ AltosPreferences.remove_state(serial);
+ send_to_clients();
+ }
+
private void start_altos_bluetooth(DeviceAddress address, boolean pause) {
// Get the BLuetoothDevice object
BluetoothDevice device = bluetooth_adapter.getRemoteDevice(address.address);
telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;
telemetry_state.address = address;
- telemetry_reader = new TelemetryReader(altos_link, handler, telemetry_state.state);
+ telemetry_reader = new TelemetryReader(altos_link, handler);
telemetry_reader.start();
AltosDebug.debug("connected TelemetryReader started");
telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
telemetry_state.address = null;
- AltosSavedState saved_state = AltosPreferences.state(0);
+ /* Pull the saved state information out of the preferences database
+ */
+ ArrayList<Integer> serials = AltosPreferences.list_states();
- if (saved_state != null) {
- AltosDebug.debug("recovered old state flight %d\n", saved_state.state.flight);
- telemetry_state.state = saved_state.state;
+ telemetry_state.latest_serial = AltosPreferences.latest_state();
+
+ for (int serial : serials) {
+ AltosSavedState saved_state = AltosPreferences.state(serial);
+ if (saved_state != null) {
+ if (serial == 0) {
+ serial = saved_state.state.serial;
+ AltosPreferences.set_state(serial, saved_state.state, saved_state.listener_state);
+ AltosPreferences.remove_state(0);
+ }
+ if (telemetry_state.latest_serial == 0)
+ telemetry_state.latest_serial = serial;
+
+ AltosDebug.debug("recovered old state serial %d flight %d\n",
+ serial,
+ saved_state.state.flight);
+ if (saved_state.state.gps != null)
+ AltosDebug.debug("\tposition %f,%f\n",
+ saved_state.state.gps.lat,
+ saved_state.state.gps.lon);
+ telemetry_state.states.put(serial, saved_state.state);
+ }
}
// Listen for GPS and Network position updates
package org.altusmetrum.AltosDroid;
+import java.util.*;
import org.altusmetrum.altoslib_7.*;
import android.location.Location;
int connect;
DeviceAddress address;
AltosConfigData config;
- AltosState state;
Location location;
int crc_errors;
double frequency;
int telemetry_rate;
+ HashMap<Integer,AltosState> states;
+
+ int latest_serial;
+
public TelemetryState() {
connect = CONNECT_NONE;
config = null;
- state = null;
+ states = new HashMap<Integer,AltosState>();
location = null;
crc_errors = 0;
frequency = AltosPreferences.frequency(0);