Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
[fw/altos] / altosdroid / src / org / altusmetrum / AltosDroid / TelemetryReader.java
1 /*
2  * Copyright © 2011 Keith Packard <keithp@keithp.com>
3  * Copyright © 2012 Mike Beattie <mike@ethernal.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; version 2 of the License.
8  *
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.
13  *
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.
17  */
18
19
20 package org.altusmetrum.AltosDroid;
21
22 import java.text.*;
23 import java.io.*;
24 import java.util.concurrent.*;
25 import android.util.Log;
26 import android.os.Handler;
27
28 import org.altusmetrum.altoslib_5.*;
29
30
31 public class TelemetryReader extends Thread {
32
33         private static final String TAG = "TelemetryReader";
34         private static final boolean D = true;
35
36         int         crc_errors;
37
38         Handler     handler;
39
40         AltosLink   link;
41         AltosState  state = null;
42
43         AltosFlightReader       stacked;
44
45         LinkedBlockingQueue<AltosLine> telemQueue;
46
47         public AltosState read() throws ParseException, AltosCRCException, InterruptedException, IOException {
48                 AltosLine l = telemQueue.take();
49                 if (l.line == null)
50                         throw new IOException("IO error");
51                 AltosTelemetry telem = AltosTelemetryLegacy.parse(l.line);
52                 if (state == null)
53                         state = new AltosState();
54                 else
55                         state = state.clone();
56                 telem.update_state(state);
57                 return state;
58         }
59
60         public void close() {
61                 state = null;
62                 if (stacked != null) {
63                         stacked.close(false);
64                         stacked = null;
65                 }
66                 link.remove_monitor(telemQueue);
67                 link = null;
68                 telemQueue.clear();
69                 telemQueue = null;
70         }
71
72         public void run() {
73                 AltosState  state = null;
74
75                 try {
76                         if (D) Log.d(TAG, "starting reader");
77                         while (stacked != null) {
78                                 AltosState      stacked_state = null;
79                                 try {
80                                         stacked_state = stacked.read();
81                                 } catch (ParseException pe) {
82                                         continue;
83                                 } catch (AltosCRCException ce) {
84                                         continue;
85                                 }
86                                 if (stacked_state != null)
87                                         state = stacked_state;
88                                 else
89                                         stacked = null;
90                         }
91                         if (state != null) {
92                                 if (D) Log.d(TAG, "Send initial state");
93                                 handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget();
94                         }
95                         if (D) Log.d(TAG, "starting loop");
96                         while (telemQueue != null) {
97                                 try {
98                                         state = read();
99                                         handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget();
100                                 } catch (ParseException pp) {
101                                         Log.e(TAG, String.format("Parse error: %d \"%s\"", pp.getErrorOffset(), pp.getMessage()));
102                                 } catch (AltosCRCException ce) {
103                                         ++crc_errors;
104                                         handler.obtainMessage(TelemetryService.MSG_CRC_ERROR, new Integer(crc_errors)).sendToTarget();
105                                 }
106                         }
107                 } catch (InterruptedException ee) {
108                 } catch (IOException ie) {
109                 } finally {
110                         close();
111                 }
112         }
113
114         public TelemetryReader (AltosLink in_link, Handler in_handler, AltosFlightReader in_stacked) {
115                 if (D) Log.d(TAG, "connected TelemetryReader create started");
116                 link    = in_link;
117                 handler = in_handler;
118                 stacked = in_stacked;
119
120                 state = null;
121                 telemQueue = new LinkedBlockingQueue<AltosLine>();
122                 link.add_monitor(telemQueue);
123                 link.set_telemetry(AltosLib.ao_telemetry_standard);
124
125                 if (D) Log.d(TAG, "connected TelemetryReader created");
126         }
127
128         private static AltosFlightReader existing_data(AltosLink link) {
129                 if (link == null)
130                         return null;
131
132                 File    file = AltosPreferences.logfile(link.serial);
133                 if (file != null) {
134                         AltosStateIterable      iterable = AltosStateIterable.iterable(file);
135                         if (iterable != null)
136                                 return new AltosReplayReader(iterable.iterator(), file, false);
137                 }
138                 return null;
139         }
140
141         public TelemetryReader(AltosLink link, Handler handler) {
142                 this(link, handler, existing_data(link));
143         }
144 }