2 * Copyright © 2010 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; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 import java.awt.event.*;
25 import java.util.concurrent.*;
26 import org.altusmetrum.altoslib_1.*;
27 import org.altusmetrum.altosuilib_1.*;
29 public class AltosIgniteUI
31 implements ActionListener
37 JLabel apogee_status_label;
39 JLabel main_status_label;
42 javax.swing.Timer timer;
48 final static int timeout = 1 * 1000;
51 boolean timer_running;
53 LinkedBlockingQueue<String> command_queue;
55 class IgniteHandler implements Runnable {
59 void send_exception(Exception e) {
60 final Exception f_e = e;
61 Runnable r = new Runnable() {
63 ignite_exception(f_e);
66 SwingUtilities.invokeLater(r);
71 AltosSerial serial = new AltosSerial(device);
72 serial.set_frame(owner);
73 ignite = new AltosIgnite(serial,
74 !device.matchProduct(Altos.product_altimeter));
76 } catch (Exception e) {
85 String command = command_queue.take();
88 if (command.equals("get_status")) {
89 apogee_status = ignite.status(AltosIgnite.Apogee);
90 main_status = ignite.status(AltosIgnite.Main);
92 } else if (command.equals("main")) {
93 ignite.fire(AltosIgnite.Main);
95 } else if (command.equals("apogee")) {
96 ignite.fire(AltosIgnite.Apogee);
98 } else if (command.equals("quit")) {
102 throw new ParseException(String.format("invalid command %s", command), 0);
104 final String f_reply = reply;
107 ignite_reply(f_reply);
110 SwingUtilities.invokeLater(r);
111 } catch (Exception e) {
117 public IgniteHandler(JFrame in_owner) {
122 void ignite_exception(Exception e) {
123 if (e instanceof FileNotFoundException) {
124 JOptionPane.showMessageDialog(owner,
125 ((FileNotFoundException) e).getMessage(),
126 "Cannot open target device",
127 JOptionPane.ERROR_MESSAGE);
128 } else if (e instanceof AltosSerialInUseException) {
129 JOptionPane.showMessageDialog(owner,
130 String.format("Device \"%s\" already in use",
131 device.toShortString()),
133 JOptionPane.ERROR_MESSAGE);
134 } else if (e instanceof IOException) {
135 IOException ee = (IOException) e;
136 JOptionPane.showMessageDialog(owner,
137 device.toShortString(),
138 ee.getLocalizedMessage(),
139 JOptionPane.ERROR_MESSAGE);
141 JOptionPane.showMessageDialog(owner,
142 String.format("Connection to \"%s\" failed",
143 device.toShortString()),
145 JOptionPane.ERROR_MESSAGE);
150 void ignite_reply(String reply) {
151 if (reply.equals("status")) {
153 } else if (reply.equals("fired")) {
158 void set_arm_text() {
159 if (arm.isSelected())
160 arm.setText(String.format("%d", time_remaining));
168 timer_running = true;
173 arm.setSelected(false);
174 arm.setEnabled(false);
175 fire.setEnabled(false);
176 timer_running = false;
181 apogee.setSelected(false);
182 main.setSelected(false);
183 fire.setEnabled(false);
187 void send_command(String command) {
189 command_queue.put(command);
190 } catch (Exception ex) {
191 ignite_exception(ex);
195 boolean getting_status = false;
197 boolean visible = false;
198 void set_ignite_status() {
199 getting_status = false;
200 apogee_status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(apogee_status)));
201 main_status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(main_status)));
208 void poll_ignite_status() {
209 if (!getting_status) {
210 getting_status = true;
211 send_command("get_status");
215 boolean firing = false;
217 void start_fire(String which) {
230 send_command("quit");
239 if (time_remaining <= 0)
244 poll_ignite_status();
248 if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) {
249 String igniter = "none";
250 if (apogee.isSelected() && !main.isSelected())
252 else if (main.isSelected() && !apogee.isSelected())
254 send_command(igniter);
259 public void actionPerformed(ActionEvent e) {
260 String cmd = e.getActionCommand();
261 if (cmd.equals("apogee") || cmd.equals("main")) {
265 if (cmd.equals("apogee") && apogee.isSelected()) {
266 main.setSelected(false);
267 arm.setEnabled(true);
269 if (cmd.equals("main") && main.isSelected()) {
270 apogee.setSelected(false);
271 arm.setEnabled(true);
274 if (cmd.equals("arm")) {
275 if (arm.isSelected()) {
276 fire.setEnabled(true);
281 if (cmd.equals("fire"))
283 if (cmd.equals("tick"))
285 if (cmd.equals("close")) {
290 /* A window listener to catch closing events and tell the config code */
291 class ConfigListener extends WindowAdapter {
294 public ConfigListener(AltosIgniteUI this_ui) {
298 public void windowClosing(WindowEvent e) {
299 ui.actionPerformed(new ActionEvent(e.getSource(),
300 ActionEvent.ACTION_PERFORMED,
305 private boolean open() {
306 command_queue = new LinkedBlockingQueue<String>();
308 device = AltosDeviceUIDialog.show(owner, Altos.product_any);
309 if (device != null) {
310 IgniteHandler handler = new IgniteHandler(owner);
311 Thread t = new Thread(handler);
318 public AltosIgniteUI(JFrame in_owner) {
321 apogee_status = AltosIgnite.Unknown;
322 main_status = AltosIgnite.Unknown;
327 Container pane = getContentPane();
328 GridBagConstraints c = new GridBagConstraints();
329 Insets i = new Insets(4,4,4,4);
331 timer = new javax.swing.Timer(timeout, this);
332 timer.setActionCommand("tick");
333 timer_running = false;
338 pane.setLayout(new GridBagLayout());
340 c.fill = GridBagConstraints.NONE;
341 c.anchor = GridBagConstraints.CENTER;
349 c.anchor = GridBagConstraints.CENTER;
350 label = new JLabel ("Fire Igniter");
356 c.anchor = GridBagConstraints.WEST;
357 apogee = new JRadioButton ("Apogee");
359 apogee.addActionListener(this);
360 apogee.setActionCommand("apogee");
365 c.anchor = GridBagConstraints.WEST;
366 apogee_status_label = new JLabel();
367 pane.add(apogee_status_label, c);
372 c.anchor = GridBagConstraints.WEST;
373 main = new JRadioButton ("Main");
375 main.addActionListener(this);
376 main.setActionCommand("main");
381 c.anchor = GridBagConstraints.WEST;
382 main_status_label = new JLabel();
383 pane.add(main_status_label, c);
388 c.anchor = GridBagConstraints.CENTER;
389 arm = new JToggleButton ("Arm");
391 arm.addActionListener(this);
392 arm.setActionCommand("arm");
393 arm.setEnabled(false);
398 c.anchor = GridBagConstraints.CENTER;
399 fire = new JButton ("Fire");
400 fire.setEnabled(false);
402 fire.addActionListener(this);
403 fire.setActionCommand("fire");
408 c.anchor = GridBagConstraints.CENTER;
409 close = new JButton ("Close");
411 close.addActionListener(this);
412 close.setActionCommand("close");
415 setLocationRelativeTo(owner);
417 addWindowListener(new ConfigListener(this));