gecko/dom/system/GPSDGeolocationProvider.js

205 lines
6.4 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
const Ci = Components.interfaces;
const Cc = Components.classes;
var gLoggingEnabled = false;
function LOG(aMsg) {
if (gLoggingEnabled)
{
aMsg = ("*** GPSD GEO: " + aMsg);
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(aMsg);
dump(aMsg);
}
}
function GeoPositionCoordsObject(latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed) {
this.latitude = latitude;
this.longitude = longitude;
this.altitude = altitude;
this.accuracy = accuracy;
this.altitudeAccuracy = altitudeAccuracy;
this.heading = heading;
this.speed = speed;
};
GeoPositionCoordsObject.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPositionCoords]),
// Class Info is required to be able to pass objects back into the DOM.
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPositionCoords],
flags: Ci.nsIClassInfo.DOM_OBJECT,
classDescription: "Geoposition Coordinate Object"}),
latitude: null,
longitude: null,
altitude: null,
accuracy: null,
altitudeAccuracy: null,
heading: null,
speed: null,
};
function GeoPositionObject(latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed, timestamp) {
this.coords = new GeoPositionCoordsObject(latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed);
this.timestamp = timestamp;
};
GeoPositionObject.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPosition]),
// Class Info is required to be able to pass objects back into the DOM.
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPosition],
flags: Ci.nsIClassInfo.DOM_OBJECT,
classDescription: "Geoposition Object"}),
coords: null,
timestamp: null,
};
function GPSDProvider() {
this.prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch).QueryInterface(Ci.nsIPrefService);
try {
gLoggingEnabled = this.prefService.getBoolPref("geo.gpsd.logging.enabled");
} catch (e) {}
};
GPSDProvider.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIGeolocationProvider]),
classID: Components.ID("{0A3BE523-0F2A-32CC-CCD8-1E5986D5A79D}"),
prefService: null,
transport: null,
outputStream: null,
inputStream: null,
startup: function() {
LOG("startup called\n");
var socketTransportService = Cc["@mozilla.org/network/socket-transport-service;1"].getService(Ci.nsISocketTransportService);
var hostIPAddr = "127.0.0.1";
var hostPort = "2947";
try {
hostIPAddr = this.prefService.getCharPref("geo.gpsd.host.ipaddr");
} catch (e) {}
try {
hostPort = this.prefService.getCharPref("geo.gpsd.host.port");
} catch (e) {}
LOG("Host info: " + hostIPAddr + ":" + hostPort + "\n");
this.transport = socketTransportService.createTransport(null, 0, hostIPAddr, hostPort, null);
// Alright to open streams here as they are non-blocking by default
this.outputStream = this.transport.openOutputStream(0,0,0);
this.inputStream = this.transport.openInputStream(0,0,0);
},
shutdown: function() {
LOG("shutdown called\n");
this.outputStream.close();
this.inputStream.close();
this.transport.close(Components.results.NS_OK);
},
watch: function(c, isPrivate) {
LOG("watch called\n");
try {
// Go into "watcher" mode
var mode = '?WATCH={"enable":true,"json":true}';
this.outputStream.write(mode, mode.length);
} catch (e) { return; }
var dataListener = {
onStartRequest: function(request, context) {},
onStopRequest: function(request, context, status) {},
onDataAvailable: function(request, context, inputStream, offset, count) {
var sInputStream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream);
sInputStream.init(inputStream);
var responseSentence = sInputStream.read(count);
var response = null;
try {
response = JSON.parse(responseSentence);
} catch (e) { return; }
// is the right kind of sentence?
if (response.class != 'TPV') {
//don't do anything
return;
}
// is there a fix?
if (response.mode == '1') {
// don't do anything
return;
}
LOG("Got info: " + responseSentence);
// The API requires these values, if one is missing
// we return without updating the position.
if (response.time && response.lat && response.lon
&& response.epx && response.epy) {
var timestamp = response.time; // UTC
var latitude = response.lat; // degrees
var longitude = response.lon; // degrees
var horizontalError = Math.max(response.epx,response.epy); } // meters
else { return; }
// Altitude is optional, but if it's present, so must be vertical precision.
var altitude = null;
var verticalError = null;
if (response.alt && response.epv) {
altitude = response.alt; // meters
verticalError = response.epv; // meters
}
var speed = null;
if (response.speed) { var speed = response.speed; } // meters/sec
var course = null;
if (response.track) { var course = response.track; } // degrees
var geoPos = new GeoPositionObject(latitude, longitude, altitude, horizontalError, verticalError, course, speed, timestamp);
c.update(geoPos);
LOG("Position updated:" + timestamp + "," + latitude + "," + longitude + ","
+ horizontalError + "," + altitude + "," + verticalError + "," + course
+ "," + speed);
}
};
var pump = Cc["@mozilla.org/network/input-stream-pump;1"].createInstance(Ci.nsIInputStreamPump);
pump.init(this.inputStream, -1, -1, 0, 0, false);
pump.asyncRead(dataListener, null);
},
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([GPSDProvider]);