Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extGPS / src / org / gvsig / gps / GPSDriver.java @ 4763

History | View | Annotate | Download (10.9 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41

    
42
/* CVS MESSAGES:
43
*
44
* $Id: GPSDriver.java 4763 2006-04-07 11:10:26Z jaume $
45
* $Log$
46
* Revision 1.5  2006-04-07 11:10:26  jaume
47
* *** empty log message ***
48
*
49
* Revision 1.4  2006/04/07 08:27:48  jaume
50
* *** empty log message ***
51
*
52
* Revision 1.3  2006/04/06 10:34:46  jaume
53
* *** empty log message ***
54
*
55
* Revision 1.1  2006/04/05 17:08:18  jaume
56
* *** empty log message ***
57
*
58
* Revision 1.2  2006/04/03 21:07:35  jaume
59
* *** empty log message ***
60
*
61
* Revision 1.1  2006/04/03 16:10:27  jaume
62
* *** empty log message ***
63
*
64
* Revision 1.1  2006/03/31 09:55:34  jaume
65
* *** empty log message ***
66
*
67
*
68
*/
69
package org.gvsig.gps;
70

    
71
import gnu.io.CommPortIdentifier;
72
import gnu.io.PortInUseException;
73
import gnu.io.SerialPort;
74
import gnu.io.UnsupportedCommOperationException;
75

    
76
import java.io.BufferedWriter;
77
import java.io.File;
78
import java.io.FileWriter;
79
import java.io.IOException;
80
import java.io.InputStream;
81
import java.io.OutputStream;
82
import java.util.ArrayList;
83
import java.util.Enumeration;
84
import java.util.Hashtable;
85
import java.util.Iterator;
86

    
87
import org.gvsig.gps.listeners.GPSEventListener;
88
import org.gvsig.gps.parser.NMEA.GGASentence;
89
import org.gvsig.gps.parser.NMEA.IllegalSentenceException;
90
import org.gvsig.gps.parser.NMEA.NMEASentence;
91
import org.gvsig.gps.parser.NMEA.NMEASentenceFactory;
92
import org.gvsig.gps.parser.NMEA.RMCSentence;
93
import org.gvsig.gps.parser.NMEA.VTGSentence;
94

    
95
/**
96
 * Singleton class that handles the communication within the application and the
97
 * GPS receiver. It opens the port set with the setPort() method and establishes
98
 * the comunication via NMEA protocol.<br>
99
 * 
100
 * @author jaume dominguez faus - jaume.dominguez@iver.es
101
 *
102
 */
103
public class GPSDriver extends Thread {
104
        
105
        private ArrayList eventListeners = new ArrayList();
106
        
107
        // The timeOut field specifies how long a value received from the device
108
        // is valid. After this time, no more events of the corresponding class
109
        // will be fired.
110
        private static final long timeOut = 60 * 1000; // 60 seconds.
111
        
112
        private SerialPort serialPort = null;
113
        private InputStream inputStream;
114
        private OutputStream outputStream;
115

    
116
        private Hashtable register        = new Hashtable();
117
        private int rate = 1000;
118
        private long lastSampleTime;
119
        private boolean eventsEnabled;
120

    
121
        private boolean stop;
122

    
123
        private static GPSDriver instance = null;
124
        
125
        
126
        
127
        private static String fileName = "c:/gps points.txt";
128
        static BufferedWriter bw ;
129
        
130
        /**
131
         * Public instantiation of the driver is forbidden.
132
         */
133
        private GPSDriver() {};
134
        
135
        public static GPSDriver getInstance() {
136
                if (instance == null) 
137
                        instance = new GPSDriver();
138
                if (bw == null)
139
                        try {
140
                                bw = new BufferedWriter(new FileWriter(new File(fileName)));
141
                        } catch (IOException e) {
142
                                // TODO Auto-generated catch block
143
                                e.printStackTrace();
144
                        }
145
                return instance;
146
        }
147
        
148
        /**
149
         * 
150
         * @param portID
151
         * @param portSpeed
152
         * @param parity 
153
         * @param stopBits 
154
         * @param dataBits 
155
         * @throws PortInUseException
156
         */
157
        public void setPort(CommPortIdentifier portID, int portSpeed, int dataBits, int stopBits, int parity) throws PortInUseException{
158
                closePort();
159
                serialPort = (SerialPort) portID.open("gvSIG", portSpeed);
160
                try {
161
                        inputStream = serialPort.getInputStream();
162
                        outputStream = serialPort.getOutputStream();
163
                        serialPort.setSerialPortParams(
164
                                                                portSpeed, 
165
                                                                dataBits,
166
                                                                stopBits,
167
                                                                parity
168
                                                );
169

    
170
                } catch (UnsupportedCommOperationException e) {
171
                        e.printStackTrace();
172
                } catch (IOException e) {
173
                        e.printStackTrace();
174
                }
175
        }
176
        
177
        /**
178
         * Tells the driver to start monitoring and capturing data from the device.
179
         */
180
        public void start() {
181
                eventsEnabled = true;
182
                if (!this.isAlive())
183
                        super.start();
184
        }
185
        
186
        public void run() {
187
                byte[] readBuffer = new byte[2048];
188
                StringBuffer line = new StringBuffer();
189
                try {
190
                        for (int bytes = inputStream.read(readBuffer); bytes>-1; bytes = inputStream.read(readBuffer)){
191
                                // Creates a new buffer to contain the previous readed bytes and the next bunch of bytes
192
                                String str = new String(readBuffer).substring(0, bytes);
193
                                int i = str.indexOf("\n");
194
                                if (i == -1) {
195
                                        line.append(str);
196
                                } else {
197
                                        line.append(str.substring(0,i));
198
                                        analyzeMessage(line.toString());
199
                                        line = new StringBuffer();
200
                                        line.append(str.substring(i+1,str.length()));
201
                                }
202
//                                if (stop)
203
//                                        break;
204
                        }
205
                } catch (IOException e) {
206
                        e.printStackTrace();
207
                }
208
                try {
209
                        System.err.println("Sending request");
210
                        outputStream.write(new String("$PMCAG,005,1,GGA,001").getBytes());
211
                        for (int bytes = inputStream.read(readBuffer); bytes>-1; bytes = inputStream.read(readBuffer)){
212
                                // Creates a new buffer to contain the previous readed bytes and the next bunch of bytes
213
                                String str = new String(readBuffer).substring(0, bytes);
214
                                int i = str.indexOf("\n");
215
                                if (i == -1) {
216
                                        line.append(str);
217
                                } else {
218
                                        line.append(str.substring(0,i));
219
                                        analyzeMessage(line.toString());
220
                                        try {
221
                                                sleep(rate);
222
                                        } catch (InterruptedException e) {
223
                                                // TODO Auto-generated catch block
224
                                                e.printStackTrace();
225
                                        }
226
                                        line = new StringBuffer();
227
                                        line.append(str.substring(i+1,str.length()));
228
                                }
229
//                                if (stop)
230
//                                        break;
231
                        }
232
                } catch (IOException e) {
233
                        e.printStackTrace();
234
                }
235
                inputStream = null;
236
                outputStream = null;
237
        }
238
        
239
        private void analyzeMessage(String line) {
240
                try {
241
                        NMEASentence data = NMEASentenceFactory.createFromString(line);
242
                        NMEASentence oldData = (NMEASentence) register.get(data.getName());
243
                        boolean mustNotifyListeners = !data.isEquivalentTo(oldData);
244
                        register.put(data.getName(), data);
245
                        //if (mustNotifyListeners)
246
                                fireEvents();
247
                } catch (IllegalSentenceException e) {
248
//                        if (eventsEnabled && line!=null)
249
//                                NotificationManager.addWarning("Unrecognized sentence: "+line, null);
250
                }
251
                
252
        }
253
        
254
        public void setSampleRate(int millis) {
255
                this.rate = millis;
256
        }
257
        
258
        
259
        public void addEventListener(GPSEventListener l) {
260
                eventListeners.add(l);
261
        }
262
        
263
        private void fireEvents() {
264
                Iterator it = eventListeners.iterator();
265
                while (eventsEnabled && it.hasNext()) {
266
                        GPSEventListener l = (GPSEventListener) it.next();
267
                        if (System.currentTimeMillis() - lastSampleTime  >= rate ) {
268
                                Iterator i = register.keySet().iterator();
269
                                while (i.hasNext()) {
270
                                        NMEASentence aux = (NMEASentence) register.get(i.next());
271
                                        if (isCurrent(aux)) {
272
                                                // This is a valid record
273
                                                if (aux instanceof GGASentence) {
274
                                                        GGASentence s = (GGASentence) aux;
275
                                                        {
276
                                                                try {
277
                                                                        bw.write(s.getLongitude() + "," + s.getLatitude()+"\n");
278
                                                                        bw.flush();
279
                                                                } catch (IOException e) {
280
                                                                        // TODO Auto-generated catch block
281
                                                                        e.printStackTrace();
282
                                                                }
283
                                                        }
284
                                                        l.newLonLatPositionReceived(s.getLongitude(), s.getLatitude());
285
                                                } else if (aux instanceof RMCSentence) {
286
                                                        l.unhandledMessage(aux.toString());
287
                                                } else if (aux instanceof VTGSentence) {
288
                                                        VTGSentence s = (VTGSentence) aux;
289
                                                        l.speedChanged(s.getSpeed(), s.getCourse());
290
                                                } else {
291
                                                        l.unhandledMessage(aux.toString());
292
                                                }
293
                                        } else {
294
                                                // This record is too old.
295
                                                register.remove(aux);
296
                                        }
297
                                }
298

    
299
                                lastSampleTime = System.currentTimeMillis();
300
                        }
301
                }
302
        }
303
        
304
        private boolean isCurrent(NMEASentence n) {
305
                return System.currentTimeMillis() - n.getTime() < timeOut;
306
        }
307
        
308
        /**
309
         * Silences the event firing. To resume the event firing just call <b>start()</b> method.  
310
         */
311
        public void silence() {
312
                eventsEnabled = false;
313
        }
314
        
315
        public static void main(String[] args) {
316
                if (args.length < 4) {
317
                        System.out.print("GPSReader port portSpeed\n");
318
                        System.exit(-1);
319
                }
320
                Enumeration portList = CommPortIdentifier.getPortIdentifiers();
321
                while (portList.hasMoreElements()) {
322
                        CommPortIdentifier myPortId = (CommPortIdentifier) portList.nextElement();
323
                        if (myPortId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
324
                                if (myPortId.getName().equals(args[0])) {
325
                                        try {
326
                                                GPSDriver driver = GPSDriver.getInstance();
327
                                                driver.setPort(myPortId, Integer.parseInt(args[1]), SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
328
                                                driver.setSampleRate(100);
329
                                                driver.addEventListener(new GPSEventListener() {
330
                                                        public void unhandledMessage(String msg) {
331
                                                                System.out.println("UNHANDLED: "+msg);
332
                                                        }
333

    
334
                                                        public void connectionLost() {
335
                                                                System.out.println("CONNECTION LOST");        
336
                                                        }
337

    
338
                                                        public void connectionEstablished() {
339
                                                                System.out.println("CONNECTION ESTABLISHED");
340
                                                        }
341

    
342
                                                        public void newLonLatPositionReceived(double lon, double lat) {
343
                                                                System.out.println("NEW LONLAT POSITION RECEIVED: ("+lon+", "+lat+")");
344
                                                        }
345

    
346
                                                        public void signalLevelChanged(float level) {
347
                                                                System.out.println("NEW SIGNAL LEVEL: "+level);
348
                                                        }
349

    
350
                                                        public void speedChanged(float speed, short course) {
351
                                                                System.out.println("SPEED/COURSE CHANGED: ( "+speed+" Km/h, "+course+" degrees)");
352
                                                        }
353

    
354
                                                        public void estimatedPosErrorChanged(double e) {
355
                                                                System.out.println("ESTIMATED POSITION ERROR CHANGED: "+e);
356
                                                        }
357

    
358
                                                        public void heightChanged(float height) {
359
                                                                System.out.println("HEIGHT CHANGED: "+height);
360
                                                        }
361

    
362
                                                        public void precisionChanged(float pDop, float hDop, float vDop) {
363
                                                                System.out.println("PRECISION CHANGED: "+pDop+", "+hDop+", "+vDop+")");
364
                                                        }
365
                                                        
366
                                                });
367
                                                driver.start();
368
                                        } catch (PortInUseException e) {
369
                                                System.err.println("Port busy");
370
                                        }
371
                                        
372
                                }
373
                        }
374
                }
375
        }
376

    
377
        public void closePort() {
378
                if (serialPort != null) {
379
                        serialPort.notifyOnDataAvailable(false);
380
                        serialPort.removeEventListener();
381
                        if (inputStream != null) {
382
                                try {
383
                                        inputStream.close();
384
                                }
385
                                catch (IOException e) {}
386
                        }
387
                        if (outputStream != null) {
388
                                try {
389
                                        outputStream.close();
390
                                        outputStream = null;
391
                                }
392
                                catch (IOException e) {}
393
                        }
394
                        serialPort.close();
395
                        serialPort = null;
396
                }
397
                stop = true;
398
        }
399
        
400
}