2 * Copyright © 2016 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 package org.altusmetrum.AltosDroid;
21 import java.lang.ref.WeakReference;
24 import android.app.Activity;
25 import android.content.*;
26 import android.graphics.*;
28 import android.view.*;
29 import android.view.View.*;
30 import android.widget.*;
32 import org.altusmetrum.altoslib_13.*;
38 public LinearLayout igniter_view = null;
39 public TextView pretty_view = null;
40 public TextView status_view = null;
42 private void update() {
43 if (pretty_view != null)
44 pretty_view.setText(pretty);
45 if (status_view != null)
46 status_view.setText(status);
49 public void set(String name, String pretty, String status) {
50 if (!name.equals(this.name) ||
51 !pretty.equals(this.pretty) ||
52 !status.equals(this.status))
61 public void realize(LinearLayout igniter_view,
63 TextView status_view) {
64 if (igniter_view != this.igniter_view ||
65 pretty_view != this.pretty_view ||
66 status_view != this.status_view)
68 this.igniter_view = igniter_view;
69 this.pretty_view = pretty_view;
70 this.status_view = status_view;
75 public IgniterItem() {
79 class IgniterAdapter extends ArrayAdapter<IgniterItem> {
81 int selected_item = -1;
83 public IgniterAdapter(Context context, int in_resource) {
84 super(context, in_resource);
85 resource = in_resource;
89 public View getView(int position, View convertView, ViewGroup parent) {
90 IgniterItem item = getItem(position);
91 if (item.igniter_view == null) {
92 LinearLayout igniter_view = new LinearLayout(getContext());
93 String inflater = Context.LAYOUT_INFLATER_SERVICE;
94 LayoutInflater li = (LayoutInflater) getContext().getSystemService(inflater);
95 li.inflate(resource, igniter_view, true);
97 item.realize(igniter_view,
98 (TextView) igniter_view.findViewById(R.id.igniter_name),
99 (TextView) igniter_view.findViewById(R.id.igniter_status));
101 if (position == selected_item)
102 item.igniter_view.setBackgroundColor(Color.RED);
104 item.igniter_view.setBackgroundColor(Color.WHITE);
105 return item.igniter_view;
109 public class IgniterActivity extends Activity {
110 private ListView igniters_view;
111 private ToggleButton arm;
114 private HashMap<String,IgniterItem> igniters = new HashMap<String,IgniterItem>();;
116 private IgniterAdapter igniters_adapter;
118 private boolean is_bound;
119 private Messenger service = null;
120 private final Messenger messenger = new Messenger(new IncomingHandler(this));
122 private Timer query_timer;
123 private boolean query_timer_running;
125 private Timer arm_timer;
126 private int arm_remaining;
128 public static final int IGNITER_QUERY = 1;
129 public static final int IGNITER_FIRE = 2;
131 // The Handler that gets information back from the Telemetry Service
132 static class IncomingHandler extends Handler {
133 private final WeakReference<IgniterActivity> igniter_activity;
134 IncomingHandler(IgniterActivity ia) { igniter_activity = new WeakReference<IgniterActivity>(ia); }
137 public void handleMessage(Message msg) {
138 IgniterActivity ia = igniter_activity.get();
141 case AltosDroid.MSG_IGNITER_STATUS:
142 ia.igniter_status((HashMap <String,Integer>) msg.obj);
149 private ServiceConnection connection = new ServiceConnection() {
150 public void onServiceConnected(ComponentName className, IBinder binder) {
151 service = new Messenger(binder);
155 public void onServiceDisconnected(ComponentName className) {
156 // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
161 void doBindService() {
162 bindService(new Intent(this, TelemetryService.class), connection, Context.BIND_AUTO_CREATE);
166 void doUnbindService() {
168 // If we have received the service, and hence registered with it, then now is the time to unregister.
169 unbindService(connection);
174 private void done() {
175 Intent intent = new Intent();
176 setResult(Activity.RESULT_OK, intent);
180 class FireThread extends Thread {
181 private final String igniter;
185 Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_FIRE, igniter);
188 } catch (RemoteException re) {
192 public FireThread(String igniter) {
193 this.igniter = igniter;
197 private void fire_igniter() {
198 if (igniters_adapter.selected_item >= 0) {
199 IgniterItem item = igniters_adapter.getItem(igniters_adapter.selected_item);
200 FireThread ft = new FireThread(item.name);
202 arm.setChecked(false);
206 private void arm_igniter(boolean is_checked) {
209 arm_timer = new Timer();
212 fire.setEnabled(true);
213 arm_timer.scheduleAtFixedRate(new TimerTask() {
220 fire.setEnabled(false);
224 private synchronized void query_timer_tick() {
225 if (query_timer_running)
229 query_timer_running = true;
230 Thread thread = new Thread(new Runnable() {
233 Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_QUERY);
234 msg.replyTo = messenger;
235 if (service == null) {
236 synchronized(IgniterActivity.this) {
237 query_timer_running = false;
241 } catch (RemoteException re) {
242 AltosDebug.debug("igniter query thread failed");
243 synchronized(IgniterActivity.this) {
244 query_timer_running = false;
252 private boolean set_igniter(HashMap <String,Integer> status, String name, String pretty) {
253 if (!status.containsKey(name))
257 if (!igniters.containsKey(name)) {
258 item = new IgniterItem();
259 igniters.put(name, item);
260 igniters_adapter.add(item);
262 item = igniters.get(name);
264 item.set(name, pretty, AltosIgnite.status_string(status.get(name)));
268 private synchronized void igniter_status(HashMap <String,Integer> status) {
269 query_timer_running = false;
270 if (status == null) {
271 AltosDebug.debug("no igniter status");
274 set_igniter(status, "drogue", "Apogee");
275 set_igniter(status, "main", "Main");
276 for (int extra = 0;; extra++) {
277 String name = String.format("%d", extra);
278 String pretty = String.format("%c", 'A' + extra);
279 if (!set_igniter(status, name, pretty))
284 private synchronized void arm_timer_stop() {
285 if (arm_timer != null) {
292 private void arm_set_text() {
293 String text = String.format("Armed %d", arm_remaining);
300 private void arm_timer_tick() {
302 if (arm_remaining <= 0) {
304 runOnUiThread(new Runnable() {
306 arm.setChecked(false);
307 fire.setEnabled(false);
311 runOnUiThread(new Runnable() {
319 private void select_item(int position) {
320 if (position != igniters_adapter.selected_item) {
321 if (igniters_adapter.selected_item >= 0)
322 igniters_view.setItemChecked(igniters_adapter.selected_item, false);
324 igniters_view.setItemChecked(position, true);
325 arm.setEnabled(true);
327 arm.setEnabled(false);
328 igniters_adapter.selected_item = position;
332 private class IgniterItemClickListener implements ListView.OnItemClickListener {
334 public void onItemClick(AdapterView<?> av, View v, int position, long id) {
335 AltosDebug.debug("select %d\n", position);
336 select_item(position);
341 protected void onCreate(Bundle savedInstanceState) {
342 setTheme(AltosDroid.dialog_themes[AltosDroidPreferences.font_size()]);
343 super.onCreate(savedInstanceState);
346 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
347 setContentView(R.layout.igniters);
349 igniters_view = (ListView) findViewById(R.id.igniters);
350 igniters_view.setClickable(true);
352 igniters_adapter = new IgniterAdapter(this, R.layout.igniter_status);
354 igniters_view.setAdapter(igniters_adapter);
355 igniters_view.setOnItemClickListener(new IgniterItemClickListener());
357 fire = (Button) findViewById(R.id.igniter_fire);
358 fire.setEnabled(false);
359 fire.setOnClickListener(new OnClickListener() {
360 public void onClick(View v) {
365 arm = (ToggleButton) findViewById(R.id.igniter_arm);
366 arm.setEnabled(false);
367 arm.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener() {
368 public void onCheckedChanged(CompoundButton v, boolean is_checked) {
369 arm_igniter(is_checked);
373 // Set result CANCELED incase the user backs out
374 setResult(Activity.RESULT_CANCELED);
378 protected void onStart() {
384 protected void onResume() {
386 query_timer = new Timer(true);
387 query_timer.scheduleAtFixedRate(new TimerTask() {
395 protected void onPause() {
397 if (query_timer != null) {
398 query_timer.cancel();
402 arm.setChecked(false);
403 fire.setEnabled(false);
407 protected void onStop() {