org.placelab.stumbler
Class StumblerFunnel

java.lang.Object
  extended byjava.lang.Thread
      extended byorg.placelab.stumbler.StumblerFunnel
All Implemented Interfaces:
java.lang.Runnable, SpotterListener

public class StumblerFunnel
extends java.lang.Thread
implements SpotterListener

StumblerFunnel manages and collates Measurements from multiple Spotters. The StumblerFunnel, with the use of SpotterExtension objects, can be configured to allow for virtually any type of stumbling semantics. Examples of real and potential uses are given below.

Trigger, Independent, and Dependent Spotters


Timeout
If you specify a positive timeout, if the registered Trigger spotters do not produce Measurements by the timeout period (or if there are no Trigger spotters) all Dependent Spotters will have their latest Measurements collected and pushed through to StumblerFunnelUpdateListeners at that time. Negative timeouts will make it such that a Trigger Spotter must update in order for Measurements to be collected from any Dependent spotters.

Examples of StumblerFunnel configurations
"Straight-line stumbler": This type of Stumbler doesn't have any dependent spotters. This is if you just want updates to come in as the spotters make them available. StumblerFunnel f = new StumblerFunnel(-1); WiFiSpotter wifi = new WiFiSpotter(250); // wifi will produce updates every 250 ms NMEAGPSSpotter gps = SerialGPSSpotter.newSpotter(); // gps will produce updates as fast as the hardware allows SpotterExtension wifiExt = new SpotterExtension(wifi, true, -1); SpotterExtension gpsExt = new SpotterExtension(gps, false, SpotterExtension.GPS_STALE_TIME); f.addIndependentSpotter(wifiExt); f.addIndependentSpotter(gpsExt); f.addUpdateListener(new LogWriter()); f.start();

"Place Lab Stumbler": This is (a simplification) of the default config used by PlacelabStumbler. The idea is to place WiFi as accurately as possible, so WiFi should be collected when GPS Measurements come in. Running WiFi fast and independent of the GPS as above will probably see more APs, but it won't produce logs that are as accurate as this method. StumblerFunnel f = new StumblerFunnel(-1); // you might specify 2000 or something here to get something when GPS isn't active WiFiSpotter wifi = new WiFiSpotter(); NMEAGPSSpotter gps = SerialGPSSpotter.newSpotter(); SpotterExtension wifiExt = new SpotterExtension(wifi, true, -1); SpotterExtension gpsExt = new SpotterExtension(gps, false, SpotterExtension.GPS_STALE_TIME); f.addDependentSpotter(wifiExt); f.addTriggerSpotter(gpsExt); f.addUpdateListener(new AudioNotifier()); f.start();
Listeners to StumblerFunnel will get notifications containing the measurements for the StumblerSpotters as they are available according to the rules outlined above The StumblerFunnel begins its funneling operations after start() is called and runs these in a new thread. This means that stumblerUpdated notifications will not come back in the same thread as which start() was called. If this won't work for you, you can use start(EventSystem evs) and callbacks will be delivered by the given EventSystem. Finally, note that the update Hashtable is keyed by the Spotters, not the SpotterExtensions.


Nested Class Summary
protected  class StumblerFunnel.Timeout
           
 
Field Summary
protected  HashtableSet dependentSpotters
           
protected  boolean doUpdate
           
protected  EventSystem eventSystem
           
protected  HashtableSet independentSpotters
           
protected  HashtableSet shutdowns
           
protected  boolean shuttingDown
           
protected  boolean suspend
           
protected  StumblerFunnel.Timeout timeout
           
protected  boolean timeoutFired
           
protected  HashtableSet triggerSpotters
           
protected  HashtableSet updateListeners
           
protected  java.util.Vector updateSenderMeasurements
           
protected  java.util.Vector updateSenders
           
 
Fields inherited from class java.lang.Thread
MAX_PRIORITY, MIN_PRIORITY, NORM_PRIORITY
 
Constructor Summary
StumblerFunnel()
          Create a StumblerFunnel with default timeout, as set in placelab.StumblerFunnel.timeout system property or 2000 ms if not set
StumblerFunnel(long timeout)
          Create a new StumblerFunnel.
 
Method Summary
 void addDependentSpotter(SpotterExtension spotter)
          Adds a spotter to be watched by the StumblerFunnel.
 void addIndependentSpotter(SpotterExtension spotter)
          Adds a spotter to be watched by the StumblerFunnel.
 void addShutdownListener(ShutdownListener listener)
          Register to be notified when the StumblerFunnel has been signaled to shutdown.
 void addTriggerSpotter(SpotterExtension spotter)
          Adds a spotter to be watched by the StumblerFunnel.
 void addUpdateListener(StumblerFunnelUpdateListener sul)
          Register to be notified after the pulse with the latest Measurements from all the spotters
 void gotMeasurement(Spotter sender, Measurement measurement)
           
 boolean isSuspended()
           
protected  void notifyUpdate(java.util.Hashtable response)
           
protected  void pulse()
           
 void removeShutdownListener(ShutdownListener listener)
           
 void removeSpotter(SpotterExtension remove)
          Remove a SpotterExtension of any type from the StumblerFunnel
 void removeUpdateListener(StumblerFunnelUpdateListener sul)
           
 void resumeListen()
           
 void run()
           
 void shutdown()
           
 void spotterExceptionThrown(Spotter s, SpotterException ex)
           
 void start(EventSystem evs)
           
protected  void startIndependentSpotters()
           
protected  void startTriggerSpotters()
           
 void suspendListen()
           
 
Methods inherited from class java.lang.Thread
activeCount, checkAccess, countStackFrames, currentThread, destroy, dumpStack, enumerate, getContextClassLoader, getName, getPriority, getThreadGroup, holdsLock, interrupt, interrupted, isAlive, isDaemon, isInterrupted, join, join, join, resume, setContextClassLoader, setDaemon, setName, setPriority, sleep, sleep, start, stop, stop, suspend, toString, yield
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

dependentSpotters

protected HashtableSet dependentSpotters

triggerSpotters

protected HashtableSet triggerSpotters

independentSpotters

protected HashtableSet independentSpotters

shutdowns

protected HashtableSet shutdowns

updateListeners

protected HashtableSet updateListeners

shuttingDown

protected boolean shuttingDown

suspend

protected boolean suspend

doUpdate

protected boolean doUpdate

eventSystem

protected EventSystem eventSystem

timeout

protected StumblerFunnel.Timeout timeout

timeoutFired

protected volatile boolean timeoutFired

updateSenders

protected java.util.Vector updateSenders

updateSenderMeasurements

protected java.util.Vector updateSenderMeasurements
Constructor Detail

StumblerFunnel

public StumblerFunnel()
Create a StumblerFunnel with default timeout, as set in placelab.StumblerFunnel.timeout system property or 2000 ms if not set


StumblerFunnel

public StumblerFunnel(long timeout)
Create a new StumblerFunnel. If no trigger spotters have signaled that they have new Measurements available by timeout, then all dependent stumblers are polled for their Measurements.

Method Detail

start

public void start(EventSystem evs)

run

public void run()
Specified by:
run in interface java.lang.Runnable

startTriggerSpotters

protected void startTriggerSpotters()

startIndependentSpotters

protected void startIndependentSpotters()

addDependentSpotter

public void addDependentSpotter(SpotterExtension spotter)
Adds a spotter to be watched by the StumblerFunnel. All SpotterExtensions are also ShutdownListeners, so they are automatically added to the shutdownListeners Vector too

Parameters:
spotter - to be added to the StumblerFunnel

addTriggerSpotter

public void addTriggerSpotter(SpotterExtension spotter)
Adds a spotter to be watched by the StumblerFunnel. All SpotterExtensions are also ShutdownListeners, so they are automatically added to the shutdownListeners Vector too. A Trigger Spotter is one that the StumblerFunnel will always fire an update in response to an update from.

Parameters:
spotter - to be added to the StumblerFunnel

addIndependentSpotter

public void addIndependentSpotter(SpotterExtension spotter)
Adds a spotter to be watched by the StumblerFunnel. Independent Spotters are spotters for which you want to collect all Measurements they can produce, but for which their updates don't trigger any further response.


removeSpotter

public void removeSpotter(SpotterExtension remove)
Remove a SpotterExtension of any type from the StumblerFunnel

Parameters:
remove - the spotter (and) extension to be removed

addUpdateListener

public void addUpdateListener(StumblerFunnelUpdateListener sul)
Register to be notified after the pulse with the latest Measurements from all the spotters


addShutdownListener

public void addShutdownListener(ShutdownListener listener)
Register to be notified when the StumblerFunnel has been signaled to shutdown.


removeUpdateListener

public void removeUpdateListener(StumblerFunnelUpdateListener sul)

removeShutdownListener

public void removeShutdownListener(ShutdownListener listener)

pulse

protected void pulse()

notifyUpdate

protected void notifyUpdate(java.util.Hashtable response)

gotMeasurement

public void gotMeasurement(Spotter sender,
                           Measurement measurement)
Specified by:
gotMeasurement in interface SpotterListener

suspendListen

public void suspendListen()

isSuspended

public boolean isSuspended()

resumeListen

public void resumeListen()

shutdown

public void shutdown()

spotterExceptionThrown

public void spotterExceptionThrown(Spotter s,
                                   SpotterException ex)
Specified by:
spotterExceptionThrown in interface SpotterListener