|
|
 |
The Place Lab Developers' Tutorial
This tutorial will provide you with an overview of the Place Lab
API and a primer on using it to build location-enhanced applications. If you
find it best to begin with examples, the bolded links in the Table of Contents
below lead to sections with runnable code from the org.placelab.examples
package. The javadocs from each section offer more in depth
information.
- Setup:
Preparing to develop for/with Place Lab.
- Spotting:
The Place Lab interface for sensing the real world.
- Measurement:
The common type that all spotters must produce.
- BeaconMeasurement:
A measurement of a scan for beacons.
- BeaconReading:
An individual sighting of a radio beacon within a BeaconMeasurement.
- WiFiSpotter:
A spotter that scans on 802.11 wireless cards.
- WiFiSpotterExample:
A sample program that shows how to use a WiFiSpotter.
- RemoteGSMSpotter:
A spotter which uses a Bluetooth connection to slave phone to spot GSM.
- LogSpotter:
A class to read Measurements stored in a log file.
- LogSpotterExample:
A sample program that shows how to use a LogSpotter.
- Other Spotters:
Descriptions of some of the other types of Spotters available in Place Lab.
- Mapping:
Looking up the locations of Beacons using the persistent local cache of Beacon data
- Coordinate:
Place Lab's standard representation for a location in the world
- CoordinateExample:
A sample program showing how to use Coordinate and its coordinate frames.
- Beacon:
A generalized representation of a cell-based radio access point tied to a location.
- Mapper:
A class the manages the persistent cache of known beacons
- MapLoader:
An application to load your local mapper from the database at placelab.org and
other sources on the web.
- MapperExample:
Shows how to go from the BeaconMeasurement's BeaconReadings to Beacons using the mapper
- Place Lab Stumbler:
A wardriving application to generate trace files for LogSpotters and placelab.org
- Tracking:
Using Measurements, a Mapper, and a little (or a lot of) math to track device location
- Tracker:
A class that aggregates Spotter Measurements into location Estimates.
- Estimate:
A class that includes location information and, possibly, a notion of uncertainty.
- CentroidTrackerExample:
An example using the simplest type of BeaconTracker.
- ParticleFilterTracker:
A Tracker that uses probabilistic techniques and pluggable motion and sensor models.
- Utility Classes
- PlacelabWithProxy:
This class can create and manage spotters and trackers for an application.
- PlacelabExample:
A sample showing how to use the PlaceLab object and get estimates.
- Servlets and Proxies:
Applications can access location information from Place Lab's web proxy through
a common interface. The web proxy's functionality can also be extended with
servlets.
- ServletExample:
An example of a servlet that prints the last estimated device position.
- Maps and Visualizations
- MapWads:
Data files containing maps and places.
- MapView:
An extensible SWT control for displaying maps and overlaying visualizations.
- MapDemo:
An application using a MapView to show the user's location on a map.
Place Lab code is hosted on Sourceforge and can be accessed via CVS.
Most Place Lab developers use the Eclipse IDE and the build is
configured to support it. Builds can also be performed using Ant. If you're
using Eclipse, make sure and copy the appropriate classpath.* file to be named
.classpath in your placelab directory after checking out the module from the
CVS repository. If you make any global changes to your .classpath file, make
sure you reflect those changes back to the classpath.* files.
Of course, if you are just trying to use Place Lab to build your
location-aware applications, you can simply use placelab.jar (along with the
necessary support files and native pieces such as spotter.dll) with whatever
developement environment you choose.
Building for the phones requires the Series 60 MIDP SDK available from Nokia and
you may want to be aware of Known
Issues In The Nokia 6600 MIDP 2.0 Implementation v1.3. The Phone Utilities HOWTO Guide
describes how to use the Place Lab helper tools like error logging and
persistent storage on the phones.
The source for Place Lab is divided into two directories: src and srcx. Both
are compiled to the bin directory by Eclipse. src (and package org.placelab
inside it) is for release-quality code and is included in official releases.
srcx (and package org.placelabx inside it) is for research, debug, or otherwise
not-ready-for-primetime code. No file in src should ever rely on a file in
srcx.
In Place Lab, spotters are the objects that do the environmental sensing (i.e. detect radio beacons) for the system. The root class Spotter.java is an interface that all spotters implement. In many cases, spotters will have a native code component that understands how to reach the specific hardware that does the sensing.
org.placelab.spotter.Spotter
Javadoc
Source
Spotters all must produce readings of type Measurement. Because different spotters can produce readings of very different types, different kids of measurements might have very little in common. The one thing they must have is a timestamp of when the measurement was made. Individual spotters subclass Measurement in order to produce their own type of reading (for example, WiFiSpotter produces a BeaconMeasurement, GPSSpotter produces a GPSMeasurement).
org.placelab.core.Measurement
Javadoc
Source
BeaconMeasurements are produced by WiFiSpotter, BluetoothSpotter, GSMSpotter, LogSpotter, and potentially other Spotters. and represent a the result of a single scan of the environment for radio beacons. The measurement includes a set of BeaconReadings for each radio beacon seen that have the unique id as well as the observed signal strength.
org.placelab.core.BeaconMeasurement
Javadoc
Source
A BeaconReading represents a sighting of a single wireless beacon from a Spotter that spots for wireless beacons. Spotters typically return BeaconMeasurements that have zero or more BeaconReadings in them
org.placelab.core.BeaconReading
Javadoc
Source
The WiFiSpotter scans all of the 802.11 wireless cards on the machine and returns the networks that it sees. This always involves running native code. At this point, we have native support for XP, OS X, Pocket PC 2003, and some linux configurations.
org.placelab.spotter.WiFiSpotter
Javadoc
Source
package org.placelab.example;
import org.placelab.core.BeaconMeasurement; import org.placelab.core.WiFiReading; import org.placelab.spotter.Spotter; import org.placelab.spotter.SpotterException; import org.placelab.spotter.WiFiSpotter;
/** * A sample that creates a WiFiSpotter and uses it to get measurements. * This will only return readings if a WiFi card is present. */ public class WiFiSpotterExample {
public static void main(String[] args) { Spotter s = new WiFiSpotter(); try { s.open(); BeaconMeasurement m = (BeaconMeasurement) s.getMeasurement(); System.out.println(m.numberOfReadings() + " APs were seen\n"); if (m.numberOfReadings() > 0) { System.out.println(pad("MAC Address", 20) + pad("SSID", 30) + pad("RSSI", 10)); // Iterate through the Vector and print the readings for (int i = 0; i < m.numberOfReadings(); i++) { WiFiReading r = (WiFiReading) m.getReading(i); System.out.println(pad(r.getId(), 20) + pad(r.getSsid(), 30) + pad("" + r.getRssi(), 10)); } } } catch (SpotterException ex) { ex.printStackTrace(); } } // Pad out a string to the passed length public static String pad(String str, int len) { StringBuffer sb = new StringBuffer(str); for (int i=str.length(); i < len; i++) { sb.append(" "); } return sb.toString(); } }
If you have a 60 Series cell phone (e.g. Nokia 6600 or 6620) your laptop client
can position itself using both GSM and WiFi at the same time; WiFi in the
laptop and GSM by the phone relayed to the laptop over Bluetooth. To make this
work, you need both a laptop running Place Lab with Bluetooth and a 60 Series
cell phone running Place Lab with Bluetooth.
First, you must pair the phone and the laptop. This only needs to be done
once, but is a critical step. Run your phone’s Bluetooth utility, discover your
laptop, and create a pairing. (This usually involved typing a password-key on
both devices). Then on the phone set this laptop as "authorized" to allow it to
make connections without having to select accept every time the
laptop talks to the phone. Next, as is the case for any of the Place Lab
applications on the phone, run the Servers native portion of Place Lab on the
phone and go back to the application chooser without exiting the Servers
application. Next run the midlet named "BTGSM" on the phone. This starts a
Bluetooth server that will relay out GSM beacons to devices that ask for them.
You will need to answer "Yes" to two questions. (If, after you start your
laptop’s spotter, it asks you for permission more times than twice, you didn't
do the first step correctly). When BTGSM first starts up it displays the URL
used to access the server. Write down or copy the host address and port number
of this URL. (The other parts are the same for all devices). For my phone, for
example, this address is: ‘000e6d43ec17:4’. After a few seconds the phone will
switch to a different display showing how many readings it has taken, what the
GSM coverage has been for the life of the run, and what the current cell
tower’s ID is.
The laptop must have a Bluetooth interface and must also have the Microsoft
Bluetooth software installed. This software is included as part of Windows XP
SP2, but can also be installed separately from SP2. (Visit http://eben.phlegethon.org/bluetooth.html
to find out how). RemoteGSMSpotter takes a constructor argument of the address
(e.g. 000e6d43ec17:4) that was printed by the cell phone. (This spotter's
constructor also takes a second Boolean argument that enables or disables
buffering, see the Javadocs for more about buffering). Call open() on the
spotter as you would any other and the spotter is ready to go. For several
reasons the phone is hard coded to take a GSM reading once a second, so asking
for measurements more frequently than that will not result in more data being
collected. Here is sample output for
org.placelab.samples.RemoteGSMSpotterSample Getting 5 GSM readings from the
phone, 2 seconds apart.
Tower ID Name Signal strength
310:380:1301:52025 AT&T Wirel:1301:52025:1301:52025 78
310:380:1301:52025 AT&T Wirel:1301:52025:1301:52025 83
310:380:1301:52025 AT&T Wirel:1301:52025:1301:52025 78
310:380:1301:52025 AT&T Wirel:1301:52025:1301:52025 75
310:380:1301:52025 AT&T Wirel:1301:52025:1301:52025 75
org.placelab.spotter.RemoteGSMSpotter
Javadoc
Source
A LogSpotter takes a trace file created by NetStumbler or Place Lab Stumbler and replays it, creating BeaconMeasurements, to simulate a route traveled.
org.placelab.spotter.LogSpotter
Javadoc
Source
package org.placelab.example;
import org.placelab.core.BeaconReading; import org.placelab.core.StumblerMeasurement; import org.placelab.spotter.LogSpotter; import org.placelab.spotter.SpotterException; import org.placelab.util.Cmdline;
/** This sample demonstrates the use of the LogSpotter class * We show how to parse a large text-exported trace, * report the size of the trace and enlist some key values in the log. */
public class LogSpotterExample {
public static void main(String [] args) { Cmdline.parse(args); String inputFile = Cmdline.getArg("tracefile"); if (inputFile == null) { System.err.println("Usage: java " + LogSpotterExample.class.getName() + " --tracefile filename"); System.exit(1); } LogSpotter log = LogSpotter.newSpotter(inputFile); try { log.open(); // output as many chunks as are there in the inputfile if(!log.logIsFinished()) do { StumblerMeasurement m = (StumblerMeasurement)log .getMeasurement(); if(m == null) { System.out.println("log is finished"); break; } if (m.numberOfReadings() > 0) { System.out.println(pad("Timestamp", 20) + pad("Latitude", 20) + pad("Longitude", 20) + pad("BSSID", 30) + pad("RSSI", 10)); //iterate through the Vector and print the readings for (int i = 0; i < m.numberOfReadings(); i++) { BeaconReading br = (BeaconReading) m .getReading(i); System.out.println(pad("" + (((long) m.getTimestamp() / 1000L) * 1000L), 20) + pad(m.getPosition().getLatitudeAsString(), 20) + pad(m.getPosition().getLongitudeAsString(), 20) + pad(br.getId(), 30) + pad("" + br.getNormalizedSignalStrength(), 10)); } System.out.println(); } } while(!log.logIsFinished()); } catch (SpotterException ex) { ex.printStackTrace(); }
} public static String pad(String str, int len) { StringBuffer sb = new StringBuffer(str); for (int i=str.length(); i < len; i++) { sb.append(" "); } return sb.toString(); } }
- BluetoothSpotter: Scans for Bluetooth devices on systems with JSR-82 implementations.
org.placelab.spotter.BluetoothSpotter
Javadoc
Source
- NMEAGPSSpotter: Listens to an NMEA GPS device to get GPSMeasurements.
org.placelab.spotter.NMEAGPSSpotter
Javadoc
Source
- GSMSpotter: Scans for GSM cell towers on phones.
org.placelab.midp.GSMSpotter
Javadoc
Source
Place Lab maps both access points and devices in two dimensions. That is to say, we estimate latitude and longitude, but we do not model or estimate altitude at this point (there is preliminary support for three dimensional coordinates). Coordinate is the class Place Lab uses to represent all of its locations. Coordinates are like regular two dimensional points in that they have an X and Y. X and Y refer to the distance in meters from the "origin" of the Earth. This origin can be pretty much wherever you want, you can change it in CoordinateTranslator. Making the origin close to you makes the meters look reasonable (like 875) rather than huge (like 789674) making debugging easier.
Behind the scenes (in org.placelab.core.Types) Placelab chooses to use TwoDCoordinate or FixedTwoDCoordinate depending on whether it is running on a CLDC 1.0 phone or not. Applications that intend to run on both phones and larger devices will use the String based interface to Coordinate, but applications not targeted at phones can cast any Coordinate to a TwoDCoordinate and use the double based interface.
org.placelab.core.Coordinate
Javadoc
Source
package org.placelab.example;
import org.placelab.core.TwoDCoordinate;
/** * A sample program that shows how to use 2DCoordinates */ public class CoordinateExample {
public static void main(String[] args) { TwoDCoordinate c1,c2,c3; // The coordinates of Intel Research Seattle c1 = new TwoDCoordinate(47.656,-122.318); // The coordinates of Intel Research Berkeley c2 = new TwoDCoordinate(37.87042,-122.26780); double distance = c1.distanceFrom(c2); System.out.println("IRS is at ("+c1.getLatitude()+","+c1.getLongitude()+")"); System.out.println("IRB is at ("+c2.getLatitude()+","+c2.getLongitude()+")"); System.out.println("IRS and IRB are " + (int)distance/1000 + " km or " + (int)distance/1609 + " miles apart"); // Move c2 5000 meters north c2.moveBy(0, 5000); System.out.println("The point 5 km north of IRB has lat=" + c2.getLatitude() + " lon=" + c2.getLongitude()); } }
The Mapper manages the persistent cache of known access points. The mapper can take BeaconReadings and will return Beacon objects for the BeaconReadings if it knows about them.
org.placelab.mapper.Mapper
Javadoc
Source
Before running any applications that use the Mapper, you must first load your
local cache of Beacons from databases on the web. The MapLoaderGUI utility
allows you to select your region and download all the known Beacons for it.
org.placelab.mapper.loader.MapLoaderGUI
Javadoc
Source
package org.placelab.example;
import org.placelab.core.BeaconMeasurement; import org.placelab.core.BeaconReading; import org.placelab.mapper.Beacon; import org.placelab.mapper.CompoundMapper; import org.placelab.mapper.Mapper; import org.placelab.spotter.LogSpotter; import org.placelab.spotter.Spotter; import org.placelab.spotter.SpotterException; import org.placelab.spotter.WiFiSpotter;
/** * This sample is very similar to CoordinateSample with the addition * of a lookup in the persistent AP cache */ public class MapperExample {
public static void main(String[] args) { Spotter s; if(args.length >= 1) { s = LogSpotter.newSpotter(args[0]); } else { s = new WiFiSpotter(); } try { s.open(); BeaconMeasurement m = (BeaconMeasurement) s.getMeasurement(); Mapper mapper; // This Mapper can tell us where APs are // The default Mapper (set in PlacelabProperties) will be selected // here. The first argument says to exit on error, and the second // says to cache Beacons in memory as they are accessed. mapper = CompoundMapper.createDefaultMapper(true, true); int knownAPs = 0; for (int i = 0; i < m.numberOfReadings(); i++) { BeaconReading r = (BeaconReading) m.getReading(i); // Lets lookup this AP in the map Beacon b = (Beacon) mapper.findBeacon(r.getId()); if (b == null) { System.out.println(r.getId() + " is an unknown AP"); } else { System.out.println(r.getId() + " (" + r.getHumanReadableName() + ") is thought to be at " + b.getPosition()); knownAPs++; } } System.out.println("\nOf the " + m.numberOfReadings() + " APs " + knownAPs + " were known."); } catch (SpotterException ex) { ex.printStackTrace(); } } }
Place Lab Stumbler is an application that is used to collect and determine the
locations of WiFi, Bluetooth, or GSM beacons in conjunction with a GPS unit.
It also can be used to create trace files that can be played back by a
LogSpotter and that can be submitted to placelab.org for incorporation into the
site database of Beacons. For more information view the laptop stumbling HOWTO
document and the phone stumbling HOWTO document.
org.placelab.stumbler.gui.PlacelabStumblerGUI
Javadoc
Source
org.placelab.stumbler.PlacelabStumbler
Javadoc
Source
org.placelab.midp.stumbler.StumblerMidlet
Javadoc
Source
Tracker is the abstract super-class for the objects in Place Lab that aggregate measurements from the spotters into a single estimate of device position. Trackers are used in the following way: measurements are fed to the tracker, and the tracker produces estimated locations. Interested objects can also register with trackers to get call-backs when the tracker's estimate changes.
To implement a tracker, you must furnish three functions. The first is the set of measurement types the tracker understands. It is not required that a tracker understand all kinds of measurements. A tracker that can triangulate 802.11 signals, for example, may not understand GPSMeasurements. The second is a method that consumes the measurements coming from the spotter. Thirdly, the system may call a spotter to let it know that some time has elapsed without a measurement occurring. This provides a sophisticated tracker the opportunity to update an estimate based on its prediction of the velocity or path of the device.
org.placelab.client.tracker.Tracker
Javadoc
Source
An Estimate is produced each time a tracker makes a prediction about the device's position. An estimate contains a Coordinate estimate of the device's position. More sophisticated trackers may return subtypes that also include uncertainty and other meta-data.
org.placelab.client.tracker.Estimate
Javadoc
Source
package org.placelab.example;
import org.placelab.client.tracker.Estimate; import org.placelab.client.tracker.Tracker; import org.placelab.client.tracker.TwoDPositionEstimate; import org.placelab.core.BeaconMeasurement; import org.placelab.core.BeaconReading; import org.placelab.core.Measurement; import org.placelab.core.TwoDCoordinate; import org.placelab.mapper.Beacon; import org.placelab.mapper.CompoundMapper; import org.placelab.mapper.Mapper; import org.placelab.mapper.WiFiBeacon; import org.placelab.spotter.LogSpotter; import org.placelab.spotter.Spotter; import org.placelab.spotter.WiFiSpotter;
/** * This sample is a tracker that calculates the centroid of the observed * readings. * * This tracker estimates the device position to be the geometric center of the * readings that have the same timestamp. */ public class CentroidTrackerExample extends Tracker { /** The mapper to query for information about beacons */ private Mapper mapper; private TwoDPositionEstimate estimate; public CentroidTrackerExample(Mapper m) { mapper = m; }
/** return an estimate based on the last set of measurements we saw * */ public Estimate getEstimate() { if (estimate != null) { return estimate; } else { return new TwoDPositionEstimate(getLastUpdatedTime(), TwoDCoordinate.NULL, 0.0); } }
/** * updateEstimateImpl uses the passed measurement to compute a simple * geometic center. */ public void updateEstimateImpl(Measurement m) { // we only want BeaconMeasurements if (!(m instanceof BeaconMeasurement)) { return; } BeaconMeasurement meas = (BeaconMeasurement) m;
/* calculate the mean */ double totalLat=0.0, totalLon=0.0; int count=0; for (int i=0; i < meas.numberOfReadings(); i++) { BeaconReading reading = meas.getReading(i); Beacon beacon = mapper.findBeacon(reading.getId()); if (beacon == null) continue; TwoDCoordinate pos = (TwoDCoordinate)((WiFiBeacon)beacon).getPosition(); totalLat += pos.getLatitude(); totalLon += pos.getLongitude(); count++; } TwoDCoordinate mean = new TwoDCoordinate(totalLat/count, totalLon/count); /* you can also calculate the standard deviation here. For this sample, * let's ignore it. */ estimate = new TwoDPositionEstimate(getLastUpdatedTime(), mean, 0.0); }
//** returns true if m is a wifi measurement **/ public boolean acceptableMeasurement(Measurement m) { return (m instanceof BeaconMeasurement); }
public void updateWithoutMeasurement(long durationMillis) { }
protected void resetImpl() { estimate = null; }
public static void main(String[] args) { try { Spotter spotter; Mapper mapper;
// Create a mapper mapper = CompoundMapper.createDefaultMapper(true, true); // Create a new tracker Tracker t = new CentroidTrackerExample(mapper); Estimate e1, e2;
// Create either a live spotter or a log spotter if (args.length == 0) { spotter = new WiFiSpotter(); } else { spotter = LogSpotter.newSpotter(args[0]); } spotter.open();
// Get readings from the spotter BeaconMeasurement m = (BeaconMeasurement)spotter.getMeasurement(); System.out.println("The spotter saw " + m.numberOfReadings() + " readings."); t.updateEstimate(m); e1 = t.getEstimate(); System.out.println("Estimated position: " + e1.getCoord());
// wait around for 2 seconds Thread.sleep(2000);
// Do it all again m = (BeaconMeasurement)spotter.getMeasurement(); System.out.println("The spotter saw " + m.numberOfReadings() + " readings."); t.updateEstimate(m); e2= t.getEstimate(); System.out.println("Estimated position: " + e2.getCoord().getLatitudeAsString() + "," + e2.getCoord().getLongitudeAsString());
// Calculate the distance between the 2 readings TwoDCoordinate c1 = (TwoDCoordinate)e1.getCoord(), c2 = (TwoDCoordinate)e2.getCoord(); double distance = c1.distanceFrom(c2); System.out.println("The distance between estimates is: " + (int) distance + " meters.");
} catch (Exception ex) { ex.printStackTrace(); }
} }
This tracker uses probablistic machine-learning techniques to generate it's predictions of device location. It implements a two dimensional particle filter with motion and sensor models from org.placelab.client.beaconparticlefilter. This tracker produces estimates of type ParticleFilterEstimate that include its confidence in the estimated device position. The documentation for this class and its helper classes is quite thin, and for that we deeply apologize.
org.placelab.client.tracker.ParticleFilterTracker
Javadoc
Source
The PlacelabWithProxy class is a wrapping of spotter and tracker creation and maintenance. If the no-arg constructor is called, the system creates a WiFiSpotter, a CentroidTracker and the system default Mapper. The spotter is asked for measurements once a second and the measurements are mapped and fed into the tracker, much as our last sample program does. Interested clients can register with the object to receive estimates from the tracker. This object also allows a spotter, tracker and pulse frequency to be passed in on creation time. This allows a log spotter or an alternate tracker to be used instead. Passing in a pulse frequency of -1 will cause the PlacelabWithProxy object to not automatically ask the spotter for readings.
org.placelab.client.PlacelabWithProxy
Javadoc
Source
package org.placelab.example;
import org.placelab.client.PlacelabWithProxy; import org.placelab.client.tracker.Estimate; import org.placelab.client.tracker.EstimateListener; import org.placelab.client.tracker.Tracker; import org.placelab.core.Coordinate; import org.placelab.core.Measurement; import org.placelab.spotter.LogSpotter;
/** * This sample shows how to use the PlacelabWithProxy object to manage * spotters and trackers for you. */ public class PlaceLabExample implements EstimateListener { Estimate lastEstimate=null;
public static void main(String[] args) { try { PlacelabWithProxy placelab; if (args.length == 0) { // Create a default placelab (with a live spotter) placelab = new PlacelabWithProxy(); } else { // Create a placelab (with an explicit log spotter) placelab = new PlacelabWithProxy(LogSpotter.newSpotter(args[0]), null, // use default tracker null, // use default mapper 2000 // poll spotter every 2s ); } placelab.addEstimateListener(new PlaceLabExample()); placelab.createProxy(); } catch (Exception ex) { ex.printStackTrace(); } } public void estimateUpdated(Tracker t, Estimate e, Measurement m) { System.out.println("Estimated position: " + e.getCoord()); if (lastEstimate != null) { Coordinate c = e.getCoord(); Coordinate last = lastEstimate.getCoord(); System.out.println("Estimate moved " + c.distanceFromAsString(last) + " meters."); } lastEstimate = e; } }
Place Lab includes an HTTP proxy and servlet engine that allows applications to both create simple web front-ends and to include Place Lab services on remote web servers.
Place Lab communicates location information to web services via a web proxy that that runs on port 2080. This proxy is started when a PlacelabWithProxy object is created and the createProxy() method is called on it. The proxy adds the location information by appending an HTTP request header called X-PlaceLab.Location that has lat,long as its value.
Place Lab also includes a simple servlet engine to allow the application to trap and answer HTTP requests based on their URLs. This trapping and answering allows a program to add simple behaviors with HTML UIs with little effort. The servlet behavior is encapsulated in objects of type Servlet, and they are installed by calling methods in ProxyServletEngine.
To use the proxy server or the servlet engine, set your browser configuration to use http://localhost:2080 as its HTTP proxy.
org.placelab.proxy.Servlet
Javadoc
Source
org.placelab.proxy.CoreServlet
Javadoc
Source
org.placelab.proxy.ProxyServletEngine
Javadoc
Source
package org.placelab.example;
import java.util.Hashtable;
import org.placelab.client.PlacelabWithProxy; import org.placelab.client.tracker.Estimate; import org.placelab.client.tracker.EstimateListener; import org.placelab.client.tracker.Tracker; import org.placelab.core.Measurement; import org.placelab.proxy.HTTPRequest; import org.placelab.proxy.HTTPResponse; import org.placelab.proxy.Servlet; import org.placelab.proxy.ServletServer; import org.placelab.spotter.LogSpotter;
/** * This sample creates a placelab object and installs a servlet * in it. */ public class ServletExample implements Servlet, EstimateListener { private Estimate lastEstimate = null;
public static void main(String[] args) { try { ServletExample ss = new ServletExample(); // Install the samples as a servlet ServletServer.addServlet("/sample", ss);
PlacelabWithProxy placelab; if (args.length == 0) { // Create a default placelab (with a live spotter) placelab = new PlacelabWithProxy(); } else { // Create a placelab (with an explicit log spotter) placelab = new PlacelabWithProxy(LogSpotter.newSpotter(args[0]), null, // use default tracker null, // use default mapper 2000 // poll spotter every 2s ); } placelab.addEstimateListener(ss); placelab.createProxy(); System.out.println("The proxy and servlet are running. Change your broswer's http proxy to:"); System.out.println("locahost:2080 and the load the page: http://localhost:2081/sample"); } catch (Exception ex) { ex.printStackTrace(); } }
public void estimateUpdated(Tracker t, Estimate e, Measurement m) { lastEstimate = e; }
// A servlet has a name public String getName() { return "A sample servlet"; } // print the last estimate we got from the tracker public HTTPResponse serviceRequest(HTTPRequest req) { String text; if (lastEstimate == null) { text = "This is the sample servlet!\nNo estimate yet..."; } else { text = "This is the sample servlet!\nLast estimate: " + lastEstimate.getCoord(); } return new HTTPResponse( HTTPResponse.RESPONSE_OK, "text/plain", // mime type text.length(), text.getBytes()); }
// servlets can add headers to outgoing http requests. public Hashtable injectHeaders(HTTPRequest req) { Hashtable t = new Hashtable(); t.put("X-SillyHeader", "banana"); return t; } }
A mapwad is a special file that includes maps and sets of places. Mapwads can contain both
raster maps and information in us census tiger/line format to make vector maps. A full specification
of the mapwad format can be found in the javadoc for WadData.
org.placelab.demo.mapview.WadData
Javadoc
Source
MapViews consume mapwads and display interactive maps with pan and zoom
functionality as an SWT control that is usable on all platforms supported by
SWT (though memory constraints still apply for large maps, of course).
MapViews may be extended by use of MapViewOverlays to show extra information.
TrackedMapView is a MapView that includes by default the ReticleOverlay for
tracking position, APOverlay for viewing nearby access points and their
activity, and the ParticleFilterOverlay for visualizing the particle filter
(when a ParticleFilterTracker is used).
org.placelab.demo.mapview.MapView
Javadoc
Source
org.placelab.demo.mapview.TrackedMapView
Javadoc
Source
org.placelab.demo.mapview.MapViewOverlay
Javadoc
Source
org.placelab.demo.mapview.MapDemo
Javadoc
Source
|
 |