1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package triptracker.client.gps.core;
21
22 import static gnu.io.SerialPortEvent.*;
23 import static gnu.io.SerialPort.*;
24 import static gnu.io.CommPortIdentifier.*;
25 import static triptracker.client.gps.core.GPSStatusState.*;
26
27 import java.io.BufferedReader;
28 import java.io.FileNotFoundException;
29 import java.io.FileOutputStream;
30 import java.io.IOException;
31 import java.io.InputStreamReader;
32 import java.io.PrintWriter;
33 import java.util.ArrayList;
34 import java.util.Date;
35 import java.util.Enumeration;
36 import java.util.List;
37 import java.util.Set;
38 import java.util.TooManyListenersException;
39 import java.util.concurrent.CopyOnWriteArraySet;
40 import gnu.io.CommPortIdentifier;
41 import gnu.io.PortInUseException;
42 import gnu.io.SerialPort;
43 import gnu.io.SerialPortEvent;
44 import gnu.io.SerialPortEventListener;
45 import gnu.io.UnsupportedCommOperationException;
46
47 import triptracker.core.Coordinate;
48 import triptracker.core.Utils;
49
50 public class GPSConnection {
51 /*** Listener set for Model View Controller (MVC) separation. */
52 protected Set<GPSListener> listeners = new CopyOnWriteArraySet<GPSListener>();
53
54 private BufferedReader inputStream;
55
56 private SerialPort sPort;
57
58 private boolean closePort = false;
59
60 private boolean isConnected = false;
61
62 private boolean recieve = false;
63
64 private boolean validSignal = false;
65
66 private CommPortIdentifier portId;
67
68 PrintWriter outW;
69
70 private static final String WANTED_SENTENCE = "GPRMC";
71
72 private String portOwner = null;
73
74 public static final int BAUDRATE = 4800;
75
76 public static final int TIMEOUT = 2000;
77
78 private NMEASentence nmea = new NMEASentence();
79
80 private Coordinate currentCoordinate = null;
81
82 /***
83 * Connects to the GPS-unit at the given port
84 *
85 * @param port Port to connect
86 */
87 public void open(String port) throws PortInUseException,
88 TooManyListenersException, UnsupportedCommOperationException,
89 IOException, IllegalArgumentException {
90
91 openFile();
92 if (!isConnected()) {
93 Enumeration portList = getPortIdentifiers();
94
95 if (!portList.hasMoreElements()) {
96 System.out.println("No ports");
97 }
98
99 while (portList.hasMoreElements()) {
100 portId = (CommPortIdentifier) portList.nextElement();
101
102 if (portId.getPortType() == PORT_SERIAL && portId.getName().equals(port)) {
103
104 sPort = (SerialPort) portId.open("TripTracker", TIMEOUT);
105 portOwner = portId.getCurrentOwner();
106
107 isConnected = true;
108 statusUpdate(CONNECTED);
109
110 sPort.notifyOnDataAvailable(true);
111
112
113 sPort.notifyOnBreakInterrupt(true);
114 sPort.notifyOnCarrierDetect(true);
115 sPort.notifyOnCTS(true);
116
117 sPort.notifyOnDSR(true);
118 sPort.notifyOnFramingError(true);
119 sPort.notifyOnOutputEmpty(true);
120 sPort.notifyOnOverrunError(true);
121 sPort.notifyOnParityError(true);
122 sPort.notifyOnRingIndicator(true);
123
124 sPort.setSerialPortParams(BAUDRATE, DATABITS_8, STOPBITS_1,
125 PARITY_NONE);
126
127 inputStream = new BufferedReader(new InputStreamReader(sPort
128 .getInputStream()));
129
130 sPort.addEventListener(new DataListener());
131
132 return;
133 }
134
135 }
136 }
137 }
138
139 /***
140 * Recieve data from GPS-unit
141 * @throws IOException
142 */
143 private void readGPSData() {
144 String dataFromGPS = null;
145 if (!recieve) {
146 return;
147 }
148
149 while (true) {
150
151 try {
152 dataFromGPS = inputStream.readLine();
153 } catch (IOException e) {
154 readExcepion(e);
155 return;
156 }
157
158
159 if ((dataFromGPS.contains("$" + WANTED_SENTENCE))) {
160
161 outW.println(dataFromGPS);
162 outW.flush();
163
164 nmea.parseSentence(dataFromGPS);
165
166
167 if (hasSignal()) {
168 generateCoordinate();
169 if (!validSignal) {
170 validSignal = true;
171 statusUpdate(HASFIXEDPOS);
172 }
173 } else if (validSignal) {
174 validSignal = false;
175 statusUpdate(HASFIXEDPOS);
176 } else {
177 statusUpdate(NOFIXEDPOS);
178 System.out.println("no fixed pos");
179 }
180
181 }
182
183
184 if (closePort) {
185 statusUpdate(NOTCONNECTED);
186 sPort.close();
187 }
188 }
189 }
190
191 /***
192 * Generates a coordinate from the NMEA class
193 *
194 */
195 private void generateCoordinate() {
196
197
198 double lat = 0, lon = 0;
199
200 try {
201 lat = Double.parseDouble(nmea.getField(3));
202 lon = Double.parseDouble(nmea.getField(5));
203 } catch (NumberFormatException e) {
204 return;
205 }
206
207 if (nmea.getField(4).contains("S")) {
208 lat = -lat;
209 }
210 if (nmea.getField(6).contains("W")) {
211 lon = -lon;
212 }
213
214 Date date = Utils.parseDate(nmea.getField(9) + nmea.getField(1),
215 "ddMMyyHHmmss");
216
217 if (date == null) {
218 throw new NullPointerException("date could not be parsed: "
219 + nmea.getField(9) + nmea.getField(1));
220 }
221
222
223 lat = Coordinate.nmeaToDec(lat);
224 lon = Coordinate.nmeaToDec(lon);
225
226 currentCoordinate = new Coordinate(lat, lon, date);
227
228 }
229
230 public Coordinate getCurrentCoordinate() {
231 return currentCoordinate;
232 }
233
234 /***
235 * Checks wheter the GPS has connection to the satellites
236 *
237 * @return true if fixed position has been obtained, false if no fixed
238 * position is available
239 */
240 public boolean hasSignal() {
241
242
243 if (nmea.getField(1).length() == 6) {
244 return true;
245 } else {
246 return false;
247 }
248 }
249
250 /***
251 * Returns a list of available serial ports.
252 *
253 * @return list of available serial ports
254 */
255 public List<String> getPorts() {
256 List<String> ports = new ArrayList<String>();
257 Enumeration portList = getPortIdentifiers();
258
259 while (portList.hasMoreElements()) {
260 portId = (CommPortIdentifier) portList.nextElement();
261
262 if (portId.getPortType() == PORT_SERIAL) {
263 ports.add(portId.getName());
264 }
265 }
266
267 if (ports.isEmpty()) {
268 ports.add("NONE, PLEASE RESTART");
269 }
270 return ports;
271 }
272
273 /***
274 * Checks if connected to the COM port
275 *
276 * @return true if connected to the com port, else false
277 */
278 public boolean isConnected() {
279 return isConnected;
280 }
281
282 /***
283 * Reports a broken listener, removes it from the listener queue and logs
284 * the error.
285 *
286 * @param listener broken listener
287 * @param exception exception thrown by listener
288 */
289 protected void brokenListener(GPSListener listener,
290 RuntimeException exception) {
291 System.err.println("Unexpected exception in listener");
292 exception.printStackTrace();
293
294
295 listeners.remove(listener);
296 }
297
298 /***
299 * Publish a connected event.
300 *
301 * @param connected true if connected, false if disconnected
302 */
303 protected void connectedEvent(boolean connected) {
304 for (GPSListener listener : listeners) {
305 try {
306 listener.connected(connected);
307 } catch (RuntimeException e) {
308 brokenListener(listener, e);
309 }
310 }
311 }
312
313 /***
314 * Register a listener for server events.
315 *
316 * @param listener event receiver to register
317 */
318 public void addListener(GPSListener listener) {
319 listeners.add(listener);
320 }
321
322 /***
323 * Remove listener from listener queue.
324 *
325 * @param listener event receiver to remove
326 */
327 public void removeListener(GPSListener listener) {
328 listeners.remove(listener);
329 }
330
331 private class DataListener implements SerialPortEventListener {
332 /***
333 * Handle serial port events
334 */
335 public void serialEvent(SerialPortEvent event) {
336 switch (event.getEventType()) {
337 case BI:
338 System.out.println("serialEvent: BI " + event.toString());
339 break;
340 case CD:
341 System.out.println("serialEvent: CD " + event.toString());
342 break;
343 case CTS:
344 System.out.println("serialEvent: CTS " + event.toString());
345 break;
346 case DATA_AVAILABLE:
347 readGPSData();
348 break;
349 case DSR:
350 System.out.println("serialEvent: DSR " + event.toString());
351 break;
352 case FE:
353 System.out.println("serialEvent: FE " + event.toString());
354 break;
355 case OE:
356 System.out.println("serialEvent: OE " + event.toString());
357 break;
358 case OUTPUT_BUFFER_EMPTY:
359 System.out.println("serialEvent: OUTPUT_BUFFER_EMPTY " + event.toString());
360 break;
361 case PE:
362 System.out.println("serialEvent: PE " + event.toString());
363 break;
364 case RI:
365 System.out.println("serialEvent: RI " + event.toString());
366 break;
367 }
368 }
369 }
370
371 private void statusUpdate(GPSStatusState state) {
372 for (GPSListener listener : listeners) {
373 try {
374 listener.statusUpdate(state);
375 } catch (RuntimeException e) {
376 brokenListener(listener, e);
377 }
378 }
379 }
380
381 /***
382 * Closes the current COM port
383 *
384 */
385 public void closePort() {
386 if (sPort == null) {
387 return;
388 }
389
390 statusUpdate(NOTCONNECTED);
391 System.out.println("CLOOS");
392 sPort.close();
393 }
394
395 /***
396 *
397 * @return the ports owner
398 */
399 public String getPortOwner() {
400 if (portOwner == null) {
401 portOwner = "Noone";
402 }
403 return portOwner;
404 }
405
406 public boolean currCoordSet() {
407 if (currentCoordinate == null) {
408 return false;
409 } else {
410 return true;
411 }
412 }
413
414 /***
415 * Start recieve from the GPS-unit
416 *
417 */
418 public void startRecieve() {
419 System.out.println("recieve set to true");
420 recieve = true;
421 }
422
423 /***
424 * Stop/pause recieve from the GPS-unit
425 *
426 */
427 public void stopRecieve() {
428 System.out.println("recieve set to false");
429 recieve = false;
430 }
431
432 /***
433 * Checks if the signal is valid
434 *
435 * @return true if valid signal
436 */
437 public boolean isValidSignal() {
438 return validSignal;
439 }
440
441 /***
442 * Opens the given file
443 *
444 * @throws FileNotFoundException
445 */
446 public void openFile() throws FileNotFoundException {
447 outW = new PrintWriter(new FileOutputStream("nmeaout.txt"));
448 }
449
450 /***
451 * Read exception has occured.
452 */
453 protected void readExcepion(IOException ioe) {
454 for (GPSListener listener : listeners) {
455 try {
456 listener.readExcepion(ioe);
457 } catch (RuntimeException e) {
458 brokenListener(listener, e);
459 }
460 }
461
462 }
463 }