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.*;
28 public class AltosIgniteUI
30 implements ActionListener
36 JLabel apogee_status_label;
38 JLabel main_status_label;
41 javax.swing.Timer timer;
47 final static int timeout = 1 * 1000;
50 boolean timer_running;
52 LinkedBlockingQueue<String> command_queue;
54 class IgniteHandler implements Runnable {
58 void send_exception(Exception e) {
59 final Exception f_e = e;
60 Runnable r = new Runnable() {
62 ignite_exception(f_e);
65 SwingUtilities.invokeLater(r);
70 AltosSerial serial = new AltosSerial(device);
71 serial.set_frame(owner);
72 ignite = new AltosIgnite(serial,
73 !device.matchProduct(Altos.product_altimeter));
75 } catch (Exception e) {
84 String command = command_queue.take();
87 if (command.equals("get_status")) {
88 apogee_status = ignite.status(AltosIgnite.Apogee);
89 main_status = ignite.status(AltosIgnite.Main);
91 } else if (command.equals("main")) {
92 ignite.fire(AltosIgnite.Main);
94 } else if (command.equals("apogee")) {
95 ignite.fire(AltosIgnite.Apogee);
97 } else if (command.equals("quit")) {
101 throw new ParseException(String.format("invalid command %s", command), 0);
103 final String f_reply = reply;
106 ignite_reply(f_reply);
109 SwingUtilities.invokeLater(r);
110 } catch (Exception e) {
116 public IgniteHandler(JFrame in_owner) {
121 void ignite_exception(Exception e) {
122 if (e instanceof FileNotFoundException) {
123 JOptionPane.showMessageDialog(owner,
124 ((FileNotFoundException) e).getMessage(),
125 "Cannot open target device",
126 JOptionPane.ERROR_MESSAGE);
127 } else if (e instanceof AltosSerialInUseException) {
128 JOptionPane.showMessageDialog(owner,
129 String.format("Device \"%s\" already in use",
130 device.toShortString()),
132 JOptionPane.ERROR_MESSAGE);
133 } else if (e instanceof IOException) {
134 IOException ee = (IOException) e;
135 JOptionPane.showMessageDialog(owner,
136 device.toShortString(),
137 ee.getLocalizedMessage(),
138 JOptionPane.ERROR_MESSAGE);
140 JOptionPane.showMessageDialog(owner,
141 String.format("Connection to \"%s\" failed",
142 device.toShortString()),
144 JOptionPane.ERROR_MESSAGE);
149 void ignite_reply(String reply) {
150 if (reply.equals("status")) {
152 } else if (reply.equals("fired")) {
157 void set_arm_text() {
158 if (arm.isSelected())
159 arm.setText(String.format("%d", time_remaining));
167 timer_running = true;
172 arm.setSelected(false);
173 arm.setEnabled(false);
174 fire.setEnabled(false);
175 timer_running = false;
180 apogee.setSelected(false);
181 main.setSelected(false);
182 fire.setEnabled(false);
186 void send_command(String command) {
188 command_queue.put(command);
189 } catch (Exception ex) {
190 ignite_exception(ex);
194 boolean getting_status = false;
196 boolean visible = false;
197 void set_ignite_status() {
198 getting_status = false;
199 apogee_status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(apogee_status)));
200 main_status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(main_status)));
207 void poll_ignite_status() {
208 if (!getting_status) {
209 getting_status = true;
210 send_command("get_status");
214 boolean firing = false;
216 void start_fire(String which) {
229 send_command("quit");
238 if (time_remaining <= 0)
243 poll_ignite_status();
247 if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) {
248 String igniter = "none";
249 if (apogee.isSelected() && !main.isSelected())
251 else if (main.isSelected() && !apogee.isSelected())
253 send_command(igniter);
258 public void actionPerformed(ActionEvent e) {
259 String cmd = e.getActionCommand();
260 if (cmd.equals("apogee") || cmd.equals("main")) {
264 if (cmd.equals("apogee") && apogee.isSelected()) {
265 main.setSelected(false);
266 arm.setEnabled(true);
268 if (cmd.equals("main") && main.isSelected()) {
269 apogee.setSelected(false);
270 arm.setEnabled(true);
273 if (cmd.equals("arm")) {
274 if (arm.isSelected()) {
275 fire.setEnabled(true);
280 if (cmd.equals("fire"))
282 if (cmd.equals("tick"))
284 if (cmd.equals("close")) {
289 /* A window listener to catch closing events and tell the config code */
290 class ConfigListener extends WindowAdapter {
293 public ConfigListener(AltosIgniteUI this_ui) {
297 public void windowClosing(WindowEvent e) {
298 ui.actionPerformed(new ActionEvent(e.getSource(),
299 ActionEvent.ACTION_PERFORMED,
304 private boolean open() {
305 command_queue = new LinkedBlockingQueue<String>();
307 device = AltosDeviceDialog.show(owner, Altos.product_any);
308 if (device != null) {
309 IgniteHandler handler = new IgniteHandler(owner);
310 Thread t = new Thread(handler);
317 public AltosIgniteUI(JFrame in_owner) {
320 apogee_status = AltosIgnite.Unknown;
321 main_status = AltosIgnite.Unknown;
326 Container pane = getContentPane();
327 GridBagConstraints c = new GridBagConstraints();
328 Insets i = new Insets(4,4,4,4);
330 timer = new javax.swing.Timer(timeout, this);
331 timer.setActionCommand("tick");
332 timer_running = false;
337 pane.setLayout(new GridBagLayout());
339 c.fill = GridBagConstraints.NONE;
340 c.anchor = GridBagConstraints.CENTER;
348 c.anchor = GridBagConstraints.CENTER;
349 label = new JLabel ("Fire Igniter");
355 c.anchor = GridBagConstraints.WEST;
356 apogee = new JRadioButton ("Apogee");
358 apogee.addActionListener(this);
359 apogee.setActionCommand("apogee");
364 c.anchor = GridBagConstraints.WEST;
365 apogee_status_label = new JLabel();
366 pane.add(apogee_status_label, c);
371 c.anchor = GridBagConstraints.WEST;
372 main = new JRadioButton ("Main");
374 main.addActionListener(this);
375 main.setActionCommand("main");
380 c.anchor = GridBagConstraints.WEST;
381 main_status_label = new JLabel();
382 pane.add(main_status_label, c);
387 c.anchor = GridBagConstraints.CENTER;
388 arm = new JToggleButton ("Arm");
390 arm.addActionListener(this);
391 arm.setActionCommand("arm");
392 arm.setEnabled(false);
397 c.anchor = GridBagConstraints.CENTER;
398 fire = new JButton ("Fire");
399 fire.setEnabled(false);
401 fire.addActionListener(this);
402 fire.setActionCommand("fire");
407 c.anchor = GridBagConstraints.CENTER;
408 close = new JButton ("Close");
410 close.addActionListener(this);
411 close.setActionCommand("close");
414 setLocationRelativeTo(owner);
416 addWindowListener(new ConfigListener(this));