altosui: Add eeprom 'manage' ui to download and delete multiple flights
[fw/altos] / altosui / AltosEepromDownload.java
1 /*
2  * Copyright © 2010 Keith Packard <keithp@keithp.com>
3  *
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.
7  *
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.
12  *
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.
16  */
17
18 package altosui;
19
20 import java.awt.*;
21 import java.awt.event.*;
22 import javax.swing.*;
23 import javax.swing.filechooser.FileNameExtensionFilter;
24 import javax.swing.table.*;
25 import java.io.*;
26 import java.util.*;
27 import java.text.*;
28 import java.util.prefs.*;
29 import java.util.concurrent.*;
30
31 import libaltosJNI.*;
32
33 public class AltosEepromDownload implements Runnable {
34
35         JFrame                  frame;
36         AltosSerial             serial_line;
37         boolean                 remote;
38         Thread                  eeprom_thread;
39         AltosEepromMonitor      monitor;
40         int                     flight = 0;
41         int                     year = 0, month = 0, day = 0;
42         boolean                 want_file = false;
43         FileWriter              eeprom_file = null;
44         LinkedList<String>      eeprom_pending = new LinkedList<String>();
45         AltosEepromList         flights;
46         ActionListener          listener;
47         boolean                 success;
48
49         private void FlushPending() throws IOException {
50                 for (String s : flights.config_data) {
51                         eeprom_file.write(s);
52                         eeprom_file.write('\n');
53                 }
54
55                 for (String s : eeprom_pending)
56                         eeprom_file.write(s);
57         }
58
59         private void CheckFile(boolean force) throws IOException {
60                 if (eeprom_file != null)
61                         return;
62                 if (force || (flight != 0 && want_file)) {
63                         AltosFile               eeprom_name;
64                         if (year != 0 && month != 0 && day != 0)
65                                 eeprom_name = new AltosFile(year, month, day, flights.config_data.serial, flight, "eeprom");
66                         else
67                                 eeprom_name = new AltosFile(flights.config_data.serial, flight, "eeprom");
68
69                         eeprom_file = new FileWriter(eeprom_name);
70                         if (eeprom_file != null) {
71                                 monitor.set_file(eeprom_name.getName());
72                                 FlushPending();
73                                 eeprom_pending = null;
74                         }
75                 }
76         }
77
78         void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException {
79                 int                     block, state_block = 0;
80                 int                     state = 0;
81                 boolean                 done = false;
82                 int                     record;
83
84                 if (flights.config_data.serial == 0)
85                         throw new IOException("no serial number found");
86
87                 monitor.set_serial(flights.config_data.serial);
88                 /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */
89
90                 state = 0; state_block = log.start_block;
91                 for (block = log.start_block; !done && block < log.end_block; block++) {
92                         monitor.set_value(Altos.state_to_string[state], state, block - state_block);
93
94                         AltosEepromBlock        eeblock = new AltosEepromBlock(serial_line, block);
95
96                         if (eeblock.has_flight) {
97                                 flight = eeblock.flight;
98                                 monitor.set_flight(flight);
99                         }
100                         if (eeblock.has_date) {
101                                 year = eeblock.year;
102                                 month = eeblock.month;
103                                 day = eeblock.day;
104                                 want_file = true;
105                         }
106
107                         if (eeblock.size() == 0 ||
108                             eeblock.has_state && eeblock.state == Altos.ao_flight_landed)
109                                         done = true;
110
111                         /* Monitor state transitions to update display */
112                         if (eeblock.has_state) {
113                                 if (eeblock.state > Altos.ao_flight_pad)
114                                         want_file = true;
115                                 if (eeblock.state > state)
116                                         state = eeblock.state;
117                         }
118
119                         CheckFile(false);
120
121                         for (record = 0; record < eeblock.size(); record++) {
122                                 AltosEepromRecord r = eeblock.get(record);
123
124                                 String log_line = String.format("%c %4x %4x %4x\n",
125                                                                 r.cmd, r.tick, r.a, r.b);
126                                 if (eeprom_file != null)
127                                         eeprom_file.write(log_line);
128                                 else
129                                         eeprom_pending.add(log_line);
130                         }
131                 }
132                 CheckFile(true);
133                 if (eeprom_file != null) {
134                         eeprom_file.flush();
135                         eeprom_file.close();
136                 }
137         }
138
139         private void show_error_internal(String message, String title) {
140                 JOptionPane.showMessageDialog(frame,
141                                               message,
142                                               title,
143                                               JOptionPane.ERROR_MESSAGE);
144         }
145
146         private void show_error(String in_message, String in_title) {
147                 final String message = in_message;
148                 final String title = in_title;
149                 Runnable r = new Runnable() {
150                                 public void run() {
151                                         try {
152                                                 show_error_internal(message, title);
153                                         } catch (Exception ex) {
154                                         }
155                                 }
156                         };
157                 SwingUtilities.invokeLater(r);
158         }
159
160         public void run () {
161                 if (remote)
162                         serial_line.start_remote();
163
164                 try {
165                         for (AltosEepromLog log : flights) {
166                                 if (log.download) {
167                                         monitor.reset();
168                                         CaptureLog(log);
169                                 }
170                         }
171                         System.out.printf("All flights successfully downloaded\n");
172                         success = true;
173                 } catch (IOException ee) {
174                         show_error (serial_line.device.toShortString(),
175                                     ee.getLocalizedMessage());
176                 } catch (InterruptedException ie) {
177                 } catch (TimeoutException te) {
178                         show_error (String.format("Connection to \"%s\" failed",
179                                                   serial_line.device.toShortString()),
180                                     "Connection Failed");
181                 }
182                 if (remote)
183                         serial_line.stop_remote();
184                 monitor.done();
185                 serial_line.flush_output();
186                 if (listener != null) {
187                         Runnable r = new Runnable() {
188                                         public void run() {
189                                                 try {
190                                                         listener.actionPerformed(new ActionEvent(this,
191                                                                                                  success ? 1 : 0,
192                                                                                                  "download"));
193                                                 } catch (Exception ex) {
194                                                 }
195                                         }
196                                 };
197                         SwingUtilities.invokeLater(r);
198                 }
199         }
200
201         public void start() {
202                 eeprom_thread = new Thread(this);
203                 eeprom_thread.start();
204         }
205
206         public void addActionListener(ActionListener l) {
207                 listener = l;
208         }
209
210         public AltosEepromDownload(JFrame given_frame,
211                                    AltosSerial given_serial_line,
212                                    boolean given_remote,
213                                    AltosEepromList given_flights) {
214
215                 frame = given_frame;
216                 serial_line = given_serial_line;
217                 remote = given_remote;
218                 flights = given_flights;
219                 success = false;
220
221                 monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed);
222                 monitor.addActionListener(new ActionListener() {
223                                 public void actionPerformed(ActionEvent e) {
224                                         if (eeprom_thread != null)
225                                                 eeprom_thread.interrupt();
226                                 }
227                         });
228         }
229 }