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_14.*;
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(0);
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 @SuppressWarnings("unchecked") HashMap<String,Integer> map = (HashMap <String,Integer>) msg.obj;
143 ia.igniter_status(map);
150 private ServiceConnection connection = new ServiceConnection() {
151 public void onServiceConnected(ComponentName className, IBinder binder) {
152 service = new Messenger(binder);
156 public void onServiceDisconnected(ComponentName className) {
157 // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
162 void doBindService() {
163 bindService(new Intent(this, TelemetryService.class), connection, Context.BIND_AUTO_CREATE);
167 void doUnbindService() {
169 // If we have received the service, and hence registered with it, then now is the time to unregister.
170 unbindService(connection);
175 private void done() {
176 Intent intent = new Intent();
177 setResult(Activity.RESULT_OK, intent);
181 class FireThread extends Thread {
182 private final String igniter;
186 Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_FIRE, igniter);
189 } catch (RemoteException re) {
193 public FireThread(String igniter) {
194 this.igniter = igniter;
198 private void fire_igniter() {
199 if (igniters_adapter.selected_item >= 0) {
200 IgniterItem item = igniters_adapter.getItem(igniters_adapter.selected_item);
201 FireThread ft = new FireThread(item.name);
203 arm.setChecked(false);
207 private void arm_igniter(boolean is_checked) {
210 arm_timer = new Timer();
213 fire.setEnabled(true);
214 arm_timer.scheduleAtFixedRate(new TimerTask() {
221 fire.setEnabled(false);
225 private synchronized void query_timer_tick() {
226 if (query_timer_running)
230 query_timer_running = true;
231 Thread thread = new Thread(new Runnable() {
234 Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_QUERY);
235 msg.replyTo = messenger;
236 if (service == null) {
237 synchronized(IgniterActivity.this) {
238 query_timer_running = false;
242 } catch (RemoteException re) {
243 AltosDebug.debug("igniter query thread failed");
244 synchronized(IgniterActivity.this) {
245 query_timer_running = false;
253 private boolean set_igniter(HashMap <String,Integer> status, String name, String pretty) {
254 if (!status.containsKey(name))
258 if (!igniters.containsKey(name)) {
259 item = new IgniterItem();
260 igniters.put(name, item);
261 igniters_adapter.add(item);
263 item = igniters.get(name);
265 item.set(name, pretty, AltosIgnite.status_string(status.get(name)));
269 private synchronized void igniter_status(HashMap <String,Integer> status) {
270 query_timer_running = false;
271 if (status == null) {
272 AltosDebug.debug("no igniter status");
275 set_igniter(status, "drogue", "Apogee");
276 set_igniter(status, "main", "Main");
277 for (int extra = 0;; extra++) {
278 String name = String.format("%d", extra);
279 String pretty = String.format("%c", 'A' + extra);
280 if (!set_igniter(status, name, pretty))
285 private synchronized void arm_timer_stop() {
286 if (arm_timer != null) {
293 private void arm_set_text() {
294 String text = String.format("Armed %d", arm_remaining);
301 private void arm_timer_tick() {
303 if (arm_remaining <= 0) {
305 runOnUiThread(new Runnable() {
307 arm.setChecked(false);
308 fire.setEnabled(false);
312 runOnUiThread(new Runnable() {
320 private void select_item(int position) {
321 if (position != igniters_adapter.selected_item) {
322 if (igniters_adapter.selected_item >= 0)
323 igniters_view.setItemChecked(igniters_adapter.selected_item, false);
325 igniters_view.setItemChecked(position, true);
326 arm.setEnabled(true);
328 arm.setEnabled(false);
329 igniters_adapter.selected_item = position;
333 private class IgniterItemClickListener implements ListView.OnItemClickListener {
335 public void onItemClick(AdapterView<?> av, View v, int position, long id) {
336 AltosDebug.debug("select %d\n", position);
337 select_item(position);
342 protected void onCreate(Bundle savedInstanceState) {
343 setTheme(AltosDroid.dialog_themes[AltosDroidPreferences.font_size()]);
344 super.onCreate(savedInstanceState);
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() {