Re: [geofencing-api] Why is geofencing design tied to service workers?

I found this a useful layman's reference for hardware support of 
geofencing: -
http://gpsworld.com/putting-the-ultra-low-power-in-geofence/

Explains a lot to me especially about power consumption,

I maintain that the SW architecture, in combination with any Android 
support for position batching, that subsequently offloads geo-fence 
processing to a central server in order to determine alarm/other 
processing for ALL users, is a viable if not preferable alternative. 

Whether or not a wake-lock or cpu-lock is a retrograde step in power 
consumption, its implementation and availability pays homage to the 
user's right to self-determination. Likewise the user should be 
empowered to authorize GPS tracking while the phone is off.

Surely a myopic cluster of GNSS ICs is a less than optimal solution 
for fleet management or social networking, and an instance of 
functionality-devolution gone too far? IMHO, other than for monitoring
 prisoners on probation, the current geofence solution is a textbook 
case of the tail wagging the dog. 

A Service Worker should be able to subscribe to a PositionManager 
optionally specifying min distance and/or seconds between updates to 
the position. A positionChanged event will be sufficient to 
re-instantiate a terminated SW.

Below is how I throttle GeoLocation.watchPosition now: -

        Tier3Toolbox.prototype.LocationThrottle = 
                
                function(initHndlr, moveHndlr, standHndlr, errorHndlr,
 userOptions)
                {
                        if(!navigator.geolocation) {
                                throw new Error("Unsupported browser -
 No Geolocation support");
                        }

                        if (arguments.length < 4) {
                                throw new Error("Insufficient call 
arguments");
                        }
                        
                        if (typeof initHndlr  != "function" ||
                                typeof moveHndlr  != "function" || 
                                typeof standHndlr != "function" ||
                                typeof errorHndlr != "function") {
                                throw new Error("The Init, Move, 
Stand, and Error handler parameters must be functions");
                        }
                        
                        var lastPos, trackerId, loiterTimer, 
deltaMetres,
                                recalibrateTimer, lastOptions, 
lastDrop, replayTimer
                                ;
                        
                        var MAXSILENCE    = 30;
                        var watchCount    = 1;
                        var acceptCount   = 1;
                        var lastUpdate    = 0;
                        
                        var initHndlr     = initHndlr;
                        var moveHndlr     = moveHndlr;
                        var standHndlr    = standHndlr;
                        var errorHndlr    = errorHndlr;
                        
                        var options, defMaxSilence, timeDetent, 
spaceDetent,
                                loiterDetent, maxLocAge, accurate, 
maxSilence, lastOptions
                                ;
                                                        
                        function moveReplay()
                        {
                                replayTimer = null;
                                
                                if ((lastDrop.timestamp > 
lastPos.timestamp)) {
                                        lastDrop.timestamp = 
Date.now();
                                        filterLocation(lastDrop);
                                }
                                               
                        }
                        
                        function loiterLimit()
                        {
                                loiterTimer = null;
                                standHndlr.call(null);
                        }
                        
                        var recalibrate = 
                                function()
                                {
                                        if (window.console) 
console.log("recalibrating");
                                        
                                        recalibrateTimer = null;
                                        
                                        if (trackerId) 
navigator.geolocation.clearWatch(trackerId);
                                        
                                        getCurrent(initAcc);
                                }
                        
                        var getCurrent = 
                                function(success) 
                                {
                                        
navigator.geolocation.getCurrentPosition(success,locError,{
                                                                
enableHighAccuracy: false,
                                                                
maximumAge: Number.POSITIVE_INFINITY,
                                                                
timeout: 10000
                                                        });
                                                             
                                }
                                
                        var initLoc = 
                                function(position) 
                                {
                                        lastPos = position;
             
                                        initHndlr.call(null, 
position); 
                                }
                        
                        var initAcc = 
                                function(position) 
                                {
                                        watchCount++;
                                        
                                        trackerId = 
navigator.geolocation.watchPosition(filterLocation, locError, {
                                                                
enableHighAccuracy: accurate,
                                                                
maximumAge: maxLocAge
                                                        });
                                                        
                                        recalibrateTimer = 
setTimeout(recalibrate, maxSilence);                                 
                                }
                                
                        var     start =
                                function(userOptions)
                                {
                                        parseOptions(userOptions);
                                        
                                        trackerId = 
navigator.geolocation.watchPosition(filterLocation, locError, {
                                                                
enableHighAccuracy: accurate,
                                                                
maximumAge: maxLocAge,
                                                                
timeout: Number.POSITIVE_INFINITY
                                                        });
                                        
                                        loiterTimer = 
setTimeout(loiterLimit, loiterDetent);
                                        recalibrateTimer = 
setTimeout(recalibrate, maxSilence);
                                }
                                
                        var     parseOptions =
                                function(userOptions)
                                {
                                        options       = userOptions ||
 lastOptions; 
                        
                                        defMaxSilence = (("maxSilence"
  in options) ? options.maxSilence        : MAXSILENCE    );
                                        timeDetent    = (("minSilence"
  in options) ? options.minSilence                :
                         0 ) * 1000;
                                        spaceDetent   = 
(("minProgress" in options) ? options.minProgress               :
                         0 );
                                        loiterDetent  = (("maxSnail"
    in options) ? options.maxSnail          : defMaxSilence ) * 1000;
                                        maxLocAge     = (("maxAge"
      in options) ? options.maxAge                    :
                         0 );
                                        if (maxLocAge != 
Number.POSITIVE_INFINITY) maxLocAge *= 1000;
                                        accurate      = (("accurate"
    in options) ? options.accurate                  : true          );
                                        maxSilence    = defMaxSilence 
* 1000;
                        
                                        lastOptions   = options;
                                }
                        
                        var locError = 
                                function(error) 
                                {
                                        errorHndlr.call(null, error);
                                }
                                
                        var filterLocation = 
                                function(position) 
                                {
                                        if (!lastPos) return;
                                        
                                        watchCount++;

                                        if (position.timestamp <= 
lastPos.timestamp)
                                                return;

                                        var currTime = Date.now();
                                      
                                        var dropping = false;
                                                
                                        if (((position.timestamp - 
lastPos.timestamp) < timeDetent) ||
                                                ((currTime           -
 lastUpdate       ) < timeDetent)) {
                                                dropping = true;
                                        } else {
                                                        
                                                
clearTimeout(recalibrateTimer);
                                                recalibrateTimer = 
setTimeout(recalibrate, maxSilence);
                                        }
                                                
                                        deltaMetres = 
Tier3Toolbox.calculateDistance(
                                                                        
position.coords.latitude,
                                                                        
position.coords.longitude,
                                                                        
lastPos.coords.latitude,
                                                                        
lastPos.coords.longitude)
                                                                        
                                        if (deltaMetres.toFixed() < 
spaceDetent) {
                                                return;
                                        }
                                        
                                        if (dropping) {
                                                lastDrop = position;
                                                
clearTimeout(replayTimer);
                                                replayTimer = 
setTimeout(moveReplay, timeDetent);
                                                return;
                                        }
                                        
                                        acceptCount++;
                                        lastPos = position;
                                        lastUpdate = currTime;
                                        
                                        clearTimeout(loiterTimer);
                                        loiterTimer = 
setTimeout(loiterLimit, loiterDetent);
                                        
                                        moveHndlr.call(null, position,
 deltaMetres);                    
                                }
                                
                        var stop = 
                                function()
                                {
                                        if (trackerId) 
navigator.geolocation.clearWatch(trackerId);
                                        
                                        
clearTimeout(recalibrateTimer);
                                        clearTimeout(loiterTimer);
                                        clearTimeout(replayTimer);
                                }
                                
                        parseOptions(userOptions);
                                                                              
                        getCurrent(initLoc);
                        
                        return {start : start, stop : stop};
                };


-- 
GitHub Notification of comment by RichardMaher
Please view or discuss this issue at 
https://github.com/w3c/geofencing-api/issues/25#issuecomment-181642272
 using your GitHub account

Received on Tuesday, 9 February 2016 00:36:23 UTC