summaryrefslogtreecommitdiff
path: root/altosdroid/src
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2016-04-25 23:12:34 -0400
committerKeith Packard <keithp@keithp.com>2016-04-25 23:12:34 -0400
commit204ae5142702044eb8ad2697a55028e904067958 (patch)
treeeadc8893251e4ebbfd036ccc57ac95aa1aba199d /altosdroid/src
parent565404599fe9edf9ba16aec348eeb19ea31af743 (diff)
altosdroid: Add idle mode monitoring, reboot. Start igniters
This adds three idle mode operations -- monitor idle, reboot flight computer and test igniters. The igniter test isn't quite wired up. Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'altosdroid/src')
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java80
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java3
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java130
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java303
-rw-r--r--altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java178
5 files changed, 673 insertions, 21 deletions
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
index 4f1dcb1a..e5f56a5a 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
@@ -64,12 +64,20 @@ 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 String EXTRA_IDLE_MODE = "idle_mode";
+ public static final String EXTRA_IDLE_RESULT = "idle_result";
+ public static final String EXTRA_TELEMETRY_SERVICE = "telemetry_service";
public int map_type = AltosMap.maptype_hybrid;
@@ -100,6 +108,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
private double frequency;
private int telemetry_rate;
+ private boolean idle_mode = false;
+
public Location location = null;
// Tabs
@@ -146,6 +156,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
case MSG_UPDATE_AGE:
ad.update_age();
break;
+ case MSG_IDLE_MODE:
+ ad.idle_mode = (Boolean) msg.obj;
+ ad.update_state(null);
+ break;
}
}
};
@@ -216,8 +230,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]));
@@ -444,7 +458,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
mCallsignView.setText(state.callsign);
}
if (saved_state == null || state.serial != saved_state.serial) {
- mSerialView.setText(String.format("%d", state.serial));
+ if (state.serial == AltosLib.MISSING)
+ mSerialView.setText("");
+ else
+ mSerialView.setText(String.format("%d", state.serial));
}
if (saved_state == null || state.flight != saved_state.flight) {
if (state.flight == AltosLib.MISSING)
@@ -461,7 +478,10 @@ 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));
}
}
@@ -681,9 +701,10 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
- AltosDebug.debug("Resume, location is %f,%f\n",
- location.getLatitude(),
- location.getLongitude());
+ if (location != null)
+ AltosDebug.debug("Resume, location is %f,%f\n",
+ location.getLatitude(),
+ location.getLongitude());
update_ui(telemetry_state, saved_state);
}
@@ -740,6 +761,12 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
if (resultCode == Activity.RESULT_OK)
set_map_type(data);
break;
+ case REQUEST_IDLE_MODE:
+ if (resultCode == Activity.RESULT_OK)
+ idle_mode(data);
+ break;
+ case REQUEST_IGNITERS:
+ break;
}
}
@@ -798,6 +825,40 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener,
}
}
+ private void idle_mode(Intent data) {
+ int type = data.getIntExtra(IdleModeActivity.EXTRA_IDLE_RESULT, -1);
+ Message msg;
+
+ 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;
+ }
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
@@ -1025,6 +1086,11 @@ 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;
}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java
index 6bc52d7e..2b10b11f 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java
@@ -207,10 +207,9 @@ public abstract class AltosDroidLink extends AltosLink {
public void print(String data) {
byte[] bytes = data.getBytes();
- AltosDebug.debug("print(): begin");
+ AltosDebug.debug(data.replace('\n', '\\'));
for (byte b : bytes)
putchar(b);
- AltosDebug.debug("print(): Wrote bytes: '" + data.replace('\n', '\\') + "'");
}
public AltosDroidLink(Handler handler) {
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java
new file mode 100644
index 00000000..ec12c192
--- /dev/null
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.view.View.OnClickListener;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+public class IdleModeActivity extends Activity {
+ private EditText callsign;
+ private Button connect;
+ private Button disconnect;
+ private Button reboot;
+ private Button igniters;
+
+ public static final String EXTRA_IDLE_MODE = "idle_mode";
+ public static final String EXTRA_IDLE_RESULT = "idle_result";
+
+ public static final int IDLE_MODE_CONNECT = 1;
+ public static final int IDLE_MODE_REBOOT = 2;
+ public static final int IDLE_MODE_IGNITERS = 3;
+ public static final int IDLE_MODE_DISCONNECT = 4;
+
+ private void done(int type) {
+ AltosPreferences.set_callsign(callsign());
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_IDLE_RESULT, type);
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ private String callsign() {
+ return callsign.getEditableText().toString();
+ }
+
+ public void connect_idle() {
+ done(IDLE_MODE_CONNECT);
+ }
+
+ public void disconnect_idle() {
+ AltosDebug.debug("Disconnect idle button pressed");
+ done(IDLE_MODE_DISCONNECT);
+ }
+
+ public void reboot_idle() {
+ done(IDLE_MODE_REBOOT);
+ }
+
+ public void igniters_idle() {
+ done(IDLE_MODE_IGNITERS);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.idle_mode);
+
+ callsign = (EditText) findViewById(R.id.set_callsign);
+ callsign.setText(new StringBuffer(AltosPreferences.callsign()));
+
+ connect = (Button) findViewById(R.id.connect_idle);
+ connect.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ connect_idle();
+ }
+ });
+ disconnect = (Button) findViewById(R.id.disconnect_idle);
+ disconnect.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ disconnect_idle();
+ }
+ });
+
+ boolean idle_mode = getIntent().getBooleanExtra(AltosDroid.EXTRA_IDLE_MODE, false);
+
+ if (idle_mode)
+ connect.setVisibility(View.GONE);
+ else
+ disconnect.setVisibility(View.GONE);
+
+ reboot = (Button) findViewById(R.id.reboot_idle);
+ reboot.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ reboot_idle();
+ }
+ });
+ igniters = (Button) findViewById(R.id.igniters_idle);
+ igniters.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ igniters_idle();
+ }
+ });
+
+ // Set result CANCELED incase the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java
new file mode 100644
index 00000000..a608bba0
--- /dev/null
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.*;
+import android.graphics.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+class IgniterItem {
+ public String name;
+ public String status;
+ public LinearLayout igniter_view = null;
+ public TextView name_view = null;
+ public TextView status_view = null;
+
+ private void update() {
+ AltosDebug.debug("update item %s %s", name, status);
+ if (name_view != null)
+ name_view.setText(name);
+ if (status_view != null)
+ status_view.setText(status);
+ }
+
+ public void set(String name, String status) {
+ if (!name.equals(this.name) || !status.equals(this.status)) {
+ this.name = name;
+ this.status = status;
+ update();
+ }
+ }
+
+ public void realize(LinearLayout igniter_view,
+ TextView name_view,
+ TextView status_view) {
+ if (igniter_view != this.igniter_view ||
+ name_view != this.name_view ||
+ status_view != this.status_view)
+ {
+ this.igniter_view = igniter_view;
+ this.name_view = name_view;
+ this.status_view = status_view;
+ update();
+ }
+ }
+
+ public IgniterItem() {
+ AltosDebug.debug("New igniter item");
+ }
+}
+
+class IgniterAdapter extends ArrayAdapter<IgniterItem> {
+ int resource;
+ int selected_item = -1;
+
+ public IgniterAdapter(Context context, int in_resource) {
+ super(context, in_resource);
+ resource = in_resource;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ IgniterItem item = getItem(position);
+ if (item.igniter_view == null) {
+ LinearLayout igniter_view = new LinearLayout(getContext());
+ String inflater = Context.LAYOUT_INFLATER_SERVICE;
+ LayoutInflater li = (LayoutInflater) getContext().getSystemService(inflater);
+ li.inflate(resource, igniter_view, true);
+
+ item.realize(igniter_view,
+ (TextView) igniter_view.findViewById(R.id.igniter_name),
+ (TextView) igniter_view.findViewById(R.id.igniter_status));
+ AltosDebug.debug("Realize new igniter view");
+ } else
+ AltosDebug.debug("Reuse existing igniter view");
+ if (position == selected_item)
+ item.igniter_view.setBackgroundColor(Color.RED);
+ else
+ item.igniter_view.setBackgroundColor(Color.BLACK);
+ return item.igniter_view;
+ }
+}
+
+public class IgniterActivity extends Activity {
+ private ListView igniters_view;
+ private ToggleButton arm;
+ private Button fire;
+
+ private HashMap<String,IgniterItem> igniters = new HashMap<String,IgniterItem>();;
+
+ private IgniterAdapter igniters_adapter;
+
+ private boolean is_bound;
+ private boolean timer_running;
+ private Messenger service = null;
+ private final Messenger messenger = new Messenger(new IncomingHandler(this));
+
+ private Timer timer;
+
+ public static final int IGNITER_QUERY = 1;
+ public static final int IGNITER_FIRE = 2;
+
+ // The Handler that gets information back from the Telemetry Service
+ static class IncomingHandler extends Handler {
+ private final WeakReference<IgniterActivity> igniter_activity;
+ IncomingHandler(IgniterActivity ia) { igniter_activity = new WeakReference<IgniterActivity>(ia); }
+
+ @Override
+ public void handleMessage(Message msg) {
+ IgniterActivity ia = igniter_activity.get();
+
+ switch (msg.what) {
+ case AltosDroid.MSG_IGNITER_STATUS:
+ ia.igniter_status((HashMap <String,Integer>) msg.obj);
+ break;
+ }
+ }
+ };
+
+
+ private ServiceConnection connection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder binder) {
+ service = new Messenger(binder);
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
+ service = null;
+ }
+ };
+
+ void doBindService() {
+ bindService(new Intent(this, TelemetryService.class), connection, Context.BIND_AUTO_CREATE);
+ is_bound = true;
+ }
+
+ void doUnbindService() {
+ if (is_bound) {
+ // If we have received the service, and hence registered with it, then now is the time to unregister.
+ unbindService(connection);
+ is_bound = false;
+ }
+ }
+
+ private void done() {
+ Intent intent = new Intent();
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ private void fire_igniter() {
+ }
+
+ private void arm_igniter(boolean is_checked) {
+ }
+
+ private synchronized void timer_tick() {
+ if (timer_running)
+ return;
+ timer_running = true;
+ try {
+ Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_QUERY);
+ msg.replyTo = messenger;
+ service.send(msg);
+ } catch (RemoteException re) {
+ }
+ }
+
+ private boolean set_igniter(HashMap <String,Integer> status, String name, String pretty) {
+ if (!status.containsKey(name))
+ return false;
+
+ IgniterItem item;
+ if (!igniters.containsKey(name)) {
+ item = new IgniterItem();
+ igniters.put(name, item);
+ igniters_adapter.add(item);
+ } else
+ item = igniters.get(name);
+
+ item.set(pretty, AltosIgnite.status_string(status.get(name)));
+ return true;
+ }
+
+ private synchronized void igniter_status(HashMap <String,Integer> status) {
+ timer_running = false;
+ if (status == null) {
+ AltosDebug.debug("no igniter status");
+ return;
+ }
+ set_igniter(status, "drogue", "Apogee");
+ set_igniter(status, "main", "Main");
+ for (int extra = 0;; extra++) {
+ String name = String.format("%d", extra);
+ String pretty = String.format("%c", 'A' + extra);
+ if (!set_igniter(status, name, pretty))
+ break;
+ }
+// if (igniters_adapter.selected_item >= 0)
+// igniters_view.setSelection(selected_item);
+ }
+
+ private class IgniterItemClickListener implements ListView.OnItemClickListener {
+ @Override
+ public void onItemClick(AdapterView<?> av, View v, int position, long id) {
+ if (igniters_adapter.selected_item >= 0)
+ igniters_view.setItemChecked(igniters_adapter.selected_item, false);
+ igniters_view.setItemChecked(position, true);
+ igniters_adapter.selected_item = position;
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.igniters);
+
+ igniters_view = (ListView) findViewById(R.id.igniters);
+ igniters_view.setClickable(true);
+
+ igniters_adapter = new IgniterAdapter(this, R.layout.igniter_status);
+
+ igniters_view.setAdapter(igniters_adapter);
+ igniters_view.setOnItemClickListener(new IgniterItemClickListener());
+
+ fire = (Button) findViewById(R.id.igniter_fire);
+ fire.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ fire_igniter();
+ }
+ });
+
+ arm = (ToggleButton) findViewById(R.id.igniter_arm);
+ arm.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener() {
+ public void onCheckedChanged(CompoundButton v, boolean is_checked) {
+ arm_igniter(is_checked);
+ }
+ });
+
+ // Set result CANCELED incase the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ doBindService();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ timer = new Timer(true);
+ timer.scheduleAtFixedRate(new TimerTask() {
+ public void run() {
+ timer_tick();
+ }},
+ 1000L, 1000L);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ timer.cancel();
+ timer = null;
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ doUnbindService();
+ }
+}
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
index 926109e2..4b26d263 100644
--- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
+++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
@@ -42,7 +42,7 @@ import android.location.Criteria;
import org.altusmetrum.altoslib_10.*;
-public class TelemetryService extends Service {
+public class TelemetryService extends Service implements AltosIdleMonitorListener {
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGISTER_CLIENT = 2;
@@ -58,6 +58,11 @@ public class TelemetryService extends Service {
static final int MSG_DISCONNECT = 12;
static final int MSG_DELETE_SERIAL = 13;
static final int MSG_BLUETOOTH_ENABLED = 14;
+ static final int MSG_MONITOR_IDLE_START= 15;
+ static final int MSG_MONITOR_IDLE_STOP = 16;
+ static final int MSG_REBOOT = 17;
+ static final int MSG_IGNITER_QUERY = 18;
+ static final int MSG_IGNITER_FIRE = 19;
// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
@@ -80,6 +85,13 @@ public class TelemetryService extends Service {
// Last data seen; send to UI when it starts
private TelemetryState telemetry_state;
+ // Idle monitor if active
+ AltosIdleMonitor idle_monitor = null;
+
+ // Igniter bits
+ AltosIgnite ignite = null;
+ boolean ignite_running;
+
// Handler of incoming messages from clients.
static class IncomingHandler extends Handler {
private final WeakReference<TelemetryService> service;
@@ -93,6 +105,7 @@ public class TelemetryService extends Service {
AltosDroidLink bt = null;
if (s == null)
return;
+
switch (msg.what) {
/* Messages from application */
@@ -212,6 +225,26 @@ public class TelemetryService extends Service {
if (address != null && !address.address.startsWith("USB"))
s.start_altos_bluetooth(address, false);
break;
+ case MSG_MONITOR_IDLE_START:
+ AltosDebug.debug("start monitor idle");
+ s.start_idle_monitor();
+ break;
+ case MSG_MONITOR_IDLE_STOP:
+ AltosDebug.debug("stop monitor idle");
+ s.stop_idle_monitor();
+ break;
+ case MSG_REBOOT:
+ AltosDebug.debug("reboot");
+ s.reboot_remote();
+ break;
+ case MSG_IGNITER_QUERY:
+ AltosDebug.debug("igniter query");
+ s.igniter_query(msg.replyTo);
+ break;
+ case MSG_IGNITER_FIRE:
+ AltosDebug.debug("igniter fire");
+ s.igniter_fire((String) msg.obj);
+ break;
default:
super.handleMessage(msg);
}
@@ -255,6 +288,7 @@ public class TelemetryService extends Service {
/* On connect, send the current state to the new client
*/
send_to_client(client);
+ send_idle_mode_to_client(client);
/* If we've got an address from a previous session, then
* go ahead and try to reconnect to the device
@@ -296,17 +330,29 @@ public class TelemetryService extends Service {
send_to_client(client);
}
- private void disconnect(boolean notify) {
- AltosDebug.debug("disconnect(): begin");
-
- telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
- telemetry_state.address = null;
+ private void send_idle_mode_to_client(Messenger client) {
+ Message m = Message.obtain(null, AltosDroid.MSG_IDLE_MODE, idle_monitor != null);
+ try {
+ client.send(m);
+ } catch (RemoteException e) {
+ AltosDebug.error("Client %s disappeared", client.toString());
+ remove_client(client);
+ }
+ }
- if (altos_link != null)
- altos_link.closing();
+ private void send_idle_mode_to_clients() {
+ for (Messenger client : clients)
+ send_idle_mode_to_client(client);
+ }
- stop_receiver_voltage_timer();
+ private void telemetry_start() {
+ if (telemetry_reader == null && idle_monitor == null && !ignite_running) {
+ telemetry_reader = new TelemetryReader(altos_link, handler);
+ telemetry_reader.start();
+ }
+ }
+ private void telemetry_stop() {
if (telemetry_reader != null) {
AltosDebug.debug("disconnect(): stopping TelemetryReader");
telemetry_reader.interrupt();
@@ -316,6 +362,23 @@ public class TelemetryService extends Service {
}
telemetry_reader = null;
}
+ }
+
+ private void disconnect(boolean notify) {
+ AltosDebug.debug("disconnect(): begin");
+
+ telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
+ telemetry_state.address = null;
+
+ if (idle_monitor != null)
+ stop_idle_monitor();
+
+ if (altos_link != null)
+ altos_link.closing();
+
+ stop_receiver_voltage_timer();
+
+ telemetry_stop();
if (telemetry_logger != null) {
AltosDebug.debug("disconnect(): stopping TelemetryLogger");
telemetry_logger.stop();
@@ -325,6 +388,7 @@ public class TelemetryService extends Service {
AltosDebug.debug("disconnect(): stopping AltosDroidLink");
altos_link.close();
altos_link = null;
+ ignite = null;
}
telemetry_state.config = null;
if (notify) {
@@ -373,14 +437,95 @@ public class TelemetryService extends Service {
send_to_clients();
}
+ private void start_idle_monitor() {
+ if (altos_link != null && idle_monitor == null) {
+ telemetry_stop();
+ idle_monitor = new AltosIdleMonitor(this, altos_link, true, false);
+ idle_monitor.set_callsign(AltosPreferences.callsign());
+ idle_monitor.start();
+ send_idle_mode_to_clients();
+ }
+ }
+
+ private void stop_idle_monitor() {
+ if (idle_monitor != null) {
+ try {
+ idle_monitor.abort();
+ } catch (InterruptedException ie) {
+ }
+ idle_monitor = null;
+ telemetry_start();
+ send_idle_mode_to_clients();
+ }
+ }
+
+ private void reboot_remote() {
+ if (altos_link != null) {
+ stop_idle_monitor();
+ try {
+ altos_link.start_remote();
+ altos_link.printf("r eboot\n");
+ altos_link.flush_output();
+ } catch (TimeoutException te) {
+ } catch (InterruptedException ie) {
+ } finally {
+ try {
+ altos_link.stop_remote();
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+ }
+
+ private void ensure_ignite() {
+ if (ignite == null)
+ ignite = new AltosIgnite(altos_link, true, false);
+ }
+
+ private synchronized void igniter_query(Messenger client) {
+ ensure_ignite();
+ HashMap<String,Integer> status_map = null;
+ ignite_running = true;
+ try {
+ stop_idle_monitor();
+ try {
+ status_map = ignite.status();
+ } catch (InterruptedException ie) {
+ AltosDebug.debug("ignite.status interrupted");
+ } catch (TimeoutException te) {
+ AltosDebug.debug("ignite.status timeout");
+ }
+ } finally {
+ ignite_running = false;
+ }
+ Message m = Message.obtain(null, AltosDroid.MSG_IGNITER_STATUS, status_map);
+ try {
+ client.send(m);
+ } catch (RemoteException e) {
+ }
+ }
+
+ private synchronized void igniter_fire(String igniter) {
+ ensure_ignite();
+ ignite_running = true;
+ stop_idle_monitor();
+ try {
+ ignite.fire(igniter);
+ } catch (InterruptedException ie) {
+ } finally {
+ ignite_running = false;
+ }
+ }
+
// Timer for receiver battery voltage monitoring
Timer receiver_voltage_timer;
private void update_receiver_voltage() {
- if (altos_link != null) {
+ if (altos_link != null && idle_monitor == null && !ignite_running) {
try {
double voltage = altos_link.monitor_battery();
telemetry_state.receiver_battery = voltage;
+ send_to_clients();
} catch (InterruptedException ie) {
}
}
@@ -428,8 +573,7 @@ public class TelemetryService extends Service {
telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;
telemetry_state.address = address;
- telemetry_reader = new TelemetryReader(altos_link, handler);
- telemetry_reader.start();
+ telemetry_start();
AltosDebug.debug("connected TelemetryReader started");
@@ -549,4 +693,14 @@ public class TelemetryService extends Service {
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
+
+ /* AltosIdleMonitorListener */
+ public void update(AltosState state, AltosListenerState listener_state) {
+ telemetry_state.states.put(state.serial, state);
+ telemetry_state.receiver_battery = listener_state.battery;
+ send_to_clients();
+ }
+
+ public void failed() {
+ }
}