/** * Internal helper method to aid in the subclass architecture. Overwrites the superclass method * and calls it internally. * * @param header * @param s */ protected void sentenceChooser(String header, String s) { if (header.equals(RMCSentence.HEADER)) { rmcSentence.setSentence(s); notifyListeners(this.rmcSentence); } else if (header.equals(GSVSentence.HEADER)) { // TODO: I wonder what happens if say 2 of 4 are received and parse is called? // Because 2 would be new data, 2 would be old data. // Can't happen because parse() only called when not null. // BUT what if it is in the middle of parsing and new data comes in? // Solution: Sync GSVSentence.parse()? checkRefresh() is already synced though. // 0. Get StringTokenizer to read info from NMEASentence: StringTokenizer st = new StringTokenizer(s, ","); st.nextToken(); // Skip header $GPGSV // 1.1 Find out how many sentences in sequence. gsvSentenceTotal = Integer.parseInt(st.nextToken()); // 1.2 Find out which sentence this is. gsvSentenceNumber = Integer.parseInt(st.nextToken()); // 2. Assign sentence to GSVSentence in order. gsvSentence.setSentence(s, gsvSentenceNumber, gsvSentenceTotal); // 3. If last sentence: if (gsvSentenceTotal == gsvSentenceNumber) { // 3a. setSentence() to last one so it is not null gsvSentence.setSentence(s); // 3b. Notify GPSListener notifyListeners(this.gsvSentence); } } else super.sentenceChooser(header, s); // Check superclass sentences. }
public Location getLocation(int timeout) throws LocationException, InterruptedException { /* TODO The timeout might play to the fact that it is still acquiring satellites? * I was wondering about that before. Maybe it makes sense to have timeout in SimpleGPS? * TODO: Solution! Keep asking for altitude until is positive? (longitude can be negative) * Or perhaps just until speed positive? (set those after) * TODO: -1 in timeout is supposed to represent the default timeout (GPSListener?) * TODO: I don't know if this is supposed to wait for the GPS to provide a new * coordinate data or if it is okay to pass the latest cached GPS coordinates. * Is the purpose of the timeout that it gets a new updated location that * is not the previously returned or cached one? */ if (timeout == 0) throw new IllegalArgumentException("timeout cannot equal 0"); // Timeout results in LocationException: long startTime = System.currentTimeMillis(); // TODO: Perhaps initialize and test for NaN instead. while (gps.getLatitude() == 0 & gps.getLongitude() == 0) { if (timeout != -1 & System.currentTimeMillis() - startTime > (timeout * 1000)) throw new LocationException("GPS timed out"); Thread.sleep(100); /* NOTE: This might very occasionally cause an error because * Thread.yield() seems to cause sentence parsing to start too soon. * (try changing sleep() to yield() to see what happens) * Perhaps something needs to be synchronized? */ } QualifiedCoordinates qc = new QualifiedCoordinates( gps.getLatitude(), gps.getLongitude(), gps.getAltitude(), (gps.getHDOP() * 6), (gps.getVDOP() * 6)); Location loc = new Location( qc, gps.getSpeed(), gps.getCourse(), gps.getTimeStamp(), 0, null); // TODO: Implement location method and extraInfo (0 and null for now) return loc; }
protected BTGPSLocationProvider() throws LocationException { // TODO: Move this to searchConnect method? // TODO: The problem here is that it searches every time. Slow. Need to try Properties? // TODO: BIG ONE: Should only connect to GPS that isPaired() (from menu). Will // allow some degree of control over which GPS is connects to in classroom. try { da = LocalDevice.getLocalDevice().getDiscoveryAgent(); da.startInquiry(DiscoveryAgent.GIAC, this); } catch (BluetoothStateException e) { throw new LocationException(e.getMessage()); } while (!doneInq) { Thread.yield(); } if (btDevice == null) throw new LocationException("No device found"); String address = btDevice.getBluetoothAddress(); String btaddy = "btspp://" + address; try { StreamConnectionNotifier scn = (StreamConnectionNotifier) Connector.open(btaddy); if (scn == null) throw new LocationException("Bad BT address"); StreamConnection c = scn.acceptAndOpen(); /* This problem below occurred one time for my Holux GPS. The solution was to * remove the device from the Bluetooth menu, then find and pair again. */ if (c == null) throw new LocationException("Failed. Try pairing at menu again"); InputStream in = c.openInputStream(); if (in != null) { gps = new SimpleGPS(in); // c.close(); // TODO: Clean up when done. HOW TO HANDLE IN LOCATION? } } catch (IOException e) { throw new LocationException(e.getMessage()); } // Add itself to SimpleGPS as listener SimpleGPS.addListener(this); }
public void setLocationListener( LocationListener listener, int interval, int timeout, int maxAge) { // * Stop all previous listener threads * listenerRunning = false; if (listyThread != null) { while (listyThread.isAlive()) { Thread.yield(); } // End old thread listyThread = null; // Discard the listener thread instance } // * Remove any listeners from GPSListener * if (listener == null) { // Remove current listener from SimpleGPS SimpleGPS.removeListener(gpsl); gpsl = null; return; // No listener provided, so return now so it dosn't make a new one } // * Inner classes need final variables * final int to = timeout; final LocationListener l = listener; final LocationProvider lp = this; final int delay = interval * 1000; // Oddly interval is in seconds, and not float // Make new thread here and start it if interval > 0, else if -1 // then use the GPSListener interface. if (interval > 0) { // Notify according to interval by user listyThread = new Thread() { public void run() { while (listenerRunning) { try { // TODO: Probably only notify if location changed? Need to compare to old. // TODO: Make helper method since this is used below too. l.locationUpdated(lp, lp.getLocation(to)); Thread.sleep(delay); } catch (LocationException e) { // TODO Auto-generated catch block } catch (InterruptedException e) { // TODO Auto-generated catch block } } } }; listyThread.setDaemon(true); // so JVM exits if thread is still running listenerRunning = true; listyThread.start(); } else if (interval < 0) { // If interval is -1, use default update interval // In our case, update as soon as new coordinates are available from GPS (via GPSListener) // TODO: Alternate method: Use GPSListener for ProximityListener and this. gpsl = new GPSListener() { public void sentenceReceived(NMEASentence sen) { // Check if GGASentence. Means that new location info is ready if (sen.getHeader().equals(GGASentence.HEADER)) { try { // TODO: Probably only notify if location changed? Need to compare to old. l.locationUpdated(lp, lp.getLocation(to)); } catch (LocationException e) { // TODO Auto-generated catch block } catch (InterruptedException e) { // TODO Auto-generated catch block } } } }; SimpleGPS.addListener(gpsl); } // TODO: Need to implement LocationListener.providerStateChanged() }