Ticket #4037: Patch_LiveGpsAcquirer.java

File Patch_LiveGpsAcquirer.java, 17.6 KB (added by casualwalker, 15 years ago)

Patch for LiveGpsAcquirer.java

Line 
1### Eclipse Workspace Patch 1.0
2#P livegps
3Index: src/livegps/LiveGpsAcquirer.java
4===================================================================
5--- src/livegps/LiveGpsAcquirer.java (revision 18830)
6+++ src/livegps/LiveGpsAcquirer.java (working copy)
7@@ -1,226 +1,307 @@
8 package livegps;
9
10 import static org.openstreetmap.josm.tools.I18n.tr;
11+
12 import java.beans.PropertyChangeEvent;
13 import java.beans.PropertyChangeListener;
14 import java.io.BufferedReader;
15-import java.io.FileInputStream;
16-import java.io.FileNotFoundException;
17 import java.io.IOException;
18 import java.io.InputStreamReader;
19 import java.net.InetAddress;
20 import java.net.Socket;
21 import java.util.ArrayList;
22 import java.util.List;
23-import java.util.Properties;
24+import java.util.logging.Logger;
25
26-import org.openstreetmap.josm.data.coor.LatLon;
27 import org.openstreetmap.josm.Main;
28+import org.openstreetmap.josm.data.coor.LatLon;
29
30 public class LiveGpsAcquirer implements Runnable {
31- Socket gpsdSocket;
32- BufferedReader gpsdReader;
33- boolean connected = false;
34- String gpsdHost = Main.pref.get("livegps.gpsd.host","localhost");
35- int gpsdPort = Main.pref.getInteger("livegps.gpsd.port", 2947);
36- boolean shutdownFlag = false;
37- private List<PropertyChangeListener> propertyChangeListener = new ArrayList<PropertyChangeListener>();
38- private PropertyChangeEvent lastStatusEvent;
39- private PropertyChangeEvent lastDataEvent;
40+ Socket gpsdSocket;
41+ BufferedReader gpsdReader;
42+ boolean connected = false;
43+ String gpsdHost = Main.pref.get("livegps.gpsd.host", "localhost");
44+ int gpsdPort = Main.pref.getInteger("livegps.gpsd.port", 2947);
45+ boolean shutdownFlag = false;
46+ private final List<PropertyChangeListener> propertyChangeListener = new ArrayList<PropertyChangeListener>();
47+ private PropertyChangeEvent lastStatusEvent;
48+ private PropertyChangeEvent lastDataEvent;
49+
50+ /**
51+ * The LiveGpsSuppressor is queried, if an event shall be suppressed.
52+ */
53+ private LiveGpsSuppressor suppressor = null;
54+
55+ /**
56+ * separate thread, where the LiveGpsSuppressor executes.
57+ */
58+ private Thread suppressorThread = null;
59+
60+ protected static final Logger log = Logger.getLogger(LiveGpsAcquirer.class
61+ .getName());
62+
63+ /**
64+ * Adds a property change listener to the acquirer.
65+ * @param listener the new listener
66+ */
67+ public void addPropertyChangeListener(PropertyChangeListener listener) {
68+ if (!propertyChangeListener.contains(listener)) {
69+ propertyChangeListener.add(listener);
70+ }
71+ }
72+
73+ /**
74+ * Remove a property change listener from the acquirer.
75+ * @param listener the new listener
76+ */
77+ public void removePropertyChangeListener(PropertyChangeListener listener) {
78+ if (propertyChangeListener.contains(listener)) {
79+ propertyChangeListener.remove(listener);
80+ }
81+ }
82+
83+ /**
84+ * Fire a gps status change event. Fires events with key "gpsstatus" and a {@link LiveGpsStatus}
85+ * object as value.
86+ * The status event may be sent any time.
87+ * @param status the status.
88+ * @param statusMessage the status message.
89+ */
90+ public void fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus status,
91+ String statusMessage) {
92+ PropertyChangeEvent event = new PropertyChangeEvent(this, "gpsstatus",
93+ null, new LiveGpsStatus(status, statusMessage));
94+
95+ if (!event.equals(lastStatusEvent)) {
96
97- /**
98- * Adds a property change listener to the acquirer.
99- * @param listener the new listener
100- */
101- public void addPropertyChangeListener(PropertyChangeListener listener) {
102- if(!propertyChangeListener.contains(listener)) {
103- propertyChangeListener.add(listener);
104- }
105- }
106+ firePropertyChangeEvent(event);
107+ lastStatusEvent = event;
108+ }
109+ }
110
111- /**
112- * Remove a property change listener from the acquirer.
113- * @param listener the new listener
114- */
115- public void removePropertyChangeListener(PropertyChangeListener listener) {
116- if(propertyChangeListener.contains(listener)) {
117- propertyChangeListener.remove(listener);
118- }
119- }
120+ /**
121+ * Fire a gps data change event to all listeners. Fires events with key "gpsdata" and a
122+ * {@link LiveGpsData} object as values.
123+ * This event is only sent, when the suppressor permits it. This
124+ * event will cause the UI to re-draw itself, which has some performance penalty,
125+ * @param oldData the old gps data.
126+ * @param newData the new gps data.
127+ */
128+ public void fireGpsDataChangeEvent(LiveGpsData oldData, LiveGpsData newData) {
129+ PropertyChangeEvent event = new PropertyChangeEvent(this, "gpsdata",
130+ oldData, newData);
131
132- /**
133- * Fire a gps status change event. Fires events with key "gpsstatus" and a {@link LiveGpsStatus}
134- * object as value.
135- * @param status the status.
136- * @param statusMessage the status message.
137- */
138- public void fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus status, String statusMessage) {
139- PropertyChangeEvent event = new PropertyChangeEvent(this, "gpsstatus", null, new LiveGpsStatus(status, statusMessage));
140- if(!event.equals(lastStatusEvent)) {
141- firePropertyChangeEvent(event);
142- lastStatusEvent = event;
143- }
144- }
145+ log.fine("Got fireGpsStatusChangeEvent");
146
147- /**
148- * Fire a gps data change event to all listeners. Fires events with key "gpsdata" and a
149- * {@link LiveGpsData} object as values.
150- * @param oldData the old gps data.
151- * @param newData the new gps data.
152- */
153- public void fireGpsDataChangeEvent(LiveGpsData oldData, LiveGpsData newData) {
154- PropertyChangeEvent event = new PropertyChangeEvent(this, "gpsdata", oldData, newData);
155- if(!event.equals(lastDataEvent)) {
156- firePropertyChangeEvent(event);
157- lastDataEvent = event;
158- }
159- }
160+ if (!event.equals(lastDataEvent) && checkSuppress()) {
161+ log.fine("Fireing");
162+ firePropertyChangeEvent(event);
163+ lastDataEvent = event;
164+ }
165+ }
166
167- /**
168- * Fires the given event to all listeners.
169- * @param event the event to fire.
170- */
171- protected void firePropertyChangeEvent(PropertyChangeEvent event) {
172- for (PropertyChangeListener listener : propertyChangeListener) {
173- listener.propertyChange(event);
174- }
175- }
176+ /**
177+ * Fires the given event to all listeners.
178+ * @param event the event to fire.
179+ */
180+ protected void firePropertyChangeEvent(PropertyChangeEvent event) {
181+ for (PropertyChangeListener listener : propertyChangeListener) {
182+ listener.propertyChange(event);
183+ }
184+ }
185
186- public void run() {
187- LiveGpsData oldGpsData = null;
188- LiveGpsData gpsData = null;
189- shutdownFlag = false;
190- while(!shutdownFlag) {
191- double lat = 0;
192- double lon = 0;
193- float speed = 0;
194- float course = 0;
195- boolean haveFix = false;
196+ public void run() {
197+ LiveGpsData oldGpsData = null;
198+ LiveGpsData gpsData = null;
199
200- try
201- {
202- if (!connected)
203- {
204- System.out.println("LiveGps tries to connect to gpsd");
205- fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.CONNECTING, tr("Connecting"));
206- InetAddress[] addrs = InetAddress.getAllByName(gpsdHost);
207- for (int i=0; i < addrs.length && gpsdSocket == null; i++) {
208- try {
209- gpsdSocket = new Socket(addrs[i], gpsdPort);
210- break;
211- } catch (Exception e) {
212- System.out.println("LiveGps: Could not open connection to gpsd: " + e);
213- gpsdSocket = null;
214- }
215- }
216+ initSuppressor();
217
218- if (gpsdSocket != null)
219- {
220- gpsdReader = new BufferedReader(new InputStreamReader(gpsdSocket.getInputStream()));
221- gpsdSocket.getOutputStream().write(new byte[] { 'w', 13, 10 });
222- fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.CONNECTING, tr("Connecting"));
223- connected = true;
224- System.out.println("LiveGps: Connected to gpsd");
225- }
226- }
227+ shutdownFlag = false;
228+ while (!shutdownFlag) {
229+ double lat = 0;
230+ double lon = 0;
231+ float speed = 0;
232+ float course = 0;
233+ boolean haveFix = false;
234
235+ try {
236+ if (!connected) {
237+ System.out.println("LiveGps tries to connect to gpsd");
238+ fireGpsStatusChangeEvent(
239+ LiveGpsStatus.GpsStatus.CONNECTING,
240+ tr("Connecting"));
241+ InetAddress[] addrs = InetAddress.getAllByName(gpsdHost);
242+ for (int i = 0; i < addrs.length && gpsdSocket == null; i++) {
243+ try {
244+ gpsdSocket = new Socket(addrs[i], gpsdPort);
245+ break;
246+ } catch (Exception e) {
247+ System.out
248+ .println("LiveGps: Could not open connection to gpsd: "
249+ + e);
250+ gpsdSocket = null;
251+ }
252+ }
253
254- if(connected) {
255- // <FIXXME date="23.06.2007" author="cdaller">
256- // TODO this read is blocking if gps is connected but has no fix, so gpsd does not send positions
257- String line = gpsdReader.readLine();
258- // </FIXXME>
259- if (line == null) break;
260- String words[] = line.split(",");
261+ if (gpsdSocket != null) {
262+ gpsdReader = new BufferedReader(new InputStreamReader(
263+ gpsdSocket.getInputStream()));
264+ gpsdSocket.getOutputStream().write(
265+ new byte[] { 'w', 13, 10 });
266+ fireGpsStatusChangeEvent(
267+ LiveGpsStatus.GpsStatus.CONNECTING,
268+ tr("Connecting"));
269+ connected = true;
270+ System.out.println("LiveGps: Connected to gpsd");
271+ }
272+ }
273
274- if ((words.length == 0) || (!words[0].equals("GPSD"))) {
275- // unexpected response.
276- continue;
277- }
278+ if (connected) {
279+ // <FIXXME date="23.06.2007" author="cdaller">
280+ // TODO this read is blocking if gps is connected but has no
281+ // fix, so gpsd does not send positions
282+ String line = gpsdReader.readLine();
283+ // </FIXXME>
284+ if (line == null)
285+ break;
286+ String words[] = line.split(",");
287
288- for (int i = 1; i < words.length; i++) {
289+ if ((words.length == 0) || (!words[0].equals("GPSD"))) {
290+ // unexpected response.
291+ continue;
292+ }
293
294- if ((words[i].length() < 2) || (words[i].charAt(1) != '=')) {
295- // unexpected response.
296- continue;
297- }
298+ for (int i = 1; i < words.length; i++) {
299
300- char what = words[i].charAt(0);
301- String value = words[i].substring(2);
302- oldGpsData = gpsData;
303- gpsData = new LiveGpsData();
304- switch(what) {
305- case 'O':
306- // full report, tab delimited.
307- String[] status = value.split("\\s+");
308- if (status.length >= 5) {
309- lat = Double.parseDouble(status[3]);
310- lon = Double.parseDouble(status[4]);
311- try {
312- speed = Float.parseFloat(status[9]);
313- course = Float.parseFloat(status[8]);
314- //view.setSpeed(speed);
315- //view.setCourse(course);
316- } catch (NumberFormatException nex) {}
317- haveFix = true;
318- }
319- break;
320- case 'P':
321- // position report, tab delimited.
322- String[] pos = value.split("\\s+");
323- if (pos.length >= 2) {
324- lat = Double.parseDouble(pos[0]);
325- lon = Double.parseDouble(pos[1]);
326- speed = Float.NaN;
327- course = Float.NaN;
328- haveFix = true;
329- }
330- default:
331- // not interested
332- }
333- fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.CONNECTED, tr("Connected"));
334- gpsData.setFix(haveFix);
335- if (haveFix) {
336- //view.setCurrentPosition(lat, lon);
337- gpsData.setLatLon(new LatLon(lat, lon));
338- gpsData.setSpeed(speed);
339- gpsData.setCourse(course);
340- fireGpsDataChangeEvent(oldGpsData, gpsData);
341- }
342- }
343- } else {
344- // not connected:
345- fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.DISCONNECTED, tr("Not connected"));
346- try { Thread.sleep(1000); } catch (InterruptedException ignore) {};
347- }
348- } catch(IOException iox) {
349- connected = false;
350- if(gpsData != null) {
351- gpsData.setFix(false);
352- fireGpsDataChangeEvent(oldGpsData, gpsData);
353- }
354- fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.CONNECTION_FAILED, tr("Connection Failed"));
355- try { Thread.sleep(1000); } catch (InterruptedException ignore) {};
356- // send warning to layer
357+ if ((words[i].length() < 2)
358+ || (words[i].charAt(1) != '=')) {
359+ // unexpected response.
360+ continue;
361+ }
362
363- }
364- }
365+ char what = words[i].charAt(0);
366+ String value = words[i].substring(2);
367+ oldGpsData = gpsData;
368+ gpsData = new LiveGpsData();
369+ switch (what) {
370+ case 'O':
371+ // full report, tab delimited.
372+ String[] status = value.split("\\s+");
373+ if (status.length >= 5) {
374+ lat = Double.parseDouble(status[3]);
375+ lon = Double.parseDouble(status[4]);
376+ try {
377+ speed = Float.parseFloat(status[9]);
378+ course = Float.parseFloat(status[8]);
379+ // view.setSpeed(speed);
380+ // view.setCourse(course);
381+ } catch (NumberFormatException nex) {
382+ }
383+ haveFix = true;
384+ }
385+ break;
386+ case 'P':
387+ // position report, tab delimited.
388+ String[] pos = value.split("\\s+");
389+ if (pos.length >= 2) {
390+ lat = Double.parseDouble(pos[0]);
391+ lon = Double.parseDouble(pos[1]);
392+ speed = Float.NaN;
393+ course = Float.NaN;
394+ haveFix = true;
395+ }
396+ default:
397+ // not interested
398+ }
399+ fireGpsStatusChangeEvent(
400+ LiveGpsStatus.GpsStatus.CONNECTED,
401+ tr("Connected"));
402+ gpsData.setFix(haveFix);
403+ if (haveFix) {
404+ // view.setCurrentPosition(lat, lon);
405+ gpsData.setLatLon(new LatLon(lat, lon));
406+ gpsData.setSpeed(speed);
407+ gpsData.setCourse(course);
408+ fireGpsDataChangeEvent(oldGpsData, gpsData);
409+ }
410+ }
411+ } else {
412+ // not connected:
413+ fireGpsStatusChangeEvent(
414+ LiveGpsStatus.GpsStatus.DISCONNECTED,
415+ tr("Not connected"));
416+ try {
417+ Thread.sleep(1000);
418+ } catch (InterruptedException ignore) {
419+ }
420+ ;
421+ }
422+ } catch (IOException iox) {
423+ connected = false;
424+ if (gpsData != null) {
425+ gpsData.setFix(false);
426+ fireGpsDataChangeEvent(oldGpsData, gpsData);
427+ }
428+ fireGpsStatusChangeEvent(
429+ LiveGpsStatus.GpsStatus.CONNECTION_FAILED,
430+ tr("Connection Failed"));
431+ try {
432+ Thread.sleep(1000);
433+ } catch (InterruptedException ignore) {
434+ }
435+ ;
436+ // send warning to layer
437
438- fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.DISCONNECTED, tr("Not connected"));
439- if (gpsdSocket != null) {
440- try {
441- gpsdSocket.close();
442- gpsdSocket = null;
443- System.out.println("LiveGps: Disconnected from gpsd");
444- }
445- catch (Exception e) {
446- System.out.println("LiveGps: Unable to close socket; reconnection may not be possible");
447- }
448- }
449- }
450+ }
451+ }
452
453- public void shutdown()
454- {
455- shutdownFlag = true;
456- }
457+ fireGpsStatusChangeEvent(LiveGpsStatus.GpsStatus.DISCONNECTED,
458+ tr("Not connected"));
459+ if (gpsdSocket != null) {
460+ try {
461+ gpsdSocket.close();
462+ gpsdSocket = null;
463+ System.out.println("LiveGps: Disconnected from gpsd");
464+ } catch (Exception e) {
465+ System.out
466+ .println("LiveGps: Unable to close socket; reconnection may not be possible");
467+ }
468+ }
469+ }
470+
471+ /**
472+ * Initialize the suppressor and start its thread.
473+ */
474+ private void initSuppressor() {
475+ suppressor = new LiveGpsSuppressor();
476+ suppressorThread = new Thread(suppressor);
477+ suppressorThread.start();
478+ }
479+
480+ public void shutdown() {
481+ // shut down the suppressor thread, too.
482+ suppressor.shutdown();
483+ this.suppressor = null;
484+ shutdownFlag = true;
485+ }
486+
487+ /**
488+ * Check, if an event may be sent now.
489+ * @return true, if an event may be sent.
490+ */
491+ private boolean checkSuppress() {
492+ if (suppressor != null) {
493+ if (suppressor.isAllowUpdate()) {
494+ log.fine("Fire allowed");
495+ return true;
496+ } else {
497+ log.fine("Fire suppressed");
498+ return false;
499+ }
500+ } else {
501+ log.warning("Firing, no suppressor presented");
502+ return true;
503+ }
504+
505+ }
506 }